@axiom-lattice/core 2.1.84 → 2.1.86
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 +80 -4
- package/dist/index.d.ts +80 -4
- package/dist/index.js +478 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -189
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -2468,7 +2468,7 @@ var InMemoryBindingStore = class {
|
|
|
2468
2468
|
* @returns Array of matching {@link Binding} objects
|
|
2469
2469
|
*/
|
|
2470
2470
|
async list(params) {
|
|
2471
|
-
|
|
2471
|
+
const results = Array.from(this.bindings.values()).filter((b) => {
|
|
2472
2472
|
if (b.tenantId !== params.tenantId) return false;
|
|
2473
2473
|
if (params.channel && b.channel !== params.channel) return false;
|
|
2474
2474
|
if (params.agentId && b.agentId !== params.agentId) return false;
|
|
@@ -5717,9 +5717,9 @@ var VolumeFilesystem = class {
|
|
|
5717
5717
|
this.client = client;
|
|
5718
5718
|
this.mountPrefix = mountPrefix;
|
|
5719
5719
|
}
|
|
5720
|
-
async lsInfo(
|
|
5721
|
-
console.log(`[VolumeFilesystem.lsInfo] path=${
|
|
5722
|
-
const entries = await this.client.list(
|
|
5720
|
+
async lsInfo(path5) {
|
|
5721
|
+
console.log(`[VolumeFilesystem.lsInfo] path=${path5} mountPrefix=${this.mountPrefix}`);
|
|
5722
|
+
const entries = await this.client.list(path5);
|
|
5723
5723
|
console.log(`[VolumeFilesystem.lsInfo] got ${entries.length} entries`);
|
|
5724
5724
|
const prefix = this.mountPrefix.endsWith("/") ? this.mountPrefix : this.mountPrefix + "/";
|
|
5725
5725
|
return entries.map((entry) => ({
|
|
@@ -8032,8 +8032,8 @@ function truncateIfTooLong(result) {
|
|
|
8032
8032
|
}
|
|
8033
8033
|
return result;
|
|
8034
8034
|
}
|
|
8035
|
-
function validatePath(
|
|
8036
|
-
const pathStr =
|
|
8035
|
+
function validatePath(path5) {
|
|
8036
|
+
const pathStr = path5 || "/";
|
|
8037
8037
|
if (!pathStr || pathStr.trim() === "") {
|
|
8038
8038
|
throw new Error("Path cannot be empty");
|
|
8039
8039
|
}
|
|
@@ -8050,10 +8050,10 @@ function validatePath(path3) {
|
|
|
8050
8050
|
}
|
|
8051
8051
|
return normalized;
|
|
8052
8052
|
}
|
|
8053
|
-
function globSearchFiles(files, pattern,
|
|
8053
|
+
function globSearchFiles(files, pattern, path5 = "/") {
|
|
8054
8054
|
let normalizedPath;
|
|
8055
8055
|
try {
|
|
8056
|
-
normalizedPath = validatePath(
|
|
8056
|
+
normalizedPath = validatePath(path5);
|
|
8057
8057
|
} catch {
|
|
8058
8058
|
return "No files found";
|
|
8059
8059
|
}
|
|
@@ -8105,7 +8105,7 @@ function formatGrepResults(results, outputMode) {
|
|
|
8105
8105
|
}
|
|
8106
8106
|
return lines.join("\n");
|
|
8107
8107
|
}
|
|
8108
|
-
function grepSearchFiles(files, pattern,
|
|
8108
|
+
function grepSearchFiles(files, pattern, path5 = null, glob = null, outputMode = "files_with_matches") {
|
|
8109
8109
|
let regex;
|
|
8110
8110
|
try {
|
|
8111
8111
|
regex = new RegExp(pattern);
|
|
@@ -8114,7 +8114,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
|
|
|
8114
8114
|
}
|
|
8115
8115
|
let normalizedPath;
|
|
8116
8116
|
try {
|
|
8117
|
-
normalizedPath = validatePath(
|
|
8117
|
+
normalizedPath = validatePath(path5);
|
|
8118
8118
|
} catch {
|
|
8119
8119
|
return "No matches found";
|
|
8120
8120
|
}
|
|
@@ -8146,7 +8146,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
|
|
|
8146
8146
|
}
|
|
8147
8147
|
return formatGrepResults(results, outputMode);
|
|
8148
8148
|
}
|
|
8149
|
-
function grepMatchesFromFiles(files, pattern,
|
|
8149
|
+
function grepMatchesFromFiles(files, pattern, path5 = null, glob = null) {
|
|
8150
8150
|
let regex;
|
|
8151
8151
|
try {
|
|
8152
8152
|
regex = new RegExp(pattern);
|
|
@@ -8155,7 +8155,7 @@ function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
|
|
|
8155
8155
|
}
|
|
8156
8156
|
let normalizedPath;
|
|
8157
8157
|
try {
|
|
8158
|
-
normalizedPath = validatePath(
|
|
8158
|
+
normalizedPath = validatePath(path5);
|
|
8159
8159
|
} catch {
|
|
8160
8160
|
return [];
|
|
8161
8161
|
}
|
|
@@ -8216,11 +8216,11 @@ var StateBackend = class {
|
|
|
8216
8216
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
8217
8217
|
* Directories have a trailing / in their path and is_dir=true.
|
|
8218
8218
|
*/
|
|
8219
|
-
lsInfo(
|
|
8219
|
+
lsInfo(path5) {
|
|
8220
8220
|
const files = this.getFiles();
|
|
8221
8221
|
const infos = [];
|
|
8222
8222
|
const subdirs = /* @__PURE__ */ new Set();
|
|
8223
|
-
const normalizedPath =
|
|
8223
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
8224
8224
|
for (const [k, fd] of Object.entries(files)) {
|
|
8225
8225
|
if (!k.startsWith(normalizedPath)) {
|
|
8226
8226
|
continue;
|
|
@@ -8326,16 +8326,16 @@ var StateBackend = class {
|
|
|
8326
8326
|
/**
|
|
8327
8327
|
* Structured search results or error string for invalid input.
|
|
8328
8328
|
*/
|
|
8329
|
-
grepRaw(pattern,
|
|
8329
|
+
grepRaw(pattern, path5 = "/", glob = null) {
|
|
8330
8330
|
const files = this.getFiles();
|
|
8331
|
-
return grepMatchesFromFiles(files, pattern,
|
|
8331
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
8332
8332
|
}
|
|
8333
8333
|
/**
|
|
8334
8334
|
* Structured glob matching returning FileInfo objects.
|
|
8335
8335
|
*/
|
|
8336
|
-
globInfo(pattern,
|
|
8336
|
+
globInfo(pattern, path5 = "/") {
|
|
8337
8337
|
const files = this.getFiles();
|
|
8338
|
-
const result = globSearchFiles(files, pattern,
|
|
8338
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
8339
8339
|
if (result === "No files found") {
|
|
8340
8340
|
return [];
|
|
8341
8341
|
}
|
|
@@ -8429,10 +8429,10 @@ function createLsTool(backend, options) {
|
|
|
8429
8429
|
...runConfig
|
|
8430
8430
|
};
|
|
8431
8431
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
8432
|
-
const
|
|
8433
|
-
const infos = await resolvedBackend.lsInfo(
|
|
8432
|
+
const path5 = input.path || "/";
|
|
8433
|
+
const infos = await resolvedBackend.lsInfo(path5);
|
|
8434
8434
|
if (infos.length === 0) {
|
|
8435
|
-
return `No files found in ${
|
|
8435
|
+
return `No files found in ${path5}`;
|
|
8436
8436
|
}
|
|
8437
8437
|
const lines = [];
|
|
8438
8438
|
for (const info of infos) {
|
|
@@ -8575,8 +8575,8 @@ function createGlobTool(backend, options) {
|
|
|
8575
8575
|
...runConfig
|
|
8576
8576
|
};
|
|
8577
8577
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
8578
|
-
const { pattern, path:
|
|
8579
|
-
const infos = await resolvedBackend.globInfo(pattern,
|
|
8578
|
+
const { pattern, path: path5 = "/" } = input;
|
|
8579
|
+
const infos = await resolvedBackend.globInfo(pattern, path5);
|
|
8580
8580
|
if (infos.length === 0) {
|
|
8581
8581
|
return `No files found matching pattern '${pattern}'`;
|
|
8582
8582
|
}
|
|
@@ -8603,8 +8603,8 @@ function createGrepTool(backend, options) {
|
|
|
8603
8603
|
...runConfig
|
|
8604
8604
|
};
|
|
8605
8605
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
8606
|
-
const { pattern, path:
|
|
8607
|
-
const result = await resolvedBackend.grepRaw(pattern,
|
|
8606
|
+
const { pattern, path: path5 = "/", glob = null } = input;
|
|
8607
|
+
const result = await resolvedBackend.grepRaw(pattern, path5, glob);
|
|
8608
8608
|
if (typeof result === "string") {
|
|
8609
8609
|
return result;
|
|
8610
8610
|
}
|
|
@@ -12721,8 +12721,7 @@ var Agent = class {
|
|
|
12721
12721
|
if (signal?.aborted) {
|
|
12722
12722
|
throw new Error("Agent execution was aborted");
|
|
12723
12723
|
}
|
|
12724
|
-
|
|
12725
|
-
result = await runnable_agent.invoke(
|
|
12724
|
+
const result = await runnable_agent.invoke(
|
|
12726
12725
|
inputMessage.command ? new Command2(inputMessage.command) : { ...rest, messages, "x-tenant-id": this.tenant_id },
|
|
12727
12726
|
{
|
|
12728
12727
|
context: { runConfig },
|
|
@@ -13081,7 +13080,7 @@ var Agent = class {
|
|
|
13081
13080
|
includeTypes: ["ai", "human", "tool"]
|
|
13082
13081
|
//["human", "ai", "tool"],
|
|
13083
13082
|
});
|
|
13084
|
-
|
|
13083
|
+
const messagesArray = filteredMessages.map((message) => ({
|
|
13085
13084
|
id: message.id,
|
|
13086
13085
|
role: message.getType(),
|
|
13087
13086
|
content: message.content,
|
|
@@ -14178,12 +14177,12 @@ var AgentManager = class _AgentManager {
|
|
|
14178
14177
|
return _AgentManager.instance;
|
|
14179
14178
|
}
|
|
14180
14179
|
callAgentInQueue(queue, return_agent_state) {
|
|
14181
|
-
return new Promise((
|
|
14180
|
+
return new Promise((resolve4, reject) => {
|
|
14182
14181
|
const callback_event = `${queue.assistant_id}::${queue.thread_id}`;
|
|
14183
14182
|
if (return_agent_state) {
|
|
14184
14183
|
event_bus_default.subscribeOnce(callback_event, (data) => {
|
|
14185
14184
|
if (data.success) {
|
|
14186
|
-
|
|
14185
|
+
resolve4(data.state);
|
|
14187
14186
|
} else {
|
|
14188
14187
|
reject(data.error);
|
|
14189
14188
|
}
|
|
@@ -14198,7 +14197,7 @@ var AgentManager = class _AgentManager {
|
|
|
14198
14197
|
},
|
|
14199
14198
|
true
|
|
14200
14199
|
);
|
|
14201
|
-
!return_agent_state &&
|
|
14200
|
+
!return_agent_state && resolve4({ callback_event_id: callback_event, success: true });
|
|
14202
14201
|
} catch (error) {
|
|
14203
14202
|
!return_agent_state && reject({
|
|
14204
14203
|
callback_event_id: callback_event,
|
|
@@ -15097,13 +15096,13 @@ var StoreBackend = class {
|
|
|
15097
15096
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
15098
15097
|
* Directories have a trailing / in their path and is_dir=true.
|
|
15099
15098
|
*/
|
|
15100
|
-
async lsInfo(
|
|
15099
|
+
async lsInfo(path5) {
|
|
15101
15100
|
const store = this.getStore();
|
|
15102
15101
|
const namespace = this.getNamespace();
|
|
15103
15102
|
const items = await this.searchStorePaginated(store, namespace);
|
|
15104
15103
|
const infos = [];
|
|
15105
15104
|
const subdirs = /* @__PURE__ */ new Set();
|
|
15106
|
-
const normalizedPath =
|
|
15105
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
15107
15106
|
for (const item of items) {
|
|
15108
15107
|
const itemKey = String(item.key);
|
|
15109
15108
|
if (!itemKey.startsWith(normalizedPath)) {
|
|
@@ -15221,7 +15220,7 @@ var StoreBackend = class {
|
|
|
15221
15220
|
/**
|
|
15222
15221
|
* Structured search results or error string for invalid input.
|
|
15223
15222
|
*/
|
|
15224
|
-
async grepRaw(pattern,
|
|
15223
|
+
async grepRaw(pattern, path5 = "/", glob = null) {
|
|
15225
15224
|
const store = this.getStore();
|
|
15226
15225
|
const namespace = this.getNamespace();
|
|
15227
15226
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -15233,12 +15232,12 @@ var StoreBackend = class {
|
|
|
15233
15232
|
continue;
|
|
15234
15233
|
}
|
|
15235
15234
|
}
|
|
15236
|
-
return grepMatchesFromFiles(files, pattern,
|
|
15235
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
15237
15236
|
}
|
|
15238
15237
|
/**
|
|
15239
15238
|
* Structured glob matching returning FileInfo objects.
|
|
15240
15239
|
*/
|
|
15241
|
-
async globInfo(pattern,
|
|
15240
|
+
async globInfo(pattern, path5 = "/") {
|
|
15242
15241
|
const store = this.getStore();
|
|
15243
15242
|
const namespace = this.getNamespace();
|
|
15244
15243
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -15250,7 +15249,7 @@ var StoreBackend = class {
|
|
|
15250
15249
|
continue;
|
|
15251
15250
|
}
|
|
15252
15251
|
}
|
|
15253
|
-
const result = globSearchFiles(files, pattern,
|
|
15252
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
15254
15253
|
if (result === "No files found") {
|
|
15255
15254
|
return [];
|
|
15256
15255
|
}
|
|
@@ -15335,8 +15334,8 @@ var FilesystemBackend = class {
|
|
|
15335
15334
|
async lsInfo(dirPath) {
|
|
15336
15335
|
try {
|
|
15337
15336
|
const resolvedPath = this.resolvePath(dirPath);
|
|
15338
|
-
const
|
|
15339
|
-
if (!
|
|
15337
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
15338
|
+
if (!stat4.isDirectory()) {
|
|
15340
15339
|
return [];
|
|
15341
15340
|
}
|
|
15342
15341
|
const entries = await fs2.readdir(resolvedPath, { withFileTypes: true });
|
|
@@ -15415,8 +15414,8 @@ var FilesystemBackend = class {
|
|
|
15415
15414
|
const resolvedPath = this.resolvePath(filePath);
|
|
15416
15415
|
let content;
|
|
15417
15416
|
if (SUPPORTS_NOFOLLOW) {
|
|
15418
|
-
const
|
|
15419
|
-
if (!
|
|
15417
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
15418
|
+
if (!stat4.isFile()) {
|
|
15420
15419
|
return `Error: File '${filePath}' not found`;
|
|
15421
15420
|
}
|
|
15422
15421
|
const fd = await fs2.open(
|
|
@@ -15429,11 +15428,11 @@ var FilesystemBackend = class {
|
|
|
15429
15428
|
await fd.close();
|
|
15430
15429
|
}
|
|
15431
15430
|
} else {
|
|
15432
|
-
const
|
|
15433
|
-
if (
|
|
15431
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
15432
|
+
if (stat4.isSymbolicLink()) {
|
|
15434
15433
|
return `Error: Symlinks are not allowed: ${filePath}`;
|
|
15435
15434
|
}
|
|
15436
|
-
if (!
|
|
15435
|
+
if (!stat4.isFile()) {
|
|
15437
15436
|
return `Error: File '${filePath}' not found`;
|
|
15438
15437
|
}
|
|
15439
15438
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
@@ -15463,10 +15462,10 @@ var FilesystemBackend = class {
|
|
|
15463
15462
|
async readRaw(filePath) {
|
|
15464
15463
|
const resolvedPath = this.resolvePath(filePath);
|
|
15465
15464
|
let content;
|
|
15466
|
-
let
|
|
15465
|
+
let stat4;
|
|
15467
15466
|
if (SUPPORTS_NOFOLLOW) {
|
|
15468
|
-
|
|
15469
|
-
if (!
|
|
15467
|
+
stat4 = await fs2.stat(resolvedPath);
|
|
15468
|
+
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
15470
15469
|
const fd = await fs2.open(
|
|
15471
15470
|
resolvedPath,
|
|
15472
15471
|
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
@@ -15477,17 +15476,17 @@ var FilesystemBackend = class {
|
|
|
15477
15476
|
await fd.close();
|
|
15478
15477
|
}
|
|
15479
15478
|
} else {
|
|
15480
|
-
|
|
15481
|
-
if (
|
|
15479
|
+
stat4 = await fs2.lstat(resolvedPath);
|
|
15480
|
+
if (stat4.isSymbolicLink()) {
|
|
15482
15481
|
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
15483
15482
|
}
|
|
15484
|
-
if (!
|
|
15483
|
+
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
15485
15484
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
15486
15485
|
}
|
|
15487
15486
|
return {
|
|
15488
15487
|
content: content.split("\n"),
|
|
15489
|
-
created_at:
|
|
15490
|
-
modified_at:
|
|
15488
|
+
created_at: stat4.ctime.toISOString(),
|
|
15489
|
+
modified_at: stat4.mtime.toISOString()
|
|
15491
15490
|
};
|
|
15492
15491
|
}
|
|
15493
15492
|
/**
|
|
@@ -15498,8 +15497,8 @@ var FilesystemBackend = class {
|
|
|
15498
15497
|
try {
|
|
15499
15498
|
const resolvedPath = this.resolvePath(filePath);
|
|
15500
15499
|
try {
|
|
15501
|
-
const
|
|
15502
|
-
if (
|
|
15500
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
15501
|
+
if (stat4.isSymbolicLink()) {
|
|
15503
15502
|
return {
|
|
15504
15503
|
error: `Cannot write to ${filePath} because it is a symlink. Symlinks are not allowed.`
|
|
15505
15504
|
};
|
|
@@ -15535,8 +15534,8 @@ var FilesystemBackend = class {
|
|
|
15535
15534
|
const resolvedPath = this.resolvePath(filePath);
|
|
15536
15535
|
let content;
|
|
15537
15536
|
if (SUPPORTS_NOFOLLOW) {
|
|
15538
|
-
const
|
|
15539
|
-
if (!
|
|
15537
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
15538
|
+
if (!stat4.isFile()) {
|
|
15540
15539
|
return { error: `Error: File '${filePath}' not found` };
|
|
15541
15540
|
}
|
|
15542
15541
|
const fd = await fs2.open(
|
|
@@ -15549,11 +15548,11 @@ var FilesystemBackend = class {
|
|
|
15549
15548
|
await fd.close();
|
|
15550
15549
|
}
|
|
15551
15550
|
} else {
|
|
15552
|
-
const
|
|
15553
|
-
if (
|
|
15551
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
15552
|
+
if (stat4.isSymbolicLink()) {
|
|
15554
15553
|
return { error: `Error: Symlinks are not allowed: ${filePath}` };
|
|
15555
15554
|
}
|
|
15556
|
-
if (!
|
|
15555
|
+
if (!stat4.isFile()) {
|
|
15557
15556
|
return { error: `Error: File '${filePath}' not found` };
|
|
15558
15557
|
}
|
|
15559
15558
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
@@ -15621,7 +15620,7 @@ var FilesystemBackend = class {
|
|
|
15621
15620
|
* Returns null if ripgrep is not available or fails.
|
|
15622
15621
|
*/
|
|
15623
15622
|
async ripgrepSearch(pattern, baseFull, includeGlob) {
|
|
15624
|
-
return new Promise((
|
|
15623
|
+
return new Promise((resolve4) => {
|
|
15625
15624
|
const args = ["--json"];
|
|
15626
15625
|
if (includeGlob) {
|
|
15627
15626
|
args.push("--glob", includeGlob);
|
|
@@ -15635,7 +15634,7 @@ var FilesystemBackend = class {
|
|
|
15635
15634
|
});
|
|
15636
15635
|
proc.on("close", (code) => {
|
|
15637
15636
|
if (code !== 0 && code !== 1) {
|
|
15638
|
-
|
|
15637
|
+
resolve4(null);
|
|
15639
15638
|
return;
|
|
15640
15639
|
}
|
|
15641
15640
|
for (const line of output.split("\n")) {
|
|
@@ -15671,10 +15670,10 @@ var FilesystemBackend = class {
|
|
|
15671
15670
|
continue;
|
|
15672
15671
|
}
|
|
15673
15672
|
}
|
|
15674
|
-
|
|
15673
|
+
resolve4(results);
|
|
15675
15674
|
});
|
|
15676
15675
|
proc.on("error", () => {
|
|
15677
|
-
|
|
15676
|
+
resolve4(null);
|
|
15678
15677
|
});
|
|
15679
15678
|
});
|
|
15680
15679
|
}
|
|
@@ -15689,8 +15688,8 @@ var FilesystemBackend = class {
|
|
|
15689
15688
|
return {};
|
|
15690
15689
|
}
|
|
15691
15690
|
const results = {};
|
|
15692
|
-
const
|
|
15693
|
-
const root =
|
|
15691
|
+
const stat4 = await fs2.stat(baseFull);
|
|
15692
|
+
const root = stat4.isDirectory() ? baseFull : path2.dirname(baseFull);
|
|
15694
15693
|
const files = await fg("**/*", {
|
|
15695
15694
|
cwd: root,
|
|
15696
15695
|
absolute: true,
|
|
@@ -15702,8 +15701,8 @@ var FilesystemBackend = class {
|
|
|
15702
15701
|
if (includeGlob && !micromatch2.isMatch(path2.basename(fp), includeGlob)) {
|
|
15703
15702
|
continue;
|
|
15704
15703
|
}
|
|
15705
|
-
const
|
|
15706
|
-
if (
|
|
15704
|
+
const stat5 = await fs2.stat(fp);
|
|
15705
|
+
if (stat5.size > this.maxFileSizeBytes) {
|
|
15707
15706
|
continue;
|
|
15708
15707
|
}
|
|
15709
15708
|
const content = await fs2.readFile(fp, "utf-8");
|
|
@@ -15745,8 +15744,8 @@ var FilesystemBackend = class {
|
|
|
15745
15744
|
}
|
|
15746
15745
|
const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
|
|
15747
15746
|
try {
|
|
15748
|
-
const
|
|
15749
|
-
if (!
|
|
15747
|
+
const stat4 = await fs2.stat(resolvedSearchPath);
|
|
15748
|
+
if (!stat4.isDirectory()) {
|
|
15750
15749
|
return [];
|
|
15751
15750
|
}
|
|
15752
15751
|
} catch {
|
|
@@ -15762,15 +15761,15 @@ var FilesystemBackend = class {
|
|
|
15762
15761
|
});
|
|
15763
15762
|
for (const matchedPath of matches) {
|
|
15764
15763
|
try {
|
|
15765
|
-
const
|
|
15766
|
-
if (!
|
|
15764
|
+
const stat4 = await fs2.stat(matchedPath);
|
|
15765
|
+
if (!stat4.isFile()) continue;
|
|
15767
15766
|
const normalizedPath = matchedPath.split("/").join(path2.sep);
|
|
15768
15767
|
if (!this.virtualMode) {
|
|
15769
15768
|
results.push({
|
|
15770
15769
|
path: normalizedPath,
|
|
15771
15770
|
is_dir: false,
|
|
15772
|
-
size:
|
|
15773
|
-
modified_at:
|
|
15771
|
+
size: stat4.size,
|
|
15772
|
+
modified_at: stat4.mtime.toISOString()
|
|
15774
15773
|
});
|
|
15775
15774
|
} else {
|
|
15776
15775
|
const cwdStr = this.cwd.endsWith(path2.sep) ? this.cwd : this.cwd + path2.sep;
|
|
@@ -15787,8 +15786,8 @@ var FilesystemBackend = class {
|
|
|
15787
15786
|
results.push({
|
|
15788
15787
|
path: virt,
|
|
15789
15788
|
is_dir: false,
|
|
15790
|
-
size:
|
|
15791
|
-
modified_at:
|
|
15789
|
+
size: stat4.size,
|
|
15790
|
+
modified_at: stat4.mtime.toISOString()
|
|
15792
15791
|
});
|
|
15793
15792
|
}
|
|
15794
15793
|
} catch {
|
|
@@ -15835,10 +15834,10 @@ var CompositeBackend = class {
|
|
|
15835
15834
|
* @returns List of FileInfo objects with route prefixes added, for files and directories
|
|
15836
15835
|
* directly in the directory. Directories have a trailing / in their path and is_dir=true.
|
|
15837
15836
|
*/
|
|
15838
|
-
async lsInfo(
|
|
15837
|
+
async lsInfo(path5) {
|
|
15839
15838
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
15840
|
-
if (
|
|
15841
|
-
const suffix =
|
|
15839
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
15840
|
+
const suffix = path5.substring(routePrefix.length);
|
|
15842
15841
|
const searchPath = suffix ? "/" + suffix : "/";
|
|
15843
15842
|
const infos = await backend.lsInfo(searchPath);
|
|
15844
15843
|
const prefixed = [];
|
|
@@ -15851,9 +15850,9 @@ var CompositeBackend = class {
|
|
|
15851
15850
|
return prefixed;
|
|
15852
15851
|
}
|
|
15853
15852
|
}
|
|
15854
|
-
if (
|
|
15853
|
+
if (path5 === "/") {
|
|
15855
15854
|
const results = [];
|
|
15856
|
-
const defaultInfos = await this.default.lsInfo(
|
|
15855
|
+
const defaultInfos = await this.default.lsInfo(path5);
|
|
15857
15856
|
results.push(...defaultInfos);
|
|
15858
15857
|
for (const [routePrefix] of this.sortedRoutes) {
|
|
15859
15858
|
results.push({
|
|
@@ -15866,7 +15865,7 @@ var CompositeBackend = class {
|
|
|
15866
15865
|
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
15867
15866
|
return results;
|
|
15868
15867
|
}
|
|
15869
|
-
return await this.default.lsInfo(
|
|
15868
|
+
return await this.default.lsInfo(path5);
|
|
15870
15869
|
}
|
|
15871
15870
|
/**
|
|
15872
15871
|
* Read file content, routing to appropriate backend.
|
|
@@ -15893,10 +15892,10 @@ var CompositeBackend = class {
|
|
|
15893
15892
|
/**
|
|
15894
15893
|
* Structured search results or error string for invalid input.
|
|
15895
15894
|
*/
|
|
15896
|
-
async grepRaw(pattern,
|
|
15895
|
+
async grepRaw(pattern, path5 = "/", glob = null) {
|
|
15897
15896
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
15898
|
-
if (
|
|
15899
|
-
const searchPath =
|
|
15897
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
15898
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
15900
15899
|
const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
|
|
15901
15900
|
if (typeof raw === "string") {
|
|
15902
15901
|
return raw;
|
|
@@ -15908,7 +15907,7 @@ var CompositeBackend = class {
|
|
|
15908
15907
|
}
|
|
15909
15908
|
}
|
|
15910
15909
|
const allMatches = [];
|
|
15911
|
-
const rawDefault = await this.default.grepRaw(pattern,
|
|
15910
|
+
const rawDefault = await this.default.grepRaw(pattern, path5, glob);
|
|
15912
15911
|
if (typeof rawDefault === "string") {
|
|
15913
15912
|
return rawDefault;
|
|
15914
15913
|
}
|
|
@@ -15930,11 +15929,11 @@ var CompositeBackend = class {
|
|
|
15930
15929
|
/**
|
|
15931
15930
|
* Structured glob matching returning FileInfo objects.
|
|
15932
15931
|
*/
|
|
15933
|
-
async globInfo(pattern,
|
|
15932
|
+
async globInfo(pattern, path5 = "/") {
|
|
15934
15933
|
const results = [];
|
|
15935
15934
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
15936
|
-
if (
|
|
15937
|
-
const searchPath =
|
|
15935
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
15936
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
15938
15937
|
const infos = await backend.globInfo(pattern, searchPath || "/");
|
|
15939
15938
|
return infos.map((fi) => ({
|
|
15940
15939
|
...fi,
|
|
@@ -15942,7 +15941,7 @@ var CompositeBackend = class {
|
|
|
15942
15941
|
}));
|
|
15943
15942
|
}
|
|
15944
15943
|
}
|
|
15945
|
-
const defaultInfos = await this.default.globInfo(pattern,
|
|
15944
|
+
const defaultInfos = await this.default.globInfo(pattern, path5);
|
|
15946
15945
|
results.push(...defaultInfos);
|
|
15947
15946
|
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
15948
15947
|
const infos = await backend.globInfo(pattern, "/");
|
|
@@ -15990,11 +15989,11 @@ var MemoryBackend = class {
|
|
|
15990
15989
|
getFiles() {
|
|
15991
15990
|
return Object.fromEntries(this.files);
|
|
15992
15991
|
}
|
|
15993
|
-
lsInfo(
|
|
15992
|
+
lsInfo(path5) {
|
|
15994
15993
|
const files = this.getFiles();
|
|
15995
15994
|
const infos = [];
|
|
15996
15995
|
const subdirs = /* @__PURE__ */ new Set();
|
|
15997
|
-
const normalizedPath =
|
|
15996
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
15998
15997
|
for (const [k, fd] of Object.entries(files)) {
|
|
15999
15998
|
if (!k.startsWith(normalizedPath)) {
|
|
16000
15999
|
continue;
|
|
@@ -16069,13 +16068,13 @@ var MemoryBackend = class {
|
|
|
16069
16068
|
this.files.set(filePath, newFileData);
|
|
16070
16069
|
return { path: filePath, filesUpdate: null, occurrences };
|
|
16071
16070
|
}
|
|
16072
|
-
grepRaw(pattern,
|
|
16071
|
+
grepRaw(pattern, path5 = "/", glob = null) {
|
|
16073
16072
|
const files = this.getFiles();
|
|
16074
|
-
return grepMatchesFromFiles(files, pattern,
|
|
16073
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
16075
16074
|
}
|
|
16076
|
-
globInfo(pattern,
|
|
16075
|
+
globInfo(pattern, path5 = "/") {
|
|
16077
16076
|
const files = this.getFiles();
|
|
16078
|
-
const result = globSearchFiles(files, pattern,
|
|
16077
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
16079
16078
|
if (result === "No files found") {
|
|
16080
16079
|
return [];
|
|
16081
16080
|
}
|
|
@@ -17118,16 +17117,16 @@ function createTeammateTools(options) {
|
|
|
17118
17117
|
update: { team_mailbox: relevantMsgs2, messages: [toolMessage2] }
|
|
17119
17118
|
});
|
|
17120
17119
|
}
|
|
17121
|
-
const messagePromise = new Promise((
|
|
17120
|
+
const messagePromise = new Promise((resolve4) => {
|
|
17122
17121
|
const handler = async (msg) => {
|
|
17123
17122
|
mailboxStore.offMessage(teamId, agentId, handler);
|
|
17124
17123
|
const allMsgs = await mailboxStore.getUnreadMessages(teamId, agentId);
|
|
17125
|
-
|
|
17124
|
+
resolve4(allMsgs);
|
|
17126
17125
|
};
|
|
17127
17126
|
mailboxStore.onMessage(teamId, agentId, handler);
|
|
17128
17127
|
});
|
|
17129
|
-
const timeoutPromise = new Promise((
|
|
17130
|
-
setTimeout(() =>
|
|
17128
|
+
const timeoutPromise = new Promise((resolve4) => {
|
|
17129
|
+
setTimeout(() => resolve4([]), READ_MESSAGES_TIMEOUT_MS2);
|
|
17131
17130
|
});
|
|
17132
17131
|
msgs = await Promise.race([messagePromise, timeoutPromise]);
|
|
17133
17132
|
mailboxStore.offMessage(teamId, agentId, () => {
|
|
@@ -17859,19 +17858,19 @@ Task Status Values:
|
|
|
17859
17858
|
update: { team_mailbox: allTeamMessages2, messages: [toolMessage2] }
|
|
17860
17859
|
});
|
|
17861
17860
|
}
|
|
17862
|
-
const messagePromise = new Promise((
|
|
17861
|
+
const messagePromise = new Promise((resolve4) => {
|
|
17863
17862
|
const handler = async (msg) => {
|
|
17864
17863
|
mailboxStore.offMessage(teamId, TEAM_LEAD_AGENT_ID, handler);
|
|
17865
17864
|
const allMsgs = await mailboxStore.getUnreadMessages(
|
|
17866
17865
|
teamId,
|
|
17867
17866
|
TEAM_LEAD_AGENT_ID
|
|
17868
17867
|
);
|
|
17869
|
-
|
|
17868
|
+
resolve4(allMsgs);
|
|
17870
17869
|
};
|
|
17871
17870
|
mailboxStore.onMessage(teamId, TEAM_LEAD_AGENT_ID, handler);
|
|
17872
17871
|
});
|
|
17873
|
-
const timeoutPromise = new Promise((
|
|
17874
|
-
setTimeout(() =>
|
|
17872
|
+
const timeoutPromise = new Promise((resolve4) => {
|
|
17873
|
+
setTimeout(() => resolve4([]), READ_MESSAGES_TIMEOUT_MS);
|
|
17875
17874
|
});
|
|
17876
17875
|
msgs = await Promise.race([messagePromise, timeoutPromise]);
|
|
17877
17876
|
mailboxStore.offMessage(
|
|
@@ -22344,10 +22343,10 @@ var MicrosandboxRemoteInstance = class {
|
|
|
22344
22343
|
content
|
|
22345
22344
|
);
|
|
22346
22345
|
},
|
|
22347
|
-
listPath: async (
|
|
22346
|
+
listPath: async (path5, options) => {
|
|
22348
22347
|
const result = await this.client.listPath(
|
|
22349
22348
|
this.name,
|
|
22350
|
-
normalizeExternalSandboxPath(
|
|
22349
|
+
normalizeExternalSandboxPath(path5),
|
|
22351
22350
|
options?.recursive
|
|
22352
22351
|
);
|
|
22353
22352
|
const files = result.entries.map((entry) => ({
|
|
@@ -22356,10 +22355,10 @@ var MicrosandboxRemoteInstance = class {
|
|
|
22356
22355
|
}));
|
|
22357
22356
|
return { files };
|
|
22358
22357
|
},
|
|
22359
|
-
findFiles: async (
|
|
22358
|
+
findFiles: async (path5, glob) => {
|
|
22360
22359
|
const result = await this.client.findFiles(
|
|
22361
22360
|
this.name,
|
|
22362
|
-
normalizeExternalSandboxPath(
|
|
22361
|
+
normalizeExternalSandboxPath(path5),
|
|
22363
22362
|
glob
|
|
22364
22363
|
);
|
|
22365
22364
|
return {
|
|
@@ -22401,15 +22400,15 @@ var MicrosandboxRemoteInstance = class {
|
|
|
22401
22400
|
}
|
|
22402
22401
|
return Buffer.from(result.content ?? "");
|
|
22403
22402
|
},
|
|
22404
|
-
deletePath: async (
|
|
22405
|
-
const resolved = normalizeExternalSandboxPath(
|
|
22403
|
+
deletePath: async (path5) => {
|
|
22404
|
+
const resolved = normalizeExternalSandboxPath(path5);
|
|
22406
22405
|
await this.client.execCommand({
|
|
22407
22406
|
sandboxName: this.name,
|
|
22408
22407
|
command: `rm -rf "${resolved}"`
|
|
22409
22408
|
});
|
|
22410
22409
|
},
|
|
22411
|
-
createDirectory: async (
|
|
22412
|
-
const resolved = normalizeExternalSandboxPath(
|
|
22410
|
+
createDirectory: async (path5) => {
|
|
22411
|
+
const resolved = normalizeExternalSandboxPath(path5);
|
|
22413
22412
|
await this.client.execCommand({
|
|
22414
22413
|
sandboxName: this.name,
|
|
22415
22414
|
command: `mkdir -p "${resolved}"`
|
|
@@ -22457,13 +22456,18 @@ var MicrosandboxServiceClient = class {
|
|
|
22457
22456
|
this.apiKey = config.apiKey;
|
|
22458
22457
|
}
|
|
22459
22458
|
async ensureSandbox(name, input) {
|
|
22459
|
+
const tStart = Date.now();
|
|
22460
22460
|
console.log(
|
|
22461
|
-
`[MicrosandboxClient] ensureSandbox name=${name} image=${input.image ?? "not set"} envKeys=${Object.keys(input.env ?? {}).join(",") || "none"}`
|
|
22461
|
+
`[MicrosandboxClient] ensureSandbox START name=${name} image=${input.image ?? "not set"} envKeys=${Object.keys(input.env ?? {}).join(",") || "none"}`
|
|
22462
22462
|
);
|
|
22463
|
-
|
|
22463
|
+
const result = await this.request(`/api/sandboxes/${encodeURIComponent(name)}`, {
|
|
22464
22464
|
method: "PUT",
|
|
22465
22465
|
body: input
|
|
22466
22466
|
});
|
|
22467
|
+
console.log(
|
|
22468
|
+
`[MicrosandboxClient] ensureSandbox DONE name=${name} status=${result.status} elapsed=${Date.now() - tStart}ms`
|
|
22469
|
+
);
|
|
22470
|
+
return result;
|
|
22467
22471
|
}
|
|
22468
22472
|
async startSandbox(name) {
|
|
22469
22473
|
return this.request(`/api/sandboxes/${encodeURIComponent(name)}/start`, {
|
|
@@ -22490,34 +22494,34 @@ var MicrosandboxServiceClient = class {
|
|
|
22490
22494
|
method: "GET"
|
|
22491
22495
|
});
|
|
22492
22496
|
}
|
|
22493
|
-
async readFile(sandboxName,
|
|
22497
|
+
async readFile(sandboxName, path5) {
|
|
22494
22498
|
return this.request("/api/files/read", {
|
|
22495
22499
|
method: "POST",
|
|
22496
|
-
body: { sandboxName, path:
|
|
22500
|
+
body: { sandboxName, path: path5 }
|
|
22497
22501
|
});
|
|
22498
22502
|
}
|
|
22499
|
-
async writeFile(sandboxName,
|
|
22503
|
+
async writeFile(sandboxName, path5, content) {
|
|
22500
22504
|
return this.request("/api/files/write", {
|
|
22501
22505
|
method: "POST",
|
|
22502
|
-
body: { sandboxName, path:
|
|
22506
|
+
body: { sandboxName, path: path5, content }
|
|
22503
22507
|
});
|
|
22504
22508
|
}
|
|
22505
|
-
async listPath(sandboxName,
|
|
22509
|
+
async listPath(sandboxName, path5, recursive) {
|
|
22506
22510
|
return this.request("/api/files/list", {
|
|
22507
22511
|
method: "POST",
|
|
22508
|
-
body: { sandboxName, path:
|
|
22512
|
+
body: { sandboxName, path: path5, recursive }
|
|
22509
22513
|
});
|
|
22510
22514
|
}
|
|
22511
|
-
async findFiles(sandboxName,
|
|
22515
|
+
async findFiles(sandboxName, path5, pattern) {
|
|
22512
22516
|
return this.request("/api/files/find", {
|
|
22513
22517
|
method: "POST",
|
|
22514
|
-
body: { sandboxName, path:
|
|
22518
|
+
body: { sandboxName, path: path5, pattern }
|
|
22515
22519
|
});
|
|
22516
22520
|
}
|
|
22517
|
-
async searchInFile(sandboxName,
|
|
22521
|
+
async searchInFile(sandboxName, path5, query) {
|
|
22518
22522
|
return this.request("/api/files/search", {
|
|
22519
22523
|
method: "POST",
|
|
22520
|
-
body: { sandboxName, path:
|
|
22524
|
+
body: { sandboxName, path: path5, query }
|
|
22521
22525
|
});
|
|
22522
22526
|
}
|
|
22523
22527
|
async replaceInFile(sandboxName, input) {
|
|
@@ -22526,14 +22530,14 @@ var MicrosandboxServiceClient = class {
|
|
|
22526
22530
|
body: { sandboxName, ...input }
|
|
22527
22531
|
});
|
|
22528
22532
|
}
|
|
22529
|
-
async uploadFile(sandboxName,
|
|
22533
|
+
async uploadFile(sandboxName, path5, content) {
|
|
22530
22534
|
return this.request("/api/files/upload", {
|
|
22531
22535
|
method: "POST",
|
|
22532
|
-
body: { sandboxName, path:
|
|
22536
|
+
body: { sandboxName, path: path5, contentBase64: content.toString("base64") }
|
|
22533
22537
|
});
|
|
22534
22538
|
}
|
|
22535
|
-
async downloadFile(sandboxName,
|
|
22536
|
-
const query = new URLSearchParams({ sandboxName, path:
|
|
22539
|
+
async downloadFile(sandboxName, path5) {
|
|
22540
|
+
const query = new URLSearchParams({ sandboxName, path: path5 });
|
|
22537
22541
|
return this.request(`/api/files/download?${query.toString()}`, {
|
|
22538
22542
|
method: "GET"
|
|
22539
22543
|
});
|
|
@@ -22544,32 +22548,32 @@ var MicrosandboxServiceClient = class {
|
|
|
22544
22548
|
body: input
|
|
22545
22549
|
});
|
|
22546
22550
|
}
|
|
22547
|
-
async volumeFsRead(volumeName,
|
|
22551
|
+
async volumeFsRead(volumeName, path5) {
|
|
22548
22552
|
const result = await this.request(
|
|
22549
22553
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/read`,
|
|
22550
22554
|
{
|
|
22551
22555
|
method: "POST",
|
|
22552
|
-
body: { path:
|
|
22556
|
+
body: { path: path5 }
|
|
22553
22557
|
}
|
|
22554
22558
|
);
|
|
22555
22559
|
return result.content;
|
|
22556
22560
|
}
|
|
22557
|
-
async volumeFsWrite(volumeName,
|
|
22561
|
+
async volumeFsWrite(volumeName, path5, content) {
|
|
22558
22562
|
await this.request(
|
|
22559
22563
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/write`,
|
|
22560
22564
|
{
|
|
22561
22565
|
method: "POST",
|
|
22562
|
-
body: { path:
|
|
22566
|
+
body: { path: path5, content }
|
|
22563
22567
|
}
|
|
22564
22568
|
);
|
|
22565
22569
|
}
|
|
22566
|
-
async volumeFsList(volumeName,
|
|
22567
|
-
console.log(`[volumeFsList] volume=${volumeName} path="${
|
|
22570
|
+
async volumeFsList(volumeName, path5) {
|
|
22571
|
+
console.log(`[volumeFsList] volume=${volumeName} path="${path5}" url=POST /api/volumes/${encodeURIComponent(volumeName)}/fs/list`);
|
|
22568
22572
|
const result = await this.request(
|
|
22569
22573
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/list`,
|
|
22570
22574
|
{
|
|
22571
22575
|
method: "POST",
|
|
22572
|
-
body: { path:
|
|
22576
|
+
body: { path: path5 }
|
|
22573
22577
|
}
|
|
22574
22578
|
);
|
|
22575
22579
|
console.log(
|
|
@@ -22578,25 +22582,25 @@ var MicrosandboxServiceClient = class {
|
|
|
22578
22582
|
);
|
|
22579
22583
|
return result.entries;
|
|
22580
22584
|
}
|
|
22581
|
-
async volumeFsDownload(volumeName,
|
|
22585
|
+
async volumeFsDownload(volumeName, path5) {
|
|
22582
22586
|
const result = await this.request(
|
|
22583
|
-
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(
|
|
22587
|
+
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path5)}`,
|
|
22584
22588
|
{
|
|
22585
22589
|
method: "GET"
|
|
22586
22590
|
}
|
|
22587
22591
|
);
|
|
22588
22592
|
return Buffer.from(result.contentBase64, "base64");
|
|
22589
22593
|
}
|
|
22590
|
-
async volumeFsUpload(volumeName,
|
|
22594
|
+
async volumeFsUpload(volumeName, path5, data) {
|
|
22591
22595
|
await this.request(
|
|
22592
22596
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/upload`,
|
|
22593
22597
|
{
|
|
22594
22598
|
method: "POST",
|
|
22595
|
-
body: { path:
|
|
22599
|
+
body: { path: path5, contentBase64: data.toString("base64") }
|
|
22596
22600
|
}
|
|
22597
22601
|
);
|
|
22598
22602
|
}
|
|
22599
|
-
async request(
|
|
22603
|
+
async request(path5, init) {
|
|
22600
22604
|
const headers = {};
|
|
22601
22605
|
if (init.body) {
|
|
22602
22606
|
headers["content-type"] = "application/json";
|
|
@@ -22604,7 +22608,7 @@ var MicrosandboxServiceClient = class {
|
|
|
22604
22608
|
if (this.apiKey) {
|
|
22605
22609
|
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
22606
22610
|
}
|
|
22607
|
-
const response = await fetch(`${this.baseURL}${
|
|
22611
|
+
const response = await fetch(`${this.baseURL}${path5}`, {
|
|
22608
22612
|
method: init.method,
|
|
22609
22613
|
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
22610
22614
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -22655,16 +22659,21 @@ var MicrosandboxRemoteProvider = class {
|
|
|
22655
22659
|
});
|
|
22656
22660
|
}
|
|
22657
22661
|
async createSandbox(name, config) {
|
|
22658
|
-
const existing = this.instances.get(name);
|
|
22659
|
-
if (existing) {
|
|
22660
|
-
return existing;
|
|
22661
|
-
}
|
|
22662
22662
|
const inFlight = this.creating.get(name);
|
|
22663
22663
|
if (inFlight) {
|
|
22664
22664
|
return inFlight;
|
|
22665
22665
|
}
|
|
22666
|
+
const existing = this.instances.get(name);
|
|
22667
|
+
if (existing) {
|
|
22668
|
+
console.log(`[MicrosandboxRemote] createSandbox name=${name} INSTANCE_CACHE_HIT`);
|
|
22669
|
+
return existing;
|
|
22670
|
+
}
|
|
22666
22671
|
const creation = (async () => {
|
|
22667
|
-
|
|
22672
|
+
const tStart = Date.now();
|
|
22673
|
+
const input = this.buildEnsureInput(config);
|
|
22674
|
+
console.log(`[MicrosandboxRemote] createSandbox name=${name} calling ensureSandbox...`);
|
|
22675
|
+
await this.client.ensureSandbox(name, input);
|
|
22676
|
+
console.log(`[MicrosandboxRemote] createSandbox DONE name=${name} elapsed=${Date.now() - tStart}ms`);
|
|
22668
22677
|
const instance = new MicrosandboxRemoteInstance(name, this.client);
|
|
22669
22678
|
this.instances.set(name, instance);
|
|
22670
22679
|
return instance;
|
|
@@ -22700,11 +22709,11 @@ var MicrosandboxRemoteProvider = class {
|
|
|
22700
22709
|
}
|
|
22701
22710
|
createVolumeFsClient(volumeName, _pathPrefix) {
|
|
22702
22711
|
return {
|
|
22703
|
-
read: (
|
|
22704
|
-
write: (
|
|
22705
|
-
list: (
|
|
22706
|
-
readRaw: (
|
|
22707
|
-
writeRaw: (
|
|
22712
|
+
read: (path5) => this.client.volumeFsRead(volumeName, path5),
|
|
22713
|
+
write: (path5, content) => this.client.volumeFsWrite(volumeName, path5, content),
|
|
22714
|
+
list: (path5) => this.client.volumeFsList(volumeName, path5),
|
|
22715
|
+
readRaw: (path5) => this.client.volumeFsDownload(volumeName, path5),
|
|
22716
|
+
writeRaw: (path5, data) => this.client.volumeFsUpload(volumeName, path5, data)
|
|
22708
22717
|
};
|
|
22709
22718
|
}
|
|
22710
22719
|
async listSandboxes() {
|
|
@@ -22803,8 +22812,8 @@ var RemoteSandboxInstance = class {
|
|
|
22803
22812
|
throw new Error(`writeFile failed: ${extractFetcherError(result.error)}`);
|
|
22804
22813
|
}
|
|
22805
22814
|
},
|
|
22806
|
-
listPath: async (
|
|
22807
|
-
const resolved = this.resolvePath(
|
|
22815
|
+
listPath: async (path5, options) => {
|
|
22816
|
+
const resolved = this.resolvePath(path5);
|
|
22808
22817
|
const result = await this.client.file.listPath({
|
|
22809
22818
|
path: resolved,
|
|
22810
22819
|
recursive: options?.recursive ?? false
|
|
@@ -22820,8 +22829,8 @@ var RemoteSandboxInstance = class {
|
|
|
22820
22829
|
}));
|
|
22821
22830
|
return { files };
|
|
22822
22831
|
},
|
|
22823
|
-
findFiles: async (
|
|
22824
|
-
const resolved = this.resolvePath(
|
|
22832
|
+
findFiles: async (path5, glob) => {
|
|
22833
|
+
const resolved = this.resolvePath(path5);
|
|
22825
22834
|
const result = await this.client.file.findFiles({ path: resolved, glob });
|
|
22826
22835
|
if (!result.ok) {
|
|
22827
22836
|
throw new Error(`findFiles failed: ${extractFetcherError(result.error)}`);
|
|
@@ -22871,8 +22880,8 @@ var RemoteSandboxInstance = class {
|
|
|
22871
22880
|
const buffer2 = await result.body.arrayBuffer();
|
|
22872
22881
|
return Buffer.from(buffer2);
|
|
22873
22882
|
},
|
|
22874
|
-
deletePath: async (
|
|
22875
|
-
const resolved = this.resolvePath(
|
|
22883
|
+
deletePath: async (path5) => {
|
|
22884
|
+
const resolved = this.resolvePath(path5);
|
|
22876
22885
|
const result = await this.client.shell.execCommand({
|
|
22877
22886
|
command: `rm -rf "${resolved}"`
|
|
22878
22887
|
});
|
|
@@ -22880,8 +22889,8 @@ var RemoteSandboxInstance = class {
|
|
|
22880
22889
|
throw new Error(`deletePath failed: ${extractFetcherError(result.error)}`);
|
|
22881
22890
|
}
|
|
22882
22891
|
},
|
|
22883
|
-
createDirectory: async (
|
|
22884
|
-
const resolved = this.resolvePath(
|
|
22892
|
+
createDirectory: async (path5) => {
|
|
22893
|
+
const resolved = this.resolvePath(path5);
|
|
22885
22894
|
const result = await this.client.shell.execCommand({
|
|
22886
22895
|
command: `mkdir -p "${resolved}"`
|
|
22887
22896
|
});
|
|
@@ -23008,7 +23017,7 @@ var RemoteSandboxProvider = class {
|
|
|
23008
23017
|
}
|
|
23009
23018
|
createVolumeFsClient(_volumeName, pathPrefix) {
|
|
23010
23019
|
const workspace = this.workspace;
|
|
23011
|
-
const
|
|
23020
|
+
const resolve4 = (p) => {
|
|
23012
23021
|
if (!p || p === "/") {
|
|
23013
23022
|
if (pathPrefix) {
|
|
23014
23023
|
return `${workspace}${pathPrefix}`;
|
|
@@ -23028,23 +23037,23 @@ var RemoteSandboxProvider = class {
|
|
|
23028
23037
|
return `${workspace}/${p}`;
|
|
23029
23038
|
};
|
|
23030
23039
|
return {
|
|
23031
|
-
read: async (
|
|
23032
|
-
const resolved =
|
|
23040
|
+
read: async (path5) => {
|
|
23041
|
+
const resolved = resolve4(path5);
|
|
23033
23042
|
const result = await this.client.file.readFile({ file: resolved });
|
|
23034
23043
|
if (!result.ok) {
|
|
23035
23044
|
throw new Error(`Volume read failed: ${extractFetcherError(result.error)}`);
|
|
23036
23045
|
}
|
|
23037
23046
|
return result.body.data?.content ?? "";
|
|
23038
23047
|
},
|
|
23039
|
-
write: async (
|
|
23040
|
-
const resolved =
|
|
23048
|
+
write: async (path5, content) => {
|
|
23049
|
+
const resolved = resolve4(path5);
|
|
23041
23050
|
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
23042
23051
|
if (!result.ok) {
|
|
23043
23052
|
throw new Error(`Volume write failed: ${extractFetcherError(result.error)}`);
|
|
23044
23053
|
}
|
|
23045
23054
|
},
|
|
23046
|
-
list: async (
|
|
23047
|
-
const resolved =
|
|
23055
|
+
list: async (path5) => {
|
|
23056
|
+
const resolved = resolve4(path5);
|
|
23048
23057
|
const result = await this.client.file.listPath({
|
|
23049
23058
|
path: resolved,
|
|
23050
23059
|
recursive: false
|
|
@@ -23061,8 +23070,8 @@ var RemoteSandboxProvider = class {
|
|
|
23061
23070
|
}));
|
|
23062
23071
|
return entries;
|
|
23063
23072
|
},
|
|
23064
|
-
readRaw: async (
|
|
23065
|
-
const resolved =
|
|
23073
|
+
readRaw: async (path5) => {
|
|
23074
|
+
const resolved = resolve4(path5);
|
|
23066
23075
|
const result = await this.client.file.downloadFile({ path: resolved });
|
|
23067
23076
|
if (!result.ok) {
|
|
23068
23077
|
throw new Error(`Volume download failed: ${extractFetcherError(result.error)}`);
|
|
@@ -23070,8 +23079,8 @@ var RemoteSandboxProvider = class {
|
|
|
23070
23079
|
const buffer2 = await result.body.arrayBuffer();
|
|
23071
23080
|
return Buffer.from(buffer2);
|
|
23072
23081
|
},
|
|
23073
|
-
writeRaw: async (
|
|
23074
|
-
const resolved =
|
|
23082
|
+
writeRaw: async (path5, data) => {
|
|
23083
|
+
const resolved = resolve4(path5);
|
|
23075
23084
|
const result = await this.client.file.uploadFile({
|
|
23076
23085
|
file: data,
|
|
23077
23086
|
path: resolved
|
|
@@ -23099,8 +23108,8 @@ var E2BInstance = class {
|
|
|
23099
23108
|
writeFile: async (file, content) => {
|
|
23100
23109
|
await this.native.files.write(file, content);
|
|
23101
23110
|
},
|
|
23102
|
-
listPath: async (
|
|
23103
|
-
const entries = await this.native.files.list(
|
|
23111
|
+
listPath: async (path5, options) => {
|
|
23112
|
+
const entries = await this.native.files.list(path5);
|
|
23104
23113
|
const files = entries.map((e) => ({
|
|
23105
23114
|
path: e.path,
|
|
23106
23115
|
is_dir: e.type === "dir",
|
|
@@ -23109,9 +23118,9 @@ var E2BInstance = class {
|
|
|
23109
23118
|
}));
|
|
23110
23119
|
return { files };
|
|
23111
23120
|
},
|
|
23112
|
-
findFiles: async (
|
|
23121
|
+
findFiles: async (path5, glob) => {
|
|
23113
23122
|
const result = await this.native.commands.run(
|
|
23114
|
-
`find "${
|
|
23123
|
+
`find "${path5}" -name "${glob}" -type f`
|
|
23115
23124
|
);
|
|
23116
23125
|
const lines = result.stdout.split("\n").filter(Boolean);
|
|
23117
23126
|
return { files: lines };
|
|
@@ -23134,13 +23143,13 @@ var E2BInstance = class {
|
|
|
23134
23143
|
return { matches, line_numbers };
|
|
23135
23144
|
},
|
|
23136
23145
|
strReplaceEditor: async (params) => {
|
|
23137
|
-
const { path:
|
|
23146
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
23138
23147
|
const delim = "#";
|
|
23139
23148
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
23140
23149
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
23141
23150
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
23142
23151
|
await this.native.commands.run(
|
|
23143
|
-
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
23152
|
+
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path5}"`
|
|
23144
23153
|
);
|
|
23145
23154
|
},
|
|
23146
23155
|
uploadFile: async (params) => {
|
|
@@ -23152,11 +23161,11 @@ var E2BInstance = class {
|
|
|
23152
23161
|
const data = await this.native.files.read(params.file, { format: "bytes" });
|
|
23153
23162
|
return Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
23154
23163
|
},
|
|
23155
|
-
deletePath: async (
|
|
23156
|
-
await this.native.commands.run(`rm -rf "${
|
|
23164
|
+
deletePath: async (path5) => {
|
|
23165
|
+
await this.native.commands.run(`rm -rf "${path5}"`);
|
|
23157
23166
|
},
|
|
23158
|
-
createDirectory: async (
|
|
23159
|
-
await this.native.commands.run(`mkdir -p "${
|
|
23167
|
+
createDirectory: async (path5) => {
|
|
23168
|
+
await this.native.commands.run(`mkdir -p "${path5}"`);
|
|
23160
23169
|
}
|
|
23161
23170
|
};
|
|
23162
23171
|
this.shell = {
|
|
@@ -23275,8 +23284,8 @@ var DaytonaInstance = class {
|
|
|
23275
23284
|
writeFile: async (file, content) => {
|
|
23276
23285
|
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
|
|
23277
23286
|
},
|
|
23278
|
-
listPath: async (
|
|
23279
|
-
const entries = await this.native.fs.listFiles(toRelativePath(
|
|
23287
|
+
listPath: async (path5, options) => {
|
|
23288
|
+
const entries = await this.native.fs.listFiles(toRelativePath(path5));
|
|
23280
23289
|
const files = entries.map((e) => {
|
|
23281
23290
|
const rawPath = e.name || "";
|
|
23282
23291
|
return {
|
|
@@ -23288,8 +23297,8 @@ var DaytonaInstance = class {
|
|
|
23288
23297
|
});
|
|
23289
23298
|
return { files };
|
|
23290
23299
|
},
|
|
23291
|
-
findFiles: async (
|
|
23292
|
-
const result = await this.native.fs.searchFiles(toRelativePath(
|
|
23300
|
+
findFiles: async (path5, glob) => {
|
|
23301
|
+
const result = await this.native.fs.searchFiles(toRelativePath(path5), glob);
|
|
23293
23302
|
return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
|
|
23294
23303
|
},
|
|
23295
23304
|
searchInFile: async (file, regex) => {
|
|
@@ -23303,8 +23312,8 @@ var DaytonaInstance = class {
|
|
|
23303
23312
|
return { matches: matchTexts, line_numbers };
|
|
23304
23313
|
},
|
|
23305
23314
|
strReplaceEditor: async (params) => {
|
|
23306
|
-
const { path:
|
|
23307
|
-
const relPath = toRelativePath(
|
|
23315
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
23316
|
+
const relPath = toRelativePath(path5);
|
|
23308
23317
|
if (replace_mode === "ALL") {
|
|
23309
23318
|
await this.native.fs.replaceInFiles([relPath], old_str, new_str);
|
|
23310
23319
|
} else {
|
|
@@ -23324,11 +23333,11 @@ var DaytonaInstance = class {
|
|
|
23324
23333
|
const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
|
|
23325
23334
|
return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
|
|
23326
23335
|
},
|
|
23327
|
-
deletePath: async (
|
|
23328
|
-
await this.native.process.executeCommand(`rm -rf "${toRelativePath(
|
|
23336
|
+
deletePath: async (path5) => {
|
|
23337
|
+
await this.native.process.executeCommand(`rm -rf "${toRelativePath(path5)}"`, void 0, void 0);
|
|
23329
23338
|
},
|
|
23330
|
-
createDirectory: async (
|
|
23331
|
-
await this.native.process.executeCommand(`mkdir -p "${toRelativePath(
|
|
23339
|
+
createDirectory: async (path5) => {
|
|
23340
|
+
await this.native.process.executeCommand(`mkdir -p "${toRelativePath(path5)}"`, void 0, void 0);
|
|
23332
23341
|
}
|
|
23333
23342
|
};
|
|
23334
23343
|
this.shell = {
|
|
@@ -23567,6 +23576,277 @@ var DaytonaProvider = class {
|
|
|
23567
23576
|
}
|
|
23568
23577
|
};
|
|
23569
23578
|
|
|
23579
|
+
// src/sandbox_lattice/providers/LocalSandboxProvider.ts
|
|
23580
|
+
import * as path4 from "path";
|
|
23581
|
+
import * as os from "os";
|
|
23582
|
+
|
|
23583
|
+
// src/sandbox_lattice/LocalSandboxInstance.ts
|
|
23584
|
+
import { execFile } from "child_process";
|
|
23585
|
+
import * as fs3 from "fs/promises";
|
|
23586
|
+
import * as path3 from "path";
|
|
23587
|
+
import * as posix from "path/posix";
|
|
23588
|
+
import { promisify } from "util";
|
|
23589
|
+
var execFileAsync = promisify(execFile);
|
|
23590
|
+
var isWin = process.platform === "win32";
|
|
23591
|
+
var LocalSandboxInstance = class {
|
|
23592
|
+
constructor(name, rootDir) {
|
|
23593
|
+
this.file = {
|
|
23594
|
+
readFile: async (file) => {
|
|
23595
|
+
const content = await fs3.readFile(this.hostPath(file), "utf-8");
|
|
23596
|
+
return { content };
|
|
23597
|
+
},
|
|
23598
|
+
writeFile: async (file, content) => {
|
|
23599
|
+
const hp = this.hostPath(file);
|
|
23600
|
+
await fs3.mkdir(path3.dirname(hp), { recursive: true });
|
|
23601
|
+
await fs3.writeFile(hp, content, "utf-8");
|
|
23602
|
+
},
|
|
23603
|
+
listPath: async (targetPath, options) => {
|
|
23604
|
+
const hp = this.hostPath(targetPath);
|
|
23605
|
+
const files = [];
|
|
23606
|
+
if (options?.recursive) {
|
|
23607
|
+
await this.walkDir(hp, targetPath, files);
|
|
23608
|
+
} else {
|
|
23609
|
+
const entries = await fs3.readdir(hp, { withFileTypes: true });
|
|
23610
|
+
for (const e of entries) {
|
|
23611
|
+
const full = path3.join(hp, e.name);
|
|
23612
|
+
const stat4 = await fs3.stat(full).catch(() => null);
|
|
23613
|
+
files.push({
|
|
23614
|
+
path: posix.join(targetPath, e.name),
|
|
23615
|
+
is_dir: e.isDirectory(),
|
|
23616
|
+
size: stat4?.size ?? 0,
|
|
23617
|
+
modified_at: stat4?.mtime.toISOString()
|
|
23618
|
+
});
|
|
23619
|
+
}
|
|
23620
|
+
}
|
|
23621
|
+
return { files };
|
|
23622
|
+
},
|
|
23623
|
+
findFiles: async (targetPath, glob) => {
|
|
23624
|
+
const hp = this.hostPath(targetPath);
|
|
23625
|
+
const results = [];
|
|
23626
|
+
const regex = new RegExp(
|
|
23627
|
+
"^" + glob.replace(/\*+/g, "(.*)").replace(/\?/g, ".") + "$"
|
|
23628
|
+
);
|
|
23629
|
+
await this.walkDirFilter(hp, regex, results);
|
|
23630
|
+
const hpNorm = hp + path3.sep;
|
|
23631
|
+
const toSandboxPath = (hostPath) => posix.join(targetPath, hostPath.slice(hpNorm.length).split(path3.sep).join("/"));
|
|
23632
|
+
return { files: results.map(toSandboxPath) };
|
|
23633
|
+
},
|
|
23634
|
+
searchInFile: async (file, regex) => {
|
|
23635
|
+
const content = await fs3.readFile(this.hostPath(file), "utf-8");
|
|
23636
|
+
const lines = content.split("\n");
|
|
23637
|
+
const matches = [];
|
|
23638
|
+
const line_numbers = [];
|
|
23639
|
+
try {
|
|
23640
|
+
const re = new RegExp(regex);
|
|
23641
|
+
for (let i = 0; i < lines.length; i++) {
|
|
23642
|
+
if (re.test(lines[i])) {
|
|
23643
|
+
matches.push(lines[i]);
|
|
23644
|
+
line_numbers.push(i + 1);
|
|
23645
|
+
}
|
|
23646
|
+
}
|
|
23647
|
+
} catch {
|
|
23648
|
+
}
|
|
23649
|
+
return { matches, line_numbers };
|
|
23650
|
+
},
|
|
23651
|
+
strReplaceEditor: async (params) => {
|
|
23652
|
+
const content = await fs3.readFile(this.hostPath(params.path), "utf-8");
|
|
23653
|
+
let result;
|
|
23654
|
+
if (params.replace_mode === "ALL") {
|
|
23655
|
+
result = content.split(params.old_str).join(params.new_str);
|
|
23656
|
+
} else {
|
|
23657
|
+
const idx = content.indexOf(params.old_str);
|
|
23658
|
+
if (idx === -1) {
|
|
23659
|
+
throw new Error(`Old string not found in ${params.path}`);
|
|
23660
|
+
}
|
|
23661
|
+
result = content.slice(0, idx) + params.new_str + content.slice(idx + params.old_str.length);
|
|
23662
|
+
}
|
|
23663
|
+
await fs3.writeFile(this.hostPath(params.path), result, "utf-8");
|
|
23664
|
+
},
|
|
23665
|
+
uploadFile: async (params) => {
|
|
23666
|
+
const hp = this.hostPath(params.file);
|
|
23667
|
+
await fs3.mkdir(path3.dirname(hp), { recursive: true });
|
|
23668
|
+
await fs3.writeFile(hp, params.data);
|
|
23669
|
+
},
|
|
23670
|
+
downloadFile: async (params) => {
|
|
23671
|
+
const data = await fs3.readFile(this.hostPath(params.file));
|
|
23672
|
+
return data;
|
|
23673
|
+
},
|
|
23674
|
+
deletePath: async (targetPath) => {
|
|
23675
|
+
await fs3.rm(this.hostPath(targetPath), { recursive: true, force: true });
|
|
23676
|
+
},
|
|
23677
|
+
createDirectory: async (targetPath) => {
|
|
23678
|
+
await fs3.mkdir(this.hostPath(targetPath), { recursive: true });
|
|
23679
|
+
}
|
|
23680
|
+
};
|
|
23681
|
+
this.shell = {
|
|
23682
|
+
execCommand: async (params) => {
|
|
23683
|
+
const hp = params.exec_dir ? this.hostPath(params.exec_dir) : this.rootDir;
|
|
23684
|
+
const timeoutMs = params.timeout ? params.timeout * 1e3 : void 0;
|
|
23685
|
+
const [shell, shellArg] = isWin ? ["cmd.exe", "/c"] : ["/bin/sh", "-c"];
|
|
23686
|
+
try {
|
|
23687
|
+
const { stdout, stderr } = await execFileAsync(
|
|
23688
|
+
shell,
|
|
23689
|
+
[shellArg, params.command],
|
|
23690
|
+
{
|
|
23691
|
+
cwd: hp,
|
|
23692
|
+
timeout: timeoutMs,
|
|
23693
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
23694
|
+
// 10MB
|
|
23695
|
+
env: { ...process.env, HOME: this.rootDir }
|
|
23696
|
+
}
|
|
23697
|
+
);
|
|
23698
|
+
const output = stderr ? `${stdout}
|
|
23699
|
+
${stderr}`.trim() : stdout.trim();
|
|
23700
|
+
return { output, exit_code: 0 };
|
|
23701
|
+
} catch (err) {
|
|
23702
|
+
const execErr = err;
|
|
23703
|
+
const out = execErr.stdout ?? "";
|
|
23704
|
+
const errOut = execErr.stderr ?? "";
|
|
23705
|
+
const output = errOut ? `${out}
|
|
23706
|
+
${errOut}`.trim() : out.trim();
|
|
23707
|
+
return { output, exit_code: execErr.code ?? 1 };
|
|
23708
|
+
}
|
|
23709
|
+
}
|
|
23710
|
+
};
|
|
23711
|
+
this.name = name;
|
|
23712
|
+
this.rootDir = rootDir;
|
|
23713
|
+
}
|
|
23714
|
+
/** Map sandbox path (absolute, e.g. `/root/foo`) to host filesystem path. */
|
|
23715
|
+
hostPath(sandboxPath) {
|
|
23716
|
+
const normalized = sandboxPath.startsWith("/") ? sandboxPath : `/${sandboxPath}`;
|
|
23717
|
+
const clean = normalized.replace(/\/+/g, "/");
|
|
23718
|
+
const resolved = path3.resolve(this.rootDir, `.${clean}`);
|
|
23719
|
+
if (!resolved.startsWith(this.rootDir + path3.sep) && resolved !== this.rootDir) {
|
|
23720
|
+
throw new Error(`Path traversal denied: ${sandboxPath}`);
|
|
23721
|
+
}
|
|
23722
|
+
return resolved;
|
|
23723
|
+
}
|
|
23724
|
+
async start() {
|
|
23725
|
+
await fs3.mkdir(this.rootDir, { recursive: true });
|
|
23726
|
+
}
|
|
23727
|
+
async stop() {
|
|
23728
|
+
}
|
|
23729
|
+
async kill() {
|
|
23730
|
+
await fs3.rm(this.rootDir, { recursive: true, force: true });
|
|
23731
|
+
}
|
|
23732
|
+
async getStatus() {
|
|
23733
|
+
try {
|
|
23734
|
+
await fs3.access(this.rootDir);
|
|
23735
|
+
return "running";
|
|
23736
|
+
} catch {
|
|
23737
|
+
return "stopped";
|
|
23738
|
+
}
|
|
23739
|
+
}
|
|
23740
|
+
async walkDir(rootHost, sandboxPrefix, result) {
|
|
23741
|
+
const walk = async (hostDir, sandboxDir) => {
|
|
23742
|
+
let entries;
|
|
23743
|
+
try {
|
|
23744
|
+
entries = await fs3.readdir(hostDir, { withFileTypes: true });
|
|
23745
|
+
} catch {
|
|
23746
|
+
return;
|
|
23747
|
+
}
|
|
23748
|
+
for (const e of entries) {
|
|
23749
|
+
const fullHost = path3.join(hostDir, e.name);
|
|
23750
|
+
const fullSandbox = posix.join(sandboxDir, e.name);
|
|
23751
|
+
try {
|
|
23752
|
+
const stat4 = await fs3.stat(fullHost);
|
|
23753
|
+
result.push({
|
|
23754
|
+
path: fullSandbox,
|
|
23755
|
+
is_dir: e.isDirectory(),
|
|
23756
|
+
size: stat4.size,
|
|
23757
|
+
modified_at: stat4.mtime.toISOString()
|
|
23758
|
+
});
|
|
23759
|
+
} catch {
|
|
23760
|
+
result.push({
|
|
23761
|
+
path: fullSandbox,
|
|
23762
|
+
is_dir: e.isDirectory()
|
|
23763
|
+
});
|
|
23764
|
+
}
|
|
23765
|
+
if (e.isDirectory()) {
|
|
23766
|
+
await walk(fullHost, fullSandbox);
|
|
23767
|
+
}
|
|
23768
|
+
}
|
|
23769
|
+
};
|
|
23770
|
+
await walk(rootHost, sandboxPrefix);
|
|
23771
|
+
}
|
|
23772
|
+
async walkDirFilter(dir, regex, result) {
|
|
23773
|
+
let entries;
|
|
23774
|
+
try {
|
|
23775
|
+
entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
23776
|
+
} catch {
|
|
23777
|
+
return;
|
|
23778
|
+
}
|
|
23779
|
+
for (const e of entries) {
|
|
23780
|
+
const full = path3.join(dir, e.name);
|
|
23781
|
+
if (e.isFile() && regex.test(e.name)) {
|
|
23782
|
+
result.push(full);
|
|
23783
|
+
}
|
|
23784
|
+
if (e.isDirectory()) {
|
|
23785
|
+
await this.walkDirFilter(full, regex, result);
|
|
23786
|
+
}
|
|
23787
|
+
}
|
|
23788
|
+
}
|
|
23789
|
+
};
|
|
23790
|
+
|
|
23791
|
+
// src/sandbox_lattice/providers/LocalSandboxProvider.ts
|
|
23792
|
+
var LocalSandboxProvider = class {
|
|
23793
|
+
constructor(config = {}) {
|
|
23794
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
23795
|
+
this.creating = /* @__PURE__ */ new Map();
|
|
23796
|
+
this.basePath = config.basePath ?? path4.join(os.homedir(), ".axiom-local-sandbox");
|
|
23797
|
+
}
|
|
23798
|
+
async createSandbox(name, _config) {
|
|
23799
|
+
const existing = this.instances.get(name);
|
|
23800
|
+
if (existing) {
|
|
23801
|
+
const running = await existing.getStatus();
|
|
23802
|
+
if (running === "running") {
|
|
23803
|
+
return existing;
|
|
23804
|
+
}
|
|
23805
|
+
this.instances.delete(name);
|
|
23806
|
+
}
|
|
23807
|
+
const inFlight = this.creating.get(name);
|
|
23808
|
+
if (inFlight) {
|
|
23809
|
+
return inFlight;
|
|
23810
|
+
}
|
|
23811
|
+
const sandboxDir = path4.join(this.basePath, name);
|
|
23812
|
+
const creation = (async () => {
|
|
23813
|
+
const instance = new LocalSandboxInstance(name, sandboxDir);
|
|
23814
|
+
await instance.start();
|
|
23815
|
+
this.instances.set(name, instance);
|
|
23816
|
+
return instance;
|
|
23817
|
+
})();
|
|
23818
|
+
this.creating.set(name, creation);
|
|
23819
|
+
creation.catch(() => this.instances.delete(name)).finally(() => this.creating.delete(name));
|
|
23820
|
+
return creation;
|
|
23821
|
+
}
|
|
23822
|
+
async getSandbox(name) {
|
|
23823
|
+
const instance = this.instances.get(name);
|
|
23824
|
+
if (!instance) {
|
|
23825
|
+
throw new Error(`Sandbox ${name} not found`);
|
|
23826
|
+
}
|
|
23827
|
+
return instance;
|
|
23828
|
+
}
|
|
23829
|
+
async stopSandbox(name) {
|
|
23830
|
+
const instance = this.instances.get(name);
|
|
23831
|
+
if (instance) {
|
|
23832
|
+
try {
|
|
23833
|
+
await instance.stop();
|
|
23834
|
+
} catch {
|
|
23835
|
+
}
|
|
23836
|
+
}
|
|
23837
|
+
}
|
|
23838
|
+
async deleteSandbox(name) {
|
|
23839
|
+
const instance = this.instances.get(name);
|
|
23840
|
+
this.instances.delete(name);
|
|
23841
|
+
if (instance) {
|
|
23842
|
+
await instance.kill();
|
|
23843
|
+
}
|
|
23844
|
+
}
|
|
23845
|
+
async listSandboxes() {
|
|
23846
|
+
return Array.from(this.instances.values());
|
|
23847
|
+
}
|
|
23848
|
+
};
|
|
23849
|
+
|
|
23570
23850
|
// src/sandbox_lattice/SandboxProviderFactory.ts
|
|
23571
23851
|
function createSandboxProvider(config) {
|
|
23572
23852
|
switch (config.type) {
|
|
@@ -23611,6 +23891,9 @@ function createSandboxProvider(config) {
|
|
|
23611
23891
|
volumeName: config.daytonaVolumeName
|
|
23612
23892
|
});
|
|
23613
23893
|
}
|
|
23894
|
+
case "local": {
|
|
23895
|
+
return new LocalSandboxProvider({ basePath: config.localSandboxBasePath });
|
|
23896
|
+
}
|
|
23614
23897
|
default: {
|
|
23615
23898
|
const exhaustiveCheck = config.type;
|
|
23616
23899
|
throw new Error(`Unknown sandbox provider type: ${exhaustiveCheck}`);
|
|
@@ -23901,6 +24184,8 @@ export {
|
|
|
23901
24184
|
InMemoryUserStore,
|
|
23902
24185
|
InMemoryUserTenantLinkStore,
|
|
23903
24186
|
LINE_NUMBER_WIDTH,
|
|
24187
|
+
LocalSandboxInstance,
|
|
24188
|
+
LocalSandboxProvider,
|
|
23904
24189
|
LoggerLatticeManager,
|
|
23905
24190
|
MAX_LINE_LENGTH,
|
|
23906
24191
|
McpLatticeManager,
|