@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.js
CHANGED
|
@@ -758,8 +758,8 @@ function buildReducer(kind) {
|
|
|
758
758
|
return (_prev, next) => next;
|
|
759
759
|
}
|
|
760
760
|
}
|
|
761
|
-
function resolvePath(obj,
|
|
762
|
-
const cleanPath =
|
|
761
|
+
function resolvePath(obj, path5) {
|
|
762
|
+
const cleanPath = path5.startsWith("state.") ? path5.slice(6) : path5;
|
|
763
763
|
const parts = cleanPath.split(/\.|\[|\]\.?/).filter(Boolean);
|
|
764
764
|
let current = obj;
|
|
765
765
|
for (const part of parts) {
|
|
@@ -1571,6 +1571,8 @@ __export(index_exports, {
|
|
|
1571
1571
|
InMemoryUserStore: () => InMemoryUserStore,
|
|
1572
1572
|
InMemoryUserTenantLinkStore: () => InMemoryUserTenantLinkStore,
|
|
1573
1573
|
LINE_NUMBER_WIDTH: () => LINE_NUMBER_WIDTH,
|
|
1574
|
+
LocalSandboxInstance: () => LocalSandboxInstance,
|
|
1575
|
+
LocalSandboxProvider: () => LocalSandboxProvider,
|
|
1574
1576
|
LoggerLatticeManager: () => LoggerLatticeManager,
|
|
1575
1577
|
MAX_LINE_LENGTH: () => MAX_LINE_LENGTH,
|
|
1576
1578
|
McpLatticeManager: () => McpLatticeManager,
|
|
@@ -4204,7 +4206,7 @@ var InMemoryBindingStore = class {
|
|
|
4204
4206
|
* @returns Array of matching {@link Binding} objects
|
|
4205
4207
|
*/
|
|
4206
4208
|
async list(params) {
|
|
4207
|
-
|
|
4209
|
+
const results = Array.from(this.bindings.values()).filter((b) => {
|
|
4208
4210
|
if (b.tenantId !== params.tenantId) return false;
|
|
4209
4211
|
if (params.channel && b.channel !== params.channel) return false;
|
|
4210
4212
|
if (params.agentId && b.agentId !== params.agentId) return false;
|
|
@@ -7456,9 +7458,9 @@ var VolumeFilesystem = class {
|
|
|
7456
7458
|
this.client = client;
|
|
7457
7459
|
this.mountPrefix = mountPrefix;
|
|
7458
7460
|
}
|
|
7459
|
-
async lsInfo(
|
|
7460
|
-
console.log(`[VolumeFilesystem.lsInfo] path=${
|
|
7461
|
-
const entries = await this.client.list(
|
|
7461
|
+
async lsInfo(path5) {
|
|
7462
|
+
console.log(`[VolumeFilesystem.lsInfo] path=${path5} mountPrefix=${this.mountPrefix}`);
|
|
7463
|
+
const entries = await this.client.list(path5);
|
|
7462
7464
|
console.log(`[VolumeFilesystem.lsInfo] got ${entries.length} entries`);
|
|
7463
7465
|
const prefix = this.mountPrefix.endsWith("/") ? this.mountPrefix : this.mountPrefix + "/";
|
|
7464
7466
|
return entries.map((entry) => ({
|
|
@@ -9768,8 +9770,8 @@ function truncateIfTooLong(result) {
|
|
|
9768
9770
|
}
|
|
9769
9771
|
return result;
|
|
9770
9772
|
}
|
|
9771
|
-
function validatePath(
|
|
9772
|
-
const pathStr =
|
|
9773
|
+
function validatePath(path5) {
|
|
9774
|
+
const pathStr = path5 || "/";
|
|
9773
9775
|
if (!pathStr || pathStr.trim() === "") {
|
|
9774
9776
|
throw new Error("Path cannot be empty");
|
|
9775
9777
|
}
|
|
@@ -9786,10 +9788,10 @@ function validatePath(path3) {
|
|
|
9786
9788
|
}
|
|
9787
9789
|
return normalized;
|
|
9788
9790
|
}
|
|
9789
|
-
function globSearchFiles(files, pattern,
|
|
9791
|
+
function globSearchFiles(files, pattern, path5 = "/") {
|
|
9790
9792
|
let normalizedPath;
|
|
9791
9793
|
try {
|
|
9792
|
-
normalizedPath = validatePath(
|
|
9794
|
+
normalizedPath = validatePath(path5);
|
|
9793
9795
|
} catch {
|
|
9794
9796
|
return "No files found";
|
|
9795
9797
|
}
|
|
@@ -9841,7 +9843,7 @@ function formatGrepResults(results, outputMode) {
|
|
|
9841
9843
|
}
|
|
9842
9844
|
return lines.join("\n");
|
|
9843
9845
|
}
|
|
9844
|
-
function grepSearchFiles(files, pattern,
|
|
9846
|
+
function grepSearchFiles(files, pattern, path5 = null, glob = null, outputMode = "files_with_matches") {
|
|
9845
9847
|
let regex;
|
|
9846
9848
|
try {
|
|
9847
9849
|
regex = new RegExp(pattern);
|
|
@@ -9850,7 +9852,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
|
|
|
9850
9852
|
}
|
|
9851
9853
|
let normalizedPath;
|
|
9852
9854
|
try {
|
|
9853
|
-
normalizedPath = validatePath(
|
|
9855
|
+
normalizedPath = validatePath(path5);
|
|
9854
9856
|
} catch {
|
|
9855
9857
|
return "No matches found";
|
|
9856
9858
|
}
|
|
@@ -9882,7 +9884,7 @@ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode =
|
|
|
9882
9884
|
}
|
|
9883
9885
|
return formatGrepResults(results, outputMode);
|
|
9884
9886
|
}
|
|
9885
|
-
function grepMatchesFromFiles(files, pattern,
|
|
9887
|
+
function grepMatchesFromFiles(files, pattern, path5 = null, glob = null) {
|
|
9886
9888
|
let regex;
|
|
9887
9889
|
try {
|
|
9888
9890
|
regex = new RegExp(pattern);
|
|
@@ -9891,7 +9893,7 @@ function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
|
|
|
9891
9893
|
}
|
|
9892
9894
|
let normalizedPath;
|
|
9893
9895
|
try {
|
|
9894
|
-
normalizedPath = validatePath(
|
|
9896
|
+
normalizedPath = validatePath(path5);
|
|
9895
9897
|
} catch {
|
|
9896
9898
|
return [];
|
|
9897
9899
|
}
|
|
@@ -9952,11 +9954,11 @@ var StateBackend = class {
|
|
|
9952
9954
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
9953
9955
|
* Directories have a trailing / in their path and is_dir=true.
|
|
9954
9956
|
*/
|
|
9955
|
-
lsInfo(
|
|
9957
|
+
lsInfo(path5) {
|
|
9956
9958
|
const files = this.getFiles();
|
|
9957
9959
|
const infos = [];
|
|
9958
9960
|
const subdirs = /* @__PURE__ */ new Set();
|
|
9959
|
-
const normalizedPath =
|
|
9961
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
9960
9962
|
for (const [k, fd] of Object.entries(files)) {
|
|
9961
9963
|
if (!k.startsWith(normalizedPath)) {
|
|
9962
9964
|
continue;
|
|
@@ -10062,16 +10064,16 @@ var StateBackend = class {
|
|
|
10062
10064
|
/**
|
|
10063
10065
|
* Structured search results or error string for invalid input.
|
|
10064
10066
|
*/
|
|
10065
|
-
grepRaw(pattern,
|
|
10067
|
+
grepRaw(pattern, path5 = "/", glob = null) {
|
|
10066
10068
|
const files = this.getFiles();
|
|
10067
|
-
return grepMatchesFromFiles(files, pattern,
|
|
10069
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
10068
10070
|
}
|
|
10069
10071
|
/**
|
|
10070
10072
|
* Structured glob matching returning FileInfo objects.
|
|
10071
10073
|
*/
|
|
10072
|
-
globInfo(pattern,
|
|
10074
|
+
globInfo(pattern, path5 = "/") {
|
|
10073
10075
|
const files = this.getFiles();
|
|
10074
|
-
const result = globSearchFiles(files, pattern,
|
|
10076
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
10075
10077
|
if (result === "No files found") {
|
|
10076
10078
|
return [];
|
|
10077
10079
|
}
|
|
@@ -10165,10 +10167,10 @@ function createLsTool(backend, options) {
|
|
|
10165
10167
|
...runConfig
|
|
10166
10168
|
};
|
|
10167
10169
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
10168
|
-
const
|
|
10169
|
-
const infos = await resolvedBackend.lsInfo(
|
|
10170
|
+
const path5 = input.path || "/";
|
|
10171
|
+
const infos = await resolvedBackend.lsInfo(path5);
|
|
10170
10172
|
if (infos.length === 0) {
|
|
10171
|
-
return `No files found in ${
|
|
10173
|
+
return `No files found in ${path5}`;
|
|
10172
10174
|
}
|
|
10173
10175
|
const lines = [];
|
|
10174
10176
|
for (const info of infos) {
|
|
@@ -10311,8 +10313,8 @@ function createGlobTool(backend, options) {
|
|
|
10311
10313
|
...runConfig
|
|
10312
10314
|
};
|
|
10313
10315
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
10314
|
-
const { pattern, path:
|
|
10315
|
-
const infos = await resolvedBackend.globInfo(pattern,
|
|
10316
|
+
const { pattern, path: path5 = "/" } = input;
|
|
10317
|
+
const infos = await resolvedBackend.globInfo(pattern, path5);
|
|
10316
10318
|
if (infos.length === 0) {
|
|
10317
10319
|
return `No files found matching pattern '${pattern}'`;
|
|
10318
10320
|
}
|
|
@@ -10339,8 +10341,8 @@ function createGrepTool(backend, options) {
|
|
|
10339
10341
|
...runConfig
|
|
10340
10342
|
};
|
|
10341
10343
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
10342
|
-
const { pattern, path:
|
|
10343
|
-
const result = await resolvedBackend.grepRaw(pattern,
|
|
10344
|
+
const { pattern, path: path5 = "/", glob = null } = input;
|
|
10345
|
+
const result = await resolvedBackend.grepRaw(pattern, path5, glob);
|
|
10344
10346
|
if (typeof result === "string") {
|
|
10345
10347
|
return result;
|
|
10346
10348
|
}
|
|
@@ -14447,8 +14449,7 @@ var Agent = class {
|
|
|
14447
14449
|
if (signal?.aborted) {
|
|
14448
14450
|
throw new Error("Agent execution was aborted");
|
|
14449
14451
|
}
|
|
14450
|
-
|
|
14451
|
-
result = await runnable_agent.invoke(
|
|
14452
|
+
const result = await runnable_agent.invoke(
|
|
14452
14453
|
inputMessage.command ? new import_langgraph6.Command(inputMessage.command) : { ...rest, messages, "x-tenant-id": this.tenant_id },
|
|
14453
14454
|
{
|
|
14454
14455
|
context: { runConfig },
|
|
@@ -14807,7 +14808,7 @@ var Agent = class {
|
|
|
14807
14808
|
includeTypes: ["ai", "human", "tool"]
|
|
14808
14809
|
//["human", "ai", "tool"],
|
|
14809
14810
|
});
|
|
14810
|
-
|
|
14811
|
+
const messagesArray = filteredMessages.map((message) => ({
|
|
14811
14812
|
id: message.id,
|
|
14812
14813
|
role: message.getType(),
|
|
14813
14814
|
content: message.content,
|
|
@@ -15888,12 +15889,12 @@ var AgentManager = class _AgentManager {
|
|
|
15888
15889
|
return _AgentManager.instance;
|
|
15889
15890
|
}
|
|
15890
15891
|
callAgentInQueue(queue, return_agent_state) {
|
|
15891
|
-
return new Promise((
|
|
15892
|
+
return new Promise((resolve4, reject) => {
|
|
15892
15893
|
const callback_event = `${queue.assistant_id}::${queue.thread_id}`;
|
|
15893
15894
|
if (return_agent_state) {
|
|
15894
15895
|
event_bus_default.subscribeOnce(callback_event, (data) => {
|
|
15895
15896
|
if (data.success) {
|
|
15896
|
-
|
|
15897
|
+
resolve4(data.state);
|
|
15897
15898
|
} else {
|
|
15898
15899
|
reject(data.error);
|
|
15899
15900
|
}
|
|
@@ -15908,7 +15909,7 @@ var AgentManager = class _AgentManager {
|
|
|
15908
15909
|
},
|
|
15909
15910
|
true
|
|
15910
15911
|
);
|
|
15911
|
-
!return_agent_state &&
|
|
15912
|
+
!return_agent_state && resolve4({ callback_event_id: callback_event, success: true });
|
|
15912
15913
|
} catch (error) {
|
|
15913
15914
|
!return_agent_state && reject({
|
|
15914
15915
|
callback_event_id: callback_event,
|
|
@@ -16804,13 +16805,13 @@ var StoreBackend = class {
|
|
|
16804
16805
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
16805
16806
|
* Directories have a trailing / in their path and is_dir=true.
|
|
16806
16807
|
*/
|
|
16807
|
-
async lsInfo(
|
|
16808
|
+
async lsInfo(path5) {
|
|
16808
16809
|
const store = this.getStore();
|
|
16809
16810
|
const namespace = this.getNamespace();
|
|
16810
16811
|
const items = await this.searchStorePaginated(store, namespace);
|
|
16811
16812
|
const infos = [];
|
|
16812
16813
|
const subdirs = /* @__PURE__ */ new Set();
|
|
16813
|
-
const normalizedPath =
|
|
16814
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
16814
16815
|
for (const item of items) {
|
|
16815
16816
|
const itemKey = String(item.key);
|
|
16816
16817
|
if (!itemKey.startsWith(normalizedPath)) {
|
|
@@ -16928,7 +16929,7 @@ var StoreBackend = class {
|
|
|
16928
16929
|
/**
|
|
16929
16930
|
* Structured search results or error string for invalid input.
|
|
16930
16931
|
*/
|
|
16931
|
-
async grepRaw(pattern,
|
|
16932
|
+
async grepRaw(pattern, path5 = "/", glob = null) {
|
|
16932
16933
|
const store = this.getStore();
|
|
16933
16934
|
const namespace = this.getNamespace();
|
|
16934
16935
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -16940,12 +16941,12 @@ var StoreBackend = class {
|
|
|
16940
16941
|
continue;
|
|
16941
16942
|
}
|
|
16942
16943
|
}
|
|
16943
|
-
return grepMatchesFromFiles(files, pattern,
|
|
16944
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
16944
16945
|
}
|
|
16945
16946
|
/**
|
|
16946
16947
|
* Structured glob matching returning FileInfo objects.
|
|
16947
16948
|
*/
|
|
16948
|
-
async globInfo(pattern,
|
|
16949
|
+
async globInfo(pattern, path5 = "/") {
|
|
16949
16950
|
const store = this.getStore();
|
|
16950
16951
|
const namespace = this.getNamespace();
|
|
16951
16952
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -16957,7 +16958,7 @@ var StoreBackend = class {
|
|
|
16957
16958
|
continue;
|
|
16958
16959
|
}
|
|
16959
16960
|
}
|
|
16960
|
-
const result = globSearchFiles(files, pattern,
|
|
16961
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
16961
16962
|
if (result === "No files found") {
|
|
16962
16963
|
return [];
|
|
16963
16964
|
}
|
|
@@ -17042,8 +17043,8 @@ var FilesystemBackend = class {
|
|
|
17042
17043
|
async lsInfo(dirPath) {
|
|
17043
17044
|
try {
|
|
17044
17045
|
const resolvedPath = this.resolvePath(dirPath);
|
|
17045
|
-
const
|
|
17046
|
-
if (!
|
|
17046
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
17047
|
+
if (!stat4.isDirectory()) {
|
|
17047
17048
|
return [];
|
|
17048
17049
|
}
|
|
17049
17050
|
const entries = await fs2.readdir(resolvedPath, { withFileTypes: true });
|
|
@@ -17122,8 +17123,8 @@ var FilesystemBackend = class {
|
|
|
17122
17123
|
const resolvedPath = this.resolvePath(filePath);
|
|
17123
17124
|
let content;
|
|
17124
17125
|
if (SUPPORTS_NOFOLLOW) {
|
|
17125
|
-
const
|
|
17126
|
-
if (!
|
|
17126
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
17127
|
+
if (!stat4.isFile()) {
|
|
17127
17128
|
return `Error: File '${filePath}' not found`;
|
|
17128
17129
|
}
|
|
17129
17130
|
const fd = await fs2.open(
|
|
@@ -17136,11 +17137,11 @@ var FilesystemBackend = class {
|
|
|
17136
17137
|
await fd.close();
|
|
17137
17138
|
}
|
|
17138
17139
|
} else {
|
|
17139
|
-
const
|
|
17140
|
-
if (
|
|
17140
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
17141
|
+
if (stat4.isSymbolicLink()) {
|
|
17141
17142
|
return `Error: Symlinks are not allowed: ${filePath}`;
|
|
17142
17143
|
}
|
|
17143
|
-
if (!
|
|
17144
|
+
if (!stat4.isFile()) {
|
|
17144
17145
|
return `Error: File '${filePath}' not found`;
|
|
17145
17146
|
}
|
|
17146
17147
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
@@ -17170,10 +17171,10 @@ var FilesystemBackend = class {
|
|
|
17170
17171
|
async readRaw(filePath) {
|
|
17171
17172
|
const resolvedPath = this.resolvePath(filePath);
|
|
17172
17173
|
let content;
|
|
17173
|
-
let
|
|
17174
|
+
let stat4;
|
|
17174
17175
|
if (SUPPORTS_NOFOLLOW) {
|
|
17175
|
-
|
|
17176
|
-
if (!
|
|
17176
|
+
stat4 = await fs2.stat(resolvedPath);
|
|
17177
|
+
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
17177
17178
|
const fd = await fs2.open(
|
|
17178
17179
|
resolvedPath,
|
|
17179
17180
|
fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW
|
|
@@ -17184,17 +17185,17 @@ var FilesystemBackend = class {
|
|
|
17184
17185
|
await fd.close();
|
|
17185
17186
|
}
|
|
17186
17187
|
} else {
|
|
17187
|
-
|
|
17188
|
-
if (
|
|
17188
|
+
stat4 = await fs2.lstat(resolvedPath);
|
|
17189
|
+
if (stat4.isSymbolicLink()) {
|
|
17189
17190
|
throw new Error(`Symlinks are not allowed: ${filePath}`);
|
|
17190
17191
|
}
|
|
17191
|
-
if (!
|
|
17192
|
+
if (!stat4.isFile()) throw new Error(`File '${filePath}' not found`);
|
|
17192
17193
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
17193
17194
|
}
|
|
17194
17195
|
return {
|
|
17195
17196
|
content: content.split("\n"),
|
|
17196
|
-
created_at:
|
|
17197
|
-
modified_at:
|
|
17197
|
+
created_at: stat4.ctime.toISOString(),
|
|
17198
|
+
modified_at: stat4.mtime.toISOString()
|
|
17198
17199
|
};
|
|
17199
17200
|
}
|
|
17200
17201
|
/**
|
|
@@ -17205,8 +17206,8 @@ var FilesystemBackend = class {
|
|
|
17205
17206
|
try {
|
|
17206
17207
|
const resolvedPath = this.resolvePath(filePath);
|
|
17207
17208
|
try {
|
|
17208
|
-
const
|
|
17209
|
-
if (
|
|
17209
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
17210
|
+
if (stat4.isSymbolicLink()) {
|
|
17210
17211
|
return {
|
|
17211
17212
|
error: `Cannot write to ${filePath} because it is a symlink. Symlinks are not allowed.`
|
|
17212
17213
|
};
|
|
@@ -17242,8 +17243,8 @@ var FilesystemBackend = class {
|
|
|
17242
17243
|
const resolvedPath = this.resolvePath(filePath);
|
|
17243
17244
|
let content;
|
|
17244
17245
|
if (SUPPORTS_NOFOLLOW) {
|
|
17245
|
-
const
|
|
17246
|
-
if (!
|
|
17246
|
+
const stat4 = await fs2.stat(resolvedPath);
|
|
17247
|
+
if (!stat4.isFile()) {
|
|
17247
17248
|
return { error: `Error: File '${filePath}' not found` };
|
|
17248
17249
|
}
|
|
17249
17250
|
const fd = await fs2.open(
|
|
@@ -17256,11 +17257,11 @@ var FilesystemBackend = class {
|
|
|
17256
17257
|
await fd.close();
|
|
17257
17258
|
}
|
|
17258
17259
|
} else {
|
|
17259
|
-
const
|
|
17260
|
-
if (
|
|
17260
|
+
const stat4 = await fs2.lstat(resolvedPath);
|
|
17261
|
+
if (stat4.isSymbolicLink()) {
|
|
17261
17262
|
return { error: `Error: Symlinks are not allowed: ${filePath}` };
|
|
17262
17263
|
}
|
|
17263
|
-
if (!
|
|
17264
|
+
if (!stat4.isFile()) {
|
|
17264
17265
|
return { error: `Error: File '${filePath}' not found` };
|
|
17265
17266
|
}
|
|
17266
17267
|
content = await fs2.readFile(resolvedPath, "utf-8");
|
|
@@ -17328,7 +17329,7 @@ var FilesystemBackend = class {
|
|
|
17328
17329
|
* Returns null if ripgrep is not available or fails.
|
|
17329
17330
|
*/
|
|
17330
17331
|
async ripgrepSearch(pattern, baseFull, includeGlob) {
|
|
17331
|
-
return new Promise((
|
|
17332
|
+
return new Promise((resolve4) => {
|
|
17332
17333
|
const args = ["--json"];
|
|
17333
17334
|
if (includeGlob) {
|
|
17334
17335
|
args.push("--glob", includeGlob);
|
|
@@ -17342,7 +17343,7 @@ var FilesystemBackend = class {
|
|
|
17342
17343
|
});
|
|
17343
17344
|
proc.on("close", (code) => {
|
|
17344
17345
|
if (code !== 0 && code !== 1) {
|
|
17345
|
-
|
|
17346
|
+
resolve4(null);
|
|
17346
17347
|
return;
|
|
17347
17348
|
}
|
|
17348
17349
|
for (const line of output.split("\n")) {
|
|
@@ -17378,10 +17379,10 @@ var FilesystemBackend = class {
|
|
|
17378
17379
|
continue;
|
|
17379
17380
|
}
|
|
17380
17381
|
}
|
|
17381
|
-
|
|
17382
|
+
resolve4(results);
|
|
17382
17383
|
});
|
|
17383
17384
|
proc.on("error", () => {
|
|
17384
|
-
|
|
17385
|
+
resolve4(null);
|
|
17385
17386
|
});
|
|
17386
17387
|
});
|
|
17387
17388
|
}
|
|
@@ -17396,8 +17397,8 @@ var FilesystemBackend = class {
|
|
|
17396
17397
|
return {};
|
|
17397
17398
|
}
|
|
17398
17399
|
const results = {};
|
|
17399
|
-
const
|
|
17400
|
-
const root =
|
|
17400
|
+
const stat4 = await fs2.stat(baseFull);
|
|
17401
|
+
const root = stat4.isDirectory() ? baseFull : path2.dirname(baseFull);
|
|
17401
17402
|
const files = await (0, import_fast_glob.default)("**/*", {
|
|
17402
17403
|
cwd: root,
|
|
17403
17404
|
absolute: true,
|
|
@@ -17409,8 +17410,8 @@ var FilesystemBackend = class {
|
|
|
17409
17410
|
if (includeGlob && !import_micromatch2.default.isMatch(path2.basename(fp), includeGlob)) {
|
|
17410
17411
|
continue;
|
|
17411
17412
|
}
|
|
17412
|
-
const
|
|
17413
|
-
if (
|
|
17413
|
+
const stat5 = await fs2.stat(fp);
|
|
17414
|
+
if (stat5.size > this.maxFileSizeBytes) {
|
|
17414
17415
|
continue;
|
|
17415
17416
|
}
|
|
17416
17417
|
const content = await fs2.readFile(fp, "utf-8");
|
|
@@ -17452,8 +17453,8 @@ var FilesystemBackend = class {
|
|
|
17452
17453
|
}
|
|
17453
17454
|
const resolvedSearchPath = searchPath === "/" ? this.cwd : this.resolvePath(searchPath);
|
|
17454
17455
|
try {
|
|
17455
|
-
const
|
|
17456
|
-
if (!
|
|
17456
|
+
const stat4 = await fs2.stat(resolvedSearchPath);
|
|
17457
|
+
if (!stat4.isDirectory()) {
|
|
17457
17458
|
return [];
|
|
17458
17459
|
}
|
|
17459
17460
|
} catch {
|
|
@@ -17469,15 +17470,15 @@ var FilesystemBackend = class {
|
|
|
17469
17470
|
});
|
|
17470
17471
|
for (const matchedPath of matches) {
|
|
17471
17472
|
try {
|
|
17472
|
-
const
|
|
17473
|
-
if (!
|
|
17473
|
+
const stat4 = await fs2.stat(matchedPath);
|
|
17474
|
+
if (!stat4.isFile()) continue;
|
|
17474
17475
|
const normalizedPath = matchedPath.split("/").join(path2.sep);
|
|
17475
17476
|
if (!this.virtualMode) {
|
|
17476
17477
|
results.push({
|
|
17477
17478
|
path: normalizedPath,
|
|
17478
17479
|
is_dir: false,
|
|
17479
|
-
size:
|
|
17480
|
-
modified_at:
|
|
17480
|
+
size: stat4.size,
|
|
17481
|
+
modified_at: stat4.mtime.toISOString()
|
|
17481
17482
|
});
|
|
17482
17483
|
} else {
|
|
17483
17484
|
const cwdStr = this.cwd.endsWith(path2.sep) ? this.cwd : this.cwd + path2.sep;
|
|
@@ -17494,8 +17495,8 @@ var FilesystemBackend = class {
|
|
|
17494
17495
|
results.push({
|
|
17495
17496
|
path: virt,
|
|
17496
17497
|
is_dir: false,
|
|
17497
|
-
size:
|
|
17498
|
-
modified_at:
|
|
17498
|
+
size: stat4.size,
|
|
17499
|
+
modified_at: stat4.mtime.toISOString()
|
|
17499
17500
|
});
|
|
17500
17501
|
}
|
|
17501
17502
|
} catch {
|
|
@@ -17542,10 +17543,10 @@ var CompositeBackend = class {
|
|
|
17542
17543
|
* @returns List of FileInfo objects with route prefixes added, for files and directories
|
|
17543
17544
|
* directly in the directory. Directories have a trailing / in their path and is_dir=true.
|
|
17544
17545
|
*/
|
|
17545
|
-
async lsInfo(
|
|
17546
|
+
async lsInfo(path5) {
|
|
17546
17547
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
17547
|
-
if (
|
|
17548
|
-
const suffix =
|
|
17548
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
17549
|
+
const suffix = path5.substring(routePrefix.length);
|
|
17549
17550
|
const searchPath = suffix ? "/" + suffix : "/";
|
|
17550
17551
|
const infos = await backend.lsInfo(searchPath);
|
|
17551
17552
|
const prefixed = [];
|
|
@@ -17558,9 +17559,9 @@ var CompositeBackend = class {
|
|
|
17558
17559
|
return prefixed;
|
|
17559
17560
|
}
|
|
17560
17561
|
}
|
|
17561
|
-
if (
|
|
17562
|
+
if (path5 === "/") {
|
|
17562
17563
|
const results = [];
|
|
17563
|
-
const defaultInfos = await this.default.lsInfo(
|
|
17564
|
+
const defaultInfos = await this.default.lsInfo(path5);
|
|
17564
17565
|
results.push(...defaultInfos);
|
|
17565
17566
|
for (const [routePrefix] of this.sortedRoutes) {
|
|
17566
17567
|
results.push({
|
|
@@ -17573,7 +17574,7 @@ var CompositeBackend = class {
|
|
|
17573
17574
|
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
17574
17575
|
return results;
|
|
17575
17576
|
}
|
|
17576
|
-
return await this.default.lsInfo(
|
|
17577
|
+
return await this.default.lsInfo(path5);
|
|
17577
17578
|
}
|
|
17578
17579
|
/**
|
|
17579
17580
|
* Read file content, routing to appropriate backend.
|
|
@@ -17600,10 +17601,10 @@ var CompositeBackend = class {
|
|
|
17600
17601
|
/**
|
|
17601
17602
|
* Structured search results or error string for invalid input.
|
|
17602
17603
|
*/
|
|
17603
|
-
async grepRaw(pattern,
|
|
17604
|
+
async grepRaw(pattern, path5 = "/", glob = null) {
|
|
17604
17605
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
17605
|
-
if (
|
|
17606
|
-
const searchPath =
|
|
17606
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
17607
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
17607
17608
|
const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
|
|
17608
17609
|
if (typeof raw === "string") {
|
|
17609
17610
|
return raw;
|
|
@@ -17615,7 +17616,7 @@ var CompositeBackend = class {
|
|
|
17615
17616
|
}
|
|
17616
17617
|
}
|
|
17617
17618
|
const allMatches = [];
|
|
17618
|
-
const rawDefault = await this.default.grepRaw(pattern,
|
|
17619
|
+
const rawDefault = await this.default.grepRaw(pattern, path5, glob);
|
|
17619
17620
|
if (typeof rawDefault === "string") {
|
|
17620
17621
|
return rawDefault;
|
|
17621
17622
|
}
|
|
@@ -17637,11 +17638,11 @@ var CompositeBackend = class {
|
|
|
17637
17638
|
/**
|
|
17638
17639
|
* Structured glob matching returning FileInfo objects.
|
|
17639
17640
|
*/
|
|
17640
|
-
async globInfo(pattern,
|
|
17641
|
+
async globInfo(pattern, path5 = "/") {
|
|
17641
17642
|
const results = [];
|
|
17642
17643
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
17643
|
-
if (
|
|
17644
|
-
const searchPath =
|
|
17644
|
+
if (path5.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
17645
|
+
const searchPath = path5.substring(routePrefix.length - 1);
|
|
17645
17646
|
const infos = await backend.globInfo(pattern, searchPath || "/");
|
|
17646
17647
|
return infos.map((fi) => ({
|
|
17647
17648
|
...fi,
|
|
@@ -17649,7 +17650,7 @@ var CompositeBackend = class {
|
|
|
17649
17650
|
}));
|
|
17650
17651
|
}
|
|
17651
17652
|
}
|
|
17652
|
-
const defaultInfos = await this.default.globInfo(pattern,
|
|
17653
|
+
const defaultInfos = await this.default.globInfo(pattern, path5);
|
|
17653
17654
|
results.push(...defaultInfos);
|
|
17654
17655
|
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
17655
17656
|
const infos = await backend.globInfo(pattern, "/");
|
|
@@ -17697,11 +17698,11 @@ var MemoryBackend = class {
|
|
|
17697
17698
|
getFiles() {
|
|
17698
17699
|
return Object.fromEntries(this.files);
|
|
17699
17700
|
}
|
|
17700
|
-
lsInfo(
|
|
17701
|
+
lsInfo(path5) {
|
|
17701
17702
|
const files = this.getFiles();
|
|
17702
17703
|
const infos = [];
|
|
17703
17704
|
const subdirs = /* @__PURE__ */ new Set();
|
|
17704
|
-
const normalizedPath =
|
|
17705
|
+
const normalizedPath = path5.endsWith("/") ? path5 : path5 + "/";
|
|
17705
17706
|
for (const [k, fd] of Object.entries(files)) {
|
|
17706
17707
|
if (!k.startsWith(normalizedPath)) {
|
|
17707
17708
|
continue;
|
|
@@ -17776,13 +17777,13 @@ var MemoryBackend = class {
|
|
|
17776
17777
|
this.files.set(filePath, newFileData);
|
|
17777
17778
|
return { path: filePath, filesUpdate: null, occurrences };
|
|
17778
17779
|
}
|
|
17779
|
-
grepRaw(pattern,
|
|
17780
|
+
grepRaw(pattern, path5 = "/", glob = null) {
|
|
17780
17781
|
const files = this.getFiles();
|
|
17781
|
-
return grepMatchesFromFiles(files, pattern,
|
|
17782
|
+
return grepMatchesFromFiles(files, pattern, path5, glob);
|
|
17782
17783
|
}
|
|
17783
|
-
globInfo(pattern,
|
|
17784
|
+
globInfo(pattern, path5 = "/") {
|
|
17784
17785
|
const files = this.getFiles();
|
|
17785
|
-
const result = globSearchFiles(files, pattern,
|
|
17786
|
+
const result = globSearchFiles(files, pattern, path5);
|
|
17786
17787
|
if (result === "No files found") {
|
|
17787
17788
|
return [];
|
|
17788
17789
|
}
|
|
@@ -18829,16 +18830,16 @@ function createTeammateTools(options) {
|
|
|
18829
18830
|
update: { team_mailbox: relevantMsgs2, messages: [toolMessage2] }
|
|
18830
18831
|
});
|
|
18831
18832
|
}
|
|
18832
|
-
const messagePromise = new Promise((
|
|
18833
|
+
const messagePromise = new Promise((resolve4) => {
|
|
18833
18834
|
const handler = async (msg) => {
|
|
18834
18835
|
mailboxStore.offMessage(teamId, agentId, handler);
|
|
18835
18836
|
const allMsgs = await mailboxStore.getUnreadMessages(teamId, agentId);
|
|
18836
|
-
|
|
18837
|
+
resolve4(allMsgs);
|
|
18837
18838
|
};
|
|
18838
18839
|
mailboxStore.onMessage(teamId, agentId, handler);
|
|
18839
18840
|
});
|
|
18840
|
-
const timeoutPromise = new Promise((
|
|
18841
|
-
setTimeout(() =>
|
|
18841
|
+
const timeoutPromise = new Promise((resolve4) => {
|
|
18842
|
+
setTimeout(() => resolve4([]), READ_MESSAGES_TIMEOUT_MS2);
|
|
18842
18843
|
});
|
|
18843
18844
|
msgs = await Promise.race([messagePromise, timeoutPromise]);
|
|
18844
18845
|
mailboxStore.offMessage(teamId, agentId, () => {
|
|
@@ -19571,19 +19572,19 @@ Task Status Values:
|
|
|
19571
19572
|
update: { team_mailbox: allTeamMessages2, messages: [toolMessage2] }
|
|
19572
19573
|
});
|
|
19573
19574
|
}
|
|
19574
|
-
const messagePromise = new Promise((
|
|
19575
|
+
const messagePromise = new Promise((resolve4) => {
|
|
19575
19576
|
const handler = async (msg) => {
|
|
19576
19577
|
mailboxStore.offMessage(teamId, TEAM_LEAD_AGENT_ID, handler);
|
|
19577
19578
|
const allMsgs = await mailboxStore.getUnreadMessages(
|
|
19578
19579
|
teamId,
|
|
19579
19580
|
TEAM_LEAD_AGENT_ID
|
|
19580
19581
|
);
|
|
19581
|
-
|
|
19582
|
+
resolve4(allMsgs);
|
|
19582
19583
|
};
|
|
19583
19584
|
mailboxStore.onMessage(teamId, TEAM_LEAD_AGENT_ID, handler);
|
|
19584
19585
|
});
|
|
19585
|
-
const timeoutPromise = new Promise((
|
|
19586
|
-
setTimeout(() =>
|
|
19586
|
+
const timeoutPromise = new Promise((resolve4) => {
|
|
19587
|
+
setTimeout(() => resolve4([]), READ_MESSAGES_TIMEOUT_MS);
|
|
19587
19588
|
});
|
|
19588
19589
|
msgs = await Promise.race([messagePromise, timeoutPromise]);
|
|
19589
19590
|
mailboxStore.offMessage(
|
|
@@ -24056,10 +24057,10 @@ var MicrosandboxRemoteInstance = class {
|
|
|
24056
24057
|
content
|
|
24057
24058
|
);
|
|
24058
24059
|
},
|
|
24059
|
-
listPath: async (
|
|
24060
|
+
listPath: async (path5, options) => {
|
|
24060
24061
|
const result = await this.client.listPath(
|
|
24061
24062
|
this.name,
|
|
24062
|
-
normalizeExternalSandboxPath(
|
|
24063
|
+
normalizeExternalSandboxPath(path5),
|
|
24063
24064
|
options?.recursive
|
|
24064
24065
|
);
|
|
24065
24066
|
const files = result.entries.map((entry) => ({
|
|
@@ -24068,10 +24069,10 @@ var MicrosandboxRemoteInstance = class {
|
|
|
24068
24069
|
}));
|
|
24069
24070
|
return { files };
|
|
24070
24071
|
},
|
|
24071
|
-
findFiles: async (
|
|
24072
|
+
findFiles: async (path5, glob) => {
|
|
24072
24073
|
const result = await this.client.findFiles(
|
|
24073
24074
|
this.name,
|
|
24074
|
-
normalizeExternalSandboxPath(
|
|
24075
|
+
normalizeExternalSandboxPath(path5),
|
|
24075
24076
|
glob
|
|
24076
24077
|
);
|
|
24077
24078
|
return {
|
|
@@ -24113,15 +24114,15 @@ var MicrosandboxRemoteInstance = class {
|
|
|
24113
24114
|
}
|
|
24114
24115
|
return Buffer.from(result.content ?? "");
|
|
24115
24116
|
},
|
|
24116
|
-
deletePath: async (
|
|
24117
|
-
const resolved = normalizeExternalSandboxPath(
|
|
24117
|
+
deletePath: async (path5) => {
|
|
24118
|
+
const resolved = normalizeExternalSandboxPath(path5);
|
|
24118
24119
|
await this.client.execCommand({
|
|
24119
24120
|
sandboxName: this.name,
|
|
24120
24121
|
command: `rm -rf "${resolved}"`
|
|
24121
24122
|
});
|
|
24122
24123
|
},
|
|
24123
|
-
createDirectory: async (
|
|
24124
|
-
const resolved = normalizeExternalSandboxPath(
|
|
24124
|
+
createDirectory: async (path5) => {
|
|
24125
|
+
const resolved = normalizeExternalSandboxPath(path5);
|
|
24125
24126
|
await this.client.execCommand({
|
|
24126
24127
|
sandboxName: this.name,
|
|
24127
24128
|
command: `mkdir -p "${resolved}"`
|
|
@@ -24169,13 +24170,18 @@ var MicrosandboxServiceClient = class {
|
|
|
24169
24170
|
this.apiKey = config.apiKey;
|
|
24170
24171
|
}
|
|
24171
24172
|
async ensureSandbox(name, input) {
|
|
24173
|
+
const tStart = Date.now();
|
|
24172
24174
|
console.log(
|
|
24173
|
-
`[MicrosandboxClient] ensureSandbox name=${name} image=${input.image ?? "not set"} envKeys=${Object.keys(input.env ?? {}).join(",") || "none"}`
|
|
24175
|
+
`[MicrosandboxClient] ensureSandbox START name=${name} image=${input.image ?? "not set"} envKeys=${Object.keys(input.env ?? {}).join(",") || "none"}`
|
|
24174
24176
|
);
|
|
24175
|
-
|
|
24177
|
+
const result = await this.request(`/api/sandboxes/${encodeURIComponent(name)}`, {
|
|
24176
24178
|
method: "PUT",
|
|
24177
24179
|
body: input
|
|
24178
24180
|
});
|
|
24181
|
+
console.log(
|
|
24182
|
+
`[MicrosandboxClient] ensureSandbox DONE name=${name} status=${result.status} elapsed=${Date.now() - tStart}ms`
|
|
24183
|
+
);
|
|
24184
|
+
return result;
|
|
24179
24185
|
}
|
|
24180
24186
|
async startSandbox(name) {
|
|
24181
24187
|
return this.request(`/api/sandboxes/${encodeURIComponent(name)}/start`, {
|
|
@@ -24202,34 +24208,34 @@ var MicrosandboxServiceClient = class {
|
|
|
24202
24208
|
method: "GET"
|
|
24203
24209
|
});
|
|
24204
24210
|
}
|
|
24205
|
-
async readFile(sandboxName,
|
|
24211
|
+
async readFile(sandboxName, path5) {
|
|
24206
24212
|
return this.request("/api/files/read", {
|
|
24207
24213
|
method: "POST",
|
|
24208
|
-
body: { sandboxName, path:
|
|
24214
|
+
body: { sandboxName, path: path5 }
|
|
24209
24215
|
});
|
|
24210
24216
|
}
|
|
24211
|
-
async writeFile(sandboxName,
|
|
24217
|
+
async writeFile(sandboxName, path5, content) {
|
|
24212
24218
|
return this.request("/api/files/write", {
|
|
24213
24219
|
method: "POST",
|
|
24214
|
-
body: { sandboxName, path:
|
|
24220
|
+
body: { sandboxName, path: path5, content }
|
|
24215
24221
|
});
|
|
24216
24222
|
}
|
|
24217
|
-
async listPath(sandboxName,
|
|
24223
|
+
async listPath(sandboxName, path5, recursive) {
|
|
24218
24224
|
return this.request("/api/files/list", {
|
|
24219
24225
|
method: "POST",
|
|
24220
|
-
body: { sandboxName, path:
|
|
24226
|
+
body: { sandboxName, path: path5, recursive }
|
|
24221
24227
|
});
|
|
24222
24228
|
}
|
|
24223
|
-
async findFiles(sandboxName,
|
|
24229
|
+
async findFiles(sandboxName, path5, pattern) {
|
|
24224
24230
|
return this.request("/api/files/find", {
|
|
24225
24231
|
method: "POST",
|
|
24226
|
-
body: { sandboxName, path:
|
|
24232
|
+
body: { sandboxName, path: path5, pattern }
|
|
24227
24233
|
});
|
|
24228
24234
|
}
|
|
24229
|
-
async searchInFile(sandboxName,
|
|
24235
|
+
async searchInFile(sandboxName, path5, query) {
|
|
24230
24236
|
return this.request("/api/files/search", {
|
|
24231
24237
|
method: "POST",
|
|
24232
|
-
body: { sandboxName, path:
|
|
24238
|
+
body: { sandboxName, path: path5, query }
|
|
24233
24239
|
});
|
|
24234
24240
|
}
|
|
24235
24241
|
async replaceInFile(sandboxName, input) {
|
|
@@ -24238,14 +24244,14 @@ var MicrosandboxServiceClient = class {
|
|
|
24238
24244
|
body: { sandboxName, ...input }
|
|
24239
24245
|
});
|
|
24240
24246
|
}
|
|
24241
|
-
async uploadFile(sandboxName,
|
|
24247
|
+
async uploadFile(sandboxName, path5, content) {
|
|
24242
24248
|
return this.request("/api/files/upload", {
|
|
24243
24249
|
method: "POST",
|
|
24244
|
-
body: { sandboxName, path:
|
|
24250
|
+
body: { sandboxName, path: path5, contentBase64: content.toString("base64") }
|
|
24245
24251
|
});
|
|
24246
24252
|
}
|
|
24247
|
-
async downloadFile(sandboxName,
|
|
24248
|
-
const query = new URLSearchParams({ sandboxName, path:
|
|
24253
|
+
async downloadFile(sandboxName, path5) {
|
|
24254
|
+
const query = new URLSearchParams({ sandboxName, path: path5 });
|
|
24249
24255
|
return this.request(`/api/files/download?${query.toString()}`, {
|
|
24250
24256
|
method: "GET"
|
|
24251
24257
|
});
|
|
@@ -24256,32 +24262,32 @@ var MicrosandboxServiceClient = class {
|
|
|
24256
24262
|
body: input
|
|
24257
24263
|
});
|
|
24258
24264
|
}
|
|
24259
|
-
async volumeFsRead(volumeName,
|
|
24265
|
+
async volumeFsRead(volumeName, path5) {
|
|
24260
24266
|
const result = await this.request(
|
|
24261
24267
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/read`,
|
|
24262
24268
|
{
|
|
24263
24269
|
method: "POST",
|
|
24264
|
-
body: { path:
|
|
24270
|
+
body: { path: path5 }
|
|
24265
24271
|
}
|
|
24266
24272
|
);
|
|
24267
24273
|
return result.content;
|
|
24268
24274
|
}
|
|
24269
|
-
async volumeFsWrite(volumeName,
|
|
24275
|
+
async volumeFsWrite(volumeName, path5, content) {
|
|
24270
24276
|
await this.request(
|
|
24271
24277
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/write`,
|
|
24272
24278
|
{
|
|
24273
24279
|
method: "POST",
|
|
24274
|
-
body: { path:
|
|
24280
|
+
body: { path: path5, content }
|
|
24275
24281
|
}
|
|
24276
24282
|
);
|
|
24277
24283
|
}
|
|
24278
|
-
async volumeFsList(volumeName,
|
|
24279
|
-
console.log(`[volumeFsList] volume=${volumeName} path="${
|
|
24284
|
+
async volumeFsList(volumeName, path5) {
|
|
24285
|
+
console.log(`[volumeFsList] volume=${volumeName} path="${path5}" url=POST /api/volumes/${encodeURIComponent(volumeName)}/fs/list`);
|
|
24280
24286
|
const result = await this.request(
|
|
24281
24287
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/list`,
|
|
24282
24288
|
{
|
|
24283
24289
|
method: "POST",
|
|
24284
|
-
body: { path:
|
|
24290
|
+
body: { path: path5 }
|
|
24285
24291
|
}
|
|
24286
24292
|
);
|
|
24287
24293
|
console.log(
|
|
@@ -24290,25 +24296,25 @@ var MicrosandboxServiceClient = class {
|
|
|
24290
24296
|
);
|
|
24291
24297
|
return result.entries;
|
|
24292
24298
|
}
|
|
24293
|
-
async volumeFsDownload(volumeName,
|
|
24299
|
+
async volumeFsDownload(volumeName, path5) {
|
|
24294
24300
|
const result = await this.request(
|
|
24295
|
-
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(
|
|
24301
|
+
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path5)}`,
|
|
24296
24302
|
{
|
|
24297
24303
|
method: "GET"
|
|
24298
24304
|
}
|
|
24299
24305
|
);
|
|
24300
24306
|
return Buffer.from(result.contentBase64, "base64");
|
|
24301
24307
|
}
|
|
24302
|
-
async volumeFsUpload(volumeName,
|
|
24308
|
+
async volumeFsUpload(volumeName, path5, data) {
|
|
24303
24309
|
await this.request(
|
|
24304
24310
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/upload`,
|
|
24305
24311
|
{
|
|
24306
24312
|
method: "POST",
|
|
24307
|
-
body: { path:
|
|
24313
|
+
body: { path: path5, contentBase64: data.toString("base64") }
|
|
24308
24314
|
}
|
|
24309
24315
|
);
|
|
24310
24316
|
}
|
|
24311
|
-
async request(
|
|
24317
|
+
async request(path5, init) {
|
|
24312
24318
|
const headers = {};
|
|
24313
24319
|
if (init.body) {
|
|
24314
24320
|
headers["content-type"] = "application/json";
|
|
@@ -24316,7 +24322,7 @@ var MicrosandboxServiceClient = class {
|
|
|
24316
24322
|
if (this.apiKey) {
|
|
24317
24323
|
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
24318
24324
|
}
|
|
24319
|
-
const response = await fetch(`${this.baseURL}${
|
|
24325
|
+
const response = await fetch(`${this.baseURL}${path5}`, {
|
|
24320
24326
|
method: init.method,
|
|
24321
24327
|
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
24322
24328
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -24371,8 +24377,17 @@ var MicrosandboxRemoteProvider = class {
|
|
|
24371
24377
|
if (inFlight) {
|
|
24372
24378
|
return inFlight;
|
|
24373
24379
|
}
|
|
24380
|
+
const existing = this.instances.get(name);
|
|
24381
|
+
if (existing) {
|
|
24382
|
+
console.log(`[MicrosandboxRemote] createSandbox name=${name} INSTANCE_CACHE_HIT`);
|
|
24383
|
+
return existing;
|
|
24384
|
+
}
|
|
24374
24385
|
const creation = (async () => {
|
|
24375
|
-
|
|
24386
|
+
const tStart = Date.now();
|
|
24387
|
+
const input = this.buildEnsureInput(config);
|
|
24388
|
+
console.log(`[MicrosandboxRemote] createSandbox name=${name} calling ensureSandbox...`);
|
|
24389
|
+
await this.client.ensureSandbox(name, input);
|
|
24390
|
+
console.log(`[MicrosandboxRemote] createSandbox DONE name=${name} elapsed=${Date.now() - tStart}ms`);
|
|
24376
24391
|
const instance = new MicrosandboxRemoteInstance(name, this.client);
|
|
24377
24392
|
this.instances.set(name, instance);
|
|
24378
24393
|
return instance;
|
|
@@ -24408,11 +24423,11 @@ var MicrosandboxRemoteProvider = class {
|
|
|
24408
24423
|
}
|
|
24409
24424
|
createVolumeFsClient(volumeName, _pathPrefix) {
|
|
24410
24425
|
return {
|
|
24411
|
-
read: (
|
|
24412
|
-
write: (
|
|
24413
|
-
list: (
|
|
24414
|
-
readRaw: (
|
|
24415
|
-
writeRaw: (
|
|
24426
|
+
read: (path5) => this.client.volumeFsRead(volumeName, path5),
|
|
24427
|
+
write: (path5, content) => this.client.volumeFsWrite(volumeName, path5, content),
|
|
24428
|
+
list: (path5) => this.client.volumeFsList(volumeName, path5),
|
|
24429
|
+
readRaw: (path5) => this.client.volumeFsDownload(volumeName, path5),
|
|
24430
|
+
writeRaw: (path5, data) => this.client.volumeFsUpload(volumeName, path5, data)
|
|
24416
24431
|
};
|
|
24417
24432
|
}
|
|
24418
24433
|
async listSandboxes() {
|
|
@@ -24511,8 +24526,8 @@ var RemoteSandboxInstance = class {
|
|
|
24511
24526
|
throw new Error(`writeFile failed: ${extractFetcherError(result.error)}`);
|
|
24512
24527
|
}
|
|
24513
24528
|
},
|
|
24514
|
-
listPath: async (
|
|
24515
|
-
const resolved = this.resolvePath(
|
|
24529
|
+
listPath: async (path5, options) => {
|
|
24530
|
+
const resolved = this.resolvePath(path5);
|
|
24516
24531
|
const result = await this.client.file.listPath({
|
|
24517
24532
|
path: resolved,
|
|
24518
24533
|
recursive: options?.recursive ?? false
|
|
@@ -24528,8 +24543,8 @@ var RemoteSandboxInstance = class {
|
|
|
24528
24543
|
}));
|
|
24529
24544
|
return { files };
|
|
24530
24545
|
},
|
|
24531
|
-
findFiles: async (
|
|
24532
|
-
const resolved = this.resolvePath(
|
|
24546
|
+
findFiles: async (path5, glob) => {
|
|
24547
|
+
const resolved = this.resolvePath(path5);
|
|
24533
24548
|
const result = await this.client.file.findFiles({ path: resolved, glob });
|
|
24534
24549
|
if (!result.ok) {
|
|
24535
24550
|
throw new Error(`findFiles failed: ${extractFetcherError(result.error)}`);
|
|
@@ -24579,8 +24594,8 @@ var RemoteSandboxInstance = class {
|
|
|
24579
24594
|
const buffer2 = await result.body.arrayBuffer();
|
|
24580
24595
|
return Buffer.from(buffer2);
|
|
24581
24596
|
},
|
|
24582
|
-
deletePath: async (
|
|
24583
|
-
const resolved = this.resolvePath(
|
|
24597
|
+
deletePath: async (path5) => {
|
|
24598
|
+
const resolved = this.resolvePath(path5);
|
|
24584
24599
|
const result = await this.client.shell.execCommand({
|
|
24585
24600
|
command: `rm -rf "${resolved}"`
|
|
24586
24601
|
});
|
|
@@ -24588,8 +24603,8 @@ var RemoteSandboxInstance = class {
|
|
|
24588
24603
|
throw new Error(`deletePath failed: ${extractFetcherError(result.error)}`);
|
|
24589
24604
|
}
|
|
24590
24605
|
},
|
|
24591
|
-
createDirectory: async (
|
|
24592
|
-
const resolved = this.resolvePath(
|
|
24606
|
+
createDirectory: async (path5) => {
|
|
24607
|
+
const resolved = this.resolvePath(path5);
|
|
24593
24608
|
const result = await this.client.shell.execCommand({
|
|
24594
24609
|
command: `mkdir -p "${resolved}"`
|
|
24595
24610
|
});
|
|
@@ -24716,7 +24731,7 @@ var RemoteSandboxProvider = class {
|
|
|
24716
24731
|
}
|
|
24717
24732
|
createVolumeFsClient(_volumeName, pathPrefix) {
|
|
24718
24733
|
const workspace = this.workspace;
|
|
24719
|
-
const
|
|
24734
|
+
const resolve4 = (p) => {
|
|
24720
24735
|
if (!p || p === "/") {
|
|
24721
24736
|
if (pathPrefix) {
|
|
24722
24737
|
return `${workspace}${pathPrefix}`;
|
|
@@ -24736,23 +24751,23 @@ var RemoteSandboxProvider = class {
|
|
|
24736
24751
|
return `${workspace}/${p}`;
|
|
24737
24752
|
};
|
|
24738
24753
|
return {
|
|
24739
|
-
read: async (
|
|
24740
|
-
const resolved =
|
|
24754
|
+
read: async (path5) => {
|
|
24755
|
+
const resolved = resolve4(path5);
|
|
24741
24756
|
const result = await this.client.file.readFile({ file: resolved });
|
|
24742
24757
|
if (!result.ok) {
|
|
24743
24758
|
throw new Error(`Volume read failed: ${extractFetcherError(result.error)}`);
|
|
24744
24759
|
}
|
|
24745
24760
|
return result.body.data?.content ?? "";
|
|
24746
24761
|
},
|
|
24747
|
-
write: async (
|
|
24748
|
-
const resolved =
|
|
24762
|
+
write: async (path5, content) => {
|
|
24763
|
+
const resolved = resolve4(path5);
|
|
24749
24764
|
const result = await this.client.file.writeFile({ file: resolved, content });
|
|
24750
24765
|
if (!result.ok) {
|
|
24751
24766
|
throw new Error(`Volume write failed: ${extractFetcherError(result.error)}`);
|
|
24752
24767
|
}
|
|
24753
24768
|
},
|
|
24754
|
-
list: async (
|
|
24755
|
-
const resolved =
|
|
24769
|
+
list: async (path5) => {
|
|
24770
|
+
const resolved = resolve4(path5);
|
|
24756
24771
|
const result = await this.client.file.listPath({
|
|
24757
24772
|
path: resolved,
|
|
24758
24773
|
recursive: false
|
|
@@ -24769,8 +24784,8 @@ var RemoteSandboxProvider = class {
|
|
|
24769
24784
|
}));
|
|
24770
24785
|
return entries;
|
|
24771
24786
|
},
|
|
24772
|
-
readRaw: async (
|
|
24773
|
-
const resolved =
|
|
24787
|
+
readRaw: async (path5) => {
|
|
24788
|
+
const resolved = resolve4(path5);
|
|
24774
24789
|
const result = await this.client.file.downloadFile({ path: resolved });
|
|
24775
24790
|
if (!result.ok) {
|
|
24776
24791
|
throw new Error(`Volume download failed: ${extractFetcherError(result.error)}`);
|
|
@@ -24778,8 +24793,8 @@ var RemoteSandboxProvider = class {
|
|
|
24778
24793
|
const buffer2 = await result.body.arrayBuffer();
|
|
24779
24794
|
return Buffer.from(buffer2);
|
|
24780
24795
|
},
|
|
24781
|
-
writeRaw: async (
|
|
24782
|
-
const resolved =
|
|
24796
|
+
writeRaw: async (path5, data) => {
|
|
24797
|
+
const resolved = resolve4(path5);
|
|
24783
24798
|
const result = await this.client.file.uploadFile({
|
|
24784
24799
|
file: data,
|
|
24785
24800
|
path: resolved
|
|
@@ -24807,8 +24822,8 @@ var E2BInstance = class {
|
|
|
24807
24822
|
writeFile: async (file, content) => {
|
|
24808
24823
|
await this.native.files.write(file, content);
|
|
24809
24824
|
},
|
|
24810
|
-
listPath: async (
|
|
24811
|
-
const entries = await this.native.files.list(
|
|
24825
|
+
listPath: async (path5, options) => {
|
|
24826
|
+
const entries = await this.native.files.list(path5);
|
|
24812
24827
|
const files = entries.map((e) => ({
|
|
24813
24828
|
path: e.path,
|
|
24814
24829
|
is_dir: e.type === "dir",
|
|
@@ -24817,9 +24832,9 @@ var E2BInstance = class {
|
|
|
24817
24832
|
}));
|
|
24818
24833
|
return { files };
|
|
24819
24834
|
},
|
|
24820
|
-
findFiles: async (
|
|
24835
|
+
findFiles: async (path5, glob) => {
|
|
24821
24836
|
const result = await this.native.commands.run(
|
|
24822
|
-
`find "${
|
|
24837
|
+
`find "${path5}" -name "${glob}" -type f`
|
|
24823
24838
|
);
|
|
24824
24839
|
const lines = result.stdout.split("\n").filter(Boolean);
|
|
24825
24840
|
return { files: lines };
|
|
@@ -24842,13 +24857,13 @@ var E2BInstance = class {
|
|
|
24842
24857
|
return { matches, line_numbers };
|
|
24843
24858
|
},
|
|
24844
24859
|
strReplaceEditor: async (params) => {
|
|
24845
|
-
const { path:
|
|
24860
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
24846
24861
|
const delim = "#";
|
|
24847
24862
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
24848
24863
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
24849
24864
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
24850
24865
|
await this.native.commands.run(
|
|
24851
|
-
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
24866
|
+
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path5}"`
|
|
24852
24867
|
);
|
|
24853
24868
|
},
|
|
24854
24869
|
uploadFile: async (params) => {
|
|
@@ -24860,11 +24875,11 @@ var E2BInstance = class {
|
|
|
24860
24875
|
const data = await this.native.files.read(params.file, { format: "bytes" });
|
|
24861
24876
|
return Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
24862
24877
|
},
|
|
24863
|
-
deletePath: async (
|
|
24864
|
-
await this.native.commands.run(`rm -rf "${
|
|
24878
|
+
deletePath: async (path5) => {
|
|
24879
|
+
await this.native.commands.run(`rm -rf "${path5}"`);
|
|
24865
24880
|
},
|
|
24866
|
-
createDirectory: async (
|
|
24867
|
-
await this.native.commands.run(`mkdir -p "${
|
|
24881
|
+
createDirectory: async (path5) => {
|
|
24882
|
+
await this.native.commands.run(`mkdir -p "${path5}"`);
|
|
24868
24883
|
}
|
|
24869
24884
|
};
|
|
24870
24885
|
this.shell = {
|
|
@@ -24983,8 +24998,8 @@ var DaytonaInstance = class {
|
|
|
24983
24998
|
writeFile: async (file, content) => {
|
|
24984
24999
|
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
|
|
24985
25000
|
},
|
|
24986
|
-
listPath: async (
|
|
24987
|
-
const entries = await this.native.fs.listFiles(toRelativePath(
|
|
25001
|
+
listPath: async (path5, options) => {
|
|
25002
|
+
const entries = await this.native.fs.listFiles(toRelativePath(path5));
|
|
24988
25003
|
const files = entries.map((e) => {
|
|
24989
25004
|
const rawPath = e.name || "";
|
|
24990
25005
|
return {
|
|
@@ -24996,8 +25011,8 @@ var DaytonaInstance = class {
|
|
|
24996
25011
|
});
|
|
24997
25012
|
return { files };
|
|
24998
25013
|
},
|
|
24999
|
-
findFiles: async (
|
|
25000
|
-
const result = await this.native.fs.searchFiles(toRelativePath(
|
|
25014
|
+
findFiles: async (path5, glob) => {
|
|
25015
|
+
const result = await this.native.fs.searchFiles(toRelativePath(path5), glob);
|
|
25001
25016
|
return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
|
|
25002
25017
|
},
|
|
25003
25018
|
searchInFile: async (file, regex) => {
|
|
@@ -25011,8 +25026,8 @@ var DaytonaInstance = class {
|
|
|
25011
25026
|
return { matches: matchTexts, line_numbers };
|
|
25012
25027
|
},
|
|
25013
25028
|
strReplaceEditor: async (params) => {
|
|
25014
|
-
const { path:
|
|
25015
|
-
const relPath = toRelativePath(
|
|
25029
|
+
const { path: path5, old_str, new_str, replace_mode } = params;
|
|
25030
|
+
const relPath = toRelativePath(path5);
|
|
25016
25031
|
if (replace_mode === "ALL") {
|
|
25017
25032
|
await this.native.fs.replaceInFiles([relPath], old_str, new_str);
|
|
25018
25033
|
} else {
|
|
@@ -25032,11 +25047,11 @@ var DaytonaInstance = class {
|
|
|
25032
25047
|
const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
|
|
25033
25048
|
return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
|
|
25034
25049
|
},
|
|
25035
|
-
deletePath: async (
|
|
25036
|
-
await this.native.process.executeCommand(`rm -rf "${toRelativePath(
|
|
25050
|
+
deletePath: async (path5) => {
|
|
25051
|
+
await this.native.process.executeCommand(`rm -rf "${toRelativePath(path5)}"`, void 0, void 0);
|
|
25037
25052
|
},
|
|
25038
|
-
createDirectory: async (
|
|
25039
|
-
await this.native.process.executeCommand(`mkdir -p "${toRelativePath(
|
|
25053
|
+
createDirectory: async (path5) => {
|
|
25054
|
+
await this.native.process.executeCommand(`mkdir -p "${toRelativePath(path5)}"`, void 0, void 0);
|
|
25040
25055
|
}
|
|
25041
25056
|
};
|
|
25042
25057
|
this.shell = {
|
|
@@ -25275,6 +25290,277 @@ var DaytonaProvider = class {
|
|
|
25275
25290
|
}
|
|
25276
25291
|
};
|
|
25277
25292
|
|
|
25293
|
+
// src/sandbox_lattice/providers/LocalSandboxProvider.ts
|
|
25294
|
+
var path4 = __toESM(require("path"));
|
|
25295
|
+
var os = __toESM(require("os"));
|
|
25296
|
+
|
|
25297
|
+
// src/sandbox_lattice/LocalSandboxInstance.ts
|
|
25298
|
+
var import_node_child_process = require("child_process");
|
|
25299
|
+
var fs3 = __toESM(require("fs/promises"));
|
|
25300
|
+
var path3 = __toESM(require("path"));
|
|
25301
|
+
var posix = __toESM(require("path/posix"));
|
|
25302
|
+
var import_node_util = require("util");
|
|
25303
|
+
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
25304
|
+
var isWin = process.platform === "win32";
|
|
25305
|
+
var LocalSandboxInstance = class {
|
|
25306
|
+
constructor(name, rootDir) {
|
|
25307
|
+
this.file = {
|
|
25308
|
+
readFile: async (file) => {
|
|
25309
|
+
const content = await fs3.readFile(this.hostPath(file), "utf-8");
|
|
25310
|
+
return { content };
|
|
25311
|
+
},
|
|
25312
|
+
writeFile: async (file, content) => {
|
|
25313
|
+
const hp = this.hostPath(file);
|
|
25314
|
+
await fs3.mkdir(path3.dirname(hp), { recursive: true });
|
|
25315
|
+
await fs3.writeFile(hp, content, "utf-8");
|
|
25316
|
+
},
|
|
25317
|
+
listPath: async (targetPath, options) => {
|
|
25318
|
+
const hp = this.hostPath(targetPath);
|
|
25319
|
+
const files = [];
|
|
25320
|
+
if (options?.recursive) {
|
|
25321
|
+
await this.walkDir(hp, targetPath, files);
|
|
25322
|
+
} else {
|
|
25323
|
+
const entries = await fs3.readdir(hp, { withFileTypes: true });
|
|
25324
|
+
for (const e of entries) {
|
|
25325
|
+
const full = path3.join(hp, e.name);
|
|
25326
|
+
const stat4 = await fs3.stat(full).catch(() => null);
|
|
25327
|
+
files.push({
|
|
25328
|
+
path: posix.join(targetPath, e.name),
|
|
25329
|
+
is_dir: e.isDirectory(),
|
|
25330
|
+
size: stat4?.size ?? 0,
|
|
25331
|
+
modified_at: stat4?.mtime.toISOString()
|
|
25332
|
+
});
|
|
25333
|
+
}
|
|
25334
|
+
}
|
|
25335
|
+
return { files };
|
|
25336
|
+
},
|
|
25337
|
+
findFiles: async (targetPath, glob) => {
|
|
25338
|
+
const hp = this.hostPath(targetPath);
|
|
25339
|
+
const results = [];
|
|
25340
|
+
const regex = new RegExp(
|
|
25341
|
+
"^" + glob.replace(/\*+/g, "(.*)").replace(/\?/g, ".") + "$"
|
|
25342
|
+
);
|
|
25343
|
+
await this.walkDirFilter(hp, regex, results);
|
|
25344
|
+
const hpNorm = hp + path3.sep;
|
|
25345
|
+
const toSandboxPath = (hostPath) => posix.join(targetPath, hostPath.slice(hpNorm.length).split(path3.sep).join("/"));
|
|
25346
|
+
return { files: results.map(toSandboxPath) };
|
|
25347
|
+
},
|
|
25348
|
+
searchInFile: async (file, regex) => {
|
|
25349
|
+
const content = await fs3.readFile(this.hostPath(file), "utf-8");
|
|
25350
|
+
const lines = content.split("\n");
|
|
25351
|
+
const matches = [];
|
|
25352
|
+
const line_numbers = [];
|
|
25353
|
+
try {
|
|
25354
|
+
const re = new RegExp(regex);
|
|
25355
|
+
for (let i = 0; i < lines.length; i++) {
|
|
25356
|
+
if (re.test(lines[i])) {
|
|
25357
|
+
matches.push(lines[i]);
|
|
25358
|
+
line_numbers.push(i + 1);
|
|
25359
|
+
}
|
|
25360
|
+
}
|
|
25361
|
+
} catch {
|
|
25362
|
+
}
|
|
25363
|
+
return { matches, line_numbers };
|
|
25364
|
+
},
|
|
25365
|
+
strReplaceEditor: async (params) => {
|
|
25366
|
+
const content = await fs3.readFile(this.hostPath(params.path), "utf-8");
|
|
25367
|
+
let result;
|
|
25368
|
+
if (params.replace_mode === "ALL") {
|
|
25369
|
+
result = content.split(params.old_str).join(params.new_str);
|
|
25370
|
+
} else {
|
|
25371
|
+
const idx = content.indexOf(params.old_str);
|
|
25372
|
+
if (idx === -1) {
|
|
25373
|
+
throw new Error(`Old string not found in ${params.path}`);
|
|
25374
|
+
}
|
|
25375
|
+
result = content.slice(0, idx) + params.new_str + content.slice(idx + params.old_str.length);
|
|
25376
|
+
}
|
|
25377
|
+
await fs3.writeFile(this.hostPath(params.path), result, "utf-8");
|
|
25378
|
+
},
|
|
25379
|
+
uploadFile: async (params) => {
|
|
25380
|
+
const hp = this.hostPath(params.file);
|
|
25381
|
+
await fs3.mkdir(path3.dirname(hp), { recursive: true });
|
|
25382
|
+
await fs3.writeFile(hp, params.data);
|
|
25383
|
+
},
|
|
25384
|
+
downloadFile: async (params) => {
|
|
25385
|
+
const data = await fs3.readFile(this.hostPath(params.file));
|
|
25386
|
+
return data;
|
|
25387
|
+
},
|
|
25388
|
+
deletePath: async (targetPath) => {
|
|
25389
|
+
await fs3.rm(this.hostPath(targetPath), { recursive: true, force: true });
|
|
25390
|
+
},
|
|
25391
|
+
createDirectory: async (targetPath) => {
|
|
25392
|
+
await fs3.mkdir(this.hostPath(targetPath), { recursive: true });
|
|
25393
|
+
}
|
|
25394
|
+
};
|
|
25395
|
+
this.shell = {
|
|
25396
|
+
execCommand: async (params) => {
|
|
25397
|
+
const hp = params.exec_dir ? this.hostPath(params.exec_dir) : this.rootDir;
|
|
25398
|
+
const timeoutMs = params.timeout ? params.timeout * 1e3 : void 0;
|
|
25399
|
+
const [shell, shellArg] = isWin ? ["cmd.exe", "/c"] : ["/bin/sh", "-c"];
|
|
25400
|
+
try {
|
|
25401
|
+
const { stdout, stderr } = await execFileAsync(
|
|
25402
|
+
shell,
|
|
25403
|
+
[shellArg, params.command],
|
|
25404
|
+
{
|
|
25405
|
+
cwd: hp,
|
|
25406
|
+
timeout: timeoutMs,
|
|
25407
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
25408
|
+
// 10MB
|
|
25409
|
+
env: { ...process.env, HOME: this.rootDir }
|
|
25410
|
+
}
|
|
25411
|
+
);
|
|
25412
|
+
const output = stderr ? `${stdout}
|
|
25413
|
+
${stderr}`.trim() : stdout.trim();
|
|
25414
|
+
return { output, exit_code: 0 };
|
|
25415
|
+
} catch (err) {
|
|
25416
|
+
const execErr = err;
|
|
25417
|
+
const out = execErr.stdout ?? "";
|
|
25418
|
+
const errOut = execErr.stderr ?? "";
|
|
25419
|
+
const output = errOut ? `${out}
|
|
25420
|
+
${errOut}`.trim() : out.trim();
|
|
25421
|
+
return { output, exit_code: execErr.code ?? 1 };
|
|
25422
|
+
}
|
|
25423
|
+
}
|
|
25424
|
+
};
|
|
25425
|
+
this.name = name;
|
|
25426
|
+
this.rootDir = rootDir;
|
|
25427
|
+
}
|
|
25428
|
+
/** Map sandbox path (absolute, e.g. `/root/foo`) to host filesystem path. */
|
|
25429
|
+
hostPath(sandboxPath) {
|
|
25430
|
+
const normalized = sandboxPath.startsWith("/") ? sandboxPath : `/${sandboxPath}`;
|
|
25431
|
+
const clean = normalized.replace(/\/+/g, "/");
|
|
25432
|
+
const resolved = path3.resolve(this.rootDir, `.${clean}`);
|
|
25433
|
+
if (!resolved.startsWith(this.rootDir + path3.sep) && resolved !== this.rootDir) {
|
|
25434
|
+
throw new Error(`Path traversal denied: ${sandboxPath}`);
|
|
25435
|
+
}
|
|
25436
|
+
return resolved;
|
|
25437
|
+
}
|
|
25438
|
+
async start() {
|
|
25439
|
+
await fs3.mkdir(this.rootDir, { recursive: true });
|
|
25440
|
+
}
|
|
25441
|
+
async stop() {
|
|
25442
|
+
}
|
|
25443
|
+
async kill() {
|
|
25444
|
+
await fs3.rm(this.rootDir, { recursive: true, force: true });
|
|
25445
|
+
}
|
|
25446
|
+
async getStatus() {
|
|
25447
|
+
try {
|
|
25448
|
+
await fs3.access(this.rootDir);
|
|
25449
|
+
return "running";
|
|
25450
|
+
} catch {
|
|
25451
|
+
return "stopped";
|
|
25452
|
+
}
|
|
25453
|
+
}
|
|
25454
|
+
async walkDir(rootHost, sandboxPrefix, result) {
|
|
25455
|
+
const walk = async (hostDir, sandboxDir) => {
|
|
25456
|
+
let entries;
|
|
25457
|
+
try {
|
|
25458
|
+
entries = await fs3.readdir(hostDir, { withFileTypes: true });
|
|
25459
|
+
} catch {
|
|
25460
|
+
return;
|
|
25461
|
+
}
|
|
25462
|
+
for (const e of entries) {
|
|
25463
|
+
const fullHost = path3.join(hostDir, e.name);
|
|
25464
|
+
const fullSandbox = posix.join(sandboxDir, e.name);
|
|
25465
|
+
try {
|
|
25466
|
+
const stat4 = await fs3.stat(fullHost);
|
|
25467
|
+
result.push({
|
|
25468
|
+
path: fullSandbox,
|
|
25469
|
+
is_dir: e.isDirectory(),
|
|
25470
|
+
size: stat4.size,
|
|
25471
|
+
modified_at: stat4.mtime.toISOString()
|
|
25472
|
+
});
|
|
25473
|
+
} catch {
|
|
25474
|
+
result.push({
|
|
25475
|
+
path: fullSandbox,
|
|
25476
|
+
is_dir: e.isDirectory()
|
|
25477
|
+
});
|
|
25478
|
+
}
|
|
25479
|
+
if (e.isDirectory()) {
|
|
25480
|
+
await walk(fullHost, fullSandbox);
|
|
25481
|
+
}
|
|
25482
|
+
}
|
|
25483
|
+
};
|
|
25484
|
+
await walk(rootHost, sandboxPrefix);
|
|
25485
|
+
}
|
|
25486
|
+
async walkDirFilter(dir, regex, result) {
|
|
25487
|
+
let entries;
|
|
25488
|
+
try {
|
|
25489
|
+
entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
25490
|
+
} catch {
|
|
25491
|
+
return;
|
|
25492
|
+
}
|
|
25493
|
+
for (const e of entries) {
|
|
25494
|
+
const full = path3.join(dir, e.name);
|
|
25495
|
+
if (e.isFile() && regex.test(e.name)) {
|
|
25496
|
+
result.push(full);
|
|
25497
|
+
}
|
|
25498
|
+
if (e.isDirectory()) {
|
|
25499
|
+
await this.walkDirFilter(full, regex, result);
|
|
25500
|
+
}
|
|
25501
|
+
}
|
|
25502
|
+
}
|
|
25503
|
+
};
|
|
25504
|
+
|
|
25505
|
+
// src/sandbox_lattice/providers/LocalSandboxProvider.ts
|
|
25506
|
+
var LocalSandboxProvider = class {
|
|
25507
|
+
constructor(config = {}) {
|
|
25508
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
25509
|
+
this.creating = /* @__PURE__ */ new Map();
|
|
25510
|
+
this.basePath = config.basePath ?? path4.join(os.homedir(), ".axiom-local-sandbox");
|
|
25511
|
+
}
|
|
25512
|
+
async createSandbox(name, _config) {
|
|
25513
|
+
const existing = this.instances.get(name);
|
|
25514
|
+
if (existing) {
|
|
25515
|
+
const running = await existing.getStatus();
|
|
25516
|
+
if (running === "running") {
|
|
25517
|
+
return existing;
|
|
25518
|
+
}
|
|
25519
|
+
this.instances.delete(name);
|
|
25520
|
+
}
|
|
25521
|
+
const inFlight = this.creating.get(name);
|
|
25522
|
+
if (inFlight) {
|
|
25523
|
+
return inFlight;
|
|
25524
|
+
}
|
|
25525
|
+
const sandboxDir = path4.join(this.basePath, name);
|
|
25526
|
+
const creation = (async () => {
|
|
25527
|
+
const instance = new LocalSandboxInstance(name, sandboxDir);
|
|
25528
|
+
await instance.start();
|
|
25529
|
+
this.instances.set(name, instance);
|
|
25530
|
+
return instance;
|
|
25531
|
+
})();
|
|
25532
|
+
this.creating.set(name, creation);
|
|
25533
|
+
creation.catch(() => this.instances.delete(name)).finally(() => this.creating.delete(name));
|
|
25534
|
+
return creation;
|
|
25535
|
+
}
|
|
25536
|
+
async getSandbox(name) {
|
|
25537
|
+
const instance = this.instances.get(name);
|
|
25538
|
+
if (!instance) {
|
|
25539
|
+
throw new Error(`Sandbox ${name} not found`);
|
|
25540
|
+
}
|
|
25541
|
+
return instance;
|
|
25542
|
+
}
|
|
25543
|
+
async stopSandbox(name) {
|
|
25544
|
+
const instance = this.instances.get(name);
|
|
25545
|
+
if (instance) {
|
|
25546
|
+
try {
|
|
25547
|
+
await instance.stop();
|
|
25548
|
+
} catch {
|
|
25549
|
+
}
|
|
25550
|
+
}
|
|
25551
|
+
}
|
|
25552
|
+
async deleteSandbox(name) {
|
|
25553
|
+
const instance = this.instances.get(name);
|
|
25554
|
+
this.instances.delete(name);
|
|
25555
|
+
if (instance) {
|
|
25556
|
+
await instance.kill();
|
|
25557
|
+
}
|
|
25558
|
+
}
|
|
25559
|
+
async listSandboxes() {
|
|
25560
|
+
return Array.from(this.instances.values());
|
|
25561
|
+
}
|
|
25562
|
+
};
|
|
25563
|
+
|
|
25278
25564
|
// src/sandbox_lattice/SandboxProviderFactory.ts
|
|
25279
25565
|
function createSandboxProvider(config) {
|
|
25280
25566
|
switch (config.type) {
|
|
@@ -25319,6 +25605,9 @@ function createSandboxProvider(config) {
|
|
|
25319
25605
|
volumeName: config.daytonaVolumeName
|
|
25320
25606
|
});
|
|
25321
25607
|
}
|
|
25608
|
+
case "local": {
|
|
25609
|
+
return new LocalSandboxProvider({ basePath: config.localSandboxBasePath });
|
|
25610
|
+
}
|
|
25322
25611
|
default: {
|
|
25323
25612
|
const exhaustiveCheck = config.type;
|
|
25324
25613
|
throw new Error(`Unknown sandbox provider type: ${exhaustiveCheck}`);
|
|
@@ -25616,6 +25905,8 @@ PersonalAssistantConfig._config = deepClone(DEFAULT_CONFIG);
|
|
|
25616
25905
|
InMemoryUserStore,
|
|
25617
25906
|
InMemoryUserTenantLinkStore,
|
|
25618
25907
|
LINE_NUMBER_WIDTH,
|
|
25908
|
+
LocalSandboxInstance,
|
|
25909
|
+
LocalSandboxProvider,
|
|
25619
25910
|
LoggerLatticeManager,
|
|
25620
25911
|
MAX_LINE_LENGTH,
|
|
25621
25912
|
McpLatticeManager,
|