@axiom-lattice/core 2.1.49 → 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.mjs CHANGED
@@ -5011,21 +5011,28 @@ function truncateIfTooLong(result) {
5011
5011
  }
5012
5012
  return result;
5013
5013
  }
5014
- function validatePath(path3) {
5015
- const pathStr = path3 || "/";
5014
+ function validatePath(path4) {
5015
+ const pathStr = path4 || "/";
5016
5016
  if (!pathStr || pathStr.trim() === "") {
5017
5017
  throw new Error("Path cannot be empty");
5018
5018
  }
5019
- let normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
5019
+ let normalized;
5020
+ if (pathStr === "~") {
5021
+ normalized = "~/";
5022
+ } else if (pathStr.startsWith("~/")) {
5023
+ normalized = pathStr;
5024
+ } else {
5025
+ normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
5026
+ }
5020
5027
  if (!normalized.endsWith("/")) {
5021
5028
  normalized += "/";
5022
5029
  }
5023
5030
  return normalized;
5024
5031
  }
5025
- function globSearchFiles(files, pattern, path3 = "/") {
5032
+ function globSearchFiles(files, pattern, path4 = "/") {
5026
5033
  let normalizedPath;
5027
5034
  try {
5028
- normalizedPath = validatePath(path3);
5035
+ normalizedPath = validatePath(path4);
5029
5036
  } catch {
5030
5037
  return "No files found";
5031
5038
  }
@@ -5077,7 +5084,7 @@ function formatGrepResults(results, outputMode) {
5077
5084
  }
5078
5085
  return lines.join("\n");
5079
5086
  }
5080
- function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode = "files_with_matches") {
5087
+ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode = "files_with_matches") {
5081
5088
  let regex;
5082
5089
  try {
5083
5090
  regex = new RegExp(pattern);
@@ -5086,7 +5093,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
5086
5093
  }
5087
5094
  let normalizedPath;
5088
5095
  try {
5089
- normalizedPath = validatePath(path3);
5096
+ normalizedPath = validatePath(path4);
5090
5097
  } catch {
5091
5098
  return "No matches found";
5092
5099
  }
@@ -5118,7 +5125,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
5118
5125
  }
5119
5126
  return formatGrepResults(results, outputMode);
5120
5127
  }
5121
- function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
5128
+ function grepMatchesFromFiles(files, pattern, path4 = null, glob = null) {
5122
5129
  let regex;
5123
5130
  try {
5124
5131
  regex = new RegExp(pattern);
@@ -5127,7 +5134,7 @@ function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
5127
5134
  }
5128
5135
  let normalizedPath;
5129
5136
  try {
5130
- normalizedPath = validatePath(path3);
5137
+ normalizedPath = validatePath(path4);
5131
5138
  } catch {
5132
5139
  return [];
5133
5140
  }
@@ -5188,11 +5195,11 @@ var StateBackend = class {
5188
5195
  * @returns List of FileInfo objects for files and directories directly in the directory.
5189
5196
  * Directories have a trailing / in their path and is_dir=true.
5190
5197
  */
5191
- lsInfo(path3) {
5198
+ lsInfo(path4) {
5192
5199
  const files = this.getFiles();
5193
5200
  const infos = [];
5194
5201
  const subdirs = /* @__PURE__ */ new Set();
5195
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
5202
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
5196
5203
  for (const [k, fd] of Object.entries(files)) {
5197
5204
  if (!k.startsWith(normalizedPath)) {
5198
5205
  continue;
@@ -5298,16 +5305,16 @@ var StateBackend = class {
5298
5305
  /**
5299
5306
  * Structured search results or error string for invalid input.
5300
5307
  */
5301
- grepRaw(pattern, path3 = "/", glob = null) {
5308
+ grepRaw(pattern, path4 = "/", glob = null) {
5302
5309
  const files = this.getFiles();
5303
- return grepMatchesFromFiles(files, pattern, path3, glob);
5310
+ return grepMatchesFromFiles(files, pattern, path4, glob);
5304
5311
  }
5305
5312
  /**
5306
5313
  * Structured glob matching returning FileInfo objects.
5307
5314
  */
5308
- globInfo(pattern, path3 = "/") {
5315
+ globInfo(pattern, path4 = "/") {
5309
5316
  const files = this.getFiles();
5310
- const result = globSearchFiles(files, pattern, path3);
5317
+ const result = globSearchFiles(files, pattern, path4);
5311
5318
  if (result === "No files found") {
5312
5319
  return [];
5313
5320
  }
@@ -5401,10 +5408,10 @@ function createLsTool(backend, options) {
5401
5408
  ...runConfig
5402
5409
  };
5403
5410
  const resolvedBackend = await getBackend(backend, stateAndStore);
5404
- const path3 = input.path || "/";
5405
- const infos = await resolvedBackend.lsInfo(path3);
5411
+ const path4 = input.path || "/";
5412
+ const infos = await resolvedBackend.lsInfo(path4);
5406
5413
  if (infos.length === 0) {
5407
- return `No files found in ${path3}`;
5414
+ return `No files found in ${path4}`;
5408
5415
  }
5409
5416
  const lines = [];
5410
5417
  for (const info of infos) {
@@ -5547,8 +5554,8 @@ function createGlobTool(backend, options) {
5547
5554
  ...runConfig
5548
5555
  };
5549
5556
  const resolvedBackend = await getBackend(backend, stateAndStore);
5550
- const { pattern, path: path3 = "/" } = input;
5551
- const infos = await resolvedBackend.globInfo(pattern, path3);
5557
+ const { pattern, path: path4 = "/" } = input;
5558
+ const infos = await resolvedBackend.globInfo(pattern, path4);
5552
5559
  if (infos.length === 0) {
5553
5560
  return `No files found matching pattern '${pattern}'`;
5554
5561
  }
@@ -5575,8 +5582,8 @@ function createGrepTool(backend, options) {
5575
5582
  ...runConfig
5576
5583
  };
5577
5584
  const resolvedBackend = await getBackend(backend, stateAndStore);
5578
- const { pattern, path: path3 = "/", glob = null } = input;
5579
- const result = await resolvedBackend.grepRaw(pattern, path3, glob);
5585
+ const { pattern, path: path4 = "/", glob = null } = input;
5586
+ const result = await resolvedBackend.grepRaw(pattern, path4, glob);
5580
5587
  if (typeof result === "string") {
5581
5588
  return result;
5582
5589
  }
@@ -12995,13 +13002,13 @@ var StoreBackend = class {
12995
13002
  * @returns List of FileInfo objects for files and directories directly in the directory.
12996
13003
  * Directories have a trailing / in their path and is_dir=true.
12997
13004
  */
12998
- async lsInfo(path3) {
13005
+ async lsInfo(path4) {
12999
13006
  const store = this.getStore();
13000
13007
  const namespace = this.getNamespace();
13001
13008
  const items = await this.searchStorePaginated(store, namespace);
13002
13009
  const infos = [];
13003
13010
  const subdirs = /* @__PURE__ */ new Set();
13004
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
13011
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
13005
13012
  for (const item of items) {
13006
13013
  const itemKey = String(item.key);
13007
13014
  if (!itemKey.startsWith(normalizedPath)) {
@@ -13119,7 +13126,7 @@ var StoreBackend = class {
13119
13126
  /**
13120
13127
  * Structured search results or error string for invalid input.
13121
13128
  */
13122
- async grepRaw(pattern, path3 = "/", glob = null) {
13129
+ async grepRaw(pattern, path4 = "/", glob = null) {
13123
13130
  const store = this.getStore();
13124
13131
  const namespace = this.getNamespace();
13125
13132
  const items = await this.searchStorePaginated(store, namespace);
@@ -13131,12 +13138,12 @@ var StoreBackend = class {
13131
13138
  continue;
13132
13139
  }
13133
13140
  }
13134
- return grepMatchesFromFiles(files, pattern, path3, glob);
13141
+ return grepMatchesFromFiles(files, pattern, path4, glob);
13135
13142
  }
13136
13143
  /**
13137
13144
  * Structured glob matching returning FileInfo objects.
13138
13145
  */
13139
- async globInfo(pattern, path3 = "/") {
13146
+ async globInfo(pattern, path4 = "/") {
13140
13147
  const store = this.getStore();
13141
13148
  const namespace = this.getNamespace();
13142
13149
  const items = await this.searchStorePaginated(store, namespace);
@@ -13148,7 +13155,7 @@ var StoreBackend = class {
13148
13155
  continue;
13149
13156
  }
13150
13157
  }
13151
- const result = globSearchFiles(files, pattern, path3);
13158
+ const result = globSearchFiles(files, pattern, path4);
13152
13159
  if (result === "No files found") {
13153
13160
  return [];
13154
13161
  }
@@ -13197,8 +13204,9 @@ var FilesystemBackend = class {
13197
13204
  */
13198
13205
  resolvePath(key) {
13199
13206
  if (this.virtualMode) {
13200
- const vpath = key.startsWith("/") ? key : "/" + key;
13201
- if (vpath.includes("..") || vpath.startsWith("~")) {
13207
+ const normalizedKey = key === "~" ? "/" : key.startsWith("~/") ? `/${key.slice(2)}` : key;
13208
+ const vpath = normalizedKey.startsWith("/") ? normalizedKey : "/" + normalizedKey;
13209
+ if (vpath.includes("..") || vpath.includes("~")) {
13202
13210
  throw new Error("Path traversal not allowed");
13203
13211
  }
13204
13212
  const full = path2.resolve(this.cwd, vpath.substring(1));
@@ -13723,10 +13731,10 @@ var CompositeBackend = class {
13723
13731
  * @returns List of FileInfo objects with route prefixes added, for files and directories
13724
13732
  * directly in the directory. Directories have a trailing / in their path and is_dir=true.
13725
13733
  */
13726
- async lsInfo(path3) {
13734
+ async lsInfo(path4) {
13727
13735
  for (const [routePrefix, backend] of this.sortedRoutes) {
13728
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13729
- const suffix = path3.substring(routePrefix.length);
13736
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13737
+ const suffix = path4.substring(routePrefix.length);
13730
13738
  const searchPath = suffix ? "/" + suffix : "/";
13731
13739
  const infos = await backend.lsInfo(searchPath);
13732
13740
  const prefixed = [];
@@ -13739,9 +13747,9 @@ var CompositeBackend = class {
13739
13747
  return prefixed;
13740
13748
  }
13741
13749
  }
13742
- if (path3 === "/") {
13750
+ if (path4 === "/") {
13743
13751
  const results = [];
13744
- const defaultInfos = await this.default.lsInfo(path3);
13752
+ const defaultInfos = await this.default.lsInfo(path4);
13745
13753
  results.push(...defaultInfos);
13746
13754
  for (const [routePrefix] of this.sortedRoutes) {
13747
13755
  results.push({
@@ -13754,7 +13762,7 @@ var CompositeBackend = class {
13754
13762
  results.sort((a, b) => a.path.localeCompare(b.path));
13755
13763
  return results;
13756
13764
  }
13757
- return await this.default.lsInfo(path3);
13765
+ return await this.default.lsInfo(path4);
13758
13766
  }
13759
13767
  /**
13760
13768
  * Read file content, routing to appropriate backend.
@@ -13781,10 +13789,10 @@ var CompositeBackend = class {
13781
13789
  /**
13782
13790
  * Structured search results or error string for invalid input.
13783
13791
  */
13784
- async grepRaw(pattern, path3 = "/", glob = null) {
13792
+ async grepRaw(pattern, path4 = "/", glob = null) {
13785
13793
  for (const [routePrefix, backend] of this.sortedRoutes) {
13786
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13787
- const searchPath = path3.substring(routePrefix.length - 1);
13794
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13795
+ const searchPath = path4.substring(routePrefix.length - 1);
13788
13796
  const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
13789
13797
  if (typeof raw === "string") {
13790
13798
  return raw;
@@ -13796,7 +13804,7 @@ var CompositeBackend = class {
13796
13804
  }
13797
13805
  }
13798
13806
  const allMatches = [];
13799
- const rawDefault = await this.default.grepRaw(pattern, path3, glob);
13807
+ const rawDefault = await this.default.grepRaw(pattern, path4, glob);
13800
13808
  if (typeof rawDefault === "string") {
13801
13809
  return rawDefault;
13802
13810
  }
@@ -13818,11 +13826,11 @@ var CompositeBackend = class {
13818
13826
  /**
13819
13827
  * Structured glob matching returning FileInfo objects.
13820
13828
  */
13821
- async globInfo(pattern, path3 = "/") {
13829
+ async globInfo(pattern, path4 = "/") {
13822
13830
  const results = [];
13823
13831
  for (const [routePrefix, backend] of this.sortedRoutes) {
13824
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
13825
- const searchPath = path3.substring(routePrefix.length - 1);
13832
+ if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13833
+ const searchPath = path4.substring(routePrefix.length - 1);
13826
13834
  const infos = await backend.globInfo(pattern, searchPath || "/");
13827
13835
  return infos.map((fi) => ({
13828
13836
  ...fi,
@@ -13830,7 +13838,7 @@ var CompositeBackend = class {
13830
13838
  }));
13831
13839
  }
13832
13840
  }
13833
- const defaultInfos = await this.default.globInfo(pattern, path3);
13841
+ const defaultInfos = await this.default.globInfo(pattern, path4);
13834
13842
  results.push(...defaultInfos);
13835
13843
  for (const [routePrefix, backend] of Object.entries(this.routes)) {
13836
13844
  const infos = await backend.globInfo(pattern, "/");
@@ -13878,11 +13886,11 @@ var MemoryBackend = class {
13878
13886
  getFiles() {
13879
13887
  return Object.fromEntries(this.files);
13880
13888
  }
13881
- lsInfo(path3) {
13889
+ lsInfo(path4) {
13882
13890
  const files = this.getFiles();
13883
13891
  const infos = [];
13884
13892
  const subdirs = /* @__PURE__ */ new Set();
13885
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
13893
+ const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
13886
13894
  for (const [k, fd] of Object.entries(files)) {
13887
13895
  if (!k.startsWith(normalizedPath)) {
13888
13896
  continue;
@@ -13957,13 +13965,13 @@ var MemoryBackend = class {
13957
13965
  this.files.set(filePath, newFileData);
13958
13966
  return { path: filePath, filesUpdate: null, occurrences };
13959
13967
  }
13960
- grepRaw(pattern, path3 = "/", glob = null) {
13968
+ grepRaw(pattern, path4 = "/", glob = null) {
13961
13969
  const files = this.getFiles();
13962
- return grepMatchesFromFiles(files, pattern, path3, glob);
13970
+ return grepMatchesFromFiles(files, pattern, path4, glob);
13963
13971
  }
13964
- globInfo(pattern, path3 = "/") {
13972
+ globInfo(pattern, path4 = "/") {
13965
13973
  const files = this.getFiles();
13966
- const result = globSearchFiles(files, pattern, path3);
13974
+ const result = globSearchFiles(files, pattern, path4);
13967
13975
  if (result === "No files found") {
13968
13976
  return [];
13969
13977
  }
@@ -18024,9 +18032,9 @@ var MicrosandboxInstance = class {
18024
18032
  const fs3 = this.native.fs();
18025
18033
  await fs3.write(file, Buffer.from(content));
18026
18034
  },
18027
- listPath: async (path3, options) => {
18035
+ listPath: async (path4, options) => {
18028
18036
  const fs3 = this.native.fs();
18029
- const entries = await fs3.list(path3);
18037
+ const entries = await fs3.list(path4);
18030
18038
  const files = (entries || []).map((e) => ({
18031
18039
  path: e.path,
18032
18040
  is_dir: e.kind === "directory",
@@ -18035,10 +18043,10 @@ var MicrosandboxInstance = class {
18035
18043
  }));
18036
18044
  return { files };
18037
18045
  },
18038
- findFiles: async (path3, glob) => {
18046
+ findFiles: async (path4, glob) => {
18039
18047
  const output = await this.native.execWithConfig({
18040
18048
  cmd: "sh",
18041
- args: ["-c", `find "${path3}" -name "${glob}" -type f`]
18049
+ args: ["-c", `find "${path4}" -name "${glob}" -type f`]
18042
18050
  });
18043
18051
  const lines = output.stdout().split("\n").filter(Boolean);
18044
18052
  return { files: lines };
@@ -18062,14 +18070,14 @@ var MicrosandboxInstance = class {
18062
18070
  return { matches, line_numbers };
18063
18071
  },
18064
18072
  strReplaceEditor: async (params) => {
18065
- const { path: path3, old_str, new_str, replace_mode } = params;
18073
+ const { path: path4, old_str, new_str, replace_mode } = params;
18066
18074
  const delim = "#";
18067
18075
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18068
18076
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18069
18077
  const flag = replace_mode === "ALL" ? "g" : "";
18070
18078
  await this.native.execWithConfig({
18071
18079
  cmd: "sh",
18072
- args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`]
18080
+ args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`]
18073
18081
  });
18074
18082
  },
18075
18083
  uploadFile: async (params) => {
@@ -18208,31 +18216,77 @@ var MicrosandboxProvider = class {
18208
18216
  }
18209
18217
  };
18210
18218
 
18219
+ // src/sandbox_lattice/pathUtils.ts
18220
+ import path3 from "path";
18221
+ function isVirtualSandboxPath(inputPath) {
18222
+ return inputPath === "~" || inputPath.startsWith("~/") || inputPath.startsWith("/");
18223
+ }
18224
+ function toSandboxHomePath(inputPath, options = {}) {
18225
+ const { homeDir = "/home/daytona", absolute = false } = options;
18226
+ if (!isVirtualSandboxPath(inputPath)) {
18227
+ return inputPath;
18228
+ }
18229
+ let relativePath = inputPath;
18230
+ while (relativePath.startsWith("~/") || relativePath.startsWith("/")) {
18231
+ if (relativePath.startsWith("~/")) {
18232
+ relativePath = relativePath.slice(2);
18233
+ } else {
18234
+ relativePath = relativePath.slice(1);
18235
+ }
18236
+ }
18237
+ if (relativePath === "~") {
18238
+ relativePath = "";
18239
+ }
18240
+ if (!absolute) {
18241
+ return relativePath;
18242
+ }
18243
+ return relativePath ? path3.posix.join(homeDir, relativePath) : homeDir;
18244
+ }
18245
+
18211
18246
  // src/sandbox_lattice/MicrosandboxRemoteInstance.ts
18212
18247
  var MicrosandboxRemoteInstance = class {
18213
18248
  constructor(name, client) {
18214
18249
  this.client = client;
18215
18250
  this.file = {
18216
18251
  readFile: async (file) => {
18217
- const result = await this.client.readFile(this.name, file);
18252
+ const result = await this.client.readFile(
18253
+ this.name,
18254
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" })
18255
+ );
18218
18256
  return { content: result.content };
18219
18257
  },
18220
18258
  writeFile: async (file, content) => {
18221
- await this.client.writeFile(this.name, file, content);
18259
+ await this.client.writeFile(
18260
+ this.name,
18261
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" }),
18262
+ content
18263
+ );
18222
18264
  },
18223
- listPath: async (path3, options) => {
18224
- const result = await this.client.listPath(this.name, path3, options?.recursive);
18265
+ listPath: async (path4, options) => {
18266
+ const result = await this.client.listPath(
18267
+ this.name,
18268
+ toSandboxHomePath(path4, { absolute: true, homeDir: "/home/daytona" }),
18269
+ options?.recursive
18270
+ );
18225
18271
  const files = result.entries.map((entry) => ({
18226
18272
  path: entry.path,
18227
18273
  is_dir: entry.type === "dir"
18228
18274
  }));
18229
18275
  return { files };
18230
18276
  },
18231
- findFiles: async (path3, glob) => {
18232
- return this.client.findFiles(this.name, path3, glob);
18277
+ findFiles: async (path4, glob) => {
18278
+ return this.client.findFiles(
18279
+ this.name,
18280
+ toSandboxHomePath(path4, { absolute: true, homeDir: "/home/daytona" }),
18281
+ glob
18282
+ );
18233
18283
  },
18234
18284
  searchInFile: async (file, regex) => {
18235
- const result = await this.client.searchInFile(this.name, file, regex);
18285
+ const result = await this.client.searchInFile(
18286
+ this.name,
18287
+ toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" }),
18288
+ regex
18289
+ );
18236
18290
  return {
18237
18291
  matches: result.matches.map((match) => match.content),
18238
18292
  line_numbers: result.matches.map((match) => match.line)
@@ -18240,16 +18294,23 @@ var MicrosandboxRemoteInstance = class {
18240
18294
  },
18241
18295
  strReplaceEditor: async (params) => {
18242
18296
  await this.client.replaceInFile(this.name, {
18243
- path: params.path,
18297
+ path: toSandboxHomePath(params.path, { absolute: true, homeDir: "/home/daytona" }),
18244
18298
  search: params.old_str,
18245
18299
  replace: params.new_str
18246
18300
  });
18247
18301
  },
18248
18302
  uploadFile: async (params) => {
18249
- await this.client.uploadFile(this.name, params.file, params.data);
18303
+ await this.client.uploadFile(
18304
+ this.name,
18305
+ toSandboxHomePath(params.file, { absolute: true, homeDir: "/home/daytona" }),
18306
+ params.data
18307
+ );
18250
18308
  },
18251
18309
  downloadFile: async (params) => {
18252
- const result = await this.client.downloadFile(this.name, params.file);
18310
+ const result = await this.client.downloadFile(
18311
+ this.name,
18312
+ toSandboxHomePath(params.file, { absolute: true, homeDir: "/home/daytona" })
18313
+ );
18253
18314
  if (result.contentBase64) {
18254
18315
  return Buffer.from(result.contentBase64, "base64");
18255
18316
  }
@@ -18294,6 +18355,7 @@ var MicrosandboxRemoteInstance = class {
18294
18355
  var MicrosandboxServiceClient = class {
18295
18356
  constructor(config) {
18296
18357
  this.baseURL = config.baseURL.replace(/\/$/, "");
18358
+ this.apiKey = config.apiKey;
18297
18359
  }
18298
18360
  async ensureSandbox(name, input) {
18299
18361
  return this.request(`/api/sandboxes/${encodeURIComponent(name)}`, {
@@ -18326,34 +18388,34 @@ var MicrosandboxServiceClient = class {
18326
18388
  method: "GET"
18327
18389
  });
18328
18390
  }
18329
- async readFile(sandboxName, path3) {
18391
+ async readFile(sandboxName, path4) {
18330
18392
  return this.request("/api/files/read", {
18331
18393
  method: "POST",
18332
- body: { sandboxName, path: path3 }
18394
+ body: { sandboxName, path: path4 }
18333
18395
  });
18334
18396
  }
18335
- async writeFile(sandboxName, path3, content) {
18397
+ async writeFile(sandboxName, path4, content) {
18336
18398
  return this.request("/api/files/write", {
18337
18399
  method: "POST",
18338
- body: { sandboxName, path: path3, content }
18400
+ body: { sandboxName, path: path4, content }
18339
18401
  });
18340
18402
  }
18341
- async listPath(sandboxName, path3, recursive) {
18403
+ async listPath(sandboxName, path4, recursive) {
18342
18404
  return this.request("/api/files/list", {
18343
18405
  method: "POST",
18344
- body: { sandboxName, path: path3, recursive }
18406
+ body: { sandboxName, path: path4, recursive }
18345
18407
  });
18346
18408
  }
18347
- async findFiles(sandboxName, path3, pattern) {
18409
+ async findFiles(sandboxName, path4, pattern) {
18348
18410
  return this.request("/api/files/find", {
18349
18411
  method: "POST",
18350
- body: { sandboxName, path: path3, pattern }
18412
+ body: { sandboxName, path: path4, pattern }
18351
18413
  });
18352
18414
  }
18353
- async searchInFile(sandboxName, path3, query) {
18415
+ async searchInFile(sandboxName, path4, query) {
18354
18416
  return this.request("/api/files/search", {
18355
18417
  method: "POST",
18356
- body: { sandboxName, path: path3, query }
18418
+ body: { sandboxName, path: path4, query }
18357
18419
  });
18358
18420
  }
18359
18421
  async replaceInFile(sandboxName, input) {
@@ -18362,14 +18424,14 @@ var MicrosandboxServiceClient = class {
18362
18424
  body: { sandboxName, ...input }
18363
18425
  });
18364
18426
  }
18365
- async uploadFile(sandboxName, path3, content) {
18427
+ async uploadFile(sandboxName, path4, content) {
18366
18428
  return this.request("/api/files/upload", {
18367
18429
  method: "POST",
18368
- body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
18430
+ body: { sandboxName, path: path4, contentBase64: content.toString("base64") }
18369
18431
  });
18370
18432
  }
18371
- async downloadFile(sandboxName, path3) {
18372
- const query = new URLSearchParams({ sandboxName, path: path3 });
18433
+ async downloadFile(sandboxName, path4) {
18434
+ const query = new URLSearchParams({ sandboxName, path: path4 });
18373
18435
  return this.request(`/api/files/download?${query.toString()}`, {
18374
18436
  method: "GET"
18375
18437
  });
@@ -18380,33 +18442,60 @@ var MicrosandboxServiceClient = class {
18380
18442
  body: input
18381
18443
  });
18382
18444
  }
18383
- async request(path3, init) {
18384
- const response = await fetch(`${this.baseURL}${path3}`, {
18445
+ async request(path4, init) {
18446
+ const headers = {};
18447
+ if (init.body) {
18448
+ headers["content-type"] = "application/json";
18449
+ }
18450
+ if (this.apiKey) {
18451
+ headers.Authorization = `Bearer ${this.apiKey}`;
18452
+ }
18453
+ const response = await fetch(`${this.baseURL}${path4}`, {
18385
18454
  method: init.method,
18386
- headers: init.body ? { "content-type": "application/json" } : void 0,
18455
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
18387
18456
  body: init.body ? JSON.stringify(init.body) : void 0
18388
18457
  });
18389
18458
  if (!response.ok) {
18390
18459
  throw new Error(`Microsandbox service request failed: ${response.status} ${response.statusText}`);
18391
18460
  }
18392
18461
  const payload = await response.json();
18462
+ if (payload?.success === false) {
18463
+ throw new Error(`Microsandbox service request failed: ${payload.error ?? "unsuccessful response envelope"}`);
18464
+ }
18465
+ if (payload?.success !== true || !("data" in payload)) {
18466
+ throw new Error("Microsandbox service returned an invalid success envelope");
18467
+ }
18393
18468
  return payload.data;
18394
18469
  }
18395
18470
  };
18396
18471
 
18397
18472
  // src/sandbox_lattice/providers/MicrosandboxRemoteProvider.ts
18398
- var defaultMicrosandboxRemoteConfig = {
18399
- image: process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0",
18400
- cpus: Number(process.env.MICROSANDBOX_CPUS ?? "1"),
18401
- memoryMib: Number(process.env.MICROSANDBOX_MEMORY ?? "512")
18402
- };
18473
+ function parseOptionalNumberEnv(name, fallback) {
18474
+ const rawValue = process.env[name];
18475
+ if (rawValue === void 0) {
18476
+ return fallback;
18477
+ }
18478
+ const parsedValue = Number(rawValue);
18479
+ if (!Number.isFinite(parsedValue)) {
18480
+ throw new Error(`Invalid ${name} environment value: ${rawValue}`);
18481
+ }
18482
+ return parsedValue;
18483
+ }
18484
+ function getDefaultMicrosandboxRemoteConfig() {
18485
+ return {
18486
+ image: process.env.MICROSANDBOX_IMAGE ?? "daytonaio/sandbox:0.6.0",
18487
+ cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
18488
+ memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512)
18489
+ };
18490
+ }
18403
18491
  var MicrosandboxRemoteProvider = class {
18404
18492
  constructor(config) {
18405
18493
  this.config = config;
18406
18494
  this.instances = /* @__PURE__ */ new Map();
18407
18495
  this.creating = /* @__PURE__ */ new Map();
18408
18496
  this.client = config.client ?? new MicrosandboxServiceClient({
18409
- baseURL: config.baseURL
18497
+ baseURL: config.baseURL,
18498
+ apiKey: config.apiKey ?? process.env.MICROSANDBOX_API_KEY
18410
18499
  });
18411
18500
  }
18412
18501
  async createSandbox(name, config) {
@@ -18425,9 +18514,14 @@ var MicrosandboxRemoteProvider = class {
18425
18514
  return instance;
18426
18515
  })();
18427
18516
  this.creating.set(name, creation);
18428
- creation.finally(() => {
18429
- this.creating.delete(name);
18430
- });
18517
+ creation.then(
18518
+ () => {
18519
+ this.creating.delete(name);
18520
+ },
18521
+ () => {
18522
+ this.creating.delete(name);
18523
+ }
18524
+ );
18431
18525
  return creation;
18432
18526
  }
18433
18527
  async getSandbox(name) {
@@ -18449,6 +18543,7 @@ var MicrosandboxRemoteProvider = class {
18449
18543
  return Array.from(this.instances.values());
18450
18544
  }
18451
18545
  buildEnsureInput(config) {
18546
+ const defaultMicrosandboxRemoteConfig = getDefaultMicrosandboxRemoteConfig();
18452
18547
  return {
18453
18548
  image: this.config.image ?? defaultMicrosandboxRemoteConfig.image,
18454
18549
  cpus: this.config.cpus ?? defaultMicrosandboxRemoteConfig.cpus,
@@ -18460,20 +18555,20 @@ var MicrosandboxRemoteProvider = class {
18460
18555
  buildDefaultVolumes(config) {
18461
18556
  const tenantId = config?.tenantId ?? "default";
18462
18557
  const volumes = {
18463
- "/home/microsandbox/.agents/skills": {
18558
+ "/home/daytona/.agents/skills": {
18464
18559
  type: "named",
18465
18560
  name: `${tenantId}-skills`
18466
18561
  }
18467
18562
  };
18468
18563
  if (config?.assistant_id) {
18469
- volumes["/home/microsandbox/agent"] = {
18564
+ volumes["/home/daytona/agent"] = {
18470
18565
  type: "named",
18471
18566
  name: `${tenantId}-agent-${config.assistant_id}`
18472
18567
  };
18473
18568
  }
18474
18569
  if (config?.projectId) {
18475
18570
  const projectVolumeName = config.workspaceId ? `${tenantId}-workspace-${config.workspaceId}-project-${config.projectId}` : `${tenantId}-project-${config.projectId}`;
18476
- volumes["/home/microsandbox/project"] = {
18571
+ volumes["/home/daytona/project"] = {
18477
18572
  type: "named",
18478
18573
  name: projectVolumeName
18479
18574
  };
@@ -18503,9 +18598,9 @@ var RemoteSandboxInstance = class {
18503
18598
  throw new Error(String(result.error));
18504
18599
  }
18505
18600
  },
18506
- listPath: async (path3, options) => {
18601
+ listPath: async (path4, options) => {
18507
18602
  const result = await this.client.file.listPath({
18508
- path: path3,
18603
+ path: path4,
18509
18604
  recursive: options?.recursive ?? false
18510
18605
  });
18511
18606
  if (!result.ok) {
@@ -18519,8 +18614,8 @@ var RemoteSandboxInstance = class {
18519
18614
  }));
18520
18615
  return { files };
18521
18616
  },
18522
- findFiles: async (path3, glob) => {
18523
- const result = await this.client.file.findFiles({ path: path3, glob });
18617
+ findFiles: async (path4, glob) => {
18618
+ const result = await this.client.file.findFiles({ path: path4, glob });
18524
18619
  if (!result.ok) {
18525
18620
  throw new Error(String(result.error));
18526
18621
  }
@@ -18657,8 +18752,8 @@ var E2BInstance = class {
18657
18752
  writeFile: async (file, content) => {
18658
18753
  await this.native.files.write(file, content);
18659
18754
  },
18660
- listPath: async (path3, options) => {
18661
- const entries = await this.native.files.list(path3);
18755
+ listPath: async (path4, options) => {
18756
+ const entries = await this.native.files.list(path4);
18662
18757
  const files = entries.map((e) => ({
18663
18758
  path: e.path,
18664
18759
  is_dir: e.type === "dir",
@@ -18667,9 +18762,9 @@ var E2BInstance = class {
18667
18762
  }));
18668
18763
  return { files };
18669
18764
  },
18670
- findFiles: async (path3, glob) => {
18765
+ findFiles: async (path4, glob) => {
18671
18766
  const result = await this.native.commands.run(
18672
- `find "${path3}" -name "${glob}" -type f`
18767
+ `find "${path4}" -name "${glob}" -type f`
18673
18768
  );
18674
18769
  const lines = result.stdout.split("\n").filter(Boolean);
18675
18770
  return { files: lines };
@@ -18692,13 +18787,13 @@ var E2BInstance = class {
18692
18787
  return { matches, line_numbers };
18693
18788
  },
18694
18789
  strReplaceEditor: async (params) => {
18695
- const { path: path3, old_str, new_str, replace_mode } = params;
18790
+ const { path: path4, old_str, new_str, replace_mode } = params;
18696
18791
  const delim = "#";
18697
18792
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18698
18793
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18699
18794
  const flag = replace_mode === "ALL" ? "g" : "";
18700
18795
  await this.native.commands.run(
18701
- `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`
18796
+ `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`
18702
18797
  );
18703
18798
  },
18704
18799
  uploadFile: async (params) => {
@@ -18814,14 +18909,14 @@ var DaytonaInstance = class {
18814
18909
  this.native = native;
18815
18910
  this.file = {
18816
18911
  readFile: async (file) => {
18817
- const buffer2 = await this.native.fs.downloadFile(this.toSandboxHomePath(file));
18912
+ const buffer2 = await this.native.fs.downloadFile(toSandboxHomePath(file));
18818
18913
  return { content: buffer2.toString("utf-8") };
18819
18914
  },
18820
18915
  writeFile: async (file, content) => {
18821
- await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), this.toSandboxHomePath(file));
18916
+ await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toSandboxHomePath(file));
18822
18917
  },
18823
- listPath: async (path3, options) => {
18824
- const entries = await this.native.fs.listFiles(this.toSandboxHomePath(path3));
18918
+ listPath: async (path4, options) => {
18919
+ const entries = await this.native.fs.listFiles(toSandboxHomePath(path4));
18825
18920
  const files = entries.map((e) => {
18826
18921
  let name = e.name || "";
18827
18922
  while (name.startsWith("~/") || name.startsWith("/")) {
@@ -18831,7 +18926,7 @@ var DaytonaInstance = class {
18831
18926
  name = name.slice(1);
18832
18927
  }
18833
18928
  }
18834
- const fullPath = name ? `${path3}/${name}`.replace(/\/+/g, "/") : path3;
18929
+ const fullPath = name ? `${path4}/${name}`.replace(/\/+/g, "/") : path4;
18835
18930
  return {
18836
18931
  path: fullPath,
18837
18932
  is_dir: e.isDir ?? false,
@@ -18841,12 +18936,12 @@ var DaytonaInstance = class {
18841
18936
  });
18842
18937
  return { files };
18843
18938
  },
18844
- findFiles: async (path3, glob) => {
18845
- const result = await this.native.fs.searchFiles(this.toSandboxHomePath(path3), glob);
18939
+ findFiles: async (path4, glob) => {
18940
+ const result = await this.native.fs.searchFiles(toSandboxHomePath(path4), glob);
18846
18941
  return { files: result.files || [] };
18847
18942
  },
18848
18943
  searchInFile: async (file, regex) => {
18849
- const matches = await this.native.fs.findFiles(this.toSandboxHomePath(file), regex);
18944
+ const matches = await this.native.fs.findFiles(toSandboxHomePath(file), regex);
18850
18945
  const line_numbers = [];
18851
18946
  const matchTexts = [];
18852
18947
  for (const match of matches) {
@@ -18856,8 +18951,8 @@ var DaytonaInstance = class {
18856
18951
  return { matches: matchTexts, line_numbers };
18857
18952
  },
18858
18953
  strReplaceEditor: async (params) => {
18859
- const { path: path3, old_str, new_str, replace_mode } = params;
18860
- const relPath = this.toSandboxHomePath(path3);
18954
+ const { path: path4, old_str, new_str, replace_mode } = params;
18955
+ const relPath = toSandboxHomePath(path4);
18861
18956
  if (replace_mode === "ALL") {
18862
18957
  await this.native.fs.replaceInFiles([relPath], old_str, new_str);
18863
18958
  } else {
@@ -18871,10 +18966,10 @@ var DaytonaInstance = class {
18871
18966
  }
18872
18967
  },
18873
18968
  uploadFile: async (params) => {
18874
- await this.native.fs.uploadFile(params.data, this.toSandboxHomePath(params.file));
18969
+ await this.native.fs.uploadFile(params.data, toSandboxHomePath(params.file));
18875
18970
  },
18876
18971
  downloadFile: async (params) => {
18877
- const buffer2 = await this.native.fs.downloadFile(this.toSandboxHomePath(params.file));
18972
+ const buffer2 = await this.native.fs.downloadFile(toSandboxHomePath(params.file));
18878
18973
  return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
18879
18974
  }
18880
18975
  };
@@ -18895,25 +18990,6 @@ var DaytonaInstance = class {
18895
18990
  };
18896
18991
  this.name = name;
18897
18992
  }
18898
- /**
18899
- * All sandbox file operations live under the user's home directory (~).
18900
- * The AI uses virtual paths like "~/agent/file.txt". Daytona SDK expects
18901
- * relative paths for file operations (they are resolved against ~ automatically),
18902
- * so we strip the leading "~/" or "/" here.
18903
- *
18904
- * Handles edge cases like "~/~/agent/file.txt" by repeatedly stripping prefixes.
18905
- */
18906
- toSandboxHomePath(path3) {
18907
- let result = path3;
18908
- while (result.startsWith("~/") || result.startsWith("/")) {
18909
- if (result.startsWith("~/")) {
18910
- result = result.slice(2);
18911
- } else if (result.startsWith("/")) {
18912
- result = result.slice(1);
18913
- }
18914
- }
18915
- return result;
18916
- }
18917
18993
  async start() {
18918
18994
  await this.native.start();
18919
18995
  }