@letta-ai/letta-code 0.13.1 → 0.13.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.
Files changed (2) hide show
  1. package/letta.js +790 -453
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3065,7 +3065,7 @@ var package_default;
3065
3065
  var init_package = __esm(() => {
3066
3066
  package_default = {
3067
3067
  name: "@letta-ai/letta-code",
3068
- version: "0.13.1",
3068
+ version: "0.13.2",
3069
3069
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3070
3070
  type: "module",
3071
3071
  bin: {
@@ -5916,32 +5916,30 @@ var init_plan = () => {};
5916
5916
  var recall_default = `---
5917
5917
  name: recall
5918
5918
  description: Search conversation history to recall past discussions, decisions, and context
5919
- tools: Skill, Bash, Read, BashOutput
5920
- model: haiku
5921
- memoryBlocks: human, persona, skills, loaded_skills
5919
+ tools: Bash, Read, BashOutput
5920
+ model: opus
5921
+ memoryBlocks: skills, loaded_skills
5922
+ skills: searching-messages
5922
5923
  mode: stateless
5923
5924
  ---
5924
5925
 
5925
5926
  You are a subagent launched via the Task tool to search conversation history. You run autonomously and return a single final report when done. You CANNOT ask questions mid-execution.
5926
5927
 
5927
- ## Instructions
5928
-
5929
- ### Step 1: Load the searching-messages skill
5930
- \`\`\`
5931
- Skill({ command: "load", skills: ["searching-messages"] })
5932
- \`\`\`
5933
-
5934
- After loading, your \`loaded_skills\` memory block contains the full instructions with ready-to-use bash commands. Follow them directly - do not search for files or guess at commands.
5928
+ ## CRITICAL WARNINGS
5935
5929
 
5936
- ### Step 2: Search the parent agent's history
5930
+ 1. **NEVER use \`conversation_search\`** - It only searches YOUR empty history, not the parent's.
5931
+ 2. **NEVER invent commands** - There is NO \`letta messages search\` or \`letta messages list\`. These don't exist.
5937
5932
 
5938
- **CRITICAL - Two rules:**
5933
+ ## Instructions
5939
5934
 
5940
- 1. **DO NOT use \`conversation_search\`** - That tool only searches YOUR history (empty). You MUST use the Bash scripts from the skill.
5935
+ The \`searching-messages\` skill is pre-loaded in your \`<loaded_skills>\` memory block below. Read it carefully - it contains:
5936
+ - \`# Skill Directory:\` - the exact path to use in commands
5937
+ - Multiple search strategies (needle + expand, date-bounded, broad discovery)
5938
+ - Command options and examples
5941
5939
 
5942
- 2. **ALWAYS add \`--agent-id $LETTA_PARENT_AGENT_ID\`** - This searches the parent agent's history. The only exception is \`--all-agents\` searches.
5940
+ **Follow the skill's strategies thoroughly.** Use multiple searches if needed to gather comprehensive context. Always add \`--agent-id $LETTA_PARENT_AGENT_ID\` to search the parent agent's history.
5943
5941
 
5944
- Follow the strategies documented in the loaded skill.
5942
+ After gathering results, compile a comprehensive report.
5945
5943
 
5946
5944
  ## Output Format
5947
5945
 
@@ -9675,6 +9673,7 @@ var init_truncation = __esm(() => {
9675
9673
  init_overflow();
9676
9674
  LIMITS = {
9677
9675
  BASH_OUTPUT_CHARS: 30000,
9676
+ TASK_OUTPUT_CHARS: 30000,
9678
9677
  READ_MAX_LINES: 2000,
9679
9678
  READ_MAX_CHARS_PER_LINE: 2000,
9680
9679
  GREP_OUTPUT_CHARS: 1e4,
@@ -19528,6 +19527,33 @@ ${pathLine}${processedContent}`;
19528
19527
  throw new Error(`Failed to ${command} skill(s): ${String(error)}`);
19529
19528
  }
19530
19529
  }
19530
+ async function preloadSkillsContent(skillIds, skillsDir) {
19531
+ if (skillIds.length === 0) {
19532
+ return "No skills currently loaded.";
19533
+ }
19534
+ let content = "";
19535
+ for (const skillId of skillIds) {
19536
+ try {
19537
+ const { content: skillContent, path: skillPath } = await readSkillContent(skillId, skillsDir);
19538
+ const skillDir = dirname5(skillPath);
19539
+ const hasExtras = hasAdditionalFiles(skillPath);
19540
+ const pathLine = hasExtras ? `# Skill Directory: ${skillDir}
19541
+
19542
+ ` : "";
19543
+ const processedContent = hasExtras ? skillContent.replace(/<SKILL_DIR>/g, skillDir) : skillContent;
19544
+ const separator = content ? `
19545
+
19546
+ ---
19547
+
19548
+ ` : "";
19549
+ content = `${content}${separator}# Skill: ${skillId}
19550
+ ${pathLine}${processedContent}`;
19551
+ } catch (error) {
19552
+ console.error(`Warning: Could not pre-load skill "${skillId}": ${error instanceof Error ? error.message : String(error)}`);
19553
+ }
19554
+ }
19555
+ return content || "No skills currently loaded.";
19556
+ }
19531
19557
  var init_Skill2 = __esm(async () => {
19532
19558
  init_context();
19533
19559
  init_skills2();
@@ -19921,7 +19947,7 @@ function parseResultFromStdout(stdout, agentId) {
19921
19947
  };
19922
19948
  }
19923
19949
  }
19924
- function buildSubagentArgs(type, config, model, userPrompt) {
19950
+ function buildSubagentArgs(type, config, model, userPrompt, preloadedSkillsContent) {
19925
19951
  const args = [
19926
19952
  "--new-agent",
19927
19953
  "--system",
@@ -19959,6 +19985,9 @@ function buildSubagentArgs(type, config, model, userPrompt) {
19959
19985
  if (config.allowedTools !== "all" && Array.isArray(config.allowedTools) && config.allowedTools.length > 0) {
19960
19986
  args.push("--tools", config.allowedTools.join(","));
19961
19987
  }
19988
+ if (preloadedSkillsContent) {
19989
+ args.push("--block-value", `loaded_skills=${preloadedSkillsContent}`);
19990
+ }
19962
19991
  return args;
19963
19992
  }
19964
19993
  async function executeSubagent(type, config, model, userPrompt, baseURL, subagentId, isRetry = false, signal) {
@@ -19972,7 +20001,11 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
19972
20001
  }
19973
20002
  updateSubagent(subagentId, { model });
19974
20003
  try {
19975
- const cliArgs = buildSubagentArgs(type, config, model, userPrompt);
20004
+ let preloadedSkillsContent;
20005
+ if (config.skills && config.skills.length > 0) {
20006
+ preloadedSkillsContent = await preloadSkillsContent(config.skills, SKILLS_DIR);
20007
+ }
20008
+ const cliArgs = buildSubagentArgs(type, config, model, userPrompt, preloadedSkillsContent);
19976
20009
  const lettaCmd = process.env.LETTA_CODE_BIN || "letta";
19977
20010
  let parentAgentId;
19978
20011
  try {
@@ -20103,9 +20136,11 @@ var init_manager2 = __esm(async () => {
20103
20136
  init_session();
20104
20137
  init_context();
20105
20138
  init_model();
20139
+ init_skills2();
20106
20140
  init_subagents();
20107
20141
  await __promiseAll([
20108
20142
  init_settings_manager(),
20143
+ init_Skill2(),
20109
20144
  init_client2()
20110
20145
  ]);
20111
20146
  });
@@ -20152,9 +20187,12 @@ async function task(args) {
20152
20187
  `subagent_type=${subagent_type}`,
20153
20188
  result.agentId ? `agent_id=${result.agentId}` : undefined
20154
20189
  ].filter(Boolean).join(" ");
20155
- return `${header}
20190
+ const fullOutput = `${header}
20156
20191
 
20157
20192
  ${result.report}`;
20193
+ const userCwd = process.env.USER_CWD || process.cwd();
20194
+ const { content: truncatedOutput } = truncateByChars(fullOutput, LIMITS.TASK_OUTPUT_CHARS, "Task", { workingDirectory: userCwd, toolName: "Task" });
20195
+ return truncatedOutput;
20158
20196
  } catch (error) {
20159
20197
  const errorMessage = error instanceof Error ? error.message : String(error);
20160
20198
  completeSubagent(subagentId, { success: false, error: errorMessage });
@@ -20164,6 +20202,7 @@ ${result.report}`;
20164
20202
  var init_Task2 = __esm(async () => {
20165
20203
  init_subagents();
20166
20204
  init_subagentState();
20205
+ init_truncation();
20167
20206
  await init_manager2();
20168
20207
  });
20169
20208
 
@@ -24267,7 +24306,7 @@ var init_manager3 = __esm(async () => {
24267
24306
 
24268
24307
  // src/agent/create.ts
24269
24308
  import { join as join11 } from "node:path";
24270
- async function createAgent(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingModel = "openai/text-embedding-3-small", updateArgs, skillsDirectory, parallelToolCalls = true, enableSleeptime = false, systemPromptPreset, initBlocks, baseTools) {
24309
+ async function createAgent(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingModel, updateArgs, skillsDirectory, parallelToolCalls = true, enableSleeptime = false, systemPromptPreset, initBlocks, baseTools) {
24271
24310
  let options;
24272
24311
  if (typeof nameOrOptions === "object") {
24273
24312
  options = nameOrOptions;
@@ -24286,7 +24325,7 @@ async function createAgent(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingM
24286
24325
  };
24287
24326
  }
24288
24327
  const name = options.name ?? DEFAULT_AGENT_NAME;
24289
- const embeddingModelVal = options.embeddingModel ?? "openai/text-embedding-3-small";
24328
+ const embeddingModelVal = options.embeddingModel;
24290
24329
  const parallelToolCallsVal = options.parallelToolCalls ?? true;
24291
24330
  const enableSleeptimeVal = options.enableSleeptime ?? false;
24292
24331
  let modelHandle;
@@ -24408,7 +24447,7 @@ ${options.systemPromptAppend}`;
24408
24447
  system: systemPromptContent,
24409
24448
  name,
24410
24449
  description: agentDescription,
24411
- embedding: embeddingModelVal,
24450
+ embedding: embeddingModelVal || undefined,
24412
24451
  model: modelHandle,
24413
24452
  context_window_limit: contextWindow,
24414
24453
  tools: toolNames,
@@ -50487,6 +50526,103 @@ var init_auto_update = __esm(() => {
50487
50526
  DEBUG = process.env.LETTA_DEBUG_AUTOUPDATE === "1";
50488
50527
  });
50489
50528
 
50529
+ // src/tools/impl/overflow.ts
50530
+ var exports_overflow = {};
50531
+ __export(exports_overflow, {
50532
+ writeOverflowFile: () => writeOverflowFile2,
50533
+ getOverflowStats: () => getOverflowStats,
50534
+ getOverflowDirectory: () => getOverflowDirectory2,
50535
+ ensureOverflowDirectory: () => ensureOverflowDirectory2,
50536
+ cleanupOldOverflowFiles: () => cleanupOldOverflowFiles,
50537
+ OVERFLOW_CONFIG: () => OVERFLOW_CONFIG2
50538
+ });
50539
+ import { randomUUID as randomUUID2 } from "node:crypto";
50540
+ import * as fs10 from "node:fs";
50541
+ import * as os3 from "node:os";
50542
+ import * as path18 from "node:path";
50543
+ function getOverflowDirectory2(workingDirectory) {
50544
+ const homeDir = os3.homedir();
50545
+ const lettaDir = path18.join(homeDir, ".letta");
50546
+ const normalizedPath = path18.normalize(workingDirectory);
50547
+ const sanitizedPath = normalizedPath.replace(/^[/\\]/, "").replace(/[/\\:]/g, "_").replace(/\s+/g, "_");
50548
+ const overflowDir = path18.join(lettaDir, "projects", sanitizedPath, "agent-tools");
50549
+ return overflowDir;
50550
+ }
50551
+ function ensureOverflowDirectory2(workingDirectory) {
50552
+ const overflowDir = getOverflowDirectory2(workingDirectory);
50553
+ if (!fs10.existsSync(overflowDir)) {
50554
+ fs10.mkdirSync(overflowDir, { recursive: true });
50555
+ }
50556
+ return overflowDir;
50557
+ }
50558
+ function writeOverflowFile2(content, workingDirectory, toolName) {
50559
+ const overflowDir = ensureOverflowDirectory2(workingDirectory);
50560
+ const uuid = randomUUID2();
50561
+ const filename = toolName ? `${toolName.toLowerCase()}-${uuid}.txt` : `${uuid}.txt`;
50562
+ const filePath = path18.join(overflowDir, filename);
50563
+ fs10.writeFileSync(filePath, content, "utf-8");
50564
+ return filePath;
50565
+ }
50566
+ function cleanupOldOverflowFiles(workingDirectory, maxAgeMs = 24 * 60 * 60 * 1000) {
50567
+ const overflowDir = getOverflowDirectory2(workingDirectory);
50568
+ if (!fs10.existsSync(overflowDir)) {
50569
+ return 0;
50570
+ }
50571
+ let files;
50572
+ try {
50573
+ files = fs10.readdirSync(overflowDir);
50574
+ } catch {
50575
+ return 0;
50576
+ }
50577
+ const now = Date.now();
50578
+ let deletedCount = 0;
50579
+ for (const file of files) {
50580
+ const filePath = path18.join(overflowDir, file);
50581
+ try {
50582
+ const stats = fs10.statSync(filePath);
50583
+ if (stats.isDirectory()) {
50584
+ continue;
50585
+ }
50586
+ if (now - stats.mtimeMs > maxAgeMs) {
50587
+ fs10.unlinkSync(filePath);
50588
+ deletedCount++;
50589
+ }
50590
+ } catch {}
50591
+ }
50592
+ return deletedCount;
50593
+ }
50594
+ function getOverflowStats(workingDirectory) {
50595
+ const overflowDir = getOverflowDirectory2(workingDirectory);
50596
+ if (!fs10.existsSync(overflowDir)) {
50597
+ return {
50598
+ directory: overflowDir,
50599
+ exists: false,
50600
+ fileCount: 0,
50601
+ totalSize: 0
50602
+ };
50603
+ }
50604
+ const files = fs10.readdirSync(overflowDir);
50605
+ let totalSize = 0;
50606
+ for (const file of files) {
50607
+ const filePath = path18.join(overflowDir, file);
50608
+ const stats = fs10.statSync(filePath);
50609
+ totalSize += stats.size;
50610
+ }
50611
+ return {
50612
+ directory: overflowDir,
50613
+ exists: true,
50614
+ fileCount: files.length,
50615
+ totalSize
50616
+ };
50617
+ }
50618
+ var OVERFLOW_CONFIG2;
50619
+ var init_overflow2 = __esm(() => {
50620
+ OVERFLOW_CONFIG2 = {
50621
+ ENABLED: process.env.LETTA_TOOL_OVERFLOW_TO_FILE?.toLowerCase() !== "false",
50622
+ MIDDLE_TRUNCATE: process.env.LETTA_TOOL_MIDDLE_TRUNCATE?.toLowerCase() !== "false"
50623
+ };
50624
+ });
50625
+
50490
50626
  // src/agent/promptAssets.ts
50491
50627
  var exports_promptAssets2 = {};
50492
50628
  __export(exports_promptAssets2, {
@@ -50620,9 +50756,9 @@ __export(exports_subagents2, {
50620
50756
  GLOBAL_AGENTS_DIR: () => GLOBAL_AGENTS_DIR2,
50621
50757
  AGENTS_DIR: () => AGENTS_DIR2
50622
50758
  });
50623
- import { existsSync as existsSync8 } from "node:fs";
50759
+ import { existsSync as existsSync9 } from "node:fs";
50624
50760
  import { readdir as readdir6, readFile as readFile7 } from "node:fs/promises";
50625
- import { join as join15 } from "node:path";
50761
+ import { join as join16 } from "node:path";
50626
50762
  function isValidName2(name) {
50627
50763
  return /^[a-z][a-z0-9-]*$/.test(name);
50628
50764
  }
@@ -50704,7 +50840,7 @@ function getBuiltinSubagentNames2() {
50704
50840
  return new Set(Object.keys(getBuiltinSubagents2()));
50705
50841
  }
50706
50842
  async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors) {
50707
- if (!existsSync8(agentsDir)) {
50843
+ if (!existsSync9(agentsDir)) {
50708
50844
  return;
50709
50845
  }
50710
50846
  try {
@@ -50713,7 +50849,7 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
50713
50849
  if (!entry.isFile() || !entry.name.endsWith(".md")) {
50714
50850
  continue;
50715
50851
  }
50716
- const filePath = join15(agentsDir, entry.name);
50852
+ const filePath = join16(agentsDir, entry.name);
50717
50853
  try {
50718
50854
  const config = await parseSubagentFile2(filePath);
50719
50855
  if (config) {
@@ -50745,7 +50881,7 @@ async function discoverSubagents2(workingDirectory = process.cwd()) {
50745
50881
  const subagents = [];
50746
50882
  const seenNames = new Set;
50747
50883
  await discoverSubagentsFromDir2(GLOBAL_AGENTS_DIR2, seenNames, subagents, errors);
50748
- const projectAgentsDir = join15(workingDirectory, AGENTS_DIR2);
50884
+ const projectAgentsDir = join16(workingDirectory, AGENTS_DIR2);
50749
50885
  await discoverSubagentsFromDir2(projectAgentsDir, seenNames, subagents, errors);
50750
50886
  return { subagents, errors };
50751
50887
  }
@@ -50784,7 +50920,7 @@ var init_subagents2 = __esm(() => {
50784
50920
  plan_default,
50785
50921
  recall_default
50786
50922
  ];
50787
- GLOBAL_AGENTS_DIR2 = join15(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
50923
+ GLOBAL_AGENTS_DIR2 = join16(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
50788
50924
  VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
50789
50925
  cache4 = {
50790
50926
  builtins: null,
@@ -50794,10 +50930,10 @@ var init_subagents2 = __esm(() => {
50794
50930
  });
50795
50931
 
50796
50932
  // node_modules/is-docker/index.js
50797
- import fs10 from "node:fs";
50933
+ import fs11 from "node:fs";
50798
50934
  function hasDockerEnv() {
50799
50935
  try {
50800
- fs10.statSync("/.dockerenv");
50936
+ fs11.statSync("/.dockerenv");
50801
50937
  return true;
50802
50938
  } catch {
50803
50939
  return false;
@@ -50805,7 +50941,7 @@ function hasDockerEnv() {
50805
50941
  }
50806
50942
  function hasDockerCGroup() {
50807
50943
  try {
50808
- return fs10.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
50944
+ return fs11.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
50809
50945
  } catch {
50810
50946
  return false;
50811
50947
  }
@@ -50820,7 +50956,7 @@ var isDockerCached;
50820
50956
  var init_is_docker = () => {};
50821
50957
 
50822
50958
  // node_modules/is-inside-container/index.js
50823
- import fs11 from "node:fs";
50959
+ import fs12 from "node:fs";
50824
50960
  function isInsideContainer() {
50825
50961
  if (cachedResult === undefined) {
50826
50962
  cachedResult = hasContainerEnv() || isDocker();
@@ -50829,7 +50965,7 @@ function isInsideContainer() {
50829
50965
  }
50830
50966
  var cachedResult, hasContainerEnv = () => {
50831
50967
  try {
50832
- fs11.statSync("/run/.containerenv");
50968
+ fs12.statSync("/run/.containerenv");
50833
50969
  return true;
50834
50970
  } catch {
50835
50971
  return false;
@@ -50841,20 +50977,20 @@ var init_is_inside_container = __esm(() => {
50841
50977
 
50842
50978
  // node_modules/is-wsl/index.js
50843
50979
  import process13 from "node:process";
50844
- import os3 from "node:os";
50845
- import fs12 from "node:fs";
50980
+ import os4 from "node:os";
50981
+ import fs13 from "node:fs";
50846
50982
  var isWsl = () => {
50847
50983
  if (process13.platform !== "linux") {
50848
50984
  return false;
50849
50985
  }
50850
- if (os3.release().toLowerCase().includes("microsoft")) {
50986
+ if (os4.release().toLowerCase().includes("microsoft")) {
50851
50987
  if (isInsideContainer()) {
50852
50988
  return false;
50853
50989
  }
50854
50990
  return true;
50855
50991
  }
50856
50992
  try {
50857
- return fs12.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
50993
+ return fs13.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
50858
50994
  } catch {
50859
50995
  return false;
50860
50996
  }
@@ -50866,7 +51002,7 @@ var init_is_wsl = __esm(() => {
50866
51002
 
50867
51003
  // node_modules/wsl-utils/index.js
50868
51004
  import process14 from "node:process";
50869
- import fs13, { constants as fsConstants } from "node:fs/promises";
51005
+ import fs14, { constants as fsConstants } from "node:fs/promises";
50870
51006
  var wslDrivesMountPoint, powerShellPathFromWsl = async () => {
50871
51007
  const mountPoint = await wslDrivesMountPoint();
50872
51008
  return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
@@ -50889,13 +51025,13 @@ var init_wsl_utils = __esm(() => {
50889
51025
  const configFilePath = "/etc/wsl.conf";
50890
51026
  let isConfigFileExists = false;
50891
51027
  try {
50892
- await fs13.access(configFilePath, fsConstants.F_OK);
51028
+ await fs14.access(configFilePath, fsConstants.F_OK);
50893
51029
  isConfigFileExists = true;
50894
51030
  } catch {}
50895
51031
  if (!isConfigFileExists) {
50896
51032
  return defaultMountPoint;
50897
51033
  }
50898
- const configContent = await fs13.readFile(configFilePath, { encoding: "utf8" });
51034
+ const configContent = await fs14.readFile(configFilePath, { encoding: "utf8" });
50899
51035
  const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
50900
51036
  if (!configMountPoint) {
50901
51037
  return defaultMountPoint;
@@ -51049,11 +51185,11 @@ __export(exports_open, {
51049
51185
  });
51050
51186
  import process18 from "node:process";
51051
51187
  import { Buffer as Buffer3 } from "node:buffer";
51052
- import path18 from "node:path";
51188
+ import path19 from "node:path";
51053
51189
  import { fileURLToPath as fileURLToPath8 } from "node:url";
51054
51190
  import { promisify as promisify8 } from "node:util";
51055
51191
  import childProcess from "node:child_process";
51056
- import fs14, { constants as fsConstants2 } from "node:fs/promises";
51192
+ import fs15, { constants as fsConstants2 } from "node:fs/promises";
51057
51193
  async function getWindowsDefaultBrowserFromWsl() {
51058
51194
  const powershellPath = await powerShellPath();
51059
51195
  const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
@@ -51210,7 +51346,7 @@ var execFile7, __dirname2, localXdgOpenPath, platform2, arch, pTryEach = async (
51210
51346
  const isBundled = !__dirname2 || __dirname2 === "/";
51211
51347
  let exeLocalXdgOpen = false;
51212
51348
  try {
51213
- await fs14.access(localXdgOpenPath, fsConstants2.X_OK);
51349
+ await fs15.access(localXdgOpenPath, fsConstants2.X_OK);
51214
51350
  exeLocalXdgOpen = true;
51215
51351
  } catch {}
51216
51352
  const useSystemXdgOpen = process18.versions.electron ?? (platform2 === "android" || isBundled || !exeLocalXdgOpen);
@@ -51274,8 +51410,8 @@ var init_open = __esm(() => {
51274
51410
  init_default_browser();
51275
51411
  init_is_inside_container();
51276
51412
  execFile7 = promisify8(childProcess.execFile);
51277
- __dirname2 = path18.dirname(fileURLToPath8(import.meta.url));
51278
- localXdgOpenPath = path18.join(__dirname2, "xdg-open");
51413
+ __dirname2 = path19.dirname(fileURLToPath8(import.meta.url));
51414
+ localXdgOpenPath = path19.join(__dirname2, "xdg-open");
51279
51415
  ({ platform: platform2, arch } = process18);
51280
51416
  apps = {};
51281
51417
  defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
@@ -52998,7 +53134,7 @@ __export(exports_approval_execution, {
52998
53134
  executeAutoAllowedTools: () => executeAutoAllowedTools,
52999
53135
  executeApprovalBatch: () => executeApprovalBatch
53000
53136
  });
53001
- import * as path19 from "node:path";
53137
+ import * as path20 from "node:path";
53002
53138
  function isParallelSafe(toolName) {
53003
53139
  return PARALLEL_SAFE_TOOLS.has(toolName);
53004
53140
  }
@@ -53010,7 +53146,7 @@ function getResourceKey(toolName, toolArgs) {
53010
53146
  const filePath = toolArgs.file_path;
53011
53147
  if (typeof filePath === "string") {
53012
53148
  const userCwd = process.env.USER_CWD || process.cwd();
53013
- return path19.isAbsolute(filePath) ? path19.normalize(filePath) : path19.resolve(userCwd, filePath);
53149
+ return path20.isAbsolute(filePath) ? path20.normalize(filePath) : path20.resolve(userCwd, filePath);
53014
53150
  }
53015
53151
  }
53016
53152
  return "__global__";
@@ -53660,8 +53796,8 @@ Usage: letta -p "..." --new-agent`);
53660
53796
  (async () => {
53661
53797
  try {
53662
53798
  const { syncSkillsToAgent: syncSkillsToAgent3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills2(), exports_skills));
53663
- const { join: join16 } = await import("node:path");
53664
- const resolvedSkillsDirectory = skillsDirectory || join16(process.cwd(), SKILLS_DIR3);
53799
+ const { join: join17 } = await import("node:path");
53800
+ const resolvedSkillsDirectory = skillsDirectory || join17(process.cwd(), SKILLS_DIR3);
53665
53801
  await syncSkillsToAgent3(client, agent.id, resolvedSkillsDirectory, {
53666
53802
  skipIfUnchanged: true
53667
53803
  });
@@ -54607,7 +54743,7 @@ __export(exports_kittyProtocolDetector, {
54607
54743
  isKittyProtocolEnabled: () => isKittyProtocolEnabled,
54608
54744
  detectAndEnableKittyProtocol: () => detectAndEnableKittyProtocol
54609
54745
  });
54610
- import * as fs15 from "node:fs";
54746
+ import * as fs16 from "node:fs";
54611
54747
  async function detectAndEnableKittyProtocol() {
54612
54748
  if (detectionComplete) {
54613
54749
  return;
@@ -54680,7 +54816,7 @@ async function detectAndEnableKittyProtocol() {
54680
54816
  if (DEBUG2) {
54681
54817
  console.error("[kitty] querying support");
54682
54818
  }
54683
- fs15.writeSync(process.stdout.fd, "\x1B[?u\x1B[c");
54819
+ fs16.writeSync(process.stdout.fd, "\x1B[?u\x1B[c");
54684
54820
  timeoutId = setTimeout(finish, 200);
54685
54821
  });
54686
54822
  }
@@ -54689,14 +54825,14 @@ function isKittyProtocolEnabled() {
54689
54825
  }
54690
54826
  function enableKittyKeyboardProtocol() {
54691
54827
  try {
54692
- fs15.writeSync(process.stdout.fd, "\x1B[>1u");
54828
+ fs16.writeSync(process.stdout.fd, "\x1B[>1u");
54693
54829
  kittyEnabled = true;
54694
54830
  } catch {}
54695
54831
  }
54696
54832
  function disableKittyKeyboardProtocol() {
54697
54833
  try {
54698
54834
  if (kittyEnabled) {
54699
- fs15.writeSync(process.stdout.fd, "\x1B[<u");
54835
+ fs16.writeSync(process.stdout.fd, "\x1B[<u");
54700
54836
  kittyEnabled = false;
54701
54837
  }
54702
54838
  } catch {}
@@ -54928,10 +55064,10 @@ __export(exports_settings, {
54928
55064
  loadProjectSettings: () => loadProjectSettings,
54929
55065
  getSetting: () => getSetting
54930
55066
  });
54931
- import { homedir as homedir9 } from "node:os";
54932
- import { join as join16 } from "node:path";
55067
+ import { homedir as homedir10 } from "node:os";
55068
+ import { join as join17 } from "node:path";
54933
55069
  function getSettingsPath() {
54934
- return join16(homedir9(), ".letta", "settings.json");
55070
+ return join17(homedir10(), ".letta", "settings.json");
54935
55071
  }
54936
55072
  async function loadSettings() {
54937
55073
  const settingsPath = getSettingsPath();
@@ -54968,7 +55104,7 @@ async function getSetting(key) {
54968
55104
  return settings[key];
54969
55105
  }
54970
55106
  function getProjectSettingsPath() {
54971
- return join16(process.cwd(), ".letta", "settings.local.json");
55107
+ return join17(process.cwd(), ".letta", "settings.local.json");
54972
55108
  }
54973
55109
  async function loadProjectSettings() {
54974
55110
  const settingsPath = getProjectSettingsPath();
@@ -54986,7 +55122,7 @@ async function loadProjectSettings() {
54986
55122
  }
54987
55123
  async function saveProjectSettings(settings) {
54988
55124
  const settingsPath = getProjectSettingsPath();
54989
- const dirPath = join16(process.cwd(), ".letta");
55125
+ const dirPath = join17(process.cwd(), ".letta");
54990
55126
  try {
54991
55127
  if (!exists(dirPath)) {
54992
55128
  await mkdir(dirPath, { recursive: true });
@@ -56157,7 +56293,7 @@ function parsePatchOperations(input) {
56157
56293
  continue;
56158
56294
  }
56159
56295
  if (line.startsWith("*** Add File:")) {
56160
- const path20 = line.replace("*** Add File:", "").trim();
56296
+ const path21 = line.replace("*** Add File:", "").trim();
56161
56297
  i++;
56162
56298
  const contentLines = [];
56163
56299
  const patchLines = [];
@@ -56173,7 +56309,7 @@ function parsePatchOperations(input) {
56173
56309
  }
56174
56310
  operations.push({
56175
56311
  kind: "add",
56176
- path: path20,
56312
+ path: path21,
56177
56313
  content: contentLines.join(`
56178
56314
  `),
56179
56315
  patchLines
@@ -56181,7 +56317,7 @@ function parsePatchOperations(input) {
56181
56317
  continue;
56182
56318
  }
56183
56319
  if (line.startsWith("*** Update File:")) {
56184
- const path20 = line.replace("*** Update File:", "").trim();
56320
+ const path21 = line.replace("*** Update File:", "").trim();
56185
56321
  i++;
56186
56322
  if (i < stopIdx && lines[i]?.startsWith("*** Move to:")) {
56187
56323
  i++;
@@ -56217,7 +56353,7 @@ function parsePatchOperations(input) {
56217
56353
  }
56218
56354
  operations.push({
56219
56355
  kind: "update",
56220
- path: path20,
56356
+ path: path21,
56221
56357
  oldString: oldParts.join(`
56222
56358
  `),
56223
56359
  newString: newParts.join(`
@@ -56227,8 +56363,8 @@ function parsePatchOperations(input) {
56227
56363
  continue;
56228
56364
  }
56229
56365
  if (line.startsWith("*** Delete File:")) {
56230
- const path20 = line.replace("*** Delete File:", "").trim();
56231
- operations.push({ kind: "delete", path: path20 });
56366
+ const path21 = line.replace("*** Delete File:", "").trim();
56367
+ operations.push({ kind: "delete", path: path21 });
56232
56368
  i++;
56233
56369
  continue;
56234
56370
  }
@@ -56460,16 +56596,16 @@ class Diff {
56460
56596
  }
56461
56597
  }
56462
56598
  }
56463
- addToPath(path20, added, removed, oldPosInc, options) {
56464
- const last = path20.lastComponent;
56599
+ addToPath(path21, added, removed, oldPosInc, options) {
56600
+ const last = path21.lastComponent;
56465
56601
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
56466
56602
  return {
56467
- oldPos: path20.oldPos + oldPosInc,
56603
+ oldPos: path21.oldPos + oldPosInc,
56468
56604
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
56469
56605
  };
56470
56606
  } else {
56471
56607
  return {
56472
- oldPos: path20.oldPos + oldPosInc,
56608
+ oldPos: path21.oldPos + oldPosInc,
56473
56609
  lastComponent: { count: 1, added, removed, previousComponent: last }
56474
56610
  };
56475
56611
  }
@@ -58206,9 +58342,9 @@ function getFileEditHeader(toolName, toolArgs) {
58206
58342
  const relPath = relative4(cwd2, filePath);
58207
58343
  const displayPath = relPath.startsWith("..") ? filePath : relPath;
58208
58344
  if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
58209
- const { existsSync: existsSync9 } = __require("node:fs");
58345
+ const { existsSync: existsSync10 } = __require("node:fs");
58210
58346
  try {
58211
- if (existsSync9(filePath)) {
58347
+ if (existsSync10(filePath)) {
58212
58348
  return `Overwrite ${displayPath}?`;
58213
58349
  }
58214
58350
  } catch {}
@@ -58891,9 +59027,9 @@ function getHeaderText(fileEdit) {
58891
59027
  const relPath = relative4(cwd2, fileEdit.filePath);
58892
59028
  const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
58893
59029
  if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
58894
- const { existsSync: existsSync9 } = __require("node:fs");
59030
+ const { existsSync: existsSync10 } = __require("node:fs");
58895
59031
  try {
58896
- if (existsSync9(fileEdit.filePath)) {
59032
+ if (existsSync10(fileEdit.filePath)) {
58897
59033
  return `Overwrite ${displayPath}?`;
58898
59034
  }
58899
59035
  } catch {}
@@ -60568,7 +60704,7 @@ var init_ApprovalSwitch = __esm(async () => {
60568
60704
  });
60569
60705
 
60570
60706
  // src/cli/components/AssistantMessageRich.tsx
60571
- var import_react43, jsx_dev_runtime21, normalize4 = (s) => s.replace(/\r\n/g, `
60707
+ var import_react43, jsx_dev_runtime21, normalize5 = (s) => s.replace(/\r\n/g, `
60572
60708
  `).replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, `
60573
60709
 
60574
60710
  `).replace(/^\n+|\n+$/g, ""), AssistantMessage;
@@ -60583,7 +60719,7 @@ var init_AssistantMessageRich = __esm(async () => {
60583
60719
  AssistantMessage = import_react43.memo(({ line }) => {
60584
60720
  const columns = useTerminalWidth();
60585
60721
  const contentWidth = Math.max(0, columns - 2);
60586
- const normalizedText = normalize4(line.text);
60722
+ const normalizedText = normalize5(line.text);
60587
60723
  return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
60588
60724
  flexDirection: "row",
60589
60725
  children: [
@@ -61802,7 +61938,7 @@ var init_pasteRegistry = __esm(() => {
61802
61938
 
61803
61939
  // src/cli/helpers/clipboard.ts
61804
61940
  import { execFileSync as execFileSync2 } from "node:child_process";
61805
- import { existsSync as existsSync9, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
61941
+ import { existsSync as existsSync10, readFileSync as readFileSync2, statSync as statSync3 } from "node:fs";
61806
61942
  import { basename as basename2, extname as extname3, isAbsolute as isAbsolute12, resolve as resolve18 } from "node:path";
61807
61943
  function countLines2(text) {
61808
61944
  return (text.match(/\r\n|\r|\n/g) || []).length + 1;
@@ -61853,7 +61989,7 @@ function translatePasteForImages(paste) {
61853
61989
  if (!isAbsolute12(filePath))
61854
61990
  filePath = resolve18(process.cwd(), filePath);
61855
61991
  const ext3 = extname3(filePath || "").toLowerCase();
61856
- if (IMAGE_EXTS.has(ext3) && existsSync9(filePath) && statSync2(filePath).isFile()) {
61992
+ if (IMAGE_EXTS.has(ext3) && existsSync10(filePath) && statSync3(filePath).isFile()) {
61857
61993
  const buf = readFileSync2(filePath);
61858
61994
  const b64 = buf.toString("base64");
61859
61995
  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";
@@ -62441,13 +62577,13 @@ __export(exports_terminalKeybindingInstaller, {
62441
62577
  });
62442
62578
  import {
62443
62579
  copyFileSync,
62444
- existsSync as existsSync10,
62445
- mkdirSync as mkdirSync4,
62580
+ existsSync as existsSync11,
62581
+ mkdirSync as mkdirSync5,
62446
62582
  readFileSync as readFileSync3,
62447
- writeFileSync as writeFileSync2
62583
+ writeFileSync as writeFileSync3
62448
62584
  } from "node:fs";
62449
- import { homedir as homedir10, platform as platform3 } from "node:os";
62450
- import { dirname as dirname10, join as join17 } from "node:path";
62585
+ import { homedir as homedir11, platform as platform3 } from "node:os";
62586
+ import { dirname as dirname10, join as join18 } from "node:path";
62451
62587
  function detectTerminalType() {
62452
62588
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
62453
62589
  return "cursor";
@@ -62477,18 +62613,18 @@ function getKeybindingsPath(terminal) {
62477
62613
  cursor: "Cursor",
62478
62614
  windsurf: "Windsurf"
62479
62615
  }[terminal];
62480
- const os4 = platform3();
62481
- if (os4 === "darwin") {
62482
- return join17(homedir10(), "Library", "Application Support", appName, "User", "keybindings.json");
62616
+ const os5 = platform3();
62617
+ if (os5 === "darwin") {
62618
+ return join18(homedir11(), "Library", "Application Support", appName, "User", "keybindings.json");
62483
62619
  }
62484
- if (os4 === "win32") {
62620
+ if (os5 === "win32") {
62485
62621
  const appData = process.env.APPDATA;
62486
62622
  if (!appData)
62487
62623
  return null;
62488
- return join17(appData, appName, "User", "keybindings.json");
62624
+ return join18(appData, appName, "User", "keybindings.json");
62489
62625
  }
62490
- if (os4 === "linux") {
62491
- return join17(homedir10(), ".config", appName, "User", "keybindings.json");
62626
+ if (os5 === "linux") {
62627
+ return join18(homedir11(), ".config", appName, "User", "keybindings.json");
62492
62628
  }
62493
62629
  return null;
62494
62630
  }
@@ -62510,7 +62646,7 @@ function parseKeybindings(content) {
62510
62646
  }
62511
62647
  }
62512
62648
  function keybindingExists(keybindingsPath) {
62513
- if (!existsSync10(keybindingsPath))
62649
+ if (!existsSync11(keybindingsPath))
62514
62650
  return false;
62515
62651
  try {
62516
62652
  const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
@@ -62523,7 +62659,7 @@ function keybindingExists(keybindingsPath) {
62523
62659
  }
62524
62660
  }
62525
62661
  function createBackup(keybindingsPath) {
62526
- if (!existsSync10(keybindingsPath))
62662
+ if (!existsSync11(keybindingsPath))
62527
62663
  return null;
62528
62664
  const backupPath = `${keybindingsPath}.letta-backup`;
62529
62665
  try {
@@ -62539,12 +62675,12 @@ function installKeybinding(keybindingsPath) {
62539
62675
  return { success: true, alreadyExists: true };
62540
62676
  }
62541
62677
  const parentDir = dirname10(keybindingsPath);
62542
- if (!existsSync10(parentDir)) {
62543
- mkdirSync4(parentDir, { recursive: true });
62678
+ if (!existsSync11(parentDir)) {
62679
+ mkdirSync5(parentDir, { recursive: true });
62544
62680
  }
62545
62681
  let keybindings = [];
62546
62682
  let backupPath = null;
62547
- if (existsSync10(keybindingsPath)) {
62683
+ if (existsSync11(keybindingsPath)) {
62548
62684
  backupPath = createBackup(keybindingsPath);
62549
62685
  const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
62550
62686
  const parsed = parseKeybindings(content);
@@ -62559,7 +62695,7 @@ function installKeybinding(keybindingsPath) {
62559
62695
  keybindings.push(SHIFT_ENTER_KEYBINDING);
62560
62696
  const newContent = `${JSON.stringify(keybindings, null, 2)}
62561
62697
  `;
62562
- writeFileSync2(keybindingsPath, newContent, { encoding: "utf-8" });
62698
+ writeFileSync3(keybindingsPath, newContent, { encoding: "utf-8" });
62563
62699
  return {
62564
62700
  success: true,
62565
62701
  backupPath: backupPath ?? undefined
@@ -62574,7 +62710,7 @@ function installKeybinding(keybindingsPath) {
62574
62710
  }
62575
62711
  function removeKeybinding(keybindingsPath) {
62576
62712
  try {
62577
- if (!existsSync10(keybindingsPath)) {
62713
+ if (!existsSync11(keybindingsPath)) {
62578
62714
  return { success: true };
62579
62715
  }
62580
62716
  const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
@@ -62588,7 +62724,7 @@ function removeKeybinding(keybindingsPath) {
62588
62724
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
62589
62725
  const newContent = `${JSON.stringify(filtered, null, 2)}
62590
62726
  `;
62591
- writeFileSync2(keybindingsPath, newContent, { encoding: "utf-8" });
62727
+ writeFileSync3(keybindingsPath, newContent, { encoding: "utf-8" });
62592
62728
  return { success: true };
62593
62729
  } catch (error) {
62594
62730
  const message = error instanceof Error ? error.message : String(error);
@@ -62606,14 +62742,14 @@ function installKeybindingForCurrentTerminal() {
62606
62742
  error: "Not running in a VS Code-like terminal"
62607
62743
  };
62608
62744
  }
62609
- const path20 = getKeybindingsPath(terminal);
62610
- if (!path20) {
62745
+ const path21 = getKeybindingsPath(terminal);
62746
+ if (!path21) {
62611
62747
  return {
62612
62748
  success: false,
62613
62749
  error: `Could not determine keybindings.json path for ${terminal}`
62614
62750
  };
62615
62751
  }
62616
- return installKeybinding(path20);
62752
+ return installKeybinding(path21);
62617
62753
  }
62618
62754
  function removeKeybindingForCurrentTerminal() {
62619
62755
  const terminal = detectTerminalType();
@@ -62623,14 +62759,14 @@ function removeKeybindingForCurrentTerminal() {
62623
62759
  error: "Not running in a VS Code-like terminal"
62624
62760
  };
62625
62761
  }
62626
- const path20 = getKeybindingsPath(terminal);
62627
- if (!path20) {
62762
+ const path21 = getKeybindingsPath(terminal);
62763
+ if (!path21) {
62628
62764
  return {
62629
62765
  success: false,
62630
62766
  error: `Could not determine keybindings.json path for ${terminal}`
62631
62767
  };
62632
62768
  }
62633
- return removeKeybinding(path20);
62769
+ return removeKeybinding(path21);
62634
62770
  }
62635
62771
  function isWezTerm() {
62636
62772
  return process.env.TERM_PROGRAM === "WezTerm";
@@ -62641,17 +62777,17 @@ function getWezTermConfigPath() {
62641
62777
  }
62642
62778
  const xdgConfig = process.env.XDG_CONFIG_HOME;
62643
62779
  if (xdgConfig) {
62644
- const xdgPath = join17(xdgConfig, "wezterm", "wezterm.lua");
62645
- if (existsSync10(xdgPath))
62780
+ const xdgPath = join18(xdgConfig, "wezterm", "wezterm.lua");
62781
+ if (existsSync11(xdgPath))
62646
62782
  return xdgPath;
62647
62783
  }
62648
- const configPath = join17(homedir10(), ".config", "wezterm", "wezterm.lua");
62649
- if (existsSync10(configPath))
62784
+ const configPath = join18(homedir11(), ".config", "wezterm", "wezterm.lua");
62785
+ if (existsSync11(configPath))
62650
62786
  return configPath;
62651
- return join17(homedir10(), ".wezterm.lua");
62787
+ return join18(homedir11(), ".wezterm.lua");
62652
62788
  }
62653
62789
  function wezTermDeleteFixExists(configPath) {
62654
- if (!existsSync10(configPath))
62790
+ if (!existsSync11(configPath))
62655
62791
  return false;
62656
62792
  try {
62657
62793
  const content = readFileSync3(configPath, { encoding: "utf-8" });
@@ -62668,7 +62804,7 @@ function installWezTermDeleteFix() {
62668
62804
  }
62669
62805
  let content = "";
62670
62806
  let backupPath = null;
62671
- if (existsSync10(configPath)) {
62807
+ if (existsSync11(configPath)) {
62672
62808
  backupPath = `${configPath}.letta-backup`;
62673
62809
  copyFileSync(configPath, backupPath);
62674
62810
  content = readFileSync3(configPath, { encoding: "utf-8" });
@@ -62698,10 +62834,10 @@ ${WEZTERM_DELETE_FIX}
62698
62834
  `;
62699
62835
  }
62700
62836
  const parentDir = dirname10(configPath);
62701
- if (!existsSync10(parentDir)) {
62702
- mkdirSync4(parentDir, { recursive: true });
62837
+ if (!existsSync11(parentDir)) {
62838
+ mkdirSync5(parentDir, { recursive: true });
62703
62839
  }
62704
- writeFileSync2(configPath, content, { encoding: "utf-8" });
62840
+ writeFileSync3(configPath, content, { encoding: "utf-8" });
62705
62841
  return {
62706
62842
  success: true,
62707
62843
  backupPath: backupPath ?? undefined
@@ -63098,9 +63234,9 @@ __export(exports_custom, {
63098
63234
  GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
63099
63235
  COMMANDS_DIR: () => COMMANDS_DIR
63100
63236
  });
63101
- import { existsSync as existsSync11 } from "node:fs";
63237
+ import { existsSync as existsSync12 } from "node:fs";
63102
63238
  import { readdir as readdir7, readFile as readFile8 } from "node:fs/promises";
63103
- import { basename as basename3, dirname as dirname11, join as join18 } from "node:path";
63239
+ import { basename as basename3, dirname as dirname11, join as join19 } from "node:path";
63104
63240
  async function getCustomCommands() {
63105
63241
  if (cachedCommands !== null) {
63106
63242
  return cachedCommands;
@@ -63111,7 +63247,7 @@ async function getCustomCommands() {
63111
63247
  function refreshCustomCommands() {
63112
63248
  cachedCommands = null;
63113
63249
  }
63114
- async function discoverCustomCommands(projectPath = join18(process.cwd(), COMMANDS_DIR)) {
63250
+ async function discoverCustomCommands(projectPath = join19(process.cwd(), COMMANDS_DIR)) {
63115
63251
  const commandsById = new Map;
63116
63252
  const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
63117
63253
  for (const cmd of userCommands) {
@@ -63132,7 +63268,7 @@ async function discoverCustomCommands(projectPath = join18(process.cwd(), COMMAN
63132
63268
  return result;
63133
63269
  }
63134
63270
  async function discoverFromDirectory(dirPath, source) {
63135
- if (!existsSync11(dirPath)) {
63271
+ if (!existsSync12(dirPath)) {
63136
63272
  return [];
63137
63273
  }
63138
63274
  const commands2 = [];
@@ -63143,7 +63279,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source) {
63143
63279
  try {
63144
63280
  const entries = await readdir7(currentPath, { withFileTypes: true });
63145
63281
  for (const entry of entries) {
63146
- const fullPath = join18(currentPath, entry.name);
63282
+ const fullPath = join19(currentPath, entry.name);
63147
63283
  if (entry.isDirectory()) {
63148
63284
  await findCommandFiles(fullPath, rootPath, commands2, source);
63149
63285
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -63228,7 +63364,7 @@ async function findCustomCommand(commandName) {
63228
63364
  }
63229
63365
  var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
63230
63366
  var init_custom = __esm(() => {
63231
- GLOBAL_COMMANDS_DIR = join18(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
63367
+ GLOBAL_COMMANDS_DIR = join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
63232
63368
  });
63233
63369
 
63234
63370
  // src/cli/components/HelpDialog.tsx
@@ -66077,7 +66213,7 @@ var require_jsx_runtime = __commonJS((exports, module) => {
66077
66213
 
66078
66214
  // node_modules/supports-color/index.js
66079
66215
  import process19 from "node:process";
66080
- import os4 from "node:os";
66216
+ import os5 from "node:os";
66081
66217
  import tty2 from "node:tty";
66082
66218
  function hasFlag2(flag, argv = globalThis.Deno ? globalThis.Deno.args : process19.argv) {
66083
66219
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
@@ -66143,7 +66279,7 @@ function _supportsColor2(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
66143
66279
  return min;
66144
66280
  }
66145
66281
  if (process19.platform === "win32") {
66146
- const osRelease = os4.release().split(".");
66282
+ const osRelease = os5.release().split(".");
66147
66283
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
66148
66284
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
66149
66285
  }
@@ -66498,21 +66634,21 @@ var init_AgentInfoBar = __esm(async () => {
66498
66634
  });
66499
66635
 
66500
66636
  // src/cli/helpers/fileSearch.ts
66501
- import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
66502
- import { join as join19, resolve as resolve19 } from "node:path";
66637
+ import { readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
66638
+ import { join as join20, resolve as resolve19 } from "node:path";
66503
66639
  function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = []) {
66504
66640
  if (results.length >= maxResults) {
66505
66641
  return results;
66506
66642
  }
66507
66643
  try {
66508
- const entries = readdirSync4(dir);
66644
+ const entries = readdirSync5(dir);
66509
66645
  for (const entry of entries) {
66510
66646
  if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "build") {
66511
66647
  continue;
66512
66648
  }
66513
66649
  try {
66514
- const fullPath = join19(dir, entry);
66515
- const stats = statSync3(fullPath);
66650
+ const fullPath = join20(dir, entry);
66651
+ const stats = statSync4(fullPath);
66516
66652
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
66517
66653
  const matches = pattern.length === 0 || relativePath.toLowerCase().includes(pattern.toLowerCase());
66518
66654
  if (matches) {
@@ -66544,7 +66680,7 @@ async function searchFiles(query, deep = false) {
66544
66680
  try {
66545
66681
  const resolvedDir = resolve19(process.cwd(), dirPart);
66546
66682
  try {
66547
- statSync3(resolvedDir);
66683
+ statSync4(resolvedDir);
66548
66684
  searchDir = resolvedDir;
66549
66685
  searchPattern = pattern;
66550
66686
  } catch {}
@@ -66556,15 +66692,15 @@ async function searchFiles(query, deep = false) {
66556
66692
  } else {
66557
66693
  let entries = [];
66558
66694
  try {
66559
- entries = readdirSync4(searchDir);
66695
+ entries = readdirSync5(searchDir);
66560
66696
  } catch {
66561
66697
  return [];
66562
66698
  }
66563
66699
  const matchingEntries = searchPattern.length === 0 ? entries : entries.filter((entry) => entry.toLowerCase().includes(searchPattern.toLowerCase()));
66564
66700
  for (const entry of matchingEntries.slice(0, 50)) {
66565
66701
  try {
66566
- const fullPath = join19(searchDir, entry);
66567
- const stats = statSync3(fullPath);
66702
+ const fullPath = join20(searchDir, entry);
66703
+ const stats = statSync4(fullPath);
66568
66704
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
66569
66705
  results.push({
66570
66706
  path: relativePath,
@@ -70679,7 +70815,7 @@ var init_PendingApprovalStub = __esm(async () => {
70679
70815
  });
70680
70816
 
70681
70817
  // src/cli/components/ReasoningMessageRich.tsx
70682
- var import_react73, jsx_dev_runtime49, normalize5 = (s) => s.replace(/\r\n/g, `
70818
+ var import_react73, jsx_dev_runtime49, normalize6 = (s) => s.replace(/\r\n/g, `
70683
70819
  `).replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, `
70684
70820
 
70685
70821
  `).replace(/^\n+|\n+$/g, ""), ReasoningMessage;
@@ -70694,7 +70830,7 @@ var init_ReasoningMessageRich = __esm(async () => {
70694
70830
  ReasoningMessage = import_react73.memo(({ line }) => {
70695
70831
  const columns = useTerminalWidth();
70696
70832
  const contentWidth = Math.max(0, columns - 2);
70697
- const normalizedText = normalize5(line.text);
70833
+ const normalizedText = normalize6(line.text);
70698
70834
  return /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(Box_default, {
70699
70835
  flexDirection: "column",
70700
70836
  children: [
@@ -71654,8 +71790,8 @@ function MemoryDiffRenderer({
71654
71790
  }, undefined, false, undefined, this);
71655
71791
  }
71656
71792
  const command = args.command;
71657
- const path20 = args.path || args.old_path || "unknown";
71658
- const blockName = path20.split("/").pop() || path20;
71793
+ const path21 = args.path || args.old_path || "unknown";
71794
+ const blockName = path21.split("/").pop() || path21;
71659
71795
  switch (command) {
71660
71796
  case "str_replace": {
71661
71797
  const oldStr = args.old_string || args.old_str || "";
@@ -74198,9 +74334,9 @@ async function getLettaConfig2() {
74198
74334
  const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY || "";
74199
74335
  return { baseUrl, apiKey };
74200
74336
  }
74201
- async function providersRequest2(method, path20, body) {
74337
+ async function providersRequest2(method, path21, body) {
74202
74338
  const { baseUrl, apiKey } = await getLettaConfig2();
74203
- const url = `${baseUrl}${path20}`;
74339
+ const url = `${baseUrl}${path21}`;
74204
74340
  const response = await fetch(url, {
74205
74341
  method,
74206
74342
  headers: {
@@ -74731,9 +74867,9 @@ var exports_App = {};
74731
74867
  __export(exports_App, {
74732
74868
  default: () => App2
74733
74869
  });
74734
- import { existsSync as existsSync12, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
74735
- import { homedir as homedir11 } from "node:os";
74736
- import { join as join20 } from "node:path";
74870
+ import { existsSync as existsSync13, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
74871
+ import { homedir as homedir12 } from "node:os";
74872
+ import { join as join21 } from "node:path";
74737
74873
  function uid4(prefix) {
74738
74874
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
74739
74875
  }
@@ -74845,7 +74981,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
74845
74981
  }
74846
74982
  function planFileExists() {
74847
74983
  const planFilePath = permissionMode.getPlanFilePath();
74848
- return !!planFilePath && existsSync12(planFilePath);
74984
+ return !!planFilePath && existsSync13(planFilePath);
74849
74985
  }
74850
74986
  function getQuestionsFromApproval(approval) {
74851
74987
  const parsed = safeJsonParseOr(approval.toolArgs, {});
@@ -75003,6 +75139,19 @@ function App2({
75003
75139
  const [autoDeniedApprovals, setAutoDeniedApprovals] = import_react84.useState([]);
75004
75140
  const executingToolCallIdsRef = import_react84.useRef([]);
75005
75141
  const interruptQueuedRef = import_react84.useRef(false);
75142
+ const autoAllowedExecutionRef = import_react84.useRef(null);
75143
+ const queuedApprovalMetadataRef = import_react84.useRef(null);
75144
+ const queueApprovalResults = import_react84.useCallback((results, metadata) => {
75145
+ setQueuedApprovalResults(results);
75146
+ if (results) {
75147
+ queuedApprovalMetadataRef.current = metadata ?? {
75148
+ conversationId: conversationIdRef.current,
75149
+ generation: conversationGenerationRef.current
75150
+ };
75151
+ } else {
75152
+ queuedApprovalMetadataRef.current = null;
75153
+ }
75154
+ }, []);
75006
75155
  const bashCommandCacheRef = import_react84.useRef([]);
75007
75156
  const [pendingRalphConfig, setPendingRalphConfig] = import_react84.useState(null);
75008
75157
  const [uiRalphActive, setUiRalphActive] = import_react84.useState(ralphMode.getState().isActive);
@@ -75363,8 +75512,8 @@ function App2({
75363
75512
  if (!planFilePath)
75364
75513
  return;
75365
75514
  try {
75366
- const { readFileSync: readFileSync5, existsSync: existsSync13 } = __require("node:fs");
75367
- if (!existsSync13(planFilePath))
75515
+ const { readFileSync: readFileSync5, existsSync: existsSync14 } = __require("node:fs");
75516
+ if (!existsSync14(planFilePath))
75368
75517
  return;
75369
75518
  const planContent = readFileSync5(planFilePath, "utf-8");
75370
75519
  const previewItem = {
@@ -75794,7 +75943,7 @@ ${newState.originalPrompt}`
75794
75943
  });
75795
75944
  }
75796
75945
  refreshDerived();
75797
- setQueuedApprovalResults(denialResults);
75946
+ queueApprovalResults(denialResults);
75798
75947
  const concatenatedMessage = queueSnapshotRef.current.join(`
75799
75948
  `);
75800
75949
  setMessageQueue([]);
@@ -75902,36 +76051,48 @@ ${newState.originalPrompt}`
75902
76051
  }
75903
76052
  } catch {}
75904
76053
  }
75905
- setToolCallsRunning(buffersRef.current, autoAllowed.map((ac) => ac.approval.toolCallId));
75906
- refreshDerived();
75907
- const autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), {
75908
- abortSignal: signal,
75909
- onStreamingOutput: updateStreamingOutput
75910
- });
75911
- const autoDeniedResults = autoDenied.map((ac) => {
75912
- const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown reason";
75913
- onChunk(buffersRef.current, {
75914
- message_type: "tool_return_message",
75915
- id: "dummy",
75916
- date: new Date().toISOString(),
75917
- tool_call_id: ac.approval.toolCallId,
75918
- tool_return: `Error: request to call tool denied. User reason: ${reason}`,
75919
- status: "error",
75920
- stdout: null,
75921
- stderr: null
75922
- });
75923
- return {
75924
- approval: ac.approval,
75925
- reason
76054
+ const autoAllowedToolCallIds = autoAllowed.map((ac) => ac.approval.toolCallId);
76055
+ const autoAllowedAbortController = abortControllerRef.current ?? new AbortController;
76056
+ const shouldTrackAutoAllowed = autoAllowedToolCallIds.length > 0;
76057
+ let autoAllowedResults = [];
76058
+ let autoDeniedResults = [];
76059
+ if (shouldTrackAutoAllowed) {
76060
+ setIsExecutingTool(true);
76061
+ executingToolCallIdsRef.current = autoAllowedToolCallIds;
76062
+ toolAbortControllerRef.current = autoAllowedAbortController;
76063
+ autoAllowedExecutionRef.current = {
76064
+ toolCallIds: autoAllowedToolCallIds,
76065
+ results: null,
76066
+ conversationId: conversationIdRef.current,
76067
+ generation: conversationGenerationRef.current
75926
76068
  };
75927
- });
75928
- if (needsUserInput.length === 0) {
75929
- if (userCancelledRef.current || abortControllerRef.current?.signal.aborted) {
75930
- setStreaming(false);
75931
- markIncompleteToolsAsCancelled(buffersRef.current);
76069
+ }
76070
+ try {
76071
+ if (autoAllowedToolCallIds.length > 0) {
76072
+ setToolCallsRunning(buffersRef.current, autoAllowedToolCallIds);
75932
76073
  refreshDerived();
75933
- return;
75934
76074
  }
76075
+ autoAllowedResults = autoAllowed.length > 0 ? await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), {
76076
+ abortSignal: autoAllowedAbortController.signal,
76077
+ onStreamingOutput: updateStreamingOutput
76078
+ }) : [];
76079
+ autoDeniedResults = autoDenied.map((ac) => {
76080
+ const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown reason";
76081
+ onChunk(buffersRef.current, {
76082
+ message_type: "tool_return_message",
76083
+ id: "dummy",
76084
+ date: new Date().toISOString(),
76085
+ tool_call_id: ac.approval.toolCallId,
76086
+ tool_return: `Error: request to call tool denied. User reason: ${reason}`,
76087
+ status: "error",
76088
+ stdout: null,
76089
+ stderr: null
76090
+ });
76091
+ return {
76092
+ approval: ac.approval,
76093
+ reason
76094
+ };
76095
+ });
75935
76096
  const allResults = [
75936
76097
  ...autoAllowedResults.map((ar) => ({
75937
76098
  type: "tool",
@@ -75948,11 +76109,77 @@ ${newState.originalPrompt}`
75948
76109
  reason: ad.reason
75949
76110
  }))
75950
76111
  ];
76112
+ if (autoAllowedExecutionRef.current) {
76113
+ autoAllowedExecutionRef.current.results = allResults;
76114
+ }
76115
+ const autoAllowedMetadata = autoAllowedExecutionRef.current ? {
76116
+ conversationId: autoAllowedExecutionRef.current.conversationId,
76117
+ generation: conversationGenerationRef.current
76118
+ } : undefined;
76119
+ if (needsUserInput.length === 0) {
76120
+ if (userCancelledRef.current || abortControllerRef.current?.signal.aborted || interruptQueuedRef.current) {
76121
+ if (allResults.length > 0) {
76122
+ queueApprovalResults(allResults, autoAllowedMetadata);
76123
+ }
76124
+ setStreaming(false);
76125
+ markIncompleteToolsAsCancelled(buffersRef.current);
76126
+ refreshDerived();
76127
+ return;
76128
+ }
76129
+ if (waitingForQueueCancelRef.current) {
76130
+ if (restoreQueueOnCancelRef.current) {
76131
+ setRestoreQueueOnCancel(false);
76132
+ } else {
76133
+ if (allResults.length > 0) {
76134
+ queueApprovalResults(allResults, autoAllowedMetadata);
76135
+ }
76136
+ const concatenatedMessage = queueSnapshotRef.current.join(`
76137
+ `);
76138
+ setMessageQueue([]);
76139
+ if (concatenatedMessage.trim()) {
76140
+ onSubmitRef.current(concatenatedMessage);
76141
+ }
76142
+ }
76143
+ waitingForQueueCancelRef.current = false;
76144
+ queueSnapshotRef.current = [];
76145
+ setStreaming(false);
76146
+ return;
76147
+ }
76148
+ setThinkingMessage(getRandomThinkingVerb());
76149
+ refreshDerived();
76150
+ await processConversation([
76151
+ {
76152
+ type: "approval",
76153
+ approvals: allResults
76154
+ }
76155
+ ], { allowReentry: true });
76156
+ return;
76157
+ }
75951
76158
  if (waitingForQueueCancelRef.current) {
75952
76159
  if (restoreQueueOnCancelRef.current) {
75953
76160
  setRestoreQueueOnCancel(false);
75954
76161
  } else {
75955
- setQueuedApprovalResults(allResults);
76162
+ const denialResults = needsUserInput.map((ac) => ({
76163
+ type: "approval",
76164
+ tool_call_id: ac.approval.toolCallId,
76165
+ approve: false,
76166
+ reason: "User cancelled - new message queued"
76167
+ }));
76168
+ for (const ac of needsUserInput) {
76169
+ onChunk(buffersRef.current, {
76170
+ message_type: "tool_return_message",
76171
+ id: "dummy",
76172
+ date: new Date().toISOString(),
76173
+ tool_call_id: ac.approval.toolCallId,
76174
+ tool_return: "Cancelled - user sent new message",
76175
+ status: "error"
76176
+ });
76177
+ }
76178
+ refreshDerived();
76179
+ const queuedResults = [...allResults, ...denialResults];
76180
+ if (queuedResults.length > 0) {
76181
+ queueApprovalResults(queuedResults, autoAllowedMetadata);
76182
+ }
75956
76183
  const concatenatedMessage = queueSnapshotRef.current.join(`
75957
76184
  `);
75958
76185
  setMessageQueue([]);
@@ -75965,64 +76192,13 @@ ${newState.originalPrompt}`
75965
76192
  setStreaming(false);
75966
76193
  return;
75967
76194
  }
75968
- setThinkingMessage(getRandomThinkingVerb());
75969
- refreshDerived();
75970
- await processConversation([
75971
- {
75972
- type: "approval",
75973
- approvals: allResults
75974
- }
75975
- ], { allowReentry: true });
75976
- return;
75977
- }
75978
- if (waitingForQueueCancelRef.current) {
75979
- if (restoreQueueOnCancelRef.current) {
75980
- setRestoreQueueOnCancel(false);
75981
- } else {
75982
- const denialResults = needsUserInput.map((ac) => ({
75983
- type: "approval",
75984
- tool_call_id: ac.approval.toolCallId,
75985
- approve: false,
75986
- reason: "User cancelled - new message queued"
75987
- }));
75988
- for (const ac of needsUserInput) {
75989
- onChunk(buffersRef.current, {
75990
- message_type: "tool_return_message",
75991
- id: "dummy",
75992
- date: new Date().toISOString(),
75993
- tool_call_id: ac.approval.toolCallId,
75994
- tool_return: "Cancelled - user sent new message",
75995
- status: "error"
75996
- });
75997
- }
75998
- refreshDerived();
75999
- const allResults = [
76000
- ...autoAllowedResults.map((ar) => ({
76001
- type: "tool",
76002
- tool_call_id: ar.toolCallId,
76003
- tool_return: ar.result.toolReturn,
76004
- status: ar.result.status
76005
- })),
76006
- ...autoDeniedResults.map((ad) => ({
76007
- type: "approval",
76008
- tool_call_id: ad.approval.toolCallId,
76009
- approve: false,
76010
- reason: ad.reason
76011
- })),
76012
- ...denialResults
76013
- ];
76014
- setQueuedApprovalResults(allResults);
76015
- const concatenatedMessage = queueSnapshotRef.current.join(`
76016
- `);
76017
- setMessageQueue([]);
76018
- if (concatenatedMessage.trim()) {
76019
- onSubmitRef.current(concatenatedMessage);
76020
- }
76195
+ } finally {
76196
+ if (shouldTrackAutoAllowed) {
76197
+ setIsExecutingTool(false);
76198
+ toolAbortControllerRef.current = null;
76199
+ executingToolCallIdsRef.current = [];
76200
+ autoAllowedExecutionRef.current = null;
76021
76201
  }
76022
- waitingForQueueCancelRef.current = false;
76023
- queueSnapshotRef.current = [];
76024
- setStreaming(false);
76025
- return;
76026
76202
  }
76027
76203
  if (userCancelledRef.current || abortControllerRef.current?.signal.aborted) {
76028
76204
  setStreaming(false);
@@ -76094,33 +76270,11 @@ ${newState.originalPrompt}`
76094
76270
  const approvalPendingDetected = isApprovalPendingError(detailFromRun) || isApprovalPendingError(latestErrorText);
76095
76271
  if (!hasApprovalInPayload && approvalPendingDetected && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES2) {
76096
76272
  llmApiErrorRetriesRef.current += 1;
76097
- const statusId = uid4("status");
76098
- buffersRef.current.byId.set(statusId, {
76099
- kind: "status",
76100
- id: statusId,
76101
- lines: [
76102
- "[LAZY RECOVERY] Detected CONFLICT: server has pending approval",
76103
- "[LAZY RECOVERY] Fetching stale approvals to auto-deny..."
76104
- ]
76105
- });
76106
- buffersRef.current.order.push(statusId);
76107
- refreshDerived();
76108
76273
  try {
76109
76274
  const client = await getClient2();
76110
76275
  const agent = await client.agents.retrieve(agentIdRef.current);
76111
76276
  const { pendingApprovals: existingApprovals } = await getResumeData2(client, agent, conversationIdRef.current);
76112
76277
  if (existingApprovals && existingApprovals.length > 0) {
76113
- buffersRef.current.byId.set(statusId, {
76114
- kind: "status",
76115
- id: statusId,
76116
- lines: [
76117
- "[LAZY RECOVERY] Detected CONFLICT: server has pending approval",
76118
- `[LAZY RECOVERY] Found ${existingApprovals.length} stale approval(s):`,
76119
- ...existingApprovals.map((a) => ` - ${a.toolName} (${a.toolCallId.slice(0, 8)}...)`),
76120
- "[LAZY RECOVERY] Auto-denying and batching with user message..."
76121
- ]
76122
- });
76123
- refreshDerived();
76124
76278
  const denialResults = existingApprovals.map((approval2) => ({
76125
76279
  type: "approval",
76126
76280
  tool_call_id: approval2.toolCallId,
@@ -76132,32 +76286,8 @@ ${newState.originalPrompt}`
76132
76286
  approvals: denialResults
76133
76287
  };
76134
76288
  currentInput.unshift(approvalPayload);
76135
- } else {
76136
- buffersRef.current.byId.set(statusId, {
76137
- kind: "status",
76138
- id: statusId,
76139
- lines: [
76140
- "[LAZY RECOVERY] Detected CONFLICT but no pending approvals found",
76141
- "[LAZY RECOVERY] Retrying message..."
76142
- ]
76143
- });
76144
- refreshDerived();
76145
76289
  }
76146
- } catch (_recoveryError) {
76147
- buffersRef.current.byId.set(statusId, {
76148
- kind: "status",
76149
- id: statusId,
76150
- lines: [
76151
- "[LAZY RECOVERY] Failed to fetch pending approvals",
76152
- "[LAZY RECOVERY] Retrying message anyway..."
76153
- ]
76154
- });
76155
- refreshDerived();
76156
- }
76157
- await new Promise((resolve20) => setTimeout(resolve20, 500));
76158
- buffersRef.current.byId.delete(statusId);
76159
- buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
76160
- refreshDerived();
76290
+ } catch {}
76161
76291
  buffersRef.current.interrupted = false;
76162
76292
  continue;
76163
76293
  }
@@ -76276,7 +76406,8 @@ ${newState.originalPrompt}`
76276
76406
  setStreaming,
76277
76407
  currentModelId,
76278
76408
  updateStreamingOutput,
76279
- needsEagerApprovalCheck
76409
+ needsEagerApprovalCheck,
76410
+ queueApprovalResults
76280
76411
  ]);
76281
76412
  const handleExit = import_react84.useCallback(async () => {
76282
76413
  saveLastAgentBeforeExit();
@@ -76294,17 +76425,28 @@ ${newState.originalPrompt}`
76294
76425
  const handleInterrupt = import_react84.useCallback(async () => {
76295
76426
  if (isExecutingTool && toolAbortControllerRef.current) {
76296
76427
  toolAbortControllerRef.current.abort();
76297
- if (executingToolCallIdsRef.current.length > 0) {
76428
+ conversationGenerationRef.current += 1;
76429
+ processingConversationRef.current = 0;
76430
+ const autoAllowedResults = autoAllowedExecutionRef.current?.results;
76431
+ const autoAllowedMetadata = autoAllowedExecutionRef.current ? {
76432
+ conversationId: autoAllowedExecutionRef.current.conversationId,
76433
+ generation: conversationGenerationRef.current
76434
+ } : undefined;
76435
+ if (autoAllowedResults && autoAllowedResults.length > 0) {
76436
+ queueApprovalResults(autoAllowedResults, autoAllowedMetadata);
76437
+ interruptQueuedRef.current = true;
76438
+ } else if (executingToolCallIdsRef.current.length > 0) {
76298
76439
  const interruptedResults = executingToolCallIdsRef.current.map((toolCallId) => ({
76299
76440
  type: "tool",
76300
76441
  tool_call_id: toolCallId,
76301
76442
  tool_return: INTERRUPTED_BY_USER,
76302
76443
  status: "error"
76303
76444
  }));
76304
- setQueuedApprovalResults(interruptedResults);
76305
- executingToolCallIdsRef.current = [];
76445
+ queueApprovalResults(interruptedResults);
76306
76446
  interruptQueuedRef.current = true;
76307
76447
  }
76448
+ executingToolCallIdsRef.current = [];
76449
+ autoAllowedExecutionRef.current = null;
76308
76450
  buffersRef.current.abortGeneration = (buffersRef.current.abortGeneration || 0) + 1;
76309
76451
  const toolsCancelled = markIncompleteToolsAsCancelled(buffersRef.current);
76310
76452
  interruptActiveSubagents(INTERRUPTED_BY_USER);
@@ -76347,14 +76489,33 @@ ${newState.originalPrompt}`
76347
76489
  appendError(INTERRUPT_MESSAGE, true);
76348
76490
  }
76349
76491
  refreshDerived();
76350
- if (pendingApprovals.length > 0) {
76351
- const denialResults = pendingApprovals.map((approval) => ({
76492
+ const denialResults = pendingApprovals.map((approval) => ({
76493
+ type: "approval",
76494
+ tool_call_id: approval.toolCallId,
76495
+ approve: false,
76496
+ reason: "User interrupted the stream"
76497
+ }));
76498
+ const autoHandledSnapshot = [...autoHandledResults];
76499
+ const autoDeniedSnapshot = [...autoDeniedApprovals];
76500
+ const queuedResults = [
76501
+ ...autoHandledSnapshot.map((ar) => ({
76502
+ type: "tool",
76503
+ tool_call_id: ar.toolCallId,
76504
+ tool_return: ar.result.toolReturn,
76505
+ status: ar.result.status,
76506
+ stdout: ar.result.stdout,
76507
+ stderr: ar.result.stderr
76508
+ })),
76509
+ ...autoDeniedSnapshot.map((ad) => ({
76352
76510
  type: "approval",
76353
- tool_call_id: approval.toolCallId,
76511
+ tool_call_id: ad.approval.toolCallId,
76354
76512
  approve: false,
76355
- reason: "User interrupted the stream"
76356
- }));
76357
- setQueuedApprovalResults(denialResults);
76513
+ reason: ad.reason
76514
+ })),
76515
+ ...denialResults
76516
+ ];
76517
+ if (queuedResults.length > 0) {
76518
+ queueApprovalResults(queuedResults);
76358
76519
  }
76359
76520
  setPendingApprovals([]);
76360
76521
  setApprovalContexts([]);
@@ -76389,7 +76550,10 @@ ${newState.originalPrompt}`
76389
76550
  isExecutingTool,
76390
76551
  refreshDerived,
76391
76552
  setStreaming,
76392
- pendingApprovals
76553
+ pendingApprovals,
76554
+ autoHandledResults,
76555
+ autoDeniedApprovals,
76556
+ queueApprovalResults
76393
76557
  ]);
76394
76558
  const processConversationRef = import_react84.useRef(processConversation);
76395
76559
  import_react84.useEffect(() => {
@@ -76671,42 +76835,82 @@ ${newState.originalPrompt}`
76671
76835
  return { blocked: true };
76672
76836
  }
76673
76837
  const allResults = [];
76674
- if (autoAllowed.length > 0) {
76675
- setToolCallsRunning(buffersRef.current, autoAllowed.map((ac) => ac.approval.toolCallId));
76676
- refreshDerived();
76677
- const autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), { onStreamingOutput: updateStreamingOutput });
76678
- allResults.push(...autoAllowedResults.map((ar) => ({
76679
- type: "tool",
76680
- tool_call_id: ar.toolCallId,
76681
- tool_return: ar.result.toolReturn,
76682
- status: ar.result.status,
76683
- stdout: ar.result.stdout,
76684
- stderr: ar.result.stderr
76685
- })));
76686
- }
76687
- for (const ac of autoDenied) {
76688
- const reason = ac.permission.reason || "Permission denied";
76689
- onChunk(buffersRef.current, {
76690
- message_type: "tool_return_message",
76691
- id: "dummy",
76692
- date: new Date().toISOString(),
76693
- tool_call_id: ac.approval.toolCallId,
76694
- tool_return: `Error: request to call tool denied. User reason: ${reason}`,
76695
- status: "error",
76696
- stdout: null,
76697
- stderr: null
76698
- });
76699
- allResults.push({
76700
- type: "approval",
76701
- tool_call_id: ac.approval.toolCallId,
76702
- approve: false,
76703
- reason
76704
- });
76838
+ const autoAllowedToolCallIds = autoAllowed.map((ac) => ac.approval.toolCallId);
76839
+ const autoAllowedAbortController = abortControllerRef.current ?? new AbortController;
76840
+ const shouldTrackAutoAllowed = autoAllowedToolCallIds.length > 0;
76841
+ let autoAllowedResults = [];
76842
+ if (shouldTrackAutoAllowed) {
76843
+ setIsExecutingTool(true);
76844
+ executingToolCallIdsRef.current = autoAllowedToolCallIds;
76845
+ toolAbortControllerRef.current = autoAllowedAbortController;
76846
+ autoAllowedExecutionRef.current = {
76847
+ toolCallIds: autoAllowedToolCallIds,
76848
+ results: null,
76849
+ conversationId: conversationIdRef.current,
76850
+ generation: conversationGenerationRef.current
76851
+ };
76705
76852
  }
76706
- if (allResults.length > 0) {
76707
- await processConversation([
76708
- { type: "approval", approvals: allResults }
76709
- ]);
76853
+ try {
76854
+ if (autoAllowed.length > 0) {
76855
+ setToolCallsRunning(buffersRef.current, autoAllowedToolCallIds);
76856
+ refreshDerived();
76857
+ autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), {
76858
+ abortSignal: autoAllowedAbortController.signal,
76859
+ onStreamingOutput: updateStreamingOutput
76860
+ });
76861
+ allResults.push(...autoAllowedResults.map((ar) => ({
76862
+ type: "tool",
76863
+ tool_call_id: ar.toolCallId,
76864
+ tool_return: ar.result.toolReturn,
76865
+ status: ar.result.status,
76866
+ stdout: ar.result.stdout,
76867
+ stderr: ar.result.stderr
76868
+ })));
76869
+ }
76870
+ for (const ac of autoDenied) {
76871
+ const reason = ac.permission.reason || "Permission denied";
76872
+ onChunk(buffersRef.current, {
76873
+ message_type: "tool_return_message",
76874
+ id: "dummy",
76875
+ date: new Date().toISOString(),
76876
+ tool_call_id: ac.approval.toolCallId,
76877
+ tool_return: `Error: request to call tool denied. User reason: ${reason}`,
76878
+ status: "error",
76879
+ stdout: null,
76880
+ stderr: null
76881
+ });
76882
+ allResults.push({
76883
+ type: "approval",
76884
+ tool_call_id: ac.approval.toolCallId,
76885
+ approve: false,
76886
+ reason
76887
+ });
76888
+ }
76889
+ if (autoAllowedExecutionRef.current) {
76890
+ autoAllowedExecutionRef.current.results = allResults;
76891
+ }
76892
+ const autoAllowedMetadata = autoAllowedExecutionRef.current ? {
76893
+ conversationId: autoAllowedExecutionRef.current.conversationId,
76894
+ generation: conversationGenerationRef.current
76895
+ } : undefined;
76896
+ if (userCancelledRef.current || autoAllowedAbortController.signal.aborted || interruptQueuedRef.current) {
76897
+ if (allResults.length > 0) {
76898
+ queueApprovalResults(allResults, autoAllowedMetadata);
76899
+ }
76900
+ return { blocked: false };
76901
+ }
76902
+ if (allResults.length > 0) {
76903
+ await processConversation([
76904
+ { type: "approval", approvals: allResults }
76905
+ ]);
76906
+ }
76907
+ } finally {
76908
+ if (shouldTrackAutoAllowed) {
76909
+ setIsExecutingTool(false);
76910
+ toolAbortControllerRef.current = null;
76911
+ executingToolCallIdsRef.current = [];
76912
+ autoAllowedExecutionRef.current = null;
76913
+ }
76710
76914
  }
76711
76915
  return { blocked: false };
76712
76916
  } catch {
@@ -76717,7 +76921,8 @@ ${newState.originalPrompt}`
76717
76921
  processConversation,
76718
76922
  refreshDerived,
76719
76923
  updateStreamingOutput,
76720
- needsEagerApprovalCheck
76924
+ needsEagerApprovalCheck,
76925
+ queueApprovalResults
76721
76926
  ]);
76722
76927
  const onSubmit = import_react84.useCallback(async (message) => {
76723
76928
  const msg = message?.trim() ?? "";
@@ -77687,7 +77892,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
77687
77892
  const client = await getClient2();
77688
77893
  const fileContent = await client.agents.exportFile(agentId);
77689
77894
  const fileName = `${agentId}.af`;
77690
- writeFileSync3(fileName, JSON.stringify(fileContent, null, 2));
77895
+ writeFileSync4(fileName, JSON.stringify(fileContent, null, 2));
77691
77896
  buffersRef.current.byId.set(cmdId2, {
77692
77897
  kind: "command",
77693
77898
  id: cmdId2,
@@ -78267,52 +78472,109 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78267
78472
  }
78268
78473
  } catch {}
78269
78474
  }
78270
- setToolCallsRunning(buffersRef.current, autoAllowed.map((ac) => ac.approval.toolCallId));
78271
- refreshDerived();
78272
- const autoAllowedResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), { onStreamingOutput: updateStreamingOutput });
78273
- const autoDeniedResults = autoDenied.map((ac) => {
78274
- const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown";
78275
- onChunk(buffersRef.current, {
78276
- message_type: "tool_return_message",
78277
- id: "dummy",
78278
- date: new Date().toISOString(),
78279
- tool_call_id: ac.approval.toolCallId,
78280
- tool_return: `Error: request to call tool denied. User reason: ${reason}`,
78281
- status: "error",
78282
- stdout: null,
78283
- stderr: null
78284
- });
78285
- return {
78286
- type: "approval",
78287
- tool_call_id: ac.approval.toolCallId,
78288
- approve: false,
78289
- reason
78475
+ const autoAllowedToolCallIds = autoAllowed.map((ac) => ac.approval.toolCallId);
78476
+ const autoAllowedAbortController = abortControllerRef.current ?? new AbortController;
78477
+ const shouldTrackAutoAllowed = autoAllowedToolCallIds.length > 0;
78478
+ let autoAllowedResults = [];
78479
+ let autoDeniedResults = [];
78480
+ if (shouldTrackAutoAllowed) {
78481
+ setIsExecutingTool(true);
78482
+ executingToolCallIdsRef.current = autoAllowedToolCallIds;
78483
+ toolAbortControllerRef.current = autoAllowedAbortController;
78484
+ autoAllowedExecutionRef.current = {
78485
+ toolCallIds: autoAllowedToolCallIds,
78486
+ results: null,
78487
+ conversationId: conversationIdRef.current,
78488
+ generation: conversationGenerationRef.current
78290
78489
  };
78291
- });
78292
- refreshDerived();
78293
- const recoveryApprovalResults = [
78294
- ...autoAllowedResults.map((ar) => ({
78295
- type: "approval",
78296
- tool_call_id: ar.toolCallId,
78297
- approve: true,
78298
- tool_return: ar.result.toolReturn
78299
- })),
78300
- ...autoDeniedResults
78301
- ];
78302
- const initialInput2 = [
78303
- {
78304
- type: "approval",
78305
- approvals: recoveryApprovalResults
78306
- },
78307
- {
78308
- type: "message",
78309
- role: "user",
78310
- content: messageContent
78490
+ }
78491
+ try {
78492
+ if (autoAllowedToolCallIds.length > 0) {
78493
+ setToolCallsRunning(buffersRef.current, autoAllowedToolCallIds);
78494
+ refreshDerived();
78311
78495
  }
78312
- ];
78313
- await processConversation(initialInput2);
78314
- clearPlaceholdersInText(msg);
78315
- return { submitted: true };
78496
+ autoAllowedResults = autoAllowed.length > 0 ? await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), {
78497
+ abortSignal: autoAllowedAbortController.signal,
78498
+ onStreamingOutput: updateStreamingOutput
78499
+ }) : [];
78500
+ autoDeniedResults = autoDenied.map((ac) => {
78501
+ const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown";
78502
+ onChunk(buffersRef.current, {
78503
+ message_type: "tool_return_message",
78504
+ id: "dummy",
78505
+ date: new Date().toISOString(),
78506
+ tool_call_id: ac.approval.toolCallId,
78507
+ tool_return: `Error: request to call tool denied. User reason: ${reason}`,
78508
+ status: "error",
78509
+ stdout: null,
78510
+ stderr: null
78511
+ });
78512
+ return {
78513
+ type: "approval",
78514
+ tool_call_id: ac.approval.toolCallId,
78515
+ approve: false,
78516
+ reason
78517
+ };
78518
+ });
78519
+ const queuedResults = [
78520
+ ...autoAllowedResults.map((ar) => ({
78521
+ type: "tool",
78522
+ tool_call_id: ar.toolCallId,
78523
+ tool_return: ar.result.toolReturn,
78524
+ status: ar.result.status,
78525
+ stdout: ar.result.stdout,
78526
+ stderr: ar.result.stderr
78527
+ })),
78528
+ ...autoDeniedResults
78529
+ ];
78530
+ if (autoAllowedExecutionRef.current) {
78531
+ autoAllowedExecutionRef.current.results = queuedResults;
78532
+ }
78533
+ const autoAllowedMetadata = autoAllowedExecutionRef.current ? {
78534
+ conversationId: autoAllowedExecutionRef.current.conversationId,
78535
+ generation: conversationGenerationRef.current
78536
+ } : undefined;
78537
+ if (userCancelledRef.current || autoAllowedAbortController.signal.aborted || interruptQueuedRef.current) {
78538
+ if (queuedResults.length > 0) {
78539
+ queueApprovalResults(queuedResults, autoAllowedMetadata);
78540
+ }
78541
+ setStreaming(false);
78542
+ markIncompleteToolsAsCancelled(buffersRef.current);
78543
+ refreshDerived();
78544
+ return { submitted: false };
78545
+ }
78546
+ refreshDerived();
78547
+ const recoveryApprovalResults = [
78548
+ ...autoAllowedResults.map((ar) => ({
78549
+ type: "approval",
78550
+ tool_call_id: ar.toolCallId,
78551
+ approve: true,
78552
+ tool_return: ar.result.toolReturn
78553
+ })),
78554
+ ...autoDeniedResults
78555
+ ];
78556
+ const initialInput2 = [
78557
+ {
78558
+ type: "approval",
78559
+ approvals: recoveryApprovalResults
78560
+ },
78561
+ {
78562
+ type: "message",
78563
+ role: "user",
78564
+ content: messageContent
78565
+ }
78566
+ ];
78567
+ await processConversation(initialInput2);
78568
+ clearPlaceholdersInText(msg);
78569
+ return { submitted: true };
78570
+ } finally {
78571
+ if (shouldTrackAutoAllowed) {
78572
+ setIsExecutingTool(false);
78573
+ toolAbortControllerRef.current = null;
78574
+ executingToolCallIdsRef.current = [];
78575
+ autoAllowedExecutionRef.current = null;
78576
+ }
78577
+ }
78316
78578
  } else {
78317
78579
  buffersRef.current.byId.delete(userId);
78318
78580
  const orderIndex = buffersRef.current.order.indexOf(userId);
@@ -78378,39 +78640,105 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78378
78640
  }
78379
78641
  } catch {}
78380
78642
  }
78381
- const autoAllowedWithResults = await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), { onStreamingOutput: updateStreamingOutput });
78382
- const autoDeniedWithReasons = autoDenied.map((ac) => {
78383
- const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown";
78384
- onChunk(buffersRef.current, {
78385
- message_type: "tool_return_message",
78386
- id: "dummy",
78387
- date: new Date().toISOString(),
78388
- tool_call_id: ac.approval.toolCallId,
78389
- tool_return: `Error: request to call tool denied. User reason: ${reason}`,
78390
- status: "error",
78391
- stdout: null,
78392
- stderr: null
78393
- });
78394
- return {
78395
- approval: ac.approval,
78396
- reason
78643
+ const autoAllowedToolCallIds = autoAllowed.map((ac) => ac.approval.toolCallId);
78644
+ const autoAllowedAbortController = abortControllerRef.current ?? new AbortController;
78645
+ const shouldTrackAutoAllowed = autoAllowedToolCallIds.length > 0;
78646
+ let autoAllowedWithResults = [];
78647
+ let autoDeniedWithReasons = [];
78648
+ if (shouldTrackAutoAllowed) {
78649
+ setIsExecutingTool(true);
78650
+ executingToolCallIdsRef.current = autoAllowedToolCallIds;
78651
+ toolAbortControllerRef.current = autoAllowedAbortController;
78652
+ autoAllowedExecutionRef.current = {
78653
+ toolCallIds: autoAllowedToolCallIds,
78654
+ results: null,
78655
+ conversationId: conversationIdRef.current,
78656
+ generation: conversationGenerationRef.current
78397
78657
  };
78398
- });
78399
- setAutoHandledResults(autoAllowedWithResults);
78400
- setAutoDeniedApprovals(autoDeniedWithReasons);
78401
- refreshDerived();
78402
- return { submitted: false };
78658
+ }
78659
+ try {
78660
+ autoAllowedWithResults = autoAllowed.length > 0 ? await executeAutoAllowedTools(autoAllowed, (chunk) => onChunk(buffersRef.current, chunk), {
78661
+ abortSignal: autoAllowedAbortController.signal,
78662
+ onStreamingOutput: updateStreamingOutput
78663
+ }) : [];
78664
+ autoDeniedWithReasons = autoDenied.map((ac) => {
78665
+ const reason = ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : ("matchedRule" in ac.permission) && ac.permission.matchedRule ? `Permission denied by rule: ${ac.permission.matchedRule}` : "Permission denied: Unknown";
78666
+ onChunk(buffersRef.current, {
78667
+ message_type: "tool_return_message",
78668
+ id: "dummy",
78669
+ date: new Date().toISOString(),
78670
+ tool_call_id: ac.approval.toolCallId,
78671
+ tool_return: `Error: request to call tool denied. User reason: ${reason}`,
78672
+ status: "error",
78673
+ stdout: null,
78674
+ stderr: null
78675
+ });
78676
+ return {
78677
+ approval: ac.approval,
78678
+ reason
78679
+ };
78680
+ });
78681
+ const queuedResults = [
78682
+ ...autoAllowedWithResults.map((ar) => ({
78683
+ type: "tool",
78684
+ tool_call_id: ar.toolCallId,
78685
+ tool_return: ar.result.toolReturn,
78686
+ status: ar.result.status,
78687
+ stdout: ar.result.stdout,
78688
+ stderr: ar.result.stderr
78689
+ })),
78690
+ ...autoDeniedWithReasons.map((ad) => ({
78691
+ type: "approval",
78692
+ tool_call_id: ad.approval.toolCallId,
78693
+ approve: false,
78694
+ reason: ad.reason
78695
+ }))
78696
+ ];
78697
+ if (autoAllowedExecutionRef.current) {
78698
+ autoAllowedExecutionRef.current.results = queuedResults;
78699
+ }
78700
+ const autoAllowedMetadata = autoAllowedExecutionRef.current ? {
78701
+ conversationId: autoAllowedExecutionRef.current.conversationId,
78702
+ generation: conversationGenerationRef.current
78703
+ } : undefined;
78704
+ if (userCancelledRef.current || autoAllowedAbortController.signal.aborted || interruptQueuedRef.current) {
78705
+ if (queuedResults.length > 0) {
78706
+ queueApprovalResults(queuedResults, autoAllowedMetadata);
78707
+ }
78708
+ setStreaming(false);
78709
+ markIncompleteToolsAsCancelled(buffersRef.current);
78710
+ refreshDerived();
78711
+ return { submitted: false };
78712
+ }
78713
+ setAutoHandledResults(autoAllowedWithResults);
78714
+ setAutoDeniedApprovals(autoDeniedWithReasons);
78715
+ refreshDerived();
78716
+ return { submitted: false };
78717
+ } finally {
78718
+ if (shouldTrackAutoAllowed) {
78719
+ setIsExecutingTool(false);
78720
+ toolAbortControllerRef.current = null;
78721
+ executingToolCallIdsRef.current = [];
78722
+ autoAllowedExecutionRef.current = null;
78723
+ }
78724
+ }
78403
78725
  }
78404
78726
  }
78405
78727
  } catch (_error) {}
78406
78728
  }
78407
78729
  const initialInput = [];
78408
78730
  if (queuedApprovalResults) {
78409
- initialInput.push({
78410
- type: "approval",
78411
- approvals: queuedApprovalResults
78412
- });
78413
- setQueuedApprovalResults(null);
78731
+ const queuedMetadata = queuedApprovalMetadataRef.current;
78732
+ const isQueuedValid = queuedMetadata && queuedMetadata.conversationId === conversationIdRef.current && queuedMetadata.generation === conversationGenerationRef.current;
78733
+ if (isQueuedValid) {
78734
+ initialInput.push({
78735
+ type: "approval",
78736
+ approvals: queuedApprovalResults
78737
+ });
78738
+ } else {
78739
+ console.warn("[WARN] Dropping stale queued approval results for mismatched conversation or generation");
78740
+ }
78741
+ queueApprovalResults(null);
78414
78742
  interruptQueuedRef.current = false;
78415
78743
  }
78416
78744
  initialInput.push({
@@ -78433,6 +78761,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78433
78761
  handleExit,
78434
78762
  isExecutingTool,
78435
78763
  queuedApprovalResults,
78764
+ queueApprovalResults,
78436
78765
  pendingApprovals,
78437
78766
  profileConfirmPending,
78438
78767
  handleAgentSelect,
@@ -78544,7 +78873,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78544
78873
  const userCancelled = userCancelledRef.current;
78545
78874
  if (wasAborted || userCancelled) {
78546
78875
  if (!interruptQueuedRef.current) {
78547
- setQueuedApprovalResults(allResults);
78876
+ queueApprovalResults(allResults);
78548
78877
  }
78549
78878
  setStreaming(false);
78550
78879
  waitingForQueueCancelRef.current = false;
@@ -78572,7 +78901,8 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78572
78901
  refreshDerived,
78573
78902
  appendError,
78574
78903
  setStreaming,
78575
- updateStreamingOutput
78904
+ updateStreamingOutput,
78905
+ queueApprovalResults
78576
78906
  ]);
78577
78907
  const handleApproveCurrent = import_react84.useCallback(async (diffs) => {
78578
78908
  if (isExecutingTool)
@@ -78770,7 +79100,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78770
79100
  approve: false,
78771
79101
  reason: "User cancelled the approval"
78772
79102
  }));
78773
- setQueuedApprovalResults(denialResults);
79103
+ queueApprovalResults(denialResults);
78774
79104
  markIncompleteToolsAsCancelled(buffersRef.current);
78775
79105
  refreshDerived();
78776
79106
  setPendingApprovals([]);
@@ -78778,7 +79108,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
78778
79108
  setApprovalResults([]);
78779
79109
  setAutoHandledResults([]);
78780
79110
  setAutoDeniedApprovals([]);
78781
- }, [pendingApprovals, refreshDerived]);
79111
+ }, [pendingApprovals, refreshDerived, queueApprovalResults]);
78782
79112
  const handleModelSelect = import_react84.useCallback(async (modelId) => {
78783
79113
  await withCommandLock(async () => {
78784
79114
  let cmdId = null;
@@ -79160,7 +79490,7 @@ Consider switching to a different system prompt using /system to match.` : null;
79160
79490
  reason: "Plan mode session expired (CLI restarted). Use EnterPlanMode to re-enter plan mode, or request the user to re-enter plan mode."
79161
79491
  }
79162
79492
  ];
79163
- setQueuedApprovalResults(denialResults);
79493
+ queueApprovalResults(denialResults);
79164
79494
  markIncompleteToolsAsCancelled(buffersRef.current);
79165
79495
  refreshDerived();
79166
79496
  setPendingApprovals([]);
@@ -79172,7 +79502,7 @@ Consider switching to a different system prompt using /system to match.` : null;
79172
79502
  }
79173
79503
  if (!planFileExists()) {
79174
79504
  const planFilePath = permissionMode.getPlanFilePath();
79175
- const plansDir = join20(homedir11(), ".letta", "plans");
79505
+ const plansDir = join21(homedir12(), ".letta", "plans");
79176
79506
  handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
79177
79507
  ` + (planFilePath ? `Plan file path: ${planFilePath}
79178
79508
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
@@ -79182,7 +79512,8 @@ Consider switching to a different system prompt using /system to match.` : null;
79182
79512
  pendingApprovals,
79183
79513
  approvalResults.length,
79184
79514
  handlePlanKeepPlanning,
79185
- refreshDerived
79515
+ refreshDerived,
79516
+ queueApprovalResults
79186
79517
  ]);
79187
79518
  const handleQuestionSubmit = import_react84.useCallback(async (answers) => {
79188
79519
  const currentIndex = approvalResults.length;
@@ -80043,13 +80374,13 @@ __export(exports_terminalKeybindingInstaller2, {
80043
80374
  });
80044
80375
  import {
80045
80376
  copyFileSync as copyFileSync2,
80046
- existsSync as existsSync13,
80047
- mkdirSync as mkdirSync5,
80377
+ existsSync as existsSync14,
80378
+ mkdirSync as mkdirSync6,
80048
80379
  readFileSync as readFileSync5,
80049
- writeFileSync as writeFileSync4
80380
+ writeFileSync as writeFileSync5
80050
80381
  } from "node:fs";
80051
- import { homedir as homedir12, platform as platform5 } from "node:os";
80052
- import { dirname as dirname12, join as join21 } from "node:path";
80382
+ import { homedir as homedir13, platform as platform5 } from "node:os";
80383
+ import { dirname as dirname12, join as join22 } from "node:path";
80053
80384
  function detectTerminalType2() {
80054
80385
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
80055
80386
  return "cursor";
@@ -80079,18 +80410,18 @@ function getKeybindingsPath2(terminal) {
80079
80410
  cursor: "Cursor",
80080
80411
  windsurf: "Windsurf"
80081
80412
  }[terminal];
80082
- const os5 = platform5();
80083
- if (os5 === "darwin") {
80084
- return join21(homedir12(), "Library", "Application Support", appName, "User", "keybindings.json");
80413
+ const os6 = platform5();
80414
+ if (os6 === "darwin") {
80415
+ return join22(homedir13(), "Library", "Application Support", appName, "User", "keybindings.json");
80085
80416
  }
80086
- if (os5 === "win32") {
80417
+ if (os6 === "win32") {
80087
80418
  const appData = process.env.APPDATA;
80088
80419
  if (!appData)
80089
80420
  return null;
80090
- return join21(appData, appName, "User", "keybindings.json");
80421
+ return join22(appData, appName, "User", "keybindings.json");
80091
80422
  }
80092
- if (os5 === "linux") {
80093
- return join21(homedir12(), ".config", appName, "User", "keybindings.json");
80423
+ if (os6 === "linux") {
80424
+ return join22(homedir13(), ".config", appName, "User", "keybindings.json");
80094
80425
  }
80095
80426
  return null;
80096
80427
  }
@@ -80112,7 +80443,7 @@ function parseKeybindings2(content) {
80112
80443
  }
80113
80444
  }
80114
80445
  function keybindingExists2(keybindingsPath) {
80115
- if (!existsSync13(keybindingsPath))
80446
+ if (!existsSync14(keybindingsPath))
80116
80447
  return false;
80117
80448
  try {
80118
80449
  const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
@@ -80125,7 +80456,7 @@ function keybindingExists2(keybindingsPath) {
80125
80456
  }
80126
80457
  }
80127
80458
  function createBackup2(keybindingsPath) {
80128
- if (!existsSync13(keybindingsPath))
80459
+ if (!existsSync14(keybindingsPath))
80129
80460
  return null;
80130
80461
  const backupPath = `${keybindingsPath}.letta-backup`;
80131
80462
  try {
@@ -80141,12 +80472,12 @@ function installKeybinding2(keybindingsPath) {
80141
80472
  return { success: true, alreadyExists: true };
80142
80473
  }
80143
80474
  const parentDir = dirname12(keybindingsPath);
80144
- if (!existsSync13(parentDir)) {
80145
- mkdirSync5(parentDir, { recursive: true });
80475
+ if (!existsSync14(parentDir)) {
80476
+ mkdirSync6(parentDir, { recursive: true });
80146
80477
  }
80147
80478
  let keybindings = [];
80148
80479
  let backupPath = null;
80149
- if (existsSync13(keybindingsPath)) {
80480
+ if (existsSync14(keybindingsPath)) {
80150
80481
  backupPath = createBackup2(keybindingsPath);
80151
80482
  const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
80152
80483
  const parsed = parseKeybindings2(content);
@@ -80161,7 +80492,7 @@ function installKeybinding2(keybindingsPath) {
80161
80492
  keybindings.push(SHIFT_ENTER_KEYBINDING2);
80162
80493
  const newContent = `${JSON.stringify(keybindings, null, 2)}
80163
80494
  `;
80164
- writeFileSync4(keybindingsPath, newContent, { encoding: "utf-8" });
80495
+ writeFileSync5(keybindingsPath, newContent, { encoding: "utf-8" });
80165
80496
  return {
80166
80497
  success: true,
80167
80498
  backupPath: backupPath ?? undefined
@@ -80176,7 +80507,7 @@ function installKeybinding2(keybindingsPath) {
80176
80507
  }
80177
80508
  function removeKeybinding2(keybindingsPath) {
80178
80509
  try {
80179
- if (!existsSync13(keybindingsPath)) {
80510
+ if (!existsSync14(keybindingsPath)) {
80180
80511
  return { success: true };
80181
80512
  }
80182
80513
  const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
@@ -80190,7 +80521,7 @@ function removeKeybinding2(keybindingsPath) {
80190
80521
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
80191
80522
  const newContent = `${JSON.stringify(filtered, null, 2)}
80192
80523
  `;
80193
- writeFileSync4(keybindingsPath, newContent, { encoding: "utf-8" });
80524
+ writeFileSync5(keybindingsPath, newContent, { encoding: "utf-8" });
80194
80525
  return { success: true };
80195
80526
  } catch (error) {
80196
80527
  const message = error instanceof Error ? error.message : String(error);
@@ -80208,14 +80539,14 @@ function installKeybindingForCurrentTerminal2() {
80208
80539
  error: "Not running in a VS Code-like terminal"
80209
80540
  };
80210
80541
  }
80211
- const path20 = getKeybindingsPath2(terminal);
80212
- if (!path20) {
80542
+ const path21 = getKeybindingsPath2(terminal);
80543
+ if (!path21) {
80213
80544
  return {
80214
80545
  success: false,
80215
80546
  error: `Could not determine keybindings.json path for ${terminal}`
80216
80547
  };
80217
80548
  }
80218
- return installKeybinding2(path20);
80549
+ return installKeybinding2(path21);
80219
80550
  }
80220
80551
  function removeKeybindingForCurrentTerminal2() {
80221
80552
  const terminal = detectTerminalType2();
@@ -80225,14 +80556,14 @@ function removeKeybindingForCurrentTerminal2() {
80225
80556
  error: "Not running in a VS Code-like terminal"
80226
80557
  };
80227
80558
  }
80228
- const path20 = getKeybindingsPath2(terminal);
80229
- if (!path20) {
80559
+ const path21 = getKeybindingsPath2(terminal);
80560
+ if (!path21) {
80230
80561
  return {
80231
80562
  success: false,
80232
80563
  error: `Could not determine keybindings.json path for ${terminal}`
80233
80564
  };
80234
80565
  }
80235
- return removeKeybinding2(path20);
80566
+ return removeKeybinding2(path21);
80236
80567
  }
80237
80568
  function isWezTerm2() {
80238
80569
  return process.env.TERM_PROGRAM === "WezTerm";
@@ -80243,17 +80574,17 @@ function getWezTermConfigPath2() {
80243
80574
  }
80244
80575
  const xdgConfig = process.env.XDG_CONFIG_HOME;
80245
80576
  if (xdgConfig) {
80246
- const xdgPath = join21(xdgConfig, "wezterm", "wezterm.lua");
80247
- if (existsSync13(xdgPath))
80577
+ const xdgPath = join22(xdgConfig, "wezterm", "wezterm.lua");
80578
+ if (existsSync14(xdgPath))
80248
80579
  return xdgPath;
80249
80580
  }
80250
- const configPath = join21(homedir12(), ".config", "wezterm", "wezterm.lua");
80251
- if (existsSync13(configPath))
80581
+ const configPath = join22(homedir13(), ".config", "wezterm", "wezterm.lua");
80582
+ if (existsSync14(configPath))
80252
80583
  return configPath;
80253
- return join21(homedir12(), ".wezterm.lua");
80584
+ return join22(homedir13(), ".wezterm.lua");
80254
80585
  }
80255
80586
  function wezTermDeleteFixExists2(configPath) {
80256
- if (!existsSync13(configPath))
80587
+ if (!existsSync14(configPath))
80257
80588
  return false;
80258
80589
  try {
80259
80590
  const content = readFileSync5(configPath, { encoding: "utf-8" });
@@ -80270,7 +80601,7 @@ function installWezTermDeleteFix2() {
80270
80601
  }
80271
80602
  let content = "";
80272
80603
  let backupPath = null;
80273
- if (existsSync13(configPath)) {
80604
+ if (existsSync14(configPath)) {
80274
80605
  backupPath = `${configPath}.letta-backup`;
80275
80606
  copyFileSync2(configPath, backupPath);
80276
80607
  content = readFileSync5(configPath, { encoding: "utf-8" });
@@ -80300,10 +80631,10 @@ ${WEZTERM_DELETE_FIX2}
80300
80631
  `;
80301
80632
  }
80302
80633
  const parentDir = dirname12(configPath);
80303
- if (!existsSync13(parentDir)) {
80304
- mkdirSync5(parentDir, { recursive: true });
80634
+ if (!existsSync14(parentDir)) {
80635
+ mkdirSync6(parentDir, { recursive: true });
80305
80636
  }
80306
- writeFileSync4(configPath, content, { encoding: "utf-8" });
80637
+ writeFileSync5(configPath, content, { encoding: "utf-8" });
80307
80638
  return {
80308
80639
  success: true,
80309
80640
  backupPath: backupPath ?? undefined
@@ -80348,10 +80679,10 @@ __export(exports_settings2, {
80348
80679
  loadProjectSettings: () => loadProjectSettings2,
80349
80680
  getSetting: () => getSetting2
80350
80681
  });
80351
- import { homedir as homedir13 } from "node:os";
80352
- import { join as join22 } from "node:path";
80682
+ import { homedir as homedir14 } from "node:os";
80683
+ import { join as join23 } from "node:path";
80353
80684
  function getSettingsPath2() {
80354
- return join22(homedir13(), ".letta", "settings.json");
80685
+ return join23(homedir14(), ".letta", "settings.json");
80355
80686
  }
80356
80687
  async function loadSettings2() {
80357
80688
  const settingsPath = getSettingsPath2();
@@ -80388,7 +80719,7 @@ async function getSetting2(key) {
80388
80719
  return settings[key];
80389
80720
  }
80390
80721
  function getProjectSettingsPath2() {
80391
- return join22(process.cwd(), ".letta", "settings.local.json");
80722
+ return join23(process.cwd(), ".letta", "settings.local.json");
80392
80723
  }
80393
80724
  async function loadProjectSettings2() {
80394
80725
  const settingsPath = getProjectSettingsPath2();
@@ -80406,7 +80737,7 @@ async function loadProjectSettings2() {
80406
80737
  }
80407
80738
  async function saveProjectSettings2(settings) {
80408
80739
  const settingsPath = getProjectSettingsPath2();
80409
- const dirPath = join22(process.cwd(), ".letta");
80740
+ const dirPath = join23(process.cwd(), ".letta");
80410
80741
  try {
80411
80742
  if (!exists(dirPath)) {
80412
80743
  await mkdir(dirPath, { recursive: true });
@@ -80485,8 +80816,8 @@ var exports_create = {};
80485
80816
  __export(exports_create, {
80486
80817
  createAgent: () => createAgent2
80487
80818
  });
80488
- import { join as join23 } from "node:path";
80489
- async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingModel = "openai/text-embedding-3-small", updateArgs, skillsDirectory, parallelToolCalls = true, enableSleeptime = false, systemPromptPreset, initBlocks, baseTools) {
80819
+ import { join as join24 } from "node:path";
80820
+ async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingModel, updateArgs, skillsDirectory, parallelToolCalls = true, enableSleeptime = false, systemPromptPreset, initBlocks, baseTools) {
80490
80821
  let options;
80491
80822
  if (typeof nameOrOptions === "object") {
80492
80823
  options = nameOrOptions;
@@ -80505,7 +80836,7 @@ async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embedding
80505
80836
  };
80506
80837
  }
80507
80838
  const name = options.name ?? DEFAULT_AGENT_NAME;
80508
- const embeddingModelVal = options.embeddingModel ?? "openai/text-embedding-3-small";
80839
+ const embeddingModelVal = options.embeddingModel;
80509
80840
  const parallelToolCallsVal = options.parallelToolCalls ?? true;
80510
80841
  const enableSleeptimeVal = options.enableSleeptime ?? false;
80511
80842
  let modelHandle;
@@ -80580,7 +80911,7 @@ async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embedding
80580
80911
  }
80581
80912
  }
80582
80913
  }
80583
- const resolvedSkillsDirectory = options.skillsDirectory || join23(process.cwd(), SKILLS_DIR);
80914
+ const resolvedSkillsDirectory = options.skillsDirectory || join24(process.cwd(), SKILLS_DIR);
80584
80915
  try {
80585
80916
  const { skills, errors } = await discoverSkills(resolvedSkillsDirectory);
80586
80917
  if (errors.length > 0) {
@@ -80627,7 +80958,7 @@ ${options.systemPromptAppend}`;
80627
80958
  system: systemPromptContent,
80628
80959
  name,
80629
80960
  description: agentDescription,
80630
- embedding: embeddingModelVal,
80961
+ embedding: embeddingModelVal || undefined,
80631
80962
  model: modelHandle,
80632
80963
  context_window_limit: contextWindow,
80633
80964
  tools: toolNames,
@@ -83416,12 +83747,12 @@ EXAMPLES
83416
83747
  console.log(usage);
83417
83748
  }
83418
83749
  async function printInfo() {
83419
- const { join: join24 } = await import("path");
83750
+ const { join: join25 } = await import("path");
83420
83751
  const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
83421
83752
  const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
83422
83753
  const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
83423
83754
  const cwd2 = process.cwd();
83424
- const skillsDir = join24(cwd2, SKILLS_DIR3);
83755
+ const skillsDir = join25(cwd2, SKILLS_DIR3);
83425
83756
  const skillsExist = exists3(skillsDir);
83426
83757
  await settingsManager2.loadLocalProjectSettings(cwd2);
83427
83758
  const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
@@ -83560,6 +83891,12 @@ async function main() {
83560
83891
  telemetry2.init();
83561
83892
  const { checkAndAutoUpdate: checkAndAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_update(), exports_auto_update));
83562
83893
  checkAndAutoUpdate2().catch(() => {});
83894
+ const { cleanupOldOverflowFiles: cleanupOldOverflowFiles2 } = await Promise.resolve().then(() => (init_overflow2(), exports_overflow));
83895
+ Promise.resolve().then(() => {
83896
+ try {
83897
+ cleanupOldOverflowFiles2(process.cwd());
83898
+ } catch {}
83899
+ });
83563
83900
  const processedArgs = process.argv.map((arg) => arg === "--conv" ? "--conversation" : arg);
83564
83901
  let values;
83565
83902
  let positionals;
@@ -83796,9 +84133,9 @@ Usage: letta --new-agent`);
83796
84133
  process.exit(1);
83797
84134
  }
83798
84135
  const { resolve: resolve21 } = await import("path");
83799
- const { existsSync: existsSync14 } = await import("fs");
84136
+ const { existsSync: existsSync15 } = await import("fs");
83800
84137
  const resolvedPath = resolve21(fromAfFile);
83801
- if (!existsSync14(resolvedPath)) {
84138
+ if (!existsSync15(resolvedPath)) {
83802
84139
  console.error(`Error: AgentFile not found: ${resolvedPath}`);
83803
84140
  process.exit(1);
83804
84141
  }
@@ -84300,8 +84637,8 @@ Error: ${message}`);
84300
84637
  (async () => {
84301
84638
  try {
84302
84639
  const { syncSkillsToAgent: syncSkillsToAgent3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
84303
- const { join: join24 } = await import("path");
84304
- const resolvedSkillsDirectory = skillsDirectory2 || join24(process.cwd(), SKILLS_DIR3);
84640
+ const { join: join25 } = await import("path");
84641
+ const resolvedSkillsDirectory = skillsDirectory2 || join25(process.cwd(), SKILLS_DIR3);
84305
84642
  await syncSkillsToAgent3(client, agent.id, resolvedSkillsDirectory, {
84306
84643
  skipIfUnchanged: true
84307
84644
  });
@@ -84542,4 +84879,4 @@ Error during initialization: ${message}`);
84542
84879
  }
84543
84880
  main();
84544
84881
 
84545
- //# debugId=0420C9226EBBB2BA64756E2164756E21
84882
+ //# debugId=32B4EFE259BB1E4B64756E2164756E21