@axiom-lattice/core 2.1.85 → 2.1.87
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 -187
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -185
- 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
|
|
@@ -22659,8 +22663,17 @@ var MicrosandboxRemoteProvider = class {
|
|
|
22659
22663
|
if (inFlight) {
|
|
22660
22664
|
return inFlight;
|
|
22661
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
|
+
}
|
|
22662
22671
|
const creation = (async () => {
|
|
22663
|
-
|
|
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`);
|
|
22664
22677
|
const instance = new MicrosandboxRemoteInstance(name, this.client);
|
|
22665
22678
|
this.instances.set(name, instance);
|
|
22666
22679
|
return instance;
|
|
@@ -22696,11 +22709,11 @@ var MicrosandboxRemoteProvider = class {
|
|
|
22696
22709
|
}
|
|
22697
22710
|
createVolumeFsClient(volumeName, _pathPrefix) {
|
|
22698
22711
|
return {
|
|
22699
|
-
read: (
|
|
22700
|
-
write: (
|
|
22701
|
-
list: (
|
|
22702
|
-
readRaw: (
|
|
22703
|
-
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)
|
|
22704
22717
|
};
|
|
22705
22718
|
}
|
|
22706
22719
|
async listSandboxes() {
|
|
@@ -22799,8 +22812,8 @@ var RemoteSandboxInstance = class {
|
|
|
22799
22812
|
throw new Error(`writeFile failed: ${extractFetcherError(result.error)}`);
|
|
22800
22813
|
}
|
|
22801
22814
|
},
|
|
22802
|
-
listPath: async (
|
|
22803
|
-
const resolved = this.resolvePath(
|
|
22815
|
+
listPath: async (path5, options) => {
|
|
22816
|
+
const resolved = this.resolvePath(path5);
|
|
22804
22817
|
const result = await this.client.file.listPath({
|
|
22805
22818
|
path: resolved,
|
|
22806
22819
|
recursive: options?.recursive ?? false
|
|
@@ -22816,8 +22829,8 @@ var RemoteSandboxInstance = class {
|
|
|
22816
22829
|
}));
|
|
22817
22830
|
return { files };
|
|
22818
22831
|
},
|
|
22819
|
-
findFiles: async (
|
|
22820
|
-
const resolved = this.resolvePath(
|
|
22832
|
+
findFiles: async (path5, glob) => {
|
|
22833
|
+
const resolved = this.resolvePath(path5);
|
|
22821
22834
|
const result = await this.client.file.findFiles({ path: resolved, glob });
|
|
22822
22835
|
if (!result.ok) {
|
|
22823
22836
|
throw new Error(`findFiles failed: ${extractFetcherError(result.error)}`);
|
|
@@ -22867,8 +22880,8 @@ var RemoteSandboxInstance = class {
|
|
|
22867
22880
|
const buffer2 = await result.body.arrayBuffer();
|
|
22868
22881
|
return Buffer.from(buffer2);
|
|
22869
22882
|
},
|
|
22870
|
-
deletePath: async (
|
|
22871
|
-
const resolved = this.resolvePath(
|
|
22883
|
+
deletePath: async (path5) => {
|
|
22884
|
+
const resolved = this.resolvePath(path5);
|
|
22872
22885
|
const result = await this.client.shell.execCommand({
|
|
22873
22886
|
command: `rm -rf "${resolved}"`
|
|
22874
22887
|
});
|
|
@@ -22876,8 +22889,8 @@ var RemoteSandboxInstance = class {
|
|
|
22876
22889
|
throw new Error(`deletePath failed: ${extractFetcherError(result.error)}`);
|
|
22877
22890
|
}
|
|
22878
22891
|
},
|
|
22879
|
-
createDirectory: async (
|
|
22880
|
-
const resolved = this.resolvePath(
|
|
22892
|
+
createDirectory: async (path5) => {
|
|
22893
|
+
const resolved = this.resolvePath(path5);
|
|
22881
22894
|
const result = await this.client.shell.execCommand({
|
|
22882
22895
|
command: `mkdir -p "${resolved}"`
|
|
22883
22896
|
});
|
|
@@ -23004,7 +23017,7 @@ var RemoteSandboxProvider = class {
|
|
|
23004
23017
|
}
|
|
23005
23018
|
createVolumeFsClient(_volumeName, pathPrefix) {
|
|
23006
23019
|
const workspace = this.workspace;
|
|
23007
|
-
const
|
|
23020
|
+
const resolve4 = (p) => {
|
|
23008
23021
|
if (!p || p === "/") {
|
|
23009
23022
|
if (pathPrefix) {
|
|
23010
23023
|
return `${workspace}${pathPrefix}`;
|
|
@@ -23024,23 +23037,23 @@ var RemoteSandboxProvider = class {
|
|
|
23024
23037
|
return `${workspace}/${p}`;
|
|
23025
23038
|
};
|
|
23026
23039
|
return {
|
|
23027
|
-
read: async (
|
|
23028
|
-
const resolved =
|
|
23040
|
+
read: async (path5) => {
|
|
23041
|
+
const resolved = resolve4(path5);
|
|
23029
23042
|
const result = await this.client.file.readFile({ file: resolved });
|
|
23030
23043
|
if (!result.ok) {
|
|
23031
23044
|
throw new Error(`Volume read failed: ${extractFetcherError(result.error)}`);
|
|
23032
23045
|
}
|
|
23033
23046
|
return result.body.data?.content ?? "";
|
|
23034
23047
|
},
|
|
23035
|
-
write: async (
|
|
23036
|
-
const resolved =
|
|
23048
|
+
write: async (path5, content) => {
|
|
23049
|
+
const resolved = resolve4(path5);
|
|
23037
23050
|
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
23038
23051
|
if (!result.ok) {
|
|
23039
23052
|
throw new Error(`Volume write failed: ${extractFetcherError(result.error)}`);
|
|
23040
23053
|
}
|
|
23041
23054
|
},
|
|
23042
|
-
list: async (
|
|
23043
|
-
const resolved =
|
|
23055
|
+
list: async (path5) => {
|
|
23056
|
+
const resolved = resolve4(path5);
|
|
23044
23057
|
const result = await this.client.file.listPath({
|
|
23045
23058
|
path: resolved,
|
|
23046
23059
|
recursive: false
|
|
@@ -23057,8 +23070,8 @@ var RemoteSandboxProvider = class {
|
|
|
23057
23070
|
}));
|
|
23058
23071
|
return entries;
|
|
23059
23072
|
},
|
|
23060
|
-
readRaw: async (
|
|
23061
|
-
const resolved =
|
|
23073
|
+
readRaw: async (path5) => {
|
|
23074
|
+
const resolved = resolve4(path5);
|
|
23062
23075
|
const result = await this.client.file.downloadFile({ path: resolved });
|
|
23063
23076
|
if (!result.ok) {
|
|
23064
23077
|
throw new Error(`Volume download failed: ${extractFetcherError(result.error)}`);
|
|
@@ -23066,8 +23079,8 @@ var RemoteSandboxProvider = class {
|
|
|
23066
23079
|
const buffer2 = await result.body.arrayBuffer();
|
|
23067
23080
|
return Buffer.from(buffer2);
|
|
23068
23081
|
},
|
|
23069
|
-
writeRaw: async (
|
|
23070
|
-
const resolved =
|
|
23082
|
+
writeRaw: async (path5, data) => {
|
|
23083
|
+
const resolved = resolve4(path5);
|
|
23071
23084
|
const result = await this.client.file.uploadFile({
|
|
23072
23085
|
file: data,
|
|
23073
23086
|
path: resolved
|
|
@@ -23095,8 +23108,8 @@ var E2BInstance = class {
|
|
|
23095
23108
|
writeFile: async (file, content) => {
|
|
23096
23109
|
await this.native.files.write(file, content);
|
|
23097
23110
|
},
|
|
23098
|
-
listPath: async (
|
|
23099
|
-
const entries = await this.native.files.list(
|
|
23111
|
+
listPath: async (path5, options) => {
|
|
23112
|
+
const entries = await this.native.files.list(path5);
|
|
23100
23113
|
const files = entries.map((e) => ({
|
|
23101
23114
|
path: e.path,
|
|
23102
23115
|
is_dir: e.type === "dir",
|
|
@@ -23105,9 +23118,9 @@ var E2BInstance = class {
|
|
|
23105
23118
|
}));
|
|
23106
23119
|
return { files };
|
|
23107
23120
|
},
|
|
23108
|
-
findFiles: async (
|
|
23121
|
+
findFiles: async (path5, glob) => {
|
|
23109
23122
|
const result = await this.native.commands.run(
|
|
23110
|
-
`find "${
|
|
23123
|
+
`find "${path5}" -name "${glob}" -type f`
|
|
23111
23124
|
);
|
|
23112
23125
|
const lines = result.stdout.split("\n").filter(Boolean);
|
|
23113
23126
|
return { files: lines };
|
|
@@ -23130,13 +23143,13 @@ var E2BInstance = class {
|
|
|
23130
23143
|
return { matches, line_numbers };
|
|
23131
23144
|
},
|
|
23132
23145
|
strReplaceEditor: async (params) => {
|
|
23133
|
-
const { path:
|
|
23146
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
23134
23147
|
const delim = "#";
|
|
23135
23148
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
23136
23149
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
23137
23150
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
23138
23151
|
await this.native.commands.run(
|
|
23139
|
-
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
23152
|
+
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path5}"`
|
|
23140
23153
|
);
|
|
23141
23154
|
},
|
|
23142
23155
|
uploadFile: async (params) => {
|
|
@@ -23148,11 +23161,11 @@ var E2BInstance = class {
|
|
|
23148
23161
|
const data = await this.native.files.read(params.file, { format: "bytes" });
|
|
23149
23162
|
return Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
23150
23163
|
},
|
|
23151
|
-
deletePath: async (
|
|
23152
|
-
await this.native.commands.run(`rm -rf "${
|
|
23164
|
+
deletePath: async (path5) => {
|
|
23165
|
+
await this.native.commands.run(`rm -rf "${path5}"`);
|
|
23153
23166
|
},
|
|
23154
|
-
createDirectory: async (
|
|
23155
|
-
await this.native.commands.run(`mkdir -p "${
|
|
23167
|
+
createDirectory: async (path5) => {
|
|
23168
|
+
await this.native.commands.run(`mkdir -p "${path5}"`);
|
|
23156
23169
|
}
|
|
23157
23170
|
};
|
|
23158
23171
|
this.shell = {
|
|
@@ -23271,8 +23284,8 @@ var DaytonaInstance = class {
|
|
|
23271
23284
|
writeFile: async (file, content) => {
|
|
23272
23285
|
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
|
|
23273
23286
|
},
|
|
23274
|
-
listPath: async (
|
|
23275
|
-
const entries = await this.native.fs.listFiles(toRelativePath(
|
|
23287
|
+
listPath: async (path5, options) => {
|
|
23288
|
+
const entries = await this.native.fs.listFiles(toRelativePath(path5));
|
|
23276
23289
|
const files = entries.map((e) => {
|
|
23277
23290
|
const rawPath = e.name || "";
|
|
23278
23291
|
return {
|
|
@@ -23284,8 +23297,8 @@ var DaytonaInstance = class {
|
|
|
23284
23297
|
});
|
|
23285
23298
|
return { files };
|
|
23286
23299
|
},
|
|
23287
|
-
findFiles: async (
|
|
23288
|
-
const result = await this.native.fs.searchFiles(toRelativePath(
|
|
23300
|
+
findFiles: async (path5, glob) => {
|
|
23301
|
+
const result = await this.native.fs.searchFiles(toRelativePath(path5), glob);
|
|
23289
23302
|
return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
|
|
23290
23303
|
},
|
|
23291
23304
|
searchInFile: async (file, regex) => {
|
|
@@ -23299,8 +23312,8 @@ var DaytonaInstance = class {
|
|
|
23299
23312
|
return { matches: matchTexts, line_numbers };
|
|
23300
23313
|
},
|
|
23301
23314
|
strReplaceEditor: async (params) => {
|
|
23302
|
-
const { path:
|
|
23303
|
-
const relPath = toRelativePath(
|
|
23315
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
23316
|
+
const relPath = toRelativePath(path5);
|
|
23304
23317
|
if (replace_mode === "ALL") {
|
|
23305
23318
|
await this.native.fs.replaceInFiles([relPath], old_str, new_str);
|
|
23306
23319
|
} else {
|
|
@@ -23320,11 +23333,11 @@ var DaytonaInstance = class {
|
|
|
23320
23333
|
const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
|
|
23321
23334
|
return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
|
|
23322
23335
|
},
|
|
23323
|
-
deletePath: async (
|
|
23324
|
-
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);
|
|
23325
23338
|
},
|
|
23326
|
-
createDirectory: async (
|
|
23327
|
-
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);
|
|
23328
23341
|
}
|
|
23329
23342
|
};
|
|
23330
23343
|
this.shell = {
|
|
@@ -23563,6 +23576,277 @@ var DaytonaProvider = class {
|
|
|
23563
23576
|
}
|
|
23564
23577
|
};
|
|
23565
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
|
+
|
|
23566
23850
|
// src/sandbox_lattice/SandboxProviderFactory.ts
|
|
23567
23851
|
function createSandboxProvider(config) {
|
|
23568
23852
|
switch (config.type) {
|
|
@@ -23607,6 +23891,9 @@ function createSandboxProvider(config) {
|
|
|
23607
23891
|
volumeName: config.daytonaVolumeName
|
|
23608
23892
|
});
|
|
23609
23893
|
}
|
|
23894
|
+
case "local": {
|
|
23895
|
+
return new LocalSandboxProvider({ basePath: config.localSandboxBasePath });
|
|
23896
|
+
}
|
|
23610
23897
|
default: {
|
|
23611
23898
|
const exhaustiveCheck = config.type;
|
|
23612
23899
|
throw new Error(`Unknown sandbox provider type: ${exhaustiveCheck}`);
|
|
@@ -23897,6 +24184,8 @@ export {
|
|
|
23897
24184
|
InMemoryUserStore,
|
|
23898
24185
|
InMemoryUserTenantLinkStore,
|
|
23899
24186
|
LINE_NUMBER_WIDTH,
|
|
24187
|
+
LocalSandboxInstance,
|
|
24188
|
+
LocalSandboxProvider,
|
|
23900
24189
|
LoggerLatticeManager,
|
|
23901
24190
|
MAX_LINE_LENGTH,
|
|
23902
24191
|
McpLatticeManager,
|