@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.js CHANGED
@@ -758,8 +758,8 @@ function buildReducer(kind) {
758
758
  return (_prev, next) => next;
759
759
  }
760
760
  }
761
- function resolvePath(obj, path3) {
762
- const cleanPath = path3.startsWith("state.") ? path3.slice(6) : path3;
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
- let results = Array.from(this.bindings.values()).filter((b) => {
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(path3) {
7460
- console.log(`[VolumeFilesystem.lsInfo] path=${path3} mountPrefix=${this.mountPrefix}`);
7461
- const entries = await this.client.list(path3);
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(path3) {
9772
- const pathStr = path3 || "/";
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, path3 = "/") {
9791
+ function globSearchFiles(files, pattern, path5 = "/") {
9790
9792
  let normalizedPath;
9791
9793
  try {
9792
- normalizedPath = validatePath(path3);
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, path3 = null, glob = null, outputMode = "files_with_matches") {
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(path3);
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, path3 = null, glob = null) {
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(path3);
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(path3) {
9957
+ lsInfo(path5) {
9956
9958
  const files = this.getFiles();
9957
9959
  const infos = [];
9958
9960
  const subdirs = /* @__PURE__ */ new Set();
9959
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
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, path3 = "/", glob = null) {
10067
+ grepRaw(pattern, path5 = "/", glob = null) {
10066
10068
  const files = this.getFiles();
10067
- return grepMatchesFromFiles(files, pattern, path3, glob);
10069
+ return grepMatchesFromFiles(files, pattern, path5, glob);
10068
10070
  }
10069
10071
  /**
10070
10072
  * Structured glob matching returning FileInfo objects.
10071
10073
  */
10072
- globInfo(pattern, path3 = "/") {
10074
+ globInfo(pattern, path5 = "/") {
10073
10075
  const files = this.getFiles();
10074
- const result = globSearchFiles(files, pattern, path3);
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 path3 = input.path || "/";
10169
- const infos = await resolvedBackend.lsInfo(path3);
10170
+ const path5 = input.path || "/";
10171
+ const infos = await resolvedBackend.lsInfo(path5);
10170
10172
  if (infos.length === 0) {
10171
- return `No files found in ${path3}`;
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: path3 = "/" } = input;
10315
- const infos = await resolvedBackend.globInfo(pattern, path3);
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: path3 = "/", glob = null } = input;
10343
- const result = await resolvedBackend.grepRaw(pattern, path3, glob);
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
- let result;
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
- let messagesArray = filteredMessages.map((message) => ({
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((resolve3, reject) => {
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
- resolve3(data.state);
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 && resolve3({ callback_event_id: callback_event, success: true });
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(path3) {
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 = path3.endsWith("/") ? path3 : path3 + "/";
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, path3 = "/", glob = null) {
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, path3, glob);
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, path3 = "/") {
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, path3);
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 stat3 = await fs2.stat(resolvedPath);
17046
- if (!stat3.isDirectory()) {
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 stat3 = await fs2.stat(resolvedPath);
17126
- if (!stat3.isFile()) {
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 stat3 = await fs2.lstat(resolvedPath);
17140
- if (stat3.isSymbolicLink()) {
17140
+ const stat4 = await fs2.lstat(resolvedPath);
17141
+ if (stat4.isSymbolicLink()) {
17141
17142
  return `Error: Symlinks are not allowed: ${filePath}`;
17142
17143
  }
17143
- if (!stat3.isFile()) {
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 stat3;
17174
+ let stat4;
17174
17175
  if (SUPPORTS_NOFOLLOW) {
17175
- stat3 = await fs2.stat(resolvedPath);
17176
- if (!stat3.isFile()) throw new Error(`File '${filePath}' not found`);
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
- stat3 = await fs2.lstat(resolvedPath);
17188
- if (stat3.isSymbolicLink()) {
17188
+ stat4 = await fs2.lstat(resolvedPath);
17189
+ if (stat4.isSymbolicLink()) {
17189
17190
  throw new Error(`Symlinks are not allowed: ${filePath}`);
17190
17191
  }
17191
- if (!stat3.isFile()) throw new Error(`File '${filePath}' not found`);
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: stat3.ctime.toISOString(),
17197
- modified_at: stat3.mtime.toISOString()
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 stat3 = await fs2.lstat(resolvedPath);
17209
- if (stat3.isSymbolicLink()) {
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 stat3 = await fs2.stat(resolvedPath);
17246
- if (!stat3.isFile()) {
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 stat3 = await fs2.lstat(resolvedPath);
17260
- if (stat3.isSymbolicLink()) {
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 (!stat3.isFile()) {
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((resolve3) => {
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
- resolve3(null);
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
- resolve3(results);
17382
+ resolve4(results);
17382
17383
  });
17383
17384
  proc.on("error", () => {
17384
- resolve3(null);
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 stat3 = await fs2.stat(baseFull);
17400
- const root = stat3.isDirectory() ? baseFull : path2.dirname(baseFull);
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 stat4 = await fs2.stat(fp);
17413
- if (stat4.size > this.maxFileSizeBytes) {
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 stat3 = await fs2.stat(resolvedSearchPath);
17456
- if (!stat3.isDirectory()) {
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 stat3 = await fs2.stat(matchedPath);
17473
- if (!stat3.isFile()) continue;
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: stat3.size,
17480
- modified_at: stat3.mtime.toISOString()
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: stat3.size,
17498
- modified_at: stat3.mtime.toISOString()
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(path3) {
17546
+ async lsInfo(path5) {
17546
17547
  for (const [routePrefix, backend] of this.sortedRoutes) {
17547
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
17548
- const suffix = path3.substring(routePrefix.length);
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 (path3 === "/") {
17562
+ if (path5 === "/") {
17562
17563
  const results = [];
17563
- const defaultInfos = await this.default.lsInfo(path3);
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(path3);
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, path3 = "/", glob = null) {
17604
+ async grepRaw(pattern, path5 = "/", glob = null) {
17604
17605
  for (const [routePrefix, backend] of this.sortedRoutes) {
17605
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
17606
- const searchPath = path3.substring(routePrefix.length - 1);
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, path3, glob);
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, path3 = "/") {
17641
+ async globInfo(pattern, path5 = "/") {
17641
17642
  const results = [];
17642
17643
  for (const [routePrefix, backend] of this.sortedRoutes) {
17643
- if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
17644
- const searchPath = path3.substring(routePrefix.length - 1);
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, path3);
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(path3) {
17701
+ lsInfo(path5) {
17701
17702
  const files = this.getFiles();
17702
17703
  const infos = [];
17703
17704
  const subdirs = /* @__PURE__ */ new Set();
17704
- const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
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, path3 = "/", glob = null) {
17780
+ grepRaw(pattern, path5 = "/", glob = null) {
17780
17781
  const files = this.getFiles();
17781
- return grepMatchesFromFiles(files, pattern, path3, glob);
17782
+ return grepMatchesFromFiles(files, pattern, path5, glob);
17782
17783
  }
17783
- globInfo(pattern, path3 = "/") {
17784
+ globInfo(pattern, path5 = "/") {
17784
17785
  const files = this.getFiles();
17785
- const result = globSearchFiles(files, pattern, path3);
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((resolve3) => {
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
- resolve3(allMsgs);
18837
+ resolve4(allMsgs);
18837
18838
  };
18838
18839
  mailboxStore.onMessage(teamId, agentId, handler);
18839
18840
  });
18840
- const timeoutPromise = new Promise((resolve3) => {
18841
- setTimeout(() => resolve3([]), READ_MESSAGES_TIMEOUT_MS2);
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((resolve3) => {
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
- resolve3(allMsgs);
19582
+ resolve4(allMsgs);
19582
19583
  };
19583
19584
  mailboxStore.onMessage(teamId, TEAM_LEAD_AGENT_ID, handler);
19584
19585
  });
19585
- const timeoutPromise = new Promise((resolve3) => {
19586
- setTimeout(() => resolve3([]), READ_MESSAGES_TIMEOUT_MS);
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 (path3, options) => {
24060
+ listPath: async (path5, options) => {
24060
24061
  const result = await this.client.listPath(
24061
24062
  this.name,
24062
- normalizeExternalSandboxPath(path3),
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 (path3, glob) => {
24072
+ findFiles: async (path5, glob) => {
24072
24073
  const result = await this.client.findFiles(
24073
24074
  this.name,
24074
- normalizeExternalSandboxPath(path3),
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 (path3) => {
24117
- const resolved = normalizeExternalSandboxPath(path3);
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 (path3) => {
24124
- const resolved = normalizeExternalSandboxPath(path3);
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
- return this.request(`/api/sandboxes/${encodeURIComponent(name)}`, {
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, path3) {
24211
+ async readFile(sandboxName, path5) {
24206
24212
  return this.request("/api/files/read", {
24207
24213
  method: "POST",
24208
- body: { sandboxName, path: path3 }
24214
+ body: { sandboxName, path: path5 }
24209
24215
  });
24210
24216
  }
24211
- async writeFile(sandboxName, path3, content) {
24217
+ async writeFile(sandboxName, path5, content) {
24212
24218
  return this.request("/api/files/write", {
24213
24219
  method: "POST",
24214
- body: { sandboxName, path: path3, content }
24220
+ body: { sandboxName, path: path5, content }
24215
24221
  });
24216
24222
  }
24217
- async listPath(sandboxName, path3, recursive) {
24223
+ async listPath(sandboxName, path5, recursive) {
24218
24224
  return this.request("/api/files/list", {
24219
24225
  method: "POST",
24220
- body: { sandboxName, path: path3, recursive }
24226
+ body: { sandboxName, path: path5, recursive }
24221
24227
  });
24222
24228
  }
24223
- async findFiles(sandboxName, path3, pattern) {
24229
+ async findFiles(sandboxName, path5, pattern) {
24224
24230
  return this.request("/api/files/find", {
24225
24231
  method: "POST",
24226
- body: { sandboxName, path: path3, pattern }
24232
+ body: { sandboxName, path: path5, pattern }
24227
24233
  });
24228
24234
  }
24229
- async searchInFile(sandboxName, path3, query) {
24235
+ async searchInFile(sandboxName, path5, query) {
24230
24236
  return this.request("/api/files/search", {
24231
24237
  method: "POST",
24232
- body: { sandboxName, path: path3, query }
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, path3, content) {
24247
+ async uploadFile(sandboxName, path5, content) {
24242
24248
  return this.request("/api/files/upload", {
24243
24249
  method: "POST",
24244
- body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
24250
+ body: { sandboxName, path: path5, contentBase64: content.toString("base64") }
24245
24251
  });
24246
24252
  }
24247
- async downloadFile(sandboxName, path3) {
24248
- const query = new URLSearchParams({ sandboxName, path: path3 });
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, path3) {
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: path3 }
24270
+ body: { path: path5 }
24265
24271
  }
24266
24272
  );
24267
24273
  return result.content;
24268
24274
  }
24269
- async volumeFsWrite(volumeName, path3, content) {
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: path3, content }
24280
+ body: { path: path5, content }
24275
24281
  }
24276
24282
  );
24277
24283
  }
24278
- async volumeFsList(volumeName, path3) {
24279
- console.log(`[volumeFsList] volume=${volumeName} path="${path3}" url=POST /api/volumes/${encodeURIComponent(volumeName)}/fs/list`);
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: path3 }
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, path3) {
24299
+ async volumeFsDownload(volumeName, path5) {
24294
24300
  const result = await this.request(
24295
- `/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path3)}`,
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, path3, data) {
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: path3, contentBase64: data.toString("base64") }
24313
+ body: { path: path5, contentBase64: data.toString("base64") }
24308
24314
  }
24309
24315
  );
24310
24316
  }
24311
- async request(path3, init) {
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}${path3}`, {
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
- await this.client.ensureSandbox(name, this.buildEnsureInput(config));
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: (path3) => this.client.volumeFsRead(volumeName, path3),
24412
- write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
24413
- list: (path3) => this.client.volumeFsList(volumeName, path3),
24414
- readRaw: (path3) => this.client.volumeFsDownload(volumeName, path3),
24415
- writeRaw: (path3, data) => this.client.volumeFsUpload(volumeName, path3, data)
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 (path3, options) => {
24515
- const resolved = this.resolvePath(path3);
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 (path3, glob) => {
24532
- const resolved = this.resolvePath(path3);
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 (path3) => {
24583
- const resolved = this.resolvePath(path3);
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 (path3) => {
24592
- const resolved = this.resolvePath(path3);
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 resolve3 = (p) => {
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 (path3) => {
24740
- const resolved = resolve3(path3);
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 (path3, content) => {
24748
- const resolved = resolve3(path3);
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 (path3) => {
24755
- const resolved = resolve3(path3);
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 (path3) => {
24773
- const resolved = resolve3(path3);
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 (path3, data) => {
24782
- const resolved = resolve3(path3);
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 (path3, options) => {
24811
- const entries = await this.native.files.list(path3);
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 (path3, glob) => {
24835
+ findFiles: async (path5, glob) => {
24821
24836
  const result = await this.native.commands.run(
24822
- `find "${path3}" -name "${glob}" -type f`
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: path3, old_str, new_str, replace_mode } = params;
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}' "${path3}"`
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 (path3) => {
24864
- await this.native.commands.run(`rm -rf "${path3}"`);
24878
+ deletePath: async (path5) => {
24879
+ await this.native.commands.run(`rm -rf "${path5}"`);
24865
24880
  },
24866
- createDirectory: async (path3) => {
24867
- await this.native.commands.run(`mkdir -p "${path3}"`);
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 (path3, options) => {
24987
- const entries = await this.native.fs.listFiles(toRelativePath(path3));
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 (path3, glob) => {
25000
- const result = await this.native.fs.searchFiles(toRelativePath(path3), glob);
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: path3, old_str, new_str, replace_mode } = params;
25015
- const relPath = toRelativePath(path3);
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 (path3) => {
25036
- await this.native.process.executeCommand(`rm -rf "${toRelativePath(path3)}"`, void 0, void 0);
25050
+ deletePath: async (path5) => {
25051
+ await this.native.process.executeCommand(`rm -rf "${toRelativePath(path5)}"`, void 0, void 0);
25037
25052
  },
25038
- createDirectory: async (path3) => {
25039
- await this.native.process.executeCommand(`mkdir -p "${toRelativePath(path3)}"`, void 0, void 0);
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,