@letta-ai/letta-code 0.16.1 → 0.16.2
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 +569 -303
- package/package.json +1 -1
- package/skills/syncing-memory-filesystem/SKILL.md +6 -6
package/letta.js
CHANGED
|
@@ -3122,7 +3122,7 @@ var package_default;
|
|
|
3122
3122
|
var init_package = __esm(() => {
|
|
3123
3123
|
package_default = {
|
|
3124
3124
|
name: "@letta-ai/letta-code",
|
|
3125
|
-
version: "0.16.
|
|
3125
|
+
version: "0.16.2",
|
|
3126
3126
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3127
3127
|
type: "module",
|
|
3128
3128
|
bin: {
|
|
@@ -5827,8 +5827,8 @@ Key updates:
|
|
|
5827
5827
|
...
|
|
5828
5828
|
|
|
5829
5829
|
Generated-By: Letta Code
|
|
5830
|
-
Agent-ID:
|
|
5831
|
-
Parent-Agent-ID:
|
|
5830
|
+
Agent-ID: <ACTUAL_AGENT_ID>
|
|
5831
|
+
Parent-Agent-ID: <ACTUAL_PARENT_AGENT_ID>"
|
|
5832
5832
|
\`\`\`
|
|
5833
5833
|
|
|
5834
5834
|
**Commit type** — pick the one that fits:
|
|
@@ -5840,9 +5840,16 @@ Parent-Agent-ID: $LETTA_PARENT_AGENT_ID"
|
|
|
5840
5840
|
- \`chore(history-analyzer): ingest Claude Code history 2025-09 ⏳\`
|
|
5841
5841
|
- \`refactor(history-analyzer): reorganize memory by project domain ⏳\`
|
|
5842
5842
|
|
|
5843
|
-
**Trailers:**
|
|
5844
|
-
|
|
5845
|
-
|
|
5843
|
+
**Trailers:** Before writing the commit, resolve the actual
|
|
5844
|
+
ID values by running:
|
|
5845
|
+
\`\`\`bash
|
|
5846
|
+
echo "AGENT_ID=$LETTA_AGENT_ID"
|
|
5847
|
+
echo "PARENT_AGENT_ID=$LETTA_PARENT_AGENT_ID"
|
|
5848
|
+
\`\`\`
|
|
5849
|
+
Use the printed values (e.g. \`agent-abc123...\`) in the
|
|
5850
|
+
trailers. If a variable is empty or unset, omit that
|
|
5851
|
+
trailer entirely. Never write a literal variable name like
|
|
5852
|
+
\`$LETTA_AGENT_ID\` in the commit message.
|
|
5846
5853
|
|
|
5847
5854
|
## Important
|
|
5848
5855
|
|
|
@@ -7004,8 +7011,8 @@ Updates:
|
|
|
7004
7011
|
- <what conversation context prompted each update>
|
|
7005
7012
|
|
|
7006
7013
|
Generated-By: Letta Code
|
|
7007
|
-
Agent-ID: <
|
|
7008
|
-
Parent-Agent-ID: <
|
|
7014
|
+
Agent-ID: <ACTUAL_AGENT_ID>
|
|
7015
|
+
Parent-Agent-ID: <ACTUAL_PARENT_AGENT_ID>"
|
|
7009
7016
|
\`\`\`
|
|
7010
7017
|
|
|
7011
7018
|
**Commit type** — pick the one that fits:
|
|
@@ -7020,9 +7027,16 @@ Parent-Agent-ID: <value of $LETTA_PARENT_AGENT_ID>"
|
|
|
7020
7027
|
- \`fix(reflection): correct stale user preference note 🔮\`
|
|
7021
7028
|
- \`feat(reflection): add new project context block 🔮\`
|
|
7022
7029
|
|
|
7023
|
-
**Trailers:**
|
|
7024
|
-
|
|
7025
|
-
|
|
7030
|
+
**Trailers:** Before writing the commit, resolve the actual
|
|
7031
|
+
ID values by running:
|
|
7032
|
+
\`\`\`bash
|
|
7033
|
+
echo "AGENT_ID=$LETTA_AGENT_ID"
|
|
7034
|
+
echo "PARENT_AGENT_ID=$LETTA_PARENT_AGENT_ID"
|
|
7035
|
+
\`\`\`
|
|
7036
|
+
Use the printed values (e.g. \`agent-abc123...\`) in the
|
|
7037
|
+
trailers. If a variable is empty or unset, omit that
|
|
7038
|
+
trailer entirely. Never write a literal variable name like
|
|
7039
|
+
\`$LETTA_AGENT_ID\` in the commit message.
|
|
7026
7040
|
|
|
7027
7041
|
**Step 5b: Pull + merge to main**
|
|
7028
7042
|
|
|
@@ -41861,10 +41875,10 @@ async function getMemoryGitStatus(agentId) {
|
|
|
41861
41875
|
summary: parts.length > 0 ? parts.join(", ") : "clean"
|
|
41862
41876
|
};
|
|
41863
41877
|
}
|
|
41864
|
-
async function addGitMemoryTag(agentId) {
|
|
41878
|
+
async function addGitMemoryTag(agentId, prefetchedAgent) {
|
|
41865
41879
|
const client = await getClient2();
|
|
41866
41880
|
try {
|
|
41867
|
-
const agent = await client.agents.retrieve(agentId);
|
|
41881
|
+
const agent = prefetchedAgent ?? await client.agents.retrieve(agentId);
|
|
41868
41882
|
const tags = agent.tags || [];
|
|
41869
41883
|
if (!tags.includes(GIT_MEMORY_ENABLED_TAG)) {
|
|
41870
41884
|
await client.agents.update(agentId, {
|
|
@@ -42813,6 +42827,21 @@ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
42813
42827
|
if (isEnabled && (memfsFlag || shouldAutoEnableFromTag)) {
|
|
42814
42828
|
const { detachMemoryTools: detachMemoryTools2 } = await init_toolset().then(() => exports_toolset);
|
|
42815
42829
|
await detachMemoryTools2(agentId);
|
|
42830
|
+
const { getClient: getClient3 } = await init_client2().then(() => exports_client);
|
|
42831
|
+
const client = await getClient3();
|
|
42832
|
+
for (const label of ["skills", "loaded_skills"]) {
|
|
42833
|
+
try {
|
|
42834
|
+
const block = await client.agents.blocks.retrieve(label, {
|
|
42835
|
+
agent_id: agentId
|
|
42836
|
+
});
|
|
42837
|
+
if (block) {
|
|
42838
|
+
await client.agents.blocks.detach(block.id, {
|
|
42839
|
+
agent_id: agentId
|
|
42840
|
+
});
|
|
42841
|
+
await client.blocks.delete(block.id);
|
|
42842
|
+
}
|
|
42843
|
+
} catch {}
|
|
42844
|
+
}
|
|
42816
42845
|
}
|
|
42817
42846
|
if (noMemfsFlag) {
|
|
42818
42847
|
const { removeGitMemoryTag: removeGitMemoryTag2 } = await init_memoryGit().then(() => exports_memoryGit);
|
|
@@ -42821,7 +42850,7 @@ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
42821
42850
|
let pullSummary;
|
|
42822
42851
|
if (isEnabled) {
|
|
42823
42852
|
const { addGitMemoryTag: addGitMemoryTag2, isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2, pullMemory: pullMemory2 } = await init_memoryGit().then(() => exports_memoryGit);
|
|
42824
|
-
await addGitMemoryTag2(agentId);
|
|
42853
|
+
await addGitMemoryTag2(agentId, options?.agentTags ? { tags: options.agentTags } : undefined);
|
|
42825
42854
|
if (!isGitRepo2(agentId)) {
|
|
42826
42855
|
await cloneMemoryRepo2(agentId);
|
|
42827
42856
|
} else if (options?.pullOnExistingRepo) {
|
|
@@ -68399,6 +68428,159 @@ var init_approvalClassification = __esm(async () => {
|
|
|
68399
68428
|
await init_manager3();
|
|
68400
68429
|
});
|
|
68401
68430
|
|
|
68431
|
+
// src/cli/helpers/chunkLog.ts
|
|
68432
|
+
import {
|
|
68433
|
+
existsSync as existsSync8,
|
|
68434
|
+
mkdirSync as mkdirSync6,
|
|
68435
|
+
readdirSync as readdirSync4,
|
|
68436
|
+
unlinkSync as unlinkSync3,
|
|
68437
|
+
writeFileSync as writeFileSync5
|
|
68438
|
+
} from "node:fs";
|
|
68439
|
+
import { homedir as homedir11 } from "node:os";
|
|
68440
|
+
import { join as join15 } from "node:path";
|
|
68441
|
+
function truncateStr(value, maxLen) {
|
|
68442
|
+
if (value === null || value === undefined)
|
|
68443
|
+
return "";
|
|
68444
|
+
const s = typeof value === "string" ? value : JSON.stringify(value);
|
|
68445
|
+
if (s.length <= maxLen)
|
|
68446
|
+
return s;
|
|
68447
|
+
return `${s.slice(0, maxLen)}...[truncated, was ${s.length}b]`;
|
|
68448
|
+
}
|
|
68449
|
+
function truncateChunk(chunk) {
|
|
68450
|
+
const raw = chunk;
|
|
68451
|
+
const type = raw.message_type;
|
|
68452
|
+
switch (type) {
|
|
68453
|
+
case "reasoning_message":
|
|
68454
|
+
return {
|
|
68455
|
+
...raw,
|
|
68456
|
+
reasoning: truncateStr(raw.reasoning, CONTENT_TRUNCATE_LEN)
|
|
68457
|
+
};
|
|
68458
|
+
case "assistant_message":
|
|
68459
|
+
return {
|
|
68460
|
+
...raw,
|
|
68461
|
+
content: truncateStr(raw.content, CONTENT_TRUNCATE_LEN)
|
|
68462
|
+
};
|
|
68463
|
+
case "tool_call_message": {
|
|
68464
|
+
const truncateToolCall = (tc) => ({
|
|
68465
|
+
...tc,
|
|
68466
|
+
arguments: truncateStr(tc.arguments, CONTENT_TRUNCATE_LEN)
|
|
68467
|
+
});
|
|
68468
|
+
const result = { ...raw };
|
|
68469
|
+
if (raw.tool_call && typeof raw.tool_call === "object") {
|
|
68470
|
+
result.tool_call = truncateToolCall(raw.tool_call);
|
|
68471
|
+
}
|
|
68472
|
+
if (Array.isArray(raw.tool_calls)) {
|
|
68473
|
+
result.tool_calls = raw.tool_calls.map(truncateToolCall);
|
|
68474
|
+
}
|
|
68475
|
+
return result;
|
|
68476
|
+
}
|
|
68477
|
+
case "tool_return_message":
|
|
68478
|
+
return {
|
|
68479
|
+
...raw,
|
|
68480
|
+
tool_return: truncateStr(raw.tool_return, CONTENT_TRUNCATE_LEN)
|
|
68481
|
+
};
|
|
68482
|
+
case "ping":
|
|
68483
|
+
case "error_message":
|
|
68484
|
+
case "stop_reason":
|
|
68485
|
+
case "usage_statistics":
|
|
68486
|
+
return raw;
|
|
68487
|
+
default: {
|
|
68488
|
+
const result = { ...raw };
|
|
68489
|
+
if (typeof result.content === "string" || Array.isArray(result.content)) {
|
|
68490
|
+
result.content = truncateStr(result.content, CONTENT_TRUNCATE_LEN);
|
|
68491
|
+
}
|
|
68492
|
+
return result;
|
|
68493
|
+
}
|
|
68494
|
+
}
|
|
68495
|
+
}
|
|
68496
|
+
|
|
68497
|
+
class ChunkLog {
|
|
68498
|
+
buffer = [];
|
|
68499
|
+
dirty = false;
|
|
68500
|
+
logPath = null;
|
|
68501
|
+
agentDir = null;
|
|
68502
|
+
dirCreated = false;
|
|
68503
|
+
init(agentId, sessionId) {
|
|
68504
|
+
this.agentDir = join15(LOG_BASE_DIR, agentId);
|
|
68505
|
+
this.logPath = join15(this.agentDir, `${sessionId}.jsonl`);
|
|
68506
|
+
this.buffer = [];
|
|
68507
|
+
this.dirty = false;
|
|
68508
|
+
this.dirCreated = false;
|
|
68509
|
+
this.pruneOldSessions();
|
|
68510
|
+
}
|
|
68511
|
+
append(chunk) {
|
|
68512
|
+
this.buffer.push(truncateChunk(chunk));
|
|
68513
|
+
if (this.buffer.length > MAX_ENTRIES) {
|
|
68514
|
+
this.buffer.shift();
|
|
68515
|
+
}
|
|
68516
|
+
this.dirty = true;
|
|
68517
|
+
}
|
|
68518
|
+
flush() {
|
|
68519
|
+
if (this.dirty && this.logPath) {
|
|
68520
|
+
this.writeToDisk();
|
|
68521
|
+
this.dirty = false;
|
|
68522
|
+
}
|
|
68523
|
+
}
|
|
68524
|
+
getEntries() {
|
|
68525
|
+
return this.buffer;
|
|
68526
|
+
}
|
|
68527
|
+
get size() {
|
|
68528
|
+
return this.buffer.length;
|
|
68529
|
+
}
|
|
68530
|
+
ensureDir() {
|
|
68531
|
+
if (this.dirCreated || !this.agentDir)
|
|
68532
|
+
return;
|
|
68533
|
+
try {
|
|
68534
|
+
if (!existsSync8(this.agentDir)) {
|
|
68535
|
+
mkdirSync6(this.agentDir, { recursive: true });
|
|
68536
|
+
}
|
|
68537
|
+
this.dirCreated = true;
|
|
68538
|
+
} catch (e) {
|
|
68539
|
+
debugWarn("chunkLog", `Failed to create directory ${this.agentDir}: ${e instanceof Error ? e.message : String(e)}`);
|
|
68540
|
+
}
|
|
68541
|
+
}
|
|
68542
|
+
writeToDisk() {
|
|
68543
|
+
if (!this.logPath)
|
|
68544
|
+
return;
|
|
68545
|
+
this.ensureDir();
|
|
68546
|
+
try {
|
|
68547
|
+
const content = this.buffer.map((entry) => JSON.stringify(entry)).join(`
|
|
68548
|
+
`);
|
|
68549
|
+
writeFileSync5(this.logPath, `${content}
|
|
68550
|
+
`, "utf8");
|
|
68551
|
+
} catch (e) {
|
|
68552
|
+
debugWarn("chunkLog", `Failed to write ${this.logPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
68553
|
+
}
|
|
68554
|
+
}
|
|
68555
|
+
pruneOldSessions() {
|
|
68556
|
+
if (!this.agentDir)
|
|
68557
|
+
return;
|
|
68558
|
+
try {
|
|
68559
|
+
if (!existsSync8(this.agentDir))
|
|
68560
|
+
return;
|
|
68561
|
+
const files = readdirSync4(this.agentDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
68562
|
+
if (files.length >= MAX_SESSION_FILES) {
|
|
68563
|
+
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES + 1);
|
|
68564
|
+
for (const file of toDelete) {
|
|
68565
|
+
try {
|
|
68566
|
+
unlinkSync3(join15(this.agentDir, file));
|
|
68567
|
+
} catch (e) {
|
|
68568
|
+
debugWarn("chunkLog", `Failed to delete old session log ${file}: ${e instanceof Error ? e.message : String(e)}`);
|
|
68569
|
+
}
|
|
68570
|
+
}
|
|
68571
|
+
}
|
|
68572
|
+
} catch (e) {
|
|
68573
|
+
debugWarn("chunkLog", `Failed to prune old sessions: ${e instanceof Error ? e.message : String(e)}`);
|
|
68574
|
+
}
|
|
68575
|
+
}
|
|
68576
|
+
}
|
|
68577
|
+
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES = 5, LOG_BASE_DIR, chunkLog;
|
|
68578
|
+
var init_chunkLog = __esm(() => {
|
|
68579
|
+
init_debug();
|
|
68580
|
+
LOG_BASE_DIR = join15(homedir11(), ".letta", "logs", "chunk-logs");
|
|
68581
|
+
chunkLog = new ChunkLog;
|
|
68582
|
+
});
|
|
68583
|
+
|
|
68402
68584
|
// src/cli/helpers/streamProcessor.ts
|
|
68403
68585
|
class StreamProcessor {
|
|
68404
68586
|
pendingApprovals = new Map;
|
|
@@ -68533,6 +68715,9 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
68533
68715
|
logTiming(`TTFT: ${formatDuration(ttft)} (from POST to first content)`);
|
|
68534
68716
|
}
|
|
68535
68717
|
const { shouldOutput, errorInfo, updatedApproval } = streamProcessor.processChunk(chunk);
|
|
68718
|
+
try {
|
|
68719
|
+
chunkLog.append(chunk);
|
|
68720
|
+
} catch {}
|
|
68536
68721
|
if (abortSignal?.aborted) {
|
|
68537
68722
|
stopReason = "cancelled";
|
|
68538
68723
|
markIncompleteToolsAsCancelled(buffers, true, "user_interrupt");
|
|
@@ -68588,6 +68773,9 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
68588
68773
|
markIncompleteToolsAsCancelled(buffers, true, "stream_error");
|
|
68589
68774
|
queueMicrotask(refresh);
|
|
68590
68775
|
} finally {
|
|
68776
|
+
try {
|
|
68777
|
+
chunkLog.flush();
|
|
68778
|
+
} catch {}
|
|
68591
68779
|
if (abortSignal) {
|
|
68592
68780
|
abortSignal.removeEventListener("abort", abortHandler);
|
|
68593
68781
|
}
|
|
@@ -68662,6 +68850,7 @@ var init_stream = __esm(async () => {
|
|
|
68662
68850
|
init_error();
|
|
68663
68851
|
init_debug();
|
|
68664
68852
|
init_timing();
|
|
68853
|
+
init_chunkLog();
|
|
68665
68854
|
await __promiseAll([
|
|
68666
68855
|
init_client2(),
|
|
68667
68856
|
init_message(),
|
|
@@ -68893,7 +69082,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
68893
69082
|
return;
|
|
68894
69083
|
}
|
|
68895
69084
|
opts.onStatusChange?.("receiving", opts.connectionId);
|
|
68896
|
-
await handleIncomingMessage(parsed, socket, opts.onStatusChange, opts.connectionId);
|
|
69085
|
+
await handleIncomingMessage(parsed, socket, opts.onStatusChange, opts.connectionId, opts.defaultConversationId);
|
|
68897
69086
|
opts.onStatusChange?.("idle", opts.connectionId);
|
|
68898
69087
|
}).catch((error) => {
|
|
68899
69088
|
if (process.env.DEBUG) {
|
|
@@ -68929,11 +69118,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
68929
69118
|
}
|
|
68930
69119
|
});
|
|
68931
69120
|
}
|
|
68932
|
-
async function handleIncomingMessage(msg, socket, onStatusChange, connectionId) {
|
|
69121
|
+
async function handleIncomingMessage(msg, socket, onStatusChange, connectionId, defaultConversationId) {
|
|
68933
69122
|
try {
|
|
68934
69123
|
const agentId = msg.agentId;
|
|
68935
69124
|
const requestedConversationId = msg.conversationId || undefined;
|
|
68936
|
-
const conversationId = requestedConversationId ?? "default";
|
|
69125
|
+
const conversationId = requestedConversationId ?? defaultConversationId ?? "default";
|
|
68937
69126
|
if (!agentId) {
|
|
68938
69127
|
return;
|
|
68939
69128
|
}
|
|
@@ -69026,6 +69215,7 @@ async function handleIncomingMessage(msg, socket, onStatusChange, connectionId)
|
|
|
69026
69215
|
break;
|
|
69027
69216
|
}
|
|
69028
69217
|
const { autoAllowed, autoDenied, needsUserInput } = await classifyApprovals(approvals, {
|
|
69218
|
+
alwaysRequiresUserInput: isInteractiveApprovalTool,
|
|
69029
69219
|
treatAskAsDeny: false,
|
|
69030
69220
|
requireArgsForAutoApprove: true
|
|
69031
69221
|
});
|
|
@@ -69086,6 +69276,7 @@ var init_listen_client = __esm(async () => {
|
|
|
69086
69276
|
init_check_approval();
|
|
69087
69277
|
init_planName();
|
|
69088
69278
|
init_mode();
|
|
69279
|
+
init_interactivePolicy();
|
|
69089
69280
|
await __promiseAll([
|
|
69090
69281
|
init_approval_execution(),
|
|
69091
69282
|
init_client2(),
|
|
@@ -69121,19 +69312,19 @@ __export(exports_skills2, {
|
|
|
69121
69312
|
SKILLS_DIR: () => SKILLS_DIR2,
|
|
69122
69313
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
69123
69314
|
});
|
|
69124
|
-
import { existsSync as
|
|
69315
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
69125
69316
|
import { readdir as readdir6, readFile as readFile5 } from "node:fs/promises";
|
|
69126
|
-
import { dirname as dirname8, join as
|
|
69317
|
+
import { dirname as dirname8, join as join19 } from "node:path";
|
|
69127
69318
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
69128
69319
|
function getBundledSkillsPath2() {
|
|
69129
69320
|
const thisDir = dirname8(fileURLToPath7(import.meta.url));
|
|
69130
69321
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
69131
|
-
return
|
|
69322
|
+
return join19(thisDir, "../skills/builtin");
|
|
69132
69323
|
}
|
|
69133
|
-
return
|
|
69324
|
+
return join19(thisDir, "skills");
|
|
69134
69325
|
}
|
|
69135
69326
|
function getAgentSkillsDir2(agentId) {
|
|
69136
|
-
return
|
|
69327
|
+
return join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
69137
69328
|
}
|
|
69138
69329
|
async function getBundledSkills2() {
|
|
69139
69330
|
const bundledPath = getBundledSkillsPath2();
|
|
@@ -69142,7 +69333,7 @@ async function getBundledSkills2() {
|
|
|
69142
69333
|
}
|
|
69143
69334
|
async function discoverSkillsFromDir2(skillsPath, source) {
|
|
69144
69335
|
const errors = [];
|
|
69145
|
-
if (!
|
|
69336
|
+
if (!existsSync10(skillsPath)) {
|
|
69146
69337
|
return { skills: [], errors: [] };
|
|
69147
69338
|
}
|
|
69148
69339
|
const skills = [];
|
|
@@ -69156,7 +69347,7 @@ async function discoverSkillsFromDir2(skillsPath, source) {
|
|
|
69156
69347
|
}
|
|
69157
69348
|
return { skills, errors };
|
|
69158
69349
|
}
|
|
69159
|
-
async function discoverSkills2(projectSkillsPath =
|
|
69350
|
+
async function discoverSkills2(projectSkillsPath = join19(process.cwd(), SKILLS_DIR2), agentId, options) {
|
|
69160
69351
|
const allErrors = [];
|
|
69161
69352
|
const skillsById = new Map;
|
|
69162
69353
|
const sourceSet = new Set(options?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -69198,7 +69389,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source) {
|
|
|
69198
69389
|
try {
|
|
69199
69390
|
const entries = await readdir6(currentPath, { withFileTypes: true });
|
|
69200
69391
|
for (const entry of entries) {
|
|
69201
|
-
const fullPath =
|
|
69392
|
+
const fullPath = join19(currentPath, entry.name);
|
|
69202
69393
|
if (entry.isDirectory()) {
|
|
69203
69394
|
await findSkillFiles2(fullPath, rootPath, skills, errors, source);
|
|
69204
69395
|
} else if (entry.isFile() && entry.name.toUpperCase() === "SKILL.MD") {
|
|
@@ -69273,7 +69464,7 @@ ${lines.join(`
|
|
|
69273
69464
|
var SKILLS_DIR2 = ".skills", GLOBAL_SKILLS_DIR2;
|
|
69274
69465
|
var init_skills2 = __esm(() => {
|
|
69275
69466
|
init_skillSources();
|
|
69276
|
-
GLOBAL_SKILLS_DIR2 =
|
|
69467
|
+
GLOBAL_SKILLS_DIR2 = join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
69277
69468
|
});
|
|
69278
69469
|
|
|
69279
69470
|
// src/utils/fs.ts
|
|
@@ -69287,10 +69478,10 @@ __export(exports_fs, {
|
|
|
69287
69478
|
exists: () => exists2
|
|
69288
69479
|
});
|
|
69289
69480
|
import {
|
|
69290
|
-
existsSync as
|
|
69481
|
+
existsSync as existsSync11,
|
|
69291
69482
|
readFileSync as fsReadFileSync2,
|
|
69292
69483
|
writeFileSync as fsWriteFileSync2,
|
|
69293
|
-
mkdirSync as
|
|
69484
|
+
mkdirSync as mkdirSync8
|
|
69294
69485
|
} from "node:fs";
|
|
69295
69486
|
import { dirname as dirname9 } from "node:path";
|
|
69296
69487
|
async function readFile6(path19) {
|
|
@@ -69298,16 +69489,16 @@ async function readFile6(path19) {
|
|
|
69298
69489
|
}
|
|
69299
69490
|
async function writeFile2(path19, content) {
|
|
69300
69491
|
const dir = dirname9(path19);
|
|
69301
|
-
if (!
|
|
69302
|
-
|
|
69492
|
+
if (!existsSync11(dir)) {
|
|
69493
|
+
mkdirSync8(dir, { recursive: true });
|
|
69303
69494
|
}
|
|
69304
69495
|
fsWriteFileSync2(path19, content, { encoding: "utf-8", flush: true });
|
|
69305
69496
|
}
|
|
69306
69497
|
function exists2(path19) {
|
|
69307
|
-
return
|
|
69498
|
+
return existsSync11(path19);
|
|
69308
69499
|
}
|
|
69309
69500
|
async function mkdir2(path19, options) {
|
|
69310
|
-
|
|
69501
|
+
mkdirSync8(path19, options);
|
|
69311
69502
|
}
|
|
69312
69503
|
async function readJsonFile(path19) {
|
|
69313
69504
|
const text = await readFile6(path19);
|
|
@@ -69627,7 +69818,7 @@ __export(exports_auto_update, {
|
|
|
69627
69818
|
import { execFile as execFile4 } from "node:child_process";
|
|
69628
69819
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
69629
69820
|
import { readdir as readdir7, rm } from "node:fs/promises";
|
|
69630
|
-
import { join as
|
|
69821
|
+
import { join as join20 } from "node:path";
|
|
69631
69822
|
import { promisify as promisify4 } from "node:util";
|
|
69632
69823
|
function debugLog2(...args) {
|
|
69633
69824
|
if (DEBUG) {
|
|
@@ -69787,12 +69978,12 @@ async function getNpmGlobalPath() {
|
|
|
69787
69978
|
}
|
|
69788
69979
|
}
|
|
69789
69980
|
async function cleanupOrphanedDirs(globalPath) {
|
|
69790
|
-
const lettaAiDir =
|
|
69981
|
+
const lettaAiDir = join20(globalPath, "lib/node_modules/@letta-ai");
|
|
69791
69982
|
try {
|
|
69792
69983
|
const entries = await readdir7(lettaAiDir);
|
|
69793
69984
|
for (const entry of entries) {
|
|
69794
69985
|
if (entry.startsWith(".letta-code-")) {
|
|
69795
|
-
const orphanPath =
|
|
69986
|
+
const orphanPath = join20(lettaAiDir, entry);
|
|
69796
69987
|
debugLog2("Cleaning orphaned temp directory:", orphanPath);
|
|
69797
69988
|
await rm(orphanPath, { recursive: true, force: true });
|
|
69798
69989
|
}
|
|
@@ -70148,9 +70339,9 @@ __export(exports_subagents2, {
|
|
|
70148
70339
|
GLOBAL_AGENTS_DIR: () => GLOBAL_AGENTS_DIR2,
|
|
70149
70340
|
AGENTS_DIR: () => AGENTS_DIR2
|
|
70150
70341
|
});
|
|
70151
|
-
import { existsSync as
|
|
70342
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
70152
70343
|
import { readdir as readdir8, readFile as readFile7 } from "node:fs/promises";
|
|
70153
|
-
import { join as
|
|
70344
|
+
import { join as join22 } from "node:path";
|
|
70154
70345
|
function isValidName2(name) {
|
|
70155
70346
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
70156
70347
|
}
|
|
@@ -70232,7 +70423,7 @@ function getBuiltinSubagentNames2() {
|
|
|
70232
70423
|
return new Set(Object.keys(getBuiltinSubagents2()));
|
|
70233
70424
|
}
|
|
70234
70425
|
async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors) {
|
|
70235
|
-
if (!
|
|
70426
|
+
if (!existsSync13(agentsDir)) {
|
|
70236
70427
|
return;
|
|
70237
70428
|
}
|
|
70238
70429
|
try {
|
|
@@ -70241,7 +70432,7 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
|
|
|
70241
70432
|
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
70242
70433
|
continue;
|
|
70243
70434
|
}
|
|
70244
|
-
const filePath =
|
|
70435
|
+
const filePath = join22(agentsDir, entry.name);
|
|
70245
70436
|
try {
|
|
70246
70437
|
const config = await parseSubagentFile2(filePath);
|
|
70247
70438
|
if (config) {
|
|
@@ -70273,7 +70464,7 @@ async function discoverSubagents2(workingDirectory = process.cwd()) {
|
|
|
70273
70464
|
const subagents = [];
|
|
70274
70465
|
const seenNames = new Set;
|
|
70275
70466
|
await discoverSubagentsFromDir2(GLOBAL_AGENTS_DIR2, seenNames, subagents, errors);
|
|
70276
|
-
const projectAgentsDir =
|
|
70467
|
+
const projectAgentsDir = join22(workingDirectory, AGENTS_DIR2);
|
|
70277
70468
|
await discoverSubagentsFromDir2(projectAgentsDir, seenNames, subagents, errors);
|
|
70278
70469
|
return { subagents, errors };
|
|
70279
70470
|
}
|
|
@@ -70316,7 +70507,7 @@ var init_subagents2 = __esm(() => {
|
|
|
70316
70507
|
recall_default,
|
|
70317
70508
|
reflection_default
|
|
70318
70509
|
];
|
|
70319
|
-
GLOBAL_AGENTS_DIR2 =
|
|
70510
|
+
GLOBAL_AGENTS_DIR2 = join22(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
|
|
70320
70511
|
VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
|
|
70321
70512
|
cache5 = {
|
|
70322
70513
|
builtins: null,
|
|
@@ -71213,6 +71404,12 @@ var init_cli2 = __esm(() => {
|
|
|
71213
71404
|
});
|
|
71214
71405
|
|
|
71215
71406
|
// src/agent/turn-recovery-policy.ts
|
|
71407
|
+
function hasNonRetryableQuotaDetail(detail) {
|
|
71408
|
+
if (typeof detail !== "string")
|
|
71409
|
+
return false;
|
|
71410
|
+
const normalized = detail.toLowerCase();
|
|
71411
|
+
return NON_RETRYABLE_429_REASONS.some((reason) => normalized.includes(reason)) || NON_RETRYABLE_QUOTA_DETAIL_PATTERNS.some((pattern) => normalized.includes(pattern));
|
|
71412
|
+
}
|
|
71216
71413
|
function isInvalidToolCallIdsError(detail) {
|
|
71217
71414
|
if (typeof detail !== "string")
|
|
71218
71415
|
return false;
|
|
@@ -71245,9 +71442,12 @@ function isNonRetryableProviderErrorDetail(detail) {
|
|
|
71245
71442
|
}
|
|
71246
71443
|
function shouldRetryRunMetadataError(errorType, detail) {
|
|
71247
71444
|
const explicitLlmError = errorType === "llm_error";
|
|
71445
|
+
const nonRetryableQuotaDetail = hasNonRetryableQuotaDetail(detail);
|
|
71248
71446
|
const retryable429Detail = typeof detail === "string" && RETRYABLE_429_PATTERN.test(detail);
|
|
71249
71447
|
const retryableDetail = isRetryableProviderErrorDetail(detail);
|
|
71250
71448
|
const nonRetryableDetail = isNonRetryableProviderErrorDetail(detail);
|
|
71449
|
+
if (nonRetryableQuotaDetail)
|
|
71450
|
+
return false;
|
|
71251
71451
|
if (nonRetryableDetail && !retryable429Detail)
|
|
71252
71452
|
return false;
|
|
71253
71453
|
if (explicitLlmError)
|
|
@@ -71256,10 +71456,9 @@ function shouldRetryRunMetadataError(errorType, detail) {
|
|
|
71256
71456
|
}
|
|
71257
71457
|
function shouldRetryPreStreamTransientError(opts) {
|
|
71258
71458
|
const { status, detail } = opts;
|
|
71459
|
+
if (hasNonRetryableQuotaDetail(detail))
|
|
71460
|
+
return false;
|
|
71259
71461
|
if (status === 429) {
|
|
71260
|
-
if (typeof detail === "string" && NON_RETRYABLE_429_REASONS.some((r) => detail.includes(r))) {
|
|
71261
|
-
return false;
|
|
71262
|
-
}
|
|
71263
71462
|
return true;
|
|
71264
71463
|
}
|
|
71265
71464
|
if (status !== undefined && status >= 500)
|
|
@@ -71347,7 +71546,7 @@ function rebuildInputWithFreshDenials(currentInput, serverApprovals, denialReaso
|
|
|
71347
71546
|
function shouldAttemptApprovalRecovery(opts) {
|
|
71348
71547
|
return opts.approvalPendingDetected && opts.retries < opts.maxRetries;
|
|
71349
71548
|
}
|
|
71350
|
-
var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN;
|
|
71549
|
+
var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN;
|
|
71351
71550
|
var init_turn_recovery_policy = __esm(() => {
|
|
71352
71551
|
init_zaiErrors();
|
|
71353
71552
|
RETRYABLE_PROVIDER_DETAIL_PATTERNS = [
|
|
@@ -71381,7 +71580,19 @@ var init_turn_recovery_policy = __esm(() => {
|
|
|
71381
71580
|
"context_length_exceeded",
|
|
71382
71581
|
"invalid_encrypted_content"
|
|
71383
71582
|
];
|
|
71384
|
-
NON_RETRYABLE_429_REASONS = [
|
|
71583
|
+
NON_RETRYABLE_429_REASONS = [
|
|
71584
|
+
"agents-limit-exceeded",
|
|
71585
|
+
"exceeded-quota",
|
|
71586
|
+
"free-usage-exceeded",
|
|
71587
|
+
"premium-usage-exceeded",
|
|
71588
|
+
"standard-usage-exceeded",
|
|
71589
|
+
"basic-usage-exceeded",
|
|
71590
|
+
"not-enough-credits"
|
|
71591
|
+
];
|
|
71592
|
+
NON_RETRYABLE_QUOTA_DETAIL_PATTERNS = [
|
|
71593
|
+
"hosted model usage limit",
|
|
71594
|
+
"out of credits"
|
|
71595
|
+
];
|
|
71385
71596
|
NON_RETRYABLE_4XX_PATTERN = /Error code:\s*4(0[0-8]|1\d|2\d|3\d|4\d|51)/i;
|
|
71386
71597
|
RETRYABLE_429_PATTERN = /Error code:\s*429|rate limit|too many requests/i;
|
|
71387
71598
|
});
|
|
@@ -71930,6 +72141,18 @@ function isCreditExhaustedError2(e, reasons) {
|
|
|
71930
72141
|
return false;
|
|
71931
72142
|
return hasErrorReason2(e, "not-enough-credits", reasons);
|
|
71932
72143
|
}
|
|
72144
|
+
function getTierUsageLimitMessage2(reasons) {
|
|
72145
|
+
if (reasons.includes("premium-usage-exceeded")) {
|
|
72146
|
+
return `You've reached your Premium model usage limit. Try switching to Standard or Basic hosted models with /model. View your plan and usage at ${LETTA_USAGE_URL2}, or connect your own provider keys with /connect.`;
|
|
72147
|
+
}
|
|
72148
|
+
if (reasons.includes("standard-usage-exceeded")) {
|
|
72149
|
+
return `You've reached your Standard model usage limit. Try switching to Basic hosted models with /model. View your plan and usage at ${LETTA_USAGE_URL2}, or connect your own provider keys with /connect.`;
|
|
72150
|
+
}
|
|
72151
|
+
if (reasons.includes("basic-usage-exceeded")) {
|
|
72152
|
+
return `You've reached your Basic model usage limit. Try switching models with /model, view your plan and usage at ${LETTA_USAGE_URL2}, or connect your own provider keys with /connect.`;
|
|
72153
|
+
}
|
|
72154
|
+
return;
|
|
72155
|
+
}
|
|
71933
72156
|
function findEncryptedContentDetail2(e) {
|
|
71934
72157
|
if (typeof e !== "object" || e === null)
|
|
71935
72158
|
return;
|
|
@@ -72032,9 +72255,9 @@ Delete ${resourceType} at: ${LETTA_AGENTS_URL2}`;
|
|
|
72032
72255
|
if (isCreditExhaustedError2(e, reasons)) {
|
|
72033
72256
|
return `Your account is out of credits for hosted inference. Add credits, enable auto-recharge, or upgrade at ${LETTA_USAGE_URL2}. You can also connect your own provider keys with /connect.`;
|
|
72034
72257
|
}
|
|
72035
|
-
|
|
72036
|
-
|
|
72037
|
-
|
|
72258
|
+
const tierUsageLimitMsg = getTierUsageLimitMessage2(reasons);
|
|
72259
|
+
if (tierUsageLimitMsg)
|
|
72260
|
+
return tierUsageLimitMsg;
|
|
72038
72261
|
if (hasErrorReason2(e, "byok-not-available-on-free-tier", reasons)) {
|
|
72039
72262
|
const { modelDisplayName } = getErrorContext();
|
|
72040
72263
|
const modelInfo = modelDisplayName ? ` (${modelDisplayName})` : "";
|
|
@@ -72555,7 +72778,7 @@ var init_catalog = __esm(() => {
|
|
|
72555
72778
|
});
|
|
72556
72779
|
|
|
72557
72780
|
// src/reminders/engine.ts
|
|
72558
|
-
import { join as
|
|
72781
|
+
import { join as join23 } from "node:path";
|
|
72559
72782
|
async function buildSessionContextReminder(context3) {
|
|
72560
72783
|
if (!context3.sessionContextReminderEnabled || context3.state.hasSentSessionContext) {
|
|
72561
72784
|
return null;
|
|
@@ -72579,7 +72802,7 @@ async function buildSkillsReminder(context3) {
|
|
|
72579
72802
|
const previousSkillsReminder = context3.state.cachedSkillsReminder;
|
|
72580
72803
|
let latestSkillsReminder = previousSkillsReminder ?? "";
|
|
72581
72804
|
try {
|
|
72582
|
-
const skillsDir = getSkillsDirectory() ||
|
|
72805
|
+
const skillsDir = getSkillsDirectory() || join23(process.cwd(), SKILLS_DIR);
|
|
72583
72806
|
const { skills } = await discoverSkills(skillsDir, context3.agent.id, {
|
|
72584
72807
|
sources: context3.skillSources
|
|
72585
72808
|
});
|
|
@@ -73010,7 +73233,7 @@ function parseRegistryHandle(handle) {
|
|
|
73010
73233
|
}
|
|
73011
73234
|
async function importAgentFromRegistry(options) {
|
|
73012
73235
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
73013
|
-
const { join:
|
|
73236
|
+
const { join: join24 } = await import("node:path");
|
|
73014
73237
|
const { writeFile: writeFile4, unlink } = await import("node:fs/promises");
|
|
73015
73238
|
const { author, name } = parseRegistryHandle(options.handle);
|
|
73016
73239
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -73022,7 +73245,7 @@ async function importAgentFromRegistry(options) {
|
|
|
73022
73245
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
73023
73246
|
}
|
|
73024
73247
|
const afContent = await response.text();
|
|
73025
|
-
const tempPath =
|
|
73248
|
+
const tempPath = join24(tmpdir3(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
73026
73249
|
await writeFile4(tempPath, afContent, "utf-8");
|
|
73027
73250
|
try {
|
|
73028
73251
|
const result = await importAgentFromFile({
|
|
@@ -73745,19 +73968,6 @@ In headless mode, use:
|
|
|
73745
73968
|
conversationId
|
|
73746
73969
|
});
|
|
73747
73970
|
}
|
|
73748
|
-
for (const label of ["skills", "loaded_skills"]) {
|
|
73749
|
-
try {
|
|
73750
|
-
const block = await client.agents.blocks.retrieve(label, {
|
|
73751
|
-
agent_id: agent.id
|
|
73752
|
-
});
|
|
73753
|
-
if (block) {
|
|
73754
|
-
await client.agents.blocks.detach(block.id, {
|
|
73755
|
-
agent_id: agent.id
|
|
73756
|
-
});
|
|
73757
|
-
await client.blocks.delete(block.id);
|
|
73758
|
-
}
|
|
73759
|
-
} catch {}
|
|
73760
|
-
}
|
|
73761
73971
|
setAgentContext2(agent.id, skillsDirectory, resolvedSkillSources);
|
|
73762
73972
|
const outputFormat = values["output-format"] || "text";
|
|
73763
73973
|
const includePartialMessages = Boolean(values["include-partial-messages"]);
|
|
@@ -73913,7 +74123,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
73913
74123
|
syncReminderStateFromContextTracker(sharedReminderState, reminderContextTracker);
|
|
73914
74124
|
const lastRunAt = agent.last_run_completion;
|
|
73915
74125
|
const { parts: sharedReminderParts } = await buildSharedReminderParts({
|
|
73916
|
-
mode: "headless-one-shot",
|
|
74126
|
+
mode: isSubagent ? "subagent" : "headless-one-shot",
|
|
73917
74127
|
agent: {
|
|
73918
74128
|
id: agent.id,
|
|
73919
74129
|
name: agent.name,
|
|
@@ -74512,6 +74722,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
74512
74722
|
let currentAbortController = null;
|
|
74513
74723
|
const reminderContextTracker = createContextTracker();
|
|
74514
74724
|
const sharedReminderState = createSharedReminderState();
|
|
74725
|
+
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
74515
74726
|
const resolveAllPendingApprovals = async () => {
|
|
74516
74727
|
const { getResumeData: getResumeData3 } = await Promise.resolve().then(() => (init_check_approval(), exports_check_approval));
|
|
74517
74728
|
while (true) {
|
|
@@ -74863,7 +75074,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
74863
75074
|
syncReminderStateFromContextTracker(sharedReminderState, reminderContextTracker);
|
|
74864
75075
|
const lastRunAt = agent.last_run_completion;
|
|
74865
75076
|
const { parts: sharedReminderParts } = await buildSharedReminderParts({
|
|
74866
|
-
mode: "headless-bidirectional",
|
|
75077
|
+
mode: isSubagent ? "subagent" : "headless-bidirectional",
|
|
74867
75078
|
agent: {
|
|
74868
75079
|
id: agent.id,
|
|
74869
75080
|
name: agent.name,
|
|
@@ -75443,10 +75654,10 @@ __export(exports_settings, {
|
|
|
75443
75654
|
loadProjectSettings: () => loadProjectSettings,
|
|
75444
75655
|
getSetting: () => getSetting
|
|
75445
75656
|
});
|
|
75446
|
-
import { homedir as
|
|
75447
|
-
import { join as
|
|
75657
|
+
import { homedir as homedir16 } from "node:os";
|
|
75658
|
+
import { join as join24 } from "node:path";
|
|
75448
75659
|
function getSettingsPath() {
|
|
75449
|
-
return
|
|
75660
|
+
return join24(homedir16(), ".letta", "settings.json");
|
|
75450
75661
|
}
|
|
75451
75662
|
async function loadSettings() {
|
|
75452
75663
|
const settingsPath = getSettingsPath();
|
|
@@ -75483,7 +75694,7 @@ async function getSetting(key) {
|
|
|
75483
75694
|
return settings[key];
|
|
75484
75695
|
}
|
|
75485
75696
|
function getProjectSettingsPath() {
|
|
75486
|
-
return
|
|
75697
|
+
return join24(process.cwd(), ".letta", "settings.local.json");
|
|
75487
75698
|
}
|
|
75488
75699
|
async function loadProjectSettings() {
|
|
75489
75700
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -75501,7 +75712,7 @@ async function loadProjectSettings() {
|
|
|
75501
75712
|
}
|
|
75502
75713
|
async function saveProjectSettings(settings) {
|
|
75503
75714
|
const settingsPath = getProjectSettingsPath();
|
|
75504
|
-
const dirPath =
|
|
75715
|
+
const dirPath = join24(process.cwd(), ".letta");
|
|
75505
75716
|
try {
|
|
75506
75717
|
if (!exists(dirPath)) {
|
|
75507
75718
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -78997,9 +79208,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
78997
79208
|
const relPath = relative7(cwd2, filePath);
|
|
78998
79209
|
const displayPath = relPath.startsWith("..") ? filePath : relPath;
|
|
78999
79210
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
79000
|
-
const { existsSync:
|
|
79211
|
+
const { existsSync: existsSync14 } = __require("node:fs");
|
|
79001
79212
|
try {
|
|
79002
|
-
if (
|
|
79213
|
+
if (existsSync14(filePath)) {
|
|
79003
79214
|
return `Overwrite ${displayPath}?`;
|
|
79004
79215
|
}
|
|
79005
79216
|
} catch {}
|
|
@@ -79701,9 +79912,9 @@ function getHeaderText(fileEdit) {
|
|
|
79701
79912
|
const relPath = relative7(cwd2, fileEdit.filePath);
|
|
79702
79913
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
79703
79914
|
if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
|
|
79704
|
-
const { existsSync:
|
|
79915
|
+
const { existsSync: existsSync14 } = __require("node:fs");
|
|
79705
79916
|
try {
|
|
79706
|
-
if (
|
|
79917
|
+
if (existsSync14(fileEdit.filePath)) {
|
|
79707
79918
|
return `Overwrite ${displayPath}?`;
|
|
79708
79919
|
}
|
|
79709
79920
|
} catch {}
|
|
@@ -82950,9 +83161,9 @@ var init_pasteRegistry = __esm(() => {
|
|
|
82950
83161
|
|
|
82951
83162
|
// src/cli/helpers/clipboard.ts
|
|
82952
83163
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
82953
|
-
import { existsSync as
|
|
83164
|
+
import { existsSync as existsSync14, readFileSync as readFileSync3, statSync as statSync4, unlinkSync as unlinkSync5 } from "node:fs";
|
|
82954
83165
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
82955
|
-
import { basename as basename3, extname as extname5, isAbsolute as isAbsolute16, join as
|
|
83166
|
+
import { basename as basename3, extname as extname5, isAbsolute as isAbsolute16, join as join25, resolve as resolve22 } from "node:path";
|
|
82956
83167
|
function countLines2(text) {
|
|
82957
83168
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
82958
83169
|
}
|
|
@@ -83002,7 +83213,7 @@ function translatePasteForImages(paste) {
|
|
|
83002
83213
|
if (!isAbsolute16(filePath))
|
|
83003
83214
|
filePath = resolve22(process.cwd(), filePath);
|
|
83004
83215
|
const ext3 = extname5(filePath || "").toLowerCase();
|
|
83005
|
-
if (IMAGE_EXTS.has(ext3) &&
|
|
83216
|
+
if (IMAGE_EXTS.has(ext3) && existsSync14(filePath) && statSync4(filePath).isFile()) {
|
|
83006
83217
|
const buf = readFileSync3(filePath);
|
|
83007
83218
|
const b64 = buf.toString("base64");
|
|
83008
83219
|
const mt = ext3 === ".png" ? "image/png" : ext3 === ".jpg" || ext3 === ".jpeg" ? "image/jpeg" : ext3 === ".gif" ? "image/gif" : ext3 === ".webp" ? "image/webp" : ext3 === ".bmp" ? "image/bmp" : ext3 === ".svg" ? "image/svg+xml" : ext3 === ".tif" || ext3 === ".tiff" ? "image/tiff" : ext3 === ".heic" ? "image/heic" : ext3 === ".heif" ? "image/heif" : ext3 === ".avif" ? "image/avif" : "application/octet-stream";
|
|
@@ -83020,7 +83231,7 @@ function translatePasteForImages(paste) {
|
|
|
83020
83231
|
function getClipboardImageToTempFile() {
|
|
83021
83232
|
if (process.platform !== "darwin")
|
|
83022
83233
|
return null;
|
|
83023
|
-
const tempPath =
|
|
83234
|
+
const tempPath = join25(tmpdir3(), `letta-clipboard-${Date.now()}.bin`);
|
|
83024
83235
|
try {
|
|
83025
83236
|
const jxa = `
|
|
83026
83237
|
ObjC.import('AppKit');
|
|
@@ -83043,13 +83254,13 @@ function getClipboardImageToTempFile() {
|
|
|
83043
83254
|
encoding: "utf8",
|
|
83044
83255
|
stdio: ["ignore", "pipe", "ignore"]
|
|
83045
83256
|
}).trim();
|
|
83046
|
-
if (!uti || !
|
|
83257
|
+
if (!uti || !existsSync14(tempPath))
|
|
83047
83258
|
return null;
|
|
83048
83259
|
return { tempPath, uti };
|
|
83049
83260
|
} catch {
|
|
83050
|
-
if (
|
|
83261
|
+
if (existsSync14(tempPath)) {
|
|
83051
83262
|
try {
|
|
83052
|
-
|
|
83263
|
+
unlinkSync5(tempPath);
|
|
83053
83264
|
} catch {}
|
|
83054
83265
|
}
|
|
83055
83266
|
return null;
|
|
@@ -83065,7 +83276,7 @@ async function tryImportClipboardImageMac() {
|
|
|
83065
83276
|
try {
|
|
83066
83277
|
const buffer = readFileSync3(tempPath);
|
|
83067
83278
|
try {
|
|
83068
|
-
|
|
83279
|
+
unlinkSync5(tempPath);
|
|
83069
83280
|
} catch {}
|
|
83070
83281
|
const mediaType = UTI_TO_MEDIA_TYPE[uti] || "image/png";
|
|
83071
83282
|
const resized = await resizeImageIfNeeded3(buffer, mediaType);
|
|
@@ -83080,9 +83291,9 @@ async function tryImportClipboardImageMac() {
|
|
|
83080
83291
|
height: resized.height
|
|
83081
83292
|
};
|
|
83082
83293
|
} catch (err) {
|
|
83083
|
-
if (
|
|
83294
|
+
if (existsSync14(tempPath)) {
|
|
83084
83295
|
try {
|
|
83085
|
-
|
|
83296
|
+
unlinkSync5(tempPath);
|
|
83086
83297
|
} catch {}
|
|
83087
83298
|
}
|
|
83088
83299
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -83657,13 +83868,13 @@ __export(exports_terminalKeybindingInstaller, {
|
|
|
83657
83868
|
});
|
|
83658
83869
|
import {
|
|
83659
83870
|
copyFileSync,
|
|
83660
|
-
existsSync as
|
|
83661
|
-
mkdirSync as
|
|
83871
|
+
existsSync as existsSync15,
|
|
83872
|
+
mkdirSync as mkdirSync10,
|
|
83662
83873
|
readFileSync as readFileSync4,
|
|
83663
|
-
writeFileSync as
|
|
83874
|
+
writeFileSync as writeFileSync7
|
|
83664
83875
|
} from "node:fs";
|
|
83665
|
-
import { homedir as
|
|
83666
|
-
import { dirname as dirname11, join as
|
|
83876
|
+
import { homedir as homedir17, platform as platform4 } from "node:os";
|
|
83877
|
+
import { dirname as dirname11, join as join26 } from "node:path";
|
|
83667
83878
|
function detectTerminalType() {
|
|
83668
83879
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
83669
83880
|
return "cursor";
|
|
@@ -83695,16 +83906,16 @@ function getKeybindingsPath(terminal) {
|
|
|
83695
83906
|
}[terminal];
|
|
83696
83907
|
const os5 = platform4();
|
|
83697
83908
|
if (os5 === "darwin") {
|
|
83698
|
-
return
|
|
83909
|
+
return join26(homedir17(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
83699
83910
|
}
|
|
83700
83911
|
if (os5 === "win32") {
|
|
83701
83912
|
const appData = process.env.APPDATA;
|
|
83702
83913
|
if (!appData)
|
|
83703
83914
|
return null;
|
|
83704
|
-
return
|
|
83915
|
+
return join26(appData, appName, "User", "keybindings.json");
|
|
83705
83916
|
}
|
|
83706
83917
|
if (os5 === "linux") {
|
|
83707
|
-
return
|
|
83918
|
+
return join26(homedir17(), ".config", appName, "User", "keybindings.json");
|
|
83708
83919
|
}
|
|
83709
83920
|
return null;
|
|
83710
83921
|
}
|
|
@@ -83726,7 +83937,7 @@ function parseKeybindings(content) {
|
|
|
83726
83937
|
}
|
|
83727
83938
|
}
|
|
83728
83939
|
function keybindingExists(keybindingsPath) {
|
|
83729
|
-
if (!
|
|
83940
|
+
if (!existsSync15(keybindingsPath))
|
|
83730
83941
|
return false;
|
|
83731
83942
|
try {
|
|
83732
83943
|
const content = readFileSync4(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -83739,7 +83950,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
83739
83950
|
}
|
|
83740
83951
|
}
|
|
83741
83952
|
function createBackup(keybindingsPath) {
|
|
83742
|
-
if (!
|
|
83953
|
+
if (!existsSync15(keybindingsPath))
|
|
83743
83954
|
return null;
|
|
83744
83955
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
83745
83956
|
try {
|
|
@@ -83755,12 +83966,12 @@ function installKeybinding(keybindingsPath) {
|
|
|
83755
83966
|
return { success: true, alreadyExists: true };
|
|
83756
83967
|
}
|
|
83757
83968
|
const parentDir = dirname11(keybindingsPath);
|
|
83758
|
-
if (!
|
|
83759
|
-
|
|
83969
|
+
if (!existsSync15(parentDir)) {
|
|
83970
|
+
mkdirSync10(parentDir, { recursive: true });
|
|
83760
83971
|
}
|
|
83761
83972
|
let keybindings = [];
|
|
83762
83973
|
let backupPath = null;
|
|
83763
|
-
if (
|
|
83974
|
+
if (existsSync15(keybindingsPath)) {
|
|
83764
83975
|
backupPath = createBackup(keybindingsPath);
|
|
83765
83976
|
const content = readFileSync4(keybindingsPath, { encoding: "utf-8" });
|
|
83766
83977
|
const parsed = parseKeybindings(content);
|
|
@@ -83775,7 +83986,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
83775
83986
|
keybindings.push(SHIFT_ENTER_KEYBINDING);
|
|
83776
83987
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
83777
83988
|
`;
|
|
83778
|
-
|
|
83989
|
+
writeFileSync7(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
83779
83990
|
return {
|
|
83780
83991
|
success: true,
|
|
83781
83992
|
backupPath: backupPath ?? undefined
|
|
@@ -83790,7 +84001,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
83790
84001
|
}
|
|
83791
84002
|
function removeKeybinding(keybindingsPath) {
|
|
83792
84003
|
try {
|
|
83793
|
-
if (!
|
|
84004
|
+
if (!existsSync15(keybindingsPath)) {
|
|
83794
84005
|
return { success: true };
|
|
83795
84006
|
}
|
|
83796
84007
|
const content = readFileSync4(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -83804,7 +84015,7 @@ function removeKeybinding(keybindingsPath) {
|
|
|
83804
84015
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
83805
84016
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
83806
84017
|
`;
|
|
83807
|
-
|
|
84018
|
+
writeFileSync7(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
83808
84019
|
return { success: true };
|
|
83809
84020
|
} catch (error) {
|
|
83810
84021
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -83857,17 +84068,17 @@ function getWezTermConfigPath() {
|
|
|
83857
84068
|
}
|
|
83858
84069
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
83859
84070
|
if (xdgConfig) {
|
|
83860
|
-
const xdgPath =
|
|
83861
|
-
if (
|
|
84071
|
+
const xdgPath = join26(xdgConfig, "wezterm", "wezterm.lua");
|
|
84072
|
+
if (existsSync15(xdgPath))
|
|
83862
84073
|
return xdgPath;
|
|
83863
84074
|
}
|
|
83864
|
-
const configPath =
|
|
83865
|
-
if (
|
|
84075
|
+
const configPath = join26(homedir17(), ".config", "wezterm", "wezterm.lua");
|
|
84076
|
+
if (existsSync15(configPath))
|
|
83866
84077
|
return configPath;
|
|
83867
|
-
return
|
|
84078
|
+
return join26(homedir17(), ".wezterm.lua");
|
|
83868
84079
|
}
|
|
83869
84080
|
function wezTermDeleteFixExists(configPath) {
|
|
83870
|
-
if (!
|
|
84081
|
+
if (!existsSync15(configPath))
|
|
83871
84082
|
return false;
|
|
83872
84083
|
try {
|
|
83873
84084
|
const content = readFileSync4(configPath, { encoding: "utf-8" });
|
|
@@ -83884,7 +84095,7 @@ function installWezTermDeleteFix() {
|
|
|
83884
84095
|
}
|
|
83885
84096
|
let content = "";
|
|
83886
84097
|
let backupPath = null;
|
|
83887
|
-
if (
|
|
84098
|
+
if (existsSync15(configPath)) {
|
|
83888
84099
|
backupPath = `${configPath}.letta-backup`;
|
|
83889
84100
|
copyFileSync(configPath, backupPath);
|
|
83890
84101
|
content = readFileSync4(configPath, { encoding: "utf-8" });
|
|
@@ -83914,10 +84125,10 @@ ${WEZTERM_DELETE_FIX}
|
|
|
83914
84125
|
`;
|
|
83915
84126
|
}
|
|
83916
84127
|
const parentDir = dirname11(configPath);
|
|
83917
|
-
if (!
|
|
83918
|
-
|
|
84128
|
+
if (!existsSync15(parentDir)) {
|
|
84129
|
+
mkdirSync10(parentDir, { recursive: true });
|
|
83919
84130
|
}
|
|
83920
|
-
|
|
84131
|
+
writeFileSync7(configPath, content, { encoding: "utf-8" });
|
|
83921
84132
|
return {
|
|
83922
84133
|
success: true,
|
|
83923
84134
|
backupPath: backupPath ?? undefined
|
|
@@ -84405,9 +84616,9 @@ __export(exports_custom, {
|
|
|
84405
84616
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
84406
84617
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
84407
84618
|
});
|
|
84408
|
-
import { existsSync as
|
|
84619
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
84409
84620
|
import { readdir as readdir9, readFile as readFile9 } from "node:fs/promises";
|
|
84410
|
-
import { basename as basename4, dirname as dirname12, join as
|
|
84621
|
+
import { basename as basename4, dirname as dirname12, join as join27 } from "node:path";
|
|
84411
84622
|
async function getCustomCommands() {
|
|
84412
84623
|
if (cachedCommands !== null) {
|
|
84413
84624
|
return cachedCommands;
|
|
@@ -84418,7 +84629,7 @@ async function getCustomCommands() {
|
|
|
84418
84629
|
function refreshCustomCommands() {
|
|
84419
84630
|
cachedCommands = null;
|
|
84420
84631
|
}
|
|
84421
|
-
async function discoverCustomCommands(projectPath =
|
|
84632
|
+
async function discoverCustomCommands(projectPath = join27(process.cwd(), COMMANDS_DIR)) {
|
|
84422
84633
|
const commandsById = new Map;
|
|
84423
84634
|
const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
|
|
84424
84635
|
for (const cmd of userCommands) {
|
|
@@ -84439,7 +84650,7 @@ async function discoverCustomCommands(projectPath = join26(process.cwd(), COMMAN
|
|
|
84439
84650
|
return result;
|
|
84440
84651
|
}
|
|
84441
84652
|
async function discoverFromDirectory(dirPath, source) {
|
|
84442
|
-
if (!
|
|
84653
|
+
if (!existsSync16(dirPath)) {
|
|
84443
84654
|
return [];
|
|
84444
84655
|
}
|
|
84445
84656
|
const commands2 = [];
|
|
@@ -84450,7 +84661,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source) {
|
|
|
84450
84661
|
try {
|
|
84451
84662
|
const entries = await readdir9(currentPath, { withFileTypes: true });
|
|
84452
84663
|
for (const entry of entries) {
|
|
84453
|
-
const fullPath =
|
|
84664
|
+
const fullPath = join27(currentPath, entry.name);
|
|
84454
84665
|
if (entry.isDirectory()) {
|
|
84455
84666
|
await findCommandFiles(fullPath, rootPath, commands2, source);
|
|
84456
84667
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -84535,7 +84746,7 @@ async function findCustomCommand(commandName) {
|
|
|
84535
84746
|
}
|
|
84536
84747
|
var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
|
|
84537
84748
|
var init_custom = __esm(() => {
|
|
84538
|
-
GLOBAL_COMMANDS_DIR =
|
|
84749
|
+
GLOBAL_COMMANDS_DIR = join27(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
|
|
84539
84750
|
});
|
|
84540
84751
|
|
|
84541
84752
|
// src/cli/components/HelpDialog.tsx
|
|
@@ -87212,8 +87423,8 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
87212
87423
|
});
|
|
87213
87424
|
|
|
87214
87425
|
// src/cli/helpers/fileSearch.ts
|
|
87215
|
-
import { readdirSync as
|
|
87216
|
-
import { join as
|
|
87426
|
+
import { readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
|
|
87427
|
+
import { join as join28, resolve as resolve23 } from "node:path";
|
|
87217
87428
|
function shouldExcludeEntry(entry) {
|
|
87218
87429
|
if (entry.startsWith(".")) {
|
|
87219
87430
|
return true;
|
|
@@ -87225,13 +87436,13 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [],
|
|
|
87225
87436
|
return results;
|
|
87226
87437
|
}
|
|
87227
87438
|
try {
|
|
87228
|
-
const entries =
|
|
87439
|
+
const entries = readdirSync6(dir);
|
|
87229
87440
|
for (const entry of entries) {
|
|
87230
87441
|
if (shouldExcludeEntry(entry)) {
|
|
87231
87442
|
continue;
|
|
87232
87443
|
}
|
|
87233
87444
|
try {
|
|
87234
|
-
const fullPath =
|
|
87445
|
+
const fullPath = join28(dir, entry);
|
|
87235
87446
|
const stats = statSync5(fullPath);
|
|
87236
87447
|
const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
|
|
87237
87448
|
const matches = pattern.length === 0 || relativePath.toLowerCase().includes(pattern.toLowerCase());
|
|
@@ -87279,14 +87490,14 @@ async function searchFiles(query, deep = false) {
|
|
|
87279
87490
|
} else {
|
|
87280
87491
|
let entries = [];
|
|
87281
87492
|
try {
|
|
87282
|
-
entries =
|
|
87493
|
+
entries = readdirSync6(searchDir);
|
|
87283
87494
|
} catch {
|
|
87284
87495
|
return [];
|
|
87285
87496
|
}
|
|
87286
87497
|
const matchingEntries = entries.filter((entry) => !shouldExcludeEntry(entry)).filter((entry) => searchPattern.length === 0 || entry.toLowerCase().includes(searchPattern.toLowerCase()));
|
|
87287
87498
|
for (const entry of matchingEntries.slice(0, 50)) {
|
|
87288
87499
|
try {
|
|
87289
|
-
const fullPath =
|
|
87500
|
+
const fullPath = join28(searchDir, entry);
|
|
87290
87501
|
const stats = statSync5(fullPath);
|
|
87291
87502
|
const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
|
|
87292
87503
|
results.push({
|
|
@@ -90493,21 +90704,21 @@ var init_McpSelector = __esm(async () => {
|
|
|
90493
90704
|
});
|
|
90494
90705
|
|
|
90495
90706
|
// src/agent/memoryScanner.ts
|
|
90496
|
-
import { readdirSync as
|
|
90497
|
-
import { join as
|
|
90707
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync5, statSync as statSync6 } from "node:fs";
|
|
90708
|
+
import { join as join29, relative as relative7 } from "node:path";
|
|
90498
90709
|
function scanMemoryFilesystem(memoryRoot) {
|
|
90499
90710
|
const nodes = [];
|
|
90500
90711
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
90501
90712
|
let entries;
|
|
90502
90713
|
try {
|
|
90503
|
-
entries =
|
|
90714
|
+
entries = readdirSync7(dir);
|
|
90504
90715
|
} catch {
|
|
90505
90716
|
return;
|
|
90506
90717
|
}
|
|
90507
90718
|
const filtered = entries.filter((name) => !name.startsWith("."));
|
|
90508
90719
|
const sorted = filtered.sort((a, b) => {
|
|
90509
|
-
const aPath =
|
|
90510
|
-
const bPath =
|
|
90720
|
+
const aPath = join29(dir, a);
|
|
90721
|
+
const bPath = join29(dir, b);
|
|
90511
90722
|
let aIsDir = false;
|
|
90512
90723
|
let bIsDir = false;
|
|
90513
90724
|
try {
|
|
@@ -90527,7 +90738,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
90527
90738
|
return a.localeCompare(b);
|
|
90528
90739
|
});
|
|
90529
90740
|
sorted.forEach((name, index) => {
|
|
90530
|
-
const fullPath =
|
|
90741
|
+
const fullPath = join29(dir, name);
|
|
90531
90742
|
let isDir = false;
|
|
90532
90743
|
try {
|
|
90533
90744
|
isDir = statSync6(fullPath).isDirectory();
|
|
@@ -90760,7 +90971,7 @@ a:hover { text-decoration: underline; }
|
|
|
90760
90971
|
.tree-item.dir:not(.collapsed) { border-left-color: var(--accent); }
|
|
90761
90972
|
.tree-item.dir:hover { background: var(--surface-2); }
|
|
90762
90973
|
.tree-item.dir.collapsed ~ .tree-children { display: none; }
|
|
90763
|
-
.tree-children {
|
|
90974
|
+
.tree-children { padding-left: 12px; }
|
|
90764
90975
|
.tree-children.hidden { display: none; }
|
|
90765
90976
|
.tree-item.file { cursor: pointer; padding-left: 24px; }
|
|
90766
90977
|
.tree-item.file:hover { background: var(--hover-accent); }
|
|
@@ -92198,9 +92409,9 @@ var init_memory_viewer_template = () => {};
|
|
|
92198
92409
|
|
|
92199
92410
|
// src/web/generate-memory-viewer.ts
|
|
92200
92411
|
import { execFile as execFileCb2 } from "node:child_process";
|
|
92201
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
92202
|
-
import { homedir as
|
|
92203
|
-
import { join as
|
|
92412
|
+
import { chmodSync as chmodSync2, existsSync as existsSync17, mkdirSync as mkdirSync11, writeFileSync as writeFileSync8 } from "node:fs";
|
|
92413
|
+
import { homedir as homedir18 } from "node:os";
|
|
92414
|
+
import { join as join30 } from "node:path";
|
|
92204
92415
|
import { promisify as promisify10 } from "node:util";
|
|
92205
92416
|
async function runGitSafe(cwd2, args) {
|
|
92206
92417
|
try {
|
|
@@ -92482,23 +92693,26 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
92482
92693
|
data.agent.name = options.agentName;
|
|
92483
92694
|
}
|
|
92484
92695
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
92485
|
-
const html = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", jsonPayload);
|
|
92486
|
-
if (!
|
|
92487
|
-
|
|
92696
|
+
const html = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
92697
|
+
if (!existsSync17(VIEWERS_DIR)) {
|
|
92698
|
+
mkdirSync11(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
92488
92699
|
}
|
|
92489
92700
|
try {
|
|
92490
92701
|
chmodSync2(VIEWERS_DIR, 448);
|
|
92491
92702
|
} catch {}
|
|
92492
|
-
const filePath =
|
|
92493
|
-
|
|
92703
|
+
const filePath = join30(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
92704
|
+
writeFileSync8(filePath, html);
|
|
92494
92705
|
chmodSync2(filePath, 384);
|
|
92495
|
-
|
|
92496
|
-
|
|
92497
|
-
|
|
92498
|
-
|
|
92499
|
-
|
|
92706
|
+
const isTmux = Boolean(process.env.TMUX);
|
|
92707
|
+
if (!isTmux) {
|
|
92708
|
+
try {
|
|
92709
|
+
const { default: openUrl } = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
92710
|
+
await openUrl(filePath, { wait: false });
|
|
92711
|
+
} catch {
|
|
92712
|
+
throw new Error(`Could not open browser. Run: open ${filePath}`);
|
|
92713
|
+
}
|
|
92500
92714
|
}
|
|
92501
|
-
return { filePath };
|
|
92715
|
+
return { filePath, opened: !isTmux };
|
|
92502
92716
|
}
|
|
92503
92717
|
var execFile10, VIEWERS_DIR, MAX_COMMITS = 500, RECENT_DIFF_COUNT = 50, PER_DIFF_CAP = 1e5, TOTAL_PAYLOAD_CAP = 5000000, RECORD_SEP = "\x1E", REFLECTION_PATTERN;
|
|
92504
92718
|
var init_generate_memory_viewer = __esm(async () => {
|
|
@@ -92510,12 +92724,12 @@ var init_generate_memory_viewer = __esm(async () => {
|
|
|
92510
92724
|
init_memoryGit()
|
|
92511
92725
|
]);
|
|
92512
92726
|
execFile10 = promisify10(execFileCb2);
|
|
92513
|
-
VIEWERS_DIR =
|
|
92727
|
+
VIEWERS_DIR = join30(homedir18(), ".letta", "viewers");
|
|
92514
92728
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
92515
92729
|
});
|
|
92516
92730
|
|
|
92517
92731
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
92518
|
-
import { existsSync as
|
|
92732
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
92519
92733
|
function renderTreePrefix(node) {
|
|
92520
92734
|
let prefix = "";
|
|
92521
92735
|
for (let i = 0;i < node.depth; i++) {
|
|
@@ -92541,7 +92755,7 @@ function MemfsTreeViewer({
|
|
|
92541
92755
|
const [status, setStatus] = import_react72.useState(null);
|
|
92542
92756
|
const statusTimerRef = import_react72.useRef(null);
|
|
92543
92757
|
const memoryRoot = getMemoryFilesystemRoot(agentId);
|
|
92544
|
-
const memoryExists =
|
|
92758
|
+
const memoryExists = existsSync18(memoryRoot);
|
|
92545
92759
|
const hasGitRepo = import_react72.useMemo(() => isGitRepo(agentId), [agentId]);
|
|
92546
92760
|
function showStatus(msg, durationMs) {
|
|
92547
92761
|
if (statusTimerRef.current)
|
|
@@ -92567,7 +92781,13 @@ function MemfsTreeViewer({
|
|
|
92567
92781
|
}
|
|
92568
92782
|
if ((input === "o" || input === "O") && hasGitRepo) {
|
|
92569
92783
|
showStatus("Opening in browser...", 1e4);
|
|
92570
|
-
generateAndOpenMemoryViewer(agentId, { agentName }).then(() =>
|
|
92784
|
+
generateAndOpenMemoryViewer(agentId, { agentName }).then((result) => {
|
|
92785
|
+
if (result.opened) {
|
|
92786
|
+
showStatus("Opened in browser", 3000);
|
|
92787
|
+
} else {
|
|
92788
|
+
showStatus(`Run: open ${result.filePath}`, 15000);
|
|
92789
|
+
}
|
|
92790
|
+
}).catch((err) => showStatus(err instanceof Error ? err.message : "Failed to open viewer", 5000));
|
|
92571
92791
|
return;
|
|
92572
92792
|
}
|
|
92573
92793
|
if (key.escape) {
|
|
@@ -95142,11 +95362,11 @@ var init_byok_providers = __esm(async () => {
|
|
|
95142
95362
|
|
|
95143
95363
|
// src/utils/aws-credentials.ts
|
|
95144
95364
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
95145
|
-
import { homedir as
|
|
95146
|
-
import { join as
|
|
95365
|
+
import { homedir as homedir19 } from "node:os";
|
|
95366
|
+
import { join as join31 } from "node:path";
|
|
95147
95367
|
async function parseAwsCredentials() {
|
|
95148
|
-
const credentialsPath =
|
|
95149
|
-
const configPath =
|
|
95368
|
+
const credentialsPath = join31(homedir19(), ".aws", "credentials");
|
|
95369
|
+
const configPath = join31(homedir19(), ".aws", "config");
|
|
95150
95370
|
const profiles = new Map;
|
|
95151
95371
|
try {
|
|
95152
95372
|
const content = await readFile10(credentialsPath, "utf-8");
|
|
@@ -96254,8 +96474,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
96254
96474
|
try {
|
|
96255
96475
|
const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
96256
96476
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
96257
|
-
const { join:
|
|
96258
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
96477
|
+
const { join: join32 } = await import("node:path");
|
|
96478
|
+
const skillsDir = getSkillsDirectory2() || join32(process.cwd(), SKILLS_DIR3);
|
|
96259
96479
|
const result = await discoverSkills3(skillsDir, agentId, {
|
|
96260
96480
|
sources: getSkillSources2()
|
|
96261
96481
|
});
|
|
@@ -100960,12 +101180,12 @@ __export(exports_shellAliases, {
|
|
|
100960
101180
|
expandAliases: () => expandAliases,
|
|
100961
101181
|
clearAliasCache: () => clearAliasCache
|
|
100962
101182
|
});
|
|
100963
|
-
import { existsSync as
|
|
100964
|
-
import { homedir as
|
|
100965
|
-
import { join as
|
|
101183
|
+
import { existsSync as existsSync19, readFileSync as readFileSync6 } from "node:fs";
|
|
101184
|
+
import { homedir as homedir20 } from "node:os";
|
|
101185
|
+
import { join as join32 } from "node:path";
|
|
100966
101186
|
function parseAliasesFromFile(filePath) {
|
|
100967
101187
|
const aliases = new Map;
|
|
100968
|
-
if (!
|
|
101188
|
+
if (!existsSync19(filePath)) {
|
|
100969
101189
|
return aliases;
|
|
100970
101190
|
}
|
|
100971
101191
|
try {
|
|
@@ -101031,10 +101251,10 @@ function loadAliases(forceReload = false) {
|
|
|
101031
101251
|
if (aliasCache && !forceReload) {
|
|
101032
101252
|
return aliasCache;
|
|
101033
101253
|
}
|
|
101034
|
-
const home =
|
|
101254
|
+
const home = homedir20();
|
|
101035
101255
|
const allAliases = new Map;
|
|
101036
101256
|
for (const file of ALIAS_FILES) {
|
|
101037
|
-
const filePath =
|
|
101257
|
+
const filePath = join32(home, file);
|
|
101038
101258
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
101039
101259
|
for (const [name, value] of fileAliases) {
|
|
101040
101260
|
allAliases.set(name, value);
|
|
@@ -102370,9 +102590,9 @@ var exports_App = {};
|
|
|
102370
102590
|
__export(exports_App, {
|
|
102371
102591
|
default: () => App2
|
|
102372
102592
|
});
|
|
102373
|
-
import { existsSync as
|
|
102374
|
-
import { homedir as
|
|
102375
|
-
import { join as
|
|
102593
|
+
import { existsSync as existsSync20, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync9 } from "node:fs";
|
|
102594
|
+
import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
|
|
102595
|
+
import { join as join33 } from "node:path";
|
|
102376
102596
|
function deriveReasoningEffort(modelSettings, llmConfig) {
|
|
102377
102597
|
if (modelSettings && "provider_type" in modelSettings) {
|
|
102378
102598
|
if (modelSettings.provider_type === "openai" && "reasoning" in modelSettings && modelSettings.reasoning) {
|
|
@@ -102569,7 +102789,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
102569
102789
|
}
|
|
102570
102790
|
function planFileExists() {
|
|
102571
102791
|
const planFilePath = permissionMode.getPlanFilePath();
|
|
102572
|
-
return !!planFilePath &&
|
|
102792
|
+
return !!planFilePath && existsSync20(planFilePath);
|
|
102573
102793
|
}
|
|
102574
102794
|
function getQuestionsFromApproval(approval) {
|
|
102575
102795
|
const parsed = safeJsonParseOr(approval.toolArgs, {});
|
|
@@ -102939,6 +103159,11 @@ function App2({
|
|
|
102939
103159
|
const sessionStatsRef = import_react96.useRef(new SessionStats);
|
|
102940
103160
|
const sessionStartTimeRef = import_react96.useRef(Date.now());
|
|
102941
103161
|
const sessionHooksRanRef = import_react96.useRef(false);
|
|
103162
|
+
import_react96.useEffect(() => {
|
|
103163
|
+
if (agentId && agentId !== "loading") {
|
|
103164
|
+
chunkLog.init(agentId, telemetry.getSessionId());
|
|
103165
|
+
}
|
|
103166
|
+
}, [agentId]);
|
|
102942
103167
|
const syncTrajectoryTokenBase = import_react96.useCallback(() => {
|
|
102943
103168
|
const snapshot = sessionStatsRef.current.getTrajectorySnapshot();
|
|
102944
103169
|
setTrajectoryTokenBase(snapshot?.tokens ?? 0);
|
|
@@ -103662,8 +103887,8 @@ function App2({
|
|
|
103662
103887
|
if (!planFilePath)
|
|
103663
103888
|
return;
|
|
103664
103889
|
try {
|
|
103665
|
-
const { readFileSync: readFileSync8, existsSync:
|
|
103666
|
-
if (!
|
|
103890
|
+
const { readFileSync: readFileSync8, existsSync: existsSync21 } = __require("node:fs");
|
|
103891
|
+
if (!existsSync21(planFilePath))
|
|
103667
103892
|
return;
|
|
103668
103893
|
const planContent = readFileSync8(planFilePath, "utf-8");
|
|
103669
103894
|
const previewItem = {
|
|
@@ -103942,9 +104167,9 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
|
|
|
103942
104167
|
(async () => {
|
|
103943
104168
|
try {
|
|
103944
104169
|
const { watch } = await import("node:fs");
|
|
103945
|
-
const { existsSync:
|
|
104170
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
103946
104171
|
const memRoot = getMemoryFilesystemRoot(agentId);
|
|
103947
|
-
if (!
|
|
104172
|
+
if (!existsSync21(memRoot))
|
|
103948
104173
|
return;
|
|
103949
104174
|
watcher = watch(memRoot, { recursive: true }, () => {});
|
|
103950
104175
|
memfsWatcherRef.current = watcher;
|
|
@@ -105147,6 +105372,7 @@ ${feedback}
|
|
|
105147
105372
|
setStreaming(false);
|
|
105148
105373
|
resetTrajectoryBases();
|
|
105149
105374
|
toolResultsInFlightRef.current = false;
|
|
105375
|
+
setIsExecutingTool(false);
|
|
105150
105376
|
if (!toolsCancelled) {
|
|
105151
105377
|
appendError(INTERRUPT_MESSAGE, true);
|
|
105152
105378
|
}
|
|
@@ -105206,12 +105432,17 @@ ${feedback}
|
|
|
105206
105432
|
}
|
|
105207
105433
|
if (abortControllerRef.current) {
|
|
105208
105434
|
abortControllerRef.current.abort();
|
|
105435
|
+
abortControllerRef.current = null;
|
|
105209
105436
|
}
|
|
105437
|
+
setIsExecutingTool(false);
|
|
105438
|
+
toolResultsInFlightRef.current = false;
|
|
105210
105439
|
pendingInterruptRecoveryConversationIdRef.current = conversationIdRef.current;
|
|
105211
105440
|
} catch (e) {
|
|
105212
105441
|
const errorDetails = formatErrorDetails2(e, agentId);
|
|
105213
105442
|
appendError(`Failed to interrupt stream: ${errorDetails}`);
|
|
105214
105443
|
setInterruptRequested(false);
|
|
105444
|
+
setIsExecutingTool(false);
|
|
105445
|
+
toolResultsInFlightRef.current = false;
|
|
105215
105446
|
}
|
|
105216
105447
|
}
|
|
105217
105448
|
}, [
|
|
@@ -106848,7 +107079,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
106848
107079
|
fileContent = await client.agents.exportFile(agentId, exportParams);
|
|
106849
107080
|
}
|
|
106850
107081
|
const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
|
|
106851
|
-
|
|
107082
|
+
writeFileSync9(fileName, JSON.stringify(fileContent, null, 2));
|
|
106852
107083
|
let summary = `AgentFile exported to ${fileName}`;
|
|
106853
107084
|
if (skills.length > 0) {
|
|
106854
107085
|
summary += `
|
|
@@ -106938,11 +107169,11 @@ Path: ${result2.memoryDir}`, true, msg);
|
|
|
106938
107169
|
setCommandRunning(true);
|
|
106939
107170
|
try {
|
|
106940
107171
|
const memoryDir = getMemoryFilesystemRoot(agentId);
|
|
106941
|
-
if (!
|
|
107172
|
+
if (!existsSync20(memoryDir)) {
|
|
106942
107173
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
106943
107174
|
return { submitted: true };
|
|
106944
107175
|
}
|
|
106945
|
-
const backupDir =
|
|
107176
|
+
const backupDir = join33(tmpdir4(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
106946
107177
|
renameSync2(memoryDir, backupDir);
|
|
106947
107178
|
ensureMemoryFilesystemDirs(agentId);
|
|
106948
107179
|
updateMemorySyncCommand(cmdId, `Memory filesystem reset.
|
|
@@ -106970,8 +107201,8 @@ Run \`/memfs sync\` to repopulate from API.`, true, msg);
|
|
|
106970
107201
|
await removeGitMemoryTag2(agentId);
|
|
106971
107202
|
let backupInfo = "";
|
|
106972
107203
|
const memoryDir = getMemoryFilesystemRoot(agentId);
|
|
106973
|
-
if (
|
|
106974
|
-
const backupDir =
|
|
107204
|
+
if (existsSync20(memoryDir)) {
|
|
107205
|
+
const backupDir = join33(tmpdir4(), `letta-memfs-disable-${agentId}-${Date.now()}`);
|
|
106975
107206
|
renameSync2(memoryDir, backupDir);
|
|
106976
107207
|
backupInfo = `
|
|
106977
107208
|
Local files backed up to ${backupDir}`;
|
|
@@ -108656,10 +108887,11 @@ ${guidance}`);
|
|
|
108656
108887
|
context_tokens: stats.usage.contextTokens
|
|
108657
108888
|
};
|
|
108658
108889
|
})(),
|
|
108659
|
-
agent_name: agentName,
|
|
108660
|
-
agent_description: agentDescription,
|
|
108661
|
-
model: currentModelId,
|
|
108662
|
-
billing_tier: billingTier
|
|
108890
|
+
agent_name: agentName ?? undefined,
|
|
108891
|
+
agent_description: agentDescription ?? undefined,
|
|
108892
|
+
model: currentModelId ?? undefined,
|
|
108893
|
+
billing_tier: billingTier ?? undefined,
|
|
108894
|
+
recent_chunks: chunkLog.getEntries()
|
|
108663
108895
|
})
|
|
108664
108896
|
});
|
|
108665
108897
|
if (!response.ok) {
|
|
@@ -108965,7 +109197,7 @@ ${guidance}`);
|
|
|
108965
109197
|
}
|
|
108966
109198
|
if (!planFileExists()) {
|
|
108967
109199
|
const planFilePath = permissionMode.getPlanFilePath();
|
|
108968
|
-
const plansDir =
|
|
109200
|
+
const plansDir = join33(homedir21(), ".letta", "plans");
|
|
108969
109201
|
handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
|
|
108970
109202
|
` + (planFilePath ? `Plan file path: ${planFilePath}
|
|
108971
109203
|
` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
|
|
@@ -110082,6 +110314,7 @@ var init_App2 = __esm(async () => {
|
|
|
110082
110314
|
init_SessionStats();
|
|
110083
110315
|
init_AnimationContext();
|
|
110084
110316
|
init_backfill();
|
|
110317
|
+
init_chunkLog();
|
|
110085
110318
|
init_contextChart();
|
|
110086
110319
|
init_diff2();
|
|
110087
110320
|
init_errorContext();
|
|
@@ -110219,13 +110452,13 @@ __export(exports_terminalKeybindingInstaller2, {
|
|
|
110219
110452
|
});
|
|
110220
110453
|
import {
|
|
110221
110454
|
copyFileSync as copyFileSync2,
|
|
110222
|
-
existsSync as
|
|
110223
|
-
mkdirSync as
|
|
110455
|
+
existsSync as existsSync21,
|
|
110456
|
+
mkdirSync as mkdirSync12,
|
|
110224
110457
|
readFileSync as readFileSync8,
|
|
110225
|
-
writeFileSync as
|
|
110458
|
+
writeFileSync as writeFileSync10
|
|
110226
110459
|
} from "node:fs";
|
|
110227
|
-
import { homedir as
|
|
110228
|
-
import { dirname as dirname13, join as
|
|
110460
|
+
import { homedir as homedir22, platform as platform5 } from "node:os";
|
|
110461
|
+
import { dirname as dirname13, join as join34 } from "node:path";
|
|
110229
110462
|
function detectTerminalType2() {
|
|
110230
110463
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
110231
110464
|
return "cursor";
|
|
@@ -110257,16 +110490,16 @@ function getKeybindingsPath2(terminal) {
|
|
|
110257
110490
|
}[terminal];
|
|
110258
110491
|
const os6 = platform5();
|
|
110259
110492
|
if (os6 === "darwin") {
|
|
110260
|
-
return
|
|
110493
|
+
return join34(homedir22(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
110261
110494
|
}
|
|
110262
110495
|
if (os6 === "win32") {
|
|
110263
110496
|
const appData = process.env.APPDATA;
|
|
110264
110497
|
if (!appData)
|
|
110265
110498
|
return null;
|
|
110266
|
-
return
|
|
110499
|
+
return join34(appData, appName, "User", "keybindings.json");
|
|
110267
110500
|
}
|
|
110268
110501
|
if (os6 === "linux") {
|
|
110269
|
-
return
|
|
110502
|
+
return join34(homedir22(), ".config", appName, "User", "keybindings.json");
|
|
110270
110503
|
}
|
|
110271
110504
|
return null;
|
|
110272
110505
|
}
|
|
@@ -110288,7 +110521,7 @@ function parseKeybindings2(content) {
|
|
|
110288
110521
|
}
|
|
110289
110522
|
}
|
|
110290
110523
|
function keybindingExists2(keybindingsPath) {
|
|
110291
|
-
if (!
|
|
110524
|
+
if (!existsSync21(keybindingsPath))
|
|
110292
110525
|
return false;
|
|
110293
110526
|
try {
|
|
110294
110527
|
const content = readFileSync8(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -110301,7 +110534,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
110301
110534
|
}
|
|
110302
110535
|
}
|
|
110303
110536
|
function createBackup2(keybindingsPath) {
|
|
110304
|
-
if (!
|
|
110537
|
+
if (!existsSync21(keybindingsPath))
|
|
110305
110538
|
return null;
|
|
110306
110539
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
110307
110540
|
try {
|
|
@@ -110317,12 +110550,12 @@ function installKeybinding2(keybindingsPath) {
|
|
|
110317
110550
|
return { success: true, alreadyExists: true };
|
|
110318
110551
|
}
|
|
110319
110552
|
const parentDir = dirname13(keybindingsPath);
|
|
110320
|
-
if (!
|
|
110321
|
-
|
|
110553
|
+
if (!existsSync21(parentDir)) {
|
|
110554
|
+
mkdirSync12(parentDir, { recursive: true });
|
|
110322
110555
|
}
|
|
110323
110556
|
let keybindings = [];
|
|
110324
110557
|
let backupPath = null;
|
|
110325
|
-
if (
|
|
110558
|
+
if (existsSync21(keybindingsPath)) {
|
|
110326
110559
|
backupPath = createBackup2(keybindingsPath);
|
|
110327
110560
|
const content = readFileSync8(keybindingsPath, { encoding: "utf-8" });
|
|
110328
110561
|
const parsed = parseKeybindings2(content);
|
|
@@ -110337,7 +110570,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
110337
110570
|
keybindings.push(SHIFT_ENTER_KEYBINDING2);
|
|
110338
110571
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
110339
110572
|
`;
|
|
110340
|
-
|
|
110573
|
+
writeFileSync10(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
110341
110574
|
return {
|
|
110342
110575
|
success: true,
|
|
110343
110576
|
backupPath: backupPath ?? undefined
|
|
@@ -110352,7 +110585,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
110352
110585
|
}
|
|
110353
110586
|
function removeKeybinding2(keybindingsPath) {
|
|
110354
110587
|
try {
|
|
110355
|
-
if (!
|
|
110588
|
+
if (!existsSync21(keybindingsPath)) {
|
|
110356
110589
|
return { success: true };
|
|
110357
110590
|
}
|
|
110358
110591
|
const content = readFileSync8(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -110366,7 +110599,7 @@ function removeKeybinding2(keybindingsPath) {
|
|
|
110366
110599
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
110367
110600
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
110368
110601
|
`;
|
|
110369
|
-
|
|
110602
|
+
writeFileSync10(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
110370
110603
|
return { success: true };
|
|
110371
110604
|
} catch (error) {
|
|
110372
110605
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -110419,17 +110652,17 @@ function getWezTermConfigPath2() {
|
|
|
110419
110652
|
}
|
|
110420
110653
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
110421
110654
|
if (xdgConfig) {
|
|
110422
|
-
const xdgPath =
|
|
110423
|
-
if (
|
|
110655
|
+
const xdgPath = join34(xdgConfig, "wezterm", "wezterm.lua");
|
|
110656
|
+
if (existsSync21(xdgPath))
|
|
110424
110657
|
return xdgPath;
|
|
110425
110658
|
}
|
|
110426
|
-
const configPath =
|
|
110427
|
-
if (
|
|
110659
|
+
const configPath = join34(homedir22(), ".config", "wezterm", "wezterm.lua");
|
|
110660
|
+
if (existsSync21(configPath))
|
|
110428
110661
|
return configPath;
|
|
110429
|
-
return
|
|
110662
|
+
return join34(homedir22(), ".wezterm.lua");
|
|
110430
110663
|
}
|
|
110431
110664
|
function wezTermDeleteFixExists2(configPath) {
|
|
110432
|
-
if (!
|
|
110665
|
+
if (!existsSync21(configPath))
|
|
110433
110666
|
return false;
|
|
110434
110667
|
try {
|
|
110435
110668
|
const content = readFileSync8(configPath, { encoding: "utf-8" });
|
|
@@ -110446,7 +110679,7 @@ function installWezTermDeleteFix2() {
|
|
|
110446
110679
|
}
|
|
110447
110680
|
let content = "";
|
|
110448
110681
|
let backupPath = null;
|
|
110449
|
-
if (
|
|
110682
|
+
if (existsSync21(configPath)) {
|
|
110450
110683
|
backupPath = `${configPath}.letta-backup`;
|
|
110451
110684
|
copyFileSync2(configPath, backupPath);
|
|
110452
110685
|
content = readFileSync8(configPath, { encoding: "utf-8" });
|
|
@@ -110476,10 +110709,10 @@ ${WEZTERM_DELETE_FIX2}
|
|
|
110476
110709
|
`;
|
|
110477
110710
|
}
|
|
110478
110711
|
const parentDir = dirname13(configPath);
|
|
110479
|
-
if (!
|
|
110480
|
-
|
|
110712
|
+
if (!existsSync21(parentDir)) {
|
|
110713
|
+
mkdirSync12(parentDir, { recursive: true });
|
|
110481
110714
|
}
|
|
110482
|
-
|
|
110715
|
+
writeFileSync10(configPath, content, { encoding: "utf-8" });
|
|
110483
110716
|
return {
|
|
110484
110717
|
success: true,
|
|
110485
110718
|
backupPath: backupPath ?? undefined
|
|
@@ -110524,10 +110757,10 @@ __export(exports_settings2, {
|
|
|
110524
110757
|
loadProjectSettings: () => loadProjectSettings2,
|
|
110525
110758
|
getSetting: () => getSetting2
|
|
110526
110759
|
});
|
|
110527
|
-
import { homedir as
|
|
110528
|
-
import { join as
|
|
110760
|
+
import { homedir as homedir23 } from "node:os";
|
|
110761
|
+
import { join as join35 } from "node:path";
|
|
110529
110762
|
function getSettingsPath2() {
|
|
110530
|
-
return
|
|
110763
|
+
return join35(homedir23(), ".letta", "settings.json");
|
|
110531
110764
|
}
|
|
110532
110765
|
async function loadSettings2() {
|
|
110533
110766
|
const settingsPath = getSettingsPath2();
|
|
@@ -110564,7 +110797,7 @@ async function getSetting2(key) {
|
|
|
110564
110797
|
return settings[key];
|
|
110565
110798
|
}
|
|
110566
110799
|
function getProjectSettingsPath2() {
|
|
110567
|
-
return
|
|
110800
|
+
return join35(process.cwd(), ".letta", "settings.local.json");
|
|
110568
110801
|
}
|
|
110569
110802
|
async function loadProjectSettings2() {
|
|
110570
110803
|
const settingsPath = getProjectSettingsPath2();
|
|
@@ -110582,7 +110815,7 @@ async function loadProjectSettings2() {
|
|
|
110582
110815
|
}
|
|
110583
110816
|
async function saveProjectSettings2(settings) {
|
|
110584
110817
|
const settingsPath = getProjectSettingsPath2();
|
|
110585
|
-
const dirPath =
|
|
110818
|
+
const dirPath = join35(process.cwd(), ".letta");
|
|
110586
110819
|
try {
|
|
110587
110820
|
if (!exists(dirPath)) {
|
|
110588
110821
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -111285,7 +111518,7 @@ function parseRegistryHandle2(handle) {
|
|
|
111285
111518
|
}
|
|
111286
111519
|
async function importAgentFromRegistry2(options) {
|
|
111287
111520
|
const { tmpdir: tmpdir5 } = await import("node:os");
|
|
111288
|
-
const { join:
|
|
111521
|
+
const { join: join36 } = await import("node:path");
|
|
111289
111522
|
const { writeFile: writeFile5, unlink } = await import("node:fs/promises");
|
|
111290
111523
|
const { author, name } = parseRegistryHandle2(options.handle);
|
|
111291
111524
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -111297,7 +111530,7 @@ async function importAgentFromRegistry2(options) {
|
|
|
111297
111530
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
111298
111531
|
}
|
|
111299
111532
|
const afContent = await response.text();
|
|
111300
|
-
const tempPath =
|
|
111533
|
+
const tempPath = join36(tmpdir5(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
111301
111534
|
await writeFile5(tempPath, afContent, "utf-8");
|
|
111302
111535
|
try {
|
|
111303
111536
|
const result = await importAgentFromFile2({
|
|
@@ -111545,23 +111778,23 @@ __export(exports_memoryFilesystem2, {
|
|
|
111545
111778
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
111546
111779
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
111547
111780
|
});
|
|
111548
|
-
import { existsSync as
|
|
111549
|
-
import { homedir as
|
|
111550
|
-
import { join as
|
|
111551
|
-
function getMemoryFilesystemRoot2(agentId, homeDir =
|
|
111552
|
-
return
|
|
111781
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync13 } from "node:fs";
|
|
111782
|
+
import { homedir as homedir24 } from "node:os";
|
|
111783
|
+
import { join as join36 } from "node:path";
|
|
111784
|
+
function getMemoryFilesystemRoot2(agentId, homeDir = homedir24()) {
|
|
111785
|
+
return join36(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
111553
111786
|
}
|
|
111554
|
-
function getMemorySystemDir2(agentId, homeDir =
|
|
111555
|
-
return
|
|
111787
|
+
function getMemorySystemDir2(agentId, homeDir = homedir24()) {
|
|
111788
|
+
return join36(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
111556
111789
|
}
|
|
111557
|
-
function ensureMemoryFilesystemDirs2(agentId, homeDir =
|
|
111790
|
+
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir24()) {
|
|
111558
111791
|
const root = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
111559
111792
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
111560
|
-
if (!
|
|
111561
|
-
|
|
111793
|
+
if (!existsSync22(root)) {
|
|
111794
|
+
mkdirSync13(root, { recursive: true });
|
|
111562
111795
|
}
|
|
111563
|
-
if (!
|
|
111564
|
-
|
|
111796
|
+
if (!existsSync22(systemDir)) {
|
|
111797
|
+
mkdirSync13(systemDir, { recursive: true });
|
|
111565
111798
|
}
|
|
111566
111799
|
}
|
|
111567
111800
|
function labelFromRelativePath2(relativePath) {
|
|
@@ -111646,6 +111879,21 @@ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
111646
111879
|
if (isEnabled && (memfsFlag || shouldAutoEnableFromTag)) {
|
|
111647
111880
|
const { detachMemoryTools: detachMemoryTools2 } = await init_toolset().then(() => exports_toolset);
|
|
111648
111881
|
await detachMemoryTools2(agentId);
|
|
111882
|
+
const { getClient: getClient3 } = await init_client2().then(() => exports_client);
|
|
111883
|
+
const client = await getClient3();
|
|
111884
|
+
for (const label of ["skills", "loaded_skills"]) {
|
|
111885
|
+
try {
|
|
111886
|
+
const block = await client.agents.blocks.retrieve(label, {
|
|
111887
|
+
agent_id: agentId
|
|
111888
|
+
});
|
|
111889
|
+
if (block) {
|
|
111890
|
+
await client.agents.blocks.detach(block.id, {
|
|
111891
|
+
agent_id: agentId
|
|
111892
|
+
});
|
|
111893
|
+
await client.blocks.delete(block.id);
|
|
111894
|
+
}
|
|
111895
|
+
} catch {}
|
|
111896
|
+
}
|
|
111649
111897
|
}
|
|
111650
111898
|
if (noMemfsFlag) {
|
|
111651
111899
|
const { removeGitMemoryTag: removeGitMemoryTag2 } = await init_memoryGit().then(() => exports_memoryGit);
|
|
@@ -111654,7 +111902,7 @@ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
111654
111902
|
let pullSummary;
|
|
111655
111903
|
if (isEnabled) {
|
|
111656
111904
|
const { addGitMemoryTag: addGitMemoryTag2, isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2, pullMemory: pullMemory2 } = await init_memoryGit().then(() => exports_memoryGit);
|
|
111657
|
-
await addGitMemoryTag2(agentId);
|
|
111905
|
+
await addGitMemoryTag2(agentId, options?.agentTags ? { tags: options.agentTags } : undefined);
|
|
111658
111906
|
if (!isGitRepo2(agentId)) {
|
|
111659
111907
|
await cloneMemoryRepo2(agentId);
|
|
111660
111908
|
} else if (options?.pullOnExistingRepo) {
|
|
@@ -112708,6 +112956,18 @@ function isCreditExhaustedError(e, reasons) {
|
|
|
112708
112956
|
return false;
|
|
112709
112957
|
return hasErrorReason(e, "not-enough-credits", reasons);
|
|
112710
112958
|
}
|
|
112959
|
+
function getTierUsageLimitMessage(reasons) {
|
|
112960
|
+
if (reasons.includes("premium-usage-exceeded")) {
|
|
112961
|
+
return `You've reached your Premium model usage limit. Try switching to Standard or Basic hosted models with /model. View your plan and usage at ${LETTA_USAGE_URL}, or connect your own provider keys with /connect.`;
|
|
112962
|
+
}
|
|
112963
|
+
if (reasons.includes("standard-usage-exceeded")) {
|
|
112964
|
+
return `You've reached your Standard model usage limit. Try switching to Basic hosted models with /model. View your plan and usage at ${LETTA_USAGE_URL}, or connect your own provider keys with /connect.`;
|
|
112965
|
+
}
|
|
112966
|
+
if (reasons.includes("basic-usage-exceeded")) {
|
|
112967
|
+
return `You've reached your Basic model usage limit. Try switching models with /model, view your plan and usage at ${LETTA_USAGE_URL}, or connect your own provider keys with /connect.`;
|
|
112968
|
+
}
|
|
112969
|
+
return;
|
|
112970
|
+
}
|
|
112711
112971
|
var ENCRYPTED_CONTENT_HINT = [
|
|
112712
112972
|
"",
|
|
112713
112973
|
"This occurs when the conversation contains messages with encrypted",
|
|
@@ -112815,9 +113075,9 @@ Delete ${resourceType} at: ${LETTA_AGENTS_URL}`;
|
|
|
112815
113075
|
if (isCreditExhaustedError(e, reasons)) {
|
|
112816
113076
|
return `Your account is out of credits for hosted inference. Add credits, enable auto-recharge, or upgrade at ${LETTA_USAGE_URL}. You can also connect your own provider keys with /connect.`;
|
|
112817
113077
|
}
|
|
112818
|
-
|
|
112819
|
-
|
|
112820
|
-
|
|
113078
|
+
const tierUsageLimitMsg = getTierUsageLimitMessage(reasons);
|
|
113079
|
+
if (tierUsageLimitMsg)
|
|
113080
|
+
return tierUsageLimitMsg;
|
|
112821
113081
|
if (hasErrorReason(e, "byok-not-available-on-free-tier", reasons)) {
|
|
112822
113082
|
const { modelDisplayName } = getErrorContext();
|
|
112823
113083
|
const modelInfo = modelDisplayName ? ` (${modelDisplayName})` : "";
|
|
@@ -113661,7 +113921,7 @@ await __promiseAll([
|
|
|
113661
113921
|
var import_react28 = __toESM(require_react(), 1);
|
|
113662
113922
|
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
113663
113923
|
function ListenerStatusUI(props) {
|
|
113664
|
-
const { agentId, connectionId, onReady } = props;
|
|
113924
|
+
const { agentId, connectionId, conversationId, onReady } = props;
|
|
113665
113925
|
const [status, setStatus] = import_react28.useState("idle");
|
|
113666
113926
|
const [retryInfo, setRetryInfo] = import_react28.useState(null);
|
|
113667
113927
|
import_react28.useEffect(() => {
|
|
@@ -113675,7 +113935,7 @@ function ListenerStatusUI(props) {
|
|
|
113675
113935
|
}
|
|
113676
113936
|
});
|
|
113677
113937
|
}, [onReady]);
|
|
113678
|
-
const adeUrl = `https://app.letta.com/agents/${agentId}?deviceId=${connectionId}`;
|
|
113938
|
+
const adeUrl = `https://app.letta.com/agents/${agentId}?deviceId=${connectionId}${conversationId ? `&conversationId=${conversationId}` : ""}`;
|
|
113679
113939
|
const statusText = retryInfo ? `Reconnecting (attempt ${retryInfo.attempt}, retry in ${Math.round(retryInfo.nextRetryIn / 1000)}s)` : status === "receiving" ? "Receiving message" : status === "processing" ? "Processing message" : "Awaiting instructions";
|
|
113680
113940
|
const showSpinner = status !== "idle" || retryInfo !== null;
|
|
113681
113941
|
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
@@ -113735,28 +113995,33 @@ function ListenerStatusUI(props) {
|
|
|
113735
113995
|
// src/cli/subcommands/listen.tsx
|
|
113736
113996
|
var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
113737
113997
|
async function runListenSubcommand(argv) {
|
|
113998
|
+
const processedArgv = argv.map((arg) => arg === "--conv" ? "--conversation" : arg);
|
|
113738
113999
|
const { values } = parseArgs3({
|
|
113739
|
-
args:
|
|
114000
|
+
args: processedArgv,
|
|
113740
114001
|
options: {
|
|
113741
114002
|
name: { type: "string" },
|
|
113742
114003
|
agent: { type: "string" },
|
|
114004
|
+
conversation: { type: "string", short: "C" },
|
|
113743
114005
|
help: { type: "boolean", short: "h" }
|
|
113744
114006
|
},
|
|
113745
114007
|
allowPositionals: false
|
|
113746
114008
|
});
|
|
113747
114009
|
if (values.help) {
|
|
113748
|
-
console.log(`Usage: letta listen --name <connection-name> [--agent <agent-id>]
|
|
114010
|
+
console.log(`Usage: letta listen --name <connection-name> [--agent <agent-id>] [--conversation <id>]
|
|
113749
114011
|
`);
|
|
113750
114012
|
console.log(`Register this letta-code instance to receive messages from Letta Cloud.
|
|
113751
114013
|
`);
|
|
113752
114014
|
console.log("Options:");
|
|
113753
114015
|
console.log(" --name <name> Friendly name for this connection (required)");
|
|
113754
114016
|
console.log(" --agent <id> Bind connection to specific agent (required for CLI usage)");
|
|
114017
|
+
console.log(" --conversation <id>, --conv <id>, -C <id>");
|
|
114018
|
+
console.log(" Route messages to a specific conversation");
|
|
113755
114019
|
console.log(` -h, --help Show this help message
|
|
113756
114020
|
`);
|
|
113757
114021
|
console.log("Examples:");
|
|
113758
114022
|
console.log(' letta listen --name "george" --agent agent-abc123');
|
|
113759
|
-
console.log(
|
|
114023
|
+
console.log(' letta listen --name "laptop-work" --agent agent-xyz789');
|
|
114024
|
+
console.log(` letta listen --name "daily-cron" --agent agent-abc123 --conv conv-xyz789
|
|
113760
114025
|
`);
|
|
113761
114026
|
console.log("Once connected, this instance will listen for incoming messages from cloud agents.");
|
|
113762
114027
|
console.log("Messages will be executed locally using your letta-code environment.");
|
|
@@ -113764,6 +114029,7 @@ async function runListenSubcommand(argv) {
|
|
|
113764
114029
|
}
|
|
113765
114030
|
const connectionName = values.name;
|
|
113766
114031
|
const agentId = values.agent;
|
|
114032
|
+
const conversationId = values.conversation;
|
|
113767
114033
|
if (!connectionName) {
|
|
113768
114034
|
console.error(`Error: --name is required
|
|
113769
114035
|
`);
|
|
@@ -113802,7 +114068,8 @@ async function runListenSubcommand(argv) {
|
|
|
113802
114068
|
body: JSON.stringify({
|
|
113803
114069
|
deviceId,
|
|
113804
114070
|
connectionName,
|
|
113805
|
-
agentId
|
|
114071
|
+
agentId,
|
|
114072
|
+
...conversationId && { conversationId }
|
|
113806
114073
|
})
|
|
113807
114074
|
});
|
|
113808
114075
|
if (!registerResponse.ok) {
|
|
@@ -113818,6 +114085,7 @@ async function runListenSubcommand(argv) {
|
|
|
113818
114085
|
const { unmount } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ListenerStatusUI, {
|
|
113819
114086
|
agentId,
|
|
113820
114087
|
connectionId,
|
|
114088
|
+
conversationId,
|
|
113821
114089
|
onReady: (callbacks) => {
|
|
113822
114090
|
updateStatusCallback = callbacks.updateStatus;
|
|
113823
114091
|
updateRetryStatusCallback = callbacks.updateRetryStatus;
|
|
@@ -113831,6 +114099,7 @@ async function runListenSubcommand(argv) {
|
|
|
113831
114099
|
deviceId,
|
|
113832
114100
|
connectionName,
|
|
113833
114101
|
agentId,
|
|
114102
|
+
defaultConversationId: conversationId,
|
|
113834
114103
|
onStatusChange: (status) => {
|
|
113835
114104
|
clearRetryStatusCallback?.();
|
|
113836
114105
|
updateStatusCallback?.(status);
|
|
@@ -113867,10 +114136,10 @@ async function runListenSubcommand(argv) {
|
|
|
113867
114136
|
|
|
113868
114137
|
// src/cli/subcommands/memfs.ts
|
|
113869
114138
|
await init_memoryGit();
|
|
113870
|
-
import { cpSync, existsSync as
|
|
114139
|
+
import { cpSync, existsSync as existsSync9, mkdirSync as mkdirSync7, rmSync as rmSync2, statSync as statSync2 } from "node:fs";
|
|
113871
114140
|
import { readdir as readdir5 } from "node:fs/promises";
|
|
113872
|
-
import { homedir as
|
|
113873
|
-
import { join as
|
|
114141
|
+
import { homedir as homedir12 } from "node:os";
|
|
114142
|
+
import { join as join16 } from "node:path";
|
|
113874
114143
|
import { parseArgs as parseArgs4 } from "node:util";
|
|
113875
114144
|
function printUsage3() {
|
|
113876
114145
|
console.log(`
|
|
@@ -113899,10 +114168,10 @@ function getAgentId3(agentFromArgs, agentIdFromArgs) {
|
|
|
113899
114168
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
113900
114169
|
}
|
|
113901
114170
|
function getMemoryRoot(agentId) {
|
|
113902
|
-
return
|
|
114171
|
+
return join16(homedir12(), ".letta", "agents", agentId, "memory");
|
|
113903
114172
|
}
|
|
113904
114173
|
function getAgentRoot(agentId) {
|
|
113905
|
-
return
|
|
114174
|
+
return join16(homedir12(), ".letta", "agents", agentId);
|
|
113906
114175
|
}
|
|
113907
114176
|
function formatBackupTimestamp(date = new Date) {
|
|
113908
114177
|
const pad = (value) => String(value).padStart(2, "0");
|
|
@@ -113916,7 +114185,7 @@ function formatBackupTimestamp(date = new Date) {
|
|
|
113916
114185
|
}
|
|
113917
114186
|
async function listBackups(agentId) {
|
|
113918
114187
|
const agentRoot = getAgentRoot(agentId);
|
|
113919
|
-
if (!
|
|
114188
|
+
if (!existsSync9(agentRoot)) {
|
|
113920
114189
|
return [];
|
|
113921
114190
|
}
|
|
113922
114191
|
const entries = await readdir5(agentRoot, { withFileTypes: true });
|
|
@@ -113926,7 +114195,7 @@ async function listBackups(agentId) {
|
|
|
113926
114195
|
continue;
|
|
113927
114196
|
if (!entry.name.startsWith("memory-backup-"))
|
|
113928
114197
|
continue;
|
|
113929
|
-
const path19 =
|
|
114198
|
+
const path19 = join16(agentRoot, entry.name);
|
|
113930
114199
|
let createdAt = null;
|
|
113931
114200
|
try {
|
|
113932
114201
|
const stat2 = statSync2(path19);
|
|
@@ -113943,7 +114212,7 @@ function resolveBackupPath(agentId, from) {
|
|
|
113943
114212
|
if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
|
|
113944
114213
|
return from;
|
|
113945
114214
|
}
|
|
113946
|
-
return
|
|
114215
|
+
return join16(getAgentRoot(agentId), from);
|
|
113947
114216
|
}
|
|
113948
114217
|
async function runMemfsSubcommand(argv) {
|
|
113949
114218
|
let parsed;
|
|
@@ -114015,14 +114284,14 @@ async function runMemfsSubcommand(argv) {
|
|
|
114015
114284
|
}
|
|
114016
114285
|
if (action === "backup") {
|
|
114017
114286
|
const root = getMemoryRoot(agentId);
|
|
114018
|
-
if (!
|
|
114287
|
+
if (!existsSync9(root)) {
|
|
114019
114288
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
114020
114289
|
return 1;
|
|
114021
114290
|
}
|
|
114022
114291
|
const agentRoot = getAgentRoot(agentId);
|
|
114023
114292
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
114024
|
-
const backupPath =
|
|
114025
|
-
if (
|
|
114293
|
+
const backupPath = join16(agentRoot, backupName);
|
|
114294
|
+
if (existsSync9(backupPath)) {
|
|
114026
114295
|
console.error(`Backup already exists at ${backupPath}`);
|
|
114027
114296
|
return 1;
|
|
114028
114297
|
}
|
|
@@ -114046,7 +114315,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
114046
114315
|
return 1;
|
|
114047
114316
|
}
|
|
114048
114317
|
const backupPath = resolveBackupPath(agentId, from);
|
|
114049
|
-
if (!
|
|
114318
|
+
if (!existsSync9(backupPath)) {
|
|
114050
114319
|
console.error(`Backup not found: ${backupPath}`);
|
|
114051
114320
|
return 1;
|
|
114052
114321
|
}
|
|
@@ -114068,11 +114337,11 @@ async function runMemfsSubcommand(argv) {
|
|
|
114068
114337
|
return 1;
|
|
114069
114338
|
}
|
|
114070
114339
|
const root = getMemoryRoot(agentId);
|
|
114071
|
-
if (!
|
|
114340
|
+
if (!existsSync9(root)) {
|
|
114072
114341
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
114073
114342
|
return 1;
|
|
114074
114343
|
}
|
|
114075
|
-
if (
|
|
114344
|
+
if (existsSync9(out)) {
|
|
114076
114345
|
const stat2 = statSync2(out);
|
|
114077
114346
|
if (stat2.isDirectory()) {
|
|
114078
114347
|
const contents = await readdir5(out);
|
|
@@ -114085,7 +114354,7 @@ async function runMemfsSubcommand(argv) {
|
|
|
114085
114354
|
return 1;
|
|
114086
114355
|
}
|
|
114087
114356
|
} else {
|
|
114088
|
-
|
|
114357
|
+
mkdirSync7(out, { recursive: true });
|
|
114089
114358
|
}
|
|
114090
114359
|
cpSync(root, out, { recursive: true });
|
|
114091
114360
|
console.log(JSON.stringify({ exportedFrom: root, exportedTo: out, agentId }, null, 2));
|
|
@@ -114277,8 +114546,8 @@ async function runSubcommand(argv) {
|
|
|
114277
114546
|
|
|
114278
114547
|
// src/permissions/mode.ts
|
|
114279
114548
|
init_readOnlyShell();
|
|
114280
|
-
import { homedir as
|
|
114281
|
-
import { isAbsolute as isAbsolute14, join as
|
|
114549
|
+
import { homedir as homedir13 } from "node:os";
|
|
114550
|
+
import { isAbsolute as isAbsolute14, join as join17, relative as relative3, resolve as resolve19 } from "node:path";
|
|
114282
114551
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
114283
114552
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
114284
114553
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
@@ -114314,7 +114583,7 @@ function resolvePlanTargetPath2(targetPath, workingDirectory) {
|
|
|
114314
114583
|
if (!trimmedPath)
|
|
114315
114584
|
return null;
|
|
114316
114585
|
if (trimmedPath.startsWith("~/")) {
|
|
114317
|
-
return resolve19(
|
|
114586
|
+
return resolve19(homedir13(), trimmedPath.slice(2));
|
|
114318
114587
|
}
|
|
114319
114588
|
if (isAbsolute14(trimmedPath)) {
|
|
114320
114589
|
return resolve19(trimmedPath);
|
|
@@ -114440,7 +114709,7 @@ class PermissionModeManager2 {
|
|
|
114440
114709
|
return "allow";
|
|
114441
114710
|
}
|
|
114442
114711
|
if (writeTools.includes(toolName)) {
|
|
114443
|
-
const plansDir =
|
|
114712
|
+
const plansDir = join17(homedir13(), ".letta", "plans");
|
|
114444
114713
|
const targetPath = toolArgs?.file_path || toolArgs?.path;
|
|
114445
114714
|
let candidatePaths = [];
|
|
114446
114715
|
if ((toolName === "ApplyPatch" || toolName === "apply_patch") && toolArgs?.input) {
|
|
@@ -114510,8 +114779,8 @@ var permissionMode2 = new PermissionModeManager2;
|
|
|
114510
114779
|
init_debug();
|
|
114511
114780
|
init_fs();
|
|
114512
114781
|
await init_secrets();
|
|
114513
|
-
import { homedir as
|
|
114514
|
-
import { join as
|
|
114782
|
+
import { homedir as homedir14 } from "node:os";
|
|
114783
|
+
import { join as join18 } from "node:path";
|
|
114515
114784
|
var DEFAULT_SETTINGS2 = {
|
|
114516
114785
|
lastAgent: null,
|
|
114517
114786
|
tokenStreaming: false,
|
|
@@ -114843,8 +115112,8 @@ class SettingsManager2 {
|
|
|
114843
115112
|
if (!this.settings)
|
|
114844
115113
|
return;
|
|
114845
115114
|
const settingsPath = this.getSettingsPath();
|
|
114846
|
-
const home = process.env.HOME ||
|
|
114847
|
-
const dirPath =
|
|
115115
|
+
const home = process.env.HOME || homedir14();
|
|
115116
|
+
const dirPath = join18(home, ".letta");
|
|
114848
115117
|
try {
|
|
114849
115118
|
if (!exists(dirPath)) {
|
|
114850
115119
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -114876,7 +115145,7 @@ class SettingsManager2 {
|
|
|
114876
115145
|
if (!settings)
|
|
114877
115146
|
return;
|
|
114878
115147
|
const settingsPath = this.getProjectSettingsPath(workingDirectory);
|
|
114879
|
-
const dirPath =
|
|
115148
|
+
const dirPath = join18(workingDirectory, ".letta");
|
|
114880
115149
|
try {
|
|
114881
115150
|
let existingSettings = {};
|
|
114882
115151
|
if (exists(settingsPath)) {
|
|
@@ -114897,14 +115166,14 @@ class SettingsManager2 {
|
|
|
114897
115166
|
}
|
|
114898
115167
|
}
|
|
114899
115168
|
getSettingsPath() {
|
|
114900
|
-
const home = process.env.HOME ||
|
|
114901
|
-
return
|
|
115169
|
+
const home = process.env.HOME || homedir14();
|
|
115170
|
+
return join18(home, ".letta", "settings.json");
|
|
114902
115171
|
}
|
|
114903
115172
|
getProjectSettingsPath(workingDirectory) {
|
|
114904
|
-
return
|
|
115173
|
+
return join18(workingDirectory, ".letta", "settings.json");
|
|
114905
115174
|
}
|
|
114906
115175
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
114907
|
-
return
|
|
115176
|
+
return join18(workingDirectory, ".letta", "settings.local.json");
|
|
114908
115177
|
}
|
|
114909
115178
|
async loadLocalProjectSettings(workingDirectory = process.cwd()) {
|
|
114910
115179
|
const cached = this.localProjectSettings.get(workingDirectory);
|
|
@@ -114955,7 +115224,7 @@ class SettingsManager2 {
|
|
|
114955
115224
|
if (!settings)
|
|
114956
115225
|
return;
|
|
114957
115226
|
const settingsPath = this.getLocalProjectSettingsPath(workingDirectory);
|
|
114958
|
-
const dirPath =
|
|
115227
|
+
const dirPath = join18(workingDirectory, ".letta");
|
|
114959
115228
|
try {
|
|
114960
115229
|
if (!exists(dirPath)) {
|
|
114961
115230
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -115270,7 +115539,7 @@ class SettingsManager2 {
|
|
|
115270
115539
|
this.upsertAgentSettings(agentId, { toolset: preference });
|
|
115271
115540
|
}
|
|
115272
115541
|
hasLocalLettaDir(workingDirectory = process.cwd()) {
|
|
115273
|
-
const dirPath =
|
|
115542
|
+
const dirPath = join18(workingDirectory, ".letta");
|
|
115274
115543
|
return exists(dirPath);
|
|
115275
115544
|
}
|
|
115276
115545
|
storeOAuthState(state, codeVerifier, redirectUri, provider) {
|
|
@@ -115973,12 +116242,12 @@ EXAMPLES
|
|
|
115973
116242
|
console.log(usage);
|
|
115974
116243
|
}
|
|
115975
116244
|
async function printInfo() {
|
|
115976
|
-
const { join:
|
|
116245
|
+
const { join: join37 } = await import("path");
|
|
115977
116246
|
const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
|
|
115978
116247
|
const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills2(), exports_skills2));
|
|
115979
116248
|
const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
|
|
115980
116249
|
const cwd2 = process.cwd();
|
|
115981
|
-
const skillsDir =
|
|
116250
|
+
const skillsDir = join37(cwd2, SKILLS_DIR3);
|
|
115982
116251
|
const skillsExist = exists3(skillsDir);
|
|
115983
116252
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
115984
116253
|
const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
|
|
@@ -116422,9 +116691,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
116422
116691
|
}
|
|
116423
116692
|
} else {
|
|
116424
116693
|
const { resolve: resolve26 } = await import("path");
|
|
116425
|
-
const { existsSync:
|
|
116694
|
+
const { existsSync: existsSync23 } = await import("fs");
|
|
116426
116695
|
const resolvedPath = resolve26(fromAfFile);
|
|
116427
|
-
if (!
|
|
116696
|
+
if (!existsSync23(resolvedPath)) {
|
|
116428
116697
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
116429
116698
|
process.exit(1);
|
|
116430
116699
|
}
|
|
@@ -116584,6 +116853,7 @@ Error: ${message}`);
|
|
|
116584
116853
|
const [resumedExistingConversation, setResumedExistingConversation] = useState50(false);
|
|
116585
116854
|
const [agentProvenance, setAgentProvenance] = useState50(null);
|
|
116586
116855
|
const [selectedGlobalAgentId, setSelectedGlobalAgentId] = useState50(null);
|
|
116856
|
+
const [validatedAgent, setValidatedAgent] = useState50(null);
|
|
116587
116857
|
const [resumeAgentId, setResumeAgentId] = useState50(null);
|
|
116588
116858
|
const [resumeAgentName, setResumeAgentName] = useState50(null);
|
|
116589
116859
|
const [selectedConversationId, setSelectedConversationId] = useState50(null);
|
|
@@ -116775,9 +117045,10 @@ Error: ${message}`);
|
|
|
116775
117045
|
}
|
|
116776
117046
|
const localAgentId = settingsManager2.getLocalLastAgentId(process.cwd());
|
|
116777
117047
|
let localAgentExists = false;
|
|
117048
|
+
let cachedAgent = null;
|
|
116778
117049
|
if (localAgentId) {
|
|
116779
117050
|
try {
|
|
116780
|
-
await client.agents.retrieve(localAgentId);
|
|
117051
|
+
cachedAgent = await client.agents.retrieve(localAgentId);
|
|
116781
117052
|
localAgentExists = true;
|
|
116782
117053
|
} catch {
|
|
116783
117054
|
setFailedAgentMessage(`Unable to locate recently used agent ${localAgentId}`);
|
|
@@ -116787,7 +117058,7 @@ Error: ${message}`);
|
|
|
116787
117058
|
let globalAgentExists = false;
|
|
116788
117059
|
if (globalAgentId && globalAgentId !== localAgentId) {
|
|
116789
117060
|
try {
|
|
116790
|
-
await client.agents.retrieve(globalAgentId);
|
|
117061
|
+
cachedAgent = await client.agents.retrieve(globalAgentId);
|
|
116791
117062
|
globalAgentExists = true;
|
|
116792
117063
|
} catch {}
|
|
116793
117064
|
} else if (globalAgentId && globalAgentId === localAgentId) {
|
|
@@ -116808,6 +117079,9 @@ Error: ${message}`);
|
|
|
116808
117079
|
switch (target.action) {
|
|
116809
117080
|
case "resume":
|
|
116810
117081
|
setSelectedGlobalAgentId(target.agentId);
|
|
117082
|
+
if (cachedAgent && cachedAgent.id === target.agentId) {
|
|
117083
|
+
setValidatedAgent(cachedAgent);
|
|
117084
|
+
}
|
|
116811
117085
|
setLoadingState("assembling");
|
|
116812
117086
|
return;
|
|
116813
117087
|
case "select":
|
|
@@ -116987,7 +117261,7 @@ Error: ${message}`);
|
|
|
116987
117261
|
}
|
|
116988
117262
|
if (!agent && resumingAgentId) {
|
|
116989
117263
|
try {
|
|
116990
|
-
agent = await client.agents.retrieve(resumingAgentId);
|
|
117264
|
+
agent = validatedAgent && validatedAgent.id === resumingAgentId ? validatedAgent : await client.agents.retrieve(resumingAgentId);
|
|
116991
117265
|
} catch (error) {
|
|
116992
117266
|
console.error(`Agent ${resumingAgentId} not found (error: ${JSON.stringify(error)})`);
|
|
116993
117267
|
setLoadingState("selecting_global");
|
|
@@ -117014,30 +117288,13 @@ Error: ${message}`);
|
|
|
117014
117288
|
}
|
|
117015
117289
|
settingsManager2.updateLocalProjectSettings({ lastAgent: agent.id });
|
|
117016
117290
|
settingsManager2.updateSettings({ lastAgent: agent.id });
|
|
117017
|
-
for (const label of ["skills", "loaded_skills"]) {
|
|
117018
|
-
try {
|
|
117019
|
-
const block = await client.agents.blocks.retrieve(label, {
|
|
117020
|
-
agent_id: agent.id
|
|
117021
|
-
});
|
|
117022
|
-
if (block) {
|
|
117023
|
-
await client.agents.blocks.detach(block.id, {
|
|
117024
|
-
agent_id: agent.id
|
|
117025
|
-
});
|
|
117026
|
-
await client.blocks.delete(block.id);
|
|
117027
|
-
}
|
|
117028
|
-
} catch {}
|
|
117029
|
-
}
|
|
117030
117291
|
setAgentContext(agent.id, skillsDirectory2, resolvedSkillSources);
|
|
117031
117292
|
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
117032
|
-
|
|
117033
|
-
|
|
117034
|
-
|
|
117035
|
-
|
|
117036
|
-
|
|
117037
|
-
} catch (error) {
|
|
117038
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
117039
|
-
process.exit(1);
|
|
117040
|
-
}
|
|
117293
|
+
const agentId2 = agent.id;
|
|
117294
|
+
const agentTags = agent.tags ?? undefined;
|
|
117295
|
+
const memfsSyncPromise = Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2)).then(({ applyMemfsFlags: applyMemfsFlags3 }) => applyMemfsFlags3(agentId2, memfsFlag, noMemfsFlag, {
|
|
117296
|
+
agentTags
|
|
117297
|
+
}));
|
|
117041
117298
|
const isResumingProject = !shouldCreateNew && !!resumingAgentId;
|
|
117042
117299
|
const isReusingExistingAgent = !shouldCreateNew && !fromAfFile2 && agent && agent.id;
|
|
117043
117300
|
const resuming = !!(continueSession || agentIdArg || isResumingProject || isReusingExistingAgent);
|
|
@@ -117076,8 +117333,7 @@ Error: ${message}`);
|
|
|
117076
117333
|
setResumedExistingConversation(true);
|
|
117077
117334
|
try {
|
|
117078
117335
|
setLoadingState("checking");
|
|
117079
|
-
const
|
|
117080
|
-
const data = await getResumeData(client, freshAgent, specifiedConversationId);
|
|
117336
|
+
const data = await getResumeData(client, agent, specifiedConversationId);
|
|
117081
117337
|
setResumeData(data);
|
|
117082
117338
|
} catch (error) {
|
|
117083
117339
|
if (error instanceof APIError && (error.status === 404 || error.status === 422)) {
|
|
@@ -117096,8 +117352,7 @@ Error: ${message}`);
|
|
|
117096
117352
|
if (lastSession && lastSession.agentId === agent.id) {
|
|
117097
117353
|
try {
|
|
117098
117354
|
setLoadingState("checking");
|
|
117099
|
-
const
|
|
117100
|
-
const data = await getResumeData(client, freshAgent, lastSession.conversationId);
|
|
117355
|
+
const data = await getResumeData(client, agent, lastSession.conversationId);
|
|
117101
117356
|
conversationIdToUse = lastSession.conversationId;
|
|
117102
117357
|
setResumedExistingConversation(true);
|
|
117103
117358
|
setResumeData(data);
|
|
@@ -117118,8 +117373,7 @@ Error: ${message}`);
|
|
|
117118
117373
|
} else if (selectedConversationId) {
|
|
117119
117374
|
try {
|
|
117120
117375
|
setLoadingState("checking");
|
|
117121
|
-
const
|
|
117122
|
-
const data = await getResumeData(client, freshAgent, selectedConversationId);
|
|
117376
|
+
const data = await getResumeData(client, agent, selectedConversationId);
|
|
117123
117377
|
conversationIdToUse = selectedConversationId;
|
|
117124
117378
|
setResumedExistingConversation(true);
|
|
117125
117379
|
setResumeData(data);
|
|
@@ -117139,11 +117393,22 @@ Error: ${message}`);
|
|
|
117139
117393
|
} else {
|
|
117140
117394
|
conversationIdToUse = "default";
|
|
117141
117395
|
setLoadingState("checking");
|
|
117142
|
-
const
|
|
117143
|
-
|
|
117396
|
+
const [data] = await Promise.all([
|
|
117397
|
+
getResumeData(client, agent, "default"),
|
|
117398
|
+
memfsSyncPromise.catch((error) => {
|
|
117399
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
117400
|
+
process.exit(1);
|
|
117401
|
+
})
|
|
117402
|
+
]);
|
|
117144
117403
|
setResumeData(data);
|
|
117145
117404
|
setResumedExistingConversation(true);
|
|
117146
117405
|
}
|
|
117406
|
+
try {
|
|
117407
|
+
await memfsSyncPromise;
|
|
117408
|
+
} catch (error) {
|
|
117409
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
117410
|
+
process.exit(1);
|
|
117411
|
+
}
|
|
117147
117412
|
if (!isSubagent) {
|
|
117148
117413
|
settingsManager2.setLocalLastSession({ agentId: agent.id, conversationId: conversationIdToUse }, process.cwd());
|
|
117149
117414
|
settingsManager2.setGlobalLastSession({
|
|
@@ -117176,6 +117441,7 @@ Error during initialization: ${message}`);
|
|
|
117176
117441
|
fromAfFile2,
|
|
117177
117442
|
loadingState,
|
|
117178
117443
|
selectedGlobalAgentId,
|
|
117444
|
+
validatedAgent,
|
|
117179
117445
|
shouldContinue,
|
|
117180
117446
|
resumeAgentId,
|
|
117181
117447
|
selectedConversationId
|
|
@@ -117291,4 +117557,4 @@ Error during initialization: ${message}`);
|
|
|
117291
117557
|
}
|
|
117292
117558
|
main();
|
|
117293
117559
|
|
|
117294
|
-
//# debugId=
|
|
117560
|
+
//# debugId=B0F648D57141B93564756E2164756E21
|