@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.d.mts +5 -11
- package/dist/index.d.ts +5 -11
- package/dist/index.js +212 -136
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +212 -136
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5011,21 +5011,28 @@ function truncateIfTooLong(result) {
|
|
|
5011
5011
|
}
|
|
5012
5012
|
return result;
|
|
5013
5013
|
}
|
|
5014
|
-
function validatePath(
|
|
5015
|
-
const pathStr =
|
|
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
|
|
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,
|
|
5032
|
+
function globSearchFiles(files, pattern, path4 = "/") {
|
|
5026
5033
|
let normalizedPath;
|
|
5027
5034
|
try {
|
|
5028
|
-
normalizedPath = validatePath(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
5198
|
+
lsInfo(path4) {
|
|
5192
5199
|
const files = this.getFiles();
|
|
5193
5200
|
const infos = [];
|
|
5194
5201
|
const subdirs = /* @__PURE__ */ new Set();
|
|
5195
|
-
const normalizedPath =
|
|
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,
|
|
5308
|
+
grepRaw(pattern, path4 = "/", glob = null) {
|
|
5302
5309
|
const files = this.getFiles();
|
|
5303
|
-
return grepMatchesFromFiles(files, pattern,
|
|
5310
|
+
return grepMatchesFromFiles(files, pattern, path4, glob);
|
|
5304
5311
|
}
|
|
5305
5312
|
/**
|
|
5306
5313
|
* Structured glob matching returning FileInfo objects.
|
|
5307
5314
|
*/
|
|
5308
|
-
globInfo(pattern,
|
|
5315
|
+
globInfo(pattern, path4 = "/") {
|
|
5309
5316
|
const files = this.getFiles();
|
|
5310
|
-
const result = globSearchFiles(files, pattern,
|
|
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
|
|
5405
|
-
const infos = await resolvedBackend.lsInfo(
|
|
5411
|
+
const path4 = input.path || "/";
|
|
5412
|
+
const infos = await resolvedBackend.lsInfo(path4);
|
|
5406
5413
|
if (infos.length === 0) {
|
|
5407
|
-
return `No files found in ${
|
|
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:
|
|
5551
|
-
const infos = await resolvedBackend.globInfo(pattern,
|
|
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:
|
|
5579
|
-
const result = await resolvedBackend.grepRaw(pattern,
|
|
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(
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
13201
|
-
|
|
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(
|
|
13734
|
+
async lsInfo(path4) {
|
|
13727
13735
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13728
|
-
if (
|
|
13729
|
-
const suffix =
|
|
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 (
|
|
13750
|
+
if (path4 === "/") {
|
|
13743
13751
|
const results = [];
|
|
13744
|
-
const defaultInfos = await this.default.lsInfo(
|
|
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(
|
|
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,
|
|
13792
|
+
async grepRaw(pattern, path4 = "/", glob = null) {
|
|
13785
13793
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13786
|
-
if (
|
|
13787
|
-
const searchPath =
|
|
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,
|
|
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,
|
|
13829
|
+
async globInfo(pattern, path4 = "/") {
|
|
13822
13830
|
const results = [];
|
|
13823
13831
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13824
|
-
if (
|
|
13825
|
-
const searchPath =
|
|
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,
|
|
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(
|
|
13889
|
+
lsInfo(path4) {
|
|
13882
13890
|
const files = this.getFiles();
|
|
13883
13891
|
const infos = [];
|
|
13884
13892
|
const subdirs = /* @__PURE__ */ new Set();
|
|
13885
|
-
const normalizedPath =
|
|
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,
|
|
13968
|
+
grepRaw(pattern, path4 = "/", glob = null) {
|
|
13961
13969
|
const files = this.getFiles();
|
|
13962
|
-
return grepMatchesFromFiles(files, pattern,
|
|
13970
|
+
return grepMatchesFromFiles(files, pattern, path4, glob);
|
|
13963
13971
|
}
|
|
13964
|
-
globInfo(pattern,
|
|
13972
|
+
globInfo(pattern, path4 = "/") {
|
|
13965
13973
|
const files = this.getFiles();
|
|
13966
|
-
const result = globSearchFiles(files, pattern,
|
|
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 (
|
|
18035
|
+
listPath: async (path4, options) => {
|
|
18028
18036
|
const fs3 = this.native.fs();
|
|
18029
|
-
const entries = await fs3.list(
|
|
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 (
|
|
18046
|
+
findFiles: async (path4, glob) => {
|
|
18039
18047
|
const output = await this.native.execWithConfig({
|
|
18040
18048
|
cmd: "sh",
|
|
18041
|
-
args: ["-c", `find "${
|
|
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:
|
|
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}' "${
|
|
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(
|
|
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(
|
|
18259
|
+
await this.client.writeFile(
|
|
18260
|
+
this.name,
|
|
18261
|
+
toSandboxHomePath(file, { absolute: true, homeDir: "/home/daytona" }),
|
|
18262
|
+
content
|
|
18263
|
+
);
|
|
18222
18264
|
},
|
|
18223
|
-
listPath: async (
|
|
18224
|
-
const result = await this.client.listPath(
|
|
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 (
|
|
18232
|
-
return this.client.findFiles(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
18391
|
+
async readFile(sandboxName, path4) {
|
|
18330
18392
|
return this.request("/api/files/read", {
|
|
18331
18393
|
method: "POST",
|
|
18332
|
-
body: { sandboxName, path:
|
|
18394
|
+
body: { sandboxName, path: path4 }
|
|
18333
18395
|
});
|
|
18334
18396
|
}
|
|
18335
|
-
async writeFile(sandboxName,
|
|
18397
|
+
async writeFile(sandboxName, path4, content) {
|
|
18336
18398
|
return this.request("/api/files/write", {
|
|
18337
18399
|
method: "POST",
|
|
18338
|
-
body: { sandboxName, path:
|
|
18400
|
+
body: { sandboxName, path: path4, content }
|
|
18339
18401
|
});
|
|
18340
18402
|
}
|
|
18341
|
-
async listPath(sandboxName,
|
|
18403
|
+
async listPath(sandboxName, path4, recursive) {
|
|
18342
18404
|
return this.request("/api/files/list", {
|
|
18343
18405
|
method: "POST",
|
|
18344
|
-
body: { sandboxName, path:
|
|
18406
|
+
body: { sandboxName, path: path4, recursive }
|
|
18345
18407
|
});
|
|
18346
18408
|
}
|
|
18347
|
-
async findFiles(sandboxName,
|
|
18409
|
+
async findFiles(sandboxName, path4, pattern) {
|
|
18348
18410
|
return this.request("/api/files/find", {
|
|
18349
18411
|
method: "POST",
|
|
18350
|
-
body: { sandboxName, path:
|
|
18412
|
+
body: { sandboxName, path: path4, pattern }
|
|
18351
18413
|
});
|
|
18352
18414
|
}
|
|
18353
|
-
async searchInFile(sandboxName,
|
|
18415
|
+
async searchInFile(sandboxName, path4, query) {
|
|
18354
18416
|
return this.request("/api/files/search", {
|
|
18355
18417
|
method: "POST",
|
|
18356
|
-
body: { sandboxName, path:
|
|
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,
|
|
18427
|
+
async uploadFile(sandboxName, path4, content) {
|
|
18366
18428
|
return this.request("/api/files/upload", {
|
|
18367
18429
|
method: "POST",
|
|
18368
|
-
body: { sandboxName, path:
|
|
18430
|
+
body: { sandboxName, path: path4, contentBase64: content.toString("base64") }
|
|
18369
18431
|
});
|
|
18370
18432
|
}
|
|
18371
|
-
async downloadFile(sandboxName,
|
|
18372
|
-
const query = new URLSearchParams({ sandboxName, path:
|
|
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(
|
|
18384
|
-
const
|
|
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:
|
|
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
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
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.
|
|
18429
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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 (
|
|
18601
|
+
listPath: async (path4, options) => {
|
|
18507
18602
|
const result = await this.client.file.listPath({
|
|
18508
|
-
path:
|
|
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 (
|
|
18523
|
-
const result = await this.client.file.findFiles({ path:
|
|
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 (
|
|
18661
|
-
const entries = await this.native.files.list(
|
|
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 (
|
|
18765
|
+
findFiles: async (path4, glob) => {
|
|
18671
18766
|
const result = await this.native.commands.run(
|
|
18672
|
-
`find "${
|
|
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:
|
|
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}' "${
|
|
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(
|
|
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"),
|
|
18916
|
+
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toSandboxHomePath(file));
|
|
18822
18917
|
},
|
|
18823
|
-
listPath: async (
|
|
18824
|
-
const entries = await this.native.fs.listFiles(
|
|
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 ? `${
|
|
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 (
|
|
18845
|
-
const result = await this.native.fs.searchFiles(
|
|
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(
|
|
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:
|
|
18860
|
-
const relPath =
|
|
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,
|
|
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(
|
|
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
|
}
|