@letta-ai/letta-code 0.21.11 → 0.21.12
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 +903 -327
- 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.12",
|
|
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.
|
|
@@ -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;
|
|
52742
|
+
}
|
|
52743
|
+
if (expandedPath.startsWith("~/") || expandedPath.startsWith("$HOME/") || expandedPath.startsWith('"$HOME/') || expandedPath.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(expandedPath)) {
|
|
52744
|
+
return normalizeScopedPath(expandedPath);
|
|
52745
|
+
}
|
|
52746
|
+
if (cwd2) {
|
|
52747
|
+
return normalizeScopedPath(resolve5(cwd2, expandedPath));
|
|
52748
|
+
}
|
|
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;
|
|
52567
52764
|
}
|
|
52568
|
-
|
|
52569
|
-
|
|
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
|
+
}
|
|
52570
52779
|
}
|
|
52571
|
-
|
|
52572
|
-
|
|
52780
|
+
return true;
|
|
52781
|
+
}
|
|
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;
|
|
52794
|
+
}
|
|
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 };
|
|
52573
52886
|
}
|
|
52574
|
-
return
|
|
52887
|
+
return {
|
|
52888
|
+
subcommand: null,
|
|
52889
|
+
worktreeSubcommand: null,
|
|
52890
|
+
resolvedCwd,
|
|
52891
|
+
isSafe: false
|
|
52892
|
+
};
|
|
52575
52893
|
}
|
|
52576
|
-
function
|
|
52577
|
-
|
|
52578
|
-
return prefixes.some((prefix) => resolved === prefix || resolved.startsWith(`${prefix}/`));
|
|
52894
|
+
function tokenLooksLikePath(token) {
|
|
52895
|
+
return token.includes("/") || token.includes("\\") || token === "." || token === ".." || token.startsWith("$") || token.startsWith("~") || token.startsWith("$HOME");
|
|
52579
52896
|
}
|
|
52580
|
-
function
|
|
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, "/");
|
|
@@ -65158,10 +65621,10 @@ __export(exports_skills, {
|
|
|
65158
65621
|
});
|
|
65159
65622
|
import { existsSync as existsSync17 } from "node:fs";
|
|
65160
65623
|
import { readdir as readdir4, readFile as readFile5, realpath as realpath2, stat as stat4 } from "node:fs/promises";
|
|
65161
|
-
import { dirname as
|
|
65624
|
+
import { dirname as dirname9, join as join19 } from "node:path";
|
|
65162
65625
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
65163
65626
|
function getBundledSkillsPath() {
|
|
65164
|
-
const thisDir =
|
|
65627
|
+
const thisDir = dirname9(fileURLToPath7(import.meta.url));
|
|
65165
65628
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
65166
65629
|
return join19(thisDir, "../skills/builtin");
|
|
65167
65630
|
}
|
|
@@ -65363,10 +65826,10 @@ var init_skillContentRegistry = __esm(() => {
|
|
|
65363
65826
|
// src/tools/impl/Skill.ts
|
|
65364
65827
|
import { readdirSync as readdirSync7 } from "node:fs";
|
|
65365
65828
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
65366
|
-
import { dirname as
|
|
65829
|
+
import { dirname as dirname10, join as join20 } from "node:path";
|
|
65367
65830
|
function hasAdditionalFiles(skillMdPath) {
|
|
65368
65831
|
try {
|
|
65369
|
-
const skillDir =
|
|
65832
|
+
const skillDir = dirname10(skillMdPath);
|
|
65370
65833
|
const entries = readdirSync7(skillDir);
|
|
65371
65834
|
return entries.some((e) => e.toUpperCase() !== "SKILL.MD");
|
|
65372
65835
|
} catch {
|
|
@@ -65425,7 +65888,7 @@ async function skill(args) {
|
|
|
65425
65888
|
const agentId = getCurrentAgentId();
|
|
65426
65889
|
const skillsDir = await getResolvedSkillsDir();
|
|
65427
65890
|
const { content: skillContent, path: skillPath } = await readSkillContent(skillName, skillsDir, agentId);
|
|
65428
|
-
const skillDir =
|
|
65891
|
+
const skillDir = dirname10(skillPath);
|
|
65429
65892
|
const hasExtras = hasAdditionalFiles(skillPath);
|
|
65430
65893
|
const processedContent = hasExtras ? skillContent.replace(/<SKILL_DIR>/g, skillDir) : skillContent;
|
|
65431
65894
|
const dirHeader = hasExtras ? `# Skill Directory: ${skillDir}
|
|
@@ -66009,15 +66472,32 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
|
|
|
66009
66472
|
const inheritedApiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
66010
66473
|
const inheritedBaseUrl = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL;
|
|
66011
66474
|
const subagentWorkingDirectory = resolveSubagentWorkingDirectory();
|
|
66475
|
+
const inheritedMemoryRoots = resolveAllowedMemoryRoots();
|
|
66476
|
+
const childEnv = {
|
|
66477
|
+
...process.env,
|
|
66478
|
+
...inheritedApiKey && { LETTA_API_KEY: inheritedApiKey },
|
|
66479
|
+
...inheritedBaseUrl && { LETTA_BASE_URL: inheritedBaseUrl },
|
|
66480
|
+
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
66481
|
+
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
66482
|
+
};
|
|
66483
|
+
if (config.permissionMode === "memory") {
|
|
66484
|
+
if (inheritedMemoryRoots.primaryRoot) {
|
|
66485
|
+
childEnv.MEMORY_DIR = inheritedMemoryRoots.primaryRoot;
|
|
66486
|
+
childEnv.LETTA_MEMORY_DIR = inheritedMemoryRoots.primaryRoot;
|
|
66487
|
+
} else {
|
|
66488
|
+
delete childEnv.MEMORY_DIR;
|
|
66489
|
+
delete childEnv.LETTA_MEMORY_DIR;
|
|
66490
|
+
}
|
|
66491
|
+
const parentMemoryDir = process.env.MEMORY_DIR || process.env.LETTA_MEMORY_DIR;
|
|
66492
|
+
if (parentMemoryDir && parentMemoryDir.trim().length > 0) {
|
|
66493
|
+
childEnv.PARENT_MEMORY_DIR = parentMemoryDir;
|
|
66494
|
+
} else {
|
|
66495
|
+
delete childEnv.PARENT_MEMORY_DIR;
|
|
66496
|
+
}
|
|
66497
|
+
}
|
|
66012
66498
|
const proc2 = spawn4(launcher.command, launcher.args, {
|
|
66013
66499
|
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
|
-
}
|
|
66500
|
+
env: childEnv
|
|
66021
66501
|
});
|
|
66022
66502
|
proc2.once("spawn", () => {
|
|
66023
66503
|
updateSubagent(subagentId, { status: "running" });
|
|
@@ -66196,6 +66676,7 @@ var init_manager2 = __esm(async () => {
|
|
|
66196
66676
|
init_subagentState();
|
|
66197
66677
|
init_constants();
|
|
66198
66678
|
init_cli();
|
|
66679
|
+
init_memoryScope();
|
|
66199
66680
|
init_mode();
|
|
66200
66681
|
init_session();
|
|
66201
66682
|
init_context();
|
|
@@ -69706,8 +70187,8 @@ function matchesFilePattern(query, pattern, workingDirectory, options) {
|
|
|
69706
70187
|
globPattern = globPattern.slice(2);
|
|
69707
70188
|
}
|
|
69708
70189
|
if (globPattern.startsWith("~/")) {
|
|
69709
|
-
const
|
|
69710
|
-
globPattern = globPattern.replace(/^~/,
|
|
70190
|
+
const homedir17 = __require("node:os").homedir();
|
|
70191
|
+
globPattern = globPattern.replace(/^~/, homedir17);
|
|
69711
70192
|
}
|
|
69712
70193
|
globPattern = normalizeAbsolutePattern(globPattern, workingDirectory);
|
|
69713
70194
|
const windowsContext = isWindowsContext(workingDirectory);
|
|
@@ -70220,7 +70701,7 @@ function getDefaultDecision(toolName, toolArgs) {
|
|
|
70220
70701
|
}
|
|
70221
70702
|
if (toolName === "Task" || toolName === "task") {
|
|
70222
70703
|
const subagentType = typeof toolArgs?.subagent_type === "string" ? toolArgs.subagent_type : "";
|
|
70223
|
-
if (
|
|
70704
|
+
if (SAFE_AUTO_APPROVE_SUBAGENT_TYPES.has(subagentType)) {
|
|
70224
70705
|
return "allow";
|
|
70225
70706
|
}
|
|
70226
70707
|
return "ask";
|
|
@@ -70251,7 +70732,7 @@ async function checkPermissionWithHooks(toolName, toolArgs, permissions, working
|
|
|
70251
70732
|
}
|
|
70252
70733
|
return result;
|
|
70253
70734
|
}
|
|
70254
|
-
var WORKING_DIRECTORY_TOOLS_V2, WORKING_DIRECTORY_TOOLS_V1, READ_ONLY_SHELL_TOOLS, FILE_TOOLS_V2, FILE_TOOLS_V1,
|
|
70735
|
+
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
70736
|
var init_checker = __esm(async () => {
|
|
70256
70737
|
init_context();
|
|
70257
70738
|
init_canonical();
|
|
@@ -70318,7 +70799,7 @@ var init_checker = __esm(async () => {
|
|
|
70318
70799
|
"read_many_files",
|
|
70319
70800
|
"ReadManyFiles"
|
|
70320
70801
|
];
|
|
70321
|
-
|
|
70802
|
+
SAFE_AUTO_APPROVE_SUBAGENT_TYPES = new Set([
|
|
70322
70803
|
"explore",
|
|
70323
70804
|
"Explore",
|
|
70324
70805
|
"recall",
|
|
@@ -70336,10 +70817,10 @@ __export(exports_loader, {
|
|
|
70336
70817
|
loadPermissions: () => loadPermissions,
|
|
70337
70818
|
getUserSettingsPaths: () => getUserSettingsPaths
|
|
70338
70819
|
});
|
|
70339
|
-
import { homedir as
|
|
70820
|
+
import { homedir as homedir17 } from "node:os";
|
|
70340
70821
|
import { join as join21 } from "node:path";
|
|
70341
70822
|
function getUserSettingsPaths(options = {}) {
|
|
70342
|
-
const homeDir = options.homeDir ||
|
|
70823
|
+
const homeDir = options.homeDir || homedir17();
|
|
70343
70824
|
const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join21(homeDir, ".config");
|
|
70344
70825
|
return {
|
|
70345
70826
|
canonical: join21(homeDir, ".letta", "settings.json"),
|
|
@@ -70461,8 +70942,8 @@ var exports_analyzer = {};
|
|
|
70461
70942
|
__export(exports_analyzer, {
|
|
70462
70943
|
analyzeApprovalContext: () => analyzeApprovalContext
|
|
70463
70944
|
});
|
|
70464
|
-
import { homedir as
|
|
70465
|
-
import { dirname as
|
|
70945
|
+
import { homedir as homedir18 } from "node:os";
|
|
70946
|
+
import { dirname as dirname12, relative as relative8, resolve as resolve22, win32 as win322 } from "node:path";
|
|
70466
70947
|
function normalizeOsPath(path20) {
|
|
70467
70948
|
return path20.replace(/\\/g, "/");
|
|
70468
70949
|
}
|
|
@@ -70488,7 +70969,7 @@ function isPathWithinDirectory(path20, directory) {
|
|
|
70488
70969
|
return !relativePath.startsWith("../") && relativePath !== ".." && !relativePath.startsWith("/") && !/^[a-zA-Z]:\//.test(relativePath);
|
|
70489
70970
|
}
|
|
70490
70971
|
function dirnameForContext(path20) {
|
|
70491
|
-
return isWindowsPath(path20) ? win322.dirname(path20) :
|
|
70972
|
+
return isWindowsPath(path20) ? win322.dirname(path20) : dirname12(path20);
|
|
70492
70973
|
}
|
|
70493
70974
|
function formatAbsoluteRulePath(path20) {
|
|
70494
70975
|
const normalized = normalizeOsPath(path20).replace(/\/+$/, "");
|
|
@@ -70498,7 +70979,7 @@ function formatAbsoluteRulePath(path20) {
|
|
|
70498
70979
|
return `//${normalized.replace(/^\/+/, "")}`;
|
|
70499
70980
|
}
|
|
70500
70981
|
function formatDisplayPath(path20) {
|
|
70501
|
-
return normalizeOsPath(path20).replace(normalizeOsPath(
|
|
70982
|
+
return normalizeOsPath(path20).replace(normalizeOsPath(homedir18()), "~");
|
|
70502
70983
|
}
|
|
70503
70984
|
function analyzeApprovalContext(toolName, toolArgs, workingDirectory) {
|
|
70504
70985
|
const canonicalTool = canonicalToolName(toolName);
|
|
@@ -70549,7 +71030,7 @@ function analyzeReadApproval(filePath, workingDir) {
|
|
|
70549
71030
|
};
|
|
70550
71031
|
}
|
|
70551
71032
|
const relativePath = normalizeOsPath(relativePathForContext(workingDir, absolutePath));
|
|
70552
|
-
const relativeDir =
|
|
71033
|
+
const relativeDir = dirname12(relativePath);
|
|
70553
71034
|
const pattern = relativeDir === "." || relativeDir === "" ? "**" : `${relativeDir}/**`;
|
|
70554
71035
|
return {
|
|
70555
71036
|
recommendedRule: `Read(${pattern})`,
|
|
@@ -70692,7 +71173,7 @@ function detectSkillScript(command, workingDir) {
|
|
|
70692
71173
|
return null;
|
|
70693
71174
|
}
|
|
70694
71175
|
const normalizedWorkingDir = normalizePathSeparators(workingDir).replace(/\/$/, "");
|
|
70695
|
-
const normalizedHomeDir = normalizePathSeparators(
|
|
71176
|
+
const normalizedHomeDir = normalizePathSeparators(homedir18()).replace(/\/$/, "");
|
|
70696
71177
|
const detect = (source, regex2) => {
|
|
70697
71178
|
for (const candidate of pathCandidates) {
|
|
70698
71179
|
const match3 = candidate.match(regex2);
|
|
@@ -72224,15 +72705,15 @@ __export(exports_memoryFilesystem, {
|
|
|
72224
72705
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR
|
|
72225
72706
|
});
|
|
72226
72707
|
import { existsSync as existsSync18, mkdirSync as mkdirSync13 } from "node:fs";
|
|
72227
|
-
import { homedir as
|
|
72708
|
+
import { homedir as homedir19 } from "node:os";
|
|
72228
72709
|
import { join as join22 } from "node:path";
|
|
72229
|
-
function getMemoryFilesystemRoot(agentId, homeDir =
|
|
72710
|
+
function getMemoryFilesystemRoot(agentId, homeDir = homedir19()) {
|
|
72230
72711
|
return join22(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
|
|
72231
72712
|
}
|
|
72232
|
-
function getMemorySystemDir(agentId, homeDir =
|
|
72713
|
+
function getMemorySystemDir(agentId, homeDir = homedir19()) {
|
|
72233
72714
|
return join22(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
|
|
72234
72715
|
}
|
|
72235
|
-
function ensureMemoryFilesystemDirs(agentId, homeDir =
|
|
72716
|
+
function ensureMemoryFilesystemDirs(agentId, homeDir = homedir19()) {
|
|
72236
72717
|
const root = getMemoryFilesystemRoot(agentId, homeDir);
|
|
72237
72718
|
const systemDir = getMemorySystemDir(agentId, homeDir);
|
|
72238
72719
|
if (!existsSync18(root)) {
|
|
@@ -75298,7 +75779,7 @@ import {
|
|
|
75298
75779
|
readFile as readFile7,
|
|
75299
75780
|
writeFile as writeFile4
|
|
75300
75781
|
} from "node:fs/promises";
|
|
75301
|
-
import { homedir as
|
|
75782
|
+
import { homedir as homedir20, tmpdir as tmpdir3 } from "node:os";
|
|
75302
75783
|
import { join as join25 } from "node:path";
|
|
75303
75784
|
function buildReflectionSubagentPrompt(input) {
|
|
75304
75785
|
const lines = [];
|
|
@@ -75492,7 +75973,7 @@ function getTranscriptRoot() {
|
|
|
75492
75973
|
if (envRoot) {
|
|
75493
75974
|
return envRoot;
|
|
75494
75975
|
}
|
|
75495
|
-
return join25(
|
|
75976
|
+
return join25(homedir20(), ".letta", DEFAULT_TRANSCRIPT_DIR);
|
|
75496
75977
|
}
|
|
75497
75978
|
function defaultState() {
|
|
75498
75979
|
return { auto_cursor_line: 0 };
|
|
@@ -75681,7 +76162,7 @@ import {
|
|
|
75681
76162
|
unlinkSync as unlinkSync7,
|
|
75682
76163
|
writeFileSync as writeFileSync11
|
|
75683
76164
|
} from "node:fs";
|
|
75684
|
-
import { homedir as
|
|
76165
|
+
import { homedir as homedir21 } from "node:os";
|
|
75685
76166
|
import { join as join26 } from "node:path";
|
|
75686
76167
|
function truncateStr(value, maxLen) {
|
|
75687
76168
|
if (value === null || value === undefined)
|
|
@@ -75822,7 +76303,7 @@ class ChunkLog {
|
|
|
75822
76303
|
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
|
|
75823
76304
|
var init_chunkLog = __esm(() => {
|
|
75824
76305
|
init_debug();
|
|
75825
|
-
LOG_BASE_DIR = join26(
|
|
76306
|
+
LOG_BASE_DIR = join26(homedir21(), ".letta", "logs", "chunk-logs");
|
|
75826
76307
|
chunkLog = new ChunkLog;
|
|
75827
76308
|
});
|
|
75828
76309
|
|
|
@@ -76839,6 +77320,7 @@ var init_engine = __esm(async () => {
|
|
|
76839
77320
|
default: "Normal approval flow.",
|
|
76840
77321
|
acceptEdits: "File edits auto-approved.",
|
|
76841
77322
|
plan: "Read-only mode. Focus on exploration and planning.",
|
|
77323
|
+
memory: "Memory-scoped mode. Reads are broad; mutations are limited to allowed memory roots.",
|
|
76842
77324
|
bypassPermissions: "All tools auto-approved. Bias toward action."
|
|
76843
77325
|
};
|
|
76844
77326
|
sharedReminderProviders = {
|
|
@@ -76951,10 +77433,10 @@ var init_constants2 = __esm(() => {
|
|
|
76951
77433
|
// src/websocket/listener/remote-settings.ts
|
|
76952
77434
|
import { existsSync as existsSync21, readFileSync as readFileSync12 } from "node:fs";
|
|
76953
77435
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
76954
|
-
import { homedir as
|
|
77436
|
+
import { homedir as homedir22 } from "node:os";
|
|
76955
77437
|
import path20 from "node:path";
|
|
76956
77438
|
function getRemoteSettingsPath() {
|
|
76957
|
-
return path20.join(
|
|
77439
|
+
return path20.join(homedir22(), ".letta", "remote-settings.json");
|
|
76958
77440
|
}
|
|
76959
77441
|
function loadRemoteSettings() {
|
|
76960
77442
|
if (_cache !== null) {
|
|
@@ -76998,7 +77480,7 @@ function saveRemoteSettings(updates) {
|
|
|
76998
77480
|
}
|
|
76999
77481
|
function loadLegacyCwdCache() {
|
|
77000
77482
|
try {
|
|
77001
|
-
const legacyPath = path20.join(
|
|
77483
|
+
const legacyPath = path20.join(homedir22(), ".letta", "cwd-cache.json");
|
|
77002
77484
|
if (!existsSync21(legacyPath))
|
|
77003
77485
|
return {};
|
|
77004
77486
|
const raw = readFileSync12(legacyPath, "utf-8");
|
|
@@ -78673,7 +79155,7 @@ __export(exports_diff, {
|
|
|
78673
79155
|
ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
|
|
78674
79156
|
ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
|
|
78675
79157
|
});
|
|
78676
|
-
import { basename as
|
|
79158
|
+
import { basename as basename3 } from "node:path";
|
|
78677
79159
|
function readFileOrNull(p) {
|
|
78678
79160
|
try {
|
|
78679
79161
|
return __require("node:fs").readFileSync(p, "utf-8");
|
|
@@ -78697,7 +79179,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
|
|
|
78697
79179
|
return { ok: true, out: content.split(oldStr).join(newStr) };
|
|
78698
79180
|
}
|
|
78699
79181
|
function computeAdvancedDiff(input, opts) {
|
|
78700
|
-
const fileName =
|
|
79182
|
+
const fileName = basename3(input.filePath || "");
|
|
78701
79183
|
const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
|
|
78702
79184
|
if (fileContent === null && input.kind !== "write") {
|
|
78703
79185
|
return { mode: "fallback", reason: "File not readable" };
|
|
@@ -78763,7 +79245,7 @@ function computeAdvancedDiff(input, opts) {
|
|
|
78763
79245
|
return { mode: "advanced", fileName, oldStr, newStr, hunks };
|
|
78764
79246
|
}
|
|
78765
79247
|
function parsePatchToAdvancedDiff(patchLines, filePath) {
|
|
78766
|
-
const fileName =
|
|
79248
|
+
const fileName = basename3(filePath);
|
|
78767
79249
|
const hunks = [];
|
|
78768
79250
|
let currentHunk = null;
|
|
78769
79251
|
let oldLine = 1;
|
|
@@ -79090,7 +79572,7 @@ var init_formatArgsDisplay = __esm(async () => {
|
|
|
79090
79572
|
});
|
|
79091
79573
|
|
|
79092
79574
|
// src/helpers/diffPreview.ts
|
|
79093
|
-
import path21, { basename as
|
|
79575
|
+
import path21, { basename as basename4 } from "node:path";
|
|
79094
79576
|
function parseHunkLinePrefix(raw) {
|
|
79095
79577
|
if (raw.length === 0) {
|
|
79096
79578
|
return { type: "context", content: "" };
|
|
@@ -79196,7 +79678,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79196
79678
|
filePath: resolvedFilePath,
|
|
79197
79679
|
content: toolArgs.content || ""
|
|
79198
79680
|
});
|
|
79199
|
-
previews.push(toDiffPreview(result,
|
|
79681
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79200
79682
|
}
|
|
79201
79683
|
} else if (isFileEditTool2(toolName)) {
|
|
79202
79684
|
const filePath = toolArgs.file_path;
|
|
@@ -79208,7 +79690,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79208
79690
|
filePath: resolvedFilePath,
|
|
79209
79691
|
edits: toolArgs.edits
|
|
79210
79692
|
});
|
|
79211
|
-
previews.push(toDiffPreview(result,
|
|
79693
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79212
79694
|
} else {
|
|
79213
79695
|
const result = computeAdvancedDiff2({
|
|
79214
79696
|
kind: "edit",
|
|
@@ -79217,7 +79699,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79217
79699
|
newString: toolArgs.new_string || "",
|
|
79218
79700
|
replaceAll: toolArgs.replace_all
|
|
79219
79701
|
});
|
|
79220
|
-
previews.push(toDiffPreview(result,
|
|
79702
|
+
previews.push(toDiffPreview(result, basename4(filePath)));
|
|
79221
79703
|
}
|
|
79222
79704
|
}
|
|
79223
79705
|
} else if (isPatchTool2(toolName) && toolArgs.input) {
|
|
@@ -79226,7 +79708,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79226
79708
|
if (op.kind === "add" || op.kind === "update") {
|
|
79227
79709
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
79228
79710
|
if (result) {
|
|
79229
|
-
previews.push(toDiffPreview(result,
|
|
79711
|
+
previews.push(toDiffPreview(result, basename4(op.path)));
|
|
79230
79712
|
}
|
|
79231
79713
|
}
|
|
79232
79714
|
}
|
|
@@ -79236,7 +79718,7 @@ async function computeDiffPreviews(toolName, toolArgs, workingDirectory = proces
|
|
|
79236
79718
|
if (op.kind === "add" || op.kind === "update") {
|
|
79237
79719
|
const result = parsePatchToAdvancedDiff2(op.patchLines, op.path);
|
|
79238
79720
|
if (result) {
|
|
79239
|
-
previews.push(toDiffPreview(result,
|
|
79721
|
+
previews.push(toDiffPreview(result, basename4(op.path)));
|
|
79240
79722
|
}
|
|
79241
79723
|
}
|
|
79242
79724
|
}
|
|
@@ -81760,18 +82242,24 @@ function buildDeviceStatus(runtime, params) {
|
|
|
81760
82242
|
function buildLoopStatus(runtime, params) {
|
|
81761
82243
|
const listener = getListenerRuntime(runtime);
|
|
81762
82244
|
if (!listener) {
|
|
81763
|
-
return {
|
|
82245
|
+
return {
|
|
82246
|
+
status: "WAITING_ON_INPUT",
|
|
82247
|
+
active_run_ids: [],
|
|
82248
|
+
plan_file_path: null
|
|
82249
|
+
};
|
|
81764
82250
|
}
|
|
81765
82251
|
const scope = getScopeForRuntime(runtime, params);
|
|
81766
82252
|
const scopedAgentId = resolveScopedAgentId(listener, scope);
|
|
81767
82253
|
const scopedConversationId = resolveScopedConversationId(listener, scope);
|
|
82254
|
+
const conversationPermissionModeState = getConversationPermissionModeState(listener, scopedAgentId, scopedConversationId);
|
|
81768
82255
|
const conversationRuntime = getConversationRuntime(listener, scopedAgentId, scopedConversationId);
|
|
81769
82256
|
const interruptedCacheActive = hasInterruptedCacheForScope(listener, scope);
|
|
81770
82257
|
const recovered = getRecoveredApprovalStateForScope(listener, scope);
|
|
81771
82258
|
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
82259
|
return {
|
|
81773
82260
|
status,
|
|
81774
|
-
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : []
|
|
82261
|
+
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : [],
|
|
82262
|
+
plan_file_path: conversationPermissionModeState.mode === "plan" ? conversationPermissionModeState.planFilePath : null
|
|
81775
82263
|
};
|
|
81776
82264
|
}
|
|
81777
82265
|
function buildQueueSnapshot(runtime, params) {
|
|
@@ -83605,7 +84093,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
83605
84093
|
symlinkSync,
|
|
83606
84094
|
unlinkSync: unlinkSync8
|
|
83607
84095
|
} = await import("node:fs");
|
|
83608
|
-
const { basename:
|
|
84096
|
+
const { basename: basename5, join: join28 } = await import("node:path");
|
|
83609
84097
|
const lettaHome = process.env.LETTA_HOME || join28(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
83610
84098
|
const globalSkillsDir = join28(lettaHome, "skills");
|
|
83611
84099
|
if (parsed.type === "skill_enable") {
|
|
@@ -83629,7 +84117,7 @@ async function handleSkillCommand(parsed, socket) {
|
|
|
83629
84117
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
83630
84118
|
return true;
|
|
83631
84119
|
}
|
|
83632
|
-
const linkName =
|
|
84120
|
+
const linkName = basename5(parsed.skill_path);
|
|
83633
84121
|
const linkPath = join28(globalSkillsDir, linkName);
|
|
83634
84122
|
mkdirSync15(globalSkillsDir, { recursive: true });
|
|
83635
84123
|
if (existsSync22(linkPath)) {
|
|
@@ -85349,7 +85837,7 @@ import {
|
|
|
85349
85837
|
readFileSync as readFileSync14,
|
|
85350
85838
|
unlinkSync as unlinkSync8
|
|
85351
85839
|
} from "node:fs";
|
|
85352
|
-
import { homedir as
|
|
85840
|
+
import { homedir as homedir26 } from "node:os";
|
|
85353
85841
|
import { join as join31 } from "node:path";
|
|
85354
85842
|
import { format as format2 } from "node:util";
|
|
85355
85843
|
function isDebugEnabled2() {
|
|
@@ -85455,7 +85943,7 @@ function debugWarn2(prefix, message, ...args) {
|
|
|
85455
85943
|
}
|
|
85456
85944
|
var DEBUG_LOG_DIR2, MAX_SESSION_FILES3 = 5, DEFAULT_TAIL_LINES2 = 50, debugLogFile2;
|
|
85457
85945
|
var init_debug2 = __esm(() => {
|
|
85458
|
-
DEBUG_LOG_DIR2 = join31(
|
|
85946
|
+
DEBUG_LOG_DIR2 = join31(homedir26(), ".letta", "logs", "debug");
|
|
85459
85947
|
debugLogFile2 = new DebugLogFile2;
|
|
85460
85948
|
});
|
|
85461
85949
|
|
|
@@ -85484,10 +85972,10 @@ __export(exports_skills2, {
|
|
|
85484
85972
|
});
|
|
85485
85973
|
import { existsSync as existsSync24 } from "node:fs";
|
|
85486
85974
|
import { readdir as readdir7, readFile as readFile8, realpath as realpath4, stat as stat6 } from "node:fs/promises";
|
|
85487
|
-
import { dirname as
|
|
85975
|
+
import { dirname as dirname13, join as join32 } from "node:path";
|
|
85488
85976
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
85489
85977
|
function getBundledSkillsPath2() {
|
|
85490
|
-
const thisDir =
|
|
85978
|
+
const thisDir = dirname13(fileURLToPath8(import.meta.url));
|
|
85491
85979
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
85492
85980
|
return join32(thisDir, "../skills/builtin");
|
|
85493
85981
|
}
|
|
@@ -85683,12 +86171,12 @@ import {
|
|
|
85683
86171
|
writeFileSync as fsWriteFileSync2,
|
|
85684
86172
|
mkdirSync as mkdirSync17
|
|
85685
86173
|
} from "node:fs";
|
|
85686
|
-
import { dirname as
|
|
86174
|
+
import { dirname as dirname14 } from "node:path";
|
|
85687
86175
|
async function readFile9(path23) {
|
|
85688
86176
|
return fsReadFileSync2(path23, { encoding: "utf-8" });
|
|
85689
86177
|
}
|
|
85690
86178
|
async function writeFile7(path23, content) {
|
|
85691
|
-
const dir =
|
|
86179
|
+
const dir = dirname14(path23);
|
|
85692
86180
|
if (!existsSync25(dir)) {
|
|
85693
86181
|
mkdirSync17(dir, { recursive: true });
|
|
85694
86182
|
}
|
|
@@ -85733,7 +86221,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85733
86221
|
}
|
|
85734
86222
|
const wasRaw = process.stdin.isRaw;
|
|
85735
86223
|
const wasFlowing = process.stdin.readableFlowing;
|
|
85736
|
-
return new Promise((
|
|
86224
|
+
return new Promise((resolve25) => {
|
|
85737
86225
|
let response = "";
|
|
85738
86226
|
let resolved = false;
|
|
85739
86227
|
const cleanup = () => {
|
|
@@ -85750,7 +86238,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85750
86238
|
};
|
|
85751
86239
|
const timeout = setTimeout(() => {
|
|
85752
86240
|
cleanup();
|
|
85753
|
-
|
|
86241
|
+
resolve25(null);
|
|
85754
86242
|
}, timeoutMs);
|
|
85755
86243
|
const onData = (data) => {
|
|
85756
86244
|
response += data.toString();
|
|
@@ -85760,7 +86248,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85760
86248
|
if (match3) {
|
|
85761
86249
|
clearTimeout(timeout);
|
|
85762
86250
|
cleanup();
|
|
85763
|
-
|
|
86251
|
+
resolve25({
|
|
85764
86252
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
85765
86253
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
85766
86254
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -85775,7 +86263,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85775
86263
|
} catch {
|
|
85776
86264
|
clearTimeout(timeout);
|
|
85777
86265
|
cleanup();
|
|
85778
|
-
|
|
86266
|
+
resolve25(null);
|
|
85779
86267
|
}
|
|
85780
86268
|
});
|
|
85781
86269
|
}
|
|
@@ -86984,10 +87472,10 @@ __export(exports_setup, {
|
|
|
86984
87472
|
runSetup: () => runSetup
|
|
86985
87473
|
});
|
|
86986
87474
|
async function runSetup() {
|
|
86987
|
-
return new Promise((
|
|
87475
|
+
return new Promise((resolve26) => {
|
|
86988
87476
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
86989
87477
|
onComplete: () => {
|
|
86990
|
-
|
|
87478
|
+
resolve26();
|
|
86991
87479
|
}
|
|
86992
87480
|
}));
|
|
86993
87481
|
waitUntilExit().catch((error) => {
|
|
@@ -87517,10 +88005,10 @@ __export(exports_import, {
|
|
|
87517
88005
|
});
|
|
87518
88006
|
import { createReadStream } from "node:fs";
|
|
87519
88007
|
import { chmod, mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
|
|
87520
|
-
import { dirname as
|
|
88008
|
+
import { dirname as dirname15, resolve as resolve26 } from "node:path";
|
|
87521
88009
|
async function importAgentFromFile(options) {
|
|
87522
88010
|
const client = await getClient();
|
|
87523
|
-
const resolvedPath =
|
|
88011
|
+
const resolvedPath = resolve26(options.filePath);
|
|
87524
88012
|
const file = createReadStream(resolvedPath);
|
|
87525
88013
|
const importResponse = await client.agents.importFile({
|
|
87526
88014
|
file,
|
|
@@ -87555,7 +88043,7 @@ async function extractSkillsFromAf(afPath, destDir) {
|
|
|
87555
88043
|
return [];
|
|
87556
88044
|
}
|
|
87557
88045
|
for (const skill2 of afData.skills) {
|
|
87558
|
-
const skillDir =
|
|
88046
|
+
const skillDir = resolve26(destDir, skill2.name);
|
|
87559
88047
|
await mkdir7(skillDir, { recursive: true });
|
|
87560
88048
|
if (skill2.files) {
|
|
87561
88049
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -87575,8 +88063,8 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
87575
88063
|
}
|
|
87576
88064
|
}
|
|
87577
88065
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
87578
|
-
const fullPath =
|
|
87579
|
-
await mkdir7(
|
|
88066
|
+
const fullPath = resolve26(skillDir, filePath);
|
|
88067
|
+
await mkdir7(dirname15(fullPath), { recursive: true });
|
|
87580
88068
|
await writeFile8(fullPath, content, "utf-8");
|
|
87581
88069
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
87582
88070
|
if (isScript) {
|
|
@@ -87882,12 +88370,12 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
87882
88370
|
};
|
|
87883
88371
|
}
|
|
87884
88372
|
async function flushAndExit(code) {
|
|
87885
|
-
const flushWritable = (stream2) => new Promise((
|
|
88373
|
+
const flushWritable = (stream2) => new Promise((resolve27) => {
|
|
87886
88374
|
if (stream2.destroyed || stream2.writableEnded) {
|
|
87887
|
-
|
|
88375
|
+
resolve27();
|
|
87888
88376
|
return;
|
|
87889
88377
|
}
|
|
87890
|
-
stream2.write("", () =>
|
|
88378
|
+
stream2.write("", () => resolve27());
|
|
87891
88379
|
});
|
|
87892
88380
|
await Promise.allSettled([
|
|
87893
88381
|
flushWritable(process.stdout),
|
|
@@ -87913,7 +88401,8 @@ async function handleHeadlessCommand(parsedArgs, model, skillsDirectoryOverride,
|
|
|
87913
88401
|
"default",
|
|
87914
88402
|
"acceptEdits",
|
|
87915
88403
|
"bypassPermissions",
|
|
87916
|
-
"plan"
|
|
88404
|
+
"plan",
|
|
88405
|
+
"memory"
|
|
87917
88406
|
];
|
|
87918
88407
|
if (validModes.includes(permissionModeValue)) {
|
|
87919
88408
|
permissionMode3.setMode(permissionModeValue);
|
|
@@ -88834,7 +89323,7 @@ ${loadedContents.join(`
|
|
|
88834
89323
|
} else {
|
|
88835
89324
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
88836
89325
|
}
|
|
88837
|
-
await new Promise((
|
|
89326
|
+
await new Promise((resolve27) => setTimeout(resolve27, retryDelayMs));
|
|
88838
89327
|
continue;
|
|
88839
89328
|
}
|
|
88840
89329
|
}
|
|
@@ -88883,7 +89372,7 @@ ${loadedContents.join(`
|
|
|
88883
89372
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
88884
89373
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
88885
89374
|
}
|
|
88886
|
-
await new Promise((
|
|
89375
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
88887
89376
|
conversationBusyRetries = 0;
|
|
88888
89377
|
continue;
|
|
88889
89378
|
}
|
|
@@ -89122,7 +89611,7 @@ ${loadedContents.join(`
|
|
|
89122
89611
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
89123
89612
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
89124
89613
|
}
|
|
89125
|
-
await new Promise((
|
|
89614
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89126
89615
|
refreshCurrentInputOtids();
|
|
89127
89616
|
continue;
|
|
89128
89617
|
}
|
|
@@ -89208,7 +89697,7 @@ ${loadedContents.join(`
|
|
|
89208
89697
|
} else {
|
|
89209
89698
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
89210
89699
|
}
|
|
89211
|
-
await new Promise((
|
|
89700
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89212
89701
|
refreshCurrentInputOtids();
|
|
89213
89702
|
continue;
|
|
89214
89703
|
}
|
|
@@ -89236,7 +89725,7 @@ ${loadedContents.join(`
|
|
|
89236
89725
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
89237
89726
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
89238
89727
|
}
|
|
89239
|
-
await new Promise((
|
|
89728
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
89240
89729
|
refreshCurrentInputOtids();
|
|
89241
89730
|
continue;
|
|
89242
89731
|
}
|
|
@@ -89570,9 +90059,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89570
90059
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
89571
90060
|
maybeNotifyBlocked(syntheticUserLine);
|
|
89572
90061
|
if (lineResolver) {
|
|
89573
|
-
const
|
|
90062
|
+
const resolve27 = lineResolver;
|
|
89574
90063
|
lineResolver = null;
|
|
89575
|
-
|
|
90064
|
+
resolve27(syntheticUserLine);
|
|
89576
90065
|
return;
|
|
89577
90066
|
}
|
|
89578
90067
|
lineQueue.push(syntheticUserLine);
|
|
@@ -89580,9 +90069,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89580
90069
|
rl.on("line", (line) => {
|
|
89581
90070
|
maybeNotifyBlocked(line);
|
|
89582
90071
|
if (lineResolver) {
|
|
89583
|
-
const
|
|
90072
|
+
const resolve27 = lineResolver;
|
|
89584
90073
|
lineResolver = null;
|
|
89585
|
-
|
|
90074
|
+
resolve27(line);
|
|
89586
90075
|
} else {
|
|
89587
90076
|
lineQueue.push(line);
|
|
89588
90077
|
}
|
|
@@ -89591,17 +90080,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89591
90080
|
setMessageQueueAdder(null);
|
|
89592
90081
|
msgQueueRuntime.clear("shutdown");
|
|
89593
90082
|
if (lineResolver) {
|
|
89594
|
-
const
|
|
90083
|
+
const resolve27 = lineResolver;
|
|
89595
90084
|
lineResolver = null;
|
|
89596
|
-
|
|
90085
|
+
resolve27(null);
|
|
89597
90086
|
}
|
|
89598
90087
|
});
|
|
89599
90088
|
async function getNextLine() {
|
|
89600
90089
|
if (lineQueue.length > 0) {
|
|
89601
90090
|
return lineQueue.shift() ?? null;
|
|
89602
90091
|
}
|
|
89603
|
-
return new Promise((
|
|
89604
|
-
lineResolver =
|
|
90092
|
+
return new Promise((resolve27) => {
|
|
90093
|
+
lineResolver = resolve27;
|
|
89605
90094
|
});
|
|
89606
90095
|
}
|
|
89607
90096
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -90105,7 +90594,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
90105
90594
|
uuid: `retry-bidir-${randomUUID8()}`
|
|
90106
90595
|
};
|
|
90107
90596
|
console.log(JSON.stringify(retryMsg));
|
|
90108
|
-
await new Promise((
|
|
90597
|
+
await new Promise((resolve27) => setTimeout(resolve27, delayMs));
|
|
90109
90598
|
continue;
|
|
90110
90599
|
}
|
|
90111
90600
|
throw preStreamError;
|
|
@@ -90401,10 +90890,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90401
90890
|
detectionComplete = true;
|
|
90402
90891
|
return;
|
|
90403
90892
|
}
|
|
90404
|
-
return new Promise((
|
|
90893
|
+
return new Promise((resolve27) => {
|
|
90405
90894
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
90406
90895
|
detectionComplete = true;
|
|
90407
|
-
|
|
90896
|
+
resolve27();
|
|
90408
90897
|
return;
|
|
90409
90898
|
}
|
|
90410
90899
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -90437,7 +90926,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90437
90926
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
90438
90927
|
}
|
|
90439
90928
|
detectionComplete = true;
|
|
90440
|
-
|
|
90929
|
+
resolve27();
|
|
90441
90930
|
};
|
|
90442
90931
|
const handleData = (data) => {
|
|
90443
90932
|
if (timeoutId === undefined) {
|
|
@@ -90795,10 +91284,10 @@ __export(exports_settings, {
|
|
|
90795
91284
|
loadProjectSettings: () => loadProjectSettings,
|
|
90796
91285
|
getSetting: () => getSetting
|
|
90797
91286
|
});
|
|
90798
|
-
import { homedir as
|
|
91287
|
+
import { homedir as homedir29 } from "node:os";
|
|
90799
91288
|
import { join as join36 } from "node:path";
|
|
90800
91289
|
function getSettingsPath() {
|
|
90801
|
-
return join36(
|
|
91290
|
+
return join36(homedir29(), ".letta", "settings.json");
|
|
90802
91291
|
}
|
|
90803
91292
|
async function loadSettings() {
|
|
90804
91293
|
const settingsPath = getSettingsPath();
|
|
@@ -106304,16 +106793,16 @@ function clipStyledSpans(spans, maxColumns) {
|
|
|
106304
106793
|
return { spans: clipped, clipped: false };
|
|
106305
106794
|
}
|
|
106306
106795
|
function languageFromPath(filePath) {
|
|
106307
|
-
const
|
|
106308
|
-
const lower =
|
|
106796
|
+
const basename5 = filePath.split("/").pop() ?? filePath;
|
|
106797
|
+
const lower = basename5.toLowerCase();
|
|
106309
106798
|
if (lower === "makefile")
|
|
106310
106799
|
return "makefile";
|
|
106311
106800
|
if (lower === "dockerfile")
|
|
106312
106801
|
return "dockerfile";
|
|
106313
|
-
const dotIdx =
|
|
106802
|
+
const dotIdx = basename5.lastIndexOf(".");
|
|
106314
106803
|
if (dotIdx < 0)
|
|
106315
106804
|
return;
|
|
106316
|
-
const ext3 =
|
|
106805
|
+
const ext3 = basename5.slice(dotIdx + 1).toLowerCase();
|
|
106317
106806
|
return EXT_TO_LANG[ext3];
|
|
106318
106807
|
}
|
|
106319
106808
|
function colorForClassName(className, palette) {
|
|
@@ -110349,7 +110838,7 @@ var init_plan_viewer_template = () => {};
|
|
|
110349
110838
|
|
|
110350
110839
|
// src/web/generate-plan-viewer.ts
|
|
110351
110840
|
import { chmodSync as chmodSync2, existsSync as existsSync28, mkdirSync as mkdirSync20, writeFileSync as writeFileSync14 } from "node:fs";
|
|
110352
|
-
import { homedir as
|
|
110841
|
+
import { homedir as homedir30 } from "node:os";
|
|
110353
110842
|
import { join as join37 } from "node:path";
|
|
110354
110843
|
async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
110355
110844
|
const data = {
|
|
@@ -110383,7 +110872,7 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
|
|
|
110383
110872
|
var VIEWERS_DIR;
|
|
110384
110873
|
var init_generate_plan_viewer = __esm(() => {
|
|
110385
110874
|
init_plan_viewer_template();
|
|
110386
|
-
VIEWERS_DIR = join37(
|
|
110875
|
+
VIEWERS_DIR = join37(homedir30(), ".letta", "viewers");
|
|
110387
110876
|
});
|
|
110388
110877
|
|
|
110389
110878
|
// src/cli/components/StaticPlanApproval.tsx
|
|
@@ -112623,7 +113112,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
112623
113112
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
112624
113113
|
import { existsSync as existsSync29, readFileSync as readFileSync16, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
112625
113114
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
112626
|
-
import { basename as
|
|
113115
|
+
import { basename as basename5, extname as extname5, isAbsolute as isAbsolute19, join as join38, resolve as resolve27 } from "node:path";
|
|
112627
113116
|
function countLines2(text) {
|
|
112628
113117
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
112629
113118
|
}
|
|
@@ -112670,8 +113159,8 @@ function translatePasteForImages(paste) {
|
|
|
112670
113159
|
}
|
|
112671
113160
|
} catch {}
|
|
112672
113161
|
}
|
|
112673
|
-
if (!
|
|
112674
|
-
filePath =
|
|
113162
|
+
if (!isAbsolute19(filePath))
|
|
113163
|
+
filePath = resolve27(process.cwd(), filePath);
|
|
112675
113164
|
const ext3 = extname5(filePath || "").toLowerCase();
|
|
112676
113165
|
if (IMAGE_EXTS.has(ext3) && existsSync29(filePath) && statSync10(filePath).isFile()) {
|
|
112677
113166
|
const buf = readFileSync16(filePath);
|
|
@@ -112680,7 +113169,7 @@ function translatePasteForImages(paste) {
|
|
|
112680
113169
|
const id = allocateImage({
|
|
112681
113170
|
data: b64,
|
|
112682
113171
|
mediaType: mt,
|
|
112683
|
-
filename:
|
|
113172
|
+
filename: basename5(filePath)
|
|
112684
113173
|
});
|
|
112685
113174
|
s = `[Image #${id}]`;
|
|
112686
113175
|
}
|
|
@@ -113446,8 +113935,8 @@ import {
|
|
|
113446
113935
|
readFileSync as readFileSync17,
|
|
113447
113936
|
writeFileSync as writeFileSync15
|
|
113448
113937
|
} from "node:fs";
|
|
113449
|
-
import { homedir as
|
|
113450
|
-
import { dirname as
|
|
113938
|
+
import { homedir as homedir31, platform as platform5 } from "node:os";
|
|
113939
|
+
import { dirname as dirname16, join as join39 } from "node:path";
|
|
113451
113940
|
function detectTerminalType() {
|
|
113452
113941
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
113453
113942
|
return "cursor";
|
|
@@ -113479,7 +113968,7 @@ function getKeybindingsPath(terminal) {
|
|
|
113479
113968
|
}[terminal];
|
|
113480
113969
|
const os7 = platform5();
|
|
113481
113970
|
if (os7 === "darwin") {
|
|
113482
|
-
return join39(
|
|
113971
|
+
return join39(homedir31(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
113483
113972
|
}
|
|
113484
113973
|
if (os7 === "win32") {
|
|
113485
113974
|
const appData = process.env.APPDATA;
|
|
@@ -113488,7 +113977,7 @@ function getKeybindingsPath(terminal) {
|
|
|
113488
113977
|
return join39(appData, appName, "User", "keybindings.json");
|
|
113489
113978
|
}
|
|
113490
113979
|
if (os7 === "linux") {
|
|
113491
|
-
return join39(
|
|
113980
|
+
return join39(homedir31(), ".config", appName, "User", "keybindings.json");
|
|
113492
113981
|
}
|
|
113493
113982
|
return null;
|
|
113494
113983
|
}
|
|
@@ -113538,7 +114027,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
113538
114027
|
if (keybindingExists(keybindingsPath)) {
|
|
113539
114028
|
return { success: true, alreadyExists: true };
|
|
113540
114029
|
}
|
|
113541
|
-
const parentDir =
|
|
114030
|
+
const parentDir = dirname16(keybindingsPath);
|
|
113542
114031
|
if (!existsSync30(parentDir)) {
|
|
113543
114032
|
mkdirSync21(parentDir, { recursive: true });
|
|
113544
114033
|
}
|
|
@@ -113645,10 +114134,10 @@ function getWezTermConfigPath() {
|
|
|
113645
114134
|
if (existsSync30(xdgPath))
|
|
113646
114135
|
return xdgPath;
|
|
113647
114136
|
}
|
|
113648
|
-
const configPath = join39(
|
|
114137
|
+
const configPath = join39(homedir31(), ".config", "wezterm", "wezterm.lua");
|
|
113649
114138
|
if (existsSync30(configPath))
|
|
113650
114139
|
return configPath;
|
|
113651
|
-
return join39(
|
|
114140
|
+
return join39(homedir31(), ".wezterm.lua");
|
|
113652
114141
|
}
|
|
113653
114142
|
function wezTermDeleteFixExists(configPath) {
|
|
113654
114143
|
if (!existsSync30(configPath))
|
|
@@ -113697,7 +114186,7 @@ return config`);
|
|
|
113697
114186
|
${WEZTERM_DELETE_FIX}
|
|
113698
114187
|
`;
|
|
113699
114188
|
}
|
|
113700
|
-
const parentDir =
|
|
114189
|
+
const parentDir = dirname16(configPath);
|
|
113701
114190
|
if (!existsSync30(parentDir)) {
|
|
113702
114191
|
mkdirSync21(parentDir, { recursive: true });
|
|
113703
114192
|
}
|
|
@@ -114280,7 +114769,7 @@ __export(exports_custom, {
|
|
|
114280
114769
|
});
|
|
114281
114770
|
import { existsSync as existsSync31 } from "node:fs";
|
|
114282
114771
|
import { readdir as readdir9, readFile as readFile11 } from "node:fs/promises";
|
|
114283
|
-
import { basename as
|
|
114772
|
+
import { basename as basename6, dirname as dirname17, join as join40 } from "node:path";
|
|
114284
114773
|
async function getCustomCommands() {
|
|
114285
114774
|
if (cachedCommands !== null) {
|
|
114286
114775
|
return cachedCommands;
|
|
@@ -114340,8 +114829,8 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
|
|
|
114340
114829
|
async function parseCommandFile(filePath, rootPath, source2) {
|
|
114341
114830
|
const content = await readFile11(filePath, "utf-8");
|
|
114342
114831
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
114343
|
-
const id =
|
|
114344
|
-
const relativePath =
|
|
114832
|
+
const id = basename6(filePath, ".md");
|
|
114833
|
+
const relativePath = dirname17(filePath).slice(rootPath.length);
|
|
114345
114834
|
const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
|
|
114346
114835
|
let description = getStringField(frontmatter, "description");
|
|
114347
114836
|
if (!description) {
|
|
@@ -114689,12 +115178,12 @@ var init_HelpDialog = __esm(async () => {
|
|
|
114689
115178
|
});
|
|
114690
115179
|
|
|
114691
115180
|
// src/hooks/writer.ts
|
|
114692
|
-
import { homedir as
|
|
114693
|
-
import { resolve as
|
|
115181
|
+
import { homedir as homedir32 } from "node:os";
|
|
115182
|
+
import { resolve as resolve28 } from "node:path";
|
|
114694
115183
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
114695
|
-
const home = process.env.HOME ||
|
|
114696
|
-
const globalSettingsPath =
|
|
114697
|
-
const projectSettingsPath =
|
|
115184
|
+
const home = process.env.HOME || homedir32();
|
|
115185
|
+
const globalSettingsPath = resolve28(home, ".letta", "settings.json");
|
|
115186
|
+
const projectSettingsPath = resolve28(workingDirectory, ".letta", "settings.json");
|
|
114698
115187
|
return globalSettingsPath === projectSettingsPath;
|
|
114699
115188
|
}
|
|
114700
115189
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -117332,7 +117821,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
117332
117821
|
|
|
117333
117822
|
// src/cli/helpers/fileSearch.ts
|
|
117334
117823
|
import { readdirSync as readdirSync13, statSync as statSync11 } from "node:fs";
|
|
117335
|
-
import { join as join41, relative as relative15, resolve as
|
|
117824
|
+
import { join as join41, relative as relative15, resolve as resolve29 } from "node:path";
|
|
117336
117825
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
117337
117826
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
117338
117827
|
return results;
|
|
@@ -117375,7 +117864,7 @@ async function searchFiles(query, deep = false) {
|
|
|
117375
117864
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
117376
117865
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
117377
117866
|
try {
|
|
117378
|
-
const resolvedDir =
|
|
117867
|
+
const resolvedDir = resolve29(getIndexRoot(), dirPart);
|
|
117379
117868
|
try {
|
|
117380
117869
|
statSync11(resolvedDir);
|
|
117381
117870
|
searchDir = resolvedDir;
|
|
@@ -119503,7 +119992,7 @@ import {
|
|
|
119503
119992
|
writeFileSync as writeFileSync16
|
|
119504
119993
|
} from "node:fs";
|
|
119505
119994
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
119506
|
-
import { dirname as
|
|
119995
|
+
import { dirname as dirname18, join as join42 } from "node:path";
|
|
119507
119996
|
function runCommand(command, args, cwd2, input) {
|
|
119508
119997
|
try {
|
|
119509
119998
|
return execFileSync4(command, args, {
|
|
@@ -119750,8 +120239,8 @@ function runGit6(args, cwd2) {
|
|
|
119750
120239
|
}
|
|
119751
120240
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
119752
120241
|
const absolutePath = join42(repoDir, workflowPath);
|
|
119753
|
-
if (!existsSync32(
|
|
119754
|
-
mkdirSync22(
|
|
120242
|
+
if (!existsSync32(dirname18(absolutePath))) {
|
|
120243
|
+
mkdirSync22(dirname18(absolutePath), { recursive: true });
|
|
119755
120244
|
}
|
|
119756
120245
|
const next = `${content.trimEnd()}
|
|
119757
120246
|
`;
|
|
@@ -123657,7 +124146,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
123657
124146
|
});
|
|
123658
124147
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
123659
124148
|
import { chmodSync as chmodSync3, existsSync as existsSync33, mkdirSync as mkdirSync23, writeFileSync as writeFileSync17 } from "node:fs";
|
|
123660
|
-
import { homedir as
|
|
124149
|
+
import { homedir as homedir33 } from "node:os";
|
|
123661
124150
|
import { join as join43 } from "node:path";
|
|
123662
124151
|
import { promisify as promisify14 } from "node:util";
|
|
123663
124152
|
async function runGitSafe(cwd2, args) {
|
|
@@ -123971,7 +124460,7 @@ var init_generate_memory_viewer = __esm(async () => {
|
|
|
123971
124460
|
init_memoryGit()
|
|
123972
124461
|
]);
|
|
123973
124462
|
execFile14 = promisify14(execFileCb5);
|
|
123974
|
-
VIEWERS_DIR2 = join43(
|
|
124463
|
+
VIEWERS_DIR2 = join43(homedir33(), ".letta", "viewers");
|
|
123975
124464
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
123976
124465
|
});
|
|
123977
124466
|
|
|
@@ -126689,11 +127178,11 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
126689
127178
|
|
|
126690
127179
|
// src/utils/aws-credentials.ts
|
|
126691
127180
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
126692
|
-
import { homedir as
|
|
127181
|
+
import { homedir as homedir34 } from "node:os";
|
|
126693
127182
|
import { join as join44 } from "node:path";
|
|
126694
127183
|
async function parseAwsCredentials() {
|
|
126695
|
-
const credentialsPath = join44(
|
|
126696
|
-
const configPath = join44(
|
|
127184
|
+
const credentialsPath = join44(homedir34(), ".aws", "credentials");
|
|
127185
|
+
const configPath = join44(homedir34(), ".aws", "config");
|
|
126697
127186
|
const profiles = new Map;
|
|
126698
127187
|
try {
|
|
126699
127188
|
const content = await readFile12(credentialsPath, "utf-8");
|
|
@@ -132174,7 +132663,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
132174
132663
|
};
|
|
132175
132664
|
}
|
|
132176
132665
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
132177
|
-
return new Promise((
|
|
132666
|
+
return new Promise((resolve30, reject) => {
|
|
132178
132667
|
const [executable, ...args] = launcher;
|
|
132179
132668
|
if (!executable) {
|
|
132180
132669
|
reject(new Error("Empty launcher"));
|
|
@@ -132187,7 +132676,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
132187
132676
|
const safeResolve = (result) => {
|
|
132188
132677
|
if (!resolved) {
|
|
132189
132678
|
resolved = true;
|
|
132190
|
-
|
|
132679
|
+
resolve30(result);
|
|
132191
132680
|
}
|
|
132192
132681
|
};
|
|
132193
132682
|
let child;
|
|
@@ -132633,7 +133122,7 @@ __export(exports_shellAliases, {
|
|
|
132633
133122
|
clearAliasCache: () => clearAliasCache
|
|
132634
133123
|
});
|
|
132635
133124
|
import { existsSync as existsSync36, readFileSync as readFileSync20 } from "node:fs";
|
|
132636
|
-
import { homedir as
|
|
133125
|
+
import { homedir as homedir35 } from "node:os";
|
|
132637
133126
|
import { join as join46 } from "node:path";
|
|
132638
133127
|
function parseAliasesFromFile(filePath) {
|
|
132639
133128
|
const aliases = new Map;
|
|
@@ -132703,7 +133192,7 @@ function loadAliases(forceReload = false) {
|
|
|
132703
133192
|
if (aliasCache && !forceReload) {
|
|
132704
133193
|
return aliasCache;
|
|
132705
133194
|
}
|
|
132706
|
-
const home =
|
|
133195
|
+
const home = homedir35();
|
|
132707
133196
|
const allAliases = new Map;
|
|
132708
133197
|
for (const file of ALIAS_FILES) {
|
|
132709
133198
|
const filePath = join46(home, file);
|
|
@@ -133364,14 +133853,14 @@ __export(exports_export, {
|
|
|
133364
133853
|
packageSkills: () => packageSkills
|
|
133365
133854
|
});
|
|
133366
133855
|
import { readdir as readdir10, readFile as readFile13 } from "node:fs/promises";
|
|
133367
|
-
import { relative as relative16, resolve as
|
|
133856
|
+
import { relative as relative16, resolve as resolve30 } from "node:path";
|
|
133368
133857
|
async function packageSkills(agentId, skillsDir) {
|
|
133369
133858
|
const skills = [];
|
|
133370
133859
|
const skillNames = new Set;
|
|
133371
133860
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
133372
133861
|
agentId && getAgentSkillsDir(agentId),
|
|
133373
|
-
|
|
133374
|
-
|
|
133862
|
+
resolve30(process.cwd(), ".skills"),
|
|
133863
|
+
resolve30(process.env.HOME || "~", ".letta", "skills")
|
|
133375
133864
|
].filter((dir) => Boolean(dir));
|
|
133376
133865
|
for (const baseDir of dirsToCheck) {
|
|
133377
133866
|
try {
|
|
@@ -133381,8 +133870,8 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
133381
133870
|
continue;
|
|
133382
133871
|
if (skillNames.has(entry.name))
|
|
133383
133872
|
continue;
|
|
133384
|
-
const skillDir =
|
|
133385
|
-
const skillMdPath =
|
|
133873
|
+
const skillDir = resolve30(baseDir, entry.name);
|
|
133874
|
+
const skillMdPath = resolve30(skillDir, "SKILL.md");
|
|
133386
133875
|
try {
|
|
133387
133876
|
await readFile13(skillMdPath, "utf-8");
|
|
133388
133877
|
} catch {
|
|
@@ -133412,7 +133901,7 @@ async function readSkillFiles(skillDir) {
|
|
|
133412
133901
|
async function walk(dir) {
|
|
133413
133902
|
const entries = await readdir10(dir, { withFileTypes: true });
|
|
133414
133903
|
for (const entry of entries) {
|
|
133415
|
-
const fullPath =
|
|
133904
|
+
const fullPath = resolve30(dir, entry.name);
|
|
133416
133905
|
if (entry.isDirectory()) {
|
|
133417
133906
|
await walk(fullPath);
|
|
133418
133907
|
} else {
|
|
@@ -133557,7 +134046,7 @@ __export(exports_App, {
|
|
|
133557
134046
|
});
|
|
133558
134047
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
133559
134048
|
import { existsSync as existsSync37, readFileSync as readFileSync21, renameSync as renameSync3, writeFileSync as writeFileSync18 } from "node:fs";
|
|
133560
|
-
import { homedir as
|
|
134049
|
+
import { homedir as homedir36, tmpdir as tmpdir6 } from "node:os";
|
|
133561
134050
|
import { join as join47, relative as relative17 } from "node:path";
|
|
133562
134051
|
function deriveReasoningEffort(modelSettings, llmConfig) {
|
|
133563
134052
|
if (modelSettings && "provider_type" in modelSettings) {
|
|
@@ -135896,7 +136385,7 @@ ${newState.originalPrompt}`,
|
|
|
135896
136385
|
cancelled = true;
|
|
135897
136386
|
break;
|
|
135898
136387
|
}
|
|
135899
|
-
await new Promise((
|
|
136388
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
135900
136389
|
}
|
|
135901
136390
|
buffersRef.current.byId.delete(statusId);
|
|
135902
136391
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -135960,7 +136449,7 @@ ${newState.originalPrompt}`,
|
|
|
135960
136449
|
cancelled = true;
|
|
135961
136450
|
break;
|
|
135962
136451
|
}
|
|
135963
|
-
await new Promise((
|
|
136452
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
135964
136453
|
}
|
|
135965
136454
|
if (retryStatusId) {
|
|
135966
136455
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -136718,7 +137207,7 @@ ${feedback}
|
|
|
136718
137207
|
});
|
|
136719
137208
|
buffersRef.current.order.push(statusId);
|
|
136720
137209
|
refreshDerived();
|
|
136721
|
-
await new Promise((
|
|
137210
|
+
await new Promise((resolve31) => setTimeout(resolve31, delayMs));
|
|
136722
137211
|
buffersRef.current.byId.delete(statusId);
|
|
136723
137212
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
136724
137213
|
refreshDerived();
|
|
@@ -136778,7 +137267,7 @@ ${feedback}
|
|
|
136778
137267
|
cancelled = true;
|
|
136779
137268
|
break;
|
|
136780
137269
|
}
|
|
136781
|
-
await new Promise((
|
|
137270
|
+
await new Promise((resolve31) => setTimeout(resolve31, 100));
|
|
136782
137271
|
}
|
|
136783
137272
|
if (retryStatusId) {
|
|
136784
137273
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -141721,7 +142210,7 @@ ${guidance}`);
|
|
|
141721
142210
|
}
|
|
141722
142211
|
if (mode === "bypassPermissions") {
|
|
141723
142212
|
const planFilePath = activePlanPath ?? fallbackPlanPath;
|
|
141724
|
-
const plansDir = join47(
|
|
142213
|
+
const plansDir = join47(homedir36(), ".letta", "plans");
|
|
141725
142214
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
141726
142215
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
141727
142216
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -141756,7 +142245,7 @@ ${guidance}`);
|
|
|
141756
142245
|
if (!hasUsablePlan) {
|
|
141757
142246
|
lastAutoHandledExitPlanToolCallIdRef.current = approval.toolCallId;
|
|
141758
142247
|
const planFilePath = activePlanPath ?? fallbackPlanPath;
|
|
141759
|
-
const plansDir = join47(
|
|
142248
|
+
const plansDir = join47(homedir36(), ".letta", "plans");
|
|
141760
142249
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
141761
142250
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
141762
142251
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -143168,8 +143657,8 @@ import {
|
|
|
143168
143657
|
readFileSync as readFileSync22,
|
|
143169
143658
|
writeFileSync as writeFileSync19
|
|
143170
143659
|
} from "node:fs";
|
|
143171
|
-
import { homedir as
|
|
143172
|
-
import { dirname as
|
|
143660
|
+
import { homedir as homedir37, platform as platform6 } from "node:os";
|
|
143661
|
+
import { dirname as dirname19, join as join48 } from "node:path";
|
|
143173
143662
|
function detectTerminalType2() {
|
|
143174
143663
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
143175
143664
|
return "cursor";
|
|
@@ -143201,7 +143690,7 @@ function getKeybindingsPath2(terminal) {
|
|
|
143201
143690
|
}[terminal];
|
|
143202
143691
|
const os8 = platform6();
|
|
143203
143692
|
if (os8 === "darwin") {
|
|
143204
|
-
return join48(
|
|
143693
|
+
return join48(homedir37(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
143205
143694
|
}
|
|
143206
143695
|
if (os8 === "win32") {
|
|
143207
143696
|
const appData = process.env.APPDATA;
|
|
@@ -143210,7 +143699,7 @@ function getKeybindingsPath2(terminal) {
|
|
|
143210
143699
|
return join48(appData, appName, "User", "keybindings.json");
|
|
143211
143700
|
}
|
|
143212
143701
|
if (os8 === "linux") {
|
|
143213
|
-
return join48(
|
|
143702
|
+
return join48(homedir37(), ".config", appName, "User", "keybindings.json");
|
|
143214
143703
|
}
|
|
143215
143704
|
return null;
|
|
143216
143705
|
}
|
|
@@ -143260,7 +143749,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
143260
143749
|
if (keybindingExists2(keybindingsPath)) {
|
|
143261
143750
|
return { success: true, alreadyExists: true };
|
|
143262
143751
|
}
|
|
143263
|
-
const parentDir =
|
|
143752
|
+
const parentDir = dirname19(keybindingsPath);
|
|
143264
143753
|
if (!existsSync38(parentDir)) {
|
|
143265
143754
|
mkdirSync24(parentDir, { recursive: true });
|
|
143266
143755
|
}
|
|
@@ -143367,10 +143856,10 @@ function getWezTermConfigPath2() {
|
|
|
143367
143856
|
if (existsSync38(xdgPath))
|
|
143368
143857
|
return xdgPath;
|
|
143369
143858
|
}
|
|
143370
|
-
const configPath = join48(
|
|
143859
|
+
const configPath = join48(homedir37(), ".config", "wezterm", "wezterm.lua");
|
|
143371
143860
|
if (existsSync38(configPath))
|
|
143372
143861
|
return configPath;
|
|
143373
|
-
return join48(
|
|
143862
|
+
return join48(homedir37(), ".wezterm.lua");
|
|
143374
143863
|
}
|
|
143375
143864
|
function wezTermDeleteFixExists2(configPath) {
|
|
143376
143865
|
if (!existsSync38(configPath))
|
|
@@ -143419,7 +143908,7 @@ return config`);
|
|
|
143419
143908
|
${WEZTERM_DELETE_FIX2}
|
|
143420
143909
|
`;
|
|
143421
143910
|
}
|
|
143422
|
-
const parentDir =
|
|
143911
|
+
const parentDir = dirname19(configPath);
|
|
143423
143912
|
if (!existsSync38(parentDir)) {
|
|
143424
143913
|
mkdirSync24(parentDir, { recursive: true });
|
|
143425
143914
|
}
|
|
@@ -143468,10 +143957,10 @@ __export(exports_settings2, {
|
|
|
143468
143957
|
loadProjectSettings: () => loadProjectSettings2,
|
|
143469
143958
|
getSetting: () => getSetting2
|
|
143470
143959
|
});
|
|
143471
|
-
import { homedir as
|
|
143960
|
+
import { homedir as homedir38 } from "node:os";
|
|
143472
143961
|
import { join as join49 } from "node:path";
|
|
143473
143962
|
function getSettingsPath2() {
|
|
143474
|
-
return join49(
|
|
143963
|
+
return join49(homedir38(), ".letta", "settings.json");
|
|
143475
143964
|
}
|
|
143476
143965
|
async function loadSettings2() {
|
|
143477
143966
|
const settingsPath = getSettingsPath2();
|
|
@@ -143993,10 +144482,10 @@ __export(exports_import2, {
|
|
|
143993
144482
|
});
|
|
143994
144483
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
143995
144484
|
import { chmod as chmod2, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile9 } from "node:fs/promises";
|
|
143996
|
-
import { dirname as
|
|
144485
|
+
import { dirname as dirname20, resolve as resolve31 } from "node:path";
|
|
143997
144486
|
async function importAgentFromFile2(options) {
|
|
143998
144487
|
const client = await getClient();
|
|
143999
|
-
const resolvedPath =
|
|
144488
|
+
const resolvedPath = resolve31(options.filePath);
|
|
144000
144489
|
const file = createReadStream2(resolvedPath);
|
|
144001
144490
|
const importResponse = await client.agents.importFile({
|
|
144002
144491
|
file,
|
|
@@ -144031,7 +144520,7 @@ async function extractSkillsFromAf2(afPath, destDir) {
|
|
|
144031
144520
|
return [];
|
|
144032
144521
|
}
|
|
144033
144522
|
for (const skill2 of afData.skills) {
|
|
144034
|
-
const skillDir =
|
|
144523
|
+
const skillDir = resolve31(destDir, skill2.name);
|
|
144035
144524
|
await mkdir8(skillDir, { recursive: true });
|
|
144036
144525
|
if (skill2.files) {
|
|
144037
144526
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -144051,8 +144540,8 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
144051
144540
|
}
|
|
144052
144541
|
}
|
|
144053
144542
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
144054
|
-
const fullPath =
|
|
144055
|
-
await mkdir8(
|
|
144543
|
+
const fullPath = resolve31(skillDir, filePath);
|
|
144544
|
+
await mkdir8(dirname20(fullPath), { recursive: true });
|
|
144056
144545
|
await writeFile9(fullPath, content, "utf-8");
|
|
144057
144546
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
144058
144547
|
if (isScript) {
|
|
@@ -144162,15 +144651,15 @@ __export(exports_memoryFilesystem2, {
|
|
|
144162
144651
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
144163
144652
|
});
|
|
144164
144653
|
import { existsSync as existsSync39, mkdirSync as mkdirSync25 } from "node:fs";
|
|
144165
|
-
import { homedir as
|
|
144654
|
+
import { homedir as homedir39 } from "node:os";
|
|
144166
144655
|
import { join as join50 } from "node:path";
|
|
144167
|
-
function getMemoryFilesystemRoot2(agentId, homeDir =
|
|
144656
|
+
function getMemoryFilesystemRoot2(agentId, homeDir = homedir39()) {
|
|
144168
144657
|
return join50(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
144169
144658
|
}
|
|
144170
|
-
function getMemorySystemDir2(agentId, homeDir =
|
|
144659
|
+
function getMemorySystemDir2(agentId, homeDir = homedir39()) {
|
|
144171
144660
|
return join50(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
144172
144661
|
}
|
|
144173
|
-
function ensureMemoryFilesystemDirs2(agentId, homeDir =
|
|
144662
|
+
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir39()) {
|
|
144174
144663
|
const root = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
144175
144664
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
144176
144665
|
if (!existsSync39(root)) {
|
|
@@ -148816,7 +149305,7 @@ async function runListenSubcommand(argv) {
|
|
|
148816
149305
|
await init_memoryGit();
|
|
148817
149306
|
import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync15, rmSync as rmSync2, statSync as statSync8 } from "node:fs";
|
|
148818
149307
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
148819
|
-
import { homedir as
|
|
149308
|
+
import { homedir as homedir23 } from "node:os";
|
|
148820
149309
|
import { join as join28 } from "node:path";
|
|
148821
149310
|
import { parseArgs as parseArgs7 } from "node:util";
|
|
148822
149311
|
function printUsage4() {
|
|
@@ -148862,10 +149351,10 @@ function parseMemfsArgs(argv) {
|
|
|
148862
149351
|
});
|
|
148863
149352
|
}
|
|
148864
149353
|
function getMemoryRoot(agentId) {
|
|
148865
|
-
return join28(
|
|
149354
|
+
return join28(homedir23(), ".letta", "agents", agentId, "memory");
|
|
148866
149355
|
}
|
|
148867
149356
|
function getAgentRoot(agentId) {
|
|
148868
|
-
return join28(
|
|
149357
|
+
return join28(homedir23(), ".letta", "agents", agentId);
|
|
148869
149358
|
}
|
|
148870
149359
|
function formatBackupTimestamp(date = new Date) {
|
|
148871
149360
|
const pad = (value) => String(value).padStart(2, "0");
|
|
@@ -149414,13 +149903,20 @@ async function runSubcommand(argv) {
|
|
|
149414
149903
|
}
|
|
149415
149904
|
|
|
149416
149905
|
// src/permissions/mode.ts
|
|
149906
|
+
init_memoryScope();
|
|
149417
149907
|
init_readOnlyShell();
|
|
149418
149908
|
init_shell_command_normalization();
|
|
149419
|
-
import { homedir as
|
|
149420
|
-
import { isAbsolute as
|
|
149909
|
+
import { homedir as homedir24 } from "node:os";
|
|
149910
|
+
import { isAbsolute as isAbsolute17, join as join29, relative as relative12 } from "node:path";
|
|
149421
149911
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
149422
149912
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
149423
149913
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
149914
|
+
function everyResolvedTargetIsWithinRoots2(candidatePaths, roots, workingDirectory) {
|
|
149915
|
+
return candidatePaths.length > 0 && candidatePaths.every((path23) => {
|
|
149916
|
+
const resolvedPath = resolveScopedTargetPath(path23, workingDirectory);
|
|
149917
|
+
return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
|
|
149918
|
+
});
|
|
149919
|
+
}
|
|
149424
149920
|
function getGlobalMode2() {
|
|
149425
149921
|
const global2 = globalThis;
|
|
149426
149922
|
if (!global2[MODE_KEY2]) {
|
|
@@ -149449,22 +149945,13 @@ function setGlobalModeBeforePlan2(value) {
|
|
|
149449
149945
|
global2[MODE_BEFORE_PLAN_KEY2] = value;
|
|
149450
149946
|
}
|
|
149451
149947
|
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);
|
|
149948
|
+
return resolveScopedTargetPath(targetPath, workingDirectory);
|
|
149462
149949
|
}
|
|
149463
149950
|
function isPathInPlansDir2(path23, plansDir) {
|
|
149464
149951
|
if (!path23.endsWith(".md"))
|
|
149465
149952
|
return false;
|
|
149466
149953
|
const rel = relative12(plansDir, path23);
|
|
149467
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
149954
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute17(rel);
|
|
149468
149955
|
}
|
|
149469
149956
|
function extractApplyPatchPaths2(input) {
|
|
149470
149957
|
const paths = [];
|
|
@@ -149651,7 +150138,7 @@ class PermissionModeManager2 {
|
|
|
149651
150138
|
return "allow";
|
|
149652
150139
|
}
|
|
149653
150140
|
if (writeTools.includes(toolName)) {
|
|
149654
|
-
const plansDir = join29(
|
|
150141
|
+
const plansDir = join29(homedir24(), ".letta", "plans");
|
|
149655
150142
|
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
149656
150143
|
let candidatePaths = [];
|
|
149657
150144
|
if ((toolName === "ApplyPatch" || toolName === "apply_patch" || toolName === "memory_apply_patch") && toolArgs?.input) {
|
|
@@ -149702,7 +150189,7 @@ class PermissionModeManager2 {
|
|
|
149702
150189
|
}
|
|
149703
150190
|
const planWritePath = extractPlanFileWritePathFromShellCommand2(command);
|
|
149704
150191
|
if (planWritePath) {
|
|
149705
|
-
const plansDir = join29(
|
|
150192
|
+
const plansDir = join29(homedir24(), ".letta", "plans");
|
|
149706
150193
|
const resolvedPath = resolvePlanTargetPath2(planWritePath, workingDirectory);
|
|
149707
150194
|
if (resolvedPath && isPathInPlansDir2(resolvedPath, plansDir)) {
|
|
149708
150195
|
return "allow";
|
|
@@ -149711,6 +150198,94 @@ class PermissionModeManager2 {
|
|
|
149711
150198
|
}
|
|
149712
150199
|
return "deny";
|
|
149713
150200
|
}
|
|
150201
|
+
case "memory": {
|
|
150202
|
+
const allowedMemoryRoots = resolveAllowedMemoryRoots().roots;
|
|
150203
|
+
const allowedReadOnlyTools = [
|
|
150204
|
+
"Read",
|
|
150205
|
+
"Glob",
|
|
150206
|
+
"Grep",
|
|
150207
|
+
"NotebookRead",
|
|
150208
|
+
"ViewImage",
|
|
150209
|
+
"view_image",
|
|
150210
|
+
"TaskOutput",
|
|
150211
|
+
"task_output",
|
|
150212
|
+
"Skill",
|
|
150213
|
+
"skill",
|
|
150214
|
+
"read_file",
|
|
150215
|
+
"list_dir",
|
|
150216
|
+
"grep_files",
|
|
150217
|
+
"ReadFile",
|
|
150218
|
+
"ListDir",
|
|
150219
|
+
"GrepFiles",
|
|
150220
|
+
"read_file_gemini",
|
|
150221
|
+
"glob_gemini",
|
|
150222
|
+
"list_directory",
|
|
150223
|
+
"search_file_content",
|
|
150224
|
+
"read_many_files",
|
|
150225
|
+
"ReadFileGemini",
|
|
150226
|
+
"GlobGemini",
|
|
150227
|
+
"ListDirectory",
|
|
150228
|
+
"SearchFileContent",
|
|
150229
|
+
"ReadManyFiles"
|
|
150230
|
+
];
|
|
150231
|
+
const writeTools = [
|
|
150232
|
+
"Write",
|
|
150233
|
+
"Edit",
|
|
150234
|
+
"MultiEdit",
|
|
150235
|
+
"NotebookEdit",
|
|
150236
|
+
"apply_patch",
|
|
150237
|
+
"ApplyPatch",
|
|
150238
|
+
"replace",
|
|
150239
|
+
"Replace",
|
|
150240
|
+
"write_file",
|
|
150241
|
+
"WriteFile",
|
|
150242
|
+
"write_file_gemini",
|
|
150243
|
+
"WriteFileGemini"
|
|
150244
|
+
];
|
|
150245
|
+
const shellTools = [
|
|
150246
|
+
"Bash",
|
|
150247
|
+
"shell",
|
|
150248
|
+
"Shell",
|
|
150249
|
+
"shell_command",
|
|
150250
|
+
"ShellCommand",
|
|
150251
|
+
"run_shell_command",
|
|
150252
|
+
"RunShellCommand",
|
|
150253
|
+
"run_shell_command_gemini",
|
|
150254
|
+
"RunShellCommandGemini"
|
|
150255
|
+
];
|
|
150256
|
+
if (allowedReadOnlyTools.includes(toolName)) {
|
|
150257
|
+
return "allow";
|
|
150258
|
+
}
|
|
150259
|
+
if (toolName === "memory_apply_patch") {
|
|
150260
|
+
return allowedMemoryRoots.length > 0 ? "allow" : "deny";
|
|
150261
|
+
}
|
|
150262
|
+
if (writeTools.includes(toolName)) {
|
|
150263
|
+
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
150264
|
+
let candidatePaths = [];
|
|
150265
|
+
if ((toolName === "ApplyPatch" || toolName === "apply_patch") && toolArgs?.input) {
|
|
150266
|
+
candidatePaths = extractApplyPatchPaths2(toolArgs.input);
|
|
150267
|
+
} else if (typeof targetPath === "string") {
|
|
150268
|
+
candidatePaths = [targetPath];
|
|
150269
|
+
}
|
|
150270
|
+
if (allowedMemoryRoots.length > 0 && everyResolvedTargetIsWithinRoots2(candidatePaths, allowedMemoryRoots, workingDirectory)) {
|
|
150271
|
+
return "allow";
|
|
150272
|
+
}
|
|
150273
|
+
return "deny";
|
|
150274
|
+
}
|
|
150275
|
+
if (shellTools.includes(toolName)) {
|
|
150276
|
+
const command = toolArgs?.command;
|
|
150277
|
+
if (command && isReadOnlyShellCommand(command, { allowExternalPaths: true })) {
|
|
150278
|
+
return "allow";
|
|
150279
|
+
}
|
|
150280
|
+
if (command && allowedMemoryRoots.length > 0 && isScopedMemoryShellCommand(command, allowedMemoryRoots, {
|
|
150281
|
+
workingDirectory
|
|
150282
|
+
})) {
|
|
150283
|
+
return "allow";
|
|
150284
|
+
}
|
|
150285
|
+
return "deny";
|
|
150286
|
+
}
|
|
150287
|
+
return "deny";
|
|
150288
|
+
}
|
|
149714
150289
|
case "default":
|
|
149715
150290
|
return null;
|
|
149716
150291
|
default:
|
|
@@ -149733,8 +150308,8 @@ await __promiseAll([
|
|
|
149733
150308
|
init_secrets()
|
|
149734
150309
|
]);
|
|
149735
150310
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
149736
|
-
import { homedir as
|
|
149737
|
-
import { join as join30, resolve as
|
|
150311
|
+
import { homedir as homedir25 } from "node:os";
|
|
150312
|
+
import { join as join30, resolve as resolve24 } from "node:path";
|
|
149738
150313
|
var DEFAULT_SETTINGS3 = {
|
|
149739
150314
|
lastAgent: null,
|
|
149740
150315
|
tokenStreaming: false,
|
|
@@ -150120,7 +150695,7 @@ class SettingsManager2 {
|
|
|
150120
150695
|
if (!this.settings)
|
|
150121
150696
|
return;
|
|
150122
150697
|
const settingsPath = this.getSettingsPath();
|
|
150123
|
-
const home = process.env.HOME ||
|
|
150698
|
+
const home = process.env.HOME || homedir25();
|
|
150124
150699
|
const dirPath = join30(home, ".letta");
|
|
150125
150700
|
try {
|
|
150126
150701
|
if (!exists(dirPath)) {
|
|
@@ -150181,14 +150756,14 @@ class SettingsManager2 {
|
|
|
150181
150756
|
}
|
|
150182
150757
|
}
|
|
150183
150758
|
getSettingsPath() {
|
|
150184
|
-
const home = process.env.HOME ||
|
|
150759
|
+
const home = process.env.HOME || homedir25();
|
|
150185
150760
|
return join30(home, ".letta", "settings.json");
|
|
150186
150761
|
}
|
|
150187
150762
|
getProjectSettingsPath(workingDirectory) {
|
|
150188
150763
|
return join30(workingDirectory, ".letta", "settings.json");
|
|
150189
150764
|
}
|
|
150190
150765
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
150191
|
-
return
|
|
150766
|
+
return resolve24(this.getProjectSettingsPath(workingDirectory)) === resolve24(this.getSettingsPath());
|
|
150192
150767
|
}
|
|
150193
150768
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
150194
150769
|
return join30(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -151150,8 +151725,8 @@ function acquireSwitchLock2() {
|
|
|
151150
151725
|
const lock = getSwitchLock2();
|
|
151151
151726
|
lock.refCount++;
|
|
151152
151727
|
if (lock.refCount === 1) {
|
|
151153
|
-
lock.promise = new Promise((
|
|
151154
|
-
lock.resolve =
|
|
151728
|
+
lock.promise = new Promise((resolve25) => {
|
|
151729
|
+
lock.resolve = resolve25;
|
|
151155
151730
|
});
|
|
151156
151731
|
}
|
|
151157
151732
|
}
|
|
@@ -151636,7 +152211,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151636
152211
|
printHelp();
|
|
151637
152212
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
151638
152213
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
151639
|
-
await new Promise((
|
|
152214
|
+
await new Promise((resolve32) => setTimeout(resolve32, helpDelayMs));
|
|
151640
152215
|
}
|
|
151641
152216
|
process.exit(0);
|
|
151642
152217
|
}
|
|
@@ -151858,9 +152433,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151858
152433
|
process.exit(1);
|
|
151859
152434
|
}
|
|
151860
152435
|
} else {
|
|
151861
|
-
const { resolve:
|
|
152436
|
+
const { resolve: resolve32 } = await import("path");
|
|
151862
152437
|
const { existsSync: existsSync40 } = await import("fs");
|
|
151863
|
-
const resolvedPath =
|
|
152438
|
+
const resolvedPath = resolve32(fromAfFile);
|
|
151864
152439
|
if (!existsSync40(resolvedPath)) {
|
|
151865
152440
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
151866
152441
|
process.exit(1);
|
|
@@ -151971,6 +152546,7 @@ Error: ${message}`);
|
|
|
151971
152546
|
"default",
|
|
151972
152547
|
"acceptEdits",
|
|
151973
152548
|
"plan",
|
|
152549
|
+
"memory",
|
|
151974
152550
|
"bypassPermissions"
|
|
151975
152551
|
];
|
|
151976
152552
|
if (validModes.includes(mode)) {
|
|
@@ -152735,4 +153311,4 @@ Error during initialization: ${message}`);
|
|
|
152735
153311
|
}
|
|
152736
153312
|
main();
|
|
152737
153313
|
|
|
152738
|
-
//# debugId=
|
|
153314
|
+
//# debugId=1C3BE0588811294864756E2164756E21
|