@axiom-lattice/core 2.1.52 → 2.1.54

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
@@ -3484,13 +3484,15 @@ var import_zod15 = __toESM(require("zod"));
3484
3484
 
3485
3485
  // src/deep_agent_new/backends/volumeFilesystem.ts
3486
3486
  var VolumeFilesystem = class {
3487
- constructor(client) {
3487
+ constructor(client, mountPrefix = "") {
3488
3488
  this.client = client;
3489
+ this.mountPrefix = mountPrefix;
3489
3490
  }
3490
- async lsInfo(path4) {
3491
- const entries = await this.client.list(path4);
3491
+ async lsInfo(path3) {
3492
+ const entries = await this.client.list(path3);
3493
+ const prefix = this.mountPrefix.endsWith("/") ? this.mountPrefix : this.mountPrefix + "/";
3492
3494
  return entries.map((entry) => ({
3493
- path: entry.path,
3495
+ path: entry.path.startsWith("/") ? entry.path : prefix + entry.path,
3494
3496
  is_dir: entry.kind === "directory",
3495
3497
  size: entry.size,
3496
3498
  modified_at: entry.modified ? new Date(entry.modified).toISOString() : void 0
@@ -3536,6 +3538,20 @@ var VolumeFilesystem = class {
3536
3538
  }
3537
3539
  };
3538
3540
 
3541
+ // src/sandbox_lattice/pathUtils.ts
3542
+ function normalizeExternalSandboxPath(inputPath) {
3543
+ if (inputPath === "~" || inputPath === "~/") {
3544
+ return "/";
3545
+ }
3546
+ if (inputPath.startsWith("~/")) {
3547
+ return `/${inputPath.slice(2)}`;
3548
+ }
3549
+ if (inputPath.startsWith("/")) {
3550
+ return inputPath;
3551
+ }
3552
+ return `/${inputPath}`;
3553
+ }
3554
+
3539
3555
  // src/sandbox_lattice/utils.ts
3540
3556
  var import_node_crypto = require("crypto");
3541
3557
  function normalizeSandboxName(name) {
@@ -3572,6 +3588,20 @@ function buildNamedVolumeName(prefix, ...parts) {
3572
3588
  }
3573
3589
 
3574
3590
  // src/sandbox_lattice/SandboxLatticeManager.ts
3591
+ function stripPrefixClient(client, prefix) {
3592
+ const strip = (p) => {
3593
+ if (p === prefix || p === prefix + "/") return "";
3594
+ if (p.startsWith(prefix + "/")) return p.slice(prefix.length + 1);
3595
+ return p;
3596
+ };
3597
+ return {
3598
+ read: (p) => client.read(strip(p)),
3599
+ write: (p, c) => client.write(strip(p), c),
3600
+ list: (p) => client.list(strip(p)),
3601
+ readRaw: (p) => client.readRaw(strip(p)),
3602
+ writeRaw: (p, d) => client.writeRaw(strip(p), d)
3603
+ };
3604
+ }
3575
3605
  function computeSandboxName(config) {
3576
3606
  switch (config.vmIsolation) {
3577
3607
  case "global":
@@ -3643,17 +3673,39 @@ var SandboxLatticeManager = class _SandboxLatticeManager extends BaseLatticeMana
3643
3673
  return this.createSandbox(name, config);
3644
3674
  }
3645
3675
  async getVolumeBackend(config) {
3676
+ return this.getVolumeBackendForPath(config, "/project");
3677
+ }
3678
+ async getVolumeBackendForPath(config, filePath) {
3646
3679
  const provider = this._requireProvider();
3647
3680
  if (!provider.createVolumeFsClient) {
3648
3681
  return null;
3649
3682
  }
3650
3683
  const tenantId = config.tenantId ?? "default";
3651
- if (!config.projectId) {
3652
- return null;
3684
+ const mapping = this._resolveVolumeForPath(config, tenantId, filePath);
3685
+ if (!mapping) return null;
3686
+ const client = provider.createVolumeFsClient(mapping.volumeName);
3687
+ return new VolumeFilesystem(stripPrefixClient(client, mapping.pathPrefix), mapping.pathPrefix);
3688
+ }
3689
+ _resolveVolumeForPath(config, tenantId, filePath) {
3690
+ const normalized = normalizeExternalSandboxPath(filePath);
3691
+ if (normalized === "/.agent" || normalized.startsWith("/.agent/")) {
3692
+ return {
3693
+ volumeName: buildNamedVolumeName("s", "skills", tenantId),
3694
+ pathPrefix: "/.agent"
3695
+ };
3696
+ }
3697
+ if (normalized === "/agent" || normalized.startsWith("/agent/")) {
3698
+ if (!config.assistant_id) return null;
3699
+ return {
3700
+ volumeName: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id),
3701
+ pathPrefix: "/agent"
3702
+ };
3653
3703
  }
3654
- const volumeName = buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId);
3655
- const client = provider.createVolumeFsClient(volumeName);
3656
- return new VolumeFilesystem(client);
3704
+ if (!config.projectId) return null;
3705
+ return {
3706
+ volumeName: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId),
3707
+ pathPrefix: "/project"
3708
+ };
3657
3709
  }
3658
3710
  async createSandbox(name, config) {
3659
3711
  const provider = this._requireProvider();
@@ -3707,9 +3759,9 @@ var SHELL_EXEC_DESCRIPTION = `Execute a shell command in the sandbox environment
3707
3759
 
3708
3760
  Use this to run CLI tools, install packages, inspect files, or perform any operation that requires a shell.
3709
3761
 
3710
- To execute a code file, pass the appropriate command (e.g. "python ~/project/main.py" or "node ~/project/app.js"). Only Python (.py) and JavaScript (.js, .mjs) files are supported.
3762
+ To execute a code file, pass the appropriate command (e.g. "python /project/main.py" or "node /project/app.js"). Only Python (.py) and JavaScript (.js, .mjs) files are supported.
3711
3763
 
3712
- Note: the working directory defaults to ~ (the sandbox home directory). Project files should be placed under ~/project/. Use paths like "~/project/file.txt" or relative paths like "project/file.txt". Never use absolute paths like "/project/file.txt".`;
3764
+ Note: the working directory defaults to /. Project files are under /project/. Use paths like "/project/file.txt".`;
3713
3765
  function formatExecutionResult(data) {
3714
3766
  const parts = [];
3715
3767
  if (data.output) {
@@ -5035,13 +5087,13 @@ var createLoadSkillContentTool = () => {
5035
5087
  async (input, _exe_config) => {
5036
5088
  try {
5037
5089
  const sandbox = await getSandboxFromExeConfig(_exe_config);
5038
- const filePath = `~/.agents/skills/${input.skill_name}/SKILL.md`;
5090
+ const filePath = `/.agent/skills/${input.skill_name}/SKILL.md`;
5039
5091
  let content;
5040
5092
  try {
5041
5093
  const result2 = await sandbox.file.readFile(filePath);
5042
5094
  content = result2.content;
5043
5095
  } catch {
5044
- const listResult = await sandbox.file.listPath("~/.agents/skills", { recursive: false });
5096
+ const listResult = await sandbox.file.listPath("/.agent/skills", { recursive: false });
5045
5097
  const available = listResult.files.filter((f) => f.is_dir).map((f) => f.path.split("/").pop()).filter(Boolean).join(", ");
5046
5098
  return `Skill "${input.skill_name}" not found. Available skills: ${available}`;
5047
5099
  }
@@ -5049,7 +5101,7 @@ var createLoadSkillContentTool = () => {
5049
5101
  let result = buildSkillFile(meta, body);
5050
5102
  try {
5051
5103
  const resourcesResult = await sandbox.file.listPath(
5052
- `~/.agents/skills/${input.skill_name}/resources`,
5104
+ `/.agent/skills/${input.skill_name}/resources`,
5053
5105
  { recursive: false }
5054
5106
  );
5055
5107
  const resources = resourcesResult.files.map((f) => f.path.split("/").pop()).filter(Boolean);
@@ -5102,14 +5154,14 @@ function createSkillMiddleware(params = {}) {
5102
5154
  projectId: runConfig.projectId,
5103
5155
  vmIsolation: "project"
5104
5156
  });
5105
- const result = await sandbox.file.listPath("~/.agents/skills", { recursive: false });
5157
+ const result = await sandbox.file.listPath("/.agent/skills", { recursive: false });
5106
5158
  const allSkills = [];
5107
5159
  for (const entry of result.files) {
5108
5160
  if (!entry.is_dir) continue;
5109
5161
  const skillName = entry.path.split("/").pop();
5110
5162
  if (!skillName) continue;
5111
5163
  try {
5112
- const fileResult = await sandbox.file.readFile(`~/.agents/skills/${skillName}/SKILL.md`);
5164
+ const fileResult = await sandbox.file.readFile(`/.agent/skills/${skillName}/SKILL.md`);
5113
5165
  const { meta } = parseSkillFrontmatter(fileResult.content);
5114
5166
  allSkills.push({
5115
5167
  id: skillName,
@@ -5273,16 +5325,16 @@ function truncateIfTooLong(result) {
5273
5325
  }
5274
5326
  return result;
5275
5327
  }
5276
- function validatePath(path4) {
5277
- const pathStr = path4 || "/";
5328
+ function validatePath(path3) {
5329
+ const pathStr = path3 || "/";
5278
5330
  if (!pathStr || pathStr.trim() === "") {
5279
5331
  throw new Error("Path cannot be empty");
5280
5332
  }
5281
5333
  let normalized;
5282
- if (pathStr === "~") {
5283
- normalized = "~/";
5334
+ if (pathStr === "~" || pathStr === "~/") {
5335
+ normalized = "/";
5284
5336
  } else if (pathStr.startsWith("~/")) {
5285
- normalized = pathStr;
5337
+ normalized = `/${pathStr.slice(2)}`;
5286
5338
  } else {
5287
5339
  normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
5288
5340
  }
@@ -5291,10 +5343,10 @@ function validatePath(path4) {
5291
5343
  }
5292
5344
  return normalized;
5293
5345
  }
5294
- function globSearchFiles(files, pattern, path4 = "/") {
5346
+ function globSearchFiles(files, pattern, path3 = "/") {
5295
5347
  let normalizedPath;
5296
5348
  try {
5297
- normalizedPath = validatePath(path4);
5349
+ normalizedPath = validatePath(path3);
5298
5350
  } catch {
5299
5351
  return "No files found";
5300
5352
  }
@@ -5346,7 +5398,7 @@ function formatGrepResults(results, outputMode) {
5346
5398
  }
5347
5399
  return lines.join("\n");
5348
5400
  }
5349
- function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode = "files_with_matches") {
5401
+ function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode = "files_with_matches") {
5350
5402
  let regex;
5351
5403
  try {
5352
5404
  regex = new RegExp(pattern);
@@ -5355,7 +5407,7 @@ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode =
5355
5407
  }
5356
5408
  let normalizedPath;
5357
5409
  try {
5358
- normalizedPath = validatePath(path4);
5410
+ normalizedPath = validatePath(path3);
5359
5411
  } catch {
5360
5412
  return "No matches found";
5361
5413
  }
@@ -5387,7 +5439,7 @@ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode =
5387
5439
  }
5388
5440
  return formatGrepResults(results, outputMode);
5389
5441
  }
5390
- function grepMatchesFromFiles(files, pattern, path4 = null, glob = null) {
5442
+ function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
5391
5443
  let regex;
5392
5444
  try {
5393
5445
  regex = new RegExp(pattern);
@@ -5396,7 +5448,7 @@ function grepMatchesFromFiles(files, pattern, path4 = null, glob = null) {
5396
5448
  }
5397
5449
  let normalizedPath;
5398
5450
  try {
5399
- normalizedPath = validatePath(path4);
5451
+ normalizedPath = validatePath(path3);
5400
5452
  } catch {
5401
5453
  return [];
5402
5454
  }
@@ -5457,11 +5509,11 @@ var StateBackend = class {
5457
5509
  * @returns List of FileInfo objects for files and directories directly in the directory.
5458
5510
  * Directories have a trailing / in their path and is_dir=true.
5459
5511
  */
5460
- lsInfo(path4) {
5512
+ lsInfo(path3) {
5461
5513
  const files = this.getFiles();
5462
5514
  const infos = [];
5463
5515
  const subdirs = /* @__PURE__ */ new Set();
5464
- const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
5516
+ const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
5465
5517
  for (const [k, fd] of Object.entries(files)) {
5466
5518
  if (!k.startsWith(normalizedPath)) {
5467
5519
  continue;
@@ -5567,16 +5619,16 @@ var StateBackend = class {
5567
5619
  /**
5568
5620
  * Structured search results or error string for invalid input.
5569
5621
  */
5570
- grepRaw(pattern, path4 = "/", glob = null) {
5622
+ grepRaw(pattern, path3 = "/", glob = null) {
5571
5623
  const files = this.getFiles();
5572
- return grepMatchesFromFiles(files, pattern, path4, glob);
5624
+ return grepMatchesFromFiles(files, pattern, path3, glob);
5573
5625
  }
5574
5626
  /**
5575
5627
  * Structured glob matching returning FileInfo objects.
5576
5628
  */
5577
- globInfo(pattern, path4 = "/") {
5629
+ globInfo(pattern, path3 = "/") {
5578
5630
  const files = this.getFiles();
5579
- const result = globSearchFiles(files, pattern, path4);
5631
+ const result = globSearchFiles(files, pattern, path3);
5580
5632
  if (result === "No files found") {
5581
5633
  return [];
5582
5634
  }
@@ -5642,16 +5694,16 @@ async function getBackend(backend, stateAndStore) {
5642
5694
  var FILESYSTEM_SYSTEM_PROMPT = `You have access to a virtual filesystem.
5643
5695
 
5644
5696
  Path conventions:
5645
- - All paths must start with ~/ (home directory) or / (root). Prefer ~/ for clarity.
5646
- - ~/agent/ \u2014 Your private agent directory (identity, memory, preferences). Isolated per agent.
5647
- - ~/project/ \u2014 Project workspace. Shared across all agents in the same project. Persisted across sessions.
5648
- - ~/.agents/skills/ \u2014 Skill definitions. Read-only for most operations.
5697
+ - All paths are absolute starting with /. Key directories:
5698
+ - /agent/ \u2014 Your private agent directory (identity, memory, preferences). Isolated per agent.
5699
+ - /project/ \u2014 Project workspace. Shared across all agents in the same project. Persisted across sessions.
5700
+ - /.agent/skills/ \u2014 Skill definitions. Read-only for most operations.
5649
5701
 
5650
5702
  - ls: list files in a directory
5651
5703
  - read_file: read a file from the filesystem
5652
5704
  - write_file: write to a file in the filesystem
5653
5705
  - edit_file: edit a file in the filesystem
5654
- - glob: find files matching a pattern (e.g., "~/project/**/*.py")
5706
+ - glob: find files matching a pattern (e.g., "/project/**/*.py")
5655
5707
  - grep: search for text within files`;
5656
5708
  var LS_TOOL_DESCRIPTION = "List files and directories in a directory";
5657
5709
  var READ_FILE_TOOL_DESCRIPTION = "Read the contents of a file";
@@ -5670,10 +5722,10 @@ function createLsTool(backend, options) {
5670
5722
  ...runConfig
5671
5723
  };
5672
5724
  const resolvedBackend = await getBackend(backend, stateAndStore);
5673
- const path4 = input.path || "/";
5674
- const infos = await resolvedBackend.lsInfo(path4);
5725
+ const path3 = input.path || "/";
5726
+ const infos = await resolvedBackend.lsInfo(path3);
5675
5727
  if (infos.length === 0) {
5676
- return `No files found in ${path4}`;
5728
+ return `No files found in ${path3}`;
5677
5729
  }
5678
5730
  const lines = [];
5679
5731
  for (const info of infos) {
@@ -5816,8 +5868,8 @@ function createGlobTool(backend, options) {
5816
5868
  ...runConfig
5817
5869
  };
5818
5870
  const resolvedBackend = await getBackend(backend, stateAndStore);
5819
- const { pattern, path: path4 = "/" } = input;
5820
- const infos = await resolvedBackend.globInfo(pattern, path4);
5871
+ const { pattern, path: path3 = "/" } = input;
5872
+ const infos = await resolvedBackend.globInfo(pattern, path3);
5821
5873
  if (infos.length === 0) {
5822
5874
  return `No files found matching pattern '${pattern}'`;
5823
5875
  }
@@ -5844,8 +5896,8 @@ function createGrepTool(backend, options) {
5844
5896
  ...runConfig
5845
5897
  };
5846
5898
  const resolvedBackend = await getBackend(backend, stateAndStore);
5847
- const { pattern, path: path4 = "/", glob = null } = input;
5848
- const result = await resolvedBackend.grepRaw(pattern, path4, glob);
5899
+ const { pattern, path: path3 = "/", glob = null } = input;
5900
+ const result = await resolvedBackend.grepRaw(pattern, path3, glob);
5849
5901
  if (typeof result === "string") {
5850
5902
  return result;
5851
5903
  }
@@ -7111,50 +7163,50 @@ var AGENTS_MD = `
7111
7163
 
7112
7164
  ## First Run
7113
7165
 
7114
- If "~/agent/BOOTSTRAP.md" exists, that's your birth certificate. Follow it, figure out who you are, set up your memory structure, then delete it. You won't need it again. This is the one cleanup exception you can do without asking first.
7166
+ If "/agent/BOOTSTRAP.md" exists, that's your birth certificate. Follow it, figure out who you are, set up your memory structure, then delete it. You won't need it again. This is the one cleanup exception you can do without asking first.
7115
7167
 
7116
7168
  ## Every Session
7117
7169
 
7118
7170
  Before doing anything else, read this startup set in order:
7119
7171
 
7120
- 1. ~/agent/SOUL.md
7121
- 2. ~/agent/AGENTS.md
7122
- 3. ~/agent/IDENTITY.md
7123
- 4. ~/agent/USER.md
7124
- 5. ~/agent/MEMORY.md
7125
- 6. ~/project/PROJECT.md
7126
- 7. ~/project/notes/index.md
7127
- 8. ~/project/notes/wip.md
7128
- 9. ~/project/notes/pending.md
7172
+ 1. /agent/SOUL.md
7173
+ 2. /agent/AGENTS.md
7174
+ 3. /agent/IDENTITY.md
7175
+ 4. /agent/USER.md
7176
+ 5. /agent/MEMORY.md
7177
+ 6. /project/PROJECT.md
7178
+ 7. /project/notes/index.md
7179
+ 8. /project/notes/wip.md
7180
+ 9. /project/notes/pending.md
7129
7181
 
7130
7182
  Don't ask permission. Just do it.
7131
7183
 
7132
7184
  After the startup set, expand only if needed:
7133
7185
 
7134
- - If ~/project/notes/wip.md mentions unfamiliar modules, unclear constraints, or prior decisions, read ~/project/notes/architecture.md and ~/project/notes/decisions.md.
7135
- - If the current interruption point still feels underspecified, read the most recent one or two ~/project/raw/YYYY-MM-DD.md files.
7186
+ - If /project/notes/wip.md mentions unfamiliar modules, unclear constraints, or prior decisions, read /project/notes/architecture.md and /project/notes/decisions.md.
7187
+ - If the current interruption point still feels underspecified, read the most recent one or two /project/raw/YYYY-MM-DD.md files.
7136
7188
  - Do not load every memory file by default. Read deeper only when the current task needs it.
7137
7189
 
7138
7190
  ## Memory Model
7139
7191
 
7140
7192
  You wake up fresh each session. Files are your continuity.
7141
7193
 
7142
- - ~/agent/ is your private scope.
7143
- - ~/agent/MEMORY.md is your memory index.
7144
- - ~/agent/memory/*.md stores categorized private memory.
7145
- - ~/agent/memory/preferences.md is one example of categorized private memory.
7146
- - ~/project/PROJECT.md, ~/project/raw/, ~/project/notes/, and ~/project/artifacts/ belong to the current project.
7147
- - ~/project/raw/YYYY-MM-DD.md records what happened.
7148
- - ~/project/notes/ records what is worth remembering.
7149
- - ~/project/artifacts/ records what was produced.
7194
+ - /agent/ is your private scope.
7195
+ - /agent/MEMORY.md is your memory index.
7196
+ - /agent/memory/*.md stores categorized private memory.
7197
+ - /agent/memory/preferences.md is one example of categorized private memory.
7198
+ - /project/PROJECT.md, /project/raw/, /project/notes/, and /project/artifacts/ belong to the current project.
7199
+ - /project/raw/YYYY-MM-DD.md records what happened.
7200
+ - /project/notes/ records what is worth remembering.
7201
+ - /project/artifacts/ records what was produced.
7150
7202
 
7151
7203
  Use this structure intentionally:
7152
7204
 
7153
- - Read ~/agent/MEMORY.md to find the durable private memory that matters now.
7154
- - Treat ~/agent/MEMORY.md as an index and navigation file, not as the main place for detailed long-term notes.
7155
- - Write the actual durable private content into ~/agent/memory/*.md.
7156
- - Use ~/project/PROJECT.md for the current project's operating context, constraints, and stable reference material.
7157
- - Prefer writing to ~/project/raw/YYYY-MM-DD.md or ~/project/notes/wip.md before promoting anything into durable notes or agent memory.
7205
+ - Read /agent/MEMORY.md to find the durable private memory that matters now.
7206
+ - Treat /agent/MEMORY.md as an index and navigation file, not as the main place for detailed long-term notes.
7207
+ - Write the actual durable private content into /agent/memory/*.md.
7208
+ - Use /project/PROJECT.md for the current project's operating context, constraints, and stable reference material.
7209
+ - Prefer writing to /project/raw/YYYY-MM-DD.md or /project/notes/wip.md before promoting anything into durable notes or agent memory.
7158
7210
  - Not every session needs a write.
7159
7211
  - Write only when the session produced something worth preserving for future work.
7160
7212
 
@@ -7169,15 +7221,15 @@ Pure one-off questions with no follow-up value usually need no memory update.
7169
7221
 
7170
7222
  Promote information upward based on value:
7171
7223
 
7172
- - Put immediate observations, action logs, and rough capture in ~/project/raw/YYYY-MM-DD.md.
7173
- - Put working understanding, partial conclusions, and candidate reminders in ~/project/notes/wip.md.
7224
+ - Put immediate observations, action logs, and rough capture in /project/raw/YYYY-MM-DD.md.
7225
+ - Put working understanding, partial conclusions, and candidate reminders in /project/notes/wip.md.
7174
7226
  - Put durable project knowledge in project notes once it becomes worth remembering.
7175
- - Put durable private lessons, preferences, reminders, and long-term context in ~/agent/MEMORY.md and ~/agent/memory/*.md.
7227
+ - Put durable private lessons, preferences, reminders, and long-term context in /agent/MEMORY.md and /agent/memory/*.md.
7176
7228
 
7177
7229
  ## Safety
7178
7230
 
7179
7231
  - Don't exfiltrate private data. Ever.
7180
- - Don't run destructive commands without asking, except deleting ~/agent/BOOTSTRAP.md after first-run setup is complete.
7232
+ - Don't run destructive commands without asking, except deleting /agent/BOOTSTRAP.md after first-run setup is complete.
7181
7233
  - When in doubt, ask.
7182
7234
 
7183
7235
  ## External vs Internal
@@ -7209,12 +7261,12 @@ There is no durable memory yet. This is a fresh workspace, so your first job is
7209
7261
 
7210
7262
  Before you start shaping identity or style, inspect the memory structure you will use.
7211
7263
 
7212
- - ~/agent/MEMORY.md
7213
- - ~/agent/memory/*.md
7214
- - ~/project/PROJECT.md
7215
- - ~/project/raw/
7216
- - ~/project/notes/
7217
- - ~/project/artifacts/
7264
+ - /agent/MEMORY.md
7265
+ - /agent/memory/*.md
7266
+ - /project/PROJECT.md
7267
+ - /project/raw/
7268
+ - /project/notes/
7269
+ - /project/artifacts/
7218
7270
 
7219
7271
  You need to understand this structure first, because this is how you will preserve continuity in future work.
7220
7272
 
@@ -7237,37 +7289,37 @@ Offer suggestions if they're stuck. Keep it human.
7237
7289
 
7238
7290
  Set up and understand this memory structure. This is the memory structure you should use in future work.
7239
7291
 
7240
- - ~/agent/MEMORY.md
7241
- - ~/agent/memory/*.md
7242
- - ~/project/PROJECT.md
7243
- - ~/project/raw/
7244
- - ~/project/notes/
7245
- - ~/project/artifacts/
7292
+ - /agent/MEMORY.md
7293
+ - /agent/memory/*.md
7294
+ - /project/PROJECT.md
7295
+ - /project/raw/
7296
+ - /project/notes/
7297
+ - /project/artifacts/
7246
7298
 
7247
7299
  Use it like this:
7248
7300
 
7249
- - ~/agent/MEMORY.md is your private memory index.
7250
- - ~/agent/memory/*.md holds categorized private memory.
7251
- - ~/project/PROJECT.md holds stable project-level context.
7252
- - ~/project/raw/ captures what happened.
7253
- - ~/project/notes/ captures what is worth remembering.
7254
- - ~/project/artifacts/ stores what was produced.
7301
+ - /agent/MEMORY.md is your private memory index.
7302
+ - /agent/memory/*.md holds categorized private memory.
7303
+ - /project/PROJECT.md holds stable project-level context.
7304
+ - /project/raw/ captures what happened.
7305
+ - /project/notes/ captures what is worth remembering.
7306
+ - /project/artifacts/ stores what was produced.
7255
7307
 
7256
7308
  ## After You Know Who You Are
7257
7309
 
7258
7310
  Update these files with what you learned:
7259
7311
 
7260
- - ~/agent/IDENTITY.md for your name, nature, and vibe.
7261
- - ~/agent/USER.md for who you're helping and how to work well with them.
7262
- - ~/agent/SOUL.md for values, behavior, and boundaries.
7263
- - ~/agent/MEMORY.md and ~/agent/memory/*.md only for durable private memory worth keeping.
7312
+ - /agent/IDENTITY.md for your name, nature, and vibe.
7313
+ - /agent/USER.md for who you're helping and how to work well with them.
7314
+ - /agent/SOUL.md for values, behavior, and boundaries.
7315
+ - /agent/MEMORY.md and /agent/memory/*.md only for durable private memory worth keeping.
7264
7316
 
7265
7317
  Do not keep rewriting these foundational files during ordinary project work.
7266
7318
  Update them only when you learn something stable enough to change your long-term identity, user model, or private memory structure.
7267
7319
 
7268
7320
  Prefer rough capture in project memory before creating durable notes:
7269
7321
 
7270
- - Start with ~/project/raw/YYYY-MM-DD.md or ~/project/notes/wip.md.
7322
+ - Start with /project/raw/YYYY-MM-DD.md or /project/notes/wip.md.
7271
7323
  - Promote only the information that should survive into project notes or private agent memory.
7272
7324
 
7273
7325
  ## When You're Done
@@ -12411,8 +12463,52 @@ var SandboxFilesystem = class {
12411
12463
  }
12412
12464
  }
12413
12465
  async read(filePath, offset = 0, limit = 1e4) {
12466
+ const ext = filePath.split(".").pop()?.toLowerCase();
12467
+ const binaryExts = /* @__PURE__ */ new Set([
12468
+ "pdf",
12469
+ "png",
12470
+ "jpg",
12471
+ "jpeg",
12472
+ "gif",
12473
+ "svg",
12474
+ "webp",
12475
+ "ico",
12476
+ "bmp",
12477
+ "zip",
12478
+ "gz",
12479
+ "tar",
12480
+ "rar",
12481
+ "7z",
12482
+ "mp3",
12483
+ "mp4",
12484
+ "avi",
12485
+ "mov",
12486
+ "wav",
12487
+ "flac",
12488
+ "exe",
12489
+ "dll",
12490
+ "so",
12491
+ "dylib",
12492
+ "wasm",
12493
+ "ttf",
12494
+ "otf",
12495
+ "woff",
12496
+ "woff2",
12497
+ "doc",
12498
+ "docx",
12499
+ "ppt",
12500
+ "pptx",
12501
+ "xls",
12502
+ "xlsx"
12503
+ ]);
12504
+ if (ext && binaryExts.has(ext)) {
12505
+ return `Error: Cannot read binary file '${filePath}': files with .${ext} extension are not supported for text reading. Use shell tools (e.g., 'file' command) to inspect, or download the file directly.`;
12506
+ }
12414
12507
  try {
12415
12508
  const result = await this.sandbox.file.readFile(filePath);
12509
+ if (result.content.includes("\0")) {
12510
+ return `Error: Cannot read binary file '${filePath}': file contains binary data. Use shell tools to inspect or download the file directly.`;
12511
+ }
12416
12512
  return result.content;
12417
12513
  } catch (e) {
12418
12514
  return `Error: File '${filePath}' not found`;
@@ -12464,9 +12560,9 @@ var SandboxFilesystem = class {
12464
12560
  throw new Error(`Error editing file '${filePath}': ${e.message}`);
12465
12561
  }
12466
12562
  }
12467
- async grepRaw(pattern, searchPath = "~/", glob = null) {
12563
+ async grepRaw(pattern, searchPath = "/", glob = null) {
12468
12564
  try {
12469
- const result = await this.sandbox.file.findFiles(searchPath || "~/", glob || "**/*");
12565
+ const result = await this.sandbox.file.findFiles(searchPath || "/", glob || "**/*");
12470
12566
  const filePaths = result.files;
12471
12567
  const matches = [];
12472
12568
  for (const absolutePath of filePaths) {
@@ -12486,7 +12582,7 @@ var SandboxFilesystem = class {
12486
12582
  return `Error: ${e.message}`;
12487
12583
  }
12488
12584
  }
12489
- async globInfo(pattern, searchPath = "~/") {
12585
+ async globInfo(pattern, searchPath = "/") {
12490
12586
  const result = await this.sandbox.file.findFiles(searchPath, pattern || "**/*");
12491
12587
  return result.files.map((filePath) => ({
12492
12588
  path: filePath,
@@ -13231,13 +13327,13 @@ var StoreBackend = class {
13231
13327
  * @returns List of FileInfo objects for files and directories directly in the directory.
13232
13328
  * Directories have a trailing / in their path and is_dir=true.
13233
13329
  */
13234
- async lsInfo(path4) {
13330
+ async lsInfo(path3) {
13235
13331
  const store = this.getStore();
13236
13332
  const namespace = this.getNamespace();
13237
13333
  const items = await this.searchStorePaginated(store, namespace);
13238
13334
  const infos = [];
13239
13335
  const subdirs = /* @__PURE__ */ new Set();
13240
- const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
13336
+ const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
13241
13337
  for (const item of items) {
13242
13338
  const itemKey = String(item.key);
13243
13339
  if (!itemKey.startsWith(normalizedPath)) {
@@ -13355,7 +13451,7 @@ var StoreBackend = class {
13355
13451
  /**
13356
13452
  * Structured search results or error string for invalid input.
13357
13453
  */
13358
- async grepRaw(pattern, path4 = "/", glob = null) {
13454
+ async grepRaw(pattern, path3 = "/", glob = null) {
13359
13455
  const store = this.getStore();
13360
13456
  const namespace = this.getNamespace();
13361
13457
  const items = await this.searchStorePaginated(store, namespace);
@@ -13367,12 +13463,12 @@ var StoreBackend = class {
13367
13463
  continue;
13368
13464
  }
13369
13465
  }
13370
- return grepMatchesFromFiles(files, pattern, path4, glob);
13466
+ return grepMatchesFromFiles(files, pattern, path3, glob);
13371
13467
  }
13372
13468
  /**
13373
13469
  * Structured glob matching returning FileInfo objects.
13374
13470
  */
13375
- async globInfo(pattern, path4 = "/") {
13471
+ async globInfo(pattern, path3 = "/") {
13376
13472
  const store = this.getStore();
13377
13473
  const namespace = this.getNamespace();
13378
13474
  const items = await this.searchStorePaginated(store, namespace);
@@ -13384,7 +13480,7 @@ var StoreBackend = class {
13384
13480
  continue;
13385
13481
  }
13386
13482
  }
13387
- const result = globSearchFiles(files, pattern, path4);
13483
+ const result = globSearchFiles(files, pattern, path3);
13388
13484
  if (result === "No files found") {
13389
13485
  return [];
13390
13486
  }
@@ -13433,7 +13529,12 @@ var FilesystemBackend = class {
13433
13529
  */
13434
13530
  resolvePath(key) {
13435
13531
  if (this.virtualMode) {
13436
- const normalizedKey = key === "~" ? "/" : key.startsWith("~/") ? `/${key.slice(2)}` : key;
13532
+ let normalizedKey = key;
13533
+ if (normalizedKey === "~" || normalizedKey === "~/") {
13534
+ normalizedKey = "/";
13535
+ } else if (normalizedKey.startsWith("~/")) {
13536
+ normalizedKey = `/${normalizedKey.slice(2)}`;
13537
+ }
13437
13538
  const vpath = normalizedKey.startsWith("/") ? normalizedKey : "/" + normalizedKey;
13438
13539
  if (vpath.includes("..") || vpath.includes("~")) {
13439
13540
  throw new Error("Path traversal not allowed");
@@ -13445,10 +13546,14 @@ var FilesystemBackend = class {
13445
13546
  }
13446
13547
  return full;
13447
13548
  }
13448
- if (path2.isAbsolute(key)) {
13449
- return key;
13549
+ let target = key;
13550
+ if (target.startsWith("~/")) {
13551
+ target = `/${target.slice(2)}`;
13450
13552
  }
13451
- return path2.resolve(this.cwd, key);
13553
+ if (path2.isAbsolute(target)) {
13554
+ return target;
13555
+ }
13556
+ return path2.resolve(this.cwd, target);
13452
13557
  }
13453
13558
  /**
13454
13559
  * List files and directories in the specified directory (non-recursive).
@@ -13960,10 +14065,10 @@ var CompositeBackend = class {
13960
14065
  * @returns List of FileInfo objects with route prefixes added, for files and directories
13961
14066
  * directly in the directory. Directories have a trailing / in their path and is_dir=true.
13962
14067
  */
13963
- async lsInfo(path4) {
14068
+ async lsInfo(path3) {
13964
14069
  for (const [routePrefix, backend] of this.sortedRoutes) {
13965
- if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
13966
- const suffix = path4.substring(routePrefix.length);
14070
+ if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
14071
+ const suffix = path3.substring(routePrefix.length);
13967
14072
  const searchPath = suffix ? "/" + suffix : "/";
13968
14073
  const infos = await backend.lsInfo(searchPath);
13969
14074
  const prefixed = [];
@@ -13976,9 +14081,9 @@ var CompositeBackend = class {
13976
14081
  return prefixed;
13977
14082
  }
13978
14083
  }
13979
- if (path4 === "/") {
14084
+ if (path3 === "/") {
13980
14085
  const results = [];
13981
- const defaultInfos = await this.default.lsInfo(path4);
14086
+ const defaultInfos = await this.default.lsInfo(path3);
13982
14087
  results.push(...defaultInfos);
13983
14088
  for (const [routePrefix] of this.sortedRoutes) {
13984
14089
  results.push({
@@ -13991,7 +14096,7 @@ var CompositeBackend = class {
13991
14096
  results.sort((a, b) => a.path.localeCompare(b.path));
13992
14097
  return results;
13993
14098
  }
13994
- return await this.default.lsInfo(path4);
14099
+ return await this.default.lsInfo(path3);
13995
14100
  }
13996
14101
  /**
13997
14102
  * Read file content, routing to appropriate backend.
@@ -14018,10 +14123,10 @@ var CompositeBackend = class {
14018
14123
  /**
14019
14124
  * Structured search results or error string for invalid input.
14020
14125
  */
14021
- async grepRaw(pattern, path4 = "/", glob = null) {
14126
+ async grepRaw(pattern, path3 = "/", glob = null) {
14022
14127
  for (const [routePrefix, backend] of this.sortedRoutes) {
14023
- if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
14024
- const searchPath = path4.substring(routePrefix.length - 1);
14128
+ if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
14129
+ const searchPath = path3.substring(routePrefix.length - 1);
14025
14130
  const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
14026
14131
  if (typeof raw === "string") {
14027
14132
  return raw;
@@ -14033,7 +14138,7 @@ var CompositeBackend = class {
14033
14138
  }
14034
14139
  }
14035
14140
  const allMatches = [];
14036
- const rawDefault = await this.default.grepRaw(pattern, path4, glob);
14141
+ const rawDefault = await this.default.grepRaw(pattern, path3, glob);
14037
14142
  if (typeof rawDefault === "string") {
14038
14143
  return rawDefault;
14039
14144
  }
@@ -14055,11 +14160,11 @@ var CompositeBackend = class {
14055
14160
  /**
14056
14161
  * Structured glob matching returning FileInfo objects.
14057
14162
  */
14058
- async globInfo(pattern, path4 = "/") {
14163
+ async globInfo(pattern, path3 = "/") {
14059
14164
  const results = [];
14060
14165
  for (const [routePrefix, backend] of this.sortedRoutes) {
14061
- if (path4.startsWith(routePrefix.replace(/\/$/, ""))) {
14062
- const searchPath = path4.substring(routePrefix.length - 1);
14166
+ if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
14167
+ const searchPath = path3.substring(routePrefix.length - 1);
14063
14168
  const infos = await backend.globInfo(pattern, searchPath || "/");
14064
14169
  return infos.map((fi) => ({
14065
14170
  ...fi,
@@ -14067,7 +14172,7 @@ var CompositeBackend = class {
14067
14172
  }));
14068
14173
  }
14069
14174
  }
14070
- const defaultInfos = await this.default.globInfo(pattern, path4);
14175
+ const defaultInfos = await this.default.globInfo(pattern, path3);
14071
14176
  results.push(...defaultInfos);
14072
14177
  for (const [routePrefix, backend] of Object.entries(this.routes)) {
14073
14178
  const infos = await backend.globInfo(pattern, "/");
@@ -14115,11 +14220,11 @@ var MemoryBackend = class {
14115
14220
  getFiles() {
14116
14221
  return Object.fromEntries(this.files);
14117
14222
  }
14118
- lsInfo(path4) {
14223
+ lsInfo(path3) {
14119
14224
  const files = this.getFiles();
14120
14225
  const infos = [];
14121
14226
  const subdirs = /* @__PURE__ */ new Set();
14122
- const normalizedPath = path4.endsWith("/") ? path4 : path4 + "/";
14227
+ const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
14123
14228
  for (const [k, fd] of Object.entries(files)) {
14124
14229
  if (!k.startsWith(normalizedPath)) {
14125
14230
  continue;
@@ -14194,13 +14299,13 @@ var MemoryBackend = class {
14194
14299
  this.files.set(filePath, newFileData);
14195
14300
  return { path: filePath, filesUpdate: null, occurrences };
14196
14301
  }
14197
- grepRaw(pattern, path4 = "/", glob = null) {
14302
+ grepRaw(pattern, path3 = "/", glob = null) {
14198
14303
  const files = this.getFiles();
14199
- return grepMatchesFromFiles(files, pattern, path4, glob);
14304
+ return grepMatchesFromFiles(files, pattern, path3, glob);
14200
14305
  }
14201
- globInfo(pattern, path4 = "/") {
14306
+ globInfo(pattern, path3 = "/") {
14202
14307
  const files = this.getFiles();
14203
- const result = globSearchFiles(files, pattern, path4);
14308
+ const result = globSearchFiles(files, pattern, path3);
14204
14309
  if (result === "No files found") {
14205
14310
  return [];
14206
14311
  }
@@ -16571,7 +16676,7 @@ var SandboxSkillStore = class {
16571
16676
  if (name.includes("..") || name.includes("/") || name.includes("\\")) {
16572
16677
  throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
16573
16678
  }
16574
- return `~/.agents/skills/${name}`;
16679
+ return `/.agent/skills/${name}`;
16575
16680
  }
16576
16681
  /**
16577
16682
  * Get skill file path in sandbox (absolute path with ~/ prefix)
@@ -16638,14 +16743,14 @@ ${body}` : `${frontmatter}
16638
16743
  async getAllSkills(tenantId, context) {
16639
16744
  try {
16640
16745
  const sandbox = await this.getSandbox(tenantId, context);
16641
- const skillsDir = "~/.agents/skills";
16746
+ const skillsDir = "/.agent/skills";
16642
16747
  try {
16643
16748
  await sandbox.file.listPath(skillsDir, { recursive: false });
16644
16749
  } catch (listError) {
16645
16750
  console.log(`[SandboxSkillStore] Skills directory not found, creating: ${skillsDir}`);
16646
16751
  try {
16647
16752
  await sandbox.shell.execCommand({
16648
- command: `mkdir -p ~/.agents/skills`
16753
+ command: `mkdir -p /.agent/skills`
16649
16754
  });
16650
16755
  } catch (mkdirError) {
16651
16756
  console.error(`[SandboxSkillStore] Failed to create skills directory: ${mkdirError.message}`);
@@ -18243,12 +18348,7 @@ var import_microsandbox = require("microsandbox");
18243
18348
 
18244
18349
  // src/sandbox_lattice/MicrosandboxInstance.ts
18245
18350
  function exec(native, cmd, opts) {
18246
- return native.execWith(cmd, (b) => {
18247
- if (opts?.args) b.args(opts.args);
18248
- if (opts?.cwd) b.cwd(opts.cwd);
18249
- if (opts?.timeoutMs) b.timeout(opts.timeoutMs);
18250
- return b;
18251
- });
18351
+ return native.execWithConfig({ cmd, args: opts?.args, cwd: opts?.cwd, timeoutMs: opts?.timeoutMs });
18252
18352
  }
18253
18353
  var MicrosandboxInstance = class {
18254
18354
  constructor(name, native) {
@@ -18256,16 +18356,16 @@ var MicrosandboxInstance = class {
18256
18356
  this.file = {
18257
18357
  readFile: async (file) => {
18258
18358
  const fs3 = this.native.fs();
18259
- const content = await fs3.readToString(file);
18359
+ const content = await fs3.readString(file);
18260
18360
  return { content };
18261
18361
  },
18262
18362
  writeFile: async (file, content) => {
18263
18363
  const fs3 = this.native.fs();
18264
18364
  await fs3.write(file, Buffer.from(content));
18265
18365
  },
18266
- listPath: async (path4, options) => {
18366
+ listPath: async (path3, options) => {
18267
18367
  const fs3 = this.native.fs();
18268
- const entries = await fs3.list(path4);
18368
+ const entries = await fs3.list(path3);
18269
18369
  const files = (entries || []).map((e) => ({
18270
18370
  path: e.path,
18271
18371
  is_dir: e.kind === "directory",
@@ -18274,9 +18374,9 @@ var MicrosandboxInstance = class {
18274
18374
  }));
18275
18375
  return { files };
18276
18376
  },
18277
- findFiles: async (path4, glob) => {
18377
+ findFiles: async (path3, glob) => {
18278
18378
  const output = await exec(this.native, "sh", {
18279
- args: ["-c", `find "${path4}" -name "${glob}" -type f`]
18379
+ args: ["-c", `find "${path3}" -name "${glob}" -type f`]
18280
18380
  });
18281
18381
  const lines = output.stdout().split("\n").filter(Boolean);
18282
18382
  return { files: lines };
@@ -18299,13 +18399,13 @@ var MicrosandboxInstance = class {
18299
18399
  return { matches, line_numbers };
18300
18400
  },
18301
18401
  strReplaceEditor: async (params) => {
18302
- const { path: path4, old_str, new_str, replace_mode } = params;
18402
+ const { path: path3, old_str, new_str, replace_mode } = params;
18303
18403
  const delim = "#";
18304
18404
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18305
18405
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
18306
18406
  const flag = replace_mode === "ALL" ? "g" : "";
18307
18407
  await exec(this.native, "sh", {
18308
- args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`]
18408
+ args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`]
18309
18409
  });
18310
18410
  },
18311
18411
  uploadFile: async (params) => {
@@ -18397,11 +18497,34 @@ var MicrosandboxProvider = class {
18397
18497
  native = void 0;
18398
18498
  }
18399
18499
  if (!native) {
18400
- const builder = import_microsandbox.Sandbox.builder(name).image(this.config.image ?? "python:3.11-slim").cpus(this.config.cpus ?? 1).memory(this.config.memoryMib ?? 512).envs({
18401
- ...this.config.env,
18402
- ...buildSandboxMetadataEnv(config)
18403
- });
18404
- native = await builder.createDetached();
18500
+ try {
18501
+ native = await import_microsandbox.Sandbox.createDetached({
18502
+ name,
18503
+ image: this.config.image ?? "python:3.11-slim",
18504
+ cpus: this.config.cpus ?? 1,
18505
+ memoryMib: this.config.memoryMib ?? 512,
18506
+ env: {
18507
+ ...this.config.env,
18508
+ ...buildSandboxMetadataEnv(config)
18509
+ }
18510
+ });
18511
+ } catch (err) {
18512
+ if (err instanceof Error && err.message.includes("already exists")) {
18513
+ await import_microsandbox.Sandbox.remove(name);
18514
+ native = await import_microsandbox.Sandbox.createDetached({
18515
+ name,
18516
+ image: this.config.image ?? "python:3.11-slim",
18517
+ cpus: this.config.cpus ?? 1,
18518
+ memoryMib: this.config.memoryMib ?? 512,
18519
+ env: {
18520
+ ...this.config.env,
18521
+ ...buildSandboxMetadataEnv(config)
18522
+ }
18523
+ });
18524
+ } else {
18525
+ throw err;
18526
+ }
18527
+ }
18405
18528
  }
18406
18529
  const instance = new MicrosandboxInstance(name, native);
18407
18530
  this.instances.set(name, instance);
@@ -18441,45 +18564,6 @@ var MicrosandboxProvider = class {
18441
18564
  }
18442
18565
  };
18443
18566
 
18444
- // src/sandbox_lattice/pathUtils.ts
18445
- var import_path2 = __toESM(require("path"));
18446
- var SANDBOX_HOME_DIR = "/home/daytona";
18447
- function normalizeExternalSandboxPath(inputPath) {
18448
- if (inputPath === "~") {
18449
- return "~/";
18450
- }
18451
- if (inputPath === SANDBOX_HOME_DIR) {
18452
- return "~/";
18453
- }
18454
- if (inputPath.startsWith(`${SANDBOX_HOME_DIR}/`)) {
18455
- return `~/${inputPath.slice(SANDBOX_HOME_DIR.length + 1)}`;
18456
- }
18457
- if (inputPath.startsWith("~/")) {
18458
- return inputPath;
18459
- }
18460
- if (inputPath.startsWith("/")) {
18461
- return `~${inputPath}`;
18462
- }
18463
- return inputPath;
18464
- }
18465
- function toSandboxRelativePath(inputPath) {
18466
- const canonicalPath = normalizeExternalSandboxPath(inputPath);
18467
- return canonicalPath === "~/" ? "" : canonicalPath.slice(2);
18468
- }
18469
- function toSandboxAbsolutePath(inputPath, homeDir = SANDBOX_HOME_DIR) {
18470
- const relativePath = toSandboxRelativePath(inputPath);
18471
- return relativePath ? import_path2.default.posix.join(homeDir, relativePath) : homeDir;
18472
- }
18473
- function fromSandboxExecutionPath(inputPath, homeDir = SANDBOX_HOME_DIR) {
18474
- if (inputPath === homeDir) {
18475
- return "~/";
18476
- }
18477
- if (inputPath.startsWith(`${homeDir}/`)) {
18478
- return `~/${inputPath.slice(homeDir.length + 1)}`;
18479
- }
18480
- return normalizeExternalSandboxPath(inputPath);
18481
- }
18482
-
18483
18567
  // src/sandbox_lattice/MicrosandboxRemoteInstance.ts
18484
18568
  var MicrosandboxRemoteInstance = class {
18485
18569
  constructor(name, client) {
@@ -18488,43 +18572,43 @@ var MicrosandboxRemoteInstance = class {
18488
18572
  readFile: async (file) => {
18489
18573
  const result = await this.client.readFile(
18490
18574
  this.name,
18491
- toSandboxAbsolutePath(file, SANDBOX_HOME_DIR)
18575
+ normalizeExternalSandboxPath(file)
18492
18576
  );
18493
18577
  return { content: result.content };
18494
18578
  },
18495
18579
  writeFile: async (file, content) => {
18496
18580
  await this.client.writeFile(
18497
18581
  this.name,
18498
- toSandboxAbsolutePath(file, SANDBOX_HOME_DIR),
18582
+ normalizeExternalSandboxPath(file),
18499
18583
  content
18500
18584
  );
18501
18585
  },
18502
- listPath: async (path4, options) => {
18586
+ listPath: async (path3, options) => {
18503
18587
  const result = await this.client.listPath(
18504
18588
  this.name,
18505
- toSandboxAbsolutePath(path4, SANDBOX_HOME_DIR),
18589
+ normalizeExternalSandboxPath(path3),
18506
18590
  options?.recursive
18507
18591
  );
18508
18592
  const files = result.entries.map((entry) => ({
18509
- path: fromSandboxExecutionPath(entry.path, SANDBOX_HOME_DIR),
18593
+ path: normalizeExternalSandboxPath(entry.path),
18510
18594
  is_dir: entry.type === "directory"
18511
18595
  }));
18512
18596
  return { files };
18513
18597
  },
18514
- findFiles: async (path4, glob) => {
18598
+ findFiles: async (path3, glob) => {
18515
18599
  const result = await this.client.findFiles(
18516
18600
  this.name,
18517
- toSandboxAbsolutePath(path4, SANDBOX_HOME_DIR),
18601
+ normalizeExternalSandboxPath(path3),
18518
18602
  glob
18519
18603
  );
18520
18604
  return {
18521
- files: result.files.map((filePath) => fromSandboxExecutionPath(filePath, SANDBOX_HOME_DIR))
18605
+ files: result.files.map((filePath) => normalizeExternalSandboxPath(filePath))
18522
18606
  };
18523
18607
  },
18524
18608
  searchInFile: async (file, regex) => {
18525
18609
  const result = await this.client.searchInFile(
18526
18610
  this.name,
18527
- toSandboxAbsolutePath(file, SANDBOX_HOME_DIR),
18611
+ normalizeExternalSandboxPath(file),
18528
18612
  regex
18529
18613
  );
18530
18614
  return {
@@ -18534,7 +18618,7 @@ var MicrosandboxRemoteInstance = class {
18534
18618
  },
18535
18619
  strReplaceEditor: async (params) => {
18536
18620
  await this.client.replaceInFile(this.name, {
18537
- path: toSandboxAbsolutePath(params.path, SANDBOX_HOME_DIR),
18621
+ path: normalizeExternalSandboxPath(params.path),
18538
18622
  search: params.old_str,
18539
18623
  replace: params.new_str
18540
18624
  });
@@ -18542,14 +18626,14 @@ var MicrosandboxRemoteInstance = class {
18542
18626
  uploadFile: async (params) => {
18543
18627
  await this.client.uploadFile(
18544
18628
  this.name,
18545
- toSandboxAbsolutePath(params.file, SANDBOX_HOME_DIR),
18629
+ normalizeExternalSandboxPath(params.file),
18546
18630
  params.data
18547
18631
  );
18548
18632
  },
18549
18633
  downloadFile: async (params) => {
18550
18634
  const result = await this.client.downloadFile(
18551
18635
  this.name,
18552
- toSandboxAbsolutePath(params.file, SANDBOX_HOME_DIR)
18636
+ normalizeExternalSandboxPath(params.file)
18553
18637
  );
18554
18638
  if (result.contentBase64) {
18555
18639
  return Buffer.from(result.contentBase64, "base64");
@@ -18628,34 +18712,34 @@ var MicrosandboxServiceClient = class {
18628
18712
  method: "GET"
18629
18713
  });
18630
18714
  }
18631
- async readFile(sandboxName, path4) {
18715
+ async readFile(sandboxName, path3) {
18632
18716
  return this.request("/api/files/read", {
18633
18717
  method: "POST",
18634
- body: { sandboxName, path: path4 }
18718
+ body: { sandboxName, path: path3 }
18635
18719
  });
18636
18720
  }
18637
- async writeFile(sandboxName, path4, content) {
18721
+ async writeFile(sandboxName, path3, content) {
18638
18722
  return this.request("/api/files/write", {
18639
18723
  method: "POST",
18640
- body: { sandboxName, path: path4, content }
18724
+ body: { sandboxName, path: path3, content }
18641
18725
  });
18642
18726
  }
18643
- async listPath(sandboxName, path4, recursive) {
18727
+ async listPath(sandboxName, path3, recursive) {
18644
18728
  return this.request("/api/files/list", {
18645
18729
  method: "POST",
18646
- body: { sandboxName, path: path4, recursive }
18730
+ body: { sandboxName, path: path3, recursive }
18647
18731
  });
18648
18732
  }
18649
- async findFiles(sandboxName, path4, pattern) {
18733
+ async findFiles(sandboxName, path3, pattern) {
18650
18734
  return this.request("/api/files/find", {
18651
18735
  method: "POST",
18652
- body: { sandboxName, path: path4, pattern }
18736
+ body: { sandboxName, path: path3, pattern }
18653
18737
  });
18654
18738
  }
18655
- async searchInFile(sandboxName, path4, query) {
18739
+ async searchInFile(sandboxName, path3, query) {
18656
18740
  return this.request("/api/files/search", {
18657
18741
  method: "POST",
18658
- body: { sandboxName, path: path4, query }
18742
+ body: { sandboxName, path: path3, query }
18659
18743
  });
18660
18744
  }
18661
18745
  async replaceInFile(sandboxName, input) {
@@ -18664,14 +18748,14 @@ var MicrosandboxServiceClient = class {
18664
18748
  body: { sandboxName, ...input }
18665
18749
  });
18666
18750
  }
18667
- async uploadFile(sandboxName, path4, content) {
18751
+ async uploadFile(sandboxName, path3, content) {
18668
18752
  return this.request("/api/files/upload", {
18669
18753
  method: "POST",
18670
- body: { sandboxName, path: path4, contentBase64: content.toString("base64") }
18754
+ body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
18671
18755
  });
18672
18756
  }
18673
- async downloadFile(sandboxName, path4) {
18674
- const query = new URLSearchParams({ sandboxName, path: path4 });
18757
+ async downloadFile(sandboxName, path3) {
18758
+ const query = new URLSearchParams({ sandboxName, path: path3 });
18675
18759
  return this.request(`/api/files/download?${query.toString()}`, {
18676
18760
  method: "GET"
18677
18761
  });
@@ -18682,54 +18766,54 @@ var MicrosandboxServiceClient = class {
18682
18766
  body: input
18683
18767
  });
18684
18768
  }
18685
- async volumeFsRead(volumeName, path4) {
18769
+ async volumeFsRead(volumeName, path3) {
18686
18770
  const result = await this.request(
18687
18771
  `/api/volumes/${encodeURIComponent(volumeName)}/fs/read`,
18688
18772
  {
18689
18773
  method: "POST",
18690
- body: { path: path4 }
18774
+ body: { path: path3 }
18691
18775
  }
18692
18776
  );
18693
18777
  return result.content;
18694
18778
  }
18695
- async volumeFsWrite(volumeName, path4, content) {
18779
+ async volumeFsWrite(volumeName, path3, content) {
18696
18780
  await this.request(
18697
18781
  `/api/volumes/${encodeURIComponent(volumeName)}/fs/write`,
18698
18782
  {
18699
18783
  method: "POST",
18700
- body: { path: path4, content }
18784
+ body: { path: path3, content }
18701
18785
  }
18702
18786
  );
18703
18787
  }
18704
- async volumeFsList(volumeName, path4) {
18788
+ async volumeFsList(volumeName, path3) {
18705
18789
  const result = await this.request(
18706
18790
  `/api/volumes/${encodeURIComponent(volumeName)}/fs/list`,
18707
18791
  {
18708
18792
  method: "POST",
18709
- body: { path: path4 }
18793
+ body: { path: path3 }
18710
18794
  }
18711
18795
  );
18712
18796
  return result.entries;
18713
18797
  }
18714
- async volumeFsDownload(volumeName, path4) {
18798
+ async volumeFsDownload(volumeName, path3) {
18715
18799
  const result = await this.request(
18716
- `/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path4)}`,
18800
+ `/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path3)}`,
18717
18801
  {
18718
18802
  method: "GET"
18719
18803
  }
18720
18804
  );
18721
18805
  return Buffer.from(result.contentBase64, "base64");
18722
18806
  }
18723
- async volumeFsUpload(volumeName, path4, data) {
18807
+ async volumeFsUpload(volumeName, path3, data) {
18724
18808
  await this.request(
18725
18809
  `/api/volumes/${encodeURIComponent(volumeName)}/fs/upload`,
18726
18810
  {
18727
18811
  method: "POST",
18728
- body: { path: path4, contentBase64: data.toString("base64") }
18812
+ body: { path: path3, contentBase64: data.toString("base64") }
18729
18813
  }
18730
18814
  );
18731
18815
  }
18732
- async request(path4, init) {
18816
+ async request(path3, init) {
18733
18817
  const headers = {};
18734
18818
  if (init.body) {
18735
18819
  headers["content-type"] = "application/json";
@@ -18737,7 +18821,7 @@ var MicrosandboxServiceClient = class {
18737
18821
  if (this.apiKey) {
18738
18822
  headers.Authorization = `Bearer ${this.apiKey}`;
18739
18823
  }
18740
- const response = await fetch(`${this.baseURL}${path4}`, {
18824
+ const response = await fetch(`${this.baseURL}${path3}`, {
18741
18825
  method: init.method,
18742
18826
  headers: Object.keys(headers).length > 0 ? headers : void 0,
18743
18827
  body: init.body ? JSON.stringify(init.body) : void 0
@@ -18770,7 +18854,7 @@ function parseOptionalNumberEnv(name, fallback) {
18770
18854
  }
18771
18855
  function getDefaultMicrosandboxRemoteConfig() {
18772
18856
  return {
18773
- image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.2",
18857
+ image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.4",
18774
18858
  //"daytonaio/sandbox:0.6.0",
18775
18859
  cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
18776
18860
  memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
@@ -18830,11 +18914,11 @@ var MicrosandboxRemoteProvider = class {
18830
18914
  }
18831
18915
  createVolumeFsClient(volumeName) {
18832
18916
  return {
18833
- read: (path4) => this.client.volumeFsRead(volumeName, path4),
18834
- write: (path4, content) => this.client.volumeFsWrite(volumeName, path4, content),
18835
- list: (path4) => this.client.volumeFsList(volumeName, path4),
18836
- readRaw: (path4) => this.client.volumeFsDownload(volumeName, path4),
18837
- writeRaw: (path4, data) => this.client.volumeFsUpload(volumeName, path4, data)
18917
+ read: (path3) => this.client.volumeFsRead(volumeName, path3),
18918
+ write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
18919
+ list: (path3) => this.client.volumeFsList(volumeName, path3),
18920
+ readRaw: (path3) => this.client.volumeFsDownload(volumeName, path3),
18921
+ writeRaw: (path3, data) => this.client.volumeFsUpload(volumeName, path3, data)
18838
18922
  };
18839
18923
  }
18840
18924
  async listSandboxes() {
@@ -18856,19 +18940,19 @@ var MicrosandboxRemoteProvider = class {
18856
18940
  buildDefaultVolumes(config) {
18857
18941
  const tenantId = config?.tenantId ?? "default";
18858
18942
  const volumes = {
18859
- "/home/daytona/.agents/skills": {
18943
+ "/.agent": {
18860
18944
  type: "named",
18861
18945
  name: buildNamedVolumeName("s", "skills", tenantId)
18862
18946
  }
18863
18947
  };
18864
18948
  if (config?.assistant_id) {
18865
- volumes["/home/daytona/agent"] = {
18949
+ volumes["/agent"] = {
18866
18950
  type: "named",
18867
18951
  name: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id)
18868
18952
  };
18869
18953
  }
18870
18954
  if (config?.projectId) {
18871
- volumes["/home/daytona/project"] = {
18955
+ volumes["/project"] = {
18872
18956
  type: "named",
18873
18957
  name: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId)
18874
18958
  };
@@ -18898,9 +18982,9 @@ var RemoteSandboxInstance = class {
18898
18982
  throw new Error(String(result.error));
18899
18983
  }
18900
18984
  },
18901
- listPath: async (path4, options) => {
18985
+ listPath: async (path3, options) => {
18902
18986
  const result = await this.client.file.listPath({
18903
- path: path4,
18987
+ path: path3,
18904
18988
  recursive: options?.recursive ?? false
18905
18989
  });
18906
18990
  if (!result.ok) {
@@ -18914,8 +18998,8 @@ var RemoteSandboxInstance = class {
18914
18998
  }));
18915
18999
  return { files };
18916
19000
  },
18917
- findFiles: async (path4, glob) => {
18918
- const result = await this.client.file.findFiles({ path: path4, glob });
19001
+ findFiles: async (path3, glob) => {
19002
+ const result = await this.client.file.findFiles({ path: path3, glob });
18919
19003
  if (!result.ok) {
18920
19004
  throw new Error(String(result.error));
18921
19005
  }
@@ -19052,8 +19136,8 @@ var E2BInstance = class {
19052
19136
  writeFile: async (file, content) => {
19053
19137
  await this.native.files.write(file, content);
19054
19138
  },
19055
- listPath: async (path4, options) => {
19056
- const entries = await this.native.files.list(path4);
19139
+ listPath: async (path3, options) => {
19140
+ const entries = await this.native.files.list(path3);
19057
19141
  const files = entries.map((e) => ({
19058
19142
  path: e.path,
19059
19143
  is_dir: e.type === "dir",
@@ -19062,9 +19146,9 @@ var E2BInstance = class {
19062
19146
  }));
19063
19147
  return { files };
19064
19148
  },
19065
- findFiles: async (path4, glob) => {
19149
+ findFiles: async (path3, glob) => {
19066
19150
  const result = await this.native.commands.run(
19067
- `find "${path4}" -name "${glob}" -type f`
19151
+ `find "${path3}" -name "${glob}" -type f`
19068
19152
  );
19069
19153
  const lines = result.stdout.split("\n").filter(Boolean);
19070
19154
  return { files: lines };
@@ -19087,13 +19171,13 @@ var E2BInstance = class {
19087
19171
  return { matches, line_numbers };
19088
19172
  },
19089
19173
  strReplaceEditor: async (params) => {
19090
- const { path: path4, old_str, new_str, replace_mode } = params;
19174
+ const { path: path3, old_str, new_str, replace_mode } = params;
19091
19175
  const delim = "#";
19092
19176
  const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
19093
19177
  const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
19094
19178
  const flag = replace_mode === "ALL" ? "g" : "";
19095
19179
  await this.native.commands.run(
19096
- `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path4}"`
19180
+ `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`
19097
19181
  );
19098
19182
  },
19099
19183
  uploadFile: async (params) => {
@@ -19204,23 +19288,27 @@ var E2BProvider = class {
19204
19288
  var import_sdk = require("@daytonaio/sdk");
19205
19289
 
19206
19290
  // src/sandbox_lattice/DaytonaInstance.ts
19291
+ function toRelativePath(inputPath) {
19292
+ const normalized = normalizeExternalSandboxPath(inputPath);
19293
+ return normalized === "/" ? "" : normalized.slice(1);
19294
+ }
19207
19295
  var DaytonaInstance = class {
19208
19296
  constructor(name, native) {
19209
19297
  this.native = native;
19210
19298
  this.file = {
19211
19299
  readFile: async (file) => {
19212
- const buffer2 = await this.native.fs.downloadFile(toSandboxRelativePath(file));
19300
+ const buffer2 = await this.native.fs.downloadFile(toRelativePath(file));
19213
19301
  return { content: buffer2.toString("utf-8") };
19214
19302
  },
19215
19303
  writeFile: async (file, content) => {
19216
- await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toSandboxRelativePath(file));
19304
+ await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
19217
19305
  },
19218
- listPath: async (path4, options) => {
19219
- const entries = await this.native.fs.listFiles(toSandboxRelativePath(path4));
19306
+ listPath: async (path3, options) => {
19307
+ const entries = await this.native.fs.listFiles(toRelativePath(path3));
19220
19308
  const files = entries.map((e) => {
19221
19309
  const rawPath = e.name || "";
19222
19310
  return {
19223
- path: fromSandboxExecutionPath(rawPath),
19311
+ path: normalizeExternalSandboxPath(rawPath),
19224
19312
  is_dir: e.isDir ?? false,
19225
19313
  size: e.size,
19226
19314
  modified_at: e.modTime ? e.modTime : void 0
@@ -19228,12 +19316,12 @@ var DaytonaInstance = class {
19228
19316
  });
19229
19317
  return { files };
19230
19318
  },
19231
- findFiles: async (path4, glob) => {
19232
- const result = await this.native.fs.searchFiles(toSandboxRelativePath(path4), glob);
19233
- return { files: (result.files || []).map((filePath) => fromSandboxExecutionPath(filePath)) };
19319
+ findFiles: async (path3, glob) => {
19320
+ const result = await this.native.fs.searchFiles(toRelativePath(path3), glob);
19321
+ return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
19234
19322
  },
19235
19323
  searchInFile: async (file, regex) => {
19236
- const matches = await this.native.fs.findFiles(toSandboxRelativePath(file), regex);
19324
+ const matches = await this.native.fs.findFiles(toRelativePath(file), regex);
19237
19325
  const line_numbers = [];
19238
19326
  const matchTexts = [];
19239
19327
  for (const match of matches) {
@@ -19243,8 +19331,8 @@ var DaytonaInstance = class {
19243
19331
  return { matches: matchTexts, line_numbers };
19244
19332
  },
19245
19333
  strReplaceEditor: async (params) => {
19246
- const { path: path4, old_str, new_str, replace_mode } = params;
19247
- const relPath = toSandboxRelativePath(path4);
19334
+ const { path: path3, old_str, new_str, replace_mode } = params;
19335
+ const relPath = toRelativePath(path3);
19248
19336
  if (replace_mode === "ALL") {
19249
19337
  await this.native.fs.replaceInFiles([relPath], old_str, new_str);
19250
19338
  } else {
@@ -19258,10 +19346,10 @@ var DaytonaInstance = class {
19258
19346
  }
19259
19347
  },
19260
19348
  uploadFile: async (params) => {
19261
- await this.native.fs.uploadFile(params.data, toSandboxRelativePath(params.file));
19349
+ await this.native.fs.uploadFile(params.data, toRelativePath(params.file));
19262
19350
  },
19263
19351
  downloadFile: async (params) => {
19264
- const buffer2 = await this.native.fs.downloadFile(toSandboxRelativePath(params.file));
19352
+ const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
19265
19353
  return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
19266
19354
  }
19267
19355
  };
@@ -19377,9 +19465,14 @@ var DaytonaProvider = class {
19377
19465
  if (volumes.length > 0) {
19378
19466
  try {
19379
19467
  for (const vol of volumes) {
19380
- const checkPath = vol.mountPath.replace("/home/daytona/", "");
19381
- await native.fs.listFiles(checkPath);
19382
- console.log(`[DaytonaProvider] Volume mount verified: ~/${checkPath}`);
19468
+ try {
19469
+ await native.fs.listFiles(vol.mountPath);
19470
+ console.log(`[DaytonaProvider] Volume mount verified: ${vol.mountPath}`);
19471
+ } catch {
19472
+ const relPath = vol.mountPath.startsWith("/") ? vol.mountPath.slice(1) : vol.mountPath;
19473
+ await native.fs.listFiles(relPath);
19474
+ console.log(`[DaytonaProvider] Volume mount verified: /${relPath}`);
19475
+ }
19383
19476
  }
19384
19477
  } catch (verifyErr) {
19385
19478
  console.warn(`[DaytonaProvider] Volume mount verification warning: ${verifyErr.message}`);
@@ -19397,9 +19490,9 @@ var DaytonaProvider = class {
19397
19490
  /**
19398
19491
  * Build volume mounts for a sandbox based on RunSandboxConfig.
19399
19492
  * Mounts:
19400
- * ~/.agents/skills → tenants/{tenantId}/skills
19401
- * ~/agent → tenants/{tenantId}/agents/{assistantId}
19402
- * ~/project → tenants/{tenantId}/projects/{projectId}
19493
+ * /.agent → tenants/{tenantId}/skills
19494
+ * /agent → tenants/{tenantId}/agents/{assistantId}
19495
+ * /project → tenants/{tenantId}/projects/{projectId}
19403
19496
  */
19404
19497
  async buildVolumeMounts(config) {
19405
19498
  if (!config || !this.config.volumeName) {
@@ -19413,20 +19506,20 @@ var DaytonaProvider = class {
19413
19506
  const mounts = [];
19414
19507
  mounts.push({
19415
19508
  volumeId: volume.id,
19416
- mountPath: "/home/daytona/.agents/skills",
19509
+ mountPath: "/.agent",
19417
19510
  subpath: `tenants/${tenantId}/skills`
19418
19511
  });
19419
19512
  if (config.assistant_id) {
19420
19513
  mounts.push({
19421
19514
  volumeId: volume.id,
19422
- mountPath: "/home/daytona/agent",
19515
+ mountPath: "/agent",
19423
19516
  subpath: `tenants/${tenantId}/agents/${config.assistant_id}`
19424
19517
  });
19425
19518
  }
19426
19519
  if (config.projectId) {
19427
19520
  mounts.push({
19428
19521
  volumeId: volume.id,
19429
- mountPath: "/home/daytona/project",
19522
+ mountPath: "/project",
19430
19523
  subpath: `tenants/${tenantId}/projects/${config.projectId}`
19431
19524
  });
19432
19525
  }