@axiom-lattice/core 2.1.50 → 2.1.51

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.js CHANGED
@@ -5212,21 +5212,28 @@ function truncateIfTooLong(result) {
5212
5212
  }
5213
5213
  return result;
5214
5214
  }
5215
- function validatePath(path3) {
5216
- const pathStr = path3 || "/";
5215
+ function validatePath(path4) {
5216
+ const pathStr = path4 || "/";
5217
5217
  if (!pathStr || pathStr.trim() === "") {
5218
5218
  throw new Error("Path cannot be empty");
5219
5219
  }
5220
- let normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
5220
+ let normalized;
5221
+ if (pathStr === "~") {
5222
+ normalized = "~/";
5223
+ } else if (pathStr.startsWith("~/")) {
5224
+ normalized = pathStr;
5225
+ } else {
5226
+ normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
5227
+ }
5221
5228
  if (!normalized.endsWith("/")) {
5222
5229
  normalized += "/";
5223
5230
  }
5224
5231
  return normalized;
5225
5232
  }
5226
- function globSearchFiles(files, pattern, path3 = "/") {
5233
+ function globSearchFiles(files, pattern, path4 = "/") {
5227
5234
  let normalizedPath;
5228
5235
  try {
5229
- normalizedPath = validatePath(path3);
5236
+ normalizedPath = validatePath(path4);
5230
5237
  } catch {
5231
5238
  return "No files found";
5232
5239
  }
@@ -5278,7 +5285,7 @@ function formatGrepResults(results, outputMode) {
5278
5285
  }
5279
5286
  return lines.join("\n");
5280
5287
  }
5281
- function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode = "files_with_matches") {
5288
+ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode = "files_with_matches") {
5282
5289
  let regex;
5283
5290
  try {
5284
5291
  regex = new RegExp(pattern);
@@ -5287,7 +5294,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
5287
5294
  }
5288
5295
  let normalizedPath;
5289
5296
  try {
5290
- normalizedPath = validatePath(path3);
5297
+ normalizedPath = validatePath(path4);
5291
5298
  } catch {
5292
5299
  return "No matches found";
5293
5300
  }
@@ -5319,7 +5326,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
5319
5326
  }
5320
5327
  return formatGrepResults(results, outputMode);
5321
5328
  }
