@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.mjs
CHANGED
|
@@ -3268,13 +3268,15 @@ import z15 from "zod";
|
|
|
3268
3268
|
|
|
3269
3269
|
// src/deep_agent_new/backends/volumeFilesystem.ts
|
|
3270
3270
|
var VolumeFilesystem = class {
|
|
3271
|
-
constructor(client) {
|
|
3271
|
+
constructor(client, mountPrefix = "") {
|
|
3272
3272
|
this.client = client;
|
|
3273
|
+
this.mountPrefix = mountPrefix;
|
|
3273
3274
|
}
|
|
3274
|
-
async lsInfo(
|
|
3275
|
-
const entries = await this.client.list(
|
|
3275
|
+
async lsInfo(path3) {
|
|
3276
|
+
const entries = await this.client.list(path3);
|
|
3277
|
+
const prefix = this.mountPrefix.endsWith("/") ? this.mountPrefix : this.mountPrefix + "/";
|
|
3276
3278
|
return entries.map((entry) => ({
|
|
3277
|
-
path: entry.path,
|
|
3279
|
+
path: entry.path.startsWith("/") ? entry.path : prefix + entry.path,
|
|
3278
3280
|
is_dir: entry.kind === "directory",
|
|
3279
3281
|
size: entry.size,
|
|
3280
3282
|
modified_at: entry.modified ? new Date(entry.modified).toISOString() : void 0
|
|
@@ -3320,6 +3322,20 @@ var VolumeFilesystem = class {
|
|
|
3320
3322
|
}
|
|
3321
3323
|
};
|
|
3322
3324
|
|
|
3325
|
+
// src/sandbox_lattice/pathUtils.ts
|
|
3326
|
+
function normalizeExternalSandboxPath(inputPath) {
|
|
3327
|
+
if (inputPath === "~" || inputPath === "~/") {
|
|
3328
|
+
return "/";
|
|
3329
|
+
}
|
|
3330
|
+
if (inputPath.startsWith("~/")) {
|
|
3331
|
+
return `/${inputPath.slice(2)}`;
|
|
3332
|
+
}
|
|
3333
|
+
if (inputPath.startsWith("/")) {
|
|
3334
|
+
return inputPath;
|
|
3335
|
+
}
|
|
3336
|
+
return `/${inputPath}`;
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3323
3339
|
// src/sandbox_lattice/utils.ts
|
|
3324
3340
|
import { createHash } from "crypto";
|
|
3325
3341
|
function normalizeSandboxName(name) {
|
|
@@ -3356,6 +3372,20 @@ function buildNamedVolumeName(prefix, ...parts) {
|
|
|
3356
3372
|
}
|
|
3357
3373
|
|
|
3358
3374
|
// src/sandbox_lattice/SandboxLatticeManager.ts
|
|
3375
|
+
function stripPrefixClient(client, prefix) {
|
|
3376
|
+
const strip = (p) => {
|
|
3377
|
+
if (p === prefix || p === prefix + "/") return "";
|
|
3378
|
+
if (p.startsWith(prefix + "/")) return p.slice(prefix.length + 1);
|
|
3379
|
+
return p;
|
|
3380
|
+
};
|
|
3381
|
+
return {
|
|
3382
|
+
read: (p) => client.read(strip(p)),
|
|
3383
|
+
write: (p, c) => client.write(strip(p), c),
|
|
3384
|
+
list: (p) => client.list(strip(p)),
|
|
3385
|
+
readRaw: (p) => client.readRaw(strip(p)),
|
|
3386
|
+
writeRaw: (p, d) => client.writeRaw(strip(p), d)
|
|
3387
|
+
};
|
|
3388
|
+
}
|
|
3359
3389
|
function computeSandboxName(config) {
|
|
3360
3390
|
switch (config.vmIsolation) {
|
|
3361
3391
|
case "global":
|
|
@@ -3427,17 +3457,39 @@ var SandboxLatticeManager = class _SandboxLatticeManager extends BaseLatticeMana
|
|
|
3427
3457
|
return this.createSandbox(name, config);
|
|
3428
3458
|
}
|
|
3429
3459
|
async getVolumeBackend(config) {
|
|
3460
|
+
return this.getVolumeBackendForPath(config, "/project");
|
|
3461
|
+
}
|
|
3462
|
+
async getVolumeBackendForPath(config, filePath) {
|
|
3430
3463
|
const provider = this._requireProvider();
|
|
3431
3464
|
if (!provider.createVolumeFsClient) {
|
|
3432
3465
|
return null;
|
|
3433
3466
|
}
|
|
3434
3467
|
const tenantId = config.tenantId ?? "default";
|
|
3435
|
-
|
|
3436
|
-
|
|
3468
|
+
const mapping = this._resolveVolumeForPath(config, tenantId, filePath);
|
|
3469
|
+
if (!mapping) return null;
|
|
3470
|
+
const client = provider.createVolumeFsClient(mapping.volumeName);
|
|
3471
|
+
return new VolumeFilesystem(stripPrefixClient(client, mapping.pathPrefix), mapping.pathPrefix);
|
|
3472
|
+
}
|
|
3473
|
+
_resolveVolumeForPath(config, tenantId, filePath) {
|
|
3474
|
+
const normalized = normalizeExternalSandboxPath(filePath);
|
|
3475
|
+
if (normalized === "/root/.agents" || normalized.startsWith("/root/.agents/")) {
|
|
3476
|
+
return {
|
|
3477
|
+
volumeName: buildNamedVolumeName("s", "skills", tenantId),
|
|
3478
|
+
pathPrefix: "/root/.agents"
|
|
3479
|
+
};
|
|
3437
3480
|
}
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3481
|
+
if (normalized === "/agent" || normalized.startsWith("/agent/")) {
|
|
3482
|
+
if (!config.assistant_id) return null;
|
|
3483
|
+
return {
|
|
3484
|
+
volumeName: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id),
|
|
3485
|
+
pathPrefix: "/agent"
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
if (!config.projectId) return null;
|
|
3489
|
+
return {
|
|
3490
|
+
volumeName: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId),
|
|
3491
|
+
pathPrefix: "/project"
|
|
3492
|
+
};
|
|
3441
3493
|
}
|
|
3442
3494
|
async createSandbox(name, config) {
|
|
3443
3495
|
const provider = this._requireProvider();
|
|
@@ -3491,9 +3543,9 @@ var SHELL_EXEC_DESCRIPTION = `Execute a shell command in the sandbox environment
|
|
|
3491
3543
|
|
|
3492
3544
|
Use this to run CLI tools, install packages, inspect files, or perform any operation that requires a shell.
|
|
3493
3545
|
|
|
3494
|
-
To execute a code file, pass the appropriate command (e.g. "python
|
|
3546
|
+
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.
|
|
3495
3547
|
|
|
3496
|
-
Note: the working directory defaults to
|
|
3548
|
+
Note: the working directory defaults to /. Project files are under /project/. Use paths like "/project/file.txt".`;
|
|
3497
3549
|
function formatExecutionResult(data) {
|
|
3498
3550
|
const parts = [];
|
|
3499
3551
|
if (data.output) {
|
|
@@ -4826,13 +4878,13 @@ var createLoadSkillContentTool = () => {
|
|
|
4826
4878
|
async (input, _exe_config) => {
|
|
4827
4879
|
try {
|
|
4828
4880
|
const sandbox = await getSandboxFromExeConfig(_exe_config);
|
|
4829
|
-
const filePath =
|
|
4881
|
+
const filePath = `/root/.agents/skills/${input.skill_name}/SKILL.md`;
|
|
4830
4882
|
let content;
|
|
4831
4883
|
try {
|
|
4832
4884
|
const result2 = await sandbox.file.readFile(filePath);
|
|
4833
4885
|
content = result2.content;
|
|
4834
4886
|
} catch {
|
|
4835
|
-
const listResult = await sandbox.file.listPath("
|
|
4887
|
+
const listResult = await sandbox.file.listPath("/root/.agents/skills", { recursive: false });
|
|
4836
4888
|
const available = listResult.files.filter((f) => f.is_dir).map((f) => f.path.split("/").pop()).filter(Boolean).join(", ");
|
|
4837
4889
|
return `Skill "${input.skill_name}" not found. Available skills: ${available}`;
|
|
4838
4890
|
}
|
|
@@ -4840,7 +4892,7 @@ var createLoadSkillContentTool = () => {
|
|
|
4840
4892
|
let result = buildSkillFile(meta, body);
|
|
4841
4893
|
try {
|
|
4842
4894
|
const resourcesResult = await sandbox.file.listPath(
|
|
4843
|
-
|
|
4895
|
+
`/root/.agents/skills/${input.skill_name}/resources`,
|
|
4844
4896
|
{ recursive: false }
|
|
4845
4897
|
);
|
|
4846
4898
|
const resources = resourcesResult.files.map((f) => f.path.split("/").pop()).filter(Boolean);
|
|
@@ -4893,14 +4945,14 @@ function createSkillMiddleware(params = {}) {
|
|
|
4893
4945
|
projectId: runConfig.projectId,
|
|
4894
4946
|
vmIsolation: "project"
|
|
4895
4947
|
});
|
|
4896
|
-
const result = await sandbox.file.listPath("
|
|
4948
|
+
const result = await sandbox.file.listPath("/root/.agents/skills", { recursive: false });
|
|
4897
4949
|
const allSkills = [];
|
|
4898
4950
|
for (const entry of result.files) {
|
|
4899
4951
|
if (!entry.is_dir) continue;
|
|
4900
4952
|
const skillName = entry.path.split("/").pop();
|
|
4901
4953
|
if (!skillName) continue;
|
|
4902
4954
|
try {
|
|
4903
|
-
const fileResult = await sandbox.file.readFile(
|
|
4955
|
+
const fileResult = await sandbox.file.readFile(`/root/.agents/skills/${skillName}/SKILL.md`);
|
|
4904
4956
|
const { meta } = parseSkillFrontmatter(fileResult.content);
|
|
4905
4957
|
allSkills.push({
|
|
4906
4958
|
id: skillName,
|
|
@@ -5064,16 +5116,16 @@ function truncateIfTooLong(result) {
|
|
|
5064
5116
|
}
|
|
5065
5117
|
return result;
|
|
5066
5118
|
}
|
|
5067
|
-
function validatePath(
|
|
5068
|
-
const pathStr =
|
|
5119
|
+
function validatePath(path3) {
|
|
5120
|
+
const pathStr = path3 || "/";
|
|
5069
5121
|
if (!pathStr || pathStr.trim() === "") {
|
|
5070
5122
|
throw new Error("Path cannot be empty");
|
|
5071
5123
|
}
|
|
5072
5124
|
let normalized;
|
|
5073
|
-
if (pathStr === "~") {
|
|
5074
|
-
normalized = "
|
|
5125
|
+
if (pathStr === "~" || pathStr === "~/") {
|
|
5126
|
+
normalized = "/";
|
|
5075
5127
|
} else if (pathStr.startsWith("~/")) {
|
|
5076
|
-
normalized = pathStr
|
|
5128
|
+
normalized = `/${pathStr.slice(2)}`;
|
|
5077
5129
|
} else {
|
|
5078
5130
|
normalized = pathStr.startsWith("/") ? pathStr : "/" + pathStr;
|
|
5079
5131
|
}
|
|
@@ -5082,10 +5134,10 @@ function validatePath(path4) {
|
|
|
5082
5134
|
}
|
|
5083
5135
|
return normalized;
|
|
5084
5136
|
}
|
|
5085
|
-
function globSearchFiles(files, pattern,
|
|
5137
|
+
function globSearchFiles(files, pattern, path3 = "/") {
|
|
5086
5138
|
let normalizedPath;
|
|
5087
5139
|
try {
|
|
5088
|
-
normalizedPath = validatePath(
|
|
5140
|
+
normalizedPath = validatePath(path3);
|
|
5089
5141
|
} catch {
|
|
5090
5142
|
return "No files found";
|
|
5091
5143
|
}
|
|
@@ -5137,7 +5189,7 @@ function formatGrepResults(results, outputMode) {
|
|
|
5137
5189
|
}
|
|
5138
5190
|
return lines.join("\n");
|
|
5139
5191
|
}
|
|
5140
|
-
function grepSearchFiles(files, pattern,
|
|
5192
|
+
function grepSearchFiles(files, pattern, path3 = null, glob = null, outputMode = "files_with_matches") {
|
|
5141
5193
|
let regex;
|
|
5142
5194
|
try {
|
|
5143
5195
|
regex = new RegExp(pattern);
|
|
@@ -5146,7 +5198,7 @@ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode =
|
|
|
5146
5198
|
}
|
|
5147
5199
|
let normalizedPath;
|
|
5148
5200
|
try {
|
|
5149
|
-
normalizedPath = validatePath(
|
|
5201
|
+
normalizedPath = validatePath(path3);
|
|
5150
5202
|
} catch {
|
|
5151
5203
|
return "No matches found";
|
|
5152
5204
|
}
|
|
@@ -5178,7 +5230,7 @@ function grepSearchFiles(files, pattern, path4 = null, glob = null, outputMode =
|
|
|
5178
5230
|
}
|
|
5179
5231
|
return formatGrepResults(results, outputMode);
|
|
5180
5232
|
}
|
|
5181
|
-
function grepMatchesFromFiles(files, pattern,
|
|
5233
|
+
function grepMatchesFromFiles(files, pattern, path3 = null, glob = null) {
|
|
5182
5234
|
let regex;
|
|
5183
5235
|
try {
|
|
5184
5236
|
regex = new RegExp(pattern);
|
|
@@ -5187,7 +5239,7 @@ function grepMatchesFromFiles(files, pattern, path4 = null, glob = null) {
|
|
|
5187
5239
|
}
|
|
5188
5240
|
let normalizedPath;
|
|
5189
5241
|
try {
|
|
5190
|
-
normalizedPath = validatePath(
|
|
5242
|
+
normalizedPath = validatePath(path3);
|
|
5191
5243
|
} catch {
|
|
5192
5244
|
return [];
|
|
5193
5245
|
}
|
|
@@ -5248,11 +5300,11 @@ var StateBackend = class {
|
|
|
5248
5300
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
5249
5301
|
* Directories have a trailing / in their path and is_dir=true.
|
|
5250
5302
|
*/
|
|
5251
|
-
lsInfo(
|
|
5303
|
+
lsInfo(path3) {
|
|
5252
5304
|
const files = this.getFiles();
|
|
5253
5305
|
const infos = [];
|
|
5254
5306
|
const subdirs = /* @__PURE__ */ new Set();
|
|
5255
|
-
const normalizedPath =
|
|
5307
|
+
const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
|
|
5256
5308
|
for (const [k, fd] of Object.entries(files)) {
|
|
5257
5309
|
if (!k.startsWith(normalizedPath)) {
|
|
5258
5310
|
continue;
|
|
@@ -5358,16 +5410,16 @@ var StateBackend = class {
|
|
|
5358
5410
|
/**
|
|
5359
5411
|
* Structured search results or error string for invalid input.
|
|
5360
5412
|
*/
|
|
5361
|
-
grepRaw(pattern,
|
|
5413
|
+
grepRaw(pattern, path3 = "/", glob = null) {
|
|
5362
5414
|
const files = this.getFiles();
|
|
5363
|
-
return grepMatchesFromFiles(files, pattern,
|
|
5415
|
+
return grepMatchesFromFiles(files, pattern, path3, glob);
|
|
5364
5416
|
}
|
|
5365
5417
|
/**
|
|
5366
5418
|
* Structured glob matching returning FileInfo objects.
|
|
5367
5419
|
*/
|
|
5368
|
-
globInfo(pattern,
|
|
5420
|
+
globInfo(pattern, path3 = "/") {
|
|
5369
5421
|
const files = this.getFiles();
|
|
5370
|
-
const result = globSearchFiles(files, pattern,
|
|
5422
|
+
const result = globSearchFiles(files, pattern, path3);
|
|
5371
5423
|
if (result === "No files found") {
|
|
5372
5424
|
return [];
|
|
5373
5425
|
}
|
|
@@ -5433,16 +5485,16 @@ async function getBackend(backend, stateAndStore) {
|
|
|
5433
5485
|
var FILESYSTEM_SYSTEM_PROMPT = `You have access to a virtual filesystem.
|
|
5434
5486
|
|
|
5435
5487
|
Path conventions:
|
|
5436
|
-
- All paths
|
|
5437
|
-
-
|
|
5438
|
-
-
|
|
5439
|
-
-
|
|
5488
|
+
- All paths are absolute starting with /. Key directories:
|
|
5489
|
+
- /agent/ \u2014 Your private agent directory (identity, memory, preferences). Isolated per agent.
|
|
5490
|
+
- /project/ \u2014 Project workspace. Shared across all agents in the same project. Persisted across sessions.
|
|
5491
|
+
- /root/.agents/skills/ \u2014 Skill definitions. Read-only for most operations.
|
|
5440
5492
|
|
|
5441
5493
|
- ls: list files in a directory
|
|
5442
5494
|
- read_file: read a file from the filesystem
|
|
5443
5495
|
- write_file: write to a file in the filesystem
|
|
5444
5496
|
- edit_file: edit a file in the filesystem
|
|
5445
|
-
- glob: find files matching a pattern (e.g., "
|
|
5497
|
+
- glob: find files matching a pattern (e.g., "/project/**/*.py")
|
|
5446
5498
|
- grep: search for text within files`;
|
|
5447
5499
|
var LS_TOOL_DESCRIPTION = "List files and directories in a directory";
|
|
5448
5500
|
var READ_FILE_TOOL_DESCRIPTION = "Read the contents of a file";
|
|
@@ -5461,10 +5513,10 @@ function createLsTool(backend, options) {
|
|
|
5461
5513
|
...runConfig
|
|
5462
5514
|
};
|
|
5463
5515
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
5464
|
-
const
|
|
5465
|
-
const infos = await resolvedBackend.lsInfo(
|
|
5516
|
+
const path3 = input.path || "/";
|
|
5517
|
+
const infos = await resolvedBackend.lsInfo(path3);
|
|
5466
5518
|
if (infos.length === 0) {
|
|
5467
|
-
return `No files found in ${
|
|
5519
|
+
return `No files found in ${path3}`;
|
|
5468
5520
|
}
|
|
5469
5521
|
const lines = [];
|
|
5470
5522
|
for (const info of infos) {
|
|
@@ -5607,8 +5659,8 @@ function createGlobTool(backend, options) {
|
|
|
5607
5659
|
...runConfig
|
|
5608
5660
|
};
|
|
5609
5661
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
5610
|
-
const { pattern, path:
|
|
5611
|
-
const infos = await resolvedBackend.globInfo(pattern,
|
|
5662
|
+
const { pattern, path: path3 = "/" } = input;
|
|
5663
|
+
const infos = await resolvedBackend.globInfo(pattern, path3);
|
|
5612
5664
|
if (infos.length === 0) {
|
|
5613
5665
|
return `No files found matching pattern '${pattern}'`;
|
|
5614
5666
|
}
|
|
@@ -5635,8 +5687,8 @@ function createGrepTool(backend, options) {
|
|
|
5635
5687
|
...runConfig
|
|
5636
5688
|
};
|
|
5637
5689
|
const resolvedBackend = await getBackend(backend, stateAndStore);
|
|
5638
|
-
const { pattern, path:
|
|
5639
|
-
const result = await resolvedBackend.grepRaw(pattern,
|
|
5690
|
+
const { pattern, path: path3 = "/", glob = null } = input;
|
|
5691
|
+
const result = await resolvedBackend.grepRaw(pattern, path3, glob);
|
|
5640
5692
|
if (typeof result === "string") {
|
|
5641
5693
|
return result;
|
|
5642
5694
|
}
|
|
@@ -6902,50 +6954,50 @@ var AGENTS_MD = `
|
|
|
6902
6954
|
|
|
6903
6955
|
## First Run
|
|
6904
6956
|
|
|
6905
|
-
If "
|
|
6957
|
+
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.
|
|
6906
6958
|
|
|
6907
6959
|
## Every Session
|
|
6908
6960
|
|
|
6909
6961
|
Before doing anything else, read this startup set in order:
|
|
6910
6962
|
|
|
6911
|
-
1.
|
|
6912
|
-
2.
|
|
6913
|
-
3.
|
|
6914
|
-
4.
|
|
6915
|
-
5.
|
|
6916
|
-
6.
|
|
6917
|
-
7.
|
|
6918
|
-
8.
|
|
6919
|
-
9.
|
|
6963
|
+
1. /agent/SOUL.md
|
|
6964
|
+
2. /agent/AGENTS.md
|
|
6965
|
+
3. /agent/IDENTITY.md
|
|
6966
|
+
4. /agent/USER.md
|
|
6967
|
+
5. /agent/MEMORY.md
|
|
6968
|
+
6. /project/PROJECT.md
|
|
6969
|
+
7. /project/notes/index.md
|
|
6970
|
+
8. /project/notes/wip.md
|
|
6971
|
+
9. /project/notes/pending.md
|
|
6920
6972
|
|
|
6921
6973
|
Don't ask permission. Just do it.
|
|
6922
6974
|
|
|
6923
6975
|
After the startup set, expand only if needed:
|
|
6924
6976
|
|
|
6925
|
-
- If
|
|
6926
|
-
- If the current interruption point still feels underspecified, read the most recent one or two
|
|
6977
|
+
- If /project/notes/wip.md mentions unfamiliar modules, unclear constraints, or prior decisions, read /project/notes/architecture.md and /project/notes/decisions.md.
|
|
6978
|
+
- If the current interruption point still feels underspecified, read the most recent one or two /project/raw/YYYY-MM-DD.md files.
|
|
6927
6979
|
- Do not load every memory file by default. Read deeper only when the current task needs it.
|
|
6928
6980
|
|
|
6929
6981
|
## Memory Model
|
|
6930
6982
|
|
|
6931
6983
|
You wake up fresh each session. Files are your continuity.
|
|
6932
6984
|
|
|
6933
|
-
-
|
|
6934
|
-
-
|
|
6935
|
-
-
|
|
6936
|
-
-
|
|
6937
|
-
-
|
|
6938
|
-
-
|
|
6939
|
-
-
|
|
6940
|
-
-
|
|
6985
|
+
- /agent/ is your private scope.
|
|
6986
|
+
- /agent/MEMORY.md is your memory index.
|
|
6987
|
+
- /agent/memory/*.md stores categorized private memory.
|
|
6988
|
+
- /agent/memory/preferences.md is one example of categorized private memory.
|
|
6989
|
+
- /project/PROJECT.md, /project/raw/, /project/notes/, and /project/artifacts/ belong to the current project.
|
|
6990
|
+
- /project/raw/YYYY-MM-DD.md records what happened.
|
|
6991
|
+
- /project/notes/ records what is worth remembering.
|
|
6992
|
+
- /project/artifacts/ records what was produced.
|
|
6941
6993
|
|
|
6942
6994
|
Use this structure intentionally:
|
|
6943
6995
|
|
|
6944
|
-
- Read
|
|
6945
|
-
- Treat
|
|
6946
|
-
- Write the actual durable private content into
|
|
6947
|
-
- Use
|
|
6948
|
-
- Prefer writing to
|
|
6996
|
+
- Read /agent/MEMORY.md to find the durable private memory that matters now.
|
|
6997
|
+
- Treat /agent/MEMORY.md as an index and navigation file, not as the main place for detailed long-term notes.
|
|
6998
|
+
- Write the actual durable private content into /agent/memory/*.md.
|
|
6999
|
+
- Use /project/PROJECT.md for the current project's operating context, constraints, and stable reference material.
|
|
7000
|
+
- Prefer writing to /project/raw/YYYY-MM-DD.md or /project/notes/wip.md before promoting anything into durable notes or agent memory.
|
|
6949
7001
|
- Not every session needs a write.
|
|
6950
7002
|
- Write only when the session produced something worth preserving for future work.
|
|
6951
7003
|
|
|
@@ -6960,15 +7012,15 @@ Pure one-off questions with no follow-up value usually need no memory update.
|
|
|
6960
7012
|
|
|
6961
7013
|
Promote information upward based on value:
|
|
6962
7014
|
|
|
6963
|
-
- Put immediate observations, action logs, and rough capture in
|
|
6964
|
-
- Put working understanding, partial conclusions, and candidate reminders in
|
|
7015
|
+
- Put immediate observations, action logs, and rough capture in /project/raw/YYYY-MM-DD.md.
|
|
7016
|
+
- Put working understanding, partial conclusions, and candidate reminders in /project/notes/wip.md.
|
|
6965
7017
|
- Put durable project knowledge in project notes once it becomes worth remembering.
|
|
6966
|
-
- Put durable private lessons, preferences, reminders, and long-term context in
|
|
7018
|
+
- Put durable private lessons, preferences, reminders, and long-term context in /agent/MEMORY.md and /agent/memory/*.md.
|
|
6967
7019
|
|
|
6968
7020
|
## Safety
|
|
6969
7021
|
|
|
6970
7022
|
- Don't exfiltrate private data. Ever.
|
|
6971
|
-
- Don't run destructive commands without asking, except deleting
|
|
7023
|
+
- Don't run destructive commands without asking, except deleting /agent/BOOTSTRAP.md after first-run setup is complete.
|
|
6972
7024
|
- When in doubt, ask.
|
|
6973
7025
|
|
|
6974
7026
|
## External vs Internal
|
|
@@ -7000,12 +7052,12 @@ There is no durable memory yet. This is a fresh workspace, so your first job is
|
|
|
7000
7052
|
|
|
7001
7053
|
Before you start shaping identity or style, inspect the memory structure you will use.
|
|
7002
7054
|
|
|
7003
|
-
-
|
|
7004
|
-
-
|
|
7005
|
-
-
|
|
7006
|
-
-
|
|
7007
|
-
-
|
|
7008
|
-
-
|
|
7055
|
+
- /agent/MEMORY.md
|
|
7056
|
+
- /agent/memory/*.md
|
|
7057
|
+
- /project/PROJECT.md
|
|
7058
|
+
- /project/raw/
|
|
7059
|
+
- /project/notes/
|
|
7060
|
+
- /project/artifacts/
|
|
7009
7061
|
|
|
7010
7062
|
You need to understand this structure first, because this is how you will preserve continuity in future work.
|
|
7011
7063
|
|
|
@@ -7028,37 +7080,37 @@ Offer suggestions if they're stuck. Keep it human.
|
|
|
7028
7080
|
|
|
7029
7081
|
Set up and understand this memory structure. This is the memory structure you should use in future work.
|
|
7030
7082
|
|
|
7031
|
-
-
|
|
7032
|
-
-
|
|
7033
|
-
-
|
|
7034
|
-
-
|
|
7035
|
-
-
|
|
7036
|
-
-
|
|
7083
|
+
- /agent/MEMORY.md
|
|
7084
|
+
- /agent/memory/*.md
|
|
7085
|
+
- /project/PROJECT.md
|
|
7086
|
+
- /project/raw/
|
|
7087
|
+
- /project/notes/
|
|
7088
|
+
- /project/artifacts/
|
|
7037
7089
|
|
|
7038
7090
|
Use it like this:
|
|
7039
7091
|
|
|
7040
|
-
-
|
|
7041
|
-
-
|
|
7042
|
-
-
|
|
7043
|
-
-
|
|
7044
|
-
-
|
|
7045
|
-
-
|
|
7092
|
+
- /agent/MEMORY.md is your private memory index.
|
|
7093
|
+
- /agent/memory/*.md holds categorized private memory.
|
|
7094
|
+
- /project/PROJECT.md holds stable project-level context.
|
|
7095
|
+
- /project/raw/ captures what happened.
|
|
7096
|
+
- /project/notes/ captures what is worth remembering.
|
|
7097
|
+
- /project/artifacts/ stores what was produced.
|
|
7046
7098
|
|
|
7047
7099
|
## After You Know Who You Are
|
|
7048
7100
|
|
|
7049
7101
|
Update these files with what you learned:
|
|
7050
7102
|
|
|
7051
|
-
-
|
|
7052
|
-
-
|
|
7053
|
-
-
|
|
7054
|
-
-
|
|
7103
|
+
- /agent/IDENTITY.md for your name, nature, and vibe.
|
|
7104
|
+
- /agent/USER.md for who you're helping and how to work well with them.
|
|
7105
|
+
- /agent/SOUL.md for values, behavior, and boundaries.
|
|
7106
|
+
- /agent/MEMORY.md and /agent/memory/*.md only for durable private memory worth keeping.
|
|
7055
7107
|
|
|
7056
7108
|
Do not keep rewriting these foundational files during ordinary project work.
|
|
7057
7109
|
Update them only when you learn something stable enough to change your long-term identity, user model, or private memory structure.
|
|
7058
7110
|
|
|
7059
7111
|
Prefer rough capture in project memory before creating durable notes:
|
|
7060
7112
|
|
|
7061
|
-
- Start with
|
|
7113
|
+
- Start with /project/raw/YYYY-MM-DD.md or /project/notes/wip.md.
|
|
7062
7114
|
- Promote only the information that should survive into project notes or private agent memory.
|
|
7063
7115
|
|
|
7064
7116
|
## When You're Done
|
|
@@ -12215,8 +12267,52 @@ var SandboxFilesystem = class {
|
|
|
12215
12267
|
}
|
|
12216
12268
|
}
|
|
12217
12269
|
async read(filePath, offset = 0, limit = 1e4) {
|
|
12270
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
12271
|
+
const binaryExts = /* @__PURE__ */ new Set([
|
|
12272
|
+
"pdf",
|
|
12273
|
+
"png",
|
|
12274
|
+
"jpg",
|
|
12275
|
+
"jpeg",
|
|
12276
|
+
"gif",
|
|
12277
|
+
"svg",
|
|
12278
|
+
"webp",
|
|
12279
|
+
"ico",
|
|
12280
|
+
"bmp",
|
|
12281
|
+
"zip",
|
|
12282
|
+
"gz",
|
|
12283
|
+
"tar",
|
|
12284
|
+
"rar",
|
|
12285
|
+
"7z",
|
|
12286
|
+
"mp3",
|
|
12287
|
+
"mp4",
|
|
12288
|
+
"avi",
|
|
12289
|
+
"mov",
|
|
12290
|
+
"wav",
|
|
12291
|
+
"flac",
|
|
12292
|
+
"exe",
|
|
12293
|
+
"dll",
|
|
12294
|
+
"so",
|
|
12295
|
+
"dylib",
|
|
12296
|
+
"wasm",
|
|
12297
|
+
"ttf",
|
|
12298
|
+
"otf",
|
|
12299
|
+
"woff",
|
|
12300
|
+
"woff2",
|
|
12301
|
+
"doc",
|
|
12302
|
+
"docx",
|
|
12303
|
+
"ppt",
|
|
12304
|
+
"pptx",
|
|
12305
|
+
"xls",
|
|
12306
|
+
"xlsx"
|
|
12307
|
+
]);
|
|
12308
|
+
if (ext && binaryExts.has(ext)) {
|
|
12309
|
+
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.`;
|
|
12310
|
+
}
|
|
12218
12311
|
try {
|
|
12219
12312
|
const result = await this.sandbox.file.readFile(filePath);
|
|
12313
|
+
if (result.content.includes("\0")) {
|
|
12314
|
+
return `Error: Cannot read binary file '${filePath}': file contains binary data. Use shell tools to inspect or download the file directly.`;
|
|
12315
|
+
}
|
|
12220
12316
|
return result.content;
|
|
12221
12317
|
} catch (e) {
|
|
12222
12318
|
return `Error: File '${filePath}' not found`;
|
|
@@ -12268,9 +12364,9 @@ var SandboxFilesystem = class {
|
|
|
12268
12364
|
throw new Error(`Error editing file '${filePath}': ${e.message}`);
|
|
12269
12365
|
}
|
|
12270
12366
|
}
|
|
12271
|
-
async grepRaw(pattern, searchPath = "
|
|
12367
|
+
async grepRaw(pattern, searchPath = "/", glob = null) {
|
|
12272
12368
|
try {
|
|
12273
|
-
const result = await this.sandbox.file.findFiles(searchPath || "
|
|
12369
|
+
const result = await this.sandbox.file.findFiles(searchPath || "/", glob || "**/*");
|
|
12274
12370
|
const filePaths = result.files;
|
|
12275
12371
|
const matches = [];
|
|
12276
12372
|
for (const absolutePath of filePaths) {
|
|
@@ -12290,7 +12386,7 @@ var SandboxFilesystem = class {
|
|
|
12290
12386
|
return `Error: ${e.message}`;
|
|
12291
12387
|
}
|
|
12292
12388
|
}
|
|
12293
|
-
async globInfo(pattern, searchPath = "
|
|
12389
|
+
async globInfo(pattern, searchPath = "/") {
|
|
12294
12390
|
const result = await this.sandbox.file.findFiles(searchPath, pattern || "**/*");
|
|
12295
12391
|
return result.files.map((filePath) => ({
|
|
12296
12392
|
path: filePath,
|
|
@@ -13055,13 +13151,13 @@ var StoreBackend = class {
|
|
|
13055
13151
|
* @returns List of FileInfo objects for files and directories directly in the directory.
|
|
13056
13152
|
* Directories have a trailing / in their path and is_dir=true.
|
|
13057
13153
|
*/
|
|
13058
|
-
async lsInfo(
|
|
13154
|
+
async lsInfo(path3) {
|
|
13059
13155
|
const store = this.getStore();
|
|
13060
13156
|
const namespace = this.getNamespace();
|
|
13061
13157
|
const items = await this.searchStorePaginated(store, namespace);
|
|
13062
13158
|
const infos = [];
|
|
13063
13159
|
const subdirs = /* @__PURE__ */ new Set();
|
|
13064
|
-
const normalizedPath =
|
|
13160
|
+
const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
|
|
13065
13161
|
for (const item of items) {
|
|
13066
13162
|
const itemKey = String(item.key);
|
|
13067
13163
|
if (!itemKey.startsWith(normalizedPath)) {
|
|
@@ -13179,7 +13275,7 @@ var StoreBackend = class {
|
|
|
13179
13275
|
/**
|
|
13180
13276
|
* Structured search results or error string for invalid input.
|
|
13181
13277
|
*/
|
|
13182
|
-
async grepRaw(pattern,
|
|
13278
|
+
async grepRaw(pattern, path3 = "/", glob = null) {
|
|
13183
13279
|
const store = this.getStore();
|
|
13184
13280
|
const namespace = this.getNamespace();
|
|
13185
13281
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -13191,12 +13287,12 @@ var StoreBackend = class {
|
|
|
13191
13287
|
continue;
|
|
13192
13288
|
}
|
|
13193
13289
|
}
|
|
13194
|
-
return grepMatchesFromFiles(files, pattern,
|
|
13290
|
+
return grepMatchesFromFiles(files, pattern, path3, glob);
|
|
13195
13291
|
}
|
|
13196
13292
|
/**
|
|
13197
13293
|
* Structured glob matching returning FileInfo objects.
|
|
13198
13294
|
*/
|
|
13199
|
-
async globInfo(pattern,
|
|
13295
|
+
async globInfo(pattern, path3 = "/") {
|
|
13200
13296
|
const store = this.getStore();
|
|
13201
13297
|
const namespace = this.getNamespace();
|
|
13202
13298
|
const items = await this.searchStorePaginated(store, namespace);
|
|
@@ -13208,7 +13304,7 @@ var StoreBackend = class {
|
|
|
13208
13304
|
continue;
|
|
13209
13305
|
}
|
|
13210
13306
|
}
|
|
13211
|
-
const result = globSearchFiles(files, pattern,
|
|
13307
|
+
const result = globSearchFiles(files, pattern, path3);
|
|
13212
13308
|
if (result === "No files found") {
|
|
13213
13309
|
return [];
|
|
13214
13310
|
}
|
|
@@ -13257,7 +13353,12 @@ var FilesystemBackend = class {
|
|
|
13257
13353
|
*/
|
|
13258
13354
|
resolvePath(key) {
|
|
13259
13355
|
if (this.virtualMode) {
|
|
13260
|
-
|
|
13356
|
+
let normalizedKey = key;
|
|
13357
|
+
if (normalizedKey === "~" || normalizedKey === "~/") {
|
|
13358
|
+
normalizedKey = "/";
|
|
13359
|
+
} else if (normalizedKey.startsWith("~/")) {
|
|
13360
|
+
normalizedKey = `/${normalizedKey.slice(2)}`;
|
|
13361
|
+
}
|
|
13261
13362
|
const vpath = normalizedKey.startsWith("/") ? normalizedKey : "/" + normalizedKey;
|
|
13262
13363
|
if (vpath.includes("..") || vpath.includes("~")) {
|
|
13263
13364
|
throw new Error("Path traversal not allowed");
|
|
@@ -13269,10 +13370,14 @@ var FilesystemBackend = class {
|
|
|
13269
13370
|
}
|
|
13270
13371
|
return full;
|
|
13271
13372
|
}
|
|
13272
|
-
|
|
13273
|
-
|
|
13373
|
+
let target = key;
|
|
13374
|
+
if (target.startsWith("~/")) {
|
|
13375
|
+
target = `/${target.slice(2)}`;
|
|
13376
|
+
}
|
|
13377
|
+
if (path2.isAbsolute(target)) {
|
|
13378
|
+
return target;
|
|
13274
13379
|
}
|
|
13275
|
-
return path2.resolve(this.cwd,
|
|
13380
|
+
return path2.resolve(this.cwd, target);
|
|
13276
13381
|
}
|
|
13277
13382
|
/**
|
|
13278
13383
|
* List files and directories in the specified directory (non-recursive).
|
|
@@ -13784,10 +13889,10 @@ var CompositeBackend = class {
|
|
|
13784
13889
|
* @returns List of FileInfo objects with route prefixes added, for files and directories
|
|
13785
13890
|
* directly in the directory. Directories have a trailing / in their path and is_dir=true.
|
|
13786
13891
|
*/
|
|
13787
|
-
async lsInfo(
|
|
13892
|
+
async lsInfo(path3) {
|
|
13788
13893
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13789
|
-
if (
|
|
13790
|
-
const suffix =
|
|
13894
|
+
if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
13895
|
+
const suffix = path3.substring(routePrefix.length);
|
|
13791
13896
|
const searchPath = suffix ? "/" + suffix : "/";
|
|
13792
13897
|
const infos = await backend.lsInfo(searchPath);
|
|
13793
13898
|
const prefixed = [];
|
|
@@ -13800,9 +13905,9 @@ var CompositeBackend = class {
|
|
|
13800
13905
|
return prefixed;
|
|
13801
13906
|
}
|
|
13802
13907
|
}
|
|
13803
|
-
if (
|
|
13908
|
+
if (path3 === "/") {
|
|
13804
13909
|
const results = [];
|
|
13805
|
-
const defaultInfos = await this.default.lsInfo(
|
|
13910
|
+
const defaultInfos = await this.default.lsInfo(path3);
|
|
13806
13911
|
results.push(...defaultInfos);
|
|
13807
13912
|
for (const [routePrefix] of this.sortedRoutes) {
|
|
13808
13913
|
results.push({
|
|
@@ -13815,7 +13920,7 @@ var CompositeBackend = class {
|
|
|
13815
13920
|
results.sort((a, b) => a.path.localeCompare(b.path));
|
|
13816
13921
|
return results;
|
|
13817
13922
|
}
|
|
13818
|
-
return await this.default.lsInfo(
|
|
13923
|
+
return await this.default.lsInfo(path3);
|
|
13819
13924
|
}
|
|
13820
13925
|
/**
|
|
13821
13926
|
* Read file content, routing to appropriate backend.
|
|
@@ -13842,10 +13947,10 @@ var CompositeBackend = class {
|
|
|
13842
13947
|
/**
|
|
13843
13948
|
* Structured search results or error string for invalid input.
|
|
13844
13949
|
*/
|
|
13845
|
-
async grepRaw(pattern,
|
|
13950
|
+
async grepRaw(pattern, path3 = "/", glob = null) {
|
|
13846
13951
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13847
|
-
if (
|
|
13848
|
-
const searchPath =
|
|
13952
|
+
if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
13953
|
+
const searchPath = path3.substring(routePrefix.length - 1);
|
|
13849
13954
|
const raw = await backend.grepRaw(pattern, searchPath || "/", glob);
|
|
13850
13955
|
if (typeof raw === "string") {
|
|
13851
13956
|
return raw;
|
|
@@ -13857,7 +13962,7 @@ var CompositeBackend = class {
|
|
|
13857
13962
|
}
|
|
13858
13963
|
}
|
|
13859
13964
|
const allMatches = [];
|
|
13860
|
-
const rawDefault = await this.default.grepRaw(pattern,
|
|
13965
|
+
const rawDefault = await this.default.grepRaw(pattern, path3, glob);
|
|
13861
13966
|
if (typeof rawDefault === "string") {
|
|
13862
13967
|
return rawDefault;
|
|
13863
13968
|
}
|
|
@@ -13879,11 +13984,11 @@ var CompositeBackend = class {
|
|
|
13879
13984
|
/**
|
|
13880
13985
|
* Structured glob matching returning FileInfo objects.
|
|
13881
13986
|
*/
|
|
13882
|
-
async globInfo(pattern,
|
|
13987
|
+
async globInfo(pattern, path3 = "/") {
|
|
13883
13988
|
const results = [];
|
|
13884
13989
|
for (const [routePrefix, backend] of this.sortedRoutes) {
|
|
13885
|
-
if (
|
|
13886
|
-
const searchPath =
|
|
13990
|
+
if (path3.startsWith(routePrefix.replace(/\/$/, ""))) {
|
|
13991
|
+
const searchPath = path3.substring(routePrefix.length - 1);
|
|
13887
13992
|
const infos = await backend.globInfo(pattern, searchPath || "/");
|
|
13888
13993
|
return infos.map((fi) => ({
|
|
13889
13994
|
...fi,
|
|
@@ -13891,7 +13996,7 @@ var CompositeBackend = class {
|
|
|
13891
13996
|
}));
|
|
13892
13997
|
}
|
|
13893
13998
|
}
|
|
13894
|
-
const defaultInfos = await this.default.globInfo(pattern,
|
|
13999
|
+
const defaultInfos = await this.default.globInfo(pattern, path3);
|
|
13895
14000
|
results.push(...defaultInfos);
|
|
13896
14001
|
for (const [routePrefix, backend] of Object.entries(this.routes)) {
|
|
13897
14002
|
const infos = await backend.globInfo(pattern, "/");
|
|
@@ -13939,11 +14044,11 @@ var MemoryBackend = class {
|
|
|
13939
14044
|
getFiles() {
|
|
13940
14045
|
return Object.fromEntries(this.files);
|
|
13941
14046
|
}
|
|
13942
|
-
lsInfo(
|
|
14047
|
+
lsInfo(path3) {
|
|
13943
14048
|
const files = this.getFiles();
|
|
13944
14049
|
const infos = [];
|
|
13945
14050
|
const subdirs = /* @__PURE__ */ new Set();
|
|
13946
|
-
const normalizedPath =
|
|
14051
|
+
const normalizedPath = path3.endsWith("/") ? path3 : path3 + "/";
|
|
13947
14052
|
for (const [k, fd] of Object.entries(files)) {
|
|
13948
14053
|
if (!k.startsWith(normalizedPath)) {
|
|
13949
14054
|
continue;
|
|
@@ -14018,13 +14123,13 @@ var MemoryBackend = class {
|
|
|
14018
14123
|
this.files.set(filePath, newFileData);
|
|
14019
14124
|
return { path: filePath, filesUpdate: null, occurrences };
|
|
14020
14125
|
}
|
|
14021
|
-
grepRaw(pattern,
|
|
14126
|
+
grepRaw(pattern, path3 = "/", glob = null) {
|
|
14022
14127
|
const files = this.getFiles();
|
|
14023
|
-
return grepMatchesFromFiles(files, pattern,
|
|
14128
|
+
return grepMatchesFromFiles(files, pattern, path3, glob);
|
|
14024
14129
|
}
|
|
14025
|
-
globInfo(pattern,
|
|
14130
|
+
globInfo(pattern, path3 = "/") {
|
|
14026
14131
|
const files = this.getFiles();
|
|
14027
|
-
const result = globSearchFiles(files, pattern,
|
|
14132
|
+
const result = globSearchFiles(files, pattern, path3);
|
|
14028
14133
|
if (result === "No files found") {
|
|
14029
14134
|
return [];
|
|
14030
14135
|
}
|
|
@@ -16399,7 +16504,7 @@ var SandboxSkillStore = class {
|
|
|
16399
16504
|
if (name.includes("..") || name.includes("/") || name.includes("\\")) {
|
|
16400
16505
|
throw new Error(`Invalid skill name: ${name} (contains invalid characters)`);
|
|
16401
16506
|
}
|
|
16402
|
-
return
|
|
16507
|
+
return `/root/.agents/skills/${name}`;
|
|
16403
16508
|
}
|
|
16404
16509
|
/**
|
|
16405
16510
|
* Get skill file path in sandbox (absolute path with ~/ prefix)
|
|
@@ -16466,14 +16571,14 @@ ${body}` : `${frontmatter}
|
|
|
16466
16571
|
async getAllSkills(tenantId, context) {
|
|
16467
16572
|
try {
|
|
16468
16573
|
const sandbox = await this.getSandbox(tenantId, context);
|
|
16469
|
-
const skillsDir = "
|
|
16574
|
+
const skillsDir = "/root/.agents/skills";
|
|
16470
16575
|
try {
|
|
16471
16576
|
await sandbox.file.listPath(skillsDir, { recursive: false });
|
|
16472
16577
|
} catch (listError) {
|
|
16473
16578
|
console.log(`[SandboxSkillStore] Skills directory not found, creating: ${skillsDir}`);
|
|
16474
16579
|
try {
|
|
16475
16580
|
await sandbox.shell.execCommand({
|
|
16476
|
-
command: `mkdir -p
|
|
16581
|
+
command: `mkdir -p /root/.agents/skills`
|
|
16477
16582
|
});
|
|
16478
16583
|
} catch (mkdirError) {
|
|
16479
16584
|
console.error(`[SandboxSkillStore] Failed to create skills directory: ${mkdirError.message}`);
|
|
@@ -18088,9 +18193,9 @@ var MicrosandboxInstance = class {
|
|
|
18088
18193
|
const fs3 = this.native.fs();
|
|
18089
18194
|
await fs3.write(file, Buffer.from(content));
|
|
18090
18195
|
},
|
|
18091
|
-
listPath: async (
|
|
18196
|
+
listPath: async (path3, options) => {
|
|
18092
18197
|
const fs3 = this.native.fs();
|
|
18093
|
-
const entries = await fs3.list(
|
|
18198
|
+
const entries = await fs3.list(path3);
|
|
18094
18199
|
const files = (entries || []).map((e) => ({
|
|
18095
18200
|
path: e.path,
|
|
18096
18201
|
is_dir: e.kind === "directory",
|
|
@@ -18099,9 +18204,9 @@ var MicrosandboxInstance = class {
|
|
|
18099
18204
|
}));
|
|
18100
18205
|
return { files };
|
|
18101
18206
|
},
|
|
18102
|
-
findFiles: async (
|
|
18207
|
+
findFiles: async (path3, glob) => {
|
|
18103
18208
|
const output = await exec(this.native, "sh", {
|
|
18104
|
-
args: ["-c", `find "${
|
|
18209
|
+
args: ["-c", `find "${path3}" -name "${glob}" -type f`]
|
|
18105
18210
|
});
|
|
18106
18211
|
const lines = output.stdout().split("\n").filter(Boolean);
|
|
18107
18212
|
return { files: lines };
|
|
@@ -18124,13 +18229,13 @@ var MicrosandboxInstance = class {
|
|
|
18124
18229
|
return { matches, line_numbers };
|
|
18125
18230
|
},
|
|
18126
18231
|
strReplaceEditor: async (params) => {
|
|
18127
|
-
const { path:
|
|
18232
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
18128
18233
|
const delim = "#";
|
|
18129
18234
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18130
18235
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18131
18236
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
18132
18237
|
await exec(this.native, "sh", {
|
|
18133
|
-
args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
18238
|
+
args: ["-c", `sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`]
|
|
18134
18239
|
});
|
|
18135
18240
|
},
|
|
18136
18241
|
uploadFile: async (params) => {
|
|
@@ -18222,16 +18327,34 @@ var MicrosandboxProvider = class {
|
|
|
18222
18327
|
native = void 0;
|
|
18223
18328
|
}
|
|
18224
18329
|
if (!native) {
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
|
|
18228
|
-
|
|
18229
|
-
|
|
18230
|
-
|
|
18231
|
-
|
|
18232
|
-
|
|
18330
|
+
try {
|
|
18331
|
+
native = await Sandbox.createDetached({
|
|
18332
|
+
name,
|
|
18333
|
+
image: this.config.image ?? "python:3.11-slim",
|
|
18334
|
+
cpus: this.config.cpus ?? 1,
|
|
18335
|
+
memoryMib: this.config.memoryMib ?? 512,
|
|
18336
|
+
env: {
|
|
18337
|
+
...this.config.env,
|
|
18338
|
+
...buildSandboxMetadataEnv(config)
|
|
18339
|
+
}
|
|
18340
|
+
});
|
|
18341
|
+
} catch (err) {
|
|
18342
|
+
if (err instanceof Error && err.message.includes("already exists")) {
|
|
18343
|
+
await Sandbox.remove(name);
|
|
18344
|
+
native = await Sandbox.createDetached({
|
|
18345
|
+
name,
|
|
18346
|
+
image: this.config.image ?? "python:3.11-slim",
|
|
18347
|
+
cpus: this.config.cpus ?? 1,
|
|
18348
|
+
memoryMib: this.config.memoryMib ?? 512,
|
|
18349
|
+
env: {
|
|
18350
|
+
...this.config.env,
|
|
18351
|
+
...buildSandboxMetadataEnv(config)
|
|
18352
|
+
}
|
|
18353
|
+
});
|
|
18354
|
+
} else {
|
|
18355
|
+
throw err;
|
|
18233
18356
|
}
|
|
18234
|
-
}
|
|
18357
|
+
}
|
|
18235
18358
|
}
|
|
18236
18359
|
const instance = new MicrosandboxInstance(name, native);
|
|
18237
18360
|
this.instances.set(name, instance);
|
|
@@ -18251,11 +18374,15 @@ var MicrosandboxProvider = class {
|
|
|
18251
18374
|
async stopSandbox(name) {
|
|
18252
18375
|
const instance = this.instances.get(name);
|
|
18253
18376
|
if (instance) {
|
|
18254
|
-
|
|
18377
|
+
try {
|
|
18378
|
+
await instance.stop();
|
|
18379
|
+
} catch {
|
|
18380
|
+
}
|
|
18255
18381
|
}
|
|
18256
18382
|
}
|
|
18257
18383
|
async deleteSandbox(name) {
|
|
18258
18384
|
const instance = this.instances.get(name);
|
|
18385
|
+
this.instances.delete(name);
|
|
18259
18386
|
if (instance) {
|
|
18260
18387
|
try {
|
|
18261
18388
|
await instance.kill();
|
|
@@ -18264,52 +18391,12 @@ var MicrosandboxProvider = class {
|
|
|
18264
18391
|
}
|
|
18265
18392
|
}
|
|
18266
18393
|
await Sandbox.remove(name);
|
|
18267
|
-
this.instances.delete(name);
|
|
18268
18394
|
}
|
|
18269
18395
|
async listSandboxes() {
|
|
18270
18396
|
return Array.from(this.instances.values());
|
|
18271
18397
|
}
|
|
18272
18398
|
};
|
|
18273
18399
|
|
|
18274
|
-
// src/sandbox_lattice/pathUtils.ts
|
|
18275
|
-
import path3 from "path";
|
|
18276
|
-
var SANDBOX_HOME_DIR = "/home/daytona";
|
|
18277
|
-
function normalizeExternalSandboxPath(inputPath) {
|
|
18278
|
-
if (inputPath === "~") {
|
|
18279
|
-
return "~/";
|
|
18280
|
-
}
|
|
18281
|
-
if (inputPath === SANDBOX_HOME_DIR) {
|
|
18282
|
-
return "~/";
|
|
18283
|
-
}
|
|
18284
|
-
if (inputPath.startsWith(`${SANDBOX_HOME_DIR}/`)) {
|
|
18285
|
-
return `~/${inputPath.slice(SANDBOX_HOME_DIR.length + 1)}`;
|
|
18286
|
-
}
|
|
18287
|
-
if (inputPath.startsWith("~/")) {
|
|
18288
|
-
return inputPath;
|
|
18289
|
-
}
|
|
18290
|
-
if (inputPath.startsWith("/")) {
|
|
18291
|
-
return `~${inputPath}`;
|
|
18292
|
-
}
|
|
18293
|
-
return inputPath;
|
|
18294
|
-
}
|
|
18295
|
-
function toSandboxRelativePath(inputPath) {
|
|
18296
|
-
const canonicalPath = normalizeExternalSandboxPath(inputPath);
|
|
18297
|
-
return canonicalPath === "~/" ? "" : canonicalPath.slice(2);
|
|
18298
|
-
}
|
|
18299
|
-
function toSandboxAbsolutePath(inputPath, homeDir = SANDBOX_HOME_DIR) {
|
|
18300
|
-
const relativePath = toSandboxRelativePath(inputPath);
|
|
18301
|
-
return relativePath ? path3.posix.join(homeDir, relativePath) : homeDir;
|
|
18302
|
-
}
|
|
18303
|
-
function fromSandboxExecutionPath(inputPath, homeDir = SANDBOX_HOME_DIR) {
|
|
18304
|
-
if (inputPath === homeDir) {
|
|
18305
|
-
return "~/";
|
|
18306
|
-
}
|
|
18307
|
-
if (inputPath.startsWith(`${homeDir}/`)) {
|
|
18308
|
-
return `~/${inputPath.slice(homeDir.length + 1)}`;
|
|
18309
|
-
}
|
|
18310
|
-
return normalizeExternalSandboxPath(inputPath);
|
|
18311
|
-
}
|
|
18312
|
-
|
|
18313
18400
|
// src/sandbox_lattice/MicrosandboxRemoteInstance.ts
|
|
18314
18401
|
var MicrosandboxRemoteInstance = class {
|
|
18315
18402
|
constructor(name, client) {
|
|
@@ -18318,43 +18405,43 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18318
18405
|
readFile: async (file) => {
|
|
18319
18406
|
const result = await this.client.readFile(
|
|
18320
18407
|
this.name,
|
|
18321
|
-
|
|
18408
|
+
normalizeExternalSandboxPath(file)
|
|
18322
18409
|
);
|
|
18323
18410
|
return { content: result.content };
|
|
18324
18411
|
},
|
|
18325
18412
|
writeFile: async (file, content) => {
|
|
18326
18413
|
await this.client.writeFile(
|
|
18327
18414
|
this.name,
|
|
18328
|
-
|
|
18415
|
+
normalizeExternalSandboxPath(file),
|
|
18329
18416
|
content
|
|
18330
18417
|
);
|
|
18331
18418
|
},
|
|
18332
|
-
listPath: async (
|
|
18419
|
+
listPath: async (path3, options) => {
|
|
18333
18420
|
const result = await this.client.listPath(
|
|
18334
18421
|
this.name,
|
|
18335
|
-
|
|
18422
|
+
normalizeExternalSandboxPath(path3),
|
|
18336
18423
|
options?.recursive
|
|
18337
18424
|
);
|
|
18338
18425
|
const files = result.entries.map((entry) => ({
|
|
18339
|
-
path:
|
|
18426
|
+
path: normalizeExternalSandboxPath(entry.path),
|
|
18340
18427
|
is_dir: entry.type === "directory"
|
|
18341
18428
|
}));
|
|
18342
18429
|
return { files };
|
|
18343
18430
|
},
|
|
18344
|
-
findFiles: async (
|
|
18431
|
+
findFiles: async (path3, glob) => {
|
|
18345
18432
|
const result = await this.client.findFiles(
|
|
18346
18433
|
this.name,
|
|
18347
|
-
|
|
18434
|
+
normalizeExternalSandboxPath(path3),
|
|
18348
18435
|
glob
|
|
18349
18436
|
);
|
|
18350
18437
|
return {
|
|
18351
|
-
files: result.files.map((filePath) =>
|
|
18438
|
+
files: result.files.map((filePath) => normalizeExternalSandboxPath(filePath))
|
|
18352
18439
|
};
|
|
18353
18440
|
},
|
|
18354
18441
|
searchInFile: async (file, regex) => {
|
|
18355
18442
|
const result = await this.client.searchInFile(
|
|
18356
18443
|
this.name,
|
|
18357
|
-
|
|
18444
|
+
normalizeExternalSandboxPath(file),
|
|
18358
18445
|
regex
|
|
18359
18446
|
);
|
|
18360
18447
|
return {
|
|
@@ -18364,7 +18451,7 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18364
18451
|
},
|
|
18365
18452
|
strReplaceEditor: async (params) => {
|
|
18366
18453
|
await this.client.replaceInFile(this.name, {
|
|
18367
|
-
path:
|
|
18454
|
+
path: normalizeExternalSandboxPath(params.path),
|
|
18368
18455
|
search: params.old_str,
|
|
18369
18456
|
replace: params.new_str
|
|
18370
18457
|
});
|
|
@@ -18372,14 +18459,14 @@ var MicrosandboxRemoteInstance = class {
|
|
|
18372
18459
|
uploadFile: async (params) => {
|
|
18373
18460
|
await this.client.uploadFile(
|
|
18374
18461
|
this.name,
|
|
18375
|
-
|
|
18462
|
+
normalizeExternalSandboxPath(params.file),
|
|
18376
18463
|
params.data
|
|
18377
18464
|
);
|
|
18378
18465
|
},
|
|
18379
18466
|
downloadFile: async (params) => {
|
|
18380
18467
|
const result = await this.client.downloadFile(
|
|
18381
18468
|
this.name,
|
|
18382
|
-
|
|
18469
|
+
normalizeExternalSandboxPath(params.file)
|
|
18383
18470
|
);
|
|
18384
18471
|
if (result.contentBase64) {
|
|
18385
18472
|
return Buffer.from(result.contentBase64, "base64");
|
|
@@ -18458,34 +18545,34 @@ var MicrosandboxServiceClient = class {
|
|
|
18458
18545
|
method: "GET"
|
|
18459
18546
|
});
|
|
18460
18547
|
}
|
|
18461
|
-
async readFile(sandboxName,
|
|
18548
|
+
async readFile(sandboxName, path3) {
|
|
18462
18549
|
return this.request("/api/files/read", {
|
|
18463
18550
|
method: "POST",
|
|
18464
|
-
body: { sandboxName, path:
|
|
18551
|
+
body: { sandboxName, path: path3 }
|
|
18465
18552
|
});
|
|
18466
18553
|
}
|
|
18467
|
-
async writeFile(sandboxName,
|
|
18554
|
+
async writeFile(sandboxName, path3, content) {
|
|
18468
18555
|
return this.request("/api/files/write", {
|
|
18469
18556
|
method: "POST",
|
|
18470
|
-
body: { sandboxName, path:
|
|
18557
|
+
body: { sandboxName, path: path3, content }
|
|
18471
18558
|
});
|
|
18472
18559
|
}
|
|
18473
|
-
async listPath(sandboxName,
|
|
18560
|
+
async listPath(sandboxName, path3, recursive) {
|
|
18474
18561
|
return this.request("/api/files/list", {
|
|
18475
18562
|
method: "POST",
|
|
18476
|
-
body: { sandboxName, path:
|
|
18563
|
+
body: { sandboxName, path: path3, recursive }
|
|
18477
18564
|
});
|
|
18478
18565
|
}
|
|
18479
|
-
async findFiles(sandboxName,
|
|
18566
|
+
async findFiles(sandboxName, path3, pattern) {
|
|
18480
18567
|
return this.request("/api/files/find", {
|
|
18481
18568
|
method: "POST",
|
|
18482
|
-
body: { sandboxName, path:
|
|
18569
|
+
body: { sandboxName, path: path3, pattern }
|
|
18483
18570
|
});
|
|
18484
18571
|
}
|
|
18485
|
-
async searchInFile(sandboxName,
|
|
18572
|
+
async searchInFile(sandboxName, path3, query) {
|
|
18486
18573
|
return this.request("/api/files/search", {
|
|
18487
18574
|
method: "POST",
|
|
18488
|
-
body: { sandboxName, path:
|
|
18575
|
+
body: { sandboxName, path: path3, query }
|
|
18489
18576
|
});
|
|
18490
18577
|
}
|
|
18491
18578
|
async replaceInFile(sandboxName, input) {
|
|
@@ -18494,14 +18581,14 @@ var MicrosandboxServiceClient = class {
|
|
|
18494
18581
|
body: { sandboxName, ...input }
|
|
18495
18582
|
});
|
|
18496
18583
|
}
|
|
18497
|
-
async uploadFile(sandboxName,
|
|
18584
|
+
async uploadFile(sandboxName, path3, content) {
|
|
18498
18585
|
return this.request("/api/files/upload", {
|
|
18499
18586
|
method: "POST",
|
|
18500
|
-
body: { sandboxName, path:
|
|
18587
|
+
body: { sandboxName, path: path3, contentBase64: content.toString("base64") }
|
|
18501
18588
|
});
|
|
18502
18589
|
}
|
|
18503
|
-
async downloadFile(sandboxName,
|
|
18504
|
-
const query = new URLSearchParams({ sandboxName, path:
|
|
18590
|
+
async downloadFile(sandboxName, path3) {
|
|
18591
|
+
const query = new URLSearchParams({ sandboxName, path: path3 });
|
|
18505
18592
|
return this.request(`/api/files/download?${query.toString()}`, {
|
|
18506
18593
|
method: "GET"
|
|
18507
18594
|
});
|
|
@@ -18512,54 +18599,54 @@ var MicrosandboxServiceClient = class {
|
|
|
18512
18599
|
body: input
|
|
18513
18600
|
});
|
|
18514
18601
|
}
|
|
18515
|
-
async volumeFsRead(volumeName,
|
|
18602
|
+
async volumeFsRead(volumeName, path3) {
|
|
18516
18603
|
const result = await this.request(
|
|
18517
18604
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/read`,
|
|
18518
18605
|
{
|
|
18519
18606
|
method: "POST",
|
|
18520
|
-
body: { path:
|
|
18607
|
+
body: { path: path3 }
|
|
18521
18608
|
}
|
|
18522
18609
|
);
|
|
18523
18610
|
return result.content;
|
|
18524
18611
|
}
|
|
18525
|
-
async volumeFsWrite(volumeName,
|
|
18612
|
+
async volumeFsWrite(volumeName, path3, content) {
|
|
18526
18613
|
await this.request(
|
|
18527
18614
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/write`,
|
|
18528
18615
|
{
|
|
18529
18616
|
method: "POST",
|
|
18530
|
-
body: { path:
|
|
18617
|
+
body: { path: path3, content }
|
|
18531
18618
|
}
|
|
18532
18619
|
);
|
|
18533
18620
|
}
|
|
18534
|
-
async volumeFsList(volumeName,
|
|
18621
|
+
async volumeFsList(volumeName, path3) {
|
|
18535
18622
|
const result = await this.request(
|
|
18536
18623
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/list`,
|
|
18537
18624
|
{
|
|
18538
18625
|
method: "POST",
|
|
18539
|
-
body: { path:
|
|
18626
|
+
body: { path: path3 }
|
|
18540
18627
|
}
|
|
18541
18628
|
);
|
|
18542
18629
|
return result.entries;
|
|
18543
18630
|
}
|
|
18544
|
-
async volumeFsDownload(volumeName,
|
|
18631
|
+
async volumeFsDownload(volumeName, path3) {
|
|
18545
18632
|
const result = await this.request(
|
|
18546
|
-
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(
|
|
18633
|
+
`/api/volumes/${encodeURIComponent(volumeName)}/fs/download?path=${encodeURIComponent(path3)}`,
|
|
18547
18634
|
{
|
|
18548
18635
|
method: "GET"
|
|
18549
18636
|
}
|
|
18550
18637
|
);
|
|
18551
18638
|
return Buffer.from(result.contentBase64, "base64");
|
|
18552
18639
|
}
|
|
18553
|
-
async volumeFsUpload(volumeName,
|
|
18640
|
+
async volumeFsUpload(volumeName, path3, data) {
|
|
18554
18641
|
await this.request(
|
|
18555
18642
|
`/api/volumes/${encodeURIComponent(volumeName)}/fs/upload`,
|
|
18556
18643
|
{
|
|
18557
18644
|
method: "POST",
|
|
18558
|
-
body: { path:
|
|
18645
|
+
body: { path: path3, contentBase64: data.toString("base64") }
|
|
18559
18646
|
}
|
|
18560
18647
|
);
|
|
18561
18648
|
}
|
|
18562
|
-
async request(
|
|
18649
|
+
async request(path3, init) {
|
|
18563
18650
|
const headers = {};
|
|
18564
18651
|
if (init.body) {
|
|
18565
18652
|
headers["content-type"] = "application/json";
|
|
@@ -18567,7 +18654,7 @@ var MicrosandboxServiceClient = class {
|
|
|
18567
18654
|
if (this.apiKey) {
|
|
18568
18655
|
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
18569
18656
|
}
|
|
18570
|
-
const response = await fetch(`${this.baseURL}${
|
|
18657
|
+
const response = await fetch(`${this.baseURL}${path3}`, {
|
|
18571
18658
|
method: init.method,
|
|
18572
18659
|
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
18573
18660
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -18600,7 +18687,7 @@ function parseOptionalNumberEnv(name, fallback) {
|
|
|
18600
18687
|
}
|
|
18601
18688
|
function getDefaultMicrosandboxRemoteConfig() {
|
|
18602
18689
|
return {
|
|
18603
|
-
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.
|
|
18690
|
+
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.4",
|
|
18604
18691
|
//"daytonaio/sandbox:0.6.0",
|
|
18605
18692
|
cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
|
|
18606
18693
|
memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
|
|
@@ -18651,20 +18738,23 @@ var MicrosandboxRemoteProvider = class {
|
|
|
18651
18738
|
return instance;
|
|
18652
18739
|
}
|
|
18653
18740
|
async stopSandbox(name) {
|
|
18654
|
-
|
|
18741
|
+
try {
|
|
18742
|
+
await this.client.stopSandbox(name);
|
|
18743
|
+
} catch {
|
|
18744
|
+
}
|
|
18655
18745
|
this.instances.delete(name);
|
|
18656
18746
|
}
|
|
18657
18747
|
async deleteSandbox(name) {
|
|
18658
|
-
await this.client.deleteSandbox(name);
|
|
18659
18748
|
this.instances.delete(name);
|
|
18749
|
+
await this.client.deleteSandbox(name);
|
|
18660
18750
|
}
|
|
18661
18751
|
createVolumeFsClient(volumeName) {
|
|
18662
18752
|
return {
|
|
18663
|
-
read: (
|
|
18664
|
-
write: (
|
|
18665
|
-
list: (
|
|
18666
|
-
readRaw: (
|
|
18667
|
-
writeRaw: (
|
|
18753
|
+
read: (path3) => this.client.volumeFsRead(volumeName, path3),
|
|
18754
|
+
write: (path3, content) => this.client.volumeFsWrite(volumeName, path3, content),
|
|
18755
|
+
list: (path3) => this.client.volumeFsList(volumeName, path3),
|
|
18756
|
+
readRaw: (path3) => this.client.volumeFsDownload(volumeName, path3),
|
|
18757
|
+
writeRaw: (path3, data) => this.client.volumeFsUpload(volumeName, path3, data)
|
|
18668
18758
|
};
|
|
18669
18759
|
}
|
|
18670
18760
|
async listSandboxes() {
|
|
@@ -18686,19 +18776,19 @@ var MicrosandboxRemoteProvider = class {
|
|
|
18686
18776
|
buildDefaultVolumes(config) {
|
|
18687
18777
|
const tenantId = config?.tenantId ?? "default";
|
|
18688
18778
|
const volumes = {
|
|
18689
|
-
"/
|
|
18779
|
+
"/root/.agents": {
|
|
18690
18780
|
type: "named",
|
|
18691
18781
|
name: buildNamedVolumeName("s", "skills", tenantId)
|
|
18692
18782
|
}
|
|
18693
18783
|
};
|
|
18694
18784
|
if (config?.assistant_id) {
|
|
18695
|
-
volumes["/
|
|
18785
|
+
volumes["/agent"] = {
|
|
18696
18786
|
type: "named",
|
|
18697
18787
|
name: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id)
|
|
18698
18788
|
};
|
|
18699
18789
|
}
|
|
18700
18790
|
if (config?.projectId) {
|
|
18701
|
-
volumes["/
|
|
18791
|
+
volumes["/project"] = {
|
|
18702
18792
|
type: "named",
|
|
18703
18793
|
name: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId)
|
|
18704
18794
|
};
|
|
@@ -18728,9 +18818,9 @@ var RemoteSandboxInstance = class {
|
|
|
18728
18818
|
throw new Error(String(result.error));
|
|
18729
18819
|
}
|
|
18730
18820
|
},
|
|
18731
|
-
listPath: async (
|
|
18821
|
+
listPath: async (path3, options) => {
|
|
18732
18822
|
const result = await this.client.file.listPath({
|
|
18733
|
-
path:
|
|
18823
|
+
path: path3,
|
|
18734
18824
|
recursive: options?.recursive ?? false
|
|
18735
18825
|
});
|
|
18736
18826
|
if (!result.ok) {
|
|
@@ -18744,8 +18834,8 @@ var RemoteSandboxInstance = class {
|
|
|
18744
18834
|
}));
|
|
18745
18835
|
return { files };
|
|
18746
18836
|
},
|
|
18747
|
-
findFiles: async (
|
|
18748
|
-
const result = await this.client.file.findFiles({ path:
|
|
18837
|
+
findFiles: async (path3, glob) => {
|
|
18838
|
+
const result = await this.client.file.findFiles({ path: path3, glob });
|
|
18749
18839
|
if (!result.ok) {
|
|
18750
18840
|
throw new Error(String(result.error));
|
|
18751
18841
|
}
|
|
@@ -18882,8 +18972,8 @@ var E2BInstance = class {
|
|
|
18882
18972
|
writeFile: async (file, content) => {
|
|
18883
18973
|
await this.native.files.write(file, content);
|
|
18884
18974
|
},
|
|
18885
|
-
listPath: async (
|
|
18886
|
-
const entries = await this.native.files.list(
|
|
18975
|
+
listPath: async (path3, options) => {
|
|
18976
|
+
const entries = await this.native.files.list(path3);
|
|
18887
18977
|
const files = entries.map((e) => ({
|
|
18888
18978
|
path: e.path,
|
|
18889
18979
|
is_dir: e.type === "dir",
|
|
@@ -18892,9 +18982,9 @@ var E2BInstance = class {
|
|
|
18892
18982
|
}));
|
|
18893
18983
|
return { files };
|
|
18894
18984
|
},
|
|
18895
|
-
findFiles: async (
|
|
18985
|
+
findFiles: async (path3, glob) => {
|
|
18896
18986
|
const result = await this.native.commands.run(
|
|
18897
|
-
`find "${
|
|
18987
|
+
`find "${path3}" -name "${glob}" -type f`
|
|
18898
18988
|
);
|
|
18899
18989
|
const lines = result.stdout.split("\n").filter(Boolean);
|
|
18900
18990
|
return { files: lines };
|
|
@@ -18917,13 +19007,13 @@ var E2BInstance = class {
|
|
|
18917
19007
|
return { matches, line_numbers };
|
|
18918
19008
|
},
|
|
18919
19009
|
strReplaceEditor: async (params) => {
|
|
18920
|
-
const { path:
|
|
19010
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
18921
19011
|
const delim = "#";
|
|
18922
19012
|
const escapedOld = old_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18923
19013
|
const escapedNew = new_str.replace(new RegExp(`[\\\\${delim}]`, "g"), "\\$&").replace(/\n/g, "\\n");
|
|
18924
19014
|
const flag = replace_mode === "ALL" ? "g" : "";
|
|
18925
19015
|
await this.native.commands.run(
|
|
18926
|
-
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${
|
|
19016
|
+
`sed -i 's${delim}${escapedOld}${delim}${escapedNew}${delim}${flag}' "${path3}"`
|
|
18927
19017
|
);
|
|
18928
19018
|
},
|
|
18929
19019
|
uploadFile: async (params) => {
|
|
@@ -19015,15 +19105,18 @@ var E2BProvider = class {
|
|
|
19015
19105
|
async stopSandbox(name) {
|
|
19016
19106
|
const instance = this.instances.get(name);
|
|
19017
19107
|
if (instance) {
|
|
19018
|
-
|
|
19108
|
+
try {
|
|
19109
|
+
await instance.stop();
|
|
19110
|
+
} catch {
|
|
19111
|
+
}
|
|
19019
19112
|
}
|
|
19020
19113
|
}
|
|
19021
19114
|
async deleteSandbox(name) {
|
|
19022
19115
|
const instance = this.instances.get(name);
|
|
19116
|
+
this.instances.delete(name);
|
|
19023
19117
|
if (instance) {
|
|
19024
19118
|
await instance.kill();
|
|
19025
19119
|
}
|
|
19026
|
-
this.instances.delete(name);
|
|
19027
19120
|
}
|
|
19028
19121
|
async listSandboxes() {
|
|
19029
19122
|
return Array.from(this.instances.values());
|
|
@@ -19034,23 +19127,27 @@ var E2BProvider = class {
|
|
|
19034
19127
|
import { Daytona } from "@daytonaio/sdk";
|
|
19035
19128
|
|
|
19036
19129
|
// src/sandbox_lattice/DaytonaInstance.ts
|
|
19130
|
+
function toRelativePath(inputPath) {
|
|
19131
|
+
const normalized = normalizeExternalSandboxPath(inputPath);
|
|
19132
|
+
return normalized === "/" ? "" : normalized.slice(1);
|
|
19133
|
+
}
|
|
19037
19134
|
var DaytonaInstance = class {
|
|
19038
19135
|
constructor(name, native) {
|
|
19039
19136
|
this.native = native;
|
|
19040
19137
|
this.file = {
|
|
19041
19138
|
readFile: async (file) => {
|
|
19042
|
-
const buffer2 = await this.native.fs.downloadFile(
|
|
19139
|
+
const buffer2 = await this.native.fs.downloadFile(toRelativePath(file));
|
|
19043
19140
|
return { content: buffer2.toString("utf-8") };
|
|
19044
19141
|
},
|
|
19045
19142
|
writeFile: async (file, content) => {
|
|
19046
|
-
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"),
|
|
19143
|
+
await this.native.fs.uploadFile(Buffer.from(content, "utf-8"), toRelativePath(file));
|
|
19047
19144
|
},
|
|
19048
|
-
listPath: async (
|
|
19049
|
-
const entries = await this.native.fs.listFiles(
|
|
19145
|
+
listPath: async (path3, options) => {
|
|
19146
|
+
const entries = await this.native.fs.listFiles(toRelativePath(path3));
|
|
19050
19147
|
const files = entries.map((e) => {
|
|
19051
19148
|
const rawPath = e.name || "";
|
|
19052
19149
|
return {
|
|
19053
|
-
path:
|
|
19150
|
+
path: normalizeExternalSandboxPath(rawPath),
|
|
19054
19151
|
is_dir: e.isDir ?? false,
|
|
19055
19152
|
size: e.size,
|
|
19056
19153
|
modified_at: e.modTime ? e.modTime : void 0
|
|
@@ -19058,12 +19155,12 @@ var DaytonaInstance = class {
|
|
|
19058
19155
|
});
|
|
19059
19156
|
return { files };
|
|
19060
19157
|
},
|
|
19061
|
-
findFiles: async (
|
|
19062
|
-
const result = await this.native.fs.searchFiles(
|
|
19063
|
-
return { files: (result.files || []).map((filePath) =>
|
|
19158
|
+
findFiles: async (path3, glob) => {
|
|
19159
|
+
const result = await this.native.fs.searchFiles(toRelativePath(path3), glob);
|
|
19160
|
+
return { files: (result.files || []).map((filePath) => normalizeExternalSandboxPath(filePath)) };
|
|
19064
19161
|
},
|
|
19065
19162
|
searchInFile: async (file, regex) => {
|
|
19066
|
-
const matches = await this.native.fs.findFiles(
|
|
19163
|
+
const matches = await this.native.fs.findFiles(toRelativePath(file), regex);
|
|
19067
19164
|
const line_numbers = [];
|
|
19068
19165
|
const matchTexts = [];
|
|
19069
19166
|
for (const match of matches) {
|
|
@@ -19073,8 +19170,8 @@ var DaytonaInstance = class {
|
|
|
19073
19170
|
return { matches: matchTexts, line_numbers };
|
|
19074
19171
|
},
|
|
19075
19172
|
strReplaceEditor: async (params) => {
|
|
19076
|
-
const { path:
|
|
19077
|
-
const relPath =
|
|
19173
|
+
const { path: path3, old_str, new_str, replace_mode } = params;
|
|
19174
|
+
const relPath = toRelativePath(path3);
|
|
19078
19175
|
if (replace_mode === "ALL") {
|
|
19079
19176
|
await this.native.fs.replaceInFiles([relPath], old_str, new_str);
|
|
19080
19177
|
} else {
|
|
@@ -19088,10 +19185,10 @@ var DaytonaInstance = class {
|
|
|
19088
19185
|
}
|
|
19089
19186
|
},
|
|
19090
19187
|
uploadFile: async (params) => {
|
|
19091
|
-
await this.native.fs.uploadFile(params.data,
|
|
19188
|
+
await this.native.fs.uploadFile(params.data, toRelativePath(params.file));
|
|
19092
19189
|
},
|
|
19093
19190
|
downloadFile: async (params) => {
|
|
19094
|
-
const buffer2 = await this.native.fs.downloadFile(
|
|
19191
|
+
const buffer2 = await this.native.fs.downloadFile(toRelativePath(params.file));
|
|
19095
19192
|
return Buffer.isBuffer(buffer2) ? buffer2 : Buffer.from(buffer2);
|
|
19096
19193
|
}
|
|
19097
19194
|
};
|
|
@@ -19207,9 +19304,14 @@ var DaytonaProvider = class {
|
|
|
19207
19304
|
if (volumes.length > 0) {
|
|
19208
19305
|
try {
|
|
19209
19306
|
for (const vol of volumes) {
|
|
19210
|
-
|
|
19211
|
-
|
|
19212
|
-
|
|
19307
|
+
try {
|
|
19308
|
+
await native.fs.listFiles(vol.mountPath);
|
|
19309
|
+
console.log(`[DaytonaProvider] Volume mount verified: ${vol.mountPath}`);
|
|
19310
|
+
} catch {
|
|
19311
|
+
const relPath = vol.mountPath.startsWith("/") ? vol.mountPath.slice(1) : vol.mountPath;
|
|
19312
|
+
await native.fs.listFiles(relPath);
|
|
19313
|
+
console.log(`[DaytonaProvider] Volume mount verified: /${relPath}`);
|
|
19314
|
+
}
|
|
19213
19315
|
}
|
|
19214
19316
|
} catch (verifyErr) {
|
|
19215
19317
|
console.warn(`[DaytonaProvider] Volume mount verification warning: ${verifyErr.message}`);
|
|
@@ -19227,9 +19329,9 @@ var DaytonaProvider = class {
|
|
|
19227
19329
|
/**
|
|
19228
19330
|
* Build volume mounts for a sandbox based on RunSandboxConfig.
|
|
19229
19331
|
* Mounts:
|
|
19230
|
-
*
|
|
19231
|
-
*
|
|
19232
|
-
*
|
|
19332
|
+
* /root/.agents → tenants/{tenantId}/skills
|
|
19333
|
+
* /agent → tenants/{tenantId}/agents/{assistantId}
|
|
19334
|
+
* /project → tenants/{tenantId}/projects/{projectId}
|
|
19233
19335
|
*/
|
|
19234
19336
|
async buildVolumeMounts(config) {
|
|
19235
19337
|
if (!config || !this.config.volumeName) {
|
|
@@ -19243,20 +19345,20 @@ var DaytonaProvider = class {
|
|
|
19243
19345
|
const mounts = [];
|
|
19244
19346
|
mounts.push({
|
|
19245
19347
|
volumeId: volume.id,
|
|
19246
|
-
mountPath: "/
|
|
19348
|
+
mountPath: "/root/.agents",
|
|
19247
19349
|
subpath: `tenants/${tenantId}/skills`
|
|
19248
19350
|
});
|
|
19249
19351
|
if (config.assistant_id) {
|
|
19250
19352
|
mounts.push({
|
|
19251
19353
|
volumeId: volume.id,
|
|
19252
|
-
mountPath: "/
|
|
19354
|
+
mountPath: "/agent",
|
|
19253
19355
|
subpath: `tenants/${tenantId}/agents/${config.assistant_id}`
|
|
19254
19356
|
});
|
|
19255
19357
|
}
|
|
19256
19358
|
if (config.projectId) {
|
|
19257
19359
|
mounts.push({
|
|
19258
19360
|
volumeId: volume.id,
|
|
19259
|
-
mountPath: "/
|
|
19361
|
+
mountPath: "/project",
|
|
19260
19362
|
subpath: `tenants/${tenantId}/projects/${config.projectId}`
|
|
19261
19363
|
});
|
|
19262
19364
|
}
|
|
@@ -19305,18 +19407,21 @@ var DaytonaProvider = class {
|
|
|
19305
19407
|
async stopSandbox(name) {
|
|
19306
19408
|
const instance = this.instances.get(name);
|
|
19307
19409
|
if (instance) {
|
|
19308
|
-
|
|
19410
|
+
try {
|
|
19411
|
+
await instance.stop();
|
|
19412
|
+
} catch {
|
|
19413
|
+
}
|
|
19309
19414
|
}
|
|
19310
19415
|
}
|
|
19311
19416
|
async deleteSandbox(name) {
|
|
19312
19417
|
const instance = this.instances.get(name);
|
|
19418
|
+
this.instances.delete(name);
|
|
19313
19419
|
if (instance) {
|
|
19314
19420
|
try {
|
|
19315
19421
|
await instance.kill();
|
|
19316
19422
|
} catch {
|
|
19317
19423
|
}
|
|
19318
19424
|
}
|
|
19319
|
-
this.instances.delete(name);
|
|
19320
19425
|
}
|
|
19321
19426
|
async listSandboxes() {
|
|
19322
19427
|
return Array.from(this.instances.values());
|