@axiom-lattice/core 2.1.53 → 2.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +12 -8
- package/dist/index.d.ts +12 -8
- package/dist/index.js +379 -274
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +379 -274
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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(
|
|
3491
|
-
const entries = await this.client.list(
|
|
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
|
-
|
|
3652
|
-
|
|
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 === "/root/.agents" || normalized.startsWith("/root/.agents/")) {
|
|
3692
|
+
return {
|
|
3693
|
+
volumeName: buildNamedVolumeName("s", "skills", tenantId),
|
|
3694
|
+
pathPrefix: "/root/.agents"
|
|
3695
|
+
};
|
|
3653
3696
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
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
|
+
};
|
|
3703
|
+
}
|
|
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
|
|
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
|
|
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 =
|
|
5090
|
+
const filePath = `/root/.agents/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("
|
|
5096
|
+
const listResult = await sandbox.file.listPath("/root/.agents/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
|
-
|
|
5104
|
+
`/root/.agents/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("
|
|
5157
|
+
const result = await sandbox.file.listPath("/root/.agents/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(
|
|
5164
|
+
const fileResult = await sandbox.file.readFile(`/root/.agents/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(
|
|
5277
|
-
const pathStr =
|
|
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,
|
|
5346
|
+
function globSearchFiles(files, pattern, path3 = "/") {
|
|
5295
5347
|
let normalizedPath;
|
|
5296
5348
|
try {
|
|
5297
|
-
normalizedPath = validatePath(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
5512
|
+
lsInfo(path3) {
|
|
5461
5513
|
const files = this.getFiles();
|
|
5462
5514
|
const infos = [];
|
|
5463
5515
|
const subdirs = /* @__PURE__ */ new Set();
|
|
5464
|
-
const normalizedPath =
|
|
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,
|
|
5622
|
+
grepRaw(pattern, path3 = "/", glob = null) {
|
|
5571
5623
|
const files = this.getFiles();
|
|
5572
|
-
return grepMatchesFromFiles(files, pattern,
|
|
5624
|
+
return grepMatchesFromFiles(files, pattern, path3, glob);
|
|
5573
5625
|
}
|
|
5574
5626
|
/**
|
|
5575
5627
|
* Structured glob matching returning FileInfo objects.
|
|
5576
5628
|
*/
|
|
5577
|
-
globInfo(pattern,
|
|
5629
|
+
globInfo(pattern, path3 = "/") {
|
|
5578
5630
|
const files = this.getFiles();
|
|
5579
|
-
const result = globSearchFiles(files, pattern,
|
|
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
|
|
5646
|
-
-
|
|
5647
|
-
-
|
|
5648
|
-
-
|
|
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
|
+
- /root/.agents/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., "
|
|
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
|
|
5674
|
-
const infos = await resolvedBackend.lsInfo(
|
|
5725
|
+
const path3 = input.path || "/";
|
|
5726
|
+
const infos = await resolvedBackend.lsInfo(path3);
|
|
5675
5727
|
if (infos.length === 0) {
|
|
5676
|
-
return `No files found in ${
|
|
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:
|
|
5820
|
-
const infos = await resolvedBackend.globInfo(pattern,
|
|
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:
|
|
5848
|
-
const result = await resolvedBackend.grepRaw(pattern,
|
|
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 "
|
|
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.
|
|
7121
|
-
2.
|
|
7122
|
-
3.
|
|
7123
|
-
4.
|
|
7124
|
-
5.
|
|
7125
|
-
6.
|
|
7126
|
-
7.
|
|
7127
|
-
8.
|
|
7128
|
-
9.
|
|
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
|
|
7135
|
-
- If the current interruption point still feels underspecified, read the most recent one or two
|
|
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
|
-
-
|
|
7143
|
-
-
|
|
7144
|
-
-
|
|
7145
|
-
-
|
|
7146
|
-
-
|
|
7147
|
-
-
|
|
7148
|
-
-
|
|
7149
|
-
-
|
|
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
|
|
7154
|
-
- Treat
|
|
7155
|
-
- Write the actual durable private content into
|
|
7156
|
-
- Use
|
|
7157
|
-
- Prefer writing to
|
|
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
|
|
7173
|
-
- Put working understanding, partial conclusions, and candidate reminders in
|
|
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
|
|
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
|
|
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
|
-
-
|
|
7213
|
-
-
|
|
7214
|
-
-
|
|
7215
|
-
-
|
|
7216
|
-
-
|
|
7217
|
-
-
|
|
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
|
-
-
|
|
7241
|
-
-
|
|
7242
|
-
-
|
|
7243
|
-
-
|
|
7244
|
-
-
|
|
7245
|
-
-
|
|
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
|
-
-
|
|
7250
|
-
-
|
|
7251
|
-
-
|
|
7252
|
-
-
|
|
7253
|
-
-
|
|
7254
|
-
-
|
|
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
|
-
-
|
|
7261
|
-
-
|
|
7262
|
-
-
|
|
7263
|
-
-
|
|
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
|
|
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 = "
|
|
12563
|
+
async grepRaw(pattern, searchPath = "/", glob = null) {
|
|
12468
12564
|
try {
|
|
12469
|
-
const result = await this.sandbox.file.findFiles(searchPath || "
|
|
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(
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
13449
|
-
|
|
13549
|
+
let target = key;
|
|
13550
|
+
if (target.startsWith("~/")) {
|
|
13551
|
+
target = `/${target.slice(2)}`;
|
|
13552
|
+
}
|
|
13553
|
+
if (path2.isAbsolute(target)) {
|
|
13554
|
+
return target;
|
|
13450
13555
|
}
|
|
13451
|
-
return path2.resolve(this.cwd,
|
|
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(
|
|
14068
|
+
async lsInfo(path3) {
|
|
13964
14069
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13965
|
-
if (
|
|
13966
|
-
const suffix =
|
|
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 (
|
|
14084
|
+
if (path3 === "/") {
|
|
13980
14085
|
const results = [];
|
|
13981
|
-
const defaultInfos = await this.default.lsInfo(
|
|
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(
|
|
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,
|
|
14126
|
+
async grepRaw(pattern, path3 = "/", glob = null) {
|
|
14022
14127
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
14023
|
-
if (
|
|
14024
|
-
const searchPath =
|
|
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,
|
|
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,
|
|
14163
|
+
async globInfo(pattern, path3 = "/") {
|
|
14059
14164
|
const results = [];
|
|
14060
14165
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
14061
|
-
if (
|
|
14062
|
-
const searchPath =
|
|
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,
|
|
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(
|
|
14223
|
+
lsInfo(path3) {
|
|
14119
14224
|
const files = this.getFiles();
|
|
14120
14225
|
const infos = [];
|
|
14121
14226
|
const subdirs = /* @__PURE__ */ new Set();
|
|
14122
|
-
const normalizedPath =
|
|
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,
|
|
14302
|
+
grepRaw(pattern, path3 = "/", glob = null) {
|
|
14198
14303
|
const files = this.getFiles();
|
|
14199
|
-
return grepMatchesFromFiles(files, pattern,
|
|
14304
|
+
return grepMatchesFromFiles(files, pattern, path3, glob);
|
|
14200
14305
|
}
|
|
14201
|
-
globInfo(pattern,
|
|
14306
|
+
globInfo(pattern, path3 = "/") {
|
|
14202
14307
|
const files = this.getFiles();
|
|
14203
|
-
const result = globSearchFiles(files, pattern,
|
|
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
|
|
16679
|
+
return `/root/.agents/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 = "
|
|
16746
|
+
const skillsDir = "/root/.agents/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
|
|
16753
|
+
command: `mkdir -p /root/.agents/skills`
|
|
16649
16754
|
});
|
|
16650
16755
|
} catch (mkdirError) {
|
|
16651
16756
|
console.error(`[SandboxSkillStore] Failed to create skills directory: ${mkdirError.message}`);
|
|
@@ -18258,9 +18363,9 @@ var MicrosandboxInstance = class {
|
|
|
18258
18363
|
const fs3 = this.native.fs();
|
|
18259
18364
|
await fs3.write(file, Buffer.from(content));
|
|
18260
18365
|
},
|
|
18261
|
-
listPath: async (
|
|
18366
|
+
listPath: async (path3, options) => {
|
|
18262
18367
|
const fs3 = this.native.fs();
|
|
18263
|
-
const entries = await fs3.list(
|
|
18368
|
+
const entries = await fs3.list(path3);
|
|
18264
18369
|
const files = (entries || []).map((e) => ({
|
|
18265
18370
|
path: e.path,
|
|
18266
18371
|
is_dir: e.kind === "directory",
|
|
@@ -18269,9 +18374,9 @@ var MicrosandboxInstance = class {
|
|
|
18269
18374
|
}));
|
|
18270
18375
|
return { files };
|
|
18271
18376
|
},
|
|
18272
|
-
findFiles: async (
|
|
18377
|
+
findFiles: async (path3, glob) => {
|
|
18273
18378
|
const output = await exec(this.native, "sh", {
|
|
18274
|
-
args: ["-c", `find "${
|
|
18379
|
+
args: ["-c", `find "${path3}" -name "${glob}" -type f`]
|
|
18275
18380
|
});
|
|
18276
18381
|
const lines = output.stdout().split("\n").filter(Boolean);
|
|
18277
18382
|
return { files: lines };
|
|
@@ -18294,13 +18399,13 @@ var MicrosandboxInstance = class {
|
|
|
18294
18399
|
return { matches, line_numbers };
|
|
18295
18400
|
},
|
|
18296
18401
|
strReplaceEditor: async (params) => {
|
|
18297
|
-
const { path:
|
|
18402
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
18298
18403
|
const delim = "#";
|
|
18299
18404
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18300
18405
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18301
18406
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
18302
18407
|
await exec(this.native, "sh", {
|
|
18303
|
-
args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
18408
|
+
args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`]
|
|
18304
18409
|
});
|
|
18305
18410
|
},
|
|
18306
18411
|
uploadFile: async (params) => {
|
|
@@ -18392,16 +18497,34 @@ var MicrosandboxProvider = class {
|
|
|
18392
18497
|
native = void 0;
|
|
18393
18498
|
}
|
|
18394
18499
|
if (!native) {
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
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;
|
|
18403
18526
|
}
|
|
18404
|
-
}
|
|
18527
|
+
}
|
|
18405
18528
|
}
|
|
18406
18529
|
const instance = new MicrosandboxInstance(name, native);
|
|
18407
18530
|
this.instances.set(name, instance);
|
|
@@ -18421,11 +18544,15 @@ var MicrosandboxProvider = class {
|
|
|
18421
18544
|
async stopSandbox(name) {
|
|
18422
18545
|
const instance = this.instances.get(name);
|
|
18423
18546
|
if (instance) {
|
|
18424
|
-
|
|
18547
|
+
try {
|
|
18548
|
+
await instance.stop();
|
|
18549
|
+
} catch {
|
|
18550
|
+
}
|
|
18425
18551
|
}
|
|
18426
18552
|
}
|
|
18427
18553
|
async deleteSandbox(name) {
|
|
18428
18554
|
const instance = this.instances.get(name);
|
|
18555
|
+
this.instances.delete(name);
|
|
18429
18556
|
if (instance) {
|
|
18430
18557
|
try {
|
|
18431
18558
|
await instance.kill();
|
|
@@ -18434,52 +18561,12 @@ var MicrosandboxProvider = class {
|
|
|
18434
18561
|
}
|
|
18435
18562
|
}
|
|
18436
18563
|
await import_microsandbox.Sandbox.remove(name);
|
|
18437
|
-
this.instances.delete(name);
|
|
18438
18564
|
}
|
|
18439
18565
|
async listSandboxes() {
|
|
18440
18566
|
return Array.from(this.instances.values());
|
|
18441
18567
|
}
|
|
18442
18568
|
};
|
|
18443
18569
|
|
|
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
18570
|
// src/sandbox_lattice/MicrosandboxRemoteInstance.ts
|
|
18484
18571
|
var MicrosandboxRemoteInstance = class {
|
|
18485
18572
|
constructor(name, client) {
|
|
@@ -18488,43 +18575,43 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18488
18575
|
readFile: async (file) => {
|
|
18489
18576
|
const result = await this.client.readFile(
|
|
18490
18577
|
this.name,
|
|
18491
|
-
|
|
18578
|
+
normalizeExternalSandboxPath(file)
|
|
18492
18579
|
);
|
|
18493
18580
|
return { content: result.content };
|
|
18494
18581
|
},
|
|
18495
18582
|
writeFile: async (file, content) => {
|
|
18496
18583
|
await this.client.writeFile(
|
|
18497
18584
|
this.name,
|
|
18498
|
-
|
|
18585
|
+
normalizeExternalSandboxPath(file),
|
|
18499
18586
|
content
|
|
18500
18587
|
);
|
|
18501
18588
|
},
|
|
18502
|
-
listPath: async (
|
|
18589
|
+
listPath: async (path3, options) => {
|
|
18503
18590
|
const result = await this.client.listPath(
|
|
18504
18591
|
this.name,
|
|
18505
|
-
|
|
18592
|
+
normalizeExternalSandboxPath(path3),
|
|
18506
18593
|
options?.recursive
|
|
18507
18594
|
);
|
|
18508
18595
|
const files = result.entries.map((entry) => ({
|
|
18509
|
-
path:
|
|
18596
|
+
path: normalizeExternalSandboxPath(entry.path),
|
|
18510
18597
|
is_dir: entry.type === "directory"
|
|
18511
18598
|
}));
|
|
18512
18599
|
return { files };
|
|
18513
18600
|
},
|
|
18514
|
-
findFiles: async (
|
|
18601
|
+
findFiles: async (path3, glob) => {
|
|
18515
18602
|
const result = await this.client.findFiles(
|
|
18516
18603
|
this.name,
|
|
18517
|
-
|
|
18604
|
+
normalizeExternalSandboxPath(path3),
|
|
18518
18605
|
glob
|
|
18519
18606
|
);
|
|
18520
18607
|
return {
|
|
18521
|
-
files: result.files.map((filePath) =>
|
|
18608
|
+
files: result.files.map((filePath) => normalizeExternalSandboxPath(filePath))
|
|
18522
18609
|
};
|
|
18523
18610
|
},
|
|
18524
18611
|
searchInFile: async (file, regex) => {
|
|
18525
18612
|
const result = await this.client.searchInFile(
|
|
18526
18613
|
this.name,
|
|
18527
|
-
|
|
18614
|
+
normalizeExternalSandboxPath(file),
|
|
18528
18615
|
regex
|
|
18529
18616
|
);
|
|
18530
18617
|
return {
|
|
@@ -18534,7 +18621,7 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18534
18621
|
},
|
|
18535
18622
|
strReplaceEditor: async (params) => {
|
|
18536
18623
|
await this.client.replaceInFile(this.name, {
|
|
18537
|
-
path:
|
|
18624
|
+
path: normalizeExternalSandboxPath(params.path),
|
|
18538
18625
|
search: params.old_str,
|
|
18539
18626
|
replace: params.new_str
|
|
18540
18627
|
});
|
|
@@ -18542,14 +18629,14 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18542
18629
|
uploadFile: async (params) => {
|
|
18543
18630
|
await this.client.uploadFile(
|
|
18544
18631
|
this.name,
|
|
18545
|
-
|
|
18632
|
+
normalizeExternalSandboxPath(params.file),
|
|
18546
18633
|
params.data
|
|
18547
18634
|
);
|
|
18548
18635
|
},
|
|
18549
18636
|
downloadFile: async (params) => {
|
|
18550
18637
|
const result = await this.client.downloadFile(
|
|
18551
18638
|
this.name,
|
|
18552
|
-
|
|
18639
|
+
normalizeExternalSandboxPath(params.file)
|
|
18553
18640
|
);
|
|
18554
18641
|
if (result.contentBase64) {
|
|
18555
18642
|
return Buffer.from(result.contentBase64, "base64");
|
|
@@ -18628,34 +18715,34 @@ var MicrosandboxServiceClient = class {
|
|
|
18628
18715
|
method: "GET"
|
|
18629
18716
|
});
|
|
18630
18717
|
}
|
|
18631
|
-
async readFile(sandboxName,
|
|
18718
|
+
async readFile(sandboxName, path3) {
|
|
18632
18719
|
return this.request("/api/files/read", {
|
|
18633
18720
|
method: "POST",
|
|
18634
|
-
body: { sandboxName, path:
|
|
18721
|
+
body: { sandboxName, path: path3 }
|
|
18635
18722
|
});
|
|
18636
18723
|
}
|
|
18637
|
-
async writeFile(sandboxName,
|
|
18724
|
+
async writeFile(sandboxName, path3, content) {
|
|
18638
18725
|
return this.request("/api/files/write", {
|
|
18639
18726
|
method: "POST",
|
|
18640
|
-
body: { sandboxName, path:
|
|
18727
|
+
body: { sandboxName, path: path3, content }
|
|
18641
18728
|
});
|
|
18642
18729
|
}
|
|
18643
|
-
async listPath(sandboxName,
|
|
18730
|
+
async listPath(sandboxName, path3, recursive) {
|
|
18644
18731
|
return this.request("/api/files/list", {
|
|
18645
18732
|
method: "POST",
|
|
18646
|
-
body: { sandboxName, path:
|
|
18733
|
+
body: { sandboxName, path: path3, recursive }
|
|
18647
18734
|
});
|
|
18648
18735
|
}
|
|
18649
|
-
async findFiles(sandboxName,
|
|
18736
|
+
async findFiles(sandboxName, path3, pattern) {
|
|
18650
18737
|
return this.request("/api/files/find", {
|
|
18651
18738
|
method: "POST",
|
|
18652
|
-
body: { sandboxName, path:
|
|
18739
|
+
body: { sandboxName, path: path3, pattern }
|
|
18653
18740
|
});
|
|
18654
18741
|
}
|
|
18655
|
-
async searchInFile(sandboxName,
|
|
18742
|
+
async searchInFile(sandboxName, path3, query) {
|
|
18656
18743
|
return this.request("/api/files/search", {
|
|
18657
18744
|
method: "POST",
|
|
18658
|
-
body: { sandboxName, path:
|
|
18745
|
+
body: { sandboxName, path: path3, query }
|
|
18659
18746
|
});
|
|
18660
18747
|
}
|
|
18661
18748
|
async replaceInFile(sandboxName, input) {
|
|
@@ -18664,14 +18751,14 @@ var MicrosandboxServiceClient = class {
|
|
|
18664
18751
|
body: { sandboxName, ...input }
|
|
18665
18752
|
});
|
|
18666
18753
|
}
|
|
18667
|
-
async uploadFile(sandboxName,
|
|
18754
|
+
async uploadFile(sandboxName, path3, content) {
|
|
18668
18755
|
return this.request("/api/files/upload", {
|
|
18669
18756
|
method: "POST",
|
|
18670
|
-
body: { sandboxName, path:
|
|
18757
|
+
body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
|
|
18671
18758
|
});
|
|
18672
18759
|
}
|
|
18673
|
-
async downloadFile(sandboxName,
|
|
18674
|
-
const query = new URLSearchParams({ sandboxName, path:
|
|
18760
|
+
async downloadFile(sandboxName, path3) {
|
|
18761
|
+
const query = new URLSearchParams({ sandboxName, path: path3 });
|
|
18675
18762
|
return this.request(`/api/files/download?${query.toString()}`, {
|
|
18676
18763
|
method: "GET"
|
|
18677
18764
|
});
|
|
@@ -18682,54 +18769,54 @@ var MicrosandboxServiceClient = class {
|
|
|
18682
18769
|
body: input
|
|
18683
18770
|
});
|
|
18684
18771
|
}
|
|
18685
|
-
async volumeFsRead(volumeName,
|
|
18772
|
+
async volumeFsRead(volumeName, path3) {
|
|
18686
18773
|
const result = await this.request(
|
|
18687
18774
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/read`,
|
|
18688
18775
|
{
|
|
18689
18776
|
method: "POST",
|
|
18690
|
-
body: { path:
|
|
18777
|
+
body: { path: path3 }
|
|
18691
18778
|
}
|
|
18692
18779
|
);
|
|
18693
18780
|
return result.content;
|
|
18694
18781
|
}
|
|
18695
|
-
async volumeFsWrite(volumeName,
|
|
18782
|
+
async volumeFsWrite(volumeName, path3, content) {
|
|
18696
18783
|
await this.request(
|
|
18697
18784
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/write`,
|
|
18698
18785
|
{
|
|
18699
18786
|
method: "POST",
|
|
18700
|
-
body: { path:
|
|
18787
|
+
body: { path: path3, content }
|
|
18701
18788
|
}
|
|
18702
18789
|
);
|
|
18703
18790
|
}
|
|
18704
|
-
async volumeFsList(volumeName,
|
|
18791
|
+
async volumeFsList(volumeName, path3) {
|
|
18705
18792
|
const result = await this.request(
|
|
18706
18793
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/list`,
|
|
18707
18794
|
{
|
|
18708
18795
|
method: "POST",
|
|
18709
|
-
body: { path:
|
|
18796
|
+
body: { path: path3 }
|
|
18710
18797
|
}
|
|
18711
18798
|
);
|
|
18712
18799
|
return result.entries;
|
|
18713
18800
|
}
|
|
18714
|
-
async volumeFsDownload(volumeName,
|
|
18801
|
+
async volumeFsDownload(volumeName, path3) {
|
|
18715
18802
|
const result = await this.request(
|
|
18716
|
-
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(
|
|
18803
|
+
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path3)}`,
|
|
18717
18804
|
{
|
|
18718
18805
|
method: "GET"
|
|
18719
18806
|
}
|
|
18720
18807
|
);
|
|
18721
18808
|
return Buffer.from(result.contentBase64, "base64");
|
|
18722
18809
|
}
|
|
18723
|
-
async volumeFsUpload(volumeName,
|
|
18810
|
+
async volumeFsUpload(volumeName, path3, data) {
|
|
18724
18811
|
await this.request(
|
|
18725
18812
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/upload`,
|
|
18726
18813
|
{
|
|
18727
18814
|
method: "POST",
|
|
18728
|
-
body: { path:
|
|
18815
|
+
body: { path: path3, contentBase64: data.toString("base64") }
|
|
18729
18816
|
}
|
|
18730
18817
|
);
|
|
18731
18818
|
}
|
|
18732
|
-
async request(
|
|
18819
|
+
async request(path3, init) {
|
|
18733
18820
|
const headers = {};
|
|
18734
18821
|
if (init.body) {
|
|
18735
18822
|
headers["content-type"] = "application/json";
|
|
@@ -18737,7 +18824,7 @@ var MicrosandboxServiceClient = class {
|
|
|
18737
18824
|
if (this.apiKey) {
|
|
18738
18825
|
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
18739
18826
|
}
|
|
18740
|
-
const response = await fetch(`${this.baseURL}${
|
|
18827
|
+
const response = await fetch(`${this.baseURL}${path3}`, {
|
|
18741
18828
|
method: init.method,
|
|
18742
18829
|
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
18743
18830
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -18770,7 +18857,7 @@ function parseOptionalNumberEnv(name, fallback) {
|
|
|
18770
18857
|
}
|
|
18771
18858
|
function getDefaultMicrosandboxRemoteConfig() {
|
|
18772
18859
|
return {
|
|
18773
|
-
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.
|
|
18860
|
+
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.4",
|
|
18774
18861
|
//"daytonaio/sandbox:0.6.0",
|
|
18775
18862
|
cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
|
|
18776
18863
|
memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
|
|
@@ -18821,20 +18908,23 @@ var MicrosandboxRemoteProvider = class {
|
|
|
18821
18908
|
return instance;
|
|
18822
18909
|
}
|
|
18823
18910
|
async stopSandbox(name) {
|
|
18824
|
-
|
|
18911
|
+
try {
|
|
18912
|
+
await this.client.stopSandbox(name);
|
|
18913
|
+
} catch {
|
|
18914
|
+
}
|
|
18825
18915
|
this.instances.delete(name);
|
|
18826
18916
|
}
|
|
18827
18917
|
async deleteSandbox(name) {
|
|
18828
|
-
await this.client.deleteSandbox(name);
|
|
18829
18918
|
this.instances.delete(name);
|
|
18919
|
+
await this.client.deleteSandbox(name);
|
|
18830
18920
|
}
|
|
18831
18921
|
createVolumeFsClient(volumeName) {
|
|
18832
18922
|
return {
|
|
18833
|
-
read: (
|
|
18834
|
-
write: (
|
|
18835
|
-
list: (
|
|
18836
|
-
readRaw: (
|
|
18837
|
-
writeRaw: (
|
|
18923
|
+
read: (path3) => this.client.volumeFsRead(volumeName, path3),
|
|
18924
|
+
write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
|
|
18925
|
+
list: (path3) => this.client.volumeFsList(volumeName, path3),
|
|
18926
|
+
readRaw: (path3) => this.client.volumeFsDownload(volumeName, path3),
|
|
18927
|
+
writeRaw: (path3, data) => this.client.volumeFsUpload(volumeName, path3, data)
|
|
18838
18928
|
};
|
|
18839
18929
|
}
|
|
18840
18930
|
async listSandboxes() {
|
|
@@ -18856,19 +18946,19 @@ var MicrosandboxRemoteProvider = class {
|
|
|
18856
18946
|
buildDefaultVolumes(config) {
|
|
18857
18947
|
const tenantId = config?.tenantId ?? "default";
|
|
18858
18948
|
const volumes = {
|
|
18859
|
-
"/
|
|
18949
|
+
"/root/.agents": {
|
|
18860
18950
|
type: "named",
|
|
18861
18951
|
name: buildNamedVolumeName("s", "skills", tenantId)
|
|
18862
18952
|
}
|
|
18863
18953
|
};
|
|
18864
18954
|
if (config?.assistant_id) {
|
|
18865
|
-
volumes["/
|
|
18955
|
+
volumes["/agent"] = {
|
|
18866
18956
|
type: "named",
|
|
18867
18957
|
name: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id)
|
|
18868
18958
|
};
|
|
18869
18959
|
}
|
|
18870
18960
|
if (config?.projectId) {
|
|
18871
|
-
volumes["/
|
|
18961
|
+
volumes["/project"] = {
|
|
18872
18962
|
type: "named",
|
|
18873
18963
|
name: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId)
|
|
18874
18964
|
};
|
|
@@ -18898,9 +18988,9 @@ var RemoteSandboxInstance = class {
|
|
|
18898
18988
|
throw new Error(String(result.error));
|
|
18899
18989
|
}
|
|
18900
18990
|
},
|
|
18901
|
-
listPath: async (
|
|
18991
|
+
listPath: async (path3, options) => {
|
|
18902
18992
|
const result = await this.client.file.listPath({
|
|
18903
|
-
path:
|
|
18993
|
+
path: path3,
|
|
18904
18994
|
recursive: options?.recursive ?? false
|
|
18905
18995
|
});
|
|
18906
18996
|
if (!result.ok) {
|
|
@@ -18914,8 +19004,8 @@ var RemoteSandboxInstance = class {
|
|
|
18914
19004
|
}));
|
|
18915
19005
|
return { files };
|
|
18916
19006
|
},
|
|
18917
|
-
findFiles: async (
|
|
18918
|
-
const result = await this.client.file.findFiles({ path:
|
|
19007
|
+
findFiles: async (path3, glob) => {
|
|
19008
|
+
const result = await this.client.file.findFiles({ path: path3, glob });
|
|
18919
19009
|
if (!result.ok) {
|
|
18920
19010
|
throw new Error(String(result.error));
|
|
18921
19011
|
}
|
|
@@ -19052,8 +19142,8 @@ var E2BInstance = class {
|
|
|
19052
19142
|
writeFile: async (file, content) => {
|
|
19053
19143
|
await this.native.files.write(file, content);
|
|
19054
19144
|
},
|
|
19055
|
-
listPath: async (
|
|
19056
|
-
const entries = await this.native.files.list(
|
|
19145
|
+
listPath: async (path3, options) => {
|
|
19146
|
+
const entries = await this.native.files.list(path3);
|
|
19057
19147
|
const files = entries.map((e) => ({
|
|
19058
19148
|
path: e.path,
|
|
19059
19149
|
is_dir: e.type === "dir",
|
|
@@ -19062,9 +19152,9 @@ var E2BInstance = class {
|
|
|
19062
19152
|
}));
|
|
19063
19153
|
return { files };
|
|
19064
19154
|
},
|
|
19065
|
-
findFiles: async (
|
|
19155
|
+
findFiles: async (path3, glob) => {
|
|
19066
19156
|
const result = await this.native.commands.run(
|
|
19067
|
-
`find "${
|
|
19157
|
+
`find "${path3}" -name "${glob}" -type f`
|
|
19068
19158
|
);
|
|
19069
19159
|
const lines = result.stdout.split("\n").filter(Boolean);
|
|
19070
19160
|
return { files: lines };
|
|
@@ -19087,13 +19177,13 @@ var E2BInstance = class {
|
|
|
19087
19177
|
return { matches, line_numbers };
|
|
19088
19178
|
},
|
|
19089
19179
|
strReplaceEditor: async (params) => {
|
|
19090
|
-
const { path:
|
|
19180
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
19091
19181
|
const delim = "#";
|
|
19092
19182
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
19093
19183
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
19094
19184
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
19095
19185
|
await this.native.commands.run(
|
|
19096
|
-
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
19186
|
+
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`
|
|
19097
19187
|
);
|
|
19098
19188
|
},
|
|
19099
19189
|
uploadFile: async (params) => {
|
|
@@ -19185,15 +19275,18 @@ var E2BProvider = class {
|
|
|
19185
19275
|
async stopSandbox(name) {
|
|
19186
19276
|
const instance = this.instances.get(name);
|
|
19187
19277
|
if (instance) {
|
|
19188
|
-
|
|
19278
|
+
try {
|
|
19279
|
+
await instance.stop();
|
|
19280
|
+
} catch {
|
|
19281
|
+
}
|
|
19189
19282
|
}
|
|
19190
19283
|
}
|
|
19191
19284
|
async deleteSandbox(name) {
|
|
19192
19285
|
const instance = this.instances.get(name);
|
|
19286
|
+
this.instances.delete(name);
|
|
19193
19287
|
if (instance) {
|
|
19194
19288
|
await instance.kill();
|
|
19195
19289
|
}
|
|
19196
|
-
this.instances.delete(name);
|
|
19197
19290
|
}
|
|
19198
19291
|
async listSandboxes() {
|
|
19199
19292
|
return Array.from(this.instances.values());
|
|
@@ -19204,23 +19297,27 @@ var E2BProvider = class {
|
|
|
19204
19297
|
var import_sdk = require("@daytonaio/sdk");
|
|
19205
19298
|
|
|
19206
19299
|
// src/sandbox_lattice/DaytonaInstance.ts
|
|
19300
|
+
function toRelativePath(inputPath) {
|
|
19301
|
+
const normalized = normalizeExternalSandboxPath(inputPath);
|
|
19302
|
+
return normalized === "/" ? "" : normalized.slice(1);
|
|
19303
|
+
}
|
|
19207
19304
|
var DaytonaInstance = class {
|
|
19208
19305
|
constructor(name, native) {
|
|
19209
19306
|
this.native = native;
|
|
19210
19307
|
this.file = {
|
|
19211
19308
|
readFile: async (file) => {
|
|
19212
|
-
const buffer2 = await this.native.fs.downloadFile(
|
|
19309
|
+
const buffer2 = await this.native.fs.downloadFile(toRelativePath(file));
|
|
19213
19310
|
return { content: buffer2.toString("utf-8") };
|
|
19214
19311
|
},
|
|
19215
19312
|
writeFile: async (file, content) => {
|
|
19216
|
-
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"),
|
|
19313
|
+
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
|
|
19217
19314
|
},
|
|
19218
|
-
listPath: async (
|
|
19219
|
-
const entries = await this.native.fs.listFiles(
|
|
19315
|
+
listPath: async (path3, options) => {
|
|
19316
|
+
const entries = await this.native.fs.listFiles(toRelativePath(path3));
|
|
19220
19317
|
const files = entries.map((e) => {
|
|
19221
19318
|
const rawPath = e.name || "";
|
|
19222
19319
|
return {
|
|
19223
|
-
path:
|
|
19320
|
+
path: normalizeExternalSandboxPath(rawPath),
|
|
19224
19321
|
is_dir: e.isDir ?? false,
|
|
19225
19322
|
size: e.size,
|
|
19226
19323
|
modified_at: e.modTime ? e.modTime : void 0
|
|
@@ -19228,12 +19325,12 @@ var DaytonaInstance = class {
|
|
|
19228
19325
|
});
|
|
19229
19326
|
return { files };
|
|
19230
19327
|
},
|
|
19231
|
-
findFiles: async (
|
|
19232
|
-
const result = await this.native.fs.searchFiles(
|
|
19233
|
-
return { files: (result.files || []).map((filePath) =>
|
|
19328
|
+
findFiles: async (path3, glob) => {
|
|
19329
|
+
const result = await this.native.fs.searchFiles(toRelativePath(path3), glob);
|
|
19330
|
+
return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
|
|
19234
19331
|
},
|
|
19235
19332
|
searchInFile: async (file, regex) => {
|
|
19236
|
-
const matches = await this.native.fs.findFiles(
|
|
19333
|
+
const matches = await this.native.fs.findFiles(toRelativePath(file), regex);
|
|
19237
19334
|
const line_numbers = [];
|
|
19238
19335
|
const matchTexts = [];
|
|
19239
19336
|
for (const match of matches) {
|
|
@@ -19243,8 +19340,8 @@ var DaytonaInstance = class {
|
|
|
19243
19340
|
return { matches: matchTexts, line_numbers };
|
|
19244
19341
|
},
|
|
19245
19342
|
strReplaceEditor: async (params) => {
|
|
19246
|
-
const { path:
|
|
19247
|
-
const relPath =
|
|
19343
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
19344
|
+
const relPath = toRelativePath(path3);
|
|
19248
19345
|
if (replace_mode === "ALL") {
|
|
19249
19346
|
await this.native.fs.replaceInFiles([relPath], old_str, new_str);
|
|
19250
19347
|
} else {
|
|
@@ -19258,10 +19355,10 @@ var DaytonaInstance = class {
|
|
|
19258
19355
|
}
|
|
19259
19356
|
},
|
|
19260
19357
|
uploadFile: async (params) => {
|
|
19261
|
-
await this.native.fs.uploadFile(params.data,
|
|
19358
|
+
await this.native.fs.uploadFile(params.data, toRelativePath(params.file));
|
|
19262
19359
|
},
|
|
19263
19360
|
downloadFile: async (params) => {
|
|
19264
|
-
const buffer2 = await this.native.fs.downloadFile(
|
|
19361
|
+
const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
|
|
19265
19362
|
return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
|
|
19266
19363
|
}
|
|
19267
19364
|
};
|
|
@@ -19377,9 +19474,14 @@ var DaytonaProvider = class {
|
|
|
19377
19474
|
if (volumes.length > 0) {
|
|
19378
19475
|
try {
|
|
19379
19476
|
for (const vol of volumes) {
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19477
|
+
try {
|
|
19478
|
+
await native.fs.listFiles(vol.mountPath);
|
|
19479
|
+
console.log(`[DaytonaProvider] Volume mount verified: ${vol.mountPath}`);
|
|
19480
|
+
} catch {
|
|
19481
|
+
const relPath = vol.mountPath.startsWith("/") ? vol.mountPath.slice(1) : vol.mountPath;
|
|
19482
|
+
await native.fs.listFiles(relPath);
|
|
19483
|
+
console.log(`[DaytonaProvider] Volume mount verified: /${relPath}`);
|
|
19484
|
+
}
|
|
19383
19485
|
}
|
|
19384
19486
|
} catch (verifyErr) {
|
|
19385
19487
|
console.warn(`[DaytonaProvider] Volume mount verification warning: ${verifyErr.message}`);
|
|
@@ -19397,9 +19499,9 @@ var DaytonaProvider = class {
|
|
|
19397
19499
|
/**
|
|
19398
19500
|
* Build volume mounts for a sandbox based on RunSandboxConfig.
|
|
19399
19501
|
* Mounts:
|
|
19400
|
-
*
|
|
19401
|
-
*
|
|
19402
|
-
*
|
|
19502
|
+
* /root/.agents → tenants/{tenantId}/skills
|
|
19503
|
+
* /agent → tenants/{tenantId}/agents/{assistantId}
|
|
19504
|
+
* /project → tenants/{tenantId}/projects/{projectId}
|
|
19403
19505
|
*/
|
|
19404
19506
|
async buildVolumeMounts(config) {
|
|
19405
19507
|
if (!config || !this.config.volumeName) {
|
|
@@ -19413,20 +19515,20 @@ var DaytonaProvider = class {
|
|
|
19413
19515
|
const mounts = [];
|
|
19414
19516
|
mounts.push({
|
|
19415
19517
|
volumeId: volume.id,
|
|
19416
|
-
mountPath: "/
|
|
19518
|
+
mountPath: "/root/.agents",
|
|
19417
19519
|
subpath: `tenants/${tenantId}/skills`
|
|
19418
19520
|
});
|
|
19419
19521
|
if (config.assistant_id) {
|
|
19420
19522
|
mounts.push({
|
|
19421
19523
|
volumeId: volume.id,
|
|
19422
|
-
mountPath: "/
|
|
19524
|
+
mountPath: "/agent",
|
|
19423
19525
|
subpath: `tenants/${tenantId}/agents/${config.assistant_id}`
|
|
19424
19526
|
});
|
|
19425
19527
|
}
|
|
19426
19528
|
if (config.projectId) {
|
|
19427
19529
|
mounts.push({
|
|
19428
19530
|
volumeId: volume.id,
|
|
19429
|
-
mountPath: "/
|
|
19531
|
+
mountPath: "/project",
|
|
19430
19532
|
subpath: `tenants/${tenantId}/projects/${config.projectId}`
|
|
19431
19533
|
});
|
|
19432
19534
|
}
|
|
@@ -19475,18 +19577,21 @@ var DaytonaProvider = class {
|
|
|
19475
19577
|
async stopSandbox(name) {
|
|
19476
19578
|
const instance = this.instances.get(name);
|
|
19477
19579
|
if (instance) {
|
|
19478
|
-
|
|
19580
|
+
try {
|
|
19581
|
+
await instance.stop();
|
|
19582
|
+
} catch {
|
|
19583
|
+
}
|
|
19479
19584
|
}
|
|
19480
19585
|
}
|
|
19481
19586
|
async deleteSandbox(name) {
|
|
19482
19587
|
const instance = this.instances.get(name);
|
|
19588
|
+
this.instances.delete(name);
|
|
19483
19589
|
if (instance) {
|
|
19484
19590
|
try {
|
|
19485
19591
|
await instance.kill();
|
|
19486
19592
|
} catch {
|
|
19487
19593
|
}
|
|
19488
19594
|
}
|
|
19489
|
-
this.instances.delete(name);
|
|
19490
19595
|
}
|
|
19491
19596
|
async listSandboxes() {
|
|
19492
19597
|
return Array.from(this.instances.values());
|