5322
- function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
5329
+ function grepMatchesFromFiles(files, pattern, path4 = null, glob = null) {
5323
5330
  let regex;
5324
5331
  try {
5325
5332
  regex = new RegExp(pattern);
@@ -5328,7 +5335,7 @@ function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
5328
5335
  }
5329
5336
  let normalizedPath;
5330
5337
  try {
5331
- normalizedPath = validatePath(path3);
5338
+ normalizedPath = validatePath(path4);
5332
5339
  } catch {
5333
5340
  return [];
5334
5341
  }
@@ -5389,11 +5396,11 @@ var StateBackend = class {
5389
5396
  * @returns List of FileInfo objects for files and directories directly in the directory.
5390
5397
  * Directories have a trailing / in their path and is_dir=true.
5391
5398
  */
5392
- lsInfo(path3) {
5399
+ lsInfo(path4) {
5393
5400
  const files = this.getFiles();
5394
5401
  const infos = [];
5395
5402
  const subdirs = /* @__PURE__ */ new Set();
5396
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
5403
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
5397
5404
  for (const [k, fd] of Object.entries(files)) {
5398
5405
  if (!k.startsWith(normalizedPath)) {
5399
5406
  continue;
@@ -5499,16 +5506,16 @@ var StateBackend = class {
5499
5506
  /**
5500
5507
  * Structured search results or error string for invalid input.
5501
5508
  */
5502
- grepRaw(pattern, path3 = "/", glob = null) {
5509
+ grepRaw(pattern, path4 = "/", glob = null) {
5503
5510
  const files = this.getFiles();
5504
- return grepMatchesFromFiles(files, pattern, path3, glob);
5511
+ return grepMatchesFromFiles(files, pattern, path4, glob);
5505
5512
  }
5506
5513
  /**
5507
5514
  * Structured glob matching returning FileInfo objects.
5508
5515
  */
5509
- globInfo(pattern, path3 = "/") {
5516
+ globInfo(pattern, path4 = "/") {
5510
5517
  const files = this.getFiles();
5511
- const result = globSearchFiles(files, pattern, path3);
5518
+ const result = globSearchFiles(files, pattern, path4);
5512
5519
  if (result === "No files found") {
5513
5520
  return [];
5514
5521
  }
@@ -5602,10 +5609,10 @@ function createLsTool(backend, options) {
5602
5609
  ...runConfig
5603
5610
  };
5604
5611
  const resolvedBackend = await getBackend(backend, stateAndStore);
5605
- const path3 = input.path || "/";
5606
- const infos = await resolvedBackend.lsInfo(path3);
5612
+ const path4 = input.path || "/";
5613
+ const infos = await resolvedBackend.lsInfo(path4);
5607
5614
  if (infos.length === 0) {
5608
- return `No files found in ${path3}`;
5615
+ return `No files found in ${path4}`;
5609
5616
  }
5610
5617
  const lines = [];
5611
5618
  for (const info of infos) {
@@ -5748,8 +5755,8 @@ function createGlobTool(backend, options) {
5748
5755
  ...runConfig
5749
5756
  };
5750
5757
  const resolvedBackend = await getBackend(backend, stateAndStore);
5751
- const { pattern, path: path3 = "/" } = input;
5752
- const infos = await resolvedBackend.globInfo(pattern, path3);
5758
+ const { pattern, path: path4 = "/" } = input;
5759
+ const infos = await resolvedBackend.globInfo(pattern, path4);
5753
5760
  if (infos.length === 0) {
5754
5761
  return `No files found matching pattern '${pattern}'`;
5755
5762
  }
@@ -5776,8 +5783,8 @@ function createGrepTool(backend, options) {
5776
5783
  ...runConfig
5777
5784
  };
5778
5785
  const resolvedBackend = await getBackend(backend, stateAndStore);
5779
- const { pattern, path: path3 = "/", glob = null } = input;
5780
- const result = await resolvedBackend.grepRaw(pattern, path3, glob);
5786
+ const { pattern, path: path4 = "/", glob = null } = input;
5787
+ const result = await resolvedBackend.grepRaw(pattern, path4, glob);
5781
5788
  if (typeof result === "string") {
5782
5789
  return result;
5783
5790
  }
@@ -13163,13 +13170,13 @@ var StoreBackend = class {
13163
13170
  * @returns List of FileInfo objects for files and directories directly in the directory.
13164
13171
  * Directories have a trailing / in their path and is_dir=true.
13165
13172
  */
13166
- async lsInfo(path3) {
13173
+ async lsInfo(path4) {
13167
13174
  const store = this.getStore();
13168
13175
  const namespace = this.getNamespace();
13169
13176
  const items = await this.searchStorePaginated(store, namespace);
13170
13177
  const infos = [];
13171
13178
  const subdirs = /* @__PURE__ */ new Set();
13172
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
13179
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
13173
13180
  for (const item of items) {
13174
13181
  const itemKey = String(item.key);
13175
13182
  if (!itemKey.startsWith(normalizedPath)) {
@@ -13287,7 +13294,7 @@ var StoreBackend = class {
13287
13294
  /**
13288
13295
  * Structured search results or error string for invalid input.
13289
13296
  */
13290
- async grepRaw(pattern, path3 = "/", glob = null) {
13297
+ async grepRaw(pattern, path4 = "/", glob = null) {
13291
13298
  const store = this.getStore();
13292
13299
  const namespace = this.getNamespace();
13293
13300
  const items = await this.searchStorePaginated(store, namespace);
@@ -13299,12 +13306,12 @@ var StoreBackend = class {
13299
13306
  continue;
13300
13307
  }
13301
13308
  }
13302
- return grepMatchesFromFiles(files, pattern, path3, glob);
13309
+ return grepMatchesFromFiles(files, pattern, path4, glob);
13303
13310
  }
13304
13311
  /**
13305
13312
  * Structured glob matching returning FileInfo objects.
13306
13313
  */
13307
- async globInfo(pattern, path3 = "/") {
13314
+ async globInfo(pattern, path4 = "/") {
13308
13315
  const store = this.getStore();
13309
13316
  const namespace = this.getNamespace();
13310
13317
  const items = await this.searchStorePaginated(store, namespace);
@@ -13316,7 +13323,7 @@ var StoreBackend = class {
13316
13323
  continue;
13317
13324
  }
13318
13325
  }
13319
- const result = globSearchFiles(files, pattern, path3);
13326
+ const result = globSearchFiles(files, pattern, path4);
13320
13327
  if (result === "No files found") {
13321
13328
  return [];
13322
13329
  }
@@ -13365,8 +13372,9 @@ var FilesystemBackend = class {
13365
13372
  */
13366
13373
  resolvePath(key) {
13367
13374
  if (this.virtualMode) {
13368
- const vpath = key.startsWith("/") ? key : "/" + key;
13369
- if (vpath.includes("..") || vpath.startsWith("~")) {
13375
+ const normalizedKey = key === "~" ? "/" : key.startsWith("~/") ? `/${key.slice(2)}` : key;
13376
+ const vpath = normalizedKey.startsWith("/") ? normalizedKey : "/" + normalizedKey;
13377
+ if (vpath.includes("..") || vpath.includes("~")) {
13370
13378
  throw new Error("Path traversal not allowed");
13371
13379
  }
13372
13380
  const full = path2.resolve(this.cwd, vpath.substring(1));
@@ -13891,10 +13899,10 @@ var CompositeBackend = class {
13891
13899
  * @returns List of FileInfo objects with route prefixes added, for files and directories
13892
13900
  * directly in the directory. Directories have a trailing / in their path and is_dir=true.
13893
13901
  */
13894
- async lsInfo(path3) {
13902
+ async lsInfo(path4) {
13895
13903
  for (const [routePrefix, backend] of this.sortedRoutes) {
13896
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13897
- const suffix = path3.substring(routePrefix.length);
13904
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13905
+ const suffix = path4.substring(routePrefix.length);
13898
13906
  const searchPath = suffix ? "/" + suffix : "/";
13899
13907
  const infos = await backend.lsInfo(searchPath);
13900
13908
  const prefixed = [];
@@ -13907,9 +13915,9 @@ var CompositeBackend = class {
13907
13915
  return prefixed;
13908
13916
  }
13909
13917
  }
13910
- if (path3 === "/") {
13918
+ if (path4 === "/") {
13911
13919
  const results = [];
13912
- const defaultInfos = await this.default.lsInfo(path3);
13920
+ const defaultInfos = await this.default.lsInfo(path4);
13913
13921
  results.push(...defaultInfos);
13914
13922
  for (const [routePrefix] of this.sortedRoutes) {
13915
13923
  results.push({
@@ -13922,7 +13930,7 @@ var CompositeBackend = class {
13922
13930
  results.sort((a, b) => a.path.localeCompare(b.path));
13923
13931
  return results;
13924
13932
  }
13925
- return await this.default.lsInfo(path3);
13933
+ return await this.default.lsInfo(path4);
13926
13934
  }
13927
13935
  /**
13928
13936
  * Read file content, routing to appropriate backend.
@@ -13949,10 +13957,10 @@ var CompositeBackend = class {
13949
13957
  /**
13950
13958
  * Structured search results or error string for invalid input.
13951
13959
  */
13952
- async grepRaw(pattern, path3 = "/", glob = null) {
13960
+ async grepRaw(pattern, path4 = "/", glob = null) {
13953
13961
  for (const [routePrefix, backend] of this.sortedRoutes) {
13954
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13955
- const searchPath = path3.substring(routePrefix.length - 1);
13962
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13963
+ const searchPath = path4.substring(routePrefix.length - 1);
13956
13964
  const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
13957
13965
  if (typeof raw === "string") {
13958
13966
  return raw;
@@ -13964,7 +13972,7 @@ var CompositeBackend = class {
13964
13972
  }
13965
13973
  }
13966
13974
  const allMatches = [];
13967
- const rawDefault = await this.default.grepRaw(pattern, path3, glob);
13975
+ const rawDefault = await this.default.grepRaw(pattern, path4, glob);
13968
13976
  if (typeof rawDefault === "string") {
13969
13977
  return rawDefault;
13970
13978
  }
@@ -13986,11 +13994,11 @@ var CompositeBackend = class {
13986
13994
  /**
13987
13995
  * Structured glob matching returning FileInfo objects.
13988
13996
  */
13989
- async globInfo(pattern, path3 = "/") {
13997
+ async globInfo(pattern, path4 = "/") {
13990
13998
  const results = [];
13991
13999
  for (const [routePrefix, backend] of this.sortedRoutes) {
13992
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13993
- const searchPath = path3.substring(routePrefix.length - 1);
14000
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
14001
+ const searchPath = path4.substring(routePrefix.length - 1);
13994
14002
  const infos = await backend.globInfo(pattern, searchPath || "/");
13995
14003
  return infos.map((fi) => ({
13996
14004
  ...fi,
@@ -13998,7 +14006,7 @@ var CompositeBackend = class {
13998
14006
  }));
13999
14007
  }
14000
14008
  }
14001
- const defaultInfos = await this.default.globInfo(pattern, path3);
14009
+ const defaultInfos = await this.default.globInfo(pattern, path4);
14002
14010
  results.push(...defaultInfos);
14003
14011
  for (const [routePrefix, backend] of Object.entries(this.routes)) {
14004
14012
  const infos = await backend.globInfo(pattern, "/");
@@ -14046,11 +14054,11 @@ var MemoryBackend = class {
14046
14054
  getFiles() {
14047
14055
  return Object.fromEntries(this.files);
14048
14056
  }
14049
- lsInfo(path3) {
14057
+ lsInfo(path4) {
14050
14058
  const files = this.getFiles();
14051
14059
  const infos = [];
14052
14060
  const subdirs = /* @__PURE__ */ new Set();
14053
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
14061
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
14054
14062
  for (const [k, fd] of Object.entries(files)) {
14055
14063
  if (!k.startsWith(normalizedPath)) {
14056
14064
  continue;
@@ -14125,13 +14133,13 @@ var MemoryBackend = class {
14125
14133
  this.files.set(filePath, newFileData);
14126
14134
  return { path: filePath, filesUpdate: null, occurrences };
14127
14135
  }
14128
- grepRaw(pattern, path3 = "/", glob = null) {
14136
+ grepRaw(pattern, path4 = "/", glob = null) {
14129
14137
  const files = this.getFiles();
14130
- return grepMatchesFromFiles(files, pattern, path3, glob);
14138
+ return grepMatchesFromFiles(files, pattern, path4, glob);
14131
14139
  }
14132
- globInfo(pattern, path3 = "/") {
14140
+ globInfo(pattern, path4 = "/") {
14133
14141
  const files = this.getFiles();
14134
- const result = globSearchFiles(files, pattern, path3);
14142
+ const result = globSearchFiles(files, pattern, path4);
14135
14143
  if (result === "No files found") {
14136
14144
  return [];
14137
14145
  }
@@ -18186,9 +18194,9 @@ var MicrosandboxInstance = class {
18186
18194
  const fs3 = this.native.fs();
18187
18195
  await fs3.write(file, Buffer.from(content));
18188
18196
  },
18189
- listPath: async (path3, options) => {
18197
+ listPath: async (path4, options) => {
18190
18198
  const fs3 = this.native.fs();
18191
- const entries = await fs3.list(path3);
18199
+ const entries = await fs3.list(path4);
18192
18200
  const files = (entries || []).map((e) => ({
18193
18201
  path: e.path,
18194
18202
  is_dir: e.kind === "directory",
@@ -18197,10 +18205,10 @@ var MicrosandboxInstance = class {
18197
18205
  }));
18198
18206
  return { files };
18199
18207
  },
18200
- findFiles: async (path3, glob) => {
18208
+ findFiles: async (path4, glob) => {
18201
18209
  const output = await this.native.execWithConfig({
18202
18210
  cmd: "sh",
18203
- args: ["-c", `find "${path3}" -name "${glob}" -type f`]
18211
+ args: ["-c", `find "${path4}" -name "${glob}" -type f`]
18204
18212
  });
18205
18213
  const lines = output.stdout().split("\n").filter(Boolean);
18206
18214
  return { files: lines };
@@ -18224,14 +18232,14 @@ var MicrosandboxInstance = class {
18224
18232
  return { matches, line_numbers };
18225
18233
  },
18226
18234
  strReplaceEditor: async (params) => {
18227
- const { path: path3, old_str, new_str, replace_mode } = params;
18235
+ const { path: path4, old_str, new_str, replace_mode } = params;
18228
18236
  const delim = "#";
18229
18237
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18230
18238
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18231
18239
  const flag = replace_mode === "ALL" ? "g" : "";
18232
18240
  await this.native.execWithConfig({
18233
18241
  cmd: "sh",
18234
- args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`]
18242
+ args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`]
18235
18243
  });
18236
18244
  },
18237
18245
  uploadFile: async (params) => {
@@ -18370,31 +18378,77 @@ var MicrosandboxProvider = class {
18370
18378
  }
18371
18379
  };
18372
18380
 
18381
+ // src/sandbox_lattice/pathUtils.ts
18382
+ var import_path2 = __toESM(require("path"));
18383
+ function isVirtualSandboxPath(inputPath) {
18384
+ return inputPath === "~" || inputPath.startsWith("~/") || inputPath.startsWith("/");
18385
+ }
18386
+ function toSandboxHomePath(inputPath, options = {}) {
18387
+ const { homeDir = "/home/daytona", absolute = false } = options;
18388
+ if (!isVirtualSandboxPath(inputPath)) {
18389
+ return inputPath;
18390
+ }
18391
+ let relativePath = inputPath;
18392
+ while (relativePath.startsWith("~/") || relativePath.startsWith("/")) {
18393
+ if (relativePath.startsWith("~/")) {
18394
+ relativePath = relativePath.slice(2);
18395
+ } else {
18396
+ relativePath = relativePath.slice(1);
18397
+ }
18398
+ }
18399
+ if (relativePath === "~") {
18400
+ relativePath = "";
18401
+ }
18402
+ if (!absolute) {
18403
+ return relativePath;
18404
+ }
18405
+ return relativePath ? import_path2.default.posix.join(homeDir, relativePath) : homeDir;
18406
+ }
18407
+
18373
18408
  // src/sandbox_lattice/MicrosandboxRemoteInstance.ts
18374
18409
  var MicrosandboxRemoteInstance = class {
18375
18410
  constructor(name, client) {
18376
18411
  this.client = client;
18377
18412
  this.file = {
18378
18413
  readFile: async (file) => {
18379
- const result = await this.client.readFile(this.name, file);
18414
+ const result = await this.client.readFile(
18415
+ this.name,
18416
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" })
18417
+ );
18380
18418
  return { content: result.content };
18381
18419
  },
18382
18420
  writeFile: async (file, content) => {
18383
- await this.client.writeFile(this.name, file, content);
18421
+ await this.client.writeFile(
18422
+ this.name,
18423
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" }),
18424
+ content
18425
+ );
18384
18426
  },
18385
- listPath: async (path3, options) => {
18386
- const result = await this.client.listPath(this.name, path3, options?.recursive);
18427
+ listPath: async (path4, options) => {
18428
+ const result = await this.client.listPath(
18429
+ this.name,
18430
+ toSandboxHomePath(path4, { absolute: true, homeDir: "/home/daytona" }),
18431
+ options?.recursive
18432
+ );
18387
18433
  const files = result.entries.map((entry) => ({
18388
18434
  path: entry.path,
18389
18435
  is_dir: entry.type === "dir"
18390
18436
  }));
18391
18437
  return { files };
18392
18438
  },
18393
- findFiles: async (path3, glob) => {
18394
- return this.client.findFiles(this.name, path3, glob);
18439
+ findFiles: async (path4, glob) => {
18440
+ return this.client.findFiles(
18441
+ this.name,
18442
+ toSandboxHomePath(path4, { absolute: true, homeDir: "/home/daytona" }),
18443
+ glob
18444
+ );
18395
18445
  },
18396
18446
  searchInFile: async (file, regex) => {
18397
- const result = await this.client.searchInFile(this.name, file, regex);
18447
+ const result = await this.client.searchInFile(
18448
+ this.name,
18449
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" }),
18450
+ regex
18451
+ );
18398
18452
  return {
18399
18453
  matches: result.matches.map((match) => match.content),
18400
18454
  line_numbers: result.matches.map((match) => match.line)
@@ -18402,16 +18456,23 @@ var MicrosandboxRemoteInstance = class {
18402
18456
  },
18403
18457
  strReplaceEditor: async (params) => {
18404
18458
  await this.client.replaceInFile(this.name, {
18405
- path: params.path,
18459
+ path: toSandboxHomePath(params.path, { absolute: true, homeDir: "/home/daytona" }),
18406
18460
  search: params.old_str,
18407
18461
  replace: params.new_str
18408
18462
  });
18409
18463
  },
18410
18464
  uploadFile: async (params) => {
18411
- await this.client.uploadFile(this.name, params.file, params.data);
18465
+ await this.client.uploadFile(
18466
+ this.name,
18467
+ toSandboxHomePath(params.file, { absolute: true, homeDir: "/home/daytona" }),
18468
+ params.data
18469
+ );
18412
18470
  },
18413
18471
  downloadFile: async (params) => {
18414
- const result = await this.client.downloadFile(this.name, params.file);
18472
+ const result = await this.client.downloadFile(
18473
+ this.name,
18474
+ toSandboxHomePath(params.file, { absolute: true, homeDir: "/home/daytona" })
18475
+ );
18415
18476
  if (result.contentBase64) {
18416
18477
  return Buffer.from(result.contentBase64, "base64");
18417
18478
  }
@@ -18456,6 +18517,7 @@ var MicrosandboxRemoteInstance = class {
18456
18517
  var MicrosandboxServiceClient = class {
18457
18518
  constructor(config) {
18458
18519
  this.baseURL = config.baseURL.replace(/\/$/, "");
18520
+ this.apiKey = config.apiKey;
18459
18521
  }
18460
18522
  async ensureSandbox(name, input) {
18461
18523
  return this.request(`/api/sandboxes/${encodeURIComponent(name)}`, {
@@ -18488,34 +18550,34 @@ var MicrosandboxServiceClient = class {
18488
18550
  method: "GET"
18489
18551
  });
18490
18552
  }
18491
- async readFile(sandboxName, path3) {
18553
+ async readFile(sandboxName, path4) {
18492
18554
  return this.request("/api/files/read", {
18493
18555
  method: "POST",
18494
- body: { sandboxName, path: path3 }
18556
+ body: { sandboxName, path: path4 }
18495
18557
  });
18496
18558
  }
18497
- async writeFile(sandboxName, path3, content) {
18559
+ async writeFile(sandboxName, path4, content) {
18498
18560
  return this.request("/api/files/write", {
18499
18561
  method: "POST",
18500
- body: { sandboxName, path: path3, content }
18562
+ body: { sandboxName, path: path4, content }
18501
18563
  });
18502
18564
  }
18503
- async listPath(sandboxName, path3, recursive) {
18565
+ async listPath(sandboxName, path4, recursive) {
18504
18566
  return this.request("/api/files/list", {
18505
18567
  method: "POST",
18506
- body: { sandboxName, path: path3, recursive }
18568
+ body: { sandboxName, path: path4, recursive }
18507
18569
  });
18508
18570
  }
18509
- async findFiles(sandboxName, path3, pattern) {
18571
+ async findFiles(sandboxName, path4, pattern) {
18510
18572
  return this.request("/api/files/find", {
18511
18573
  method: "POST",
18512
- body: { sandboxName, path: path3, pattern }
18574
+ body: { sandboxName, path: path4, pattern }
18513
18575
  });
18514
18576
  }
18515
- async searchInFile(sandboxName, path3, query) {
18577
+ async searchInFile(sandboxName, path4, query) {
18516
18578
  return this.request("/api/files/search", {
18517
18579
  method: "POST",
18518
- body: { sandboxName, path: path3, query }
18580
+ body: { sandboxName, path: path4, query }
18519
18581
  });
18520
18582
  }
18521
18583
  async replaceInFile(sandboxName, input) {
@@ -18524,14 +18586,14 @@ var MicrosandboxServiceClient = class {
18524
18586
  body: { sandboxName, ...input }
18525
18587
  });
18526
18588
  }
18527
- async uploadFile(sandboxName, path3, content) {
18589
+ async uploadFile(sandboxName, path4, content) {
18528
18590
  return this.request("/api/files/upload", {
18529
18591
  method: "POST",
18530
- body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
18592
+ body: { sandboxName, path: path4, contentBase64: content.toString("base64") }
18531
18593
  });
18532
18594
  }
18533
- async downloadFile(sandboxName, path3) {
18534
- const query = new URLSearchParams({ sandboxName, path: path3 });
18595
+ async downloadFile(sandboxName, path4) {
18596
+ const query = new URLSearchParams({ sandboxName, path: path4 });
18535
18597
  return this.request(`/api/files/download?${query.toString()}`, {
18536
18598
  method: "GET"
18537
18599
  });
@@ -18542,33 +18604,60 @@ var MicrosandboxServiceClient = class {
18542
18604
  body: input
18543
18605
  });
18544
18606
  }
18545
- async request(path3, init) {
18546
- const response = await fetch(`${this.baseURL}${path3}`, {
18607
+ async request(path4, init) {
18608
+ const headers = {};
18609
+ if (init.body) {
18610
+ headers["content-type"] = "application/json";
18611
+ }
18612
+ if (this.apiKey) {
18613
+ headers.Authorization = `Bearer ${this.apiKey}`;
18614
+ }
18615
+ const response = await fetch(`${this.baseURL}${path4}`, {
18547
18616
  method: init.method,
18548
- headers: init.body ? { "content-type": "application/json" } : void 0,
18617
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
18549
18618
  body: init.body ? JSON.stringify(init.body) : void 0
18550
18619
  });
18551
18620
  if (!response.ok) {
18552
18621
  throw new Error(`Microsandbox service request failed: ${response.status} ${response.statusText}`);
18553
18622
  }
18554
18623
  const payload = await response.json();
18624
+ if (payload?.success === false) {
18625
+ throw new Error(`Microsandbox service request failed: ${payload.error ?? "unsuccessful response envelope"}`);
18626
+ }
18627
+ if (payload?.success !== true || !("data" in payload)) {
18628
+ throw new Error("Microsandbox service returned an invalid success envelope");
18629
+ }
18555
18630
  return payload.data;
18556
18631
  }
18557
18632
  };
18558
18633
 
18559
18634
  // src/sandbox_lattice/providers/MicrosandboxRemoteProvider.ts
18560
- var defaultMicrosandboxRemoteConfig = {
18561
- image: process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0",
18562
- cpus: Number(process.env.MICROSANDBOX_CPUS ?? "1"),
18563
- memoryMib: Number(process.env.MICROSANDBOX_MEMORY ?? "512")
18564
- };
18635
+ function parseOptionalNumberEnv(name, fallback) {
18636
+ const rawValue = process.env[name];
18637
+ if (rawValue === void 0) {
18638
+ return fallback;
18639
+ }
18640
+ const parsedValue = Number(rawValue);
18641
+ if (!Number.isFinite(parsedValue)) {
18642
+ throw new Error(`Invalid ${name} environment value: ${rawValue}`);
18643
+ }
18644
+ return parsedValue;
18645
+ }
18646
+ function getDefaultMicrosandboxRemoteConfig() {
18647
+ return {
18648
+ image: process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0",
18649
+ cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
18650
+ memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512)
18651
+ };
18652
+ }
18565
18653
  var MicrosandboxRemoteProvider = class {
18566
18654
  constructor(config) {
18567
18655
  this.config = config;
18568
18656
  this.instances = /* @__PURE__ */ new Map();
18569
18657
  this.creating = /* @__PURE__ */ new Map();
18570
18658
  this.client = config.client ?? new MicrosandboxServiceClient({
18571
- baseURL: config.baseURL
18659
+ baseURL: config.baseURL,
18660
+ apiKey: config.apiKey ?? process.env.MICROSANDBOX_API_KEY
18572
18661
  });
18573
18662
  }
18574
18663
  async createSandbox(name, config) {
@@ -18587,9 +18676,14 @@ var MicrosandboxRemoteProvider = class {
18587
18676
  return instance;
18588
18677
  })();
18589
18678
  this.creating.set(name, creation);
18590
- creation.finally(() => {
18591
- this.creating.delete(name);
18592
- });
18679
+ creation.then(
18680
+ () => {
18681
+ this.creating.delete(name);
18682
+ },
18683
+ () => {
18684
+ this.creating.delete(name);
18685
+ }
18686
+ );
18593
18687
  return creation;
18594
18688
  }
18595
18689
  async getSandbox(name) {
@@ -18611,6 +18705,7 @@ var MicrosandboxRemoteProvider = class {
18611
18705
  return Array.from(this.instances.values());
18612
18706
  }
18613
18707
  buildEnsureInput(config) {
18708
+ const defaultMicrosandboxRemoteConfig = getDefaultMicrosandboxRemoteConfig();
18614
18709
  return {
18615
18710
  image: this.config.image ?? defaultMicrosandboxRemoteConfig.image,
18616
18711
  cpus: this.config.cpus ?? defaultMicrosandboxRemoteConfig.cpus,
@@ -18622,20 +18717,20 @@ var MicrosandboxRemoteProvider = class {
18622
18717
  buildDefaultVolumes(config) {
18623
18718
  const tenantId = config?.tenantId ?? "default";
18624
18719
  const volumes = {
18625
- "/home/microsandbox/.agents/skills": {
18720
+ "/home/daytona/.agents/skills": {
18626
18721
  type: "named",
18627
18722
  name: `${tenantId}-skills`
18628
18723
  }
18629
18724
  };
18630
18725
  if (config?.assistant_id) {
18631
- volumes["/home/microsandbox/agent"] = {
18726
+ volumes["/home/daytona/agent"] = {
18632
18727
  type: "named",
18633
18728
  name: `${tenantId}-agent-${config.assistant_id}`
18634
18729
  };
18635
18730
  }
18636
18731
  if (config?.projectId) {
18637
18732
  const projectVolumeName = config.workspaceId ? `${tenantId}-workspace-${config.workspaceId}-project-${config.projectId}` : `${tenantId}-project-${config.projectId}`;
18638
- volumes["/home/microsandbox/project"] = {
18733
+ volumes["/home/daytona/project"] = {
18639
18734
  type: "named",
18640
18735
  name: projectVolumeName
18641
18736
  };
@@ -18665,9 +18760,9 @@ var RemoteSandboxInstance = class {
18665
18760
  throw new Error(String(result.error));
18666
18761
  }
18667
18762
  },
18668
- listPath: async (path3, options) => {
18763
+ listPath: async (path4, options) => {
18669
18764
  const result = await this.client.file.listPath({
18670
- path: path3,
18765
+ path: path4,
18671
18766
  recursive: options?.recursive ?? false
18672
18767
  });
18673
18768
  if (!result.ok) {
@@ -18681,8 +18776,8 @@ var RemoteSandboxInstance = class {
18681
18776
  }));
18682
18777
  return { files };
18683
18778
  },
18684
- findFiles: async (path3, glob) => {
18685
- const result = await this.client.file.findFiles({ path: path3, glob });
18779
+ findFiles: async (path4, glob) => {
18780
+ const result = await this.client.file.findFiles({ path: path4, glob });
18686
18781
  if (!result.ok) {
18687
18782
  throw new Error(String(result.error));
18688
18783
  }
@@ -18819,8 +18914,8 @@ var E2BInstance = class {
18819
18914
  writeFile: async (file, content) => {
18820
18915
  await this.native.files.write(file, content);
18821
18916
  },
18822
- listPath: async (path3, options) => {
18823
- const entries = await this.native.files.list(path3);
18917
+ listPath: async (path4, options) => {
18918
+ const entries = await this.native.files.list(path4);
18824
18919
  const files = entries.map((e) => ({
18825
18920
  path: e.path,
18826
18921
  is_dir: e.type === "dir",
@@ -18829,9 +18924,9 @@ var E2BInstance = class {
18829
18924
  }));
18830
18925
  return { files };
18831
18926
  },
18832
- findFiles: async (path3, glob) => {
18927
+ findFiles: async (path4, glob) => {
18833
18928
  const result = await this.native.commands.run(
18834
- `find "${path3}" -name "${glob}" -type f`
18929
+ `find "${path4}" -name "${glob}" -type f`
18835
18930
  );
18836
18931
  const lines = result.stdout.split("\n").filter(Boolean);
18837
18932
  return { files: lines };
@@ -18854,13 +18949,13 @@ var E2BInstance = class {
18854
18949
  return { matches, line_numbers };
18855
18950
  },
18856
18951
  strReplaceEditor: async (params) => {
18857
- const { path: path3, old_str, new_str, replace_mode } = params;
18952
+ const { path: path4, old_str, new_str, replace_mode } = params;
18858
18953
  const delim = "#";
18859
18954
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18860
18955
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18861
18956
  const flag = replace_mode === "ALL" ? "g" : "";
18862
18957
  await this.native.commands.run(
18863
- `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`
18958
+ `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`
18864
18959
  );
18865
18960
  },
18866
18961
  uploadFile: async (params) => {
@@ -18976,14 +19071,14 @@ var DaytonaInstance = class {
18976
19071
  this.native = native;
18977
19072
  this.file = {
18978
19073
  readFile: async (file) => {
18979
- const buffer2 = await this.native.fs.downloadFile(this.toSandboxHomePath(file));
19074
+ const buffer2 = await this.native.fs.downloadFile(toSandboxHomePath(file));
18980
19075
  return { content: buffer2.toString("utf-8") };
18981
19076
  },
18982
19077
  writeFile: async (file, content) => {
18983
- await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), this.toSandboxHomePath(file));
19078
+ await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toSandboxHomePath(file));
18984
19079
  },
18985
- listPath: async (path3, options) => {
18986
- const entries = await this.native.fs.listFiles(this.toSandboxHomePath(path3));
19080
+ listPath: async (path4, options) => {
19081
+ const entries = await this.native.fs.listFiles(toSandboxHomePath(path4));
18987
19082
  const files = entries.map((e) => {
18988
19083
  let name = e.name || "";
18989
19084
  while (name.startsWith("~/") || name.startsWith("/")) {
@@ -18993,7 +19088,7 @@ var DaytonaInstance = class {
18993
19088
  name = name.slice(1);
18994
19089
  }
18995
19090
  }
18996
- const fullPath = name ? `${path3}/${name}`.replace(/\/+/g, "/") : path3;
19091
+ const fullPath = name ? `${path4}/${name}`.replace(/\/+/g, "/") : path4;
18997
19092
  return {
18998
19093
  path: fullPath,
18999
19094
  is_dir: e.isDir ?? false,
@@ -19003,12 +19098,12 @@ var DaytonaInstance = class {
19003
19098
  });
19004
19099
  return { files };
19005
19100
  },
19006
- findFiles: async (path3, glob) => {
19007
- const result = await this.native.fs.searchFiles(this.toSandboxHomePath(path3), glob);
19101
+ findFiles: async (path4, glob) => {
19102
+ const result = await this.native.fs.searchFiles(toSandboxHomePath(path4), glob);
19008
19103
  return { files: result.files || [] };
19009
19104
  },
19010
19105
  searchInFile: async (file, regex) => {
19011
- const matches = await this.native.fs.findFiles(this.toSandboxHomePath(file), regex);
19106
+ const matches = await this.native.fs.findFiles(toSandboxHomePath(file), regex);
19012
19107
  const line_numbers = [];
19013
19108
  const matchTexts = [];
19014
19109
  for (const match of matches) {
@@ -19018,8 +19113,8 @@ var DaytonaInstance = class {
19018
19113
  return { matches: matchTexts, line_numbers };
19019
19114
  },
19020
19115
  strReplaceEditor: async (params) => {
19021
- const { path: path3, old_str, new_str, replace_mode } = params;
19022
- const relPath = this.toSandboxHomePath(path3);
19116
+ const { path: path4, old_str, new_str, replace_mode } = params;
19117
+ const relPath = toSandboxHomePath(path4);
19023
19118
  if (replace_mode === "ALL") {
19024
19119
  await this.native.fs.replaceInFiles([relPath], old_str, new_str);
19025
19120
  } else {
@@ -19033,10 +19128,10 @@ var DaytonaInstance = class {
19033
19128
  }
19034
19129
  },
19035
19130
  uploadFile: async (params) => {
19036
- await this.native.fs.uploadFile(params.data, this.toSandboxHomePath(params.file));
19131
+ await this.native.fs.uploadFile(params.data, toSandboxHomePath(params.file));
19037
19132
  },
19038
19133
  downloadFile: async (params) => {
19039
- const buffer2 = await this.native.fs.downloadFile(this.toSandboxHomePath(params.file));
19134
+ const buffer2 = await this.native.fs.downloadFile(toSandboxHomePath(params.file));
19040
19135
  return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
19041
19136
  }
19042
19137
  };
@@ -19057,25 +19152,6 @@ var DaytonaInstance = class {
19057
19152
  };
19058
19153
  this.name = name;
19059
19154
  }
19060
- /**
19061
- * All sandbox file operations live under the user's home directory (~).
19062
- * The AI uses virtual paths like "~/agent/file.txt". Daytona SDK expects
19063
- * relative paths for file operations (they are resolved against ~ automatically),
19064
- * so we strip the leading "~/" or "/" here.
19065
- *
19066
- * Handles edge cases like "~/~/agent/file.txt" by repeatedly stripping prefixes.
19067
- */
19068
- toSandboxHomePath(path3) {
19069
- let result = path3;
19070
- while (result.startsWith("~/") || result.startsWith("/")) {
19071
- if (result.startsWith("~/")) {
19072
- result = result.slice(2);
19073
- } else if (result.startsWith("/")) {
19074
- result = result.slice(1);
19075
- }
19076
- }
19077
- return result;
19078
- }
19079
19155
  async start() {
19080
19156
  await this.native.start();
19081
19157
  }