@letta-ai/letta-code 0.21.11 → 0.21.13
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/letta.js +1029 -340
- package/package.json +1 -1
- package/skills/working-in-parallel/SKILL.md +4 -0
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.21.
|
|
3272
|
+
version: "0.21.13",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -6841,7 +6841,7 @@ skills:
|
|
|
6841
6841
|
model: auto
|
|
6842
6842
|
memoryBlocks: none
|
|
6843
6843
|
mode: stateless
|
|
6844
|
-
permissionMode:
|
|
6844
|
+
permissionMode: memory
|
|
6845
6845
|
---
|
|
6846
6846
|
|
|
6847
6847
|
You are a history analysis subagent. You create a git worktree from the agent's memory repo, read conversation history from Claude Code or Codex, then **directly create and update memory files** in your worktree based on what you learn.
|
|
@@ -6921,12 +6921,18 @@ Keep specific correction counts ("corrected 10+ times"), specific file paths, an
|
|
|
6921
6921
|
\`\`\`bash
|
|
6922
6922
|
MEMORY_DIR=~/.letta/agents/$LETTA_PARENT_AGENT_ID/memory
|
|
6923
6923
|
WORKTREE_DIR=~/.letta/agents/$LETTA_PARENT_AGENT_ID/memory-worktrees
|
|
6924
|
-
|
|
6924
|
+
# Run \`date +%s\` first, then paste that exact output below.
|
|
6925
|
+
BRANCH_NAME="migration-<epoch-seconds>"
|
|
6925
6926
|
mkdir -p "$WORKTREE_DIR"
|
|
6926
6927
|
cd "$MEMORY_DIR"
|
|
6927
6928
|
git worktree add "$WORKTREE_DIR/$BRANCH_NAME" -b "$BRANCH_NAME"
|
|
6928
6929
|
\`\`\`
|
|
6929
6930
|
|
|
6931
|
+
Use epoch seconds from a prior \`date +%s\` command so branch names match the
|
|
6932
|
+
old behavior. Do not use shell command substitution like \`$(date +%s)\` in the
|
|
6933
|
+
branch assignment because memory-mode shell permissions deny command
|
|
6934
|
+
substitution.
|
|
6935
|
+
|
|
6930
6936
|
If worktree creation fails (locked index), retry up to 3 times with backoff (sleep 2, 5, 10). Never delete \`.git/index.lock\` manually. All edits go in \`$WORKTREE_DIR/$BRANCH_NAME/\`.
|
|
6931
6937
|
|
|
6932
6938
|
### 2. Read existing memory
|
|
@@ -7043,7 +7049,7 @@ description: Fast initialization of agent memory — reads key project files and
|
|
|
7043
7049
|
tools: Read, Write, Edit, Bash, Glob
|
|
7044
7050
|
model: auto-fast
|
|
7045
7051
|
memoryBlocks: none
|
|
7046
|
-
permissionMode:
|
|
7052
|
+
permissionMode: memory
|
|
7047
7053
|
---
|
|
7048
7054
|
|
|
7049
7055
|
You are a fast memory initialization subagent. Your job is to quickly scan a project and create a **skeleton memory hierarchy** for the parent agent. This hierarchy starts minimal and gets fleshed out as the user keeps interacting with the agent.
|
|
@@ -7151,7 +7157,7 @@ description: Decompose and reorganize memory files into focused, single-purpose
|
|
|
7151
7157
|
tools: Read, Edit, Write, Glob, Grep, Bash, TaskOutput
|
|
7152
7158
|
model: auto
|
|
7153
7159
|
memoryBlocks: none
|
|
7154
|
-
permissionMode:
|
|
7160
|
+
permissionMode: memory
|
|
7155
7161
|
---
|
|
7156
7162
|
|
|
7157
7163
|
You are a memory defragmentation subagent. You work directly on the git-backed memory filesystem to decompose and reorganize memory files.
|
|
@@ -7226,12 +7232,18 @@ making changes.
|
|
|
7226
7232
|
**Create worktree:**
|
|
7227
7233
|
|
|
7228
7234
|
\`\`\`bash
|
|
7229
|
-
|
|
7235
|
+
# Run \`date +%s\` first, then paste that exact output below.
|
|
7236
|
+
BRANCH="defrag-<epoch-seconds>"
|
|
7230
7237
|
mkdir -p "$WORKTREE_DIR"
|
|
7231
7238
|
cd "$MEMORY_DIR"
|
|
7232
7239
|
git worktree add "$WORKTREE_DIR/$BRANCH" -b "$BRANCH"
|
|
7233
7240
|
\`\`\`
|
|
7234
7241
|
|
|
7242
|
+
Use epoch seconds from a prior \`date +%s\` command so branch names match the
|
|
7243
|
+
old behavior. Do not use shell command substitution like \`$(date +%s)\` in the
|
|
7244
|
+
branch assignment because memory-mode shell permissions deny command
|
|
7245
|
+
substitution.
|
|
7246
|
+
|
|
7235
7247
|
All subsequent file operations target the worktree:
|
|
7236
7248
|
\`$WORKTREE_DIR/$BRANCH/system/\` (not the main memory dir).
|
|
7237
7249
|
|
|
@@ -7506,7 +7518,7 @@ tools: Read, Edit, Write, Glob, Grep, Bash, TaskOutput
|
|
|
7506
7518
|
model: auto
|
|
7507
7519
|
memoryBlocks: none
|
|
7508
7520
|
mode: stateless
|
|
7509
|
-
permissionMode:
|
|
7521
|
+
permissionMode: memory
|
|
7510
7522
|
---
|
|
7511
7523
|
|
|
7512
7524
|
You are a reflection subagent — a background agent that asynchronously processes conversations after they occur, similar to a "sleep-time" memory consolidation process.
|
|
@@ -40496,7 +40508,7 @@ import {
|
|
|
40496
40508
|
mkdirSync as mkdirSync8,
|
|
40497
40509
|
readFileSync as readFileSync7,
|
|
40498
40510
|
renameSync as renameSync2,
|
|
40499
|
-
|
|
40511
|
+
rmSync as rmSync2,
|
|
40500
40512
|
statSync as statSync2,
|
|
40501
40513
|
writeFileSync as writeFileSync6
|
|
40502
40514
|
} from "node:fs";
|
|
@@ -40574,7 +40586,7 @@ function isLockStale(lockDir) {
|
|
|
40574
40586
|
}
|
|
40575
40587
|
function stealLock(lockDir) {
|
|
40576
40588
|
try {
|
|
40577
|
-
|
|
40589
|
+
rmSync2(lockDir, { recursive: true, force: true });
|
|
40578
40590
|
} catch {}
|
|
40579
40591
|
}
|
|
40580
40592
|
function acquireLock() {
|
|
@@ -40595,7 +40607,7 @@ function acquireLock() {
|
|
|
40595
40607
|
try {
|
|
40596
40608
|
const current = readLockOwner(lockDir);
|
|
40597
40609
|
if (current && current.token === token) {
|
|
40598
|
-
|
|
40610
|
+
rmSync2(lockDir, { recursive: true, force: true });
|
|
40599
40611
|
}
|
|
40600
40612
|
} catch {}
|
|
40601
40613
|
}
|
|
@@ -52238,9 +52250,138 @@ var init_hooks = __esm(async () => {
|
|
|
52238
52250
|
init_types();
|
|
52239
52251
|
});
|
|
52240
52252
|
|
|
52241
|
-
// src/permissions/
|
|
52253
|
+
// src/permissions/memoryScope.ts
|
|
52242
52254
|
import { homedir as homedir11 } from "node:os";
|
|
52243
|
-
import { resolve as resolve4 } from "node:path";
|
|
52255
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute2, resolve as resolve4 } from "node:path";
|
|
52256
|
+
function normalizeScopedPath(path4) {
|
|
52257
|
+
const resolvedPath = resolve4(expandHomePath(path4));
|
|
52258
|
+
const normalized = resolvedPath.replace(/\\/g, "/");
|
|
52259
|
+
return normalized.replace(/\/+$/, "") || "/";
|
|
52260
|
+
}
|
|
52261
|
+
function expandHomePath(path4) {
|
|
52262
|
+
const value = path4.trim();
|
|
52263
|
+
const homeDir = homedir11();
|
|
52264
|
+
if (value.startsWith("~/")) {
|
|
52265
|
+
return resolve4(homeDir, value.slice(2));
|
|
52266
|
+
}
|
|
52267
|
+
if (value.startsWith("$HOME/")) {
|
|
52268
|
+
return resolve4(homeDir, value.slice(6));
|
|
52269
|
+
}
|
|
52270
|
+
if (value.startsWith('"$HOME/')) {
|
|
52271
|
+
return resolve4(homeDir, value.slice(7).replace(/"$/, ""));
|
|
52272
|
+
}
|
|
52273
|
+
return value;
|
|
52274
|
+
}
|
|
52275
|
+
function resolveScopedTargetPath(targetPath, workingDirectory) {
|
|
52276
|
+
const trimmedPath = targetPath.trim();
|
|
52277
|
+
if (!trimmedPath)
|
|
52278
|
+
return null;
|
|
52279
|
+
if (trimmedPath.startsWith("~/") || trimmedPath.startsWith("$HOME/")) {
|
|
52280
|
+
return normalizeScopedPath(trimmedPath);
|
|
52281
|
+
}
|
|
52282
|
+
if (isAbsolute2(trimmedPath) || /^[a-zA-Z]:[\\/]/.test(trimmedPath)) {
|
|
52283
|
+
return normalizeScopedPath(trimmedPath);
|
|
52284
|
+
}
|
|
52285
|
+
return normalizeScopedPath(resolve4(workingDirectory, trimmedPath));
|
|
52286
|
+
}
|
|
52287
|
+
function isPathWithinRoots(path4, roots) {
|
|
52288
|
+
const normalizedPath = normalizeScopedPath(path4);
|
|
52289
|
+
return roots.some((root) => {
|
|
52290
|
+
const normalizedRoot = normalizeScopedPath(root);
|
|
52291
|
+
return normalizedPath === normalizedRoot || normalizedPath.startsWith(`${normalizedRoot}/`);
|
|
52292
|
+
});
|
|
52293
|
+
}
|
|
52294
|
+
function addRootAndSiblingWorktree(root, acc) {
|
|
52295
|
+
const normalizedRoot = normalizeScopedPath(root);
|
|
52296
|
+
if (!normalizedRoot) {
|
|
52297
|
+
return;
|
|
52298
|
+
}
|
|
52299
|
+
acc.add(normalizedRoot);
|
|
52300
|
+
const leaf = basename(normalizedRoot);
|
|
52301
|
+
if (leaf === "memory") {
|
|
52302
|
+
acc.add(normalizeScopedPath(resolve4(dirname4(normalizedRoot), "memory-worktrees")));
|
|
52303
|
+
}
|
|
52304
|
+
}
|
|
52305
|
+
function getExplicitEnvRoots(env3) {
|
|
52306
|
+
const orderedRoots = [
|
|
52307
|
+
env3.MEMORY_DIR,
|
|
52308
|
+
env3.LETTA_MEMORY_DIR,
|
|
52309
|
+
env3.PARENT_MEMORY_DIR
|
|
52310
|
+
].map((value) => value?.trim() ?? "").filter((value) => value.length > 0);
|
|
52311
|
+
const explicitRootSet = new Set;
|
|
52312
|
+
for (const root of orderedRoots) {
|
|
52313
|
+
addRootAndSiblingWorktree(root, explicitRootSet);
|
|
52314
|
+
}
|
|
52315
|
+
return {
|
|
52316
|
+
explicitRoots: [...explicitRootSet],
|
|
52317
|
+
primaryRoot: orderedRoots.length > 0 ? normalizeScopedPath(orderedRoots[0]) : null
|
|
52318
|
+
};
|
|
52319
|
+
}
|
|
52320
|
+
function deriveAgentId(env3, explicitAgentId) {
|
|
52321
|
+
const explicit = explicitAgentId?.trim();
|
|
52322
|
+
if (explicit) {
|
|
52323
|
+
return explicit;
|
|
52324
|
+
}
|
|
52325
|
+
const envAgentId = (env3.AGENT_ID || env3.LETTA_AGENT_ID || "").trim();
|
|
52326
|
+
if (envAgentId) {
|
|
52327
|
+
return envAgentId;
|
|
52328
|
+
}
|
|
52329
|
+
try {
|
|
52330
|
+
return getCurrentAgentId().trim();
|
|
52331
|
+
} catch {
|
|
52332
|
+
return null;
|
|
52333
|
+
}
|
|
52334
|
+
}
|
|
52335
|
+
function getFallbackRoots(env3, homeDir, currentAgentId, parentAgentId) {
|
|
52336
|
+
const fallbackRoots = new Set;
|
|
52337
|
+
const resolvedCurrentAgentId = deriveAgentId(env3, currentAgentId);
|
|
52338
|
+
const resolvedParentAgentId = (parentAgentId || env3.LETTA_PARENT_AGENT_ID || "").trim() || null;
|
|
52339
|
+
let primaryRoot = null;
|
|
52340
|
+
if (resolvedCurrentAgentId) {
|
|
52341
|
+
const currentRoot = getMemoryFilesystemRoot(resolvedCurrentAgentId, homeDir);
|
|
52342
|
+
addRootAndSiblingWorktree(currentRoot, fallbackRoots);
|
|
52343
|
+
primaryRoot = normalizeScopedPath(currentRoot);
|
|
52344
|
+
}
|
|
52345
|
+
if (resolvedParentAgentId && resolvedParentAgentId !== resolvedCurrentAgentId) {
|
|
52346
|
+
const parentRoot = getMemoryFilesystemRoot(resolvedParentAgentId, homeDir);
|
|
52347
|
+
addRootAndSiblingWorktree(parentRoot, fallbackRoots);
|
|
52348
|
+
if (!primaryRoot) {
|
|
52349
|
+
primaryRoot = normalizeScopedPath(parentRoot);
|
|
52350
|
+
}
|
|
52351
|
+
}
|
|
52352
|
+
return {
|
|
52353
|
+
roots: [...fallbackRoots],
|
|
52354
|
+
primaryRoot
|
|
52355
|
+
};
|
|
52356
|
+
}
|
|
52357
|
+
function resolveAllowedMemoryRoots(options = {}) {
|
|
52358
|
+
const env3 = options.env ?? process.env;
|
|
52359
|
+
const homeDir = options.homeDir ?? homedir11();
|
|
52360
|
+
const explicit = getExplicitEnvRoots(env3);
|
|
52361
|
+
if (explicit.explicitRoots.length > 0) {
|
|
52362
|
+
return {
|
|
52363
|
+
roots: explicit.explicitRoots,
|
|
52364
|
+
explicitRoots: explicit.explicitRoots,
|
|
52365
|
+
primaryRoot: explicit.primaryRoot,
|
|
52366
|
+
usedFallback: false
|
|
52367
|
+
};
|
|
52368
|
+
}
|
|
52369
|
+
const fallback = getFallbackRoots(env3, homeDir, options.currentAgentId, options.parentAgentId);
|
|
52370
|
+
return {
|
|
52371
|
+
roots: fallback.roots,
|
|
52372
|
+
explicitRoots: [],
|
|
52373
|
+
primaryRoot: fallback.primaryRoot,
|
|
52374
|
+
usedFallback: fallback.roots.length > 0
|
|
52375
|
+
};
|
|
52376
|
+
}
|
|
52377
|
+
var init_memoryScope = __esm(() => {
|
|
52378
|
+
init_context();
|
|
52379
|
+
init_memoryFilesystem();
|
|
52380
|
+
});
|
|
52381
|
+
|
|
52382
|
+
// src/permissions/readOnlyShell.ts
|
|
52383
|
+
import { homedir as homedir12 } from "node:os";
|
|
52384
|
+
import { resolve as resolve5 } from "node:path";
|
|
52244
52385
|
function splitShellSegments(input) {
|
|
52245
52386
|
const segments = [];
|
|
52246
52387
|
let current = "";
|
|
@@ -52312,6 +52453,13 @@ function splitShellSegments(input) {
|
|
|
52312
52453
|
i += 1;
|
|
52313
52454
|
continue;
|
|
52314
52455
|
}
|
|
52456
|
+
if (ch === `
|
|
52457
|
+
` || ch === "\r") {
|
|
52458
|
+
segments.push(current);
|
|
52459
|
+
current = "";
|
|
52460
|
+
i += 1;
|
|
52461
|
+
continue;
|
|
52462
|
+
}
|
|
52315
52463
|
if (ch === "|") {
|
|
52316
52464
|
segments.push(current);
|
|
52317
52465
|
current = "";
|
|
@@ -52503,7 +52651,7 @@ function isUnderAllowedPathRoot(value, allowedPathRoots) {
|
|
|
52503
52651
|
}
|
|
52504
52652
|
const resolvedValue = expandPath(value);
|
|
52505
52653
|
return allowedPathRoots.some((root) => {
|
|
52506
|
-
const normalizedRoot = normalizeSeparators(
|
|
52654
|
+
const normalizedRoot = normalizeSeparators(resolve5(root));
|
|
52507
52655
|
return resolvedValue === normalizedRoot || resolvedValue.startsWith(`${normalizedRoot}/`);
|
|
52508
52656
|
});
|
|
52509
52657
|
}
|
|
@@ -52546,14 +52694,14 @@ function parseGitInvocation(tokens, options) {
|
|
|
52546
52694
|
return { subcommand: null, isSafePath: true };
|
|
52547
52695
|
}
|
|
52548
52696
|
function getAllowedMemoryPrefixes(agentId) {
|
|
52549
|
-
const home =
|
|
52697
|
+
const home = homedir12();
|
|
52550
52698
|
const prefixes = [
|
|
52551
|
-
normalizeSeparators(
|
|
52552
|
-
normalizeSeparators(
|
|
52699
|
+
normalizeSeparators(resolve5(home, ".letta", "agents", agentId, "memory")),
|
|
52700
|
+
normalizeSeparators(resolve5(home, ".letta", "agents", agentId, "memory-worktrees"))
|
|
52553
52701
|
];
|
|
52554
52702
|
const parentId = process.env.LETTA_PARENT_AGENT_ID;
|
|
52555
52703
|
if (parentId && parentId !== agentId) {
|
|
52556
|
-
prefixes.push(normalizeSeparators(
|
|
52704
|
+
prefixes.push(normalizeSeparators(resolve5(home, ".letta", "agents", parentId, "memory")), normalizeSeparators(resolve5(home, ".letta", "agents", parentId, "memory-worktrees")));
|
|
52557
52705
|
}
|
|
52558
52706
|
return prefixes;
|
|
52559
52707
|
}
|
|
@@ -52561,122 +52709,315 @@ function normalizeSeparators(p) {
|
|
|
52561
52709
|
return p.replace(/\\/g, "/");
|
|
52562
52710
|
}
|
|
52563
52711
|
function expandPath(p) {
|
|
52564
|
-
|
|
52565
|
-
|
|
52566
|
-
|
|
52712
|
+
return normalizeScopedPath(p);
|
|
52713
|
+
}
|
|
52714
|
+
function expandScopedVariables(value, env3, shellVars) {
|
|
52715
|
+
let unresolved = false;
|
|
52716
|
+
const expanded = value.replace(/\$(?:{([A-Za-z_][A-Za-z0-9_]*)}|([A-Za-z_][A-Za-z0-9_]*))/g, (_match, bracedName, bareName) => {
|
|
52717
|
+
const name = bracedName || bareName;
|
|
52718
|
+
if (!name) {
|
|
52719
|
+
unresolved = true;
|
|
52720
|
+
return "";
|
|
52721
|
+
}
|
|
52722
|
+
if (name === "HOME") {
|
|
52723
|
+
return homedir12();
|
|
52724
|
+
}
|
|
52725
|
+
const scopedValue = shellVars[name];
|
|
52726
|
+
if (typeof scopedValue === "string") {
|
|
52727
|
+
return scopedValue;
|
|
52728
|
+
}
|
|
52729
|
+
const envValue = env3[name];
|
|
52730
|
+
if (typeof envValue === "string") {
|
|
52731
|
+
return envValue;
|
|
52732
|
+
}
|
|
52733
|
+
unresolved = true;
|
|
52734
|
+
return "";
|
|
52735
|
+
});
|
|
52736
|
+
return unresolved ? null : expanded;
|
|
52737
|
+
}
|
|
52738
|
+
function normalizeScopePath(path4, cwd2, env3, shellVars) {
|
|
52739
|
+
const expandedPath = expandScopedVariables(path4, env3, shellVars);
|
|
52740
|
+
if (!expandedPath) {
|
|
52741
|
+
return null;
|
|
52567
52742
|
}
|
|
52568
|
-
if (
|
|
52569
|
-
return
|
|
52743
|
+
if (expandedPath.startsWith("~/") || expandedPath.startsWith("$HOME/") || expandedPath.startsWith('"$HOME/') || expandedPath.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(expandedPath)) {
|
|
52744
|
+
return normalizeScopedPath(expandedPath);
|
|
52570
52745
|
}
|
|
52571
|
-
if (
|
|
52572
|
-
return
|
|
52746
|
+
if (cwd2) {
|
|
52747
|
+
return normalizeScopedPath(resolve5(cwd2, expandedPath));
|
|
52573
52748
|
}
|
|
52574
|
-
return
|
|
52749
|
+
return null;
|
|
52750
|
+
}
|
|
52751
|
+
function parseScopedAssignmentToken(token) {
|
|
52752
|
+
const match = token.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
52753
|
+
if (!match) {
|
|
52754
|
+
return null;
|
|
52755
|
+
}
|
|
52756
|
+
return {
|
|
52757
|
+
name: match[1] ?? "",
|
|
52758
|
+
value: stripQuotes(match[2] ?? "")
|
|
52759
|
+
};
|
|
52760
|
+
}
|
|
52761
|
+
function applyScopedAssignments(tokens, env3, shellVars) {
|
|
52762
|
+
if (tokens.length === 0) {
|
|
52763
|
+
return false;
|
|
52764
|
+
}
|
|
52765
|
+
for (const token of tokens) {
|
|
52766
|
+
const assignment = parseScopedAssignmentToken(token);
|
|
52767
|
+
if (!assignment) {
|
|
52768
|
+
return false;
|
|
52769
|
+
}
|
|
52770
|
+
const expandedValue = expandScopedVariables(assignment.value, env3, shellVars);
|
|
52771
|
+
if (expandedValue === null) {
|
|
52772
|
+
return false;
|
|
52773
|
+
}
|
|
52774
|
+
if (expandedValue.startsWith("~/") || expandedValue.startsWith("$HOME/") || expandedValue.startsWith('"$HOME/') || expandedValue.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(expandedValue)) {
|
|
52775
|
+
shellVars[assignment.name] = normalizeScopedPath(expandedValue);
|
|
52776
|
+
} else {
|
|
52777
|
+
shellVars[assignment.name] = expandedValue;
|
|
52778
|
+
}
|
|
52779
|
+
}
|
|
52780
|
+
return true;
|
|
52575
52781
|
}
|
|
52576
|
-
function
|
|
52577
|
-
|
|
52578
|
-
|
|
52782
|
+
function hasUnsafeRebaseOption(tokens, startIndex) {
|
|
52783
|
+
for (let i = startIndex;i < tokens.length; i += 1) {
|
|
52784
|
+
const token = tokens[i];
|
|
52785
|
+
if (!token) {
|
|
52786
|
+
continue;
|
|
52787
|
+
}
|
|
52788
|
+
const lower = token.toLowerCase();
|
|
52789
|
+
if (lower === "--exec" || lower.startsWith("--exec=") || lower === "-x" || lower.startsWith("-x") && lower.length > 2 || lower === "--interactive" || lower === "-i" || lower === "--edit-todo") {
|
|
52790
|
+
return true;
|
|
52791
|
+
}
|
|
52792
|
+
}
|
|
52793
|
+
return false;
|
|
52579
52794
|
}
|
|
52580
|
-
function
|
|
52795
|
+
function parseScopedGitInvocation(tokens, cwd2, allowedRoots, env3, shellVars) {
|
|
52796
|
+
let index = 1;
|
|
52797
|
+
let resolvedCwd = cwd2;
|
|
52798
|
+
while (index < tokens.length) {
|
|
52799
|
+
const token = tokens[index];
|
|
52800
|
+
if (!token) {
|
|
52801
|
+
index += 1;
|
|
52802
|
+
continue;
|
|
52803
|
+
}
|
|
52804
|
+
if (token === "-C") {
|
|
52805
|
+
const pathToken = tokens[index + 1];
|
|
52806
|
+
if (!pathToken) {
|
|
52807
|
+
return {
|
|
52808
|
+
subcommand: null,
|
|
52809
|
+
worktreeSubcommand: null,
|
|
52810
|
+
resolvedCwd,
|
|
52811
|
+
isSafe: false
|
|
52812
|
+
};
|
|
52813
|
+
}
|
|
52814
|
+
const nextCwd = normalizeScopePath(pathToken, resolvedCwd, env3, shellVars);
|
|
52815
|
+
if (!nextCwd || !isPathWithinRoots(nextCwd, allowedRoots)) {
|
|
52816
|
+
return {
|
|
52817
|
+
subcommand: null,
|
|
52818
|
+
worktreeSubcommand: null,
|
|
52819
|
+
resolvedCwd,
|
|
52820
|
+
isSafe: false
|
|
52821
|
+
};
|
|
52822
|
+
}
|
|
52823
|
+
resolvedCwd = nextCwd;
|
|
52824
|
+
index += 2;
|
|
52825
|
+
continue;
|
|
52826
|
+
}
|
|
52827
|
+
if (token === "-c") {
|
|
52828
|
+
const configToken = tokens[index + 1];
|
|
52829
|
+
if (!configToken) {
|
|
52830
|
+
return {
|
|
52831
|
+
subcommand: null,
|
|
52832
|
+
worktreeSubcommand: null,
|
|
52833
|
+
resolvedCwd,
|
|
52834
|
+
isSafe: false
|
|
52835
|
+
};
|
|
52836
|
+
}
|
|
52837
|
+
if (!/^http\.extraHeader=/.test(configToken)) {
|
|
52838
|
+
return {
|
|
52839
|
+
subcommand: null,
|
|
52840
|
+
worktreeSubcommand: null,
|
|
52841
|
+
resolvedCwd,
|
|
52842
|
+
isSafe: false
|
|
52843
|
+
};
|
|
52844
|
+
}
|
|
52845
|
+
index += 2;
|
|
52846
|
+
continue;
|
|
52847
|
+
}
|
|
52848
|
+
const subcommand = token;
|
|
52849
|
+
if (!SAFE_MEMORY_GIT_SUBCOMMANDS.has(subcommand)) {
|
|
52850
|
+
if (resolvedCwd && SAFE_MEMORY_COMMANDS.has("git")) {
|
|
52851
|
+
const rawSegment = tokens.join(" ");
|
|
52852
|
+
if (subcommand === "ls-tree" && !/\s-o\b/.test(rawSegment)) {
|
|
52853
|
+
return {
|
|
52854
|
+
subcommand,
|
|
52855
|
+
worktreeSubcommand: null,
|
|
52856
|
+
resolvedCwd,
|
|
52857
|
+
isSafe: true
|
|
52858
|
+
};
|
|
52859
|
+
}
|
|
52860
|
+
}
|
|
52861
|
+
return {
|
|
52862
|
+
subcommand,
|
|
52863
|
+
worktreeSubcommand: null,
|
|
52864
|
+
resolvedCwd,
|
|
52865
|
+
isSafe: false
|
|
52866
|
+
};
|
|
52867
|
+
}
|
|
52868
|
+
const worktreeSubcommand = subcommand === "worktree" ? tokens[index + 1] ?? null : null;
|
|
52869
|
+
if (subcommand === "worktree" && worktreeSubcommand && !new Set(["add", "remove", "list"]).has(worktreeSubcommand)) {
|
|
52870
|
+
return {
|
|
52871
|
+
subcommand,
|
|
52872
|
+
worktreeSubcommand,
|
|
52873
|
+
resolvedCwd,
|
|
52874
|
+
isSafe: false
|
|
52875
|
+
};
|
|
52876
|
+
}
|
|
52877
|
+
if (subcommand === "rebase" && hasUnsafeRebaseOption(tokens, index + 1)) {
|
|
52878
|
+
return {
|
|
52879
|
+
subcommand,
|
|
52880
|
+
worktreeSubcommand,
|
|
52881
|
+
resolvedCwd,
|
|
52882
|
+
isSafe: false
|
|
52883
|
+
};
|
|
52884
|
+
}
|
|
52885
|
+
return { subcommand, worktreeSubcommand, resolvedCwd, isSafe: true };
|
|
52886
|
+
}
|
|
52887
|
+
return {
|
|
52888
|
+
subcommand: null,
|
|
52889
|
+
worktreeSubcommand: null,
|
|
52890
|
+
resolvedCwd,
|
|
52891
|
+
isSafe: false
|
|
52892
|
+
};
|
|
52893
|
+
}
|
|
52894
|
+
function tokenLooksLikePath(token) {
|
|
52895
|
+
return token.includes("/") || token.includes("\\") || token === "." || token === ".." || token.startsWith("$") || token.startsWith("~") || token.startsWith("$HOME");
|
|
52896
|
+
}
|
|
52897
|
+
function validateScopedTokens(tokens, cwd2, allowedRoots, env3, shellVars) {
|
|
52898
|
+
return tokens.every((token, index) => {
|
|
52899
|
+
if (!tokenLooksLikePath(token)) {
|
|
52900
|
+
return true;
|
|
52901
|
+
}
|
|
52902
|
+
const previous = index > 0 ? tokens[index - 1] : null;
|
|
52903
|
+
if (previous && ["-m", "--message", "--author", "--format"].includes(previous)) {
|
|
52904
|
+
return true;
|
|
52905
|
+
}
|
|
52906
|
+
const resolved = normalizeScopePath(token, cwd2, env3, shellVars);
|
|
52907
|
+
return resolved ? isPathWithinRoots(resolved, allowedRoots) : false;
|
|
52908
|
+
});
|
|
52909
|
+
}
|
|
52910
|
+
function isAllowedMemorySegment(segment, cwd2, allowedRoots, env3, shellVars) {
|
|
52581
52911
|
const tokens = tokenize4(segment);
|
|
52582
|
-
if (tokens
|
|
52583
|
-
return
|
|
52912
|
+
if (tokens.length === 0) {
|
|
52913
|
+
return { nextCwd: cwd2, safe: false };
|
|
52584
52914
|
}
|
|
52585
|
-
|
|
52915
|
+
if (applyScopedAssignments(tokens, env3, shellVars)) {
|
|
52916
|
+
return { nextCwd: cwd2, safe: true };
|
|
52917
|
+
}
|
|
52918
|
+
const command = tokens[0];
|
|
52919
|
+
if (!command) {
|
|
52920
|
+
return { nextCwd: cwd2, safe: false };
|
|
52921
|
+
}
|
|
52922
|
+
if (command === "cd") {
|
|
52923
|
+
const target = tokens[1];
|
|
52924
|
+
if (!target) {
|
|
52925
|
+
return { nextCwd: cwd2, safe: false };
|
|
52926
|
+
}
|
|
52927
|
+
const resolved = normalizeScopePath(target, cwd2, env3, shellVars);
|
|
52928
|
+
return {
|
|
52929
|
+
nextCwd: resolved,
|
|
52930
|
+
safe: resolved ? isPathWithinRoots(resolved, allowedRoots) : false
|
|
52931
|
+
};
|
|
52932
|
+
}
|
|
52933
|
+
if (!SAFE_MEMORY_COMMANDS.has(command)) {
|
|
52934
|
+
return { nextCwd: cwd2, safe: false };
|
|
52935
|
+
}
|
|
52936
|
+
if (command === "git") {
|
|
52937
|
+
const parsed = parseScopedGitInvocation(tokens, cwd2, allowedRoots, env3, shellVars);
|
|
52938
|
+
if (!parsed.isSafe) {
|
|
52939
|
+
return { nextCwd: parsed.resolvedCwd, safe: false };
|
|
52940
|
+
}
|
|
52941
|
+
const effectiveCwd = parsed.resolvedCwd;
|
|
52942
|
+
if (!effectiveCwd || !isPathWithinRoots(effectiveCwd, allowedRoots)) {
|
|
52943
|
+
return { nextCwd: effectiveCwd, safe: false };
|
|
52944
|
+
}
|
|
52945
|
+
if (!validateScopedTokens(tokens, effectiveCwd, allowedRoots, env3, shellVars)) {
|
|
52946
|
+
return { nextCwd: effectiveCwd, safe: false };
|
|
52947
|
+
}
|
|
52948
|
+
return { nextCwd: effectiveCwd, safe: true };
|
|
52949
|
+
}
|
|
52950
|
+
if (tokens.some((token) => tokenLooksLikePath(token))) {
|
|
52951
|
+
if (!validateScopedTokens(tokens.slice(1), cwd2, allowedRoots, env3, shellVars)) {
|
|
52952
|
+
return { nextCwd: cwd2, safe: false };
|
|
52953
|
+
}
|
|
52954
|
+
return { nextCwd: cwd2, safe: true };
|
|
52955
|
+
}
|
|
52956
|
+
if (!cwd2 || !isPathWithinRoots(cwd2, allowedRoots)) {
|
|
52957
|
+
return { nextCwd: cwd2, safe: false };
|
|
52958
|
+
}
|
|
52959
|
+
if (command === "find" && /-delete|\s-exec\b/.test(segment)) {
|
|
52960
|
+
return { nextCwd: cwd2, safe: false };
|
|
52961
|
+
}
|
|
52962
|
+
if (command === "sort" && /\s-o\b/.test(segment)) {
|
|
52963
|
+
return { nextCwd: cwd2, safe: false };
|
|
52964
|
+
}
|
|
52965
|
+
if (!validateScopedTokens(tokens.slice(1), cwd2, allowedRoots, env3, shellVars)) {
|
|
52966
|
+
return { nextCwd: cwd2, safe: false };
|
|
52967
|
+
}
|
|
52968
|
+
return { nextCwd: cwd2, safe: true };
|
|
52586
52969
|
}
|
|
52587
|
-
function
|
|
52588
|
-
if (!command ||
|
|
52970
|
+
function isScopedMemoryShellCommand(command, allowedRoots, options = {}) {
|
|
52971
|
+
if (!command || allowedRoots.length === 0) {
|
|
52589
52972
|
return false;
|
|
52590
52973
|
}
|
|
52974
|
+
if (Array.isArray(command)) {
|
|
52975
|
+
if (command.length === 0) {
|
|
52976
|
+
return false;
|
|
52977
|
+
}
|
|
52978
|
+
const [executable, ...rest] = command;
|
|
52979
|
+
if (executable && isShellExecutor(executable)) {
|
|
52980
|
+
const nested = extractDashCArgument(rest);
|
|
52981
|
+
if (!nested) {
|
|
52982
|
+
return false;
|
|
52983
|
+
}
|
|
52984
|
+
return isScopedMemoryShellCommand(stripQuotes(nested), allowedRoots, options);
|
|
52985
|
+
}
|
|
52986
|
+
}
|
|
52591
52987
|
const commandStr = typeof command === "string" ? command : command.join(" ");
|
|
52592
52988
|
const trimmed = commandStr.trim();
|
|
52593
52989
|
if (!trimmed) {
|
|
52594
52990
|
return false;
|
|
52595
52991
|
}
|
|
52596
|
-
const
|
|
52597
|
-
|
|
52992
|
+
const segments = splitShellSegments(trimmed);
|
|
52993
|
+
if (!segments) {
|
|
52994
|
+
return false;
|
|
52995
|
+
}
|
|
52598
52996
|
if (segments.length === 0) {
|
|
52599
52997
|
return false;
|
|
52600
52998
|
}
|
|
52601
|
-
|
|
52999
|
+
const env3 = options.env ?? process.env;
|
|
53000
|
+
const shellVars = {};
|
|
53001
|
+
const initialCwd = options.workingDirectory ? normalizeScopePath(options.workingDirectory, null, env3, shellVars) : null;
|
|
53002
|
+
let cwd2 = initialCwd;
|
|
52602
53003
|
for (const segment of segments) {
|
|
52603
|
-
const
|
|
52604
|
-
|
|
52605
|
-
const cdTarget = extractCdTarget(part);
|
|
52606
|
-
if (cdTarget) {
|
|
52607
|
-
const resolved = cwd2 ? expandPath(resolve4(expandPath(cwd2), cdTarget)) : expandPath(cdTarget);
|
|
52608
|
-
if (!isUnderMemoryDir(resolved, prefixes)) {
|
|
52609
|
-
return false;
|
|
52610
|
-
}
|
|
52611
|
-
cwd2 = resolved;
|
|
52612
|
-
continue;
|
|
52613
|
-
}
|
|
52614
|
-
if (cwd2 && isUnderMemoryDir(cwd2, prefixes)) {
|
|
52615
|
-
const tokens2 = tokenize4(part);
|
|
52616
|
-
const currentCwd = cwd2;
|
|
52617
|
-
if (!currentCwd) {
|
|
52618
|
-
return false;
|
|
52619
|
-
}
|
|
52620
|
-
const hasExternalPath = tokens2.some((t) => {
|
|
52621
|
-
if (isAbsolutePathArg(t) || isHomeAnchoredPathArg(t)) {
|
|
52622
|
-
return !isUnderMemoryDir(t, prefixes);
|
|
52623
|
-
}
|
|
52624
|
-
if (hasAbsoluteOrTraversalPathArg(t)) {
|
|
52625
|
-
const resolved = expandPath(resolve4(expandPath(currentCwd), t));
|
|
52626
|
-
return !isUnderMemoryDir(resolved, prefixes);
|
|
52627
|
-
}
|
|
52628
|
-
return false;
|
|
52629
|
-
});
|
|
52630
|
-
if (hasExternalPath) {
|
|
52631
|
-
return false;
|
|
52632
|
-
}
|
|
52633
|
-
if (!MEMORY_DIR_APPROVE_ALL) {
|
|
52634
|
-
const cmd = tokens2[0];
|
|
52635
|
-
if (!cmd || !SAFE_MEMORY_DIR_COMMANDS.has(cmd)) {
|
|
52636
|
-
return false;
|
|
52637
|
-
}
|
|
52638
|
-
}
|
|
52639
|
-
continue;
|
|
52640
|
-
}
|
|
52641
|
-
const tokens = tokenize4(part);
|
|
52642
|
-
const hasMemoryPath = tokens.some((t) => t.includes(".letta/agents/") && t.includes("/memory") || t.includes(".letta/agents/") && t.includes("/memory-worktrees"));
|
|
52643
|
-
if (hasMemoryPath) {
|
|
52644
|
-
const agentPaths = tokens.filter((t) => t.includes(".letta/agents/"));
|
|
52645
|
-
if (agentPaths.every((p) => isUnderMemoryDir(p, prefixes))) {
|
|
52646
|
-
if (!MEMORY_DIR_APPROVE_ALL) {
|
|
52647
|
-
const cmd = tokens[0];
|
|
52648
|
-
if (!cmd || !SAFE_MEMORY_DIR_COMMANDS.has(cmd)) {
|
|
52649
|
-
return false;
|
|
52650
|
-
}
|
|
52651
|
-
}
|
|
52652
|
-
continue;
|
|
52653
|
-
}
|
|
52654
|
-
}
|
|
53004
|
+
const result = isAllowedMemorySegment(segment, cwd2, allowedRoots, env3, shellVars);
|
|
53005
|
+
if (!result.safe) {
|
|
52655
53006
|
return false;
|
|
52656
53007
|
}
|
|
53008
|
+
cwd2 = result.nextCwd;
|
|
52657
53009
|
}
|
|
52658
53010
|
return true;
|
|
52659
53011
|
}
|
|
52660
|
-
|
|
53012
|
+
function isMemoryDirCommand(command, agentId) {
|
|
53013
|
+
if (!command || !agentId) {
|
|
53014
|
+
return false;
|
|
53015
|
+
}
|
|
53016
|
+
return isScopedMemoryShellCommand(command, getAllowedMemoryPrefixes(agentId));
|
|
53017
|
+
}
|
|
53018
|
+
var ALWAYS_SAFE_COMMANDS, EXTERNAL_PATH_METADATA_COMMANDS, SAFE_GIT_SUBCOMMANDS, SAFE_MEMORY_GIT_SUBCOMMANDS, SAFE_MEMORY_COMMANDS, SAFE_LETTA_COMMANDS, SAFE_GH_COMMANDS;
|
|
52661
53019
|
var init_readOnlyShell = __esm(() => {
|
|
52662
|
-
|
|
52663
|
-
"git",
|
|
52664
|
-
"rm",
|
|
52665
|
-
"mv",
|
|
52666
|
-
"mkdir",
|
|
52667
|
-
"cp",
|
|
52668
|
-
"ls",
|
|
52669
|
-
"cat",
|
|
52670
|
-
"head",
|
|
52671
|
-
"tail",
|
|
52672
|
-
"tree",
|
|
52673
|
-
"find",
|
|
52674
|
-
"wc",
|
|
52675
|
-
"split",
|
|
52676
|
-
"echo",
|
|
52677
|
-
"sort",
|
|
52678
|
-
"cd"
|
|
52679
|
-
]);
|
|
53020
|
+
init_memoryScope();
|
|
52680
53021
|
ALWAYS_SAFE_COMMANDS = new Set([
|
|
52681
53022
|
"cat",
|
|
52682
53023
|
"head",
|
|
@@ -52749,6 +53090,42 @@ var init_readOnlyShell = __esm(() => {
|
|
|
52749
53090
|
"tag",
|
|
52750
53091
|
"remote"
|
|
52751
53092
|
]);
|
|
53093
|
+
SAFE_MEMORY_GIT_SUBCOMMANDS = new Set([
|
|
53094
|
+
"add",
|
|
53095
|
+
"commit",
|
|
53096
|
+
"push",
|
|
53097
|
+
"pull",
|
|
53098
|
+
"rebase",
|
|
53099
|
+
"status",
|
|
53100
|
+
"diff",
|
|
53101
|
+
"log",
|
|
53102
|
+
"show",
|
|
53103
|
+
"branch",
|
|
53104
|
+
"tag",
|
|
53105
|
+
"remote",
|
|
53106
|
+
"rm",
|
|
53107
|
+
"mv",
|
|
53108
|
+
"merge",
|
|
53109
|
+
"worktree"
|
|
53110
|
+
]);
|
|
53111
|
+
SAFE_MEMORY_COMMANDS = new Set([
|
|
53112
|
+
"git",
|
|
53113
|
+
"rm",
|
|
53114
|
+
"mv",
|
|
53115
|
+
"mkdir",
|
|
53116
|
+
"cp",
|
|
53117
|
+
"ls",
|
|
53118
|
+
"cat",
|
|
53119
|
+
"head",
|
|
53120
|
+
"tail",
|
|
53121
|
+
"find",
|
|
53122
|
+
"sort",
|
|
53123
|
+
"echo",
|
|
53124
|
+
"wc",
|
|
53125
|
+
"split",
|
|
53126
|
+
"cd",
|
|
53127
|
+
"sleep"
|
|
53128
|
+
]);
|
|
52752
53129
|
SAFE_LETTA_COMMANDS = {
|
|
52753
53130
|
memfs: new Set(["status", "help", "backups", "export"]),
|
|
52754
53131
|
agents: new Set(["list", "help"]),
|
|
@@ -52962,8 +53339,14 @@ var exports_mode = {};
|
|
|
52962
53339
|
__export(exports_mode, {
|
|
52963
53340
|
permissionMode: () => permissionMode
|
|
52964
53341
|
});
|
|
52965
|
-
import { homedir as
|
|
52966
|
-
import { isAbsolute as
|
|
53342
|
+
import { homedir as homedir13 } from "node:os";
|
|
53343
|
+
import { isAbsolute as isAbsolute3, join as join14, relative as relative3 } from "node:path";
|
|
53344
|
+
function everyResolvedTargetIsWithinRoots(candidatePaths, roots, workingDirectory) {
|
|
53345
|
+
return candidatePaths.length > 0 && candidatePaths.every((path4) => {
|
|
53346
|
+
const resolvedPath = resolveScopedTargetPath(path4, workingDirectory);
|
|
53347
|
+
return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
|
|
53348
|
+
});
|
|
53349
|
+
}
|
|
52967
53350
|
function getGlobalMode() {
|
|
52968
53351
|
const global2 = globalThis;
|
|
52969
53352
|
if (!global2[MODE_KEY]) {
|
|
@@ -52992,22 +53375,13 @@ function setGlobalModeBeforePlan(value) {
|
|
|
52992
53375
|
global2[MODE_BEFORE_PLAN_KEY] = value;
|
|
52993
53376
|
}
|
|
52994
53377
|
function resolvePlanTargetPath(targetPath, workingDirectory) {
|
|
52995
|
-
|
|
52996
|
-
if (!trimmedPath)
|
|
52997
|
-
return null;
|
|
52998
|
-
if (trimmedPath.startsWith("~/")) {
|
|
52999
|
-
return resolve5(homedir12(), trimmedPath.slice(2));
|
|
53000
|
-
}
|
|
53001
|
-
if (isAbsolute2(trimmedPath)) {
|
|
53002
|
-
return resolve5(trimmedPath);
|
|
53003
|
-
}
|
|
53004
|
-
return resolve5(workingDirectory, trimmedPath);
|
|
53378
|
+
return resolveScopedTargetPath(targetPath, workingDirectory);
|
|
53005
53379
|
}
|
|
53006
53380
|
function isPathInPlansDir(path4, plansDir) {
|
|
53007
53381
|
if (!path4.endsWith(".md"))
|
|
53008
53382
|
return false;
|
|
53009
53383
|
const rel = relative3(plansDir, path4);
|
|
53010
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
53384
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
|
|
53011
53385
|
}
|
|
53012
53386
|
function extractApplyPatchPaths(input) {
|
|
53013
53387
|
const paths = [];
|
|
@@ -53194,7 +53568,7 @@ class PermissionModeManager {
|
|
|
53194
53568
|
return "allow";
|
|
53195
53569
|
}
|
|
53196
53570
|
if (writeTools.includes(toolName)) {
|
|
53197
|
-
const plansDir = join14(
|
|
53571
|
+
const plansDir = join14(homedir13(), ".letta", "plans");
|
|
53198
53572
|
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
53199
53573
|
let candidatePaths = [];
|
|
53200
53574
|
if ((toolName === "ApplyPatch" || toolName === "apply_patch" || toolName === "memory_apply_patch") && toolArgs?.input) {
|
|
@@ -53245,7 +53619,7 @@ class PermissionModeManager {
|
|
|
53245
53619
|
}
|
|
53246
53620
|
const planWritePath = extractPlanFileWritePathFromShellCommand(command);
|
|
53247
53621
|
if (planWritePath) {
|
|
53248
|
-
const plansDir = join14(
|
|
53622
|
+
const plansDir = join14(homedir13(), ".letta", "plans");
|
|
53249
53623
|
const resolvedPath = resolvePlanTargetPath(planWritePath, workingDirectory);
|
|
53250
53624
|
if (resolvedPath && isPathInPlansDir(resolvedPath, plansDir)) {
|
|
53251
53625
|
return "allow";
|
|
@@ -53254,6 +53628,94 @@ class PermissionModeManager {
|
|
|
53254
53628
|
}
|
|
53255
53629
|
return "deny";
|
|
53256
53630
|
}
|
|
53631
|
+
case "memory": {
|
|
53632
|
+
const allowedMemoryRoots = resolveAllowedMemoryRoots().roots;
|
|
53633
|
+
const allowedReadOnlyTools = [
|
|
53634
|
+
"Read",
|
|
53635
|
+
"Glob",
|
|
53636
|
+
"Grep",
|
|
53637
|
+
"NotebookRead",
|
|
53638
|
+
"ViewImage",
|
|
53639
|
+
"view_image",
|
|
53640
|
+
"TaskOutput",
|
|
53641
|
+
"task_output",
|
|
53642
|
+
"Skill",
|
|
53643
|
+
"skill",
|
|
53644
|
+
"read_file",
|
|
53645
|
+
"list_dir",
|
|
53646
|
+
"grep_files",
|
|
53647
|
+
"ReadFile",
|
|
53648
|
+
"ListDir",
|
|
53649
|
+
"GrepFiles",
|
|
53650
|
+
"read_file_gemini",
|
|
53651
|
+
"glob_gemini",
|
|
53652
|
+
"list_directory",
|
|
53653
|
+
"search_file_content",
|
|
53654
|
+
"read_many_files",
|
|
53655
|
+
"ReadFileGemini",
|
|
53656
|
+
"GlobGemini",
|
|
53657
|
+
"ListDirectory",
|
|
53658
|
+
"SearchFileContent",
|
|
53659
|
+
"ReadManyFiles"
|
|
53660
|
+
];
|
|
53661
|
+
const writeTools = [
|
|
53662
|
+
"Write",
|
|
53663
|
+
"Edit",
|
|
53664
|
+
"MultiEdit",
|
|
53665
|
+
"NotebookEdit",
|
|
53666
|
+
"apply_patch",
|
|
53667
|
+
"ApplyPatch",
|
|
53668
|
+
"replace",
|
|
53669
|
+
"Replace",
|
|
53670
|
+
"write_file",
|
|
53671
|
+
"WriteFile",
|
|
53672
|
+
"write_file_gemini",
|
|
53673
|
+
"WriteFileGemini"
|
|
53674
|
+
];
|
|
53675
|
+
const shellTools = [
|
|
53676
|
+
"Bash",
|
|
53677
|
+
"shell",
|
|
53678
|
+
"Shell",
|
|
53679
|
+
"shell_command",
|
|
53680
|
+
"ShellCommand",
|
|
53681
|
+
"run_shell_command",
|
|
53682
|
+
"RunShellCommand",
|
|
53683
|
+
"run_shell_command_gemini",
|
|
53684
|
+
"RunShellCommandGemini"
|
|
53685
|
+
];
|
|
53686
|
+
if (allowedReadOnlyTools.includes(toolName)) {
|
|
53687
|
+
return "allow";
|
|
53688
|
+
}
|
|
53689
|
+
if (toolName === "memory_apply_patch") {
|
|
53690
|
+
return allowedMemoryRoots.length > 0 ? "allow" : "deny";
|
|
53691
|
+
}
|
|
53692
|
+
if (writeTools.includes(toolName)) {
|
|
53693
|
+
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
53694
|
+
let candidatePaths = [];
|
|
53695
|
+
if ((toolName === "ApplyPatch" || toolName === "apply_patch") && toolArgs?.input) {
|
|
53696
|
+
candidatePaths = extractApplyPatchPaths(toolArgs.input);
|
|
53697
|
+
} else if (typeof targetPath === "string") {
|
|
53698
|
+
candidatePaths = [targetPath];
|
|
53699
|
+
}
|
|
53700
|
+
if (allowedMemoryRoots.length > 0 && everyResolvedTargetIsWithinRoots(candidatePaths, allowedMemoryRoots, workingDirectory)) {
|
|
53701
|
+
return "allow";
|
|
53702
|
+
}
|
|
53703
|
+
return "deny";
|
|
53704
|
+
}
|
|
53705
|
+
if (shellTools.includes(toolName)) {
|
|
53706
|
+
const command = toolArgs?.command;
|
|
53707
|
+
if (command && isReadOnlyShellCommand(command, { allowExternalPaths: true })) {
|
|
53708
|
+
return "allow";
|
|
53709
|
+
}
|
|
53710
|
+
if (command && allowedMemoryRoots.length > 0 && isScopedMemoryShellCommand(command, allowedMemoryRoots, {
|
|
53711
|
+
workingDirectory
|
|
53712
|
+
})) {
|
|
53713
|
+
return "allow";
|
|
53714
|
+
}
|
|
53715
|
+
return "deny";
|
|
53716
|
+
}
|
|
53717
|
+
return "deny";
|
|
53718
|
+
}
|
|
53257
53719
|
case "default":
|
|
53258
53720
|
return null;
|
|
53259
53721
|
default:
|
|
@@ -53268,6 +53730,7 @@ class PermissionModeManager {
|
|
|
53268
53730
|
}
|
|
53269
53731
|
var MODE_KEY, PLAN_FILE_KEY, MODE_BEFORE_PLAN_KEY, permissionMode;
|
|
53270
53732
|
var init_mode = __esm(() => {
|
|
53733
|
+
init_memoryScope();
|
|
53271
53734
|
init_readOnlyShell();
|
|
53272
53735
|
init_shell_command_normalization();
|
|
53273
53736
|
MODE_KEY = Symbol.for("@letta/permissionMode");
|
|
@@ -57340,8 +57803,8 @@ import {
|
|
|
57340
57803
|
unlink,
|
|
57341
57804
|
writeFile as writeFile2
|
|
57342
57805
|
} from "node:fs/promises";
|
|
57343
|
-
import { homedir as
|
|
57344
|
-
import { dirname as
|
|
57806
|
+
import { homedir as homedir15 } from "node:os";
|
|
57807
|
+
import { dirname as dirname7, isAbsolute as isAbsolute9, relative as relative5, resolve as resolve12 } from "node:path";
|
|
57345
57808
|
import { promisify as promisify10 } from "node:util";
|
|
57346
57809
|
async function getAgentIdentity() {
|
|
57347
57810
|
const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
|
|
@@ -57390,7 +57853,7 @@ async function memory(args) {
|
|
|
57390
57853
|
const rendered = renderMemoryFile({
|
|
57391
57854
|
description
|
|
57392
57855
|
}, body);
|
|
57393
|
-
await mkdir2(
|
|
57856
|
+
await mkdir2(dirname7(filePath), { recursive: true });
|
|
57394
57857
|
await writeFile2(filePath, rendered, "utf8");
|
|
57395
57858
|
affectedPaths = [relPath];
|
|
57396
57859
|
} else if (command === "str_replace") {
|
|
@@ -57459,7 +57922,7 @@ async function memory(args) {
|
|
|
57459
57922
|
throw new Error(`memory rename: destination already exists at ${newPathArg}`);
|
|
57460
57923
|
}
|
|
57461
57924
|
await loadEditableMemoryFile(oldFilePath, oldPathArg);
|
|
57462
|
-
await mkdir2(
|
|
57925
|
+
await mkdir2(dirname7(newFilePath), { recursive: true });
|
|
57463
57926
|
await rename(oldFilePath, newFilePath);
|
|
57464
57927
|
affectedPaths = [oldRelPath, newRelPath];
|
|
57465
57928
|
} else if (command === "update_description") {
|
|
@@ -57507,7 +57970,7 @@ function resolveMemoryDir() {
|
|
|
57507
57970
|
})();
|
|
57508
57971
|
const agentId = contextAgentId || (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
|
|
57509
57972
|
if (agentId && agentId.trim().length > 0) {
|
|
57510
|
-
return resolve12(
|
|
57973
|
+
return resolve12(homedir15(), ".letta", "agents", agentId, "memory");
|
|
57511
57974
|
}
|
|
57512
57975
|
throw new Error("memory: unable to resolve memory directory. Ensure MEMORY_DIR (or AGENT_ID) is available.");
|
|
57513
57976
|
}
|
|
@@ -57528,10 +57991,10 @@ function normalizeMemoryLabel(memoryDir, inputPath, fieldName) {
|
|
|
57528
57991
|
throw new Error(`memory: '${fieldName}' must be a memory-relative file path, not a home-relative filesystem path`);
|
|
57529
57992
|
}
|
|
57530
57993
|
const isWindowsAbsolute = /^[a-zA-Z]:[\\/]/.test(raw);
|
|
57531
|
-
if (
|
|
57994
|
+
if (isAbsolute9(raw) || isWindowsAbsolute) {
|
|
57532
57995
|
const absolutePath = resolve12(raw);
|
|
57533
57996
|
const relToMemory = relative5(memoryDir, absolutePath);
|
|
57534
|
-
if (relToMemory && !relToMemory.startsWith("..") && !
|
|
57997
|
+
if (relToMemory && !relToMemory.startsWith("..") && !isAbsolute9(relToMemory)) {
|
|
57535
57998
|
return normalizeRelativeMemoryLabel(relToMemory, fieldName);
|
|
57536
57999
|
}
|
|
57537
58000
|
throw new Error(memoryPrefixError(memoryDir));
|
|
@@ -57577,14 +58040,14 @@ function resolveMemoryFilePath(memoryDir, label) {
|
|
|
57577
58040
|
function resolveMemoryPath(memoryDir, path11) {
|
|
57578
58041
|
const absolute = resolve12(memoryDir, path11);
|
|
57579
58042
|
const rel = relative5(memoryDir, absolute);
|
|
57580
|
-
if (rel.startsWith("..") ||
|
|
58043
|
+
if (rel.startsWith("..") || isAbsolute9(rel)) {
|
|
57581
58044
|
throw new Error("memory: resolved path escapes memory directory");
|
|
57582
58045
|
}
|
|
57583
58046
|
return absolute;
|
|
57584
58047
|
}
|
|
57585
58048
|
function toRepoRelative(memoryDir, absolutePath) {
|
|
57586
58049
|
const rel = relative5(memoryDir, absolutePath);
|
|
57587
|
-
if (!rel || rel.startsWith("..") ||
|
|
58050
|
+
if (!rel || rel.startsWith("..") || isAbsolute9(rel)) {
|
|
57588
58051
|
throw new Error("memory: path is outside memory repository");
|
|
57589
58052
|
}
|
|
57590
58053
|
return rel.replace(/\\/g, "/");
|
|
@@ -57755,8 +58218,8 @@ import {
|
|
|
57755
58218
|
unlink as unlink2,
|
|
57756
58219
|
writeFile as writeFile3
|
|
57757
58220
|
} from "node:fs/promises";
|
|
57758
|
-
import { homedir as
|
|
57759
|
-
import { dirname as
|
|
58221
|
+
import { homedir as homedir16 } from "node:os";
|
|
58222
|
+
import { dirname as dirname8, isAbsolute as isAbsolute10, relative as relative6, resolve as resolve13 } from "node:path";
|
|
57760
58223
|
import { promisify as promisify11 } from "node:util";
|
|
57761
58224
|
async function getAgentIdentity2() {
|
|
57762
58225
|
const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
|
|
@@ -57869,7 +58332,7 @@ async function memory_apply_patch(args) {
|
|
|
57869
58332
|
}
|
|
57870
58333
|
}
|
|
57871
58334
|
for (const [absPath, content] of pendingWrites.entries()) {
|
|
57872
|
-
await mkdir3(
|
|
58335
|
+
await mkdir3(dirname8(absPath), { recursive: true });
|
|
57873
58336
|
await writeFile3(absPath, content, "utf8");
|
|
57874
58337
|
}
|
|
57875
58338
|
for (const absPath of pendingDeletes) {
|
|
@@ -58043,7 +58506,7 @@ function resolveMemoryDir2() {
|
|
|
58043
58506
|
})();
|
|
58044
58507
|
const agentId = contextAgentId || (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
|
|
58045
58508
|
if (agentId && agentId.trim().length > 0) {
|
|
58046
|
-
return resolve13(
|
|
58509
|
+
return resolve13(homedir16(), ".letta", "agents", agentId, "memory");
|
|
58047
58510
|
}
|
|
58048
58511
|
throw new Error("memory_apply_patch: unable to resolve memory directory. Ensure MEMORY_DIR (or AGENT_ID) is available.");
|
|
58049
58512
|
}
|
|
@@ -58064,10 +58527,10 @@ function normalizeMemoryLabel2(memoryDir, inputPath, fieldName) {
|
|
|
58064
58527
|
throw new Error(`memory_apply_patch: '${fieldName}' must be a memory-relative file path, not a home-relative filesystem path`);
|
|
58065
58528
|
}
|
|
58066
58529
|
const isWindowsAbsolute = /^[a-zA-Z]:[\\/]/.test(raw);
|
|
58067
|
-
if (
|
|
58530
|
+
if (isAbsolute10(raw) || isWindowsAbsolute) {
|
|
58068
58531
|
const absolutePath = resolve13(raw);
|
|
58069
58532
|
const relToMemory = relative6(memoryDir, absolutePath);
|
|
58070
|
-
if (relToMemory && !relToMemory.startsWith("..") && !
|
|
58533
|
+
if (relToMemory && !relToMemory.startsWith("..") && !isAbsolute10(relToMemory)) {
|
|
58071
58534
|
return normalizeRelativeMemoryLabel2(relToMemory, fieldName);
|
|
58072
58535
|
}
|
|
58073
58536
|
throw new Error(memoryPrefixError2(memoryDir));
|
|
@@ -58109,7 +58572,7 @@ function memoryPrefixError2(memoryDir) {
|
|
|
58109
58572
|
function resolveMemoryPath2(memoryDir, path11) {
|
|
58110
58573
|
const absolute = resolve13(memoryDir, path11);
|
|
58111
58574
|
const rel = relative6(memoryDir, absolute);
|
|
58112
|
-
if (rel.startsWith("..") ||
|
|
58575
|
+
if (rel.startsWith("..") || isAbsolute10(rel)) {
|
|
58113
58576
|
throw new Error("memory_apply_patch: resolved path escapes memory directory");
|
|
58114
58577
|
}
|
|
58115
58578
|
return absolute;
|
|
@@ -58119,7 +58582,7 @@ function resolveMemoryFilePath2(memoryDir, label) {
|
|
|
58119
58582
|
}
|
|
58120
58583
|
function toRepoRelative2(memoryDir, absolutePath) {
|
|
58121
58584
|
const rel = relative6(memoryDir, absolutePath);
|
|
58122
|
-
if (!rel || rel.startsWith("..") ||
|
|
58585
|
+
if (!rel || rel.startsWith("..") || isAbsolute10(rel)) {
|
|
58123
58586
|
throw new Error("memory_apply_patch: path is outside memory repository");
|
|
58124
58587
|
}
|
|
58125
58588
|
return rel.replace(/\\/g, "/");
|
|
@@ -64948,7 +65411,7 @@ async function runProcess(context3) {
|
|
|
64948
65411
|
}
|
|
64949
65412
|
async function shell(args) {
|
|
64950
65413
|
validateRequiredParams(args, ["command"], "shell");
|
|
64951
|
-
const { command, workdir, timeout_ms, signal, onOutput } = args;
|
|
65414
|
+
const { command, workdir, timeout_ms, env_overrides, signal, onOutput } = args;
|
|
64952
65415
|
if (!Array.isArray(command) || command.length === 0) {
|
|
64953
65416
|
throw new Error("command must be a non-empty array of strings");
|
|
64954
65417
|
}
|
|
@@ -64959,7 +65422,10 @@ async function shell(args) {
|
|
|
64959
65422
|
const context3 = {
|
|
64960
65423
|
command,
|
|
64961
65424
|
cwd: cwd2,
|
|
64962
|
-
env:
|
|
65425
|
+
env: {
|
|
65426
|
+
...getShellEnv(),
|
|
65427
|
+
...env_overrides ?? {}
|
|
65428
|
+
},
|
|
64963
65429
|
timeout,
|
|
64964
65430
|
signal,
|
|
64965
65431
|
onOutput
|
|
@@ -65080,6 +65546,7 @@ async function shell_command(args) {
|
|
|
65080
65546
|
signal,
|
|
65081
65547
|
onOutput
|
|
65082
65548
|
} = args;
|
|
65549
|
+
const envOverrides = getMemoryGitIdentityEnvOverrides(command, workdir);
|
|
65083
65550
|
const launchers = buildShellLaunchers(command, { login });
|
|
65084
65551
|
if (launchers.length === 0) {
|
|
65085
65552
|
throw new Error("Command must be a non-empty string");
|
|
@@ -65091,6 +65558,7 @@ async function shell_command(args) {
|
|
|
65091
65558
|
return await shell({
|
|
65092
65559
|
command: launcher,
|
|
65093
65560
|
workdir,
|
|
65561
|
+
env_overrides: envOverrides,
|
|
65094
65562
|
timeout_ms,
|
|
65095
65563
|
justification,
|
|
65096
65564
|
signal,
|
|
@@ -65109,7 +65577,96 @@ async function shell_command(args) {
|
|
|
65109
65577
|
const reason = lastError?.message || "Shell unavailable";
|
|
65110
65578
|
throw new Error(suffix ? `${reason} (tried: ${suffix})` : reason);
|
|
65111
65579
|
}
|
|
65580
|
+
function getMemoryGitIdentityEnvOverrides(command, workdir) {
|
|
65581
|
+
const agentId = getCurrentAgentIdOrEnv();
|
|
65582
|
+
if (!agentId) {
|
|
65583
|
+
return;
|
|
65584
|
+
}
|
|
65585
|
+
if (!containsGitCommitInvocation(command)) {
|
|
65586
|
+
return;
|
|
65587
|
+
}
|
|
65588
|
+
const scopedToMemoryDir = isMemoryDirCommand(command, agentId) || (workdir ? isMemoryDirCommand(`cd ${shellQuote(workdir)} && ${command}`, agentId) : false);
|
|
65589
|
+
if (!scopedToMemoryDir) {
|
|
65590
|
+
return;
|
|
65591
|
+
}
|
|
65592
|
+
const agentName = (process.env.AGENT_NAME || "").trim() || agentId;
|
|
65593
|
+
const agentEmail = `${agentId}@letta.com`;
|
|
65594
|
+
return {
|
|
65595
|
+
GIT_AUTHOR_NAME: agentName,
|
|
65596
|
+
GIT_AUTHOR_EMAIL: agentEmail,
|
|
65597
|
+
GIT_COMMITTER_NAME: agentName,
|
|
65598
|
+
GIT_COMMITTER_EMAIL: agentEmail
|
|
65599
|
+
};
|
|
65600
|
+
}
|
|
65601
|
+
function getCurrentAgentIdOrEnv() {
|
|
65602
|
+
const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
|
|
65603
|
+
if (envAgentId) {
|
|
65604
|
+
return envAgentId;
|
|
65605
|
+
}
|
|
65606
|
+
try {
|
|
65607
|
+
const agentId = getCurrentAgentId().trim();
|
|
65608
|
+
if (agentId) {
|
|
65609
|
+
return agentId;
|
|
65610
|
+
}
|
|
65611
|
+
} catch {}
|
|
65612
|
+
return "";
|
|
65613
|
+
}
|
|
65614
|
+
function containsGitCommitInvocation(command) {
|
|
65615
|
+
const segments = command.split(/&&|\|\||;|\|/).map((segment) => segment.trim()).filter(Boolean);
|
|
65616
|
+
for (const segment of segments) {
|
|
65617
|
+
const tokens = tokenizeSegment(segment);
|
|
65618
|
+
if (tokens.length === 0) {
|
|
65619
|
+
continue;
|
|
65620
|
+
}
|
|
65621
|
+
let index = 0;
|
|
65622
|
+
while (index < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=.*/.test(tokens[index] ?? "")) {
|
|
65623
|
+
index += 1;
|
|
65624
|
+
}
|
|
65625
|
+
if (tokens[index] !== "git") {
|
|
65626
|
+
continue;
|
|
65627
|
+
}
|
|
65628
|
+
index += 1;
|
|
65629
|
+
while (index < tokens.length) {
|
|
65630
|
+
const token = tokens[index];
|
|
65631
|
+
if (!token) {
|
|
65632
|
+
index += 1;
|
|
65633
|
+
continue;
|
|
65634
|
+
}
|
|
65635
|
+
if (token === "-c" || token === "-C") {
|
|
65636
|
+
index += 2;
|
|
65637
|
+
continue;
|
|
65638
|
+
}
|
|
65639
|
+
if (token.startsWith("-")) {
|
|
65640
|
+
index += 1;
|
|
65641
|
+
continue;
|
|
65642
|
+
}
|
|
65643
|
+
if (token === "commit") {
|
|
65644
|
+
return true;
|
|
65645
|
+
}
|
|
65646
|
+
break;
|
|
65647
|
+
}
|
|
65648
|
+
}
|
|
65649
|
+
return false;
|
|
65650
|
+
}
|
|
65651
|
+
function tokenizeSegment(segment) {
|
|
65652
|
+
const matches = segment.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
|
|
65653
|
+
if (!matches) {
|
|
65654
|
+
return [];
|
|
65655
|
+
}
|
|
65656
|
+
return matches.map(stripWrappingQuotes);
|
|
65657
|
+
}
|
|
65658
|
+
function stripWrappingQuotes(token) {
|
|
65659
|
+
if (token.startsWith('"') && token.endsWith('"') || token.startsWith("'") && token.endsWith("'")) {
|
|
65660
|
+
return token.slice(1, -1);
|
|
65661
|
+
}
|
|
65662
|
+
return token;
|
|
65663
|
+
}
|
|
65664
|
+
function shellQuote(value) {
|
|
65665
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
65666
|
+
}
|
|
65112
65667
|
var init_ShellCommand2 = __esm(async () => {
|
|
65668
|
+
init_context();
|
|
65669
|
+
init_readOnlyShell();
|
|
65113
65670
|
init_shellRunner();
|
|
65114
65671
|
await init_Shell2();
|
|
65115
65672
|
});
|
|
@@ -65158,10 +65715,10 @@ __export(exports_skills, {
|
|
|
65158
65715
|
});
|
|
65159
65716
|
import { existsSync as existsSync17 } from "node:fs";
|
|
65160
65717
|
import { readdir as readdir4, readFile as readFile5, realpath as realpath2, stat as stat4 } from "node:fs/promises";
|
|
65161
|
-
import { dirname as
|
|
65718
|
+
import { dirname as dirname9, join as join19 } from "node:path";
|
|
65162
65719
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
65163
65720
|
function getBundledSkillsPath() {
|
|
65164
|
-
const thisDir =
|
|
65721
|
+
const thisDir = dirname9(fileURLToPath7(import.meta.url));
|
|
65165
65722
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
65166
65723
|
return join19(thisDir, "../skills/builtin");
|
|
65167
65724
|
}
|
|
@@ -65363,10 +65920,21 @@ var init_skillContentRegistry = __esm(() => {
|
|
|
65363
65920
|
// src/tools/impl/Skill.ts
|
|
65364
65921
|
import { readdirSync as readdirSync7 } from "node:fs";
|
|
65365
65922
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
65366
|
-
import { dirname as
|
|
65923
|
+
import { dirname as dirname10, join as join20 } from "node:path";
|
|
65924
|
+
function getMemorySkillsDirs(agentId) {
|
|
65925
|
+
const dirs = new Set;
|
|
65926
|
+
const memoryDir = process.env.MEMORY_DIR || process.env.LETTA_MEMORY_DIR;
|
|
65927
|
+
if (memoryDir && memoryDir.trim().length > 0) {
|
|
65928
|
+
dirs.add(join20(memoryDir.trim(), "skills"));
|
|
65929
|
+
}
|
|
65930
|
+
if (agentId) {
|
|
65931
|
+
dirs.add(join20(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory", "skills"));
|
|
65932
|
+
}
|
|
65933
|
+
return Array.from(dirs);
|
|
65934
|
+
}
|
|
65367
65935
|
function hasAdditionalFiles(skillMdPath) {
|
|
65368
65936
|
try {
|
|
65369
|
-
const skillDir =
|
|
65937
|
+
const skillDir = dirname10(skillMdPath);
|
|
65370
65938
|
const entries = readdirSync7(skillDir);
|
|
65371
65939
|
return entries.some((e) => e.toUpperCase() !== "SKILL.MD");
|
|
65372
65940
|
} catch {
|
|
@@ -65386,6 +65954,13 @@ async function readSkillContent(skillId, skillsDir, agentId) {
|
|
|
65386
65954
|
return { content, path: agentSkillPath };
|
|
65387
65955
|
} catch {}
|
|
65388
65956
|
}
|
|
65957
|
+
for (const memorySkillsDir of getMemorySkillsDirs(agentId)) {
|
|
65958
|
+
const memorySkillPath = join20(memorySkillsDir, skillId, "SKILL.md");
|
|
65959
|
+
try {
|
|
65960
|
+
const content = await readFile6(memorySkillPath, "utf-8");
|
|
65961
|
+
return { content, path: memorySkillPath };
|
|
65962
|
+
} catch {}
|
|
65963
|
+
}
|
|
65389
65964
|
const globalSkillPath = join20(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
|
|
65390
65965
|
try {
|
|
65391
65966
|
const content = await readFile6(globalSkillPath, "utf-8");
|
|
@@ -65425,7 +66000,7 @@ async function skill(args) {
|
|
|
65425
66000
|
const agentId = getCurrentAgentId();
|
|
65426
66001
|
const skillsDir = await getResolvedSkillsDir();
|
|
65427
66002
|
const { content: skillContent, path: skillPath } = await readSkillContent(skillName, skillsDir, agentId);
|
|
65428
|
-
const skillDir =
|
|
66003
|
+
const skillDir = dirname10(skillPath);
|
|
65429
66004
|
const hasExtras = hasAdditionalFiles(skillPath);
|
|
65430
66005
|
const processedContent = hasExtras ? skillContent.replace(/<SKILL_DIR>/g, skillDir) : skillContent;
|
|
65431
66006
|
const dirHeader = hasExtras ? `# Skill Directory: ${skillDir}
|
|
@@ -66009,15 +66584,32 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
|
|
|
66009
66584
|
const inheritedApiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
66010
66585
|
const inheritedBaseUrl = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL;
|
|
66011
66586
|
const subagentWorkingDirectory = resolveSubagentWorkingDirectory();
|
|
66587
|
+
const inheritedMemoryRoots = resolveAllowedMemoryRoots();
|
|
66588
|
+
const childEnv = {
|
|
66589
|
+
...process.env,
|
|
66590
|
+
...inheritedApiKey && { LETTA_API_KEY: inheritedApiKey },
|
|
66591
|
+
...inheritedBaseUrl && { LETTA_BASE_URL: inheritedBaseUrl },
|
|
66592
|
+
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
66593
|
+
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
66594
|
+
};
|
|
66595
|
+
if (config.permissionMode === "memory") {
|
|
66596
|
+
if (inheritedMemoryRoots.primaryRoot) {
|
|
66597
|
+
childEnv.MEMORY_DIR = inheritedMemoryRoots.primaryRoot;
|
|
66598
|
+
childEnv.LETTA_MEMORY_DIR = inheritedMemoryRoots.primaryRoot;
|
|
66599
|
+
} else {
|
|
66600
|
+
delete childEnv.MEMORY_DIR;
|
|
66601
|
+
delete childEnv.LETTA_MEMORY_DIR;
|
|
66602
|
+
}
|
|
66603
|
+
const parentMemoryDir = process.env.MEMORY_DIR || process.env.LETTA_MEMORY_DIR;
|
|
66604
|
+
if (parentMemoryDir && parentMemoryDir.trim().length > 0) {
|
|
66605
|
+
childEnv.PARENT_MEMORY_DIR = parentMemoryDir;
|
|
66606
|
+
} else {
|
|
66607
|
+
delete childEnv.PARENT_MEMORY_DIR;
|
|
66608
|
+
}
|
|
66609
|
+
}
|
|
66012
66610
|
const proc2 = spawn4(launcher.command, launcher.args, {
|
|
66013
66611
|
cwd: subagentWorkingDirectory,
|
|
66014
|
-
env:
|
|
66015
|
-
...process.env,
|
|
66016
|
-
...inheritedApiKey && { LETTA_API_KEY: inheritedApiKey },
|
|
66017
|
-
...inheritedBaseUrl && { LETTA_BASE_URL: inheritedBaseUrl },
|
|
66018
|
-
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
66019
|
-
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
66020
|
-
}
|
|
66612
|
+
env: childEnv
|
|
66021
66613
|
});
|
|
66022
66614
|
proc2.once("spawn", () => {
|
|
66023
66615
|
updateSubagent(subagentId, { status: "running" });
|
|
@@ -66196,6 +66788,7 @@ var init_manager2 = __esm(async () => {
|
|
|
66196
66788
|
init_subagentState();
|
|
66197
66789
|
init_constants();
|
|
66198
66790
|
init_cli();
|
|
66791
|
+
init_memoryScope();
|
|
66199
66792
|
init_mode();
|
|
66200
66793
|
init_session();
|
|
66201
66794
|
init_context();
|
|
@@ -69706,8 +70299,8 @@ function matchesFilePattern(query, pattern, workingDirectory, options) {
|
|
|
69706
70299
|
globPattern = globPattern.slice(2);
|
|
69707
70300
|
}
|
|
69708
70301
|
if (globPattern.startsWith("~/")) {
|
|
69709
|
-
const
|
|
69710
|
-
globPattern = globPattern.replace(/^~/,
|
|
70302
|
+
const homedir17 = __require("node:os").homedir();
|
|
70303
|
+
globPattern = globPattern.replace(/^~/, homedir17);
|
|
69711
70304
|
}
|
|
69712
70305
|
globPattern = normalizeAbsolutePattern(globPattern, workingDirectory);
|
|
69713
70306
|
const windowsContext = isWindowsContext(workingDirectory);
|
|
@@ -70220,7 +70813,7 @@ function getDefaultDecision(toolName, toolArgs) {
|
|
|
70220
70813
|
}
|
|
70221
70814
|
if (toolName === "Task" || toolName === "task") {
|
|
70222
70815
|
const subagentType = typeof toolArgs?.subagent_type === "string" ? toolArgs.subagent_type : "";
|
|
70223
|
-
if (
|
|
70816
|
+
if (SAFE_AUTO_APPROVE_SUBAGENT_TYPES.has(subagentType)) {
|
|
70224
70817
|
return "allow";
|
|
70225
70818
|
}
|
|
70226
70819
|
return "ask";
|
|
@@ -70251,7 +70844,7 @@ async function checkPermissionWithHooks(toolName, toolArgs, permissions, working
|
|
|
70251
70844
|
}
|
|
70252
70845
|
return result;
|
|
70253
70846
|
}
|
|
70254
|
-
var WORKING_DIRECTORY_TOOLS_V2, WORKING_DIRECTORY_TOOLS_V1, READ_ONLY_SHELL_TOOLS, FILE_TOOLS_V2, FILE_TOOLS_V1,
|
|
70847
|
+
var WORKING_DIRECTORY_TOOLS_V2, WORKING_DIRECTORY_TOOLS_V1, READ_ONLY_SHELL_TOOLS, FILE_TOOLS_V2, FILE_TOOLS_V1, SAFE_AUTO_APPROVE_SUBAGENT_TYPES;
|
|
70255
70848
|
var init_checker = __esm(async () => {
|
|
70256
70849
|
init_context();
|
|
70257
70850
|
init_canonical();
|
|
@@ -70318,7 +70911,7 @@ var init_checker = __esm(async () => {
|
|
|
70318
70911
|
"read_many_files",
|
|
70319
70912
|
"ReadManyFiles"
|
|
70320
70913
|
];
|
|
70321
|
-
|
|
70914
|
+
SAFE_AUTO_APPROVE_SUBAGENT_TYPES = new Set([
|
|
70322
70915
|
"explore",
|
|
70323
70916
|
"Explore",
|
|
70324
70917
|
"recall",
|
|
@@ -70336,10 +70929,10 @@ __export(exports_loader, {
|
|
|
70336
70929
|
loadPermissions: () => loadPermissions,
|
|
70337
70930
|
getUserSettingsPaths: () => getUserSettingsPaths
|
|
70338
70931
|
});
|
|
70339
|
-
import { homedir as
|
|
70932
|
+
import { homedir as homedir17 } from "node:os";
|
|
70340
70933
|
import { join as join21 } from "node:path";
|
|
70341
70934
|
function getUserSettingsPaths(options = {}) {
|
|
70342
|
-
const homeDir = options.homeDir ||
|
|
70935
|
+
const homeDir = options.homeDir || homedir17();
|
|
70343
70936
|
const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join21(homeDir, ".config");
|
|
70344
70937
|
return {
|
|
70345
70938
|
canonical: join21(homeDir, ".letta", "settings.json"),
|
|
@@ -70461,8 +71054,8 @@ var exports_analyzer = {};
|
|
|
70461
71054
|
__export(exports_analyzer, {
|
|
70462
71055
|
analyzeApprovalContext: () => analyzeApprovalContext
|
|
70463
71056
|
});
|
|
70464
|
-
import { homedir as
|
|
70465
|
-
import { dirname as
|
|
71057
|
+
import { homedir as homedir18 } from "node:os";
|
|
71058
|
+
import { dirname as dirname12, relative as relative8, resolve as resolve22, win32 as win322 } from "node:path";
|
|
70466
71059
|
function normalizeOsPath(path20) {
|
|
70467
71060
|
return path20.replace(/\\/g, "/");
|
|
70468
71061
|
}
|
|
@@ -70488,7 +71081,7 @@ function isPathWithinDirectory(path20, directory) {
|
|
|
70488
71081
|
return !relativePath.startsWith("../") && relativePath !== ".." && !relativePath.startsWith("/") && !/^[a-zA-Z]:\//.test(relativePath);
|
|
70489
71082
|
}
|
|
70490
71083
|
function dirnameForContext(path20) {
|
|
70491
|
-
return isWindowsPath(path20) ? win322.dirname(path20) :
|
|
71084
|
+
return isWindowsPath(path20) ? win322.dirname(path20) : dirname12(path20);
|
|
70492
71085
|
}
|
|
70493
71086
|
function formatAbsoluteRulePath(path20) {
|
|
70494
71087
|
const normalized = normalizeOsPath(path20).replace(/\/+$/, "");
|
|
@@ -70498,7 +71091,7 @@ function formatAbsoluteRulePath(path20) {
|
|
|
70498
71091
|
return `//${normalized.replace(/^\/+/, "")}`;
|
|
70499
71092
|
}
|
|
70500
71093
|
function formatDisplayPath(path20) {
|
|
70501
|
-
return normalizeOsPath(path20).replace(normalizeOsPath(
|
|
71094
|
+
return normalizeOsPath(path20).replace(normalizeOsPath(homedir18()), "~");
|
|
70502
71095
|
}
|
|
70503
71096
|
function analyzeApprovalContext(toolName, toolArgs, workingDirectory) {
|
|
70504
71097
|
const canonicalTool = canonicalToolName(toolName);
|
|
@@ -70549,7 +71142,7 @@ function analyzeReadApproval(filePath, workingDir) {
|
|
|
70549
71142
|
};
|
|
70550
71143
|
}
|
|
70551
71144
|
const relativePath = normalizeOsPath(relativePathForContext(workingDir, absolutePath));
|
|
70552
|
-
const relativeDir =
|
|
71145
|
+
const relativeDir = dirname12(relativePath);
|
|
70553
71146
|
const pattern = relativeDir === "." || relativeDir === "" ? "**" : `${relativeDir}/**`;
|
|
70554
71147
|
return {
|
|
70555
71148
|
recommendedRule: `Read(${pattern})`,
|
|
@@ -70692,7 +71285,7 @@ function detectSkillScript(command, workingDir) {
|
|
|
70692
71285
|
return null;
|
|
70693
71286
|
}
|
|
70694
71287
|
const normalizedWorkingDir = normalizePathSeparators(workingDir).replace(/\/$/, "");
|
|
70695
|
-
const normalizedHomeDir = normalizePathSeparators(
|
|
71288
|
+
const normalizedHomeDir = normalizePathSeparators(homedir18()).replace(/\/$/, "");
|
|
70696
71289
|
const detect = (source, regex2) => {
|
|
70697
71290
|
for (const candidate of pathCandidates) {
|
|
70698
71291
|
const match3 = candidate.match(regex2);
|
|
@@ -72224,15 +72817,15 @@ __export(exports_memoryFilesystem, {
|
|
|
72224
72817
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR
|
|
72225
72818
|
});
|
|
72226
72819
|
import { existsSync as existsSync18, mkdirSync as mkdirSync13 } from "node:fs";
|
|
72227
|
-
import { homedir as
|
|
72820
|
+
import { homedir as homedir19 } from "node:os";
|
|
72228
72821
|
import { join as join22 } from "node:path";
|
|
72229
|
-
function getMemoryFilesystemRoot(agentId, homeDir =
|
|
72822
|
+
function getMemoryFilesystemRoot(agentId, homeDir = homedir19()) {
|
|
72230
72823
|
return join22(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
|
|
72231
72824
|
}
|
|
72232
|
-
function getMemorySystemDir(agentId, homeDir =
|
|
72825
|
+
function getMemorySystemDir(agentId, homeDir = homedir19()) {
|
|
72233
72826
|
return join22(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
|
|
72234
72827
|
}
|
|
72235
|
-
function ensureMemoryFilesystemDirs(agentId, homeDir =
|
|
72828
|
+
function ensureMemoryFilesystemDirs(agentId, homeDir = homedir19()) {
|
|
72236
72829
|
const root = getMemoryFilesystemRoot(agentId, homeDir);
|
|
72237
72830
|
const systemDir = getMemorySystemDir(agentId, homeDir);
|
|
72238
72831
|
if (!existsSync18(root)) {
|
|
@@ -75298,7 +75891,7 @@ import {
|
|
|
75298
75891
|
readFile as readFile7,
|
|
75299
75892
|
writeFile as writeFile4
|
|
75300
75893
|
} from "node:fs/promises";
|
|
75301
|
-
import { homedir as
|
|
75894
|
+
import { homedir as homedir20, tmpdir as tmpdir3 } from "node:os";
|
|
75302
75895
|
import { join as join25 } from "node:path";
|
|
75303
75896
|
function buildReflectionSubagentPrompt(input) {
|
|
75304
75897
|
const lines = [];
|
|
@@ -75492,7 +76085,7 @@ function getTranscriptRoot() {
|
|
|
75492
76085
|
if (envRoot) {
|
|
75493
76086
|
return envRoot;
|
|
75494
76087
|
}
|
|
75495
|
-
return join25(
|
|
76088
|
+
return join25(homedir20(), ".letta", DEFAULT_TRANSCRIPT_DIR);
|
|
75496
76089
|
}
|
|
75497
76090
|
function defaultState() {
|
|
75498
76091
|
return { auto_cursor_line: 0 };
|
|
@@ -75681,7 +76274,7 @@ import {
|
|
|
75681
76274
|
unlinkSync as unlinkSync7,
|
|
75682
76275
|
writeFileSync as writeFileSync11
|
|
75683
76276
|
} from "node:fs";
|
|
75684
|
-
import { homedir as
|
|
76277
|
+
import { homedir as homedir21 } from "node:os";
|
|
75685
76278
|
import { join as join26 } from "node:path";
|
|
75686
76279
|
function truncateStr(value, maxLen) {
|
|
75687
76280
|
if (value === null || value === undefined)
|
|
@@ -75822,7 +76415,7 @@ class ChunkLog {
|
|
|
75822
76415
|
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
|
|
75823
76416
|
var init_chunkLog = __esm(() => {
|
|
75824
76417
|
init_debug();
|
|
75825
|
-
LOG_BASE_DIR = join26(
|
|
76418
|
+
LOG_BASE_DIR = join26(homedir21(), ".letta", "logs", "chunk-logs");
|
|
75826
76419
|
chunkLog = new ChunkLog;
|
|
75827
76420
|
});
|
|
75828
76421
|
|
|
@@ -76839,6 +77432,7 @@ var init_engine = __esm(async () => {
|
|
|
76839
77432
|
default: "Normal approval flow.",
|
|
76840
77433
|
acceptEdits: "File edits auto-approved.",
|
|
76841
77434
|
plan: "Read-only mode. Focus on exploration and planning.",
|
|
77435
|
+
memory: "Memory-scoped mode. Reads are broad; mutations are limited to allowed memory roots.",
|
|
76842
77436
|
bypassPermissions: "All tools auto-approved. Bias toward action."
|
|
76843
77437
|
};
|
|
76844
77438
|
sharedReminderProviders = {
|
|
@@ -76951,10 +77545,10 @@ var init_constants2 = __esm(() => {
|
|
|
76951
77545
|
// src/websocket/listener/remote-settings.ts
|
|
76952
77546
|
import { existsSync as existsSync21, readFileSync as readFileSync12 } from "node:fs";
|
|
76953
77547
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
76954
|
-
import { homedir as
|
|
77548
|
+
import { homedir as homedir22 } from "node:os";
|
|
76955
77549
|
import path20 from "node:path";
|
|
76956
77550
|
function getRemoteSettingsPath() {
|
|
76957
|
-
return path20.join(
|
|
77551
|
+
return path20.join(homedir22(), ".letta", "remote-settings.json");
|
|
76958
77552
|
}
|
|
76959
77553
|
function loadRemoteSettings() {
|
|
76960
77554
|
if (_cache !== null) {
|
|
@@ -76998,7 +77592,7 @@ function saveRemoteSettings(updates) {
|
|
|
76998
77592
|
}
|
|
76999
77593
|
function loadLegacyCwdCache() {
|
|
77000
77594
|
try {
|
|
77001
|
-
const legacyPath = path20.join(
|
|
77595
|
+
const legacyPath = path20.join(homedir22(), ".letta", "cwd-cache.json");
|
|
77002
77596
|
if (!existsSync21(legacyPath))
|
|
77003
77597
|
return {};
|
|
77004
77598
|
const raw = readFileSync12(legacyPath, "utf-8");
|
|
@@ -78673,7 +79267,7 @@ __export(exports_diff, {
|
|
|
78673
79267
|
ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
|
|
78674
79268
|
ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
|
|
78675
79269
|
});
|
|
78676
|
-
import { basename as
|
|
79270
|
+
import { basename as basename3 } from "node:path";
|
|
78677
79271
|
function readFileOrNull(p) {
|
|
78678
79272
|
try {
|
|
78679
79273
|
return __require("node:fs").readFileSync(p, "utf-8");
|
|
@@ -78697,7 +79291,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
|
|
|
78697
79291
|
return { ok: true, out: content.split(oldStr).join(newStr) };
|
|
78698
79292
|
}
|
|
78699
79293
|
function computeAdvancedDiff(input, opts) {
|
|
78700
|
-
const fileName =
|
|
79294
|
+
const fileName = basename3(input.filePath || "");
|
|
78701
79295
|
const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
|
|
78702
79296
|
if (fileContent === null && input.kind !== "write") {
|
|
78703
79297
|
return { mode: "fallback", reason: "File not readable" };
|
|
@@ -78763,7 +79357,7 @@ function computeAdvancedDiff(input, opts) {
|
|
|
78763
79357
|
return { mode: "advanced", fileName, oldStr, newStr, hunks };
|
|
78764
79358
|
}
|
|
78765
79359
|
function parsePatchToAdvancedDiff(patchLines, filePath) {
|
|
78766
|
-
const fileName =
|
|
79360
|
+
const fileName = basename3(filePath);
|
|
78767
79361
|
const hunks = [];
|
|
78768
79362
|
let currentHunk = null;
|
|
78769
79363
|
let oldLine = 1;
|
|
@@ -79090,7 +79684,7 @@ var init_formatArgsDisplay = __esm(async () => {
|
|
|
79090
79684
|
});
|
|
79091
79685
|
|
|
79092
79686
|
// src/helpers/diffPreview.ts
|
|
79093
|
-
import path21, { basename as
|
|
79687
|
+
import path21, { basename as basename4 } from "node:path";
|
|
79094
79688
|
function parseHunkLinePrefix(raw) {
|
|
79095
79689
|
if (raw.length === 0) {
|
|
79096
79690
|
return { type: "context", content: "" };
|
|
@@ -79196,7 +79790,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79196
79790
|
filePath: resolvedFilePath,
|
|
79197
79791
|
content: toolArgs.content || ""
|
|
79198
79792
|
});
|
|
79199
|
-
previews.push(toDiffPreview(result,
|
|
79793
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79200
79794
|
}
|
|
79201
79795
|
} else if (isFileEditTool2(toolName)) {
|
|
79202
79796
|
const filePath = toolArgs.file_path;
|
|
@@ -79208,7 +79802,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79208
79802
|
filePath: resolvedFilePath,
|
|
79209
79803
|
edits: toolArgs.edits
|
|
79210
79804
|
});
|
|
79211
|
-
previews.push(toDiffPreview(result,
|
|
79805
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79212
79806
|
} else {
|
|
79213
79807
|
const result = computeAdvancedDiff2({
|
|
79214
79808
|
kind: "edit",
|
|
@@ -79217,7 +79811,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79217
79811
|
newString: toolArgs.new_string || "",
|
|
79218
79812
|
replaceAll: toolArgs.replace_all
|
|
79219
79813
|
});
|
|
79220
|
-
previews.push(toDiffPreview(result,
|
|
79814
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79221
79815
|
}
|
|
79222
79816
|
}
|
|
79223
79817
|
} else if (isPatchTool2(toolName) && toolArgs.input) {
|
|
@@ -79226,7 +79820,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79226
79820
|
if (op.kind === "add" || op.kind === "update") {
|
|
79227
79821
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
79228
79822
|
if (result) {
|
|
79229
|
-
previews.push(toDiffPreview(result,
|
|
79823
|
+
previews.push(toDiffPreview(result, basename4(op.path)));
|
|
79230
79824
|
}
|
|
79231
79825
|
}
|
|
79232
79826
|
}
|
|
@@ -79236,7 +79830,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79236
79830
|
if (op.kind === "add" || op.kind === "update") {
|
|
79237
79831
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
79238
79832
|
if (result) {
|
|
79239
|
-
previews.push(toDiffPreview(result,
|
|
79833
|
+
previews.push(toDiffPreview(result, basename4(op.path)));
|
|
79240
79834
|
}
|
|
79241
79835
|
}
|
|
79242
79836
|
}
|
|
@@ -81760,18 +82354,24 @@ function buildDeviceStatus(runtime, params) {
|
|
|
81760
82354
|
function buildLoopStatus(runtime, params) {
|
|
81761
82355
|
const listener = getListenerRuntime(runtime);
|
|
81762
82356
|
if (!listener) {
|
|
81763
|
-
return {
|
|
82357
|
+
return {
|
|
82358
|
+
status: "WAITING_ON_INPUT",
|
|
82359
|
+
active_run_ids: [],
|
|
82360
|
+
plan_file_path: null
|
|
82361
|
+
};
|
|
81764
82362
|
}
|
|
81765
82363
|
const scope = getScopeForRuntime(runtime, params);
|
|
81766
82364
|
const scopedAgentId = resolveScopedAgentId(listener, scope);
|
|
81767
82365
|
const scopedConversationId = resolveScopedConversationId(listener, scope);
|
|
82366
|
+
const conversationPermissionModeState = getConversationPermissionModeState(listener, scopedAgentId, scopedConversationId);
|
|
81768
82367
|
const conversationRuntime = getConversationRuntime(listener, scopedAgentId, scopedConversationId);
|
|
81769
82368
|
const interruptedCacheActive = hasInterruptedCacheForScope(listener, scope);
|
|
81770
82369
|
const recovered = getRecoveredApprovalStateForScope(listener, scope);
|
|
81771
82370
|
const status = interruptedCacheActive ? !conversationRuntime?.isProcessing ? "WAITING_ON_INPUT" : conversationRuntime?.loopStatus === "WAITING_ON_APPROVAL" ? "WAITING_ON_INPUT" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT" : recovered && recovered.pendingRequestIds.size > 0 && conversationRuntime?.loopStatus === "WAITING_ON_INPUT" ? "WAITING_ON_APPROVAL" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT";
|
|
81772
82371
|
return {
|
|
81773
82372
|
status,
|
|
81774
|
-
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : []
|
|
82373
|
+
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : [],
|
|
82374
|
+
plan_file_path: conversationPermissionModeState.mode === "plan" ? conversationPermissionModeState.planFilePath : null
|
|
81775
82375
|
};
|
|
81776
82376
|
}
|
|
81777
82377
|
function buildQueueSnapshot(runtime, params) {
|
|
@@ -83239,7 +83839,7 @@ function handleModeChange(msg, socket, runtime, scope) {
|
|
|
83239
83839
|
current.modeBeforePlan = null;
|
|
83240
83840
|
}
|
|
83241
83841
|
persistPermissionModeMapForRuntime(runtime);
|
|
83242
|
-
|
|
83842
|
+
emitRuntimeStateUpdates(runtime, scope);
|
|
83243
83843
|
if (isDebugEnabled()) {
|
|
83244
83844
|
console.log(`[Listen] Mode changed to: ${msg.mode}`);
|
|
83245
83845
|
}
|
|
@@ -83601,11 +84201,11 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
83601
84201
|
existsSync: existsSync22,
|
|
83602
84202
|
lstatSync: lstatSync2,
|
|
83603
84203
|
mkdirSync: mkdirSync15,
|
|
83604
|
-
rmdirSync
|
|
84204
|
+
rmdirSync,
|
|
83605
84205
|
symlinkSync,
|
|
83606
84206
|
unlinkSync: unlinkSync8
|
|
83607
84207
|
} = await import("node:fs");
|
|
83608
|
-
const { basename:
|
|
84208
|
+
const { basename: basename5, join: join28 } = await import("node:path");
|
|
83609
84209
|
const lettaHome = process.env.LETTA_HOME || join28(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
83610
84210
|
const globalSkillsDir = join28(lettaHome, "skills");
|
|
83611
84211
|
if (parsed.type === "skill_enable") {
|
|
@@ -83629,14 +84229,14 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
83629
84229
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
83630
84230
|
return true;
|
|
83631
84231
|
}
|
|
83632
|
-
const linkName =
|
|
84232
|
+
const linkName = basename5(parsed.skill_path);
|
|
83633
84233
|
const linkPath = join28(globalSkillsDir, linkName);
|
|
83634
84234
|
mkdirSync15(globalSkillsDir, { recursive: true });
|
|
83635
84235
|
if (existsSync22(linkPath)) {
|
|
83636
84236
|
const stat6 = lstatSync2(linkPath);
|
|
83637
84237
|
if (stat6.isSymbolicLink()) {
|
|
83638
84238
|
if (process.platform === "win32") {
|
|
83639
|
-
|
|
84239
|
+
rmdirSync(linkPath);
|
|
83640
84240
|
} else {
|
|
83641
84241
|
unlinkSync8(linkPath);
|
|
83642
84242
|
}
|
|
@@ -83694,7 +84294,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
83694
84294
|
return true;
|
|
83695
84295
|
}
|
|
83696
84296
|
if (process.platform === "win32") {
|
|
83697
|
-
|
|
84297
|
+
rmdirSync(linkPath);
|
|
83698
84298
|
} else {
|
|
83699
84299
|
unlinkSync8(linkPath);
|
|
83700
84300
|
}
|
|
@@ -85261,6 +85861,7 @@ var init_client4 = __esm(async () => {
|
|
|
85261
85861
|
__listenClientTestUtils = {
|
|
85262
85862
|
createRuntime: createLegacyTestRuntime,
|
|
85263
85863
|
createListenerRuntime: createRuntime,
|
|
85864
|
+
handleModeChange,
|
|
85264
85865
|
getOrCreateScopedRuntime,
|
|
85265
85866
|
buildListModelsEntries,
|
|
85266
85867
|
buildListModelsResponse,
|
|
@@ -85349,7 +85950,7 @@ import {
|
|
|
85349
85950
|
readFileSync as readFileSync14,
|
|
85350
85951
|
unlinkSync as unlinkSync8
|
|
85351
85952
|
} from "node:fs";
|
|
85352
|
-
import { homedir as
|
|
85953
|
+
import { homedir as homedir26 } from "node:os";
|
|
85353
85954
|
import { join as join31 } from "node:path";
|
|
85354
85955
|
import { format as format2 } from "node:util";
|
|
85355
85956
|
function isDebugEnabled2() {
|
|
@@ -85455,7 +86056,7 @@ function debugWarn2(prefix, message, ...args) {
|
|
|
85455
86056
|
}
|
|
85456
86057
|
var DEBUG_LOG_DIR2, MAX_SESSION_FILES3 = 5, DEFAULT_TAIL_LINES2 = 50, debugLogFile2;
|
|
85457
86058
|
var init_debug2 = __esm(() => {
|
|
85458
|
-
DEBUG_LOG_DIR2 = join31(
|
|
86059
|
+
DEBUG_LOG_DIR2 = join31(homedir26(), ".letta", "logs", "debug");
|
|
85459
86060
|
debugLogFile2 = new DebugLogFile2;
|
|
85460
86061
|
});
|
|
85461
86062
|
|
|
@@ -85484,10 +86085,10 @@ __export(exports_skills2, {
|
|
|
85484
86085
|
});
|
|
85485
86086
|
import { existsSync as existsSync24 } from "node:fs";
|
|
85486
86087
|
import { readdir as readdir7, readFile as readFile8, realpath as realpath4, stat as stat6 } from "node:fs/promises";
|
|
85487
|
-
import { dirname as
|
|
86088
|
+
import { dirname as dirname13, join as join32 } from "node:path";
|
|
85488
86089
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
85489
86090
|
function getBundledSkillsPath2() {
|
|
85490
|
-
const thisDir =
|
|
86091
|
+
const thisDir = dirname13(fileURLToPath8(import.meta.url));
|
|
85491
86092
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
85492
86093
|
return join32(thisDir, "../skills/builtin");
|
|
85493
86094
|
}
|
|
@@ -85683,12 +86284,12 @@ import {
|
|
|
85683
86284
|
writeFileSync as fsWriteFileSync2,
|
|
85684
86285
|
mkdirSync as mkdirSync17
|
|
85685
86286
|
} from "node:fs";
|
|
85686
|
-
import { dirname as
|
|
86287
|
+
import { dirname as dirname14 } from "node:path";
|
|
85687
86288
|
async function readFile9(path23) {
|
|
85688
86289
|
return fsReadFileSync2(path23, { encoding: "utf-8" });
|
|
85689
86290
|
}
|
|
85690
86291
|
async function writeFile7(path23, content) {
|
|
85691
|
-
const dir =
|
|
86292
|
+
const dir = dirname14(path23);
|
|
85692
86293
|
if (!existsSync25(dir)) {
|
|
85693
86294
|
mkdirSync17(dir, { recursive: true });
|
|
85694
86295
|
}
|
|
@@ -85733,7 +86334,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85733
86334
|
}
|
|
85734
86335
|
const wasRaw = process.stdin.isRaw;
|
|
85735
86336
|
const wasFlowing = process.stdin.readableFlowing;
|
|
85736
|
-
return new Promise((
|
|
86337
|
+
return new Promise((resolve25) => {
|
|
85737
86338
|
let response = "";
|
|
85738
86339
|
let resolved = false;
|
|
85739
86340
|
const cleanup = () => {
|
|
@@ -85750,7 +86351,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85750
86351
|
};
|
|
85751
86352
|
const timeout = setTimeout(() => {
|
|
85752
86353
|
cleanup();
|
|
85753
|
-
|
|
86354
|
+
resolve25(null);
|
|
85754
86355
|
}, timeoutMs);
|
|
85755
86356
|
const onData = (data) => {
|
|
85756
86357
|
response += data.toString();
|
|
@@ -85760,7 +86361,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85760
86361
|
if (match3) {
|
|
85761
86362
|
clearTimeout(timeout);
|
|
85762
86363
|
cleanup();
|
|
85763
|
-
|
|
86364
|
+
resolve25({
|
|
85764
86365
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
85765
86366
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
85766
86367
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -85775,7 +86376,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85775
86376
|
} catch {
|
|
85776
86377
|
clearTimeout(timeout);
|
|
85777
86378
|
cleanup();
|
|
85778
|
-
|
|
86379
|
+
resolve25(null);
|
|
85779
86380
|
}
|
|
85780
86381
|
});
|
|
85781
86382
|
}
|
|
@@ -86984,10 +87585,10 @@ __export(exports_setup, {
|
|
|
86984
87585
|
runSetup: () => runSetup
|
|
86985
87586
|
});
|
|
86986
87587
|
async function runSetup() {
|
|
86987
|
-
return new Promise((
|
|
87588
|
+
return new Promise((resolve26) => {
|
|
86988
87589
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
86989
87590
|
onComplete: () => {
|
|
86990
|
-
|
|
87591
|
+
resolve26();
|
|
86991
87592
|
}
|
|
86992
87593
|
}));
|
|
86993
87594
|
waitUntilExit().catch((error) => {
|
|
@@ -87517,10 +88118,10 @@ __export(exports_import, {
|
|
|
87517
88118
|
});
|
|
87518
88119
|
import { createReadStream } from "node:fs";
|
|
87519
88120
|
import { chmod, mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
|
|
87520
|
-
import { dirname as
|
|
88121
|
+
import { dirname as dirname15, resolve as resolve26 } from "node:path";
|
|
87521
88122
|
async function importAgentFromFile(options) {
|
|
87522
88123
|
const client = await getClient();
|
|
87523
|
-
const resolvedPath =
|
|
88124
|
+
const resolvedPath = resolve26(options.filePath);
|
|
87524
88125
|
const file = createReadStream(resolvedPath);
|
|
87525
88126
|
const importResponse = await client.agents.importFile({
|
|
87526
88127
|
file,
|
|
@@ -87555,7 +88156,7 @@ async function extractSkillsFromAf(afPath, destDir) {
|
|
|
87555
88156
|
return [];
|
|
87556
88157
|
}
|
|
87557
88158
|
for (const skill2 of afData.skills) {
|
|
87558
|
-
const skillDir =
|
|
88159
|
+
const skillDir = resolve26(destDir, skill2.name);
|
|
87559
88160
|
await mkdir7(skillDir, { recursive: true });
|
|
87560
88161
|
if (skill2.files) {
|
|
87561
88162
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -87575,8 +88176,8 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
87575
88176
|
}
|
|
87576
88177
|
}
|
|
87577
88178
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
87578
|
-
const fullPath =
|
|
87579
|
-
await mkdir7(
|
|
88179
|
+
const fullPath = resolve26(skillDir, filePath);
|
|
88180
|
+
await mkdir7(dirname15(fullPath), { recursive: true });
|
|
87580
88181
|
await writeFile8(fullPath, content, "utf-8");
|
|
87581
88182
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
87582
88183
|
if (isScript) {
|
|
@@ -87882,12 +88483,12 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
87882
88483
|
};
|
|
87883
88484
|
}
|
|
87884
88485
|
async function flushAndExit(code) {
|
|
87885
|
-
const flushWritable = (stream2) => new Promise((
|
|
88486
|
+
const flushWritable = (stream2) => new Promise((resolve27) => {
|
|
87886
88487
|
if (stream2.destroyed || stream2.writableEnded) {
|
|
87887
|
-
|
|
88488
|
+
resolve27();
|
|
87888
88489
|
return;
|
|
87889
88490
|
}
|
|
87890
|
-
stream2.write("", () =>
|
|
88491
|
+
stream2.write("", () => resolve27());
|
|
87891
88492
|
});
|
|
87892
88493
|
await Promise.allSettled([
|
|
87893
88494
|
flushWritable(process.stdout),
|
|
@@ -87913,7 +88514,8 @@ async function handleHeadlessCommand(parsedArgs, model, skillsDirectoryOverride,
|
|
|
87913
88514
|
"default",
|
|
87914
88515
|
"acceptEdits",
|
|
87915
88516
|
"bypassPermissions",
|
|
87916
|
-
"plan"
|
|
88517
|
+
"plan",
|
|
88518
|
+
"memory"
|
|
87917
88519
|
];
|
|
87918
88520
|
if (validModes.includes(permissionModeValue)) {
|
|
87919
88521
|
permissionMode3.setMode(permissionModeValue);
|
|
@@ -88834,7 +89436,7 @@ ${loadedContents.join(`
|
|
|
88834
89436
|
} else {
|
|
88835
89437
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
88836
89438
|
}
|
|
88837
|
-
await new Promise((
|
|
89439
|
+
await new Promise((resolve27) => setTimeout(resolve27, retryDelayMs));
|
|
88838
89440
|
continue;
|
|
88839
89441
|
}
|
|
88840
89442
|
}
|
|
@@ -88883,7 +89485,7 @@ ${loadedContents.join(`
|
|
|
88883
89485
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
88884
89486
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
88885
89487
|
}
|
|
88886
|
-
await new Promise((
|
|
89488
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
88887
89489
|
conversationBusyRetries = 0;
|
|
88888
89490
|
continue;
|
|
88889
89491
|
}
|
|
@@ -89122,7 +89724,7 @@ ${loadedContents.join(`
|
|
|
89122
89724
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
89123
89725
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
89124
89726
|
}
|
|
89125
|
-
await new Promise((
|
|
89727
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89126
89728
|
refreshCurrentInputOtids();
|
|
89127
89729
|
continue;
|
|
89128
89730
|
}
|
|
@@ -89208,7 +89810,7 @@ ${loadedContents.join(`
|
|
|
89208
89810
|
} else {
|
|
89209
89811
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
89210
89812
|
}
|
|
89211
|
-
await new Promise((
|
|
89813
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89212
89814
|
refreshCurrentInputOtids();
|
|
89213
89815
|
continue;
|
|
89214
89816
|
}
|
|
@@ -89236,7 +89838,7 @@ ${loadedContents.join(`
|
|
|
89236
89838
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
89237
89839
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
89238
89840
|
}
|
|
89239
|
-
await new Promise((
|
|
89841
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89240
89842
|
refreshCurrentInputOtids();
|
|
89241
89843
|
continue;
|
|
89242
89844
|
}
|
|
@@ -89570,9 +90172,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89570
90172
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
89571
90173
|
maybeNotifyBlocked(syntheticUserLine);
|
|
89572
90174
|
if (lineResolver) {
|
|
89573
|
-
const
|
|
90175
|
+
const resolve27 = lineResolver;
|
|
89574
90176
|
lineResolver = null;
|
|
89575
|
-
|
|
90177
|
+
resolve27(syntheticUserLine);
|
|
89576
90178
|
return;
|
|
89577
90179
|
}
|
|
89578
90180
|
lineQueue.push(syntheticUserLine);
|
|
@@ -89580,9 +90182,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89580
90182
|
rl.on("line", (line) => {
|
|
89581
90183
|
maybeNotifyBlocked(line);
|
|
89582
90184
|
if (lineResolver) {
|
|
89583
|
-
const
|
|
90185
|
+
const resolve27 = lineResolver;
|
|
89584
90186
|
lineResolver = null;
|
|
89585
|
-
|
|
90187
|
+
resolve27(line);
|
|
89586
90188
|
} else {
|
|
89587
90189
|
lineQueue.push(line);
|
|
89588
90190
|
}
|
|
@@ -89591,17 +90193,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89591
90193
|
setMessageQueueAdder(null);
|
|
89592
90194
|
msgQueueRuntime.clear("shutdown");
|
|
89593
90195
|
if (lineResolver) {
|
|
89594
|
-
const
|
|
90196
|
+
const resolve27 = lineResolver;
|
|
89595
90197
|
lineResolver = null;
|
|
89596
|
-
|
|
90198
|
+
resolve27(null);
|
|
89597
90199
|
}
|
|
89598
90200
|
});
|
|
89599
90201
|
async function getNextLine() {
|
|
89600
90202
|
if (lineQueue.length > 0) {
|
|
89601
90203
|
return lineQueue.shift() ?? null;
|
|
89602
90204
|
}
|
|
89603
|
-
return new Promise((
|
|
89604
|
-
lineResolver =
|
|
90205
|
+
return new Promise((resolve27) => {
|
|
90206
|
+
lineResolver = resolve27;
|
|
89605
90207
|
});
|
|
89606
90208
|
}
|
|
89607
90209
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -90105,7 +90707,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
90105
90707
|
uuid: `retry-bidir-${randomUUID8()}`
|
|
90106
90708
|
};
|
|
90107
90709
|
console.log(JSON.stringify(retryMsg));
|
|
90108
|
-
await new Promise((
|
|
90710
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
90109
90711
|
continue;
|
|
90110
90712
|
}
|
|
90111
90713
|
throw preStreamError;
|
|
@@ -90401,10 +91003,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90401
91003
|
detectionComplete = true;
|
|
90402
91004
|
return;
|
|
90403
91005
|
}
|
|
90404
|
-
return new Promise((
|
|
91006
|
+
return new Promise((resolve27) => {
|
|
90405
91007
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
90406
91008
|
detectionComplete = true;
|
|
90407
|
-
|
|
91009
|
+
resolve27();
|
|
90408
91010
|
return;
|
|
90409
91011
|
}
|
|
90410
91012
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -90437,7 +91039,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90437
91039
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
90438
91040
|
}
|
|
90439
91041
|
detectionComplete = true;
|
|
90440
|
-
|
|
91042
|
+
resolve27();
|
|
90441
91043
|
};
|
|
90442
91044
|
const handleData = (data) => {
|
|
90443
91045
|
if (timeoutId === undefined) {
|
|
@@ -90795,10 +91397,10 @@ __export(exports_settings, {
|
|
|
90795
91397
|
loadProjectSettings: () => loadProjectSettings,
|
|
90796
91398
|
getSetting: () => getSetting
|
|
90797
91399
|
});
|
|
90798
|
-
import { homedir as
|
|
91400
|
+
import { homedir as homedir29 } from "node:os";
|
|
90799
91401
|
import { join as join36 } from "node:path";
|
|
90800
91402
|
function getSettingsPath() {
|
|
90801
|
-
return join36(
|
|
91403
|
+
return join36(homedir29(), ".letta", "settings.json");
|
|
90802
91404
|
}
|
|
90803
91405
|
async function loadSettings() {
|
|
90804
91406
|
const settingsPath = getSettingsPath();
|
|
@@ -106304,16 +106906,16 @@ function clipStyledSpans(spans, maxColumns) {
|
|
|
106304
106906
|
return { spans: clipped, clipped: false };
|
|
106305
106907
|
}
|
|
106306
106908
|
function languageFromPath(filePath) {
|
|
106307
|
-
const
|
|
106308
|
-
const lower =
|
|
106909
|
+
const basename5 = filePath.split("/").pop() ?? filePath;
|
|
106910
|
+
const lower = basename5.toLowerCase();
|
|
106309
106911
|
if (lower === "makefile")
|
|
106310
106912
|
return "makefile";
|
|
106311
106913
|
if (lower === "dockerfile")
|
|
106312
106914
|
return "dockerfile";
|
|
106313
|
-
const dotIdx =
|
|
106915
|
+
const dotIdx = basename5.lastIndexOf(".");
|
|
106314
106916
|
if (dotIdx < 0)
|
|
106315
106917
|
return;
|
|
106316
|
-
const ext3 =
|
|
106918
|
+
const ext3 = basename5.slice(dotIdx + 1).toLowerCase();
|
|
106317
106919
|
return EXT_TO_LANG[ext3];
|
|
106318
106920
|
}
|
|
106319
106921
|
function colorForClassName(className, palette) {
|
|
@@ -110349,7 +110951,7 @@ var init_plan_viewer_template = () => {};
|
|
|
110349
110951
|
|
|
110350
110952
|
// src/web/generate-plan-viewer.ts
|
|
110351
110953
|
import { chmodSync as chmodSync2, existsSync as existsSync28, mkdirSync as mkdirSync20, writeFileSync as writeFileSync14 } from "node:fs";
|
|
110352
|
-
import { homedir as
|
|
110954
|
+
import { homedir as homedir30 } from "node:os";
|
|
110353
110955
|
import { join as join37 } from "node:path";
|
|
110354
110956
|
async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
110355
110957
|
const data = {
|
|
@@ -110383,7 +110985,7 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
|
110383
110985
|
var VIEWERS_DIR;
|
|
110384
110986
|
var init_generate_plan_viewer = __esm(() => {
|
|
110385
110987
|
init_plan_viewer_template();
|
|
110386
|
-
VIEWERS_DIR = join37(
|
|
110988
|
+
VIEWERS_DIR = join37(homedir30(), ".letta", "viewers");
|
|
110387
110989
|
});
|
|
110388
110990
|
|
|
110389
110991
|
// src/cli/components/StaticPlanApproval.tsx
|
|
@@ -112623,7 +113225,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
112623
113225
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
112624
113226
|
import { existsSync as existsSync29, readFileSync as readFileSync16, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
112625
113227
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
112626
|
-
import { basename as
|
|
113228
|
+
import { basename as basename5, extname as extname5, isAbsolute as isAbsolute19, join as join38, resolve as resolve27 } from "node:path";
|
|
112627
113229
|
function countLines2(text) {
|
|
112628
113230
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
112629
113231
|
}
|
|
@@ -112670,8 +113272,8 @@ function translatePasteForImages(paste) {
|
|
|
112670
113272
|
}
|
|
112671
113273
|
} catch {}
|
|
112672
113274
|
}
|
|
112673
|
-
if (!
|
|
112674
|
-
filePath =
|
|
113275
|
+
if (!isAbsolute19(filePath))
|
|
113276
|
+
filePath = resolve27(process.cwd(), filePath);
|
|
112675
113277
|
const ext3 = extname5(filePath || "").toLowerCase();
|
|
112676
113278
|
if (IMAGE_EXTS.has(ext3) && existsSync29(filePath) && statSync10(filePath).isFile()) {
|
|
112677
113279
|
const buf = readFileSync16(filePath);
|
|
@@ -112680,7 +113282,7 @@ function translatePasteForImages(paste) {
|
|
|
112680
113282
|
const id = allocateImage({
|
|
112681
113283
|
data: b64,
|
|
112682
113284
|
mediaType: mt,
|
|
112683
|
-
filename:
|
|
113285
|
+
filename: basename5(filePath)
|
|
112684
113286
|
});
|
|
112685
113287
|
s = `[Image #${id}]`;
|
|
112686
113288
|
}
|
|
@@ -113446,8 +114048,8 @@ import {
|
|
|
113446
114048
|
readFileSync as readFileSync17,
|
|
113447
114049
|
writeFileSync as writeFileSync15
|
|
113448
114050
|
} from "node:fs";
|
|
113449
|
-
import { homedir as
|
|
113450
|
-
import { dirname as
|
|
114051
|
+
import { homedir as homedir31, platform as platform5 } from "node:os";
|
|
114052
|
+
import { dirname as dirname16, join as join39 } from "node:path";
|
|
113451
114053
|
function detectTerminalType() {
|
|
113452
114054
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
113453
114055
|
return "cursor";
|
|
@@ -113479,7 +114081,7 @@ function getKeybindingsPath(terminal) {
|
|
|
113479
114081
|
}[terminal];
|
|
113480
114082
|
const os7 = platform5();
|
|
113481
114083
|
if (os7 === "darwin") {
|
|
113482
|
-
return join39(
|
|
114084
|
+
return join39(homedir31(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
113483
114085
|
}
|
|
113484
114086
|
if (os7 === "win32") {
|
|
113485
114087
|
const appData = process.env.APPDATA;
|
|
@@ -113488,7 +114090,7 @@ function getKeybindingsPath(terminal) {
|
|
|
113488
114090
|
return join39(appData, appName, "User", "keybindings.json");
|
|
113489
114091
|
}
|
|
113490
114092
|
if (os7 === "linux") {
|
|
113491
|
-
return join39(
|
|
114093
|
+
return join39(homedir31(), ".config", appName, "User", "keybindings.json");
|
|
113492
114094
|
}
|
|
113493
114095
|
return null;
|
|
113494
114096
|
}
|
|
@@ -113538,7 +114140,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
113538
114140
|
if (keybindingExists(keybindingsPath)) {
|
|
113539
114141
|
return { success: true, alreadyExists: true };
|
|
113540
114142
|
}
|
|
113541
|
-
const parentDir =
|
|
114143
|
+
const parentDir = dirname16(keybindingsPath);
|
|
113542
114144
|
if (!existsSync30(parentDir)) {
|
|
113543
114145
|
mkdirSync21(parentDir, { recursive: true });
|
|
113544
114146
|
}
|
|
@@ -113645,10 +114247,10 @@ function getWezTermConfigPath() {
|
|
|
113645
114247
|
if (existsSync30(xdgPath))
|
|
113646
114248
|
return xdgPath;
|
|
113647
114249
|
}
|
|
113648
|
-
const configPath = join39(
|
|
114250
|
+
const configPath = join39(homedir31(), ".config", "wezterm", "wezterm.lua");
|
|
113649
114251
|
if (existsSync30(configPath))
|
|
113650
114252
|
return configPath;
|
|
113651
|
-
return join39(
|
|
114253
|
+
return join39(homedir31(), ".wezterm.lua");
|
|
113652
114254
|
}
|
|
113653
114255
|
function wezTermDeleteFixExists(configPath) {
|
|
113654
114256
|
if (!existsSync30(configPath))
|
|
@@ -113697,7 +114299,7 @@ return config`);
|
|
|
113697
114299
|
${WEZTERM_DELETE_FIX}
|
|
113698
114300
|
`;
|
|
113699
114301
|
}
|
|
113700
|
-
const parentDir =
|
|
114302
|
+
const parentDir = dirname16(configPath);
|
|
113701
114303
|
if (!existsSync30(parentDir)) {
|
|
113702
114304
|
mkdirSync21(parentDir, { recursive: true });
|
|
113703
114305
|
}
|
|
@@ -114280,7 +114882,7 @@ __export(exports_custom, {
|
|
|
114280
114882
|
});
|
|
114281
114883
|
import { existsSync as existsSync31 } from "node:fs";
|
|
114282
114884
|
import { readdir as readdir9, readFile as readFile11 } from "node:fs/promises";
|
|
114283
|
-
import { basename as
|
|
114885
|
+
import { basename as basename6, dirname as dirname17, join as join40 } from "node:path";
|
|
114284
114886
|
async function getCustomCommands() {
|
|
114285
114887
|
if (cachedCommands !== null) {
|
|
114286
114888
|
return cachedCommands;
|
|
@@ -114340,8 +114942,8 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
|
114340
114942
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
114341
114943
|
const content = await readFile11(filePath, "utf-8");
|
|
114342
114944
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
114343
|
-
const id =
|
|
114344
|
-
const relativePath =
|
|
114945
|
+
const id = basename6(filePath, ".md");
|
|
114946
|
+
const relativePath = dirname17(filePath).slice(rootPath.length);
|
|
114345
114947
|
const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
|
|
114346
114948
|
let description = getStringField(frontmatter, "description");
|
|
114347
114949
|
if (!description) {
|
|
@@ -114689,12 +115291,12 @@ var init_HelpDialog = __esm(async () => {
|
|
|
114689
115291
|
});
|
|
114690
115292
|
|
|
114691
115293
|
// src/hooks/writer.ts
|
|
114692
|
-
import { homedir as
|
|
114693
|
-
import { resolve as
|
|
115294
|
+
import { homedir as homedir32 } from "node:os";
|
|
115295
|
+
import { resolve as resolve28 } from "node:path";
|
|
114694
115296
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
114695
|
-
const home = process.env.HOME ||
|
|
114696
|
-
const globalSettingsPath =
|
|
114697
|
-
const projectSettingsPath =
|
|
115297
|
+
const home = process.env.HOME || homedir32();
|
|
115298
|
+
const globalSettingsPath = resolve28(home, ".letta", "settings.json");
|
|
115299
|
+
const projectSettingsPath = resolve28(workingDirectory, ".letta", "settings.json");
|
|
114698
115300
|
return globalSettingsPath === projectSettingsPath;
|
|
114699
115301
|
}
|
|
114700
115302
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -117332,7 +117934,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
117332
117934
|
|
|
117333
117935
|
// src/cli/helpers/fileSearch.ts
|
|
117334
117936
|
import { readdirSync as readdirSync13, statSync as statSync11 } from "node:fs";
|
|
117335
|
-
import { join as join41, relative as relative15, resolve as
|
|
117937
|
+
import { join as join41, relative as relative15, resolve as resolve29 } from "node:path";
|
|
117336
117938
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
117337
117939
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
117338
117940
|
return results;
|
|
@@ -117375,7 +117977,7 @@ async function searchFiles(query, deep = false) {
|
|
|
117375
117977
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
117376
117978
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
117377
117979
|
try {
|
|
117378
|
-
const resolvedDir =
|
|
117980
|
+
const resolvedDir = resolve29(getIndexRoot(), dirPart);
|
|
117379
117981
|
try {
|
|
117380
117982
|
statSync11(resolvedDir);
|
|
117381
117983
|
searchDir = resolvedDir;
|
|
@@ -119499,11 +120101,11 @@ import {
|
|
|
119499
120101
|
mkdirSync as mkdirSync22,
|
|
119500
120102
|
mkdtempSync,
|
|
119501
120103
|
readFileSync as readFileSync18,
|
|
119502
|
-
rmSync as
|
|
120104
|
+
rmSync as rmSync4,
|
|
119503
120105
|
writeFileSync as writeFileSync16
|
|
119504
120106
|
} from "node:fs";
|
|
119505
120107
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
119506
|
-
import { dirname as
|
|
120108
|
+
import { dirname as dirname18, join as join42 } from "node:path";
|
|
119507
120109
|
function runCommand(command, args, cwd2, input) {
|
|
119508
120110
|
try {
|
|
119509
120111
|
return execFileSync4(command, args, {
|
|
@@ -119750,8 +120352,8 @@ function runGit6(args, cwd2) {
|
|
|
119750
120352
|
}
|
|
119751
120353
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
119752
120354
|
const absolutePath = join42(repoDir, workflowPath);
|
|
119753
|
-
if (!existsSync32(
|
|
119754
|
-
mkdirSync22(
|
|
120355
|
+
if (!existsSync32(dirname18(absolutePath))) {
|
|
120356
|
+
mkdirSync22(dirname18(absolutePath), { recursive: true });
|
|
119755
120357
|
}
|
|
119756
120358
|
const next = `${content.trimEnd()}
|
|
119757
120359
|
`;
|
|
@@ -119882,7 +120484,7 @@ async function installGithubApp(options) {
|
|
|
119882
120484
|
agentUrl: resolvedAgentId ? buildChatUrl(resolvedAgentId) : null
|
|
119883
120485
|
};
|
|
119884
120486
|
} finally {
|
|
119885
|
-
|
|
120487
|
+
rmSync4(tempDir, { recursive: true, force: true });
|
|
119886
120488
|
}
|
|
119887
120489
|
}
|
|
119888
120490
|
var DEFAULT_WORKFLOW_PATH = ".github/workflows/letta.yml", ALTERNATE_WORKFLOW_PATH = ".github/workflows/letta-code.yml";
|
|
@@ -123657,7 +124259,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
123657
124259
|
});
|
|
123658
124260
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
123659
124261
|
import { chmodSync as chmodSync3, existsSync as existsSync33, mkdirSync as mkdirSync23, writeFileSync as writeFileSync17 } from "node:fs";
|
|
123660
|
-
import { homedir as
|
|
124262
|
+
import { homedir as homedir33 } from "node:os";
|
|
123661
124263
|
import { join as join43 } from "node:path";
|
|
123662
124264
|
import { promisify as promisify14 } from "node:util";
|
|
123663
124265
|
async function runGitSafe(cwd2, args) {
|
|
@@ -123971,7 +124573,7 @@ var init_generate_memory_viewer = __esm(async () => {
|
|
|
123971
124573
|
init_memoryGit()
|
|
123972
124574
|
]);
|
|
123973
124575
|
execFile14 = promisify14(execFileCb5);
|
|
123974
|
-
VIEWERS_DIR2 = join43(
|
|
124576
|
+
VIEWERS_DIR2 = join43(homedir33(), ".letta", "viewers");
|
|
123975
124577
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
123976
124578
|
});
|
|
123977
124579
|
|
|
@@ -126689,11 +127291,11 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
126689
127291
|
|
|
126690
127292
|
// src/utils/aws-credentials.ts
|
|
126691
127293
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
126692
|
-
import { homedir as
|
|
127294
|
+
import { homedir as homedir34 } from "node:os";
|
|
126693
127295
|
import { join as join44 } from "node:path";
|
|
126694
127296
|
async function parseAwsCredentials() {
|
|
126695
|
-
const credentialsPath = join44(
|
|
126696
|
-
const configPath = join44(
|
|
127297
|
+
const credentialsPath = join44(homedir34(), ".aws", "credentials");
|
|
127298
|
+
const configPath = join44(homedir34(), ".aws", "config");
|
|
126697
127299
|
const profiles = new Map;
|
|
126698
127300
|
try {
|
|
126699
127301
|
const content = await readFile12(credentialsPath, "utf-8");
|
|
@@ -132174,7 +132776,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
132174
132776
|
};
|
|
132175
132777
|
}
|
|
132176
132778
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
132177
|
-
return new Promise((
|
|
132779
|
+
return new Promise((resolve30, reject) => {
|
|
132178
132780
|
const [executable, ...args] = launcher;
|
|
132179
132781
|
if (!executable) {
|
|
132180
132782
|
reject(new Error("Empty launcher"));
|
|
@@ -132187,7 +132789,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
132187
132789
|
const safeResolve = (result) => {
|
|
132188
132790
|
if (!resolved) {
|
|
132189
132791
|
resolved = true;
|
|
132190
|
-
|
|
132792
|
+
resolve30(result);
|
|
132191
132793
|
}
|
|
132192
132794
|
};
|
|
132193
132795
|
let child;
|
|
@@ -132633,7 +133235,7 @@ __export(exports_shellAliases, {
|
|
|
132633
133235
|
clearAliasCache: () => clearAliasCache
|
|
132634
133236
|
});
|
|
132635
133237
|
import { existsSync as existsSync36, readFileSync as readFileSync20 } from "node:fs";
|
|
132636
|
-
import { homedir as
|
|
133238
|
+
import { homedir as homedir35 } from "node:os";
|
|
132637
133239
|
import { join as join46 } from "node:path";
|
|
132638
133240
|
function parseAliasesFromFile(filePath) {
|
|
132639
133241
|
const aliases = new Map;
|
|
@@ -132703,7 +133305,7 @@ function loadAliases(forceReload = false) {
|
|
|
132703
133305
|
if (aliasCache && !forceReload) {
|
|
132704
133306
|
return aliasCache;
|
|
132705
133307
|
}
|
|
132706
|
-
const home =
|
|
133308
|
+
const home = homedir35();
|
|
132707
133309
|
const allAliases = new Map;
|
|
132708
133310
|
for (const file of ALIAS_FILES) {
|
|
132709
133311
|
const filePath = join46(home, file);
|
|
@@ -133364,14 +133966,14 @@ __export(exports_export, {
|
|
|
133364
133966
|
packageSkills: () => packageSkills
|
|
133365
133967
|
});
|
|
133366
133968
|
import { readdir as readdir10, readFile as readFile13 } from "node:fs/promises";
|
|
133367
|
-
import { relative as relative16, resolve as
|
|
133969
|
+
import { relative as relative16, resolve as resolve30 } from "node:path";
|
|
133368
133970
|
async function packageSkills(agentId, skillsDir) {
|
|
133369
133971
|
const skills = [];
|
|
133370
133972
|
const skillNames = new Set;
|
|
133371
133973
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
133372
133974
|
agentId && getAgentSkillsDir(agentId),
|
|
133373
|
-
|
|
133374
|
-
|
|
133975
|
+
resolve30(process.cwd(), ".skills"),
|
|
133976
|
+
resolve30(process.env.HOME || "~", ".letta", "skills")
|
|
133375
133977
|
].filter((dir) => Boolean(dir));
|
|
133376
133978
|
for (const baseDir of dirsToCheck) {
|
|
133377
133979
|
try {
|
|
@@ -133381,8 +133983,8 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
133381
133983
|
continue;
|
|
133382
133984
|
if (skillNames.has(entry.name))
|
|
133383
133985
|
continue;
|
|
133384
|
-
const skillDir =
|
|
133385
|
-
const skillMdPath =
|
|
133986
|
+
const skillDir = resolve30(baseDir, entry.name);
|
|
133987
|
+
const skillMdPath = resolve30(skillDir, "SKILL.md");
|
|
133386
133988
|
try {
|
|
133387
133989
|
await readFile13(skillMdPath, "utf-8");
|
|
133388
133990
|
} catch {
|
|
@@ -133412,7 +134014,7 @@ async function readSkillFiles(skillDir) {
|
|
|
133412
134014
|
async function walk(dir) {
|
|
133413
134015
|
const entries = await readdir10(dir, { withFileTypes: true });
|
|
133414
134016
|
for (const entry of entries) {
|
|
133415
|
-
const fullPath =
|
|
134017
|
+
const fullPath = resolve30(dir, entry.name);
|
|
133416
134018
|
if (entry.isDirectory()) {
|
|
133417
134019
|
await walk(fullPath);
|
|
133418
134020
|
} else {
|
|
@@ -133557,7 +134159,7 @@ __export(exports_App, {
|
|
|
133557
134159
|
});
|
|
133558
134160
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
133559
134161
|
import { existsSync as existsSync37, readFileSync as readFileSync21, renameSync as renameSync3, writeFileSync as writeFileSync18 } from "node:fs";
|
|
133560
|
-
import { homedir as
|
|
134162
|
+
import { homedir as homedir36, tmpdir as tmpdir6 } from "node:os";
|
|
133561
134163
|
import { join as join47, relative as relative17 } from "node:path";
|
|
133562
134164
|
function deriveReasoningEffort(modelSettings, llmConfig) {
|
|
133563
134165
|
if (modelSettings && "provider_type" in modelSettings) {
|
|
@@ -135896,7 +136498,7 @@ ${newState.originalPrompt}`,
|
|
|
135896
136498
|
cancelled = true;
|
|
135897
136499
|
break;
|
|
135898
136500
|
}
|
|
135899
|
-
await new Promise((
|
|
136501
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
135900
136502
|
}
|
|
135901
136503
|
buffersRef.current.byId.delete(statusId);
|
|
135902
136504
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -135960,7 +136562,7 @@ ${newState.originalPrompt}`,
|
|
|
135960
136562
|
cancelled = true;
|
|
135961
136563
|
break;
|
|
135962
136564
|
}
|
|
135963
|
-
await new Promise((
|
|
136565
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
135964
136566
|
}
|
|
135965
136567
|
if (retryStatusId) {
|
|
135966
136568
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -136718,7 +137320,7 @@ ${feedback}
|
|
|
136718
137320
|
});
|
|
136719
137321
|
buffersRef.current.order.push(statusId);
|
|
136720
137322
|
refreshDerived();
|
|
136721
|
-
await new Promise((
|
|
137323
|
+
await new Promise((resolve31) => setTimeout(resolve31, delayMs));
|
|
136722
137324
|
buffersRef.current.byId.delete(statusId);
|
|
136723
137325
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
136724
137326
|
refreshDerived();
|
|
@@ -136778,7 +137380,7 @@ ${feedback}
|
|
|
136778
137380
|
cancelled = true;
|
|
136779
137381
|
break;
|
|
136780
137382
|
}
|
|
136781
|
-
await new Promise((
|
|
137383
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
136782
137384
|
}
|
|
136783
137385
|
if (retryStatusId) {
|
|
136784
137386
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -141721,7 +142323,7 @@ ${guidance}`);
|
|
|
141721
142323
|
}
|
|
141722
142324
|
if (mode === "bypassPermissions") {
|
|
141723
142325
|
const planFilePath = activePlanPath ?? fallbackPlanPath;
|
|
141724
|
-
const plansDir = join47(
|
|
142326
|
+
const plansDir = join47(homedir36(), ".letta", "plans");
|
|
141725
142327
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
141726
142328
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
141727
142329
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -141756,7 +142358,7 @@ ${guidance}`);
|
|
|
141756
142358
|
if (!hasUsablePlan) {
|
|
141757
142359
|
lastAutoHandledExitPlanToolCallIdRef.current = approval.toolCallId;
|
|
141758
142360
|
const planFilePath = activePlanPath ?? fallbackPlanPath;
|
|
141759
|
-
const plansDir = join47(
|
|
142361
|
+
const plansDir = join47(homedir36(), ".letta", "plans");
|
|
141760
142362
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
141761
142363
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
141762
142364
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -143168,8 +143770,8 @@ import {
|
|
|
143168
143770
|
readFileSync as readFileSync22,
|
|
143169
143771
|
writeFileSync as writeFileSync19
|
|
143170
143772
|
} from "node:fs";
|
|
143171
|
-
import { homedir as
|
|
143172
|
-
import { dirname as
|
|
143773
|
+
import { homedir as homedir37, platform as platform6 } from "node:os";
|
|
143774
|
+
import { dirname as dirname19, join as join48 } from "node:path";
|
|
143173
143775
|
function detectTerminalType2() {
|
|
143174
143776
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
143175
143777
|
return "cursor";
|
|
@@ -143201,7 +143803,7 @@ function getKeybindingsPath2(terminal) {
|
|
|
143201
143803
|
}[terminal];
|
|
143202
143804
|
const os8 = platform6();
|
|
143203
143805
|
if (os8 === "darwin") {
|
|
143204
|
-
return join48(
|
|
143806
|
+
return join48(homedir37(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
143205
143807
|
}
|
|
143206
143808
|
if (os8 === "win32") {
|
|
143207
143809
|
const appData = process.env.APPDATA;
|
|
@@ -143210,7 +143812,7 @@ function getKeybindingsPath2(terminal) {
|
|
|
143210
143812
|
return join48(appData, appName, "User", "keybindings.json");
|
|
143211
143813
|
}
|
|
143212
143814
|
if (os8 === "linux") {
|
|
143213
|
-
return join48(
|
|
143815
|
+
return join48(homedir37(), ".config", appName, "User", "keybindings.json");
|
|
143214
143816
|
}
|
|
143215
143817
|
return null;
|
|
143216
143818
|
}
|
|
@@ -143260,7 +143862,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
143260
143862
|
if (keybindingExists2(keybindingsPath)) {
|
|
143261
143863
|
return { success: true, alreadyExists: true };
|
|
143262
143864
|
}
|
|
143263
|
-
const parentDir =
|
|
143865
|
+
const parentDir = dirname19(keybindingsPath);
|
|
143264
143866
|
if (!existsSync38(parentDir)) {
|
|
143265
143867
|
mkdirSync24(parentDir, { recursive: true });
|
|
143266
143868
|
}
|
|
@@ -143367,10 +143969,10 @@ function getWezTermConfigPath2() {
|
|
|
143367
143969
|
if (existsSync38(xdgPath))
|
|
143368
143970
|
return xdgPath;
|
|
143369
143971
|
}
|
|
143370
|
-
const configPath = join48(
|
|
143972
|
+
const configPath = join48(homedir37(), ".config", "wezterm", "wezterm.lua");
|
|
143371
143973
|
if (existsSync38(configPath))
|
|
143372
143974
|
return configPath;
|
|
143373
|
-
return join48(
|
|
143975
|
+
return join48(homedir37(), ".wezterm.lua");
|
|
143374
143976
|
}
|
|
143375
143977
|
function wezTermDeleteFixExists2(configPath) {
|
|
143376
143978
|
if (!existsSync38(configPath))
|
|
@@ -143419,7 +144021,7 @@ return config`);
|
|
|
143419
144021
|
${WEZTERM_DELETE_FIX2}
|
|
143420
144022
|
`;
|
|
143421
144023
|
}
|
|
143422
|
-
const parentDir =
|
|
144024
|
+
const parentDir = dirname19(configPath);
|
|
143423
144025
|
if (!existsSync38(parentDir)) {
|
|
143424
144026
|
mkdirSync24(parentDir, { recursive: true });
|
|
143425
144027
|
}
|
|
@@ -143468,10 +144070,10 @@ __export(exports_settings2, {
|
|
|
143468
144070
|
loadProjectSettings: () => loadProjectSettings2,
|
|
143469
144071
|
getSetting: () => getSetting2
|
|
143470
144072
|
});
|
|
143471
|
-
import { homedir as
|
|
144073
|
+
import { homedir as homedir38 } from "node:os";
|
|
143472
144074
|
import { join as join49 } from "node:path";
|
|
143473
144075
|
function getSettingsPath2() {
|
|
143474
|
-
return join49(
|
|
144076
|
+
return join49(homedir38(), ".letta", "settings.json");
|
|
143475
144077
|
}
|
|
143476
144078
|
async function loadSettings2() {
|
|
143477
144079
|
const settingsPath = getSettingsPath2();
|
|
@@ -143993,10 +144595,10 @@ __export(exports_import2, {
|
|
|
143993
144595
|
});
|
|
143994
144596
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
143995
144597
|
import { chmod as chmod2, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile9 } from "node:fs/promises";
|
|
143996
|
-
import { dirname as
|
|
144598
|
+
import { dirname as dirname20, resolve as resolve31 } from "node:path";
|
|
143997
144599
|
async function importAgentFromFile2(options) {
|
|
143998
144600
|
const client = await getClient();
|
|
143999
|
-
const resolvedPath =
|
|
144601
|
+
const resolvedPath = resolve31(options.filePath);
|
|
144000
144602
|
const file = createReadStream2(resolvedPath);
|
|
144001
144603
|
const importResponse = await client.agents.importFile({
|
|
144002
144604
|
file,
|
|
@@ -144031,7 +144633,7 @@ async function extractSkillsFromAf2(afPath, destDir) {
|
|
|
144031
144633
|
return [];
|
|
144032
144634
|
}
|
|
144033
144635
|
for (const skill2 of afData.skills) {
|
|
144034
|
-
const skillDir =
|
|
144636
|
+
const skillDir = resolve31(destDir, skill2.name);
|
|
144035
144637
|
await mkdir8(skillDir, { recursive: true });
|
|
144036
144638
|
if (skill2.files) {
|
|
144037
144639
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -144051,8 +144653,8 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
144051
144653
|
}
|
|
144052
144654
|
}
|
|
144053
144655
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
144054
|
-
const fullPath =
|
|
144055
|
-
await mkdir8(
|
|
144656
|
+
const fullPath = resolve31(skillDir, filePath);
|
|
144657
|
+
await mkdir8(dirname20(fullPath), { recursive: true });
|
|
144056
144658
|
await writeFile9(fullPath, content, "utf-8");
|
|
144057
144659
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
144058
144660
|
if (isScript) {
|
|
@@ -144162,15 +144764,15 @@ __export(exports_memoryFilesystem2, {
|
|
|
144162
144764
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
144163
144765
|
});
|
|
144164
144766
|
import { existsSync as existsSync39, mkdirSync as mkdirSync25 } from "node:fs";
|
|
144165
|
-
import { homedir as
|
|
144767
|
+
import { homedir as homedir39 } from "node:os";
|
|
144166
144768
|
import { join as join50 } from "node:path";
|
|
144167
|
-
function getMemoryFilesystemRoot2(agentId, homeDir =
|
|
144769
|
+
function getMemoryFilesystemRoot2(agentId, homeDir = homedir39()) {
|
|
144168
144770
|
return join50(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
144169
144771
|
}
|
|
144170
|
-
function getMemorySystemDir2(agentId, homeDir =
|
|
144772
|
+
function getMemorySystemDir2(agentId, homeDir = homedir39()) {
|
|
144171
144773
|
return join50(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
144172
144774
|
}
|
|
144173
|
-
function ensureMemoryFilesystemDirs2(agentId, homeDir =
|
|
144775
|
+
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir39()) {
|
|
144174
144776
|
const root = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
144175
144777
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
144176
144778
|
if (!existsSync39(root)) {
|
|
@@ -148814,9 +149416,9 @@ async function runListenSubcommand(argv) {
|
|
|
148814
149416
|
|
|
148815
149417
|
// src/cli/subcommands/memfs.ts
|
|
148816
149418
|
await init_memoryGit();
|
|
148817
|
-
import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync15, rmSync as
|
|
149419
|
+
import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync15, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
|
|
148818
149420
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
148819
|
-
import { homedir as
|
|
149421
|
+
import { homedir as homedir23 } from "node:os";
|
|
148820
149422
|
import { join as join28 } from "node:path";
|
|
148821
149423
|
import { parseArgs as parseArgs7 } from "node:util";
|
|
148822
149424
|
function printUsage4() {
|
|
@@ -148862,10 +149464,10 @@ function parseMemfsArgs(argv) {
|
|
|
148862
149464
|
});
|
|
148863
149465
|
}
|
|
148864
149466
|
function getMemoryRoot(agentId) {
|
|
148865
|
-
return join28(
|
|
149467
|
+
return join28(homedir23(), ".letta", "agents", agentId, "memory");
|
|
148866
149468
|
}
|
|
148867
149469
|
function getAgentRoot(agentId) {
|
|
148868
|
-
return join28(
|
|
149470
|
+
return join28(homedir23(), ".letta", "agents", agentId);
|
|
148869
149471
|
}
|
|
148870
149472
|
function formatBackupTimestamp(date = new Date) {
|
|
148871
149473
|
const pad = (value) => String(value).padStart(2, "0");
|
|
@@ -149007,7 +149609,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
149007
149609
|
return 1;
|
|
149008
149610
|
}
|
|
149009
149611
|
const root = getMemoryRoot(agentId);
|
|
149010
|
-
|
|
149612
|
+
rmSync3(root, { recursive: true, force: true });
|
|
149011
149613
|
cpSync(backupPath, root, { recursive: true });
|
|
149012
149614
|
console.log(JSON.stringify({ restoredFrom: backupPath }, null, 2));
|
|
149013
149615
|
return 0;
|
|
@@ -149414,13 +150016,20 @@ async function runSubcommand(argv) {
|
|
|
149414
150016
|
}
|
|
149415
150017
|
|
|
149416
150018
|
// src/permissions/mode.ts
|
|
150019
|
+
init_memoryScope();
|
|
149417
150020
|
init_readOnlyShell();
|
|
149418
150021
|
init_shell_command_normalization();
|
|
149419
|
-
import { homedir as
|
|
149420
|
-
import { isAbsolute as
|
|
150022
|
+
import { homedir as homedir24 } from "node:os";
|
|
150023
|
+
import { isAbsolute as isAbsolute17, join as join29, relative as relative12 } from "node:path";
|
|
149421
150024
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
149422
150025
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
149423
150026
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
150027
|
+
function everyResolvedTargetIsWithinRoots2(candidatePaths, roots, workingDirectory) {
|
|
150028
|
+
return candidatePaths.length > 0 && candidatePaths.every((path23) => {
|
|
150029
|
+
const resolvedPath = resolveScopedTargetPath(path23, workingDirectory);
|
|
150030
|
+
return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
|
|
150031
|
+
});
|
|
150032
|
+
}
|
|
149424
150033
|
function getGlobalMode2() {
|
|
149425
150034
|
const global2 = globalThis;
|
|
149426
150035
|
if (!global2[MODE_KEY2]) {
|
|
@@ -149449,22 +150058,13 @@ function setGlobalModeBeforePlan2(value) {
|
|
|
149449
150058
|
global2[MODE_BEFORE_PLAN_KEY2] = value;
|
|
149450
150059
|
}
|
|
149451
150060
|
function resolvePlanTargetPath2(targetPath, workingDirectory) {
|
|
149452
|
-
|
|
149453
|
-
if (!trimmedPath)
|
|
149454
|
-
return null;
|
|
149455
|
-
if (trimmedPath.startsWith("~/")) {
|
|
149456
|
-
return resolve24(homedir23(), trimmedPath.slice(2));
|
|
149457
|
-
}
|
|
149458
|
-
if (isAbsolute16(trimmedPath)) {
|
|
149459
|
-
return resolve24(trimmedPath);
|
|
149460
|
-
}
|
|
149461
|
-
return resolve24(workingDirectory, trimmedPath);
|
|
150061
|
+
return resolveScopedTargetPath(targetPath, workingDirectory);
|
|
149462
150062
|
}
|
|
149463
150063
|
function isPathInPlansDir2(path23, plansDir) {
|
|
149464
150064
|
if (!path23.endsWith(".md"))
|
|
149465
150065
|
return false;
|
|
149466
150066
|
const rel = relative12(plansDir, path23);
|
|
149467
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
150067
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute17(rel);
|
|
149468
150068
|
}
|
|
149469
150069
|
function extractApplyPatchPaths2(input) {
|
|
149470
150070
|
const paths = [];
|
|
@@ -149651,7 +150251,7 @@ class PermissionModeManager2 {
|
|
|
149651
150251
|
return "allow";
|
|
149652
150252
|
}
|
|
149653
150253
|
if (writeTools.includes(toolName)) {
|
|
149654
|
-
const plansDir = join29(
|
|
150254
|
+
const plansDir = join29(homedir24(), ".letta", "plans");
|
|
149655
150255
|
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
149656
150256
|
let candidatePaths = [];
|
|
149657
150257
|
if ((toolName === "ApplyPatch" || toolName === "apply_patch" || toolName === "memory_apply_patch") && toolArgs?.input) {
|
|
@@ -149702,7 +150302,7 @@ class PermissionModeManager2 {
|
|
|
149702
150302
|
}
|
|
149703
150303
|
const planWritePath = extractPlanFileWritePathFromShellCommand2(command);
|
|
149704
150304
|
if (planWritePath) {
|
|
149705
|
-
const plansDir = join29(
|
|
150305
|
+
const plansDir = join29(homedir24(), ".letta", "plans");
|
|
149706
150306
|
const resolvedPath = resolvePlanTargetPath2(planWritePath, workingDirectory);
|
|
149707
150307
|
if (resolvedPath && isPathInPlansDir2(resolvedPath, plansDir)) {
|
|
149708
150308
|
return "allow";
|
|
@@ -149711,6 +150311,94 @@ class PermissionModeManager2 {
|
|
|
149711
150311
|
}
|
|
149712
150312
|
return "deny";
|
|
149713
150313
|
}
|
|
150314
|
+
case "memory": {
|
|
150315
|
+
const allowedMemoryRoots = resolveAllowedMemoryRoots().roots;
|
|
150316
|
+
const allowedReadOnlyTools = [
|
|
150317
|
+
"Read",
|
|
150318
|
+
"Glob",
|
|
150319
|
+
"Grep",
|
|
150320
|
+
"NotebookRead",
|
|
150321
|
+
"ViewImage",
|
|
150322
|
+
"view_image",
|
|
150323
|
+
"TaskOutput",
|
|
150324
|
+
"task_output",
|
|
150325
|
+
"Skill",
|
|
150326
|
+
"skill",
|
|
150327
|
+
"read_file",
|
|
150328
|
+
"list_dir",
|
|
150329
|
+
"grep_files",
|
|
150330
|
+
"ReadFile",
|
|
150331
|
+
"ListDir",
|
|
150332
|
+
"GrepFiles",
|
|
150333
|
+
"read_file_gemini",
|
|
150334
|
+
"glob_gemini",
|
|
150335
|
+
"list_directory",
|
|
150336
|
+
"search_file_content",
|
|
150337
|
+
"read_many_files",
|
|
150338
|
+
"ReadFileGemini",
|
|
150339
|
+
"GlobGemini",
|
|
150340
|
+
"ListDirectory",
|
|
150341
|
+
"SearchFileContent",
|
|
150342
|
+
"ReadManyFiles"
|
|
150343
|
+
];
|
|
150344
|
+
const writeTools = [
|
|
150345
|
+
"Write",
|
|
150346
|
+
"Edit",
|
|
150347
|
+
"MultiEdit",
|
|
150348
|
+
"NotebookEdit",
|
|
150349
|
+
"apply_patch",
|
|
150350
|
+
"ApplyPatch",
|
|
150351
|
+
"replace",
|
|
150352
|
+
"Replace",
|
|
150353
|
+
"write_file",
|
|
150354
|
+
"WriteFile",
|
|
150355
|
+
"write_file_gemini",
|
|
150356
|
+
"WriteFileGemini"
|
|
150357
|
+
];
|
|
150358
|
+
const shellTools = [
|
|
150359
|
+
"Bash",
|
|
150360
|
+
"shell",
|
|
150361
|
+
"Shell",
|
|
150362
|
+
"shell_command",
|
|
150363
|
+
"ShellCommand",
|
|
150364
|
+
"run_shell_command",
|
|
150365
|
+
"RunShellCommand",
|
|
150366
|
+
"run_shell_command_gemini",
|
|
150367
|
+
"RunShellCommandGemini"
|
|
150368
|
+
];
|
|
150369
|
+
if (allowedReadOnlyTools.includes(toolName)) {
|
|
150370
|
+
return "allow";
|
|
150371
|
+
}
|
|
150372
|
+
if (toolName === "memory_apply_patch") {
|
|
150373
|
+
return allowedMemoryRoots.length > 0 ? "allow" : "deny";
|
|
150374
|
+
}
|
|
150375
|
+
if (writeTools.includes(toolName)) {
|
|
150376
|
+
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
150377
|
+
let candidatePaths = [];
|
|
150378
|
+
if ((toolName === "ApplyPatch" || toolName === "apply_patch") && toolArgs?.input) {
|
|
150379
|
+
candidatePaths = extractApplyPatchPaths2(toolArgs.input);
|
|
150380
|
+
} else if (typeof targetPath === "string") {
|
|
150381
|
+
candidatePaths = [targetPath];
|
|
150382
|
+
}
|
|
150383
|
+
if (allowedMemoryRoots.length > 0 && everyResolvedTargetIsWithinRoots2(candidatePaths, allowedMemoryRoots, workingDirectory)) {
|
|
150384
|
+
return "allow";
|
|
150385
|
+
}
|
|
150386
|
+
return "deny";
|
|
150387
|
+
}
|
|
150388
|
+
if (shellTools.includes(toolName)) {
|
|
150389
|
+
const command = toolArgs?.command;
|
|
150390
|
+
if (command && isReadOnlyShellCommand(command, { allowExternalPaths: true })) {
|
|
150391
|
+
return "allow";
|
|
150392
|
+
}
|
|
150393
|
+
if (command && allowedMemoryRoots.length > 0 && isScopedMemoryShellCommand(command, allowedMemoryRoots, {
|
|
150394
|
+
workingDirectory
|
|
150395
|
+
})) {
|
|
150396
|
+
return "allow";
|
|
150397
|
+
}
|
|
150398
|
+
return "deny";
|
|
150399
|
+
}
|
|
150400
|
+
return "deny";
|
|
150401
|
+
}
|
|
149714
150402
|
case "default":
|
|
149715
150403
|
return null;
|
|
149716
150404
|
default:
|
|
@@ -149733,8 +150421,8 @@ await __promiseAll([
|
|
|
149733
150421
|
init_secrets()
|
|
149734
150422
|
]);
|
|
149735
150423
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
149736
|
-
import { homedir as
|
|
149737
|
-
import { join as join30, resolve as
|
|
150424
|
+
import { homedir as homedir25 } from "node:os";
|
|
150425
|
+
import { join as join30, resolve as resolve24 } from "node:path";
|
|
149738
150426
|
var DEFAULT_SETTINGS3 = {
|
|
149739
150427
|
lastAgent: null,
|
|
149740
150428
|
tokenStreaming: false,
|
|
@@ -150120,7 +150808,7 @@ class SettingsManager2 {
|
|
|
150120
150808
|
if (!this.settings)
|
|
150121
150809
|
return;
|
|
150122
150810
|
const settingsPath = this.getSettingsPath();
|
|
150123
|
-
const home = process.env.HOME ||
|
|
150811
|
+
const home = process.env.HOME || homedir25();
|
|
150124
150812
|
const dirPath = join30(home, ".letta");
|
|
150125
150813
|
try {
|
|
150126
150814
|
if (!exists(dirPath)) {
|
|
@@ -150181,14 +150869,14 @@ class SettingsManager2 {
|
|
|
150181
150869
|
}
|
|
150182
150870
|
}
|
|
150183
150871
|
getSettingsPath() {
|
|
150184
|
-
const home = process.env.HOME ||
|
|
150872
|
+
const home = process.env.HOME || homedir25();
|
|
150185
150873
|
return join30(home, ".letta", "settings.json");
|
|
150186
150874
|
}
|
|
150187
150875
|
getProjectSettingsPath(workingDirectory) {
|
|
150188
150876
|
return join30(workingDirectory, ".letta", "settings.json");
|
|
150189
150877
|
}
|
|
150190
150878
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
150191
|
-
return
|
|
150879
|
+
return resolve24(this.getProjectSettingsPath(workingDirectory)) === resolve24(this.getSettingsPath());
|
|
150192
150880
|
}
|
|
150193
150881
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
150194
150882
|
return join30(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -151150,8 +151838,8 @@ function acquireSwitchLock2() {
|
|
|
151150
151838
|
const lock = getSwitchLock2();
|
|
151151
151839
|
lock.refCount++;
|
|
151152
151840
|
if (lock.refCount === 1) {
|
|
151153
|
-
lock.promise = new Promise((
|
|
151154
|
-
lock.resolve =
|
|
151841
|
+
lock.promise = new Promise((resolve25) => {
|
|
151842
|
+
lock.resolve = resolve25;
|
|
151155
151843
|
});
|
|
151156
151844
|
}
|
|
151157
151845
|
}
|
|
@@ -151636,7 +152324,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151636
152324
|
printHelp();
|
|
151637
152325
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
151638
152326
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
151639
|
-
await new Promise((
|
|
152327
|
+
await new Promise((resolve32) => setTimeout(resolve32, helpDelayMs));
|
|
151640
152328
|
}
|
|
151641
152329
|
process.exit(0);
|
|
151642
152330
|
}
|
|
@@ -151858,9 +152546,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151858
152546
|
process.exit(1);
|
|
151859
152547
|
}
|
|
151860
152548
|
} else {
|
|
151861
|
-
const { resolve:
|
|
152549
|
+
const { resolve: resolve32 } = await import("path");
|
|
151862
152550
|
const { existsSync: existsSync40 } = await import("fs");
|
|
151863
|
-
const resolvedPath =
|
|
152551
|
+
const resolvedPath = resolve32(fromAfFile);
|
|
151864
152552
|
if (!existsSync40(resolvedPath)) {
|
|
151865
152553
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
151866
152554
|
process.exit(1);
|
|
@@ -151971,6 +152659,7 @@ Error: ${message}`);
|
|
|
151971
152659
|
"default",
|
|
151972
152660
|
"acceptEdits",
|
|
151973
152661
|
"plan",
|
|
152662
|
+
"memory",
|
|
151974
152663
|
"bypassPermissions"
|
|
151975
152664
|
];
|
|
151976
152665
|
if (validModes.includes(mode)) {
|
|
@@ -152735,4 +153424,4 @@ Error during initialization: ${message}`);
|
|
|
152735
153424
|
}
|
|
152736
153425
|
main();
|
|
152737
153426
|
|
|
152738
|
-
//# debugId=
|
|
153427
|
+
//# debugId=9A1A4B9B002D45C364756E2164756E21
|