@letta-ai/letta-code 0.19.8 → 0.19.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -3255,7 +3255,7 @@ var package_default;
3255
3255
  var init_package = __esm(() => {
3256
3256
  package_default = {
3257
3257
  name: "@letta-ai/letta-code",
3258
- version: "0.19.8",
3258
+ version: "0.19.9",
3259
3259
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3260
3260
  type: "module",
3261
3261
  bin: {
@@ -4247,6 +4247,11 @@ class SettingsManager {
4247
4247
  }
4248
4248
  return this.getGlobalLastAgentId();
4249
4249
  }
4250
+ persistSession(agentId, conversationId, workingDirectory = process.cwd()) {
4251
+ const session = { agentId, conversationId };
4252
+ this.setLocalLastSession(session, workingDirectory);
4253
+ this.setGlobalLastSession(session);
4254
+ }
4250
4255
  getGlobalPinnedAgents() {
4251
4256
  const settings = this.getSettings();
4252
4257
  const serverKey = getCurrentServerKey(settings);
@@ -4609,6 +4614,7 @@ var init_settings_manager = __esm(async () => {
4609
4614
  enableSleeptime: false,
4610
4615
  conversationSwitchAlertEnabled: false,
4611
4616
  sessionContextEnabled: true,
4617
+ autoSwapOnQuotaLimit: true,
4612
4618
  memoryReminderInterval: 25,
4613
4619
  reflectionTrigger: "step-count",
4614
4620
  reflectionStepCount: 25,
@@ -40351,6 +40357,31 @@ var init_fileIndex = __esm(() => {
40351
40357
  cachedEntryPaths2 = new Set;
40352
40358
  });
40353
40359
 
40360
+ // src/cli/helpers/messageQueueBridge.ts
40361
+ function setMessageQueueAdder(fn) {
40362
+ queueAdder = fn;
40363
+ if (queueAdder && pendingMessages.length > 0) {
40364
+ for (const message of pendingMessages) {
40365
+ queueAdder(message);
40366
+ }
40367
+ pendingMessages.length = 0;
40368
+ }
40369
+ }
40370
+ function addToMessageQueue(message) {
40371
+ if (queueAdder) {
40372
+ queueAdder(message);
40373
+ return;
40374
+ }
40375
+ if (pendingMessages.length >= MAX_PENDING_MESSAGES) {
40376
+ pendingMessages.shift();
40377
+ }
40378
+ pendingMessages.push(message);
40379
+ }
40380
+ var queueAdder = null, pendingMessages, MAX_PENDING_MESSAGES = 10;
40381
+ var init_messageQueueBridge = __esm(() => {
40382
+ pendingMessages = [];
40383
+ });
40384
+
40354
40385
  // src/cli/helpers/planName.ts
40355
40386
  import { homedir as homedir8 } from "node:os";
40356
40387
  import { join as join9 } from "node:path";
@@ -40469,6 +40500,186 @@ var init_planName = __esm(() => {
40469
40500
  ];
40470
40501
  });
40471
40502
 
40503
+ // src/cli/helpers/subagentState.ts
40504
+ function updateSnapshot() {
40505
+ cachedSnapshot = {
40506
+ agents: Array.from(store.agents.values()),
40507
+ expanded: store.expanded
40508
+ };
40509
+ }
40510
+ function notifyListeners() {
40511
+ updateSnapshot();
40512
+ for (const listener of store.listeners) {
40513
+ listener();
40514
+ }
40515
+ }
40516
+ function generateSubagentId() {
40517
+ return `subagent-${Date.now()}-${++subagentCounter}`;
40518
+ }
40519
+ function getSubagentByToolCallId(toolCallId) {
40520
+ for (const agent of store.agents.values()) {
40521
+ if (agent.toolCallId === toolCallId) {
40522
+ return agent;
40523
+ }
40524
+ }
40525
+ return;
40526
+ }
40527
+ function registerSubagent(id, type, description, toolCallId, isBackground, silent) {
40528
+ const displayType = type.charAt(0).toUpperCase() + type.slice(1);
40529
+ const agent = {
40530
+ id,
40531
+ type: displayType,
40532
+ description,
40533
+ status: "pending",
40534
+ agentURL: null,
40535
+ toolCalls: [],
40536
+ maxToolCallsSeen: 0,
40537
+ totalTokens: 0,
40538
+ durationMs: 0,
40539
+ startTime: Date.now(),
40540
+ toolCallId,
40541
+ isBackground,
40542
+ silent
40543
+ };
40544
+ store.agents.set(id, agent);
40545
+ notifyListeners();
40546
+ }
40547
+ function updateSubagent(id, updates) {
40548
+ const agent = store.agents.get(id);
40549
+ if (!agent)
40550
+ return;
40551
+ if (updates.agentURL && agent.status === "pending") {
40552
+ updates.status = "running";
40553
+ }
40554
+ const nextToolCalls = updates.toolCalls ?? agent.toolCalls;
40555
+ const nextMax = Math.max(agent.maxToolCallsSeen, nextToolCalls.length, updates.maxToolCallsSeen ?? 0);
40556
+ const keys = Object.keys(updates);
40557
+ const isNoop = keys.every((k) => agent[k] === updates[k]) && nextMax === agent.maxToolCallsSeen;
40558
+ if (isNoop)
40559
+ return;
40560
+ const updatedAgent = { ...agent, ...updates, maxToolCallsSeen: nextMax };
40561
+ store.agents.set(id, updatedAgent);
40562
+ notifyListeners();
40563
+ }
40564
+ function addToolCall(subagentId, toolCallId, toolName, toolArgs) {
40565
+ const agent = store.agents.get(subagentId);
40566
+ if (!agent)
40567
+ return;
40568
+ if (agent.toolCalls.some((tc) => tc.id === toolCallId))
40569
+ return;
40570
+ const updatedAgent = {
40571
+ ...agent,
40572
+ toolCalls: [
40573
+ ...agent.toolCalls,
40574
+ { id: toolCallId, name: toolName, args: toolArgs }
40575
+ ],
40576
+ maxToolCallsSeen: Math.max(agent.maxToolCallsSeen, agent.toolCalls.length + 1)
40577
+ };
40578
+ store.agents.set(subagentId, updatedAgent);
40579
+ notifyListeners();
40580
+ }
40581
+ function completeSubagent(id, result) {
40582
+ const agent = store.agents.get(id);
40583
+ if (!agent)
40584
+ return;
40585
+ const updatedAgent = {
40586
+ ...agent,
40587
+ status: result.success ? "completed" : "error",
40588
+ error: result.error,
40589
+ durationMs: Date.now() - agent.startTime,
40590
+ totalTokens: result.totalTokens ?? agent.totalTokens,
40591
+ maxToolCallsSeen: Math.max(agent.maxToolCallsSeen, agent.toolCalls.length)
40592
+ };
40593
+ store.agents.set(id, updatedAgent);
40594
+ notifyListeners();
40595
+ }
40596
+ function getSubagentToolCount(agent) {
40597
+ return Math.max(agent.toolCalls.length, agent.maxToolCallsSeen);
40598
+ }
40599
+ function toggleExpanded() {
40600
+ store.expanded = !store.expanded;
40601
+ notifyListeners();
40602
+ }
40603
+ function getSubagents() {
40604
+ return Array.from(store.agents.values());
40605
+ }
40606
+ function getActiveBackgroundAgents() {
40607
+ return Array.from(store.agents.values()).filter((a) => a.silent === true && (a.status === "pending" || a.status === "running"));
40608
+ }
40609
+ function clearCompletedSubagents() {
40610
+ for (const [id, agent] of store.agents.entries()) {
40611
+ if (agent.status === "completed" || agent.status === "error") {
40612
+ store.agents.delete(id);
40613
+ }
40614
+ }
40615
+ notifyListeners();
40616
+ }
40617
+ function clearSubagentsByIds(ids) {
40618
+ for (const id of ids) {
40619
+ store.agents.delete(id);
40620
+ }
40621
+ notifyListeners();
40622
+ }
40623
+ function hasActiveSubagents() {
40624
+ for (const agent of store.agents.values()) {
40625
+ if (agent.status === "pending" || agent.status === "running") {
40626
+ return true;
40627
+ }
40628
+ }
40629
+ return false;
40630
+ }
40631
+ function interruptActiveSubagents(errorMessage) {
40632
+ let anyInterrupted = false;
40633
+ for (const [id, agent] of store.agents.entries()) {
40634
+ if (agent.status === "pending" || agent.status === "running") {
40635
+ const updatedAgent = {
40636
+ ...agent,
40637
+ status: "error",
40638
+ error: errorMessage,
40639
+ durationMs: Date.now() - agent.startTime
40640
+ };
40641
+ store.agents.set(id, updatedAgent);
40642
+ anyInterrupted = true;
40643
+ }
40644
+ }
40645
+ if (anyInterrupted) {
40646
+ notifyListeners();
40647
+ }
40648
+ }
40649
+ function subscribe2(listener) {
40650
+ store.listeners.add(listener);
40651
+ return () => {
40652
+ store.listeners.delete(listener);
40653
+ };
40654
+ }
40655
+ function getSnapshot2() {
40656
+ return cachedSnapshot;
40657
+ }
40658
+ function subscribeToStreamEvents(listener) {
40659
+ streamEventListeners.add(listener);
40660
+ return () => {
40661
+ streamEventListeners.delete(listener);
40662
+ };
40663
+ }
40664
+ function emitStreamEvent(subagentId, event) {
40665
+ for (const listener of streamEventListeners) {
40666
+ listener(subagentId, event);
40667
+ }
40668
+ }
40669
+ var store, cachedSnapshot, subagentCounter = 0, streamEventListeners;
40670
+ var init_subagentState = __esm(() => {
40671
+ store = {
40672
+ agents: new Map,
40673
+ expanded: false,
40674
+ listeners: new Set
40675
+ };
40676
+ cachedSnapshot = {
40677
+ agents: [],
40678
+ expanded: false
40679
+ };
40680
+ streamEventListeners = new Set;
40681
+ });
40682
+
40472
40683
  // src/queue/queueRuntime.ts
40473
40684
  function isCoalescable(kind) {
40474
40685
  return kind === "message" || kind === "task_notification";
@@ -40738,6 +40949,7 @@ async function executeSingleDecision(decision, onChunk, options) {
40738
40949
  signal: options?.abortSignal,
40739
40950
  toolCallId: decision.approval.toolCallId,
40740
40951
  toolContextId: options?.toolContextId,
40952
+ parentScope: options?.parentScope,
40741
40953
  onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined
40742
40954
  });
40743
40955
  if (onChunk) {
@@ -43157,6 +43369,141 @@ var init_telemetry = __esm(async () => {
43157
43369
  telemetry = new TelemetryManager;
43158
43370
  });
43159
43371
 
43372
+ // src/utils/secretsStore.ts
43373
+ var exports_secretsStore = {};
43374
+ __export(exports_secretsStore, {
43375
+ setSecretOnServer: () => setSecretOnServer,
43376
+ loadSecrets: () => loadSecrets,
43377
+ listSecretNames: () => listSecretNames,
43378
+ initSecretsFromServer: () => initSecretsFromServer,
43379
+ deleteSecretOnServer: () => deleteSecretOnServer,
43380
+ clearSecretsCache: () => clearSecretsCache
43381
+ });
43382
+ import { existsSync as existsSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync5 } from "node:fs";
43383
+ import { dirname as dirname3, join as join11 } from "node:path";
43384
+ function getAgentId3() {
43385
+ const agentId = storedAgentId || process.env.AGENT_ID || process.env.LETTA_AGENT_ID;
43386
+ if (!agentId) {
43387
+ throw new Error("No agent ID available — call initSecretsFromServer first");
43388
+ }
43389
+ return agentId;
43390
+ }
43391
+ async function initSecretsFromServer(agentId, memoryDir) {
43392
+ storedAgentId = agentId;
43393
+ if (memoryDir)
43394
+ storedMemoryDir = memoryDir;
43395
+ const client = await getClient2();
43396
+ const agent = await client.agents.retrieve(agentId, {
43397
+ include: ["agent.secrets"]
43398
+ });
43399
+ const secrets2 = {};
43400
+ if (agent.secrets && Array.isArray(agent.secrets)) {
43401
+ for (const env3 of agent.secrets) {
43402
+ if (env3.key && env3.value) {
43403
+ secrets2[env3.key] = env3.value;
43404
+ }
43405
+ }
43406
+ }
43407
+ cachedSecrets = secrets2;
43408
+ syncSecretsToMemoryBlock();
43409
+ }
43410
+ function loadSecrets() {
43411
+ return cachedSecrets ?? {};
43412
+ }
43413
+ function listSecretNames() {
43414
+ return Object.keys(loadSecrets()).sort();
43415
+ }
43416
+ async function setSecretOnServer(key, value) {
43417
+ const client = await getClient2();
43418
+ const agentId = getAgentId3();
43419
+ const secrets2 = { ...loadSecrets() };
43420
+ secrets2[key] = value;
43421
+ await client.agents.update(agentId, { secrets: secrets2 });
43422
+ cachedSecrets = secrets2;
43423
+ syncSecretsToMemoryBlock();
43424
+ }
43425
+ async function deleteSecretOnServer(key) {
43426
+ const secrets2 = { ...loadSecrets() };
43427
+ if (!(key in secrets2)) {
43428
+ return false;
43429
+ }
43430
+ delete secrets2[key];
43431
+ const client = await getClient2();
43432
+ const agentId = getAgentId3();
43433
+ await client.agents.update(agentId, { secrets: secrets2 });
43434
+ cachedSecrets = secrets2;
43435
+ syncSecretsToMemoryBlock();
43436
+ return true;
43437
+ }
43438
+ function syncSecretsToMemoryBlock() {
43439
+ const memoryDir = storedMemoryDir || process.env.MEMORY_DIR;
43440
+ if (!memoryDir)
43441
+ return;
43442
+ const names = listSecretNames();
43443
+ const secretsFilePath = join11(memoryDir, "system", "secrets.md");
43444
+ const description = names.length > 0 ? "Available secrets for shell command substitution" : "No secrets configured";
43445
+ const body = names.length > 0 ? `Use \`$SECRET_NAME\` syntax in shell commands to reference these secrets:
43446
+
43447
+ ${names.map((n) => `- \`$${n}\``).join(`
43448
+ `)}` : "";
43449
+ const rendered = `---
43450
+ description: ${description}
43451
+ ---
43452
+
43453
+ ## Available Secrets
43454
+
43455
+ ${body}
43456
+ `;
43457
+ const systemDir = dirname3(secretsFilePath);
43458
+ if (!existsSync10(systemDir)) {
43459
+ mkdirSync8(systemDir, { recursive: true });
43460
+ }
43461
+ writeFileSync5(secretsFilePath, rendered, "utf8");
43462
+ }
43463
+ function clearSecretsCache() {
43464
+ cachedSecrets = null;
43465
+ }
43466
+ var cachedSecrets = null, storedAgentId = null, storedMemoryDir = null;
43467
+ var init_secretsStore = __esm(async () => {
43468
+ await init_client2();
43469
+ });
43470
+
43471
+ // src/tools/secret-substitution.ts
43472
+ function substituteSecretsInString(input) {
43473
+ const secrets2 = loadSecrets();
43474
+ return input.replace(SECRET_PATTERN, (match, name) => {
43475
+ const value = secrets2[name];
43476
+ return value !== undefined ? value : match;
43477
+ });
43478
+ }
43479
+ function substituteSecretsInArgs(args) {
43480
+ const result = {};
43481
+ for (const [key, value] of Object.entries(args)) {
43482
+ if (typeof value === "string") {
43483
+ result[key] = substituteSecretsInString(value);
43484
+ } else {
43485
+ result[key] = value;
43486
+ }
43487
+ }
43488
+ return result;
43489
+ }
43490
+ function scrubSecretsFromString(input) {
43491
+ const secrets2 = loadSecrets();
43492
+ let result = input;
43493
+ const entries = Object.entries(secrets2).sort(([, a], [, b]) => b.length - a.length);
43494
+ for (const [name, value] of entries) {
43495
+ if (value.length > 0) {
43496
+ result = result.replaceAll(value, `$${name}`);
43497
+ }
43498
+ }
43499
+ return result;
43500
+ }
43501
+ var SECRET_PATTERN;
43502
+ var init_secret_substitution = __esm(async () => {
43503
+ await init_secretsStore();
43504
+ SECRET_PATTERN = /\$([A-Z_][A-Z0-9_]*)/g;
43505
+ });
43506
+
43160
43507
  // src/tools/descriptions/ApplyPatch.md
43161
43508
  var ApplyPatch_default = `Use the \`apply_patch\` tool to edit files.
43162
43509
  Your patch language is a stripped‑down, file‑oriented diff format designed to be easy to parse and safe to apply. You can think of it as a high‑level envelope:
@@ -44859,20 +45206,20 @@ __export(exports_memoryGit, {
44859
45206
  import { execFile as execFileCb } from "node:child_process";
44860
45207
  import {
44861
45208
  chmodSync,
44862
- existsSync as existsSync10,
44863
- mkdirSync as mkdirSync8,
45209
+ existsSync as existsSync11,
45210
+ mkdirSync as mkdirSync9,
44864
45211
  renameSync,
44865
45212
  rmSync,
44866
- writeFileSync as writeFileSync5
45213
+ writeFileSync as writeFileSync6
44867
45214
  } from "node:fs";
44868
45215
  import { homedir as homedir12 } from "node:os";
44869
- import { join as join11 } from "node:path";
45216
+ import { join as join12 } from "node:path";
44870
45217
  import { promisify as promisify6 } from "node:util";
44871
45218
  function getAgentRootDir(agentId) {
44872
- return join11(homedir12(), ".letta", "agents", agentId);
45219
+ return join12(homedir12(), ".letta", "agents", agentId);
44873
45220
  }
44874
45221
  function getMemoryRepoDir(agentId) {
44875
- return join11(getAgentRootDir(agentId), "memory");
45222
+ return join12(getAgentRootDir(agentId), "memory");
44876
45223
  }
44877
45224
  function normalizeCredentialBaseUrl(serverUrl) {
44878
45225
  const trimmed = serverUrl.trim().replace(/\/+$/, "");
@@ -44924,39 +45271,39 @@ async function configureLocalCredentialHelper(dir, token) {
44924
45271
  debugLog("memfs-git", `Configured local credential helper for ${normalizedBaseUrl}${rawBaseUrl !== normalizedBaseUrl ? ` (and raw ${rawBaseUrl})` : ""}`);
44925
45272
  }
44926
45273
  function installPreCommitHook(dir) {
44927
- const hooksDir = join11(dir, ".git", "hooks");
44928
- const hookPath = join11(hooksDir, "pre-commit");
44929
- if (!existsSync10(hooksDir)) {
44930
- mkdirSync8(hooksDir, { recursive: true });
45274
+ const hooksDir = join12(dir, ".git", "hooks");
45275
+ const hookPath = join12(hooksDir, "pre-commit");
45276
+ if (!existsSync11(hooksDir)) {
45277
+ mkdirSync9(hooksDir, { recursive: true });
44931
45278
  }
44932
- writeFileSync5(hookPath, PRE_COMMIT_HOOK_SCRIPT, "utf-8");
45279
+ writeFileSync6(hookPath, PRE_COMMIT_HOOK_SCRIPT, "utf-8");
44933
45280
  chmodSync(hookPath, 493);
44934
45281
  debugLog("memfs-git", "Installed pre-commit hook");
44935
45282
  }
44936
45283
  function isGitRepo(agentId) {
44937
- return existsSync10(join11(getMemoryRepoDir(agentId), ".git"));
45284
+ return existsSync11(join12(getMemoryRepoDir(agentId), ".git"));
44938
45285
  }
44939
45286
  async function cloneMemoryRepo(agentId) {
44940
45287
  const token = await getAuthToken();
44941
45288
  const url = getGitRemoteUrl(agentId);
44942
45289
  const dir = getMemoryRepoDir(agentId);
44943
45290
  debugLog("memfs-git", `Cloning ${url} → ${dir}`);
44944
- if (!existsSync10(dir)) {
44945
- mkdirSync8(dir, { recursive: true });
45291
+ if (!existsSync11(dir)) {
45292
+ mkdirSync9(dir, { recursive: true });
44946
45293
  await runGit(dir, ["clone", url, "."], token);
44947
- } else if (!existsSync10(join11(dir, ".git"))) {
45294
+ } else if (!existsSync11(join12(dir, ".git"))) {
44948
45295
  const tmpDir = `${dir}-git-clone-tmp`;
44949
45296
  try {
44950
- if (existsSync10(tmpDir)) {
45297
+ if (existsSync11(tmpDir)) {
44951
45298
  rmSync(tmpDir, { recursive: true, force: true });
44952
45299
  }
44953
- mkdirSync8(tmpDir, { recursive: true });
45300
+ mkdirSync9(tmpDir, { recursive: true });
44954
45301
  await runGit(tmpDir, ["clone", url, "."], token);
44955
- renameSync(join11(tmpDir, ".git"), join11(dir, ".git"));
45302
+ renameSync(join12(tmpDir, ".git"), join12(dir, ".git"));
44956
45303
  await runGit(dir, ["checkout", "--", "."], token);
44957
45304
  debugLog("memfs-git", "Migrated existing memory directory to git repo");
44958
45305
  } finally {
44959
- if (existsSync10(tmpDir)) {
45306
+ if (existsSync11(tmpDir)) {
44960
45307
  rmSync(tmpDir, { recursive: true, force: true });
44961
45308
  }
44962
45309
  }
@@ -45699,23 +46046,23 @@ __export(exports_memoryFilesystem, {
45699
46046
  MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR,
45700
46047
  MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR
45701
46048
  });
45702
- import { existsSync as existsSync11, mkdirSync as mkdirSync9 } from "node:fs";
46049
+ import { existsSync as existsSync12, mkdirSync as mkdirSync10 } from "node:fs";
45703
46050
  import { homedir as homedir13 } from "node:os";
45704
- import { join as join12 } from "node:path";
46051
+ import { join as join13 } from "node:path";
45705
46052
  function getMemoryFilesystemRoot(agentId, homeDir = homedir13()) {
45706
- return join12(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
46053
+ return join13(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
45707
46054
  }
45708
46055
  function getMemorySystemDir(agentId, homeDir = homedir13()) {
45709
- return join12(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
46056
+ return join13(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
45710
46057
  }
45711
46058
  function ensureMemoryFilesystemDirs(agentId, homeDir = homedir13()) {
45712
46059
  const root = getMemoryFilesystemRoot(agentId, homeDir);
45713
46060
  const systemDir = getMemorySystemDir(agentId, homeDir);
45714
- if (!existsSync11(root)) {
45715
- mkdirSync9(root, { recursive: true });
46061
+ if (!existsSync12(root)) {
46062
+ mkdirSync10(root, { recursive: true });
45716
46063
  }
45717
- if (!existsSync11(systemDir)) {
45718
- mkdirSync9(systemDir, { recursive: true });
46064
+ if (!existsSync12(systemDir)) {
46065
+ mkdirSync10(systemDir, { recursive: true });
45719
46066
  }
45720
46067
  }
45721
46068
  function labelFromRelativePath(relativePath) {
@@ -45883,6 +46230,10 @@ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
45883
46230
  const result = await pullMemory2(agentId);
45884
46231
  pullSummary = result.summary;
45885
46232
  }
46233
+ const { initSecretsFromServer: initSecretsFromServer2 } = await init_secretsStore().then(() => exports_secretsStore);
46234
+ try {
46235
+ await initSecretsFromServer2(agentId, getMemoryFilesystemRoot(agentId));
46236
+ } catch {}
45886
46237
  }
45887
46238
  const action = memfsFlag || shouldAutoEnableFromTag ? "enabled" : noMemfsFlag ? "disabled" : "unchanged";
45888
46239
  return {
@@ -45922,7 +46273,7 @@ __export(exports_shellEnv, {
45922
46273
  getShellEnv: () => getShellEnv,
45923
46274
  ensureLettaShimDir: () => ensureLettaShimDir
45924
46275
  });
45925
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync6 } from "node:fs";
46276
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync7 } from "node:fs";
45926
46277
  import { createRequire as createRequire2 } from "node:module";
45927
46278
  import { tmpdir } from "node:os";
45928
46279
  import * as path5 from "node:path";
@@ -45995,19 +46346,19 @@ function ensureLettaShimDir(invocation) {
45995
46346
  if (!invocation.command)
45996
46347
  return null;
45997
46348
  const shimDir = path5.join(tmpdir(), "letta-code-shell-shim");
45998
- mkdirSync10(shimDir, { recursive: true });
46349
+ mkdirSync11(shimDir, { recursive: true });
45999
46350
  if (process.platform === "win32") {
46000
46351
  const cmdPath = path5.join(shimDir, "letta.cmd");
46001
46352
  const quotedCommand = `"${invocation.command.replaceAll('"', '""')}"`;
46002
46353
  const quotedArgs = invocation.args.map((arg) => `"${arg.replaceAll('"', '""')}"`).join(" ");
46003
- writeFileSync6(cmdPath, `@echo off\r
46354
+ writeFileSync7(cmdPath, `@echo off\r
46004
46355
  ${quotedCommand} ${quotedArgs} %*\r
46005
46356
  `);
46006
46357
  return shimDir;
46007
46358
  }
46008
46359
  const shimPath = path5.join(shimDir, "letta");
46009
46360
  const commandWithArgs = [invocation.command, ...invocation.args].map(shellEscape).join(" ");
46010
- writeFileSync6(shimPath, `#!/bin/sh
46361
+ writeFileSync7(shimPath, `#!/bin/sh
46011
46362
  exec ${commandWithArgs} "$@"
46012
46363
  `, {
46013
46364
  mode: 493
@@ -47548,7 +47899,7 @@ var init_LS2 = __esm(() => {
47548
47899
 
47549
47900
  // src/tools/impl/LS.ts
47550
47901
  import { readdir as readdir2, stat } from "node:fs/promises";
47551
- import { join as join16, resolve as resolve11 } from "node:path";
47902
+ import { join as join17, resolve as resolve11 } from "node:path";
47552
47903
  async function ls(args) {
47553
47904
  validateRequiredParams(args, ["path"], "LS");
47554
47905
  validateParamTypes(args, LS_default2, "LS");
@@ -47558,7 +47909,7 @@ async function ls(args) {
47558
47909
  const items = await readdir2(dirPath);
47559
47910
  const filteredItems = items.filter((item) => !ignore.some((pattern) => import_picomatch2.default.isMatch(item, pattern)));
47560
47911
  const fileInfos = await Promise.all(filteredItems.map(async (item) => {
47561
- const fullPath = join16(dirPath, item);
47912
+ const fullPath = join17(dirPath, item);
47562
47913
  try {
47563
47914
  const stats = await stat(fullPath);
47564
47915
  return {
@@ -47910,7 +48261,7 @@ var init_runtime = () => {};
47910
48261
 
47911
48262
  // src/tools/impl/Memory.ts
47912
48263
  import { execFile as execFileCb2 } from "node:child_process";
47913
- import { existsSync as existsSync13 } from "node:fs";
48264
+ import { existsSync as existsSync14 } from "node:fs";
47914
48265
  import {
47915
48266
  mkdir as mkdir2,
47916
48267
  readFile as readFile3,
@@ -47921,7 +48272,7 @@ import {
47921
48272
  writeFile as writeFile2
47922
48273
  } from "node:fs/promises";
47923
48274
  import { homedir as homedir15 } from "node:os";
47924
- import { dirname as dirname5, isAbsolute as isAbsolute8, relative as relative5, resolve as resolve12 } from "node:path";
48275
+ import { dirname as dirname6, isAbsolute as isAbsolute8, relative as relative5, resolve as resolve12 } from "node:path";
47925
48276
  import { promisify as promisify9 } from "node:util";
47926
48277
  async function getAgentIdentity() {
47927
48278
  const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
@@ -47963,14 +48314,14 @@ async function memory(args) {
47963
48314
  const label = normalizeMemoryLabel(memoryDir, pathArg, "path");
47964
48315
  const filePath = resolveMemoryFilePath(memoryDir, label);
47965
48316
  const relPath = toRepoRelative(memoryDir, filePath);
47966
- if (existsSync13(filePath)) {
48317
+ if (existsSync14(filePath)) {
47967
48318
  throw new Error(`memory create: block already exists at ${pathArg}`);
47968
48319
  }
47969
48320
  const body = args.file_text ?? "";
47970
48321
  const rendered = renderMemoryFile({
47971
48322
  description
47972
48323
  }, body);
47973
- await mkdir2(dirname5(filePath), { recursive: true });
48324
+ await mkdir2(dirname6(filePath), { recursive: true });
47974
48325
  await writeFile2(filePath, rendered, "utf8");
47975
48326
  affectedPaths = [relPath];
47976
48327
  } else if (command === "str_replace") {
@@ -48015,7 +48366,7 @@ async function memory(args) {
48015
48366
  const pathArg = requireString(args.path, "path", "delete");
48016
48367
  const label = normalizeMemoryLabel(memoryDir, pathArg, "path");
48017
48368
  const targetPath = resolveMemoryPath(memoryDir, label);
48018
- if (existsSync13(targetPath) && (await stat2(targetPath)).isDirectory()) {
48369
+ if (existsSync14(targetPath) && (await stat2(targetPath)).isDirectory()) {
48019
48370
  const relPath = toRepoRelative(memoryDir, targetPath);
48020
48371
  await rm(targetPath, { recursive: true, force: false });
48021
48372
  affectedPaths = [relPath];
@@ -48035,11 +48386,11 @@ async function memory(args) {
48035
48386
  const newFilePath = resolveMemoryFilePath(memoryDir, newLabel);
48036
48387
  const oldRelPath = toRepoRelative(memoryDir, oldFilePath);
48037
48388
  const newRelPath = toRepoRelative(memoryDir, newFilePath);
48038
- if (existsSync13(newFilePath)) {
48389
+ if (existsSync14(newFilePath)) {
48039
48390
  throw new Error(`memory rename: destination already exists at ${newPathArg}`);
48040
48391
  }
48041
48392
  await loadEditableMemoryFile(oldFilePath, oldPathArg);
48042
- await mkdir2(dirname5(newFilePath), { recursive: true });
48393
+ await mkdir2(dirname6(newFilePath), { recursive: true });
48043
48394
  await rename(oldFilePath, newFilePath);
48044
48395
  affectedPaths = [oldRelPath, newRelPath];
48045
48396
  } else if (command === "update_description") {
@@ -48092,10 +48443,10 @@ function resolveMemoryDir() {
48092
48443
  throw new Error("memory: unable to resolve memory directory. Ensure MEMORY_DIR (or AGENT_ID) is available.");
48093
48444
  }
48094
48445
  function ensureMemoryRepo(memoryDir) {
48095
- if (!existsSync13(memoryDir)) {
48446
+ if (!existsSync14(memoryDir)) {
48096
48447
  throw new Error(`memory: memory directory does not exist: ${memoryDir}`);
48097
48448
  }
48098
- if (!existsSync13(resolve12(memoryDir, ".git"))) {
48449
+ if (!existsSync14(resolve12(memoryDir, ".git"))) {
48099
48450
  throw new Error(`memory: ${memoryDir} is not a git repository. This tool requires a git-backed memory filesystem.`);
48100
48451
  }
48101
48452
  }
@@ -48325,7 +48676,7 @@ var init_Memory2 = __esm(async () => {
48325
48676
 
48326
48677
  // src/tools/impl/MemoryApplyPatch.ts
48327
48678
  import { execFile as execFileCb3 } from "node:child_process";
48328
- import { existsSync as existsSync14 } from "node:fs";
48679
+ import { existsSync as existsSync15 } from "node:fs";
48329
48680
  import {
48330
48681
  access,
48331
48682
  mkdir as mkdir3,
@@ -48336,7 +48687,7 @@ import {
48336
48687
  writeFile as writeFile3
48337
48688
  } from "node:fs/promises";
48338
48689
  import { homedir as homedir16 } from "node:os";
48339
- import { dirname as dirname6, isAbsolute as isAbsolute9, relative as relative6, resolve as resolve13 } from "node:path";
48690
+ import { dirname as dirname7, isAbsolute as isAbsolute9, relative as relative6, resolve as resolve13 } from "node:path";
48340
48691
  import { promisify as promisify10 } from "node:util";
48341
48692
  async function getAgentIdentity2() {
48342
48693
  const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
@@ -48449,7 +48800,7 @@ async function memory_apply_patch(args) {
48449
48800
  }
48450
48801
  }
48451
48802
  for (const [absPath, content] of pendingWrites.entries()) {
48452
- await mkdir3(dirname6(absPath), { recursive: true });
48803
+ await mkdir3(dirname7(absPath), { recursive: true });
48453
48804
  await writeFile3(absPath, content, "utf8");
48454
48805
  }
48455
48806
  for (const absPath of pendingDeletes) {
@@ -48628,10 +48979,10 @@ function resolveMemoryDir2() {
48628
48979
  throw new Error("memory_apply_patch: unable to resolve memory directory. Ensure MEMORY_DIR (or AGENT_ID) is available.");
48629
48980
  }
48630
48981
  function ensureMemoryRepo2(memoryDir) {
48631
- if (!existsSync14(memoryDir)) {
48982
+ if (!existsSync15(memoryDir)) {
48632
48983
  throw new Error(`memory_apply_patch: memory directory does not exist: ${memoryDir}`);
48633
48984
  }
48634
- if (!existsSync14(resolve13(memoryDir, ".git"))) {
48985
+ if (!existsSync15(resolve13(memoryDir, ".git"))) {
48635
48986
  throw new Error(`memory_apply_patch: ${memoryDir} is not a git repository. This tool requires a git-backed memory filesystem.`);
48636
48987
  }
48637
48988
  }
@@ -48984,12 +49335,12 @@ __export(exports_imageResize_magick, {
48984
49335
  MAX_IMAGE_BYTES: () => MAX_IMAGE_BYTES
48985
49336
  });
48986
49337
  import { execSync } from "node:child_process";
48987
- import { readFileSync as readFileSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "node:fs";
49338
+ import { readFileSync as readFileSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync9 } from "node:fs";
48988
49339
  import { tmpdir as tmpdir2 } from "node:os";
48989
- import { join as join17 } from "node:path";
49340
+ import { join as join18 } from "node:path";
48990
49341
  async function getImageDimensions(buffer) {
48991
- const tempInput = join17(tmpdir2(), `image-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
48992
- writeFileSync8(tempInput, buffer);
49342
+ const tempInput = join18(tmpdir2(), `image-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
49343
+ writeFileSync9(tempInput, buffer);
48993
49344
  try {
48994
49345
  const output = execSync(`magick identify -format "%w %h %m" "${tempInput}"`, {
48995
49346
  encoding: "utf-8"
@@ -49011,12 +49362,12 @@ async function compressToFitByteLimit(buffer, currentWidth, currentHeight) {
49011
49362
  if (buffer.length <= MAX_IMAGE_BYTES) {
49012
49363
  return null;
49013
49364
  }
49014
- const tempInput = join17(tmpdir2(), `compress-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
49015
- writeFileSync8(tempInput, buffer);
49365
+ const tempInput = join18(tmpdir2(), `compress-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
49366
+ writeFileSync9(tempInput, buffer);
49016
49367
  try {
49017
49368
  const qualities = [85, 70, 55, 40];
49018
49369
  for (const quality of qualities) {
49019
- const tempOutput = join17(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
49370
+ const tempOutput = join18(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
49020
49371
  try {
49021
49372
  execSync(`magick "${tempInput}" -quality ${quality} "${tempOutput}"`, {
49022
49373
  stdio: "ignore"
@@ -49042,7 +49393,7 @@ async function compressToFitByteLimit(buffer, currentWidth, currentHeight) {
49042
49393
  for (const scale of scales) {
49043
49394
  const scaledWidth = Math.floor(currentWidth * scale);
49044
49395
  const scaledHeight = Math.floor(currentHeight * scale);
49045
- const tempOutput = join17(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
49396
+ const tempOutput = join18(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
49046
49397
  try {
49047
49398
  execSync(`magick "${tempInput}" -resize ${scaledWidth}x${scaledHeight} -quality 70 "${tempOutput}"`, {
49048
49399
  stdio: "ignore"
@@ -49086,11 +49437,11 @@ async function resizeImageIfNeeded(buffer, inputMediaType) {
49086
49437
  resized: false
49087
49438
  };
49088
49439
  }
49089
- const tempInput = join17(tmpdir2(), `resize-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
49090
- writeFileSync8(tempInput, buffer);
49440
+ const tempInput = join18(tmpdir2(), `resize-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
49441
+ writeFileSync9(tempInput, buffer);
49091
49442
  try {
49092
49443
  if (needsResize) {
49093
- const tempOutput2 = join17(tmpdir2(), `resize-output-${Date.now()}-${Math.random().toString(36).slice(2)}`);
49444
+ const tempOutput2 = join18(tmpdir2(), `resize-output-${Date.now()}-${Math.random().toString(36).slice(2)}`);
49094
49445
  let outputBuffer2;
49095
49446
  let outputMediaType;
49096
49447
  if (format2 === "jpeg" || format2 === "jpg") {
@@ -49121,7 +49472,7 @@ async function resizeImageIfNeeded(buffer, inputMediaType) {
49121
49472
  resized: true
49122
49473
  };
49123
49474
  }
49124
- const tempOutput = join17(tmpdir2(), `convert-output-${Date.now()}-${Math.random().toString(36).slice(2)}.png`);
49475
+ const tempOutput = join18(tmpdir2(), `convert-output-${Date.now()}-${Math.random().toString(36).slice(2)}.png`);
49125
49476
  execSync(`magick "${tempInput}" "${tempOutput}"`, {
49126
49477
  stdio: "ignore"
49127
49478
  });
@@ -61282,8 +61633,8 @@ var init_ignore = __esm(() => {
61282
61633
  // node_modules/glob/dist/esm/processor.js
61283
61634
  class HasWalkedCache {
61284
61635
  store;
61285
- constructor(store = new Map) {
61286
- this.store = store;
61636
+ constructor(store2 = new Map) {
61637
+ this.store = store2;
61287
61638
  }
61288
61639
  copy() {
61289
61640
  return new HasWalkedCache(new Map(this.store));
@@ -62184,7 +62535,7 @@ var init_ReplaceGemini2 = __esm(() => {
62184
62535
  });
62185
62536
 
62186
62537
  // src/tools/impl/Shell.ts
62187
- import { existsSync as existsSync15, statSync as statSync4 } from "node:fs";
62538
+ import { existsSync as existsSync16, statSync as statSync4 } from "node:fs";
62188
62539
  import * as path16 from "node:path";
62189
62540
  async function runProcess(context3) {
62190
62541
  const { stdout, stderr, exitCode } = await spawnWithLauncher(context3.command, {
@@ -62272,7 +62623,7 @@ function arraysEqual(a, b) {
62272
62623
  }
62273
62624
  function isUsableDirectory(candidate) {
62274
62625
  try {
62275
- return existsSync15(candidate) && statSync4(candidate).isDirectory();
62626
+ return existsSync16(candidate) && statSync4(candidate).isDirectory();
62276
62627
  } catch {
62277
62628
  return false;
62278
62629
  }
@@ -62423,22 +62774,22 @@ __export(exports_skills, {
62423
62774
  SKILLS_DIR: () => SKILLS_DIR,
62424
62775
  GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR
62425
62776
  });
62426
- import { existsSync as existsSync16 } from "node:fs";
62777
+ import { existsSync as existsSync17 } from "node:fs";
62427
62778
  import { readdir as readdir4, readFile as readFile5, realpath as realpath2, stat as stat4 } from "node:fs/promises";
62428
- import { dirname as dirname7, join as join18 } from "node:path";
62779
+ import { dirname as dirname8, join as join19 } from "node:path";
62429
62780
  import { fileURLToPath as fileURLToPath7 } from "node:url";
62430
62781
  function getBundledSkillsPath() {
62431
- const thisDir = dirname7(fileURLToPath7(import.meta.url));
62782
+ const thisDir = dirname8(fileURLToPath7(import.meta.url));
62432
62783
  if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
62433
- return join18(thisDir, "../skills/builtin");
62784
+ return join19(thisDir, "../skills/builtin");
62434
62785
  }
62435
- return join18(thisDir, "skills");
62786
+ return join19(thisDir, "skills");
62436
62787
  }
62437
62788
  function compareSkills(a, b) {
62438
62789
  return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
62439
62790
  }
62440
62791
  function getAgentSkillsDir(agentId) {
62441
- return join18(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
62792
+ return join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
62442
62793
  }
62443
62794
  async function getBundledSkills() {
62444
62795
  const bundledPath = getBundledSkillsPath();
@@ -62447,7 +62798,7 @@ async function getBundledSkills() {
62447
62798
  }
62448
62799
  async function discoverSkillsFromDir(skillsPath, source) {
62449
62800
  const errors = [];
62450
- if (!existsSync16(skillsPath)) {
62801
+ if (!existsSync17(skillsPath)) {
62451
62802
  return { skills: [], errors: [] };
62452
62803
  }
62453
62804
  const skills = [];
@@ -62461,7 +62812,7 @@ async function discoverSkillsFromDir(skillsPath, source) {
62461
62812
  }
62462
62813
  return { skills, errors };
62463
62814
  }
62464
- async function discoverSkills(projectSkillsPath = join18(process.cwd(), SKILLS_DIR), agentId, options) {
62815
+ async function discoverSkills(projectSkillsPath = join19(process.cwd(), SKILLS_DIR), agentId, options) {
62465
62816
  const allErrors = [];
62466
62817
  const skillsById = new Map;
62467
62818
  const sourceSet = new Set(options?.sources ?? ALL_SKILL_SOURCES);
@@ -62516,7 +62867,7 @@ async function findSkillFiles(currentPath, rootPath, skills, errors, source, vis
62516
62867
  try {
62517
62868
  const entries = await readdir4(currentPath, { withFileTypes: true });
62518
62869
  for (const entry of entries) {
62519
- const fullPath = join18(currentPath, entry.name);
62870
+ const fullPath = join19(currentPath, entry.name);
62520
62871
  try {
62521
62872
  let isDirectory = entry.isDirectory();
62522
62873
  let isFile = entry.isFile();
@@ -62605,7 +62956,7 @@ ${lines.join(`
62605
62956
  var SKILLS_DIR = ".skills", GLOBAL_SKILLS_DIR;
62606
62957
  var init_skills = __esm(() => {
62607
62958
  init_skillSources();
62608
- GLOBAL_SKILLS_DIR = join18(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
62959
+ GLOBAL_SKILLS_DIR = join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
62609
62960
  });
62610
62961
 
62611
62962
  // src/tools/impl/skillContentRegistry.ts
@@ -62630,10 +62981,10 @@ var init_skillContentRegistry = __esm(() => {
62630
62981
  // src/tools/impl/Skill.ts
62631
62982
  import { readdirSync as readdirSync7 } from "node:fs";
62632
62983
  import { readFile as readFile6 } from "node:fs/promises";
62633
- import { dirname as dirname8, join as join19 } from "node:path";
62984
+ import { dirname as dirname9, join as join20 } from "node:path";
62634
62985
  function hasAdditionalFiles(skillMdPath) {
62635
62986
  try {
62636
- const skillDir = dirname8(skillMdPath);
62987
+ const skillDir = dirname9(skillMdPath);
62637
62988
  const entries = readdirSync7(skillDir);
62638
62989
  return entries.some((e) => e.toUpperCase() !== "SKILL.MD");
62639
62990
  } catch {
@@ -62641,19 +62992,19 @@ function hasAdditionalFiles(skillMdPath) {
62641
62992
  }
62642
62993
  }
62643
62994
  async function readSkillContent(skillId, skillsDir, agentId) {
62644
- const projectSkillPath = join19(skillsDir, skillId, "SKILL.md");
62995
+ const projectSkillPath = join20(skillsDir, skillId, "SKILL.md");
62645
62996
  try {
62646
62997
  const content = await readFile6(projectSkillPath, "utf-8");
62647
62998
  return { content, path: projectSkillPath };
62648
62999
  } catch {}
62649
63000
  if (agentId) {
62650
- const agentSkillPath = join19(getAgentSkillsDir(agentId), skillId, "SKILL.md");
63001
+ const agentSkillPath = join20(getAgentSkillsDir(agentId), skillId, "SKILL.md");
62651
63002
  try {
62652
63003
  const content = await readFile6(agentSkillPath, "utf-8");
62653
63004
  return { content, path: agentSkillPath };
62654
63005
  } catch {}
62655
63006
  }
62656
- const globalSkillPath = join19(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
63007
+ const globalSkillPath = join20(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
62657
63008
  try {
62658
63009
  const content = await readFile6(globalSkillPath, "utf-8");
62659
63010
  return { content, path: globalSkillPath };
@@ -62667,8 +63018,8 @@ async function readSkillContent(skillId, skillsDir, agentId) {
62667
63018
  } catch {}
62668
63019
  }
62669
63020
  try {
62670
- const bundledSkillsDir = join19(process.cwd(), "skills", "skills");
62671
- const bundledSkillPath = join19(bundledSkillsDir, skillId, "SKILL.md");
63021
+ const bundledSkillsDir = join20(process.cwd(), "skills", "skills");
63022
+ const bundledSkillPath = join20(bundledSkillsDir, skillId, "SKILL.md");
62672
63023
  const content = await readFile6(bundledSkillPath, "utf-8");
62673
63024
  return { content, path: bundledSkillPath };
62674
63025
  } catch {
@@ -62680,7 +63031,7 @@ async function getResolvedSkillsDir() {
62680
63031
  if (skillsDir) {
62681
63032
  return skillsDir;
62682
63033
  }
62683
- return join19(process.cwd(), SKILLS_DIR);
63034
+ return join20(process.cwd(), SKILLS_DIR);
62684
63035
  }
62685
63036
  async function skill(args) {
62686
63037
  validateRequiredParams(args, ["skill"], "Skill");
@@ -62692,7 +63043,7 @@ async function skill(args) {
62692
63043
  const agentId = getCurrentAgentId();
62693
63044
  const skillsDir = await getResolvedSkillsDir();
62694
63045
  const { content: skillContent, path: skillPath } = await readSkillContent(skillName, skillsDir, agentId);
62695
- const skillDir = dirname8(skillPath);
63046
+ const skillDir = dirname9(skillPath);
62696
63047
  const hasExtras = hasAdditionalFiles(skillPath);
62697
63048
  const processedContent = hasExtras ? skillContent.replace(/<SKILL_DIR>/g, skillDir) : skillContent;
62698
63049
  const dirHeader = hasExtras ? `# Skill Directory: ${skillDir}
@@ -62718,174 +63069,6 @@ var init_Skill2 = __esm(() => {
62718
63069
  init_skillContentRegistry();
62719
63070
  });
62720
63071
 
62721
- // src/cli/helpers/subagentState.ts
62722
- function updateSnapshot() {
62723
- cachedSnapshot = {
62724
- agents: Array.from(store.agents.values()),
62725
- expanded: store.expanded
62726
- };
62727
- }
62728
- function notifyListeners() {
62729
- updateSnapshot();
62730
- for (const listener of store.listeners) {
62731
- listener();
62732
- }
62733
- }
62734
- function generateSubagentId() {
62735
- return `subagent-${Date.now()}-${++subagentCounter}`;
62736
- }
62737
- function getSubagentByToolCallId(toolCallId) {
62738
- for (const agent of store.agents.values()) {
62739
- if (agent.toolCallId === toolCallId) {
62740
- return agent;
62741
- }
62742
- }
62743
- return;
62744
- }
62745
- function registerSubagent(id, type, description, toolCallId, isBackground, silent) {
62746
- const displayType = type.charAt(0).toUpperCase() + type.slice(1);
62747
- const agent = {
62748
- id,
62749
- type: displayType,
62750
- description,
62751
- status: "pending",
62752
- agentURL: null,
62753
- toolCalls: [],
62754
- maxToolCallsSeen: 0,
62755
- totalTokens: 0,
62756
- durationMs: 0,
62757
- startTime: Date.now(),
62758
- toolCallId,
62759
- isBackground,
62760
- silent
62761
- };
62762
- store.agents.set(id, agent);
62763
- notifyListeners();
62764
- }
62765
- function updateSubagent(id, updates) {
62766
- const agent = store.agents.get(id);
62767
- if (!agent)
62768
- return;
62769
- if (updates.agentURL && agent.status === "pending") {
62770
- updates.status = "running";
62771
- }
62772
- const nextToolCalls = updates.toolCalls ?? agent.toolCalls;
62773
- const nextMax = Math.max(agent.maxToolCallsSeen, nextToolCalls.length, updates.maxToolCallsSeen ?? 0);
62774
- const keys = Object.keys(updates);
62775
- const isNoop = keys.every((k) => agent[k] === updates[k]) && nextMax === agent.maxToolCallsSeen;
62776
- if (isNoop)
62777
- return;
62778
- const updatedAgent = { ...agent, ...updates, maxToolCallsSeen: nextMax };
62779
- store.agents.set(id, updatedAgent);
62780
- notifyListeners();
62781
- }
62782
- function addToolCall(subagentId, toolCallId, toolName, toolArgs) {
62783
- const agent = store.agents.get(subagentId);
62784
- if (!agent)
62785
- return;
62786
- if (agent.toolCalls.some((tc) => tc.id === toolCallId))
62787
- return;
62788
- const updatedAgent = {
62789
- ...agent,
62790
- toolCalls: [
62791
- ...agent.toolCalls,
62792
- { id: toolCallId, name: toolName, args: toolArgs }
62793
- ],
62794
- maxToolCallsSeen: Math.max(agent.maxToolCallsSeen, agent.toolCalls.length + 1)
62795
- };
62796
- store.agents.set(subagentId, updatedAgent);
62797
- notifyListeners();
62798
- }
62799
- function completeSubagent(id, result) {
62800
- const agent = store.agents.get(id);
62801
- if (!agent)
62802
- return;
62803
- const updatedAgent = {
62804
- ...agent,
62805
- status: result.success ? "completed" : "error",
62806
- error: result.error,
62807
- durationMs: Date.now() - agent.startTime,
62808
- totalTokens: result.totalTokens ?? agent.totalTokens,
62809
- maxToolCallsSeen: Math.max(agent.maxToolCallsSeen, agent.toolCalls.length)
62810
- };
62811
- store.agents.set(id, updatedAgent);
62812
- notifyListeners();
62813
- }
62814
- function getSubagentToolCount(agent) {
62815
- return Math.max(agent.toolCalls.length, agent.maxToolCallsSeen);
62816
- }
62817
- function toggleExpanded() {
62818
- store.expanded = !store.expanded;
62819
- notifyListeners();
62820
- }
62821
- function getSubagents() {
62822
- return Array.from(store.agents.values());
62823
- }
62824
- function getActiveBackgroundAgents() {
62825
- return Array.from(store.agents.values()).filter((a) => a.silent === true && (a.status === "pending" || a.status === "running"));
62826
- }
62827
- function clearCompletedSubagents() {
62828
- for (const [id, agent] of store.agents.entries()) {
62829
- if (agent.status === "completed" || agent.status === "error") {
62830
- store.agents.delete(id);
62831
- }
62832
- }
62833
- notifyListeners();
62834
- }
62835
- function clearSubagentsByIds(ids) {
62836
- for (const id of ids) {
62837
- store.agents.delete(id);
62838
- }
62839
- notifyListeners();
62840
- }
62841
- function hasActiveSubagents() {
62842
- for (const agent of store.agents.values()) {
62843
- if (agent.status === "pending" || agent.status === "running") {
62844
- return true;
62845
- }
62846
- }
62847
- return false;
62848
- }
62849
- function interruptActiveSubagents(errorMessage) {
62850
- let anyInterrupted = false;
62851
- for (const [id, agent] of store.agents.entries()) {
62852
- if (agent.status === "pending" || agent.status === "running") {
62853
- const updatedAgent = {
62854
- ...agent,
62855
- status: "error",
62856
- error: errorMessage,
62857
- durationMs: Date.now() - agent.startTime
62858
- };
62859
- store.agents.set(id, updatedAgent);
62860
- anyInterrupted = true;
62861
- }
62862
- }
62863
- if (anyInterrupted) {
62864
- notifyListeners();
62865
- }
62866
- }
62867
- function subscribe2(listener) {
62868
- store.listeners.add(listener);
62869
- return () => {
62870
- store.listeners.delete(listener);
62871
- };
62872
- }
62873
- function getSnapshot2() {
62874
- return cachedSnapshot;
62875
- }
62876
- var store, cachedSnapshot, subagentCounter = 0;
62877
- var init_subagentState = __esm(() => {
62878
- store = {
62879
- agents: new Map,
62880
- expanded: false,
62881
- listeners: new Set
62882
- };
62883
- cachedSnapshot = {
62884
- agents: [],
62885
- expanded: false
62886
- };
62887
- });
62888
-
62889
63072
  // src/permissions/canonical.ts
62890
63073
  function canonicalToolName(toolName) {
62891
63074
  if (SHELL_TOOL_NAMES.has(toolName))
@@ -63279,6 +63462,8 @@ function processStreamEvent(line, state, subagentId) {
63279
63462
  case "message":
63280
63463
  if (event.message_type === "approval_request_message") {
63281
63464
  handleApprovalRequestEvent(event, state);
63465
+ } else {
63466
+ emitStreamEvent(subagentId, event);
63282
63467
  }
63283
63468
  break;
63284
63469
  case "auto_approval":
@@ -63632,31 +63817,6 @@ var init_manager2 = __esm(async () => {
63632
63817
  };
63633
63818
  });
63634
63819
 
63635
- // src/cli/helpers/messageQueueBridge.ts
63636
- function setMessageQueueAdder(fn) {
63637
- queueAdder = fn;
63638
- if (queueAdder && pendingMessages.length > 0) {
63639
- for (const message of pendingMessages) {
63640
- queueAdder(message);
63641
- }
63642
- pendingMessages.length = 0;
63643
- }
63644
- }
63645
- function addToMessageQueue(message) {
63646
- if (queueAdder) {
63647
- queueAdder(message);
63648
- return;
63649
- }
63650
- if (pendingMessages.length >= MAX_PENDING_MESSAGES) {
63651
- pendingMessages.shift();
63652
- }
63653
- pendingMessages.push(message);
63654
- }
63655
- var queueAdder = null, pendingMessages, MAX_PENDING_MESSAGES = 10;
63656
- var init_messageQueueBridge = __esm(() => {
63657
- pendingMessages = [];
63658
- });
63659
-
63660
63820
  // src/cli/helpers/taskNotifications.ts
63661
63821
  function escapeXml(str) {
63662
63822
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -63737,11 +63897,13 @@ __export(exports_Task, {
63737
63897
  task: () => task,
63738
63898
  spawnBackgroundSubagentTask: () => spawnBackgroundSubagentTask
63739
63899
  });
63740
- function buildTaskResultHeader(subagentType, result) {
63900
+ function buildTaskResultHeader(subagentType, subagentId, result, status) {
63741
63901
  return [
63742
63902
  `subagent_type=${subagentType}`,
63743
- result.agentId ? `agent_id=${result.agentId}` : undefined,
63744
- result.conversationId ? `conversation_id=${result.conversationId}` : undefined
63903
+ `subagent_id=${subagentId}`,
63904
+ status ? `subagent_status=${status}` : undefined,
63905
+ result?.agentId ? `agent_id=${result.agentId}` : undefined,
63906
+ result?.conversationId ? `conversation_id=${result.conversationId}` : undefined
63745
63907
  ].filter(Boolean).join(" ");
63746
63908
  }
63747
63909
  function writeTaskTranscriptStart(outputFile, description, subagentType) {
@@ -63760,7 +63922,9 @@ ${result.report}
63760
63922
  `);
63761
63923
  return;
63762
63924
  }
63763
- appendToOutputFile(outputFile, `[error] ${result.error || "Subagent execution failed"}
63925
+ appendToOutputFile(outputFile, `${header ? `${header}
63926
+
63927
+ ` : ""}[error] ${result.error || "Subagent execution failed"}
63764
63928
 
63765
63929
  [Task failed]
63766
63930
  `);
@@ -63800,6 +63964,7 @@ function spawnBackgroundSubagentTask(args) {
63800
63964
  existingAgentId,
63801
63965
  existingConversationId,
63802
63966
  maxTurns,
63967
+ parentScope,
63803
63968
  silentCompletion,
63804
63969
  onComplete,
63805
63970
  deps
@@ -63834,7 +63999,7 @@ function spawnBackgroundSubagentTask(args) {
63834
63999
  if (result.error) {
63835
64000
  bgTask.error = result.error;
63836
64001
  }
63837
- const header = buildTaskResultHeader(subagentType, result);
64002
+ const header = buildTaskResultHeader(subagentType, subagentId, result, result.success ? "success" : "error");
63838
64003
  writeTaskTranscriptResult(outputFile, result, header);
63839
64004
  if (result.success) {
63840
64005
  bgTask.output.push(result.report || "");
@@ -63857,7 +64022,9 @@ function spawnBackgroundSubagentTask(args) {
63857
64022
  const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
63858
64023
  const fullResult = result.success ? `${header}
63859
64024
 
63860
- ${result.report || ""}` : result.error || "Subagent execution failed";
64025
+ ${result.report || ""}` : `${header}
64026
+
64027
+ Error: ${result.error || "Subagent execution failed"}`;
63861
64028
  const userCwd = process.env.USER_CWD || process.cwd();
63862
64029
  const { content: truncatedResult } = truncateByChars(fullResult, LIMITS.TASK_OUTPUT_CHARS, "Task", { workingDirectory: userCwd, toolName: "Task" });
63863
64030
  const notificationXml = formatTaskNotificationFn({
@@ -63874,7 +64041,9 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
63874
64041
  });
63875
64042
  addToMessageQueueFn({
63876
64043
  kind: "task_notification",
63877
- text: notificationXml
64044
+ text: notificationXml,
64045
+ agentId: parentScope?.agentId,
64046
+ conversationId: parentScope?.conversationId
63878
64047
  });
63879
64048
  }
63880
64049
  runSubagentStopHooksFn(subagentType, subagentId, result.success, result.error, result.agentId, result.conversationId).catch(() => {});
@@ -63896,11 +64065,17 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
63896
64065
  const subagentSnapshot = getSubagentSnapshotFn();
63897
64066
  const subagentEntry = subagentSnapshot.agents.find((agent) => agent.id === subagentId);
63898
64067
  const durationMs = Math.max(0, Date.now() - bgTask.startTime.getTime());
64068
+ const header = buildTaskResultHeader(subagentType, subagentId, {
64069
+ agentId: existingAgentId ?? "",
64070
+ conversationId: existingConversationId
64071
+ }, "error");
63899
64072
  const notificationXml = formatTaskNotificationFn({
63900
64073
  taskId,
63901
64074
  status: "failed",
63902
64075
  summary: `Agent "${description}" failed`,
63903
- result: errorMessage,
64076
+ result: `${header}
64077
+
64078
+ Error: ${errorMessage}`,
63904
64079
  outputFile,
63905
64080
  usage: {
63906
64081
  toolUses: subagentEntry === undefined ? undefined : getSubagentToolCount(subagentEntry),
@@ -63909,7 +64084,9 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
63909
64084
  });
63910
64085
  addToMessageQueueFn({
63911
64086
  kind: "task_notification",
63912
- text: notificationXml
64087
+ text: notificationXml,
64088
+ agentId: parentScope?.agentId,
64089
+ conversationId: parentScope?.conversationId
63913
64090
  });
63914
64091
  }
63915
64092
  runSubagentStopHooksFn(subagentType, subagentId, false, errorMessage, existingAgentId, existingConversationId).catch(() => {});
@@ -63960,7 +64137,8 @@ async function task(args) {
63960
64137
  toolCallId,
63961
64138
  existingAgentId: args.agent_id,
63962
64139
  existingConversationId: args.conversation_id,
63963
- maxTurns: args.max_turns
64140
+ maxTurns: args.max_turns,
64141
+ parentScope: args.parentScope
63964
64142
  });
63965
64143
  await waitForBackgroundSubagentLink(subagentId2, null, signal);
63966
64144
  const linkedAgent = getSnapshot2().agents.find((a) => a.id === subagentId2);
@@ -63991,11 +64169,14 @@ You will be notified automatically when this task completes — a <task-notifica
63991
64169
  ...result,
63992
64170
  error: errorMessage
63993
64171
  };
63994
- writeTaskTranscriptResult(outputFile, failedResult, "");
63995
- return `Error: ${errorMessage}
64172
+ const header2 = buildTaskResultHeader(subagent_type, subagentId, failedResult, "error");
64173
+ writeTaskTranscriptResult(outputFile, failedResult, header2);
64174
+ return `${header2}
64175
+
64176
+ Error: ${errorMessage}
63996
64177
  Output file: ${outputFile}`;
63997
64178
  }
63998
- const header = buildTaskResultHeader(subagent_type, result);
64179
+ const header = buildTaskResultHeader(subagent_type, subagentId, result, "success");
63999
64180
  const fullOutput = `${header}
64000
64181
 
64001
64182
  ${result.report}`;
@@ -64006,13 +64187,21 @@ ${result.report}`;
64006
64187
  Output file: ${outputFile}`;
64007
64188
  } catch (error) {
64008
64189
  const errorMessage = error instanceof Error ? error.message : String(error);
64190
+ const header = buildTaskResultHeader(subagent_type, subagentId, {
64191
+ agentId: args.agent_id ?? "",
64192
+ conversationId: args.conversation_id
64193
+ }, "error");
64009
64194
  completeSubagent(subagentId, { success: false, error: errorMessage });
64010
64195
  runSubagentStopHooks(subagent_type, subagentId, false, errorMessage, args.agent_id, args.conversation_id).catch(() => {});
64011
- appendToOutputFile(outputFile, `[error] ${errorMessage}
64196
+ appendToOutputFile(outputFile, `${header}
64197
+
64198
+ [error] ${errorMessage}
64012
64199
 
64013
64200
  [Task failed]
64014
64201
  `);
64015
- return `Error: ${errorMessage}
64202
+ return `${header}
64203
+
64204
+ Error: ${errorMessage}
64016
64205
  Output file: ${outputFile}`;
64017
64206
  }
64018
64207
  }
@@ -67675,13 +67864,13 @@ __export(exports_loader, {
67675
67864
  getUserSettingsPaths: () => getUserSettingsPaths
67676
67865
  });
67677
67866
  import { homedir as homedir17 } from "node:os";
67678
- import { join as join20 } from "node:path";
67867
+ import { join as join21 } from "node:path";
67679
67868
  function getUserSettingsPaths(options = {}) {
67680
67869
  const homeDir = options.homeDir || homedir17();
67681
- const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join20(homeDir, ".config");
67870
+ const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join21(homeDir, ".config");
67682
67871
  return {
67683
- canonical: join20(homeDir, ".letta", "settings.json"),
67684
- legacy: join20(xdgConfigHome, "letta", "settings.json")
67872
+ canonical: join21(homeDir, ".letta", "settings.json"),
67873
+ legacy: join21(xdgConfigHome, "letta", "settings.json")
67685
67874
  };
67686
67875
  }
67687
67876
  async function loadPermissions(workingDirectory = process.cwd()) {
@@ -67695,8 +67884,8 @@ async function loadPermissions(workingDirectory = process.cwd()) {
67695
67884
  const sources = [
67696
67885
  legacyUserSettingsPath,
67697
67886
  userSettingsPath,
67698
- join20(workingDirectory, ".letta", "settings.json"),
67699
- join20(workingDirectory, ".letta", "settings.local.json")
67887
+ join21(workingDirectory, ".letta", "settings.json"),
67888
+ join21(workingDirectory, ".letta", "settings.local.json")
67700
67889
  ];
67701
67890
  for (const settingsPath of sources) {
67702
67891
  try {
@@ -67744,10 +67933,10 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
67744
67933
  settingsPath = getUserSettingsPaths().canonical;
67745
67934
  break;
67746
67935
  case "project":
67747
- settingsPath = join20(workingDirectory, ".letta", "settings.json");
67936
+ settingsPath = join21(workingDirectory, ".letta", "settings.json");
67748
67937
  break;
67749
67938
  case "local":
67750
- settingsPath = join20(workingDirectory, ".letta", "settings.local.json");
67939
+ settingsPath = join21(workingDirectory, ".letta", "settings.local.json");
67751
67940
  break;
67752
67941
  }
67753
67942
  let settings = {};
@@ -67773,7 +67962,7 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
67773
67962
  }
67774
67963
  }
67775
67964
  async function ensureLocalSettingsIgnored(workingDirectory) {
67776
- const gitignorePath = join20(workingDirectory, ".gitignore");
67965
+ const gitignorePath = join21(workingDirectory, ".gitignore");
67777
67966
  const pattern = ".letta/settings.local.json";
67778
67967
  try {
67779
67968
  let content = "";
@@ -67800,7 +67989,7 @@ __export(exports_analyzer, {
67800
67989
  analyzeApprovalContext: () => analyzeApprovalContext
67801
67990
  });
67802
67991
  import { homedir as homedir18 } from "node:os";
67803
- import { dirname as dirname10, relative as relative8, resolve as resolve22, win32 as win322 } from "node:path";
67992
+ import { dirname as dirname11, relative as relative8, resolve as resolve22, win32 as win322 } from "node:path";
67804
67993
  function normalizeOsPath(path20) {
67805
67994
  return path20.replace(/\\/g, "/");
67806
67995
  }
@@ -67826,7 +68015,7 @@ function isPathWithinDirectory(path20, directory) {
67826
68015
  return !relativePath.startsWith("../") && relativePath !== ".." && !relativePath.startsWith("/") && !/^[a-zA-Z]:\//.test(relativePath);
67827
68016
  }
67828
68017
  function dirnameForContext(path20) {
67829
- return isWindowsPath(path20) ? win322.dirname(path20) : dirname10(path20);
68018
+ return isWindowsPath(path20) ? win322.dirname(path20) : dirname11(path20);
67830
68019
  }
67831
68020
  function formatAbsoluteRulePath(path20) {
67832
68021
  const normalized = normalizeOsPath(path20).replace(/\/+$/, "");
@@ -67887,7 +68076,7 @@ function analyzeReadApproval(filePath, workingDir) {
67887
68076
  };
67888
68077
  }
67889
68078
  const relativePath = normalizeOsPath(relativePathForContext(workingDir, absolutePath));
67890
- const relativeDir = dirname10(relativePath);
68079
+ const relativeDir = dirname11(relativePath);
67891
68080
  const pattern = relativeDir === "." || relativeDir === "" ? "**" : `${relativeDir}/**`;
67892
68081
  return {
67893
68082
  recommendedRule: `Read(${pattern})`,
@@ -68972,6 +69161,7 @@ async function executeTool(name, args, options) {
68972
69161
  if (options?.onOutput) {
68973
69162
  enhancedArgs = { ...enhancedArgs, onOutput: options.onOutput };
68974
69163
  }
69164
+ enhancedArgs = substituteSecretsInArgs(enhancedArgs);
68975
69165
  }
68976
69166
  if (internalName === "Task") {
68977
69167
  if (options?.toolCallId) {
@@ -68980,6 +69170,9 @@ async function executeTool(name, args, options) {
68980
69170
  if (options?.signal) {
68981
69171
  enhancedArgs = { ...enhancedArgs, signal: options.signal };
68982
69172
  }
69173
+ if (options?.parentScope) {
69174
+ enhancedArgs = { ...enhancedArgs, parentScope: options.parentScope };
69175
+ }
68983
69176
  }
68984
69177
  if (internalName === "Skill" && options?.toolCallId) {
68985
69178
  enhancedArgs = { ...enhancedArgs, toolCallId: options.toolCallId };
@@ -69007,7 +69200,24 @@ async function executeTool(name, args, options) {
69007
69200
  const stdout = isStringArray(stdoutValue) ? stdoutValue : undefined;
69008
69201
  const stderr = isStringArray(stderrValue) ? stderrValue : undefined;
69009
69202
  const toolStatus = recordResult?.status === "error" ? "error" : "success";
69010
- const flattenedResponse = flattenToolResponse(result);
69203
+ let flattenedResponse = flattenToolResponse(result);
69204
+ if (STREAMING_SHELL_TOOLS.has(internalName)) {
69205
+ if (typeof flattenedResponse === "string") {
69206
+ flattenedResponse = scrubSecretsFromString(flattenedResponse);
69207
+ } else if (Array.isArray(flattenedResponse)) {
69208
+ flattenedResponse = flattenedResponse.map((block) => block.type === "text" ? { ...block, text: scrubSecretsFromString(block.text) } : block);
69209
+ }
69210
+ if (stdout) {
69211
+ for (let i = 0;i < stdout.length; i++) {
69212
+ stdout[i] = scrubSecretsFromString(stdout[i]);
69213
+ }
69214
+ }
69215
+ if (stderr) {
69216
+ for (let i = 0;i < stderr.length; i++) {
69217
+ stderr[i] = scrubSecretsFromString(stderr[i]);
69218
+ }
69219
+ }
69220
+ }
69011
69221
  const responseSize = typeof flattenedResponse === "string" ? flattenedResponse.length : JSON.stringify(flattenedResponse).length;
69012
69222
  telemetry.trackToolUsage(internalName, toolStatus === "success", duration, responseSize, toolStatus === "error" ? "tool_error" : undefined, stderr ? stderr.join(`
69013
69223
  `) : undefined);
@@ -69133,6 +69343,7 @@ var init_manager3 = __esm(async () => {
69133
69343
  init_hooks(),
69134
69344
  init_openai_codex_provider(),
69135
69345
  init_telemetry(),
69346
+ init_secret_substitution(),
69136
69347
  init_toolDefinitions()
69137
69348
  ]);
69138
69349
  FILE_MODIFYING_TOOLS = new Set([
@@ -69528,7 +69739,7 @@ var init_constants2 = __esm(() => {
69528
69739
  });
69529
69740
 
69530
69741
  // src/websocket/listener/remote-settings.ts
69531
- import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
69742
+ import { existsSync as existsSync18, readFileSync as readFileSync8 } from "node:fs";
69532
69743
  import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
69533
69744
  import { homedir as homedir19 } from "node:os";
69534
69745
  import path20 from "node:path";
@@ -69542,7 +69753,7 @@ function loadRemoteSettings() {
69542
69753
  let loaded = {};
69543
69754
  try {
69544
69755
  const settingsPath = getRemoteSettingsPath();
69545
- if (existsSync17(settingsPath)) {
69756
+ if (existsSync18(settingsPath)) {
69546
69757
  const raw = readFileSync8(settingsPath, "utf-8");
69547
69758
  const parsed = JSON.parse(raw);
69548
69759
  loaded = parsed;
@@ -69551,7 +69762,7 @@ function loadRemoteSettings() {
69551
69762
  if (loaded.cwdMap) {
69552
69763
  const validCwdMap = {};
69553
69764
  for (const [key, value] of Object.entries(loaded.cwdMap)) {
69554
- if (typeof value === "string" && existsSync17(value)) {
69765
+ if (typeof value === "string" && existsSync18(value)) {
69555
69766
  validCwdMap[key] = value;
69556
69767
  }
69557
69768
  }
@@ -69578,13 +69789,13 @@ function saveRemoteSettings(updates) {
69578
69789
  function loadLegacyCwdCache() {
69579
69790
  try {
69580
69791
  const legacyPath = path20.join(homedir19(), ".letta", "cwd-cache.json");
69581
- if (!existsSync17(legacyPath))
69792
+ if (!existsSync18(legacyPath))
69582
69793
  return {};
69583
69794
  const raw = readFileSync8(legacyPath, "utf-8");
69584
69795
  const parsed = JSON.parse(raw);
69585
69796
  const result = {};
69586
69797
  for (const [key, value] of Object.entries(parsed)) {
69587
- if (typeof value === "string" && existsSync17(value)) {
69798
+ if (typeof value === "string" && existsSync18(value)) {
69588
69799
  result[key] = value;
69589
69800
  }
69590
69801
  }
@@ -69991,6 +70202,38 @@ function emitStateSync(socket, runtime, scope) {
69991
70202
  emitDeviceStatusUpdate(socket, runtime, scope);
69992
70203
  emitLoopStatusUpdate(socket, runtime, scope);
69993
70204
  emitQueueUpdate(socket, runtime, scope);
70205
+ emitSubagentStateUpdate(socket, runtime, scope);
70206
+ }
70207
+ function buildSubagentSnapshot() {
70208
+ return getSubagents().filter((a) => !a.silent && (a.status === "pending" || a.status === "running")).map((a) => ({
70209
+ subagent_id: a.id,
70210
+ subagent_type: a.type,
70211
+ description: a.description,
70212
+ status: a.status,
70213
+ agent_url: a.agentURL,
70214
+ model: a.model,
70215
+ is_background: a.isBackground,
70216
+ silent: a.silent,
70217
+ tool_call_id: a.toolCallId,
70218
+ start_time: a.startTime,
70219
+ tool_calls: a.toolCalls,
70220
+ total_tokens: a.totalTokens,
70221
+ duration_ms: a.durationMs,
70222
+ error: a.error
70223
+ }));
70224
+ }
70225
+ function emitSubagentStateUpdate(socket, runtime, scope) {
70226
+ const message = {
70227
+ type: "update_subagent_state",
70228
+ subagents: buildSubagentSnapshot()
70229
+ };
70230
+ emitProtocolV2Message(socket, runtime, message, scope);
70231
+ }
70232
+ function emitSubagentStateIfOpen(runtime, scope) {
70233
+ const listener = getListenerRuntime(runtime);
70234
+ if (listener?.socket?.readyState === WebSocket2.OPEN) {
70235
+ emitSubagentStateUpdate(listener.socket, runtime, scope);
70236
+ }
69994
70237
  }
69995
70238
  function scheduleQueueEmit(runtime, scope) {
69996
70239
  runtime.pendingQueueEmitScope = scope;
@@ -70060,15 +70303,17 @@ function emitInterruptedStatusDelta(socket, runtime, params) {
70060
70303
  conversationId: params.conversationId ?? undefined
70061
70304
  });
70062
70305
  }
70063
- function emitStreamDelta(socket, runtime, delta, scope) {
70306
+ function emitStreamDelta(socket, runtime, delta, scope, subagentId) {
70064
70307
  const message = {
70065
70308
  type: "stream_delta",
70066
- delta
70309
+ delta,
70310
+ ...subagentId ? { subagent_id: subagentId } : {}
70067
70311
  };
70068
70312
  emitProtocolV2Message(socket, runtime, message, scope);
70069
70313
  }
70070
70314
  var init_protocol_outbound = __esm(async () => {
70071
70315
  init_memoryFilesystem();
70316
+ init_subagentState();
70072
70317
  init_mode();
70073
70318
  init_constants2();
70074
70319
  init_cwd();
@@ -71029,7 +71274,22 @@ function buildQueuedTurnMessage(runtime, batch) {
71029
71274
  for (const item of batch.items) {
71030
71275
  runtime.queuedMessagesByItemId.delete(item.id);
71031
71276
  }
71032
- return null;
71277
+ const mergedContent2 = mergeDequeuedBatchContent(batch.items);
71278
+ if (mergedContent2 === null) {
71279
+ return null;
71280
+ }
71281
+ const scopeItem = batch.items[0];
71282
+ return {
71283
+ type: "message",
71284
+ agentId: scopeItem?.agentId ?? runtime.agentId ?? undefined,
71285
+ conversationId: scopeItem?.conversationId ?? runtime.conversationId,
71286
+ messages: [
71287
+ {
71288
+ role: "user",
71289
+ content: mergedContent2
71290
+ }
71291
+ ]
71292
+ };
71033
71293
  }
71034
71294
  const template = runtime.queuedMessagesByItemId.get(primaryItem.id);
71035
71295
  for (const item of batch.items) {
@@ -71069,6 +71329,7 @@ function consumeQueuedTurn(runtime) {
71069
71329
  }
71070
71330
  let queueLen = 0;
71071
71331
  let hasMessage = false;
71332
+ let hasTaskNotification = false;
71072
71333
  for (const item of queuedItems) {
71073
71334
  if (!isCoalescable(item.kind) || !hasSameQueueScope(firstQueuedItem, item)) {
71074
71335
  break;
@@ -71077,8 +71338,11 @@ function consumeQueuedTurn(runtime) {
71077
71338
  if (item.kind === "message") {
71078
71339
  hasMessage = true;
71079
71340
  }
71341
+ if (item.kind === "task_notification") {
71342
+ hasTaskNotification = true;
71343
+ }
71080
71344
  }
71081
- if (!hasMessage || queueLen === 0) {
71345
+ if (!hasMessage && !hasTaskNotification || queueLen === 0) {
71082
71346
  return null;
71083
71347
  }
71084
71348
  const dequeuedBatch = runtime.queueRuntime.consumeItems(queueLen);
@@ -71965,6 +72229,9 @@ function isCloudflareEdge52xDetail(detail) {
71965
72229
  return false;
71966
72230
  return isCloudflareEdge52xHtmlError2(detail);
71967
72231
  }
72232
+ function isQuotaLimitErrorDetail(detail) {
72233
+ return hasNonRetryableQuotaDetail(detail);
72234
+ }
71968
72235
  function hasNonRetryableQuotaDetail(detail) {
71969
72236
  if (typeof detail !== "string")
71970
72237
  return false;
@@ -73421,7 +73688,7 @@ var init_accumulator = __esm(async () => {
73421
73688
  });
73422
73689
 
73423
73690
  // src/agent/clientSkills.ts
73424
- import { join as join21 } from "node:path";
73691
+ import { join as join22 } from "node:path";
73425
73692
  function toClientSkill(skill2) {
73426
73693
  return {
73427
73694
  name: skill2.id,
@@ -73430,37 +73697,64 @@ function toClientSkill(skill2) {
73430
73697
  };
73431
73698
  }
73432
73699
  function resolveSkillDiscoveryContext(options) {
73433
- const skillsDirectory = options.skillsDirectory ?? getSkillsDirectory() ?? join21(process.cwd(), SKILLS_DIR);
73700
+ const legacySkillsDirectory = options.skillsDirectory ?? getSkillsDirectory() ?? join22(process.cwd(), SKILLS_DIR);
73434
73701
  const skillSources = options.skillSources ?? getSkillSources();
73435
- return { skillsDirectory, skillSources };
73702
+ return { legacySkillsDirectory, skillSources };
73703
+ }
73704
+ function getPrimaryProjectSkillsDirectory() {
73705
+ return join22(process.cwd(), ".agents", "skills");
73436
73706
  }
73437
73707
  async function buildClientSkillsPayload(options = {}) {
73438
- const { skillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
73708
+ const { legacySkillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
73439
73709
  const discoverSkillsFn = options.discoverSkillsFn ?? discoverSkills;
73440
- try {
73441
- const discovery = await discoverSkillsFn(skillsDirectory, options.agentId, {
73442
- sources: skillSources
73710
+ const skillsById = new Map;
73711
+ const errors = [];
73712
+ const primaryProjectSkillsDirectory = getPrimaryProjectSkillsDirectory();
73713
+ const nonProjectSources = skillSources.filter((source) => source !== "project");
73714
+ const discoveryRuns = [];
73715
+ if (nonProjectSources.length > 0) {
73716
+ discoveryRuns.push({
73717
+ path: primaryProjectSkillsDirectory,
73718
+ sources: nonProjectSources
73443
73719
  });
73444
- const sortedSkills = [...discovery.skills].sort(compareSkills);
73445
- return {
73446
- clientSkills: sortedSkills.map(toClientSkill),
73447
- skillPathById: Object.fromEntries(sortedSkills.filter((skill2) => typeof skill2.path === "string" && skill2.path.length > 0).map((skill2) => [skill2.id, skill2.path])),
73448
- errors: discovery.errors
73449
- };
73450
- } catch (error) {
73451
- const message = error instanceof Error ? error.message : `Unknown error: ${String(error)}`;
73452
- options.logger?.(`Failed to build client_skills payload: ${message}`);
73453
- return {
73454
- clientSkills: [],
73455
- skillPathById: {},
73456
- errors: [
73457
- {
73458
- path: skillsDirectory,
73459
- message
73460
- }
73461
- ]
73462
- };
73463
73720
  }
73721
+ const includeProjectSource = skillSources.includes("project");
73722
+ if (includeProjectSource && legacySkillsDirectory !== primaryProjectSkillsDirectory) {
73723
+ discoveryRuns.push({
73724
+ path: legacySkillsDirectory,
73725
+ sources: ["project"]
73726
+ });
73727
+ }
73728
+ if (includeProjectSource) {
73729
+ discoveryRuns.push({
73730
+ path: primaryProjectSkillsDirectory,
73731
+ sources: ["project"]
73732
+ });
73733
+ }
73734
+ for (const run of discoveryRuns) {
73735
+ try {
73736
+ const discovery = await discoverSkillsFn(run.path, options.agentId, {
73737
+ sources: run.sources
73738
+ });
73739
+ errors.push(...discovery.errors);
73740
+ for (const skill2 of discovery.skills) {
73741
+ skillsById.set(skill2.id, skill2);
73742
+ }
73743
+ } catch (error) {
73744
+ const message = error instanceof Error ? error.message : `Unknown error: ${String(error)}`;
73745
+ errors.push({ path: run.path, message });
73746
+ }
73747
+ }
73748
+ const sortedSkills = [...skillsById.values()].sort(compareSkills);
73749
+ if (errors.length > 0) {
73750
+ const summarizedErrors = errors.map((error) => `${error.path}: ${error.message}`);
73751
+ options.logger?.(`Failed to build some client_skills entries: ${summarizedErrors.join("; ")}`);
73752
+ }
73753
+ return {
73754
+ clientSkills: sortedSkills.map(toClientSkill),
73755
+ skillPathById: Object.fromEntries(sortedSkills.filter((skill2) => typeof skill2.path === "string" && skill2.path.length > 0).map((skill2) => [skill2.id, skill2.path])),
73756
+ errors
73757
+ };
73464
73758
  }
73465
73759
  var init_clientSkills = __esm(() => {
73466
73760
  init_context();
@@ -73491,6 +73785,7 @@ function buildConversationMessagesCreateRequestBody(conversationId, messages, op
73491
73785
  client_skills: clientSkills,
73492
73786
  client_tools: clientTools,
73493
73787
  include_compaction_messages: true,
73788
+ ...opts.overrideModel ? { override_model: opts.overrideModel } : {},
73494
73789
  ...isDefaultConversation ? { agent_id: opts.agentId } : {}
73495
73790
  };
73496
73791
  }
@@ -73535,7 +73830,8 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
73535
73830
  }
73536
73831
  return `message:parts:${content.length}`;
73537
73832
  }).join(",");
73538
- debugLog("send-message-stream", "request_start conversation_id=%s agent_id=%s messages=%s stream_tokens=%s background=%s max_retries=%s", resolvedConversationId, opts.agentId ?? "none", messageSummary || "(empty)", opts.streamTokens ?? true, opts.background ?? true, requestOptions.maxRetries ?? "default");
73833
+ const firstOtid = messages[0]?.otid;
73834
+ debugLog("send-message-stream", "request_start conversation_id=%s agent_id=%s messages=%s otid=%s stream_tokens=%s background=%s max_retries=%s", resolvedConversationId, opts.agentId ?? "none", messageSummary || "(empty)", firstOtid ?? "none", opts.streamTokens ?? true, opts.background ?? true, requestOptions.maxRetries ?? "default");
73539
73835
  let stream2;
73540
73836
  try {
73541
73837
  stream2 = await client.conversations.messages.create(resolvedConversationId, requestBody, {
@@ -73546,10 +73842,10 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
73546
73842
  }
73547
73843
  });
73548
73844
  } catch (error) {
73549
- debugWarn("send-message-stream", "request_error conversation_id=%s status=%s error=%s", resolvedConversationId, error?.status ?? "none", error instanceof Error ? error.message : String(error));
73845
+ debugWarn("send-message-stream", "request_error conversation_id=%s otid=%s status=%s error=%s", resolvedConversationId, firstOtid ?? "none", error?.status ?? "none", error instanceof Error ? error.message : String(error));
73550
73846
  throw error;
73551
73847
  }
73552
- debugLog("send-message-stream", "request_ok conversation_id=%s", resolvedConversationId);
73848
+ debugLog("send-message-stream", "request_ok conversation_id=%s otid=%s", resolvedConversationId, firstOtid ?? "none");
73553
73849
  if (requestStartTime !== undefined) {
73554
73850
  streamRequestStartTimes.set(stream2, requestStartTime);
73555
73851
  }
@@ -73558,7 +73854,8 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
73558
73854
  conversationId,
73559
73855
  resolvedConversationId,
73560
73856
  agentId: opts.agentId ?? null,
73561
- requestStartedAtMs
73857
+ requestStartedAtMs,
73858
+ otid: firstOtid
73562
73859
  });
73563
73860
  return stream2;
73564
73861
  }
@@ -73580,14 +73877,14 @@ var init_message = __esm(async () => {
73580
73877
 
73581
73878
  // src/cli/helpers/chunkLog.ts
73582
73879
  import {
73583
- existsSync as existsSync18,
73584
- mkdirSync as mkdirSync12,
73880
+ existsSync as existsSync19,
73881
+ mkdirSync as mkdirSync13,
73585
73882
  readdirSync as readdirSync8,
73586
73883
  unlinkSync as unlinkSync5,
73587
- writeFileSync as writeFileSync9
73884
+ writeFileSync as writeFileSync10
73588
73885
  } from "node:fs";
73589
73886
  import { homedir as homedir20 } from "node:os";
73590
- import { join as join22 } from "node:path";
73887
+ import { join as join23 } from "node:path";
73591
73888
  function truncateStr(value, maxLen) {
73592
73889
  if (value === null || value === undefined)
73593
73890
  return "";
@@ -73651,8 +73948,8 @@ class ChunkLog {
73651
73948
  agentDir = null;
73652
73949
  dirCreated = false;
73653
73950
  init(agentId, sessionId) {
73654
- this.agentDir = join22(LOG_BASE_DIR, agentId);
73655
- this.logPath = join22(this.agentDir, `${sessionId}.jsonl`);
73951
+ this.agentDir = join23(LOG_BASE_DIR, agentId);
73952
+ this.logPath = join23(this.agentDir, `${sessionId}.jsonl`);
73656
73953
  this.buffer = [];
73657
73954
  this.dirty = false;
73658
73955
  this.dirCreated = false;
@@ -73681,8 +73978,8 @@ class ChunkLog {
73681
73978
  if (this.dirCreated || !this.agentDir)
73682
73979
  return;
73683
73980
  try {
73684
- if (!existsSync18(this.agentDir)) {
73685
- mkdirSync12(this.agentDir, { recursive: true });
73981
+ if (!existsSync19(this.agentDir)) {
73982
+ mkdirSync13(this.agentDir, { recursive: true });
73686
73983
  }
73687
73984
  this.dirCreated = true;
73688
73985
  } catch (e) {
@@ -73696,7 +73993,7 @@ class ChunkLog {
73696
73993
  try {
73697
73994
  const content = this.buffer.map((entry) => JSON.stringify(entry)).join(`
73698
73995
  `);
73699
- writeFileSync9(this.logPath, `${content}
73996
+ writeFileSync10(this.logPath, `${content}
73700
73997
  `, "utf8");
73701
73998
  } catch (e) {
73702
73999
  debugWarn("chunkLog", `Failed to write ${this.logPath}: ${e instanceof Error ? e.message : String(e)}`);
@@ -73706,14 +74003,14 @@ class ChunkLog {
73706
74003
  if (!this.agentDir)
73707
74004
  return;
73708
74005
  try {
73709
- if (!existsSync18(this.agentDir))
74006
+ if (!existsSync19(this.agentDir))
73710
74007
  return;
73711
74008
  const files = readdirSync8(this.agentDir).filter((f) => f.endsWith(".jsonl")).sort();
73712
74009
  if (files.length >= MAX_SESSION_FILES2) {
73713
74010
  const toDelete = files.slice(0, files.length - MAX_SESSION_FILES2 + 1);
73714
74011
  for (const file of toDelete) {
73715
74012
  try {
73716
- unlinkSync5(join22(this.agentDir, file));
74013
+ unlinkSync5(join23(this.agentDir, file));
73717
74014
  } catch (e) {
73718
74015
  debugWarn("chunkLog", `Failed to delete old session log ${file}: ${e instanceof Error ? e.message : String(e)}`);
73719
74016
  }
@@ -73727,7 +74024,7 @@ class ChunkLog {
73727
74024
  var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
73728
74025
  var init_chunkLog = __esm(() => {
73729
74026
  init_debug();
73730
- LOG_BASE_DIR = join22(homedir20(), ".letta", "logs", "chunk-logs");
74027
+ LOG_BASE_DIR = join23(homedir20(), ".letta", "logs", "chunk-logs");
73731
74028
  chunkLog = new ChunkLog;
73732
74029
  });
73733
74030
 
@@ -73890,7 +74187,7 @@ async function discoverFallbackRunIdForResume(client, ctx) {
73890
74187
  }
73891
74188
  return null;
73892
74189
  }
73893
- async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold, isResumeStream) {
74190
+ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold, isResumeStream, skipCancelToolsOnError) {
73894
74191
  const startTime = performance.now();
73895
74192
  const requestStartTime = getStreamRequestStartTime(stream2) ?? startTime;
73896
74193
  let hasLoggedTTFT = false;
@@ -73996,7 +74293,11 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
73996
74293
  }
73997
74294
  fallbackError = errorMessageWithDiagnostic;
73998
74295
  stopReason = streamProcessor.stopReason || "error";
73999
- markIncompleteToolsAsCancelled(buffers, true, "stream_error", true);
74296
+ if (skipCancelToolsOnError) {
74297
+ buffers.interrupted = true;
74298
+ } else {
74299
+ markIncompleteToolsAsCancelled(buffers, true, "stream_error", true);
74300
+ }
74000
74301
  queueMicrotask(refresh);
74001
74302
  } finally {
74002
74303
  try {
@@ -74021,13 +74322,15 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
74021
74322
  if (stopReason === "cancelled") {
74022
74323
  markIncompleteToolsAsCancelled(buffers, true, "user_interrupt");
74023
74324
  }
74024
- markCurrentLineAsFinished(buffers);
74325
+ if (stopReason !== "error") {
74326
+ markCurrentLineAsFinished(buffers);
74327
+ }
74025
74328
  queueMicrotask(refresh);
74026
74329
  const allPending = Array.from(streamProcessor.pendingApprovals.values());
74027
74330
  const approvals = allPending.map((a) => ({
74028
74331
  toolCallId: a.toolCallId,
74029
74332
  toolName: a.toolName || "",
74030
- toolArgs: a.toolArgs || "{}"
74333
+ toolArgs: a.toolArgs || ""
74031
74334
  }));
74032
74335
  const approval = approvals[0] || null;
74033
74336
  streamProcessor.pendingApprovals.clear();
@@ -74048,6 +74351,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
74048
74351
  async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold) {
74049
74352
  const overallStartTime = performance.now();
74050
74353
  const streamRequestContext = getStreamRequestContext(stream2);
74354
+ const streamOtid = streamRequestContext?.otid ?? null;
74051
74355
  let _client;
74052
74356
  const lazyClient = async () => {
74053
74357
  if (!_client) {
@@ -74055,54 +74359,84 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
74055
74359
  }
74056
74360
  return _client;
74057
74361
  };
74058
- let result = await drainStream(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold);
74362
+ let result = await drainStream(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker, seenSeqIdThreshold, false, true);
74059
74363
  let runIdToResume = result.lastRunId ?? null;
74060
74364
  let runIdSource = result.lastRunId ? "stream_chunk" : null;
74061
74365
  if (result.stopReason === "error" && !runIdToResume && streamRequestContext && abortSignal && !abortSignal.aborted) {
74062
- try {
74063
- debugLog("stream", "Mid-stream resume: attempting run discovery (conv=%s, agent=%s)", streamRequestContext.conversationId, streamRequestContext.agentId);
74064
- const client = await lazyClient();
74065
- runIdToResume = await discoverFallbackRunIdWithTimeout(client, streamRequestContext);
74066
- debugLog("stream", "Mid-stream resume: run discovery result: %s", runIdToResume ?? "none");
74067
- if (runIdToResume) {
74068
- result.lastRunId = runIdToResume;
74069
- runIdSource = "discovery";
74366
+ if (streamOtid) {
74367
+ runIdSource = "otid";
74368
+ debugLog("stream", "Mid-stream resume: will use OTID-based conversations stream (otid=%s)", streamOtid);
74369
+ } else {
74370
+ try {
74371
+ debugLog("stream", "Mid-stream resume: attempting run discovery (conv=%s, agent=%s)", streamRequestContext.conversationId, streamRequestContext.agentId);
74372
+ const client = await lazyClient();
74373
+ runIdToResume = await discoverFallbackRunIdWithTimeout(client, streamRequestContext);
74374
+ debugLog("stream", "Mid-stream resume: run discovery result: %s", runIdToResume ?? "none");
74375
+ if (runIdToResume) {
74376
+ result.lastRunId = runIdToResume;
74377
+ runIdSource = "discovery";
74378
+ }
74379
+ } catch (lookupError) {
74380
+ const lookupErrorMsg = lookupError instanceof Error ? lookupError.message : String(lookupError);
74381
+ telemetry.trackError("stream_resume_lookup_failed", lookupErrorMsg, "stream_resume");
74382
+ debugWarn("drainStreamWithResume", "Fallback run_id lookup failed:", lookupError);
74070
74383
  }
74071
- } catch (lookupError) {
74072
- const lookupErrorMsg = lookupError instanceof Error ? lookupError.message : String(lookupError);
74073
- telemetry.trackError("stream_resume_lookup_failed", lookupErrorMsg, "stream_resume");
74074
- debugWarn("drainStreamWithResume", "Fallback run_id lookup failed:", lookupError);
74075
74384
  }
74076
74385
  }
74077
- if (result.stopReason === "error" && runIdToResume && abortSignal && !abortSignal.aborted) {
74386
+ const isApprovalPendingConflict = result.fallbackError?.includes("waiting for approval on a tool call") ?? false;
74387
+ const canResume = result.stopReason === "error" && !isApprovalPendingConflict && (runIdToResume || runIdSource === "otid") && abortSignal && !abortSignal.aborted;
74388
+ if (canResume) {
74078
74389
  const originalFallbackError = result.fallbackError;
74079
74390
  const originalApprovals = result.approvals;
74080
74391
  const originalApproval = result.approval;
74081
74392
  telemetry.trackError("stream_resume_attempt", originalFallbackError || "Stream error (no client-side detail)", "stream_resume", {
74082
74393
  runId: result.lastRunId ?? undefined
74083
74394
  });
74084
- debugLog("stream", "Mid-stream resume: fetching run stream (source=%s, runId=%s, lastSeqId=%s)", runIdSource ?? "unknown", runIdToResume, result.lastSeqId ?? 0);
74085
- debugLog("stream", "Mid-stream resume: attempting resume (runId=%s, lastSeqId=%s)", runIdToResume, result.lastSeqId ?? 0);
74395
+ debugWarn("stream", "[MID-STREAM RESUME] Attempting (runId=%s, lastSeqId=%s, source=%s, otid=%s)", runIdToResume ?? "none", result.lastSeqId ?? 0, runIdSource ?? "unknown", streamOtid ?? "none");
74086
74396
  try {
74087
74397
  const client = await lazyClient();
74088
74398
  buffers.commitGeneration = (buffers.commitGeneration || 0) + 1;
74089
74399
  buffers.interrupted = false;
74090
- const resumeStream = await client.runs.messages.stream(runIdToResume, {
74400
+ const resumeStream = runIdSource === "otid" && streamOtid && streamRequestContext ? await client.conversations.messages.stream(streamRequestContext.resolvedConversationId, {
74401
+ agent_id: streamRequestContext.conversationId === "default" ? streamRequestContext.agentId ?? undefined : undefined,
74402
+ otid: streamOtid,
74403
+ starting_after: result.lastSeqId ?? 0,
74404
+ batch_size: 1000
74405
+ }) : await client.runs.messages.stream(runIdToResume, {
74091
74406
  starting_after: result.lastSeqId ?? 0,
74092
74407
  batch_size: 1000
74093
74408
  });
74094
74409
  const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal, undefined, onChunkProcessed, contextTracker, seenSeqIdThreshold, true);
74095
- debugLog("stream", "Mid-stream resume succeeded (runId=%s, stopReason=%s)", runIdToResume, resumeResult.stopReason);
74410
+ if (resumeResult.stopReason !== "error") {
74411
+ debugWarn("stream", "[MID-STREAM RESUME] ✅ Success (runId=%s, stopReason=%s)", runIdToResume, resumeResult.stopReason);
74412
+ } else {
74413
+ debugWarn("stream", "[MID-STREAM RESUME] ⚠️ Resumed but terminal error persisted (runId=%s)", runIdToResume);
74414
+ }
74096
74415
  result = resumeResult;
74097
- if (result.stopReason === "requires_approval" && (result.approvals?.length ?? 0) === 0 && (originalApprovals?.length ?? 0) > 0) {
74098
- result.approvals = originalApprovals;
74099
- result.approval = originalApproval;
74416
+ if (result.stopReason === "requires_approval" && (originalApprovals?.length ?? 0) > 0) {
74417
+ if ((result.approvals?.length ?? 0) === 0) {
74418
+ result.approvals = originalApprovals;
74419
+ result.approval = originalApproval;
74420
+ } else {
74421
+ result.approvals = (result.approvals ?? []).map((resumeApproval) => {
74422
+ const orig = originalApprovals?.find((a) => a.toolCallId === resumeApproval.toolCallId);
74423
+ if (!orig)
74424
+ return resumeApproval;
74425
+ return {
74426
+ ...resumeApproval,
74427
+ toolName: resumeApproval.toolName || orig.toolName,
74428
+ toolArgs: (orig.toolArgs || "") + (resumeApproval.toolArgs || "")
74429
+ };
74430
+ });
74431
+ result.approval = result.approvals[0] ?? null;
74432
+ }
74100
74433
  }
74101
74434
  } catch (resumeError) {
74435
+ markIncompleteToolsAsCancelled(buffers, false, "stream_error", true);
74102
74436
  markCurrentLineAsFinished(buffers);
74103
74437
  result.fallbackError = originalFallbackError;
74104
74438
  const resumeErrorMsg = resumeError instanceof Error ? resumeError.message : String(resumeError);
74105
- debugLog("stream", "Mid-stream resume failed (runId=%s): %s", runIdToResume, resumeErrorMsg);
74439
+ debugWarn("stream", "[MID-STREAM RESUME] Failed (runId=%s): %s", runIdToResume, resumeErrorMsg);
74106
74440
  telemetry.trackError("stream_resume_failed", resumeErrorMsg, "stream_resume", {
74107
74441
  runId: result.lastRunId ?? undefined
74108
74442
  });
@@ -74110,13 +74444,14 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
74110
74444
  }
74111
74445
  if (result.stopReason === "error") {
74112
74446
  const skipReasons = [];
74113
- if (!result.lastRunId)
74447
+ if (!result.lastRunId && runIdSource !== "otid")
74114
74448
  skipReasons.push("no_run_id");
74115
74449
  if (!abortSignal)
74116
74450
  skipReasons.push("no_abort_signal");
74117
74451
  if (abortSignal?.aborted)
74118
74452
  skipReasons.push("user_aborted");
74119
74453
  if (skipReasons.length > 0) {
74454
+ markIncompleteToolsAsCancelled(buffers, false, "stream_error", true);
74120
74455
  markCurrentLineAsFinished(buffers);
74121
74456
  debugLog("stream", "Mid-stream resume skipped: %s", skipReasons.join(", "));
74122
74457
  telemetry.trackError("stream_resume_skipped", `${result.fallbackError || "Stream error (no client-side detail)"} [skip: ${skipReasons.join(", ")}]`, "stream_resume", {
@@ -74124,6 +74459,10 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
74124
74459
  });
74125
74460
  }
74126
74461
  }
74462
+ if (result.stopReason === "requires_approval" && (result.approvals?.length ?? 0) > 0 && buffers.interrupted) {
74463
+ buffers.interrupted = false;
74464
+ markCurrentLineAsFinished(buffers);
74465
+ }
74127
74466
  result.apiDurationMs = performance.now() - overallStartTime;
74128
74467
  return result;
74129
74468
  }
@@ -75802,7 +76141,11 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
75802
76141
  try {
75803
76142
  const approvalResults = await executeApprovalBatch(decisions, undefined, {
75804
76143
  abortSignal: recoveryAbortController.signal,
75805
- workingDirectory: getConversationWorkingDirectory(runtime.listener, recovered.agentId, recovered.conversationId)
76144
+ workingDirectory: getConversationWorkingDirectory(runtime.listener, recovered.agentId, recovered.conversationId),
76145
+ parentScope: recovered.agentId && recovered.conversationId ? {
76146
+ agentId: recovered.agentId,
76147
+ conversationId: recovered.conversationId
76148
+ } : undefined
75806
76149
  });
75807
76150
  emitToolExecutionFinishedEvents(socket, runtime, {
75808
76151
  approvals: approvalResults,
@@ -76142,7 +76485,11 @@ async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
76142
76485
  try {
76143
76486
  const approvalResults = await executeApprovalBatch(decisions, undefined, {
76144
76487
  abortSignal,
76145
- workingDirectory: recoveryWorkingDirectory
76488
+ workingDirectory: recoveryWorkingDirectory,
76489
+ parentScope: runtime.agentId && runtime.conversationId ? {
76490
+ agentId: runtime.agentId,
76491
+ conversationId: runtime.conversationId
76492
+ } : undefined
76146
76493
  });
76147
76494
  emitToolExecutionFinishedEvents(socket, runtime, {
76148
76495
  approvals: approvalResults,
@@ -76198,7 +76545,6 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
76198
76545
  let conversationBusyRetries = 0;
76199
76546
  let preStreamRecoveryAttempts = 0;
76200
76547
  const MAX_CONVERSATION_BUSY_RETRIES = 3;
76201
- const requestStartedAtMs = Date.now();
76202
76548
  while (true) {
76203
76549
  if (abortSignal?.aborted) {
76204
76550
  throw new Error("Cancelled by user");
@@ -76283,21 +76629,16 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
76283
76629
  });
76284
76630
  try {
76285
76631
  const client = await getClient2();
76286
- const discoveredRunId = await discoverFallbackRunIdWithTimeout(client, {
76287
- conversationId,
76288
- resolvedConversationId: conversationId,
76289
- agentId: runtime.agentId ?? null,
76290
- requestStartedAtMs
76291
- });
76292
- if (discoveredRunId) {
76293
- if (abortSignal?.aborted) {
76294
- throw new Error("Cancelled by user");
76295
- }
76296
- return await client.runs.messages.stream(discoveredRunId, {
76297
- starting_after: 0,
76298
- batch_size: 1000
76299
- });
76632
+ const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
76633
+ if (abortSignal?.aborted) {
76634
+ throw new Error("Cancelled by user");
76300
76635
  }
76636
+ return await client.conversations.messages.stream(conversationId, {
76637
+ agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
76638
+ otid: messageOtid ?? undefined,
76639
+ starting_after: 0,
76640
+ batch_size: 1000
76641
+ });
76301
76642
  } catch (resumeError) {
76302
76643
  if (abortSignal?.aborted) {
76303
76644
  throw new Error("Cancelled by user");
@@ -76337,7 +76678,6 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
76337
76678
  let conversationBusyRetries = 0;
76338
76679
  let preStreamRecoveryAttempts = 0;
76339
76680
  const MAX_CONVERSATION_BUSY_RETRIES = 3;
76340
- const requestStartedAtMs = Date.now();
76341
76681
  while (true) {
76342
76682
  if (abortSignal?.aborted) {
76343
76683
  throw new Error("Cancelled by user");
@@ -76412,21 +76752,16 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
76412
76752
  });
76413
76753
  try {
76414
76754
  const client = await getClient2();
76415
- const discoveredRunId = await discoverFallbackRunIdWithTimeout(client, {
76416
- conversationId,
76417
- resolvedConversationId: conversationId,
76418
- agentId: runtime.agentId ?? null,
76419
- requestStartedAtMs
76420
- });
76421
- if (discoveredRunId) {
76422
- if (abortSignal?.aborted) {
76423
- throw new Error("Cancelled by user");
76424
- }
76425
- return await client.runs.messages.stream(discoveredRunId, {
76426
- starting_after: 0,
76427
- batch_size: 1000
76428
- });
76755
+ const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
76756
+ if (abortSignal?.aborted) {
76757
+ throw new Error("Cancelled by user");
76429
76758
  }
76759
+ return await client.conversations.messages.stream(conversationId, {
76760
+ agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
76761
+ otid: messageOtid ?? undefined,
76762
+ starting_after: 0,
76763
+ batch_size: 1000
76764
+ });
76430
76765
  } catch (resumeError) {
76431
76766
  if (abortSignal?.aborted) {
76432
76767
  throw new Error("Cancelled by user");
@@ -76466,7 +76801,6 @@ var init_send = __esm(async () => {
76466
76801
  init_client2(),
76467
76802
  init_message(),
76468
76803
  init_approvalClassification(),
76469
- init_stream(),
76470
76804
  init_approval(),
76471
76805
  init_interrupts(),
76472
76806
  init_protocol_outbound(),
@@ -77414,7 +77748,8 @@ async function handleApprovalStop(params) {
77414
77748
  const executionResults = await executeApprovalBatch(decisions, undefined, {
77415
77749
  toolContextId: turnToolContextId ?? undefined,
77416
77750
  abortSignal: abortController.signal,
77417
- workingDirectory: turnWorkingDirectory
77751
+ workingDirectory: turnWorkingDirectory,
77752
+ parentScope: agentId && conversationId ? { agentId, conversationId } : undefined
77418
77753
  });
77419
77754
  const persistedExecutionResults = normalizeExecutionResultsForInterruptParity(runtime, executionResults, lastExecutingToolCallIds);
77420
77755
  validateApprovalResultIds(decisions.map((decision) => ({
@@ -78039,7 +78374,7 @@ __export(exports_memoryScanner, {
78039
78374
  getFileNodes: () => getFileNodes
78040
78375
  });
78041
78376
  import { readdirSync as readdirSync9, readFileSync as readFileSync9, statSync as statSync5 } from "node:fs";
78042
- import { join as join23, relative as relative11 } from "node:path";
78377
+ import { join as join24, relative as relative11 } from "node:path";
78043
78378
  function scanMemoryFilesystem(memoryRoot) {
78044
78379
  const nodes = [];
78045
78380
  const scanDir = (dir, depth, parentIsLast) => {
@@ -78051,8 +78386,8 @@ function scanMemoryFilesystem(memoryRoot) {
78051
78386
  }
78052
78387
  const filtered = entries.filter((name) => !name.startsWith("."));
78053
78388
  const sorted = filtered.sort((a, b) => {
78054
- const aPath = join23(dir, a);
78055
- const bPath = join23(dir, b);
78389
+ const aPath = join24(dir, a);
78390
+ const bPath = join24(dir, b);
78056
78391
  let aIsDir = false;
78057
78392
  let bIsDir = false;
78058
78393
  try {
@@ -78072,7 +78407,7 @@ function scanMemoryFilesystem(memoryRoot) {
78072
78407
  return a.localeCompare(b);
78073
78408
  });
78074
78409
  sorted.forEach((name, index) => {
78075
- const fullPath = join23(dir, name);
78410
+ const fullPath = join24(dir, name);
78076
78411
  let isDir = false;
78077
78412
  try {
78078
78413
  isDir = statSync5(fullPath).isDirectory();
@@ -78186,6 +78521,14 @@ function ensureConversationQueueRuntime(listener, runtime) {
78186
78521
  function getOrCreateScopedRuntime(listener, agentId, conversationId) {
78187
78522
  return ensureConversationQueueRuntime(listener, getOrCreateConversationRuntime(listener, agentId, conversationId));
78188
78523
  }
78524
+ function findFallbackRuntime(listener) {
78525
+ for (const cr of listener.conversationRuntimes.values()) {
78526
+ if (cr.queueRuntime) {
78527
+ return cr;
78528
+ }
78529
+ }
78530
+ return null;
78531
+ }
78189
78532
  function resolveRuntimeForApprovalRequest(listener, requestId) {
78190
78533
  if (!requestId) {
78191
78534
  return null;
@@ -78319,6 +78662,7 @@ function createRuntime() {
78319
78662
  };
78320
78663
  }
78321
78664
  function stopRuntime(runtime, suppressCallbacks) {
78665
+ setMessageQueueAdder(null);
78322
78666
  runtime.intentionallyClosed = true;
78323
78667
  clearRuntimeTimers(runtime);
78324
78668
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
@@ -78418,6 +78762,30 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
78418
78762
  emitLoopStatusUpdate(socket, conversationRuntime, scope);
78419
78763
  }
78420
78764
  }
78765
+ runtime._unsubscribeSubagentState?.();
78766
+ runtime._unsubscribeSubagentState = subscribe2(() => {
78767
+ emitSubagentStateIfOpen(runtime);
78768
+ });
78769
+ runtime._unsubscribeSubagentStreamEvents?.();
78770
+ runtime._unsubscribeSubagentStreamEvents = subscribeToStreamEvents((subagentId, event) => {
78771
+ if (socket.readyState !== WebSocket4.OPEN)
78772
+ return;
78773
+ emitStreamDelta(socket, runtime, event, undefined, subagentId);
78774
+ });
78775
+ setMessageQueueAdder((queuedMessage) => {
78776
+ const targetRuntime = queuedMessage.agentId && queuedMessage.conversationId ? getOrCreateScopedRuntime(runtime, queuedMessage.agentId, queuedMessage.conversationId) : findFallbackRuntime(runtime);
78777
+ if (!targetRuntime?.queueRuntime) {
78778
+ return;
78779
+ }
78780
+ targetRuntime.queueRuntime.enqueue({
78781
+ kind: "task_notification",
78782
+ source: "task_notification",
78783
+ text: queuedMessage.text,
78784
+ agentId: queuedMessage.agentId ?? targetRuntime.agentId ?? undefined,
78785
+ conversationId: queuedMessage.conversationId ?? targetRuntime.conversationId
78786
+ });
78787
+ scheduleQueuePump(targetRuntime, socket, opts, processQueuedTurn);
78788
+ });
78421
78789
  runtime.heartbeatInterval = setInterval(() => {
78422
78790
  if (socket.readyState === WebSocket4.OPEN) {
78423
78791
  socket.send(JSON.stringify({ type: "ping" }));
@@ -78622,8 +78990,15 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
78622
78990
  if (isSearchFilesCommand(parsed)) {
78623
78991
  (async () => {
78624
78992
  await ensureFileIndex2();
78993
+ let searchDir = ".";
78994
+ if (parsed.cwd) {
78995
+ const rel = path22.relative(process.cwd(), parsed.cwd);
78996
+ if (rel && !rel.startsWith("..")) {
78997
+ searchDir = rel;
78998
+ }
78999
+ }
78625
79000
  const files = searchFileIndex({
78626
- searchDir: ".",
79001
+ searchDir,
78627
79002
  pattern: parsed.query,
78628
79003
  deep: true,
78629
79004
  maxResults: parsed.max_results ?? 5
@@ -78721,10 +79096,10 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
78721
79096
  const { getMemoryFilesystemRoot: getMemoryFilesystemRoot2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
78722
79097
  const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memoryScanner(), exports_memoryScanner));
78723
79098
  const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
78724
- const { existsSync: existsSync19 } = await import("node:fs");
78725
- const { join: join24 } = await import("node:path");
79099
+ const { existsSync: existsSync20 } = await import("node:fs");
79100
+ const { join: join25 } = await import("node:path");
78726
79101
  const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
78727
- const memfsInitialized = existsSync19(join24(memoryRoot, ".git"));
79102
+ const memfsInitialized = existsSync20(join25(memoryRoot, ".git"));
78728
79103
  if (!memfsInitialized) {
78729
79104
  socket.send(JSON.stringify({
78730
79105
  type: "list_memory_response",
@@ -78844,6 +79219,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
78844
79219
  code,
78845
79220
  reason: reason.toString()
78846
79221
  });
79222
+ setMessageQueueAdder(null);
78847
79223
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
78848
79224
  conversationRuntime.queuedMessagesByItemId.clear();
78849
79225
  if (conversationRuntime.queueRuntime) {
@@ -78855,6 +79231,10 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
78855
79231
  }
78856
79232
  clearRuntimeTimers(runtime);
78857
79233
  killAllTerminals();
79234
+ runtime._unsubscribeSubagentState?.();
79235
+ runtime._unsubscribeSubagentState = undefined;
79236
+ runtime._unsubscribeSubagentStreamEvents?.();
79237
+ runtime._unsubscribeSubagentStreamEvents = undefined;
78858
79238
  runtime.socket = null;
78859
79239
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
78860
79240
  rejectPendingApprovalResolvers(conversationRuntime, "WebSocket disconnected");
@@ -79052,7 +79432,9 @@ function createLegacyTestRuntime() {
79052
79432
  var __listenClientTestUtils;
79053
79433
  var init_client4 = __esm(async () => {
79054
79434
  init_fileIndex();
79435
+ init_messageQueueBridge();
79055
79436
  init_planName();
79437
+ init_subagentState();
79056
79438
  init_constants();
79057
79439
  init_queueRuntime();
79058
79440
  init_debug();
@@ -79165,22 +79547,22 @@ __export(exports_skills2, {
79165
79547
  SKILLS_DIR: () => SKILLS_DIR2,
79166
79548
  GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
79167
79549
  });
79168
- import { existsSync as existsSync21 } from "node:fs";
79550
+ import { existsSync as existsSync22 } from "node:fs";
79169
79551
  import { readdir as readdir6, readFile as readFile7, realpath as realpath4, stat as stat6 } from "node:fs/promises";
79170
- import { dirname as dirname11, join as join28 } from "node:path";
79552
+ import { dirname as dirname12, join as join29 } from "node:path";
79171
79553
  import { fileURLToPath as fileURLToPath8 } from "node:url";
79172
79554
  function getBundledSkillsPath2() {
79173
- const thisDir = dirname11(fileURLToPath8(import.meta.url));
79555
+ const thisDir = dirname12(fileURLToPath8(import.meta.url));
79174
79556
  if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
79175
- return join28(thisDir, "../skills/builtin");
79557
+ return join29(thisDir, "../skills/builtin");
79176
79558
  }
79177
- return join28(thisDir, "skills");
79559
+ return join29(thisDir, "skills");
79178
79560
  }
79179
79561
  function compareSkills2(a, b) {
79180
79562
  return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
79181
79563
  }
79182
79564
  function getAgentSkillsDir2(agentId) {
79183
- return join28(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
79565
+ return join29(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
79184
79566
  }
79185
79567
  async function getBundledSkills2() {
79186
79568
  const bundledPath = getBundledSkillsPath2();
@@ -79189,7 +79571,7 @@ async function getBundledSkills2() {
79189
79571
  }
79190
79572
  async function discoverSkillsFromDir2(skillsPath, source) {
79191
79573
  const errors = [];
79192
- if (!existsSync21(skillsPath)) {
79574
+ if (!existsSync22(skillsPath)) {
79193
79575
  return { skills: [], errors: [] };
79194
79576
  }
79195
79577
  const skills = [];
@@ -79203,7 +79585,7 @@ async function discoverSkillsFromDir2(skillsPath, source) {
79203
79585
  }
79204
79586
  return { skills, errors };
79205
79587
  }
79206
- async function discoverSkills2(projectSkillsPath = join28(process.cwd(), SKILLS_DIR2), agentId, options) {
79588
+ async function discoverSkills2(projectSkillsPath = join29(process.cwd(), SKILLS_DIR2), agentId, options) {
79207
79589
  const allErrors = [];
79208
79590
  const skillsById = new Map;
79209
79591
  const sourceSet = new Set(options?.sources ?? ALL_SKILL_SOURCES);
@@ -79258,7 +79640,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
79258
79640
  try {
79259
79641
  const entries = await readdir6(currentPath, { withFileTypes: true });
79260
79642
  for (const entry of entries) {
79261
- const fullPath = join28(currentPath, entry.name);
79643
+ const fullPath = join29(currentPath, entry.name);
79262
79644
  try {
79263
79645
  let isDirectory = entry.isDirectory();
79264
79646
  let isFile = entry.isFile();
@@ -79347,7 +79729,7 @@ ${lines.join(`
79347
79729
  var SKILLS_DIR2 = ".skills", GLOBAL_SKILLS_DIR2;
79348
79730
  var init_skills2 = __esm(() => {
79349
79731
  init_skillSources();
79350
- GLOBAL_SKILLS_DIR2 = join28(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
79732
+ GLOBAL_SKILLS_DIR2 = join29(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
79351
79733
  });
79352
79734
 
79353
79735
  // src/utils/fs.ts
@@ -79361,27 +79743,27 @@ __export(exports_fs, {
79361
79743
  exists: () => exists2
79362
79744
  });
79363
79745
  import {
79364
- existsSync as existsSync22,
79746
+ existsSync as existsSync23,
79365
79747
  readFileSync as fsReadFileSync2,
79366
79748
  writeFileSync as fsWriteFileSync2,
79367
- mkdirSync as mkdirSync15
79749
+ mkdirSync as mkdirSync16
79368
79750
  } from "node:fs";
79369
- import { dirname as dirname12 } from "node:path";
79751
+ import { dirname as dirname13 } from "node:path";
79370
79752
  async function readFile8(path23) {
79371
79753
  return fsReadFileSync2(path23, { encoding: "utf-8" });
79372
79754
  }
79373
79755
  async function writeFile5(path23, content) {
79374
- const dir = dirname12(path23);
79375
- if (!existsSync22(dir)) {
79376
- mkdirSync15(dir, { recursive: true });
79756
+ const dir = dirname13(path23);
79757
+ if (!existsSync23(dir)) {
79758
+ mkdirSync16(dir, { recursive: true });
79377
79759
  }
79378
79760
  fsWriteFileSync2(path23, content, { encoding: "utf-8", flush: true });
79379
79761
  }
79380
79762
  function exists2(path23) {
79381
- return existsSync22(path23);
79763
+ return existsSync23(path23);
79382
79764
  }
79383
79765
  async function mkdir5(path23, options) {
79384
- mkdirSync15(path23, options);
79766
+ mkdirSync16(path23, options);
79385
79767
  }
79386
79768
  async function readJsonFile(path23) {
79387
79769
  const text = await readFile8(path23);
@@ -79701,7 +80083,7 @@ __export(exports_auto_update, {
79701
80083
  import { execFile as execFile11 } from "node:child_process";
79702
80084
  import { realpathSync as realpathSync2 } from "node:fs";
79703
80085
  import { readdir as readdir7, rm as rm3 } from "node:fs/promises";
79704
- import { join as join29 } from "node:path";
80086
+ import { join as join30 } from "node:path";
79705
80087
  import { promisify as promisify11 } from "node:util";
79706
80088
  function debugLog3(...args) {
79707
80089
  if (DEBUG) {
@@ -79861,12 +80243,12 @@ async function getNpmGlobalPath() {
79861
80243
  }
79862
80244
  }
79863
80245
  async function cleanupOrphanedDirs(globalPath) {
79864
- const lettaAiDir = join29(globalPath, "lib/node_modules/@letta-ai");
80246
+ const lettaAiDir = join30(globalPath, "lib/node_modules/@letta-ai");
79865
80247
  try {
79866
80248
  const entries = await readdir7(lettaAiDir);
79867
80249
  for (const entry of entries) {
79868
80250
  if (entry.startsWith(".letta-code-")) {
79869
- const orphanPath = join29(lettaAiDir, entry);
80251
+ const orphanPath = join30(lettaAiDir, entry);
79870
80252
  debugLog3("Cleaning orphaned temp directory:", orphanPath);
79871
80253
  await rm3(orphanPath, { recursive: true, force: true });
79872
80254
  }
@@ -81380,7 +81762,7 @@ __export(exports_import, {
81380
81762
  });
81381
81763
  import { createReadStream } from "node:fs";
81382
81764
  import { chmod, mkdir as mkdir6, readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
81383
- import { dirname as dirname13, resolve as resolve26 } from "node:path";
81765
+ import { dirname as dirname14, resolve as resolve26 } from "node:path";
81384
81766
  async function importAgentFromFile(options) {
81385
81767
  const client = await getClient2();
81386
81768
  const resolvedPath = resolve26(options.filePath);
@@ -81439,7 +81821,7 @@ async function writeSkillFiles(skillDir, files) {
81439
81821
  }
81440
81822
  async function writeSkillFile(skillDir, filePath, content) {
81441
81823
  const fullPath = resolve26(skillDir, filePath);
81442
- await mkdir6(dirname13(fullPath), { recursive: true });
81824
+ await mkdir6(dirname14(fullPath), { recursive: true });
81443
81825
  await writeFile6(fullPath, content, "utf-8");
81444
81826
  const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
81445
81827
  if (isScript) {
@@ -81492,7 +81874,7 @@ function parseRegistryHandle(handle) {
81492
81874
  }
81493
81875
  async function importAgentFromRegistry(options) {
81494
81876
  const { tmpdir: tmpdir3 } = await import("node:os");
81495
- const { join: join31 } = await import("node:path");
81877
+ const { join: join32 } = await import("node:path");
81496
81878
  const { writeFile: writeFile7, unlink: unlink3 } = await import("node:fs/promises");
81497
81879
  const { author, name } = parseRegistryHandle(options.handle);
81498
81880
  const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
@@ -81504,7 +81886,7 @@ async function importAgentFromRegistry(options) {
81504
81886
  throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
81505
81887
  }
81506
81888
  const afContent = await response.text();
81507
- const tempPath = join31(tmpdir3(), `letta-import-${author}-${name}-${Date.now()}.af`);
81889
+ const tempPath = join32(tmpdir3(), `letta-import-${author}-${name}-${Date.now()}.af`);
81508
81890
  await writeFile7(tempPath, afContent, "utf-8");
81509
81891
  try {
81510
81892
  const result = await importAgentFromFile({
@@ -82279,11 +82661,7 @@ In headless mode, use:
82279
82661
  setConversationId2(conversationId);
82280
82662
  if (!isSubagent) {
82281
82663
  await settingsManager.loadLocalProjectSettings();
82282
- settingsManager.setLocalLastSession({ agentId: agent.id, conversationId }, process.cwd());
82283
- settingsManager.setGlobalLastSession({
82284
- agentId: agent.id,
82285
- conversationId
82286
- });
82664
+ settingsManager.persistSession(agent.id, conversationId);
82287
82665
  }
82288
82666
  setAgentContext2(agent.id, skillsDirectory, resolvedSkillSources);
82289
82667
  const outputFormat = values["output-format"] || "text";
@@ -82580,27 +82958,39 @@ ${loadedContents.join(`
82580
82958
  continue;
82581
82959
  }
82582
82960
  if (preStreamAction === "retry_conversation_busy") {
82583
- conversationBusyRetries += 1;
82584
- const retryDelayMs = getRetryDelayMs({
82585
- category: "conversation_busy",
82586
- attempt: conversationBusyRetries
82587
- });
82588
- if (outputFormat === "stream-json") {
82589
- const retryMsg = {
82590
- type: "retry",
82591
- reason: "error",
82592
- attempt: conversationBusyRetries,
82593
- max_attempts: CONVERSATION_BUSY_MAX_RETRIES,
82594
- delay_ms: retryDelayMs,
82595
- session_id: sessionId,
82596
- uuid: `retry-conversation-busy-${randomUUID8()}`
82597
- };
82598
- console.log(JSON.stringify(retryMsg));
82599
- } else {
82600
- console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
82961
+ const messageOtid = currentInput.map((item) => item.otid).find((v) => typeof v === "string");
82962
+ try {
82963
+ const client2 = await getClient2();
82964
+ stream2 = await client2.conversations.messages.stream(conversationId, {
82965
+ agent_id: conversationId === "default" ? agent?.id ?? undefined : undefined,
82966
+ otid: messageOtid ?? undefined,
82967
+ starting_after: 0,
82968
+ batch_size: 1000
82969
+ });
82970
+ conversationBusyRetries = 0;
82971
+ } catch {
82972
+ conversationBusyRetries += 1;
82973
+ const retryDelayMs = getRetryDelayMs({
82974
+ category: "conversation_busy",
82975
+ attempt: conversationBusyRetries
82976
+ });
82977
+ if (outputFormat === "stream-json") {
82978
+ const retryMsg = {
82979
+ type: "retry",
82980
+ reason: "error",
82981
+ attempt: conversationBusyRetries,
82982
+ max_attempts: CONVERSATION_BUSY_MAX_RETRIES,
82983
+ delay_ms: retryDelayMs,
82984
+ session_id: sessionId,
82985
+ uuid: `retry-conversation-busy-${randomUUID8()}`
82986
+ };
82987
+ console.log(JSON.stringify(retryMsg));
82988
+ } else {
82989
+ console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
82990
+ }
82991
+ await new Promise((resolve27) => setTimeout(resolve27, retryDelayMs));
82992
+ continue;
82601
82993
  }
82602
- await new Promise((resolve27) => setTimeout(resolve27, retryDelayMs));
82603
- continue;
82604
82994
  }
82605
82995
  if (preStreamAction === "retry_transient") {
82606
82996
  const attempt = llmApiErrorRetries + 1;
@@ -84464,9 +84854,9 @@ __export(exports_settings, {
84464
84854
  getSetting: () => getSetting
84465
84855
  });
84466
84856
  import { homedir as homedir27 } from "node:os";
84467
- import { join as join32 } from "node:path";
84857
+ import { join as join33 } from "node:path";
84468
84858
  function getSettingsPath() {
84469
- return join32(homedir27(), ".letta", "settings.json");
84859
+ return join33(homedir27(), ".letta", "settings.json");
84470
84860
  }
84471
84861
  async function loadSettings() {
84472
84862
  const settingsPath = getSettingsPath();
@@ -84503,7 +84893,7 @@ async function getSetting(key) {
84503
84893
  return settings[key];
84504
84894
  }
84505
84895
  function getProjectSettingsPath() {
84506
- return join32(process.cwd(), ".letta", "settings.local.json");
84896
+ return join33(process.cwd(), ".letta", "settings.local.json");
84507
84897
  }
84508
84898
  async function loadProjectSettings() {
84509
84899
  const settingsPath = getProjectSettingsPath();
@@ -84521,7 +84911,7 @@ async function loadProjectSettings() {
84521
84911
  }
84522
84912
  async function saveProjectSettings(settings) {
84523
84913
  const settingsPath = getProjectSettingsPath();
84524
- const dirPath = join32(process.cwd(), ".letta");
84914
+ const dirPath = join33(process.cwd(), ".letta");
84525
84915
  try {
84526
84916
  if (!exists(dirPath)) {
84527
84917
  await mkdir(dirPath, { recursive: true });
@@ -101168,9 +101558,9 @@ function getFileEditHeader(toolName, toolArgs) {
101168
101558
  const relPath = relative15(cwd2, filePath);
101169
101559
  const displayPath = relPath.startsWith("..") ? filePath : relPath;
101170
101560
  if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
101171
- const { existsSync: existsSync25 } = __require("node:fs");
101561
+ const { existsSync: existsSync26 } = __require("node:fs");
101172
101562
  try {
101173
- if (existsSync25(filePath)) {
101563
+ if (existsSync26(filePath)) {
101174
101564
  return `Overwrite ${displayPath}?`;
101175
101565
  }
101176
101566
  } catch {}
@@ -101879,9 +102269,9 @@ function getHeaderText(fileEdit) {
101879
102269
  const relPath = relative15(cwd2, fileEdit.filePath);
101880
102270
  const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
101881
102271
  if (t === "write" || t === "write_file" || t === "writefile" || t === "write_file_gemini" || t === "writefilegemini") {
101882
- const { existsSync: existsSync25 } = __require("node:fs");
102272
+ const { existsSync: existsSync26 } = __require("node:fs");
101883
102273
  try {
101884
- if (existsSync25(fileEdit.filePath)) {
102274
+ if (existsSync26(fileEdit.filePath)) {
101885
102275
  return `Overwrite ${displayPath}?`;
101886
102276
  }
101887
102277
  } catch {}
@@ -103519,9 +103909,9 @@ html.dark .agent-name { color: var(--text-dim); }
103519
103909
  var init_plan_viewer_template = () => {};
103520
103910
 
103521
103911
  // src/web/generate-plan-viewer.ts
103522
- import { chmodSync as chmodSync2, existsSync as existsSync25, mkdirSync as mkdirSync18, writeFileSync as writeFileSync12 } from "node:fs";
103912
+ import { chmodSync as chmodSync2, existsSync as existsSync26, mkdirSync as mkdirSync19, writeFileSync as writeFileSync13 } from "node:fs";
103523
103913
  import { homedir as homedir28 } from "node:os";
103524
- import { join as join33 } from "node:path";
103914
+ import { join as join34 } from "node:path";
103525
103915
  async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
103526
103916
  const data = {
103527
103917
  agent: { name: options?.agentName ?? "" },
@@ -103531,14 +103921,14 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
103531
103921
  };
103532
103922
  const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
103533
103923
  const html = plan_viewer_template_default.replace("<!--LETTA_PLAN_DATA_PLACEHOLDER-->", () => jsonPayload);
103534
- if (!existsSync25(VIEWERS_DIR)) {
103535
- mkdirSync18(VIEWERS_DIR, { recursive: true, mode: 448 });
103924
+ if (!existsSync26(VIEWERS_DIR)) {
103925
+ mkdirSync19(VIEWERS_DIR, { recursive: true, mode: 448 });
103536
103926
  }
103537
103927
  try {
103538
103928
  chmodSync2(VIEWERS_DIR, 448);
103539
103929
  } catch {}
103540
- const filePath = join33(VIEWERS_DIR, "plan.html");
103541
- writeFileSync12(filePath, html);
103930
+ const filePath = join34(VIEWERS_DIR, "plan.html");
103931
+ writeFileSync13(filePath, html);
103542
103932
  chmodSync2(filePath, 384);
103543
103933
  const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
103544
103934
  if (!skipOpen) {
@@ -103554,7 +103944,7 @@ async function generateAndOpenPlanViewer(planContent, planFilePath, options) {
103554
103944
  var VIEWERS_DIR;
103555
103945
  var init_generate_plan_viewer = __esm(() => {
103556
103946
  init_plan_viewer_template();
103557
- VIEWERS_DIR = join33(homedir28(), ".letta", "viewers");
103947
+ VIEWERS_DIR = join34(homedir28(), ".letta", "viewers");
103558
103948
  });
103559
103949
 
103560
103950
  // src/cli/components/StaticPlanApproval.tsx
@@ -105599,9 +105989,9 @@ var init_pasteRegistry = __esm(() => {
105599
105989
 
105600
105990
  // src/cli/helpers/clipboard.ts
105601
105991
  import { execFileSync as execFileSync3 } from "node:child_process";
105602
- import { existsSync as existsSync26, readFileSync as readFileSync12, statSync as statSync8, unlinkSync as unlinkSync8 } from "node:fs";
105992
+ import { existsSync as existsSync27, readFileSync as readFileSync12, statSync as statSync8, unlinkSync as unlinkSync8 } from "node:fs";
105603
105993
  import { tmpdir as tmpdir3 } from "node:os";
105604
- import { basename as basename4, extname as extname5, isAbsolute as isAbsolute18, join as join34, resolve as resolve27 } from "node:path";
105994
+ import { basename as basename4, extname as extname5, isAbsolute as isAbsolute18, join as join35, resolve as resolve27 } from "node:path";
105605
105995
  function countLines2(text) {
105606
105996
  return (text.match(/\r\n|\r|\n/g) || []).length + 1;
105607
105997
  }
@@ -105651,7 +106041,7 @@ function translatePasteForImages(paste) {
105651
106041
  if (!isAbsolute18(filePath))
105652
106042
  filePath = resolve27(process.cwd(), filePath);
105653
106043
  const ext3 = extname5(filePath || "").toLowerCase();
105654
- if (IMAGE_EXTS.has(ext3) && existsSync26(filePath) && statSync8(filePath).isFile()) {
106044
+ if (IMAGE_EXTS.has(ext3) && existsSync27(filePath) && statSync8(filePath).isFile()) {
105655
106045
  const buf = readFileSync12(filePath);
105656
106046
  const b64 = buf.toString("base64");
105657
106047
  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";
@@ -105669,7 +106059,7 @@ function translatePasteForImages(paste) {
105669
106059
  function getClipboardImageToTempFile() {
105670
106060
  if (process.platform !== "darwin")
105671
106061
  return null;
105672
- const tempPath = join34(tmpdir3(), `letta-clipboard-${Date.now()}.bin`);
106062
+ const tempPath = join35(tmpdir3(), `letta-clipboard-${Date.now()}.bin`);
105673
106063
  try {
105674
106064
  const jxa = `
105675
106065
  ObjC.import('AppKit');
@@ -105692,11 +106082,11 @@ function getClipboardImageToTempFile() {
105692
106082
  encoding: "utf8",
105693
106083
  stdio: ["ignore", "pipe", "ignore"]
105694
106084
  }).trim();
105695
- if (!uti || !existsSync26(tempPath))
106085
+ if (!uti || !existsSync27(tempPath))
105696
106086
  return null;
105697
106087
  return { tempPath, uti };
105698
106088
  } catch {
105699
- if (existsSync26(tempPath)) {
106089
+ if (existsSync27(tempPath)) {
105700
106090
  try {
105701
106091
  unlinkSync8(tempPath);
105702
106092
  } catch {}
@@ -105729,7 +106119,7 @@ async function tryImportClipboardImageMac() {
105729
106119
  height: resized.height
105730
106120
  };
105731
106121
  } catch (err) {
105732
- if (existsSync26(tempPath)) {
106122
+ if (existsSync27(tempPath)) {
105733
106123
  try {
105734
106124
  unlinkSync8(tempPath);
105735
106125
  } catch {}
@@ -106028,6 +106418,15 @@ function PasteAwareTextInput({
106028
106418
  setNudgeCursorOffset(nextCaret);
106029
106419
  caretOffsetRef.current = nextCaret;
106030
106420
  };
106421
+ const moveCursorToStart = () => {
106422
+ setNudgeCursorOffset(0);
106423
+ caretOffsetRef.current = 0;
106424
+ };
106425
+ const moveCursorToEnd = () => {
106426
+ const endPos = displayValueRef.current.length;
106427
+ setNudgeCursorOffset(endPos);
106428
+ caretOffsetRef.current = endPos;
106429
+ };
106031
106430
  const handleRawInput = (payload) => {
106032
106431
  if (!focusRef.current)
106033
106432
  return;
@@ -106052,6 +106451,14 @@ function PasteAwareTextInput({
106052
106451
  insertNewlineAtCursor();
106053
106452
  return;
106054
106453
  }
106454
+ if (sequence === "\x1B[H" || sequence === "\x1B[1~" || sequence === "\x1BOH") {
106455
+ moveCursorToStart();
106456
+ return;
106457
+ }
106458
+ if (sequence === "\x1B[F" || sequence === "\x1B[4~" || sequence === "\x1BOF") {
106459
+ moveCursorToEnd();
106460
+ return;
106461
+ }
106055
106462
  if (sequence === "\x1B[3~" || /^\x1b\[3;\d+~$/.test(sequence)) {
106056
106463
  globalThis.__lettaForwardDeleteTimestamp = Date.now();
106057
106464
  forwardDeleteAtCursor(caretOffsetRef.current);
@@ -106288,6 +106695,102 @@ var init_FeedbackDialog = __esm(async () => {
106288
106695
  jsx_dev_runtime39 = __toESM(require_jsx_dev_runtime(), 1);
106289
106696
  });
106290
106697
 
106698
+ // src/cli/commands/secret.ts
106699
+ async function handleSecretCommand(args) {
106700
+ const [subcommand, key, value] = args;
106701
+ switch (subcommand) {
106702
+ case "set": {
106703
+ if (!key) {
106704
+ return { output: "Usage: /secret set KEY value" };
106705
+ }
106706
+ if (!value) {
106707
+ return {
106708
+ output: `Usage: /secret set KEY value
106709
+ Provide a value for the secret.`
106710
+ };
106711
+ }
106712
+ const normalizedKey = key.toUpperCase();
106713
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(normalizedKey)) {
106714
+ return {
106715
+ output: `Invalid secret name '${key}'. Use uppercase letters, numbers, and underscores only. Must start with a letter or underscore.`
106716
+ };
106717
+ }
106718
+ try {
106719
+ await setSecretOnServer(normalizedKey, value);
106720
+ return { output: `Secret '$${normalizedKey}' set.` };
106721
+ } catch (error) {
106722
+ return {
106723
+ output: `Failed to set secret: ${error instanceof Error ? error.message : String(error)}`
106724
+ };
106725
+ }
106726
+ }
106727
+ case "list": {
106728
+ const names = listSecretNames();
106729
+ if (names.length === 0) {
106730
+ return {
106731
+ output: `No secrets stored.
106732
+ Use /secret set KEY value to add a secret.`
106733
+ };
106734
+ }
106735
+ const lines = names.map((n) => ` $${n}`);
106736
+ return {
106737
+ output: `Available secrets (${names.length}):
106738
+ ${lines.join(`
106739
+ `)}
106740
+
106741
+ Use $SECRET_NAME in shell commands to reference them.`
106742
+ };
106743
+ }
106744
+ case "unset":
106745
+ case "delete":
106746
+ case "remove":
106747
+ case "rm": {
106748
+ if (!key) {
106749
+ return { output: "Usage: /secret unset KEY" };
106750
+ }
106751
+ const normalizedKey = key.toUpperCase();
106752
+ try {
106753
+ const deleted = await deleteSecretOnServer(normalizedKey);
106754
+ if (deleted) {
106755
+ return { output: `Secret '$${normalizedKey}' unset.` };
106756
+ }
106757
+ return {
106758
+ output: `Secret '$${normalizedKey}' not found.
106759
+ Use /secret list to see available secrets.`
106760
+ };
106761
+ } catch (error) {
106762
+ return {
106763
+ output: `Failed to unset secret: ${error instanceof Error ? error.message : String(error)}`
106764
+ };
106765
+ }
106766
+ }
106767
+ case undefined:
106768
+ case "":
106769
+ case "help": {
106770
+ return {
106771
+ output: `Secret management commands:
106772
+
106773
+ /secret set KEY value Set a secret (KEY is normalized to uppercase)
106774
+ /secret list List available secret names
106775
+ /secret unset KEY Unset a secret
106776
+
106777
+ Secrets are stored on the Letta server and available to the agent via /memory/system/secrets.md.
106778
+ The key must be all caps and can include underscores and numbers, but must start with a letter or underscore.
106779
+ Your agent can use $SECRET_NAME in shell commands and the value will be substituted at runtime, without the secret value being leaked into agent context.`
106780
+ };
106781
+ }
106782
+ default: {
106783
+ return {
106784
+ output: `Unknown subcommand '${subcommand}'.
106785
+ Use /secret help for usage.`
106786
+ };
106787
+ }
106788
+ }
106789
+ }
106790
+ var init_secret = __esm(async () => {
106791
+ await init_secretsStore();
106792
+ });
106793
+
106291
106794
  // src/cli/utils/terminalKeybindingInstaller.ts
106292
106795
  var exports_terminalKeybindingInstaller = {};
106293
106796
  __export(exports_terminalKeybindingInstaller, {
@@ -106306,13 +106809,13 @@ __export(exports_terminalKeybindingInstaller, {
106306
106809
  });
106307
106810
  import {
106308
106811
  copyFileSync,
106309
- existsSync as existsSync27,
106310
- mkdirSync as mkdirSync19,
106812
+ existsSync as existsSync28,
106813
+ mkdirSync as mkdirSync20,
106311
106814
  readFileSync as readFileSync13,
106312
- writeFileSync as writeFileSync13
106815
+ writeFileSync as writeFileSync14
106313
106816
  } from "node:fs";
106314
106817
  import { homedir as homedir29, platform as platform5 } from "node:os";
106315
- import { dirname as dirname14, join as join35 } from "node:path";
106818
+ import { dirname as dirname15, join as join36 } from "node:path";
106316
106819
  function detectTerminalType() {
106317
106820
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
106318
106821
  return "cursor";
@@ -106344,16 +106847,16 @@ function getKeybindingsPath(terminal) {
106344
106847
  }[terminal];
106345
106848
  const os7 = platform5();
106346
106849
  if (os7 === "darwin") {
106347
- return join35(homedir29(), "Library", "Application Support", appName, "User", "keybindings.json");
106850
+ return join36(homedir29(), "Library", "Application Support", appName, "User", "keybindings.json");
106348
106851
  }
106349
106852
  if (os7 === "win32") {
106350
106853
  const appData = process.env.APPDATA;
106351
106854
  if (!appData)
106352
106855
  return null;
106353
- return join35(appData, appName, "User", "keybindings.json");
106856
+ return join36(appData, appName, "User", "keybindings.json");
106354
106857
  }
106355
106858
  if (os7 === "linux") {
106356
- return join35(homedir29(), ".config", appName, "User", "keybindings.json");
106859
+ return join36(homedir29(), ".config", appName, "User", "keybindings.json");
106357
106860
  }
106358
106861
  return null;
106359
106862
  }
@@ -106375,7 +106878,7 @@ function parseKeybindings(content) {
106375
106878
  }
106376
106879
  }
106377
106880
  function keybindingExists(keybindingsPath) {
106378
- if (!existsSync27(keybindingsPath))
106881
+ if (!existsSync28(keybindingsPath))
106379
106882
  return false;
106380
106883
  try {
106381
106884
  const content = readFileSync13(keybindingsPath, { encoding: "utf-8" });
@@ -106388,7 +106891,7 @@ function keybindingExists(keybindingsPath) {
106388
106891
  }
106389
106892
  }
106390
106893
  function createBackup(keybindingsPath) {
106391
- if (!existsSync27(keybindingsPath))
106894
+ if (!existsSync28(keybindingsPath))
106392
106895
  return null;
106393
106896
  const backupPath = `${keybindingsPath}.letta-backup`;
106394
106897
  try {
@@ -106403,13 +106906,13 @@ function installKeybinding(keybindingsPath) {
106403
106906
  if (keybindingExists(keybindingsPath)) {
106404
106907
  return { success: true, alreadyExists: true };
106405
106908
  }
106406
- const parentDir = dirname14(keybindingsPath);
106407
- if (!existsSync27(parentDir)) {
106408
- mkdirSync19(parentDir, { recursive: true });
106909
+ const parentDir = dirname15(keybindingsPath);
106910
+ if (!existsSync28(parentDir)) {
106911
+ mkdirSync20(parentDir, { recursive: true });
106409
106912
  }
106410
106913
  let keybindings = [];
106411
106914
  let backupPath = null;
106412
- if (existsSync27(keybindingsPath)) {
106915
+ if (existsSync28(keybindingsPath)) {
106413
106916
  backupPath = createBackup(keybindingsPath);
106414
106917
  const content = readFileSync13(keybindingsPath, { encoding: "utf-8" });
106415
106918
  const parsed = parseKeybindings(content);
@@ -106424,7 +106927,7 @@ function installKeybinding(keybindingsPath) {
106424
106927
  keybindings.push(SHIFT_ENTER_KEYBINDING);
106425
106928
  const newContent = `${JSON.stringify(keybindings, null, 2)}
106426
106929
  `;
106427
- writeFileSync13(keybindingsPath, newContent, { encoding: "utf-8" });
106930
+ writeFileSync14(keybindingsPath, newContent, { encoding: "utf-8" });
106428
106931
  return {
106429
106932
  success: true,
106430
106933
  backupPath: backupPath ?? undefined
@@ -106439,7 +106942,7 @@ function installKeybinding(keybindingsPath) {
106439
106942
  }
106440
106943
  function removeKeybinding(keybindingsPath) {
106441
106944
  try {
106442
- if (!existsSync27(keybindingsPath)) {
106945
+ if (!existsSync28(keybindingsPath)) {
106443
106946
  return { success: true };
106444
106947
  }
106445
106948
  const content = readFileSync13(keybindingsPath, { encoding: "utf-8" });
@@ -106453,7 +106956,7 @@ function removeKeybinding(keybindingsPath) {
106453
106956
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
106454
106957
  const newContent = `${JSON.stringify(filtered, null, 2)}
106455
106958
  `;
106456
- writeFileSync13(keybindingsPath, newContent, { encoding: "utf-8" });
106959
+ writeFileSync14(keybindingsPath, newContent, { encoding: "utf-8" });
106457
106960
  return { success: true };
106458
106961
  } catch (error) {
106459
106962
  const message = error instanceof Error ? error.message : String(error);
@@ -106506,17 +107009,17 @@ function getWezTermConfigPath() {
106506
107009
  }
106507
107010
  const xdgConfig = process.env.XDG_CONFIG_HOME;
106508
107011
  if (xdgConfig) {
106509
- const xdgPath = join35(xdgConfig, "wezterm", "wezterm.lua");
106510
- if (existsSync27(xdgPath))
107012
+ const xdgPath = join36(xdgConfig, "wezterm", "wezterm.lua");
107013
+ if (existsSync28(xdgPath))
106511
107014
  return xdgPath;
106512
107015
  }
106513
- const configPath = join35(homedir29(), ".config", "wezterm", "wezterm.lua");
106514
- if (existsSync27(configPath))
107016
+ const configPath = join36(homedir29(), ".config", "wezterm", "wezterm.lua");
107017
+ if (existsSync28(configPath))
106515
107018
  return configPath;
106516
- return join35(homedir29(), ".wezterm.lua");
107019
+ return join36(homedir29(), ".wezterm.lua");
106517
107020
  }
106518
107021
  function wezTermDeleteFixExists(configPath) {
106519
- if (!existsSync27(configPath))
107022
+ if (!existsSync28(configPath))
106520
107023
  return false;
106521
107024
  try {
106522
107025
  const content = readFileSync13(configPath, { encoding: "utf-8" });
@@ -106533,7 +107036,7 @@ function installWezTermDeleteFix() {
106533
107036
  }
106534
107037
  let content = "";
106535
107038
  let backupPath = null;
106536
- if (existsSync27(configPath)) {
107039
+ if (existsSync28(configPath)) {
106537
107040
  backupPath = `${configPath}.letta-backup`;
106538
107041
  copyFileSync(configPath, backupPath);
106539
107042
  content = readFileSync13(configPath, { encoding: "utf-8" });
@@ -106562,11 +107065,11 @@ return config`);
106562
107065
  ${WEZTERM_DELETE_FIX}
106563
107066
  `;
106564
107067
  }
106565
- const parentDir = dirname14(configPath);
106566
- if (!existsSync27(parentDir)) {
106567
- mkdirSync19(parentDir, { recursive: true });
107068
+ const parentDir = dirname15(configPath);
107069
+ if (!existsSync28(parentDir)) {
107070
+ mkdirSync20(parentDir, { recursive: true });
106568
107071
  }
106569
- writeFileSync13(configPath, content, { encoding: "utf-8" });
107072
+ writeFileSync14(configPath, content, { encoding: "utf-8" });
106570
107073
  return {
106571
107074
  success: true,
106572
107075
  backupPath: backupPath ?? undefined
@@ -106639,7 +107142,8 @@ async function executeCommand(input) {
106639
107142
  }
106640
107143
  }
106641
107144
  var commands;
106642
- var init_registry = __esm(() => {
107145
+ var init_registry = __esm(async () => {
107146
+ await init_secret();
106643
107147
  commands = {
106644
107148
  "/agents": {
106645
107149
  desc: "Browse agents (pinned, Letta Code, all)",
@@ -106774,6 +107278,14 @@ var init_registry = __esm(() => {
106774
107278
  return "Starting new conversation...";
106775
107279
  }
106776
107280
  },
107281
+ "/fork": {
107282
+ desc: "Fork the current conversation",
107283
+ order: 20.5,
107284
+ noArgs: true,
107285
+ handler: () => {
107286
+ return "Forking conversation...";
107287
+ }
107288
+ },
106777
107289
  "/pin": {
106778
107290
  desc: "Pin current agent globally, or use -l for local only",
106779
107291
  order: 22,
@@ -106849,6 +107361,15 @@ var init_registry = __esm(() => {
106849
107361
  return "Opening MCP server manager...";
106850
107362
  }
106851
107363
  },
107364
+ "/secret": {
107365
+ desc: "Manage secrets for shell commands",
107366
+ order: 33,
107367
+ args: "<set|list|unset> [key] [value]",
107368
+ handler: async (args) => {
107369
+ const result = await handleSecretCommand(args);
107370
+ return result.output;
107371
+ }
107372
+ },
106852
107373
  "/usage": {
106853
107374
  desc: "Show session usage statistics and balance",
106854
107375
  order: 33,
@@ -107110,9 +107631,9 @@ __export(exports_custom, {
107110
107631
  GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
107111
107632
  COMMANDS_DIR: () => COMMANDS_DIR
107112
107633
  });
107113
- import { existsSync as existsSync28 } from "node:fs";
107634
+ import { existsSync as existsSync29 } from "node:fs";
107114
107635
  import { readdir as readdir8, readFile as readFile10 } from "node:fs/promises";
107115
- import { basename as basename5, dirname as dirname15, join as join36 } from "node:path";
107636
+ import { basename as basename5, dirname as dirname16, join as join37 } from "node:path";
107116
107637
  async function getCustomCommands() {
107117
107638
  if (cachedCommands !== null) {
107118
107639
  return cachedCommands;
@@ -107123,7 +107644,7 @@ async function getCustomCommands() {
107123
107644
  function refreshCustomCommands() {
107124
107645
  cachedCommands = null;
107125
107646
  }
107126
- async function discoverCustomCommands(projectPath = join36(process.cwd(), COMMANDS_DIR)) {
107647
+ async function discoverCustomCommands(projectPath = join37(process.cwd(), COMMANDS_DIR)) {
107127
107648
  const commandsById = new Map;
107128
107649
  const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
107129
107650
  for (const cmd of userCommands) {
@@ -107144,7 +107665,7 @@ async function discoverCustomCommands(projectPath = join36(process.cwd(), COMMAN
107144
107665
  return result;
107145
107666
  }
107146
107667
  async function discoverFromDirectory(dirPath, source2) {
107147
- if (!existsSync28(dirPath)) {
107668
+ if (!existsSync29(dirPath)) {
107148
107669
  return [];
107149
107670
  }
107150
107671
  const commands2 = [];
@@ -107155,7 +107676,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
107155
107676
  try {
107156
107677
  const entries = await readdir8(currentPath, { withFileTypes: true });
107157
107678
  for (const entry of entries) {
107158
- const fullPath = join36(currentPath, entry.name);
107679
+ const fullPath = join37(currentPath, entry.name);
107159
107680
  if (entry.isDirectory()) {
107160
107681
  await findCommandFiles(fullPath, rootPath, commands2, source2);
107161
107682
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -107173,7 +107694,7 @@ async function parseCommandFile(filePath, rootPath, source2) {
107173
107694
  const content = await readFile10(filePath, "utf-8");
107174
107695
  const { frontmatter, body } = parseFrontmatter(content);
107175
107696
  const id = basename5(filePath, ".md");
107176
- const relativePath = dirname15(filePath).slice(rootPath.length);
107697
+ const relativePath = dirname16(filePath).slice(rootPath.length);
107177
107698
  const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
107178
107699
  let description = getStringField(frontmatter, "description");
107179
107700
  if (!description) {
@@ -107240,7 +107761,7 @@ async function findCustomCommand(commandName) {
107240
107761
  }
107241
107762
  var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
107242
107763
  var init_custom = __esm(() => {
107243
- GLOBAL_COMMANDS_DIR = join36(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
107764
+ GLOBAL_COMMANDS_DIR = join37(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
107244
107765
  });
107245
107766
 
107246
107767
  // src/cli/components/HelpDialog.tsx
@@ -107509,10 +108030,10 @@ function HelpDialog({ onClose }) {
107509
108030
  var import_react63, jsx_dev_runtime40, PAGE_SIZE = 10, HELP_TABS;
107510
108031
  var init_HelpDialog = __esm(async () => {
107511
108032
  init_version();
107512
- init_registry();
107513
108033
  init_colors();
107514
108034
  await __promiseAll([
107515
108035
  init_build2(),
108036
+ init_registry(),
107516
108037
  init_Text2()
107517
108038
  ]);
107518
108039
  import_react63 = __toESM(require_react(), 1);
@@ -110160,7 +110681,7 @@ var init_AgentInfoBar = __esm(async () => {
110160
110681
 
110161
110682
  // src/cli/helpers/fileSearch.ts
110162
110683
  import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
110163
- import { join as join37, relative as relative15, resolve as resolve29 } from "node:path";
110684
+ import { join as join38, relative as relative15, resolve as resolve29 } from "node:path";
110164
110685
  function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
110165
110686
  if (results.length >= maxResults || depth >= maxDepth) {
110166
110687
  return results;
@@ -110169,7 +110690,7 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [],
110169
110690
  const entries = readdirSync12(dir);
110170
110691
  for (const entry of entries) {
110171
110692
  try {
110172
- const fullPath = join37(dir, entry);
110693
+ const fullPath = join38(dir, entry);
110173
110694
  const relativePath = relative15(process.cwd(), fullPath);
110174
110695
  if (shouldHardExcludeEntry(entry)) {
110175
110696
  continue;
@@ -110247,7 +110768,7 @@ async function searchFiles(query, deep = false) {
110247
110768
  const matchingEntries = entries.filter((entry) => !shouldHardExcludeEntry(entry) && (searchPattern.length === 0 || entry.toLowerCase().includes(lowerPattern)));
110248
110769
  for (const entry of matchingEntries.slice(0, 50)) {
110249
110770
  try {
110250
- const fullPath = join37(searchDir, entry);
110771
+ const fullPath = join38(searchDir, entry);
110251
110772
  const stats = statSync9(fullPath);
110252
110773
  const relativePath = relative15(process.cwd(), fullPath);
110253
110774
  results.push({
@@ -110749,10 +111270,10 @@ function SlashCommandAutocomplete({
110749
111270
  }
110750
111271
  var import_react69, jsx_dev_runtime46, VISIBLE_COMMANDS = 7, CMD_COL_WIDTH = 14, _allCommands;
110751
111272
  var init_SlashCommandAutocomplete = __esm(async () => {
110752
- init_registry();
110753
111273
  init_useTerminalWidth();
110754
111274
  await __promiseAll([
110755
111275
  init_settings_manager(),
111276
+ init_registry(),
110756
111277
  init_useAutocompleteNavigation(),
110757
111278
  init_Autocomplete(),
110758
111279
  init_Text2()
@@ -111148,6 +111669,7 @@ function Input({
111148
111669
  agentName,
111149
111670
  currentModel,
111150
111671
  currentModelProvider,
111672
+ hasTemporaryModelOverride = false,
111151
111673
  currentReasoningEffort,
111152
111674
  messageQueue,
111153
111675
  onEnterQueueEditMode,
@@ -111749,6 +112271,7 @@ function Input({
111749
112271
  currentReasoningEffort,
111750
112272
  isOpenAICodexProvider: currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
111751
112273
  isByokProvider: currentModelProvider?.startsWith("lc-") || currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
112274
+ hasTemporaryModelOverride,
111752
112275
  hideFooter,
111753
112276
  rightColumnWidth: footerRightColumnWidth,
111754
112277
  statusLineText,
@@ -111793,6 +112316,7 @@ function Input({
111793
112316
  currentModel,
111794
112317
  currentReasoningEffort,
111795
112318
  currentModelProvider,
112319
+ hasTemporaryModelOverride,
111796
112320
  hideFooter,
111797
112321
  footerRightColumnWidth,
111798
112322
  reserveInputSpace,
@@ -111888,6 +112412,7 @@ var init_InputRich = __esm(async () => {
111888
112412
  currentReasoningEffort,
111889
112413
  isOpenAICodexProvider,
111890
112414
  isByokProvider,
112415
+ hasTemporaryModelOverride,
111891
112416
  hideFooter,
111892
112417
  rightColumnWidth,
111893
112418
  statusLineText,
@@ -111936,11 +112461,12 @@ var init_InputRich = __esm(async () => {
111936
112461
  const displayAgentName = truncateEnd(agentName || "Unnamed", maxAgentChars);
111937
112462
  const reasoningTag = getReasoningEffortTag(currentReasoningEffort);
111938
112463
  const byokExtraChars = isByokProvider ? 2 : 0;
111939
- const baseReservedChars = displayAgentName.length + byokExtraChars + 4;
112464
+ const tempOverrideExtraChars = hasTemporaryModelOverride ? 2 : 0;
112465
+ const baseReservedChars = displayAgentName.length + byokExtraChars + tempOverrideExtraChars + 4;
111940
112466
  const modelWithReasoning = (currentModel ?? "unknown") + (reasoningTag ? ` (${reasoningTag})` : "");
111941
112467
  const maxModelChars = Math.max(8, rightColumnWidth - baseReservedChars);
111942
112468
  const displayModel = truncateEnd(modelWithReasoning, maxModelChars);
111943
- const rightTextLength = displayAgentName.length + displayModel.length + byokExtraChars + 3;
112469
+ const rightTextLength = displayAgentName.length + displayModel.length + byokExtraChars + tempOverrideExtraChars + 3;
111944
112470
  const rightPrefixSpaces = Math.max(0, rightColumnWidth - rightTextLength);
111945
112471
  const bgIndicatorWidth = backgroundAgents.length > 0 ? 3 + bgAgentParts.reduce((acc, p, i) => acc + (i > 0 ? 3 : 0) + p.typeLabel.length + 1 + p.elapsed.length + 2, 0) + 3 : 0;
111946
112472
  const effectiveRightWidth = backgroundAgents.length > 0 ? Math.max(rightColumnWidth, bgIndicatorWidth + rightTextLength) : rightColumnWidth;
@@ -111953,9 +112479,19 @@ var init_InputRich = __esm(async () => {
111953
112479
  parts.push(source_default.dim(" "));
111954
112480
  parts.push(isOpenAICodexProvider ? source_default.hex("#74AA9C")("▲") : source_default.yellow("▲"));
111955
112481
  }
112482
+ if (hasTemporaryModelOverride) {
112483
+ parts.push(source_default.dim(" "));
112484
+ parts.push(source_default.yellow("▲"));
112485
+ }
111956
112486
  parts.push(source_default.dim("]"));
111957
112487
  return parts.join("");
111958
- }, [displayAgentName, displayModel, isByokProvider, isOpenAICodexProvider]);
112488
+ }, [
112489
+ displayAgentName,
112490
+ displayModel,
112491
+ isByokProvider,
112492
+ isOpenAICodexProvider,
112493
+ hasTemporaryModelOverride
112494
+ ]);
111959
112495
  const rightLabel = import_react73.useMemo(() => " ".repeat(rightPrefixSpaces) + rightLabelCore, [rightPrefixSpaces, rightLabelCore]);
111960
112496
  return /* @__PURE__ */ jsx_dev_runtime50.jsxDEV(Box_default, {
111961
112497
  flexDirection: "row",
@@ -112299,15 +112835,15 @@ var init_InputRich = __esm(async () => {
112299
112835
  // src/cli/commands/install-github-app.ts
112300
112836
  import { execFileSync as execFileSync4 } from "node:child_process";
112301
112837
  import {
112302
- existsSync as existsSync29,
112303
- mkdirSync as mkdirSync20,
112838
+ existsSync as existsSync30,
112839
+ mkdirSync as mkdirSync21,
112304
112840
  mkdtempSync,
112305
112841
  readFileSync as readFileSync14,
112306
112842
  rmSync as rmSync3,
112307
- writeFileSync as writeFileSync14
112843
+ writeFileSync as writeFileSync15
112308
112844
  } from "node:fs";
112309
112845
  import { tmpdir as tmpdir4 } from "node:os";
112310
- import { dirname as dirname16, join as join38 } from "node:path";
112846
+ import { dirname as dirname17, join as join39 } from "node:path";
112311
112847
  function runCommand(command, args, cwd2, input) {
112312
112848
  try {
112313
112849
  return execFileSync4(command, args, {
@@ -112541,8 +113077,8 @@ async function createLettaAgent(apiKey, name) {
112541
113077
  return { id: data.id, name: data.name };
112542
113078
  }
112543
113079
  function cloneRepoToTemp(repo) {
112544
- const tempDir = mkdtempSync(join38(tmpdir4(), "letta-install-github-app-"));
112545
- const repoDir = join38(tempDir, "repo");
113080
+ const tempDir = mkdtempSync(join39(tmpdir4(), "letta-install-github-app-"));
113081
+ const repoDir = join39(tempDir, "repo");
112546
113082
  runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
112547
113083
  return { tempDir, repoDir };
112548
113084
  }
@@ -112553,19 +113089,19 @@ function runGit5(args, cwd2) {
112553
113089
  return runCommand("git", args, cwd2);
112554
113090
  }
112555
113091
  function writeWorkflow(repoDir, workflowPath, content) {
112556
- const absolutePath = join38(repoDir, workflowPath);
112557
- if (!existsSync29(dirname16(absolutePath))) {
112558
- mkdirSync20(dirname16(absolutePath), { recursive: true });
113092
+ const absolutePath = join39(repoDir, workflowPath);
113093
+ if (!existsSync30(dirname17(absolutePath))) {
113094
+ mkdirSync21(dirname17(absolutePath), { recursive: true });
112559
113095
  }
112560
113096
  const next = `${content.trimEnd()}
112561
113097
  `;
112562
- if (existsSync29(absolutePath)) {
113098
+ if (existsSync30(absolutePath)) {
112563
113099
  const previous = readFileSync14(absolutePath, "utf8");
112564
113100
  if (previous === next) {
112565
113101
  return false;
112566
113102
  }
112567
113103
  }
112568
- writeFileSync14(absolutePath, next, "utf8");
113104
+ writeFileSync15(absolutePath, next, "utf8");
112569
113105
  return true;
112570
113106
  }
112571
113107
  function getDefaultBaseBranch(repoDir) {
@@ -116460,9 +116996,9 @@ __export(exports_generate_memory_viewer, {
116460
116996
  generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
116461
116997
  });
116462
116998
  import { execFile as execFileCb4 } from "node:child_process";
116463
- import { chmodSync as chmodSync3, existsSync as existsSync30, mkdirSync as mkdirSync21, writeFileSync as writeFileSync15 } from "node:fs";
116999
+ import { chmodSync as chmodSync3, existsSync as existsSync31, mkdirSync as mkdirSync22, writeFileSync as writeFileSync16 } from "node:fs";
116464
117000
  import { homedir as homedir31 } from "node:os";
116465
- import { join as join39 } from "node:path";
117001
+ import { join as join40 } from "node:path";
116466
117002
  import { promisify as promisify12 } from "node:util";
116467
117003
  async function runGitSafe(cwd2, args) {
116468
117004
  try {
@@ -116745,14 +117281,14 @@ async function generateAndOpenMemoryViewer(agentId, options) {
116745
117281
  }
116746
117282
  const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
116747
117283
  const html = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
116748
- if (!existsSync30(VIEWERS_DIR2)) {
116749
- mkdirSync21(VIEWERS_DIR2, { recursive: true, mode: 448 });
117284
+ if (!existsSync31(VIEWERS_DIR2)) {
117285
+ mkdirSync22(VIEWERS_DIR2, { recursive: true, mode: 448 });
116750
117286
  }
116751
117287
  try {
116752
117288
  chmodSync3(VIEWERS_DIR2, 448);
116753
117289
  } catch {}
116754
- const filePath = join39(VIEWERS_DIR2, `memory-${encodeURIComponent(agentId)}.html`);
116755
- writeFileSync15(filePath, html);
117290
+ const filePath = join40(VIEWERS_DIR2, `memory-${encodeURIComponent(agentId)}.html`);
117291
+ writeFileSync16(filePath, html);
116756
117292
  chmodSync3(filePath, 384);
116757
117293
  const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
116758
117294
  if (!skipOpen) {
@@ -116775,12 +117311,12 @@ var init_generate_memory_viewer = __esm(async () => {
116775
117311
  init_memoryGit()
116776
117312
  ]);
116777
117313
  execFile12 = promisify12(execFileCb4);
116778
- VIEWERS_DIR2 = join39(homedir31(), ".letta", "viewers");
117314
+ VIEWERS_DIR2 = join40(homedir31(), ".letta", "viewers");
116779
117315
  REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
116780
117316
  });
116781
117317
 
116782
117318
  // src/cli/components/MemfsTreeViewer.tsx
116783
- import { existsSync as existsSync31 } from "node:fs";
117319
+ import { existsSync as existsSync32 } from "node:fs";
116784
117320
  function renderTreePrefix(node) {
116785
117321
  let prefix = "";
116786
117322
  for (let i = 0;i < node.depth; i++) {
@@ -116806,7 +117342,7 @@ function MemfsTreeViewer({
116806
117342
  const [status, setStatus] = import_react77.useState(null);
116807
117343
  const statusTimerRef = import_react77.useRef(null);
116808
117344
  const memoryRoot = getMemoryFilesystemRoot(agentId);
116809
- const memoryExists = existsSync31(memoryRoot);
117345
+ const memoryExists = existsSync32(memoryRoot);
116810
117346
  const hasGitRepo = import_react77.useMemo(() => isGitRepo(agentId), [agentId]);
116811
117347
  function showStatus(msg, durationMs) {
116812
117348
  if (statusTimerRef.current)
@@ -117599,6 +118135,9 @@ function truncateText4(text, maxWidth) {
117599
118135
  return text;
117600
118136
  return `${text.slice(0, maxWidth - 3)}...`;
117601
118137
  }
118138
+ function escapeRegExp(text) {
118139
+ return text.replace(/[.*+?^${}()|[\]\\]/g, (match3) => `\\${match3}`);
118140
+ }
117602
118141
  function getMessageText(msg) {
117603
118142
  if ("content" in msg) {
117604
118143
  const content = msg.content;
@@ -117629,6 +118168,34 @@ function getMessageText(msg) {
117629
118168
  }
117630
118169
  return `[${msg.message_type || "unknown"}]`;
117631
118170
  }
118171
+ function HighlightedText({ text, query }) {
118172
+ if (!query.trim())
118173
+ return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118174
+ children: text
118175
+ }, undefined, false, undefined, this);
118176
+ const highlightTerms = [
118177
+ ...new Set(query.trim().split(/\s+/).filter(Boolean))
118178
+ ].sort((a, b) => b.length - a.length);
118179
+ if (highlightTerms.length === 0)
118180
+ return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118181
+ children: text
118182
+ }, undefined, false, undefined, this);
118183
+ const parts = text.split(new RegExp(`(${highlightTerms.map(escapeRegExp).join("|")})`, "gi"));
118184
+ let offset = 0;
118185
+ return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118186
+ children: parts.map((part) => {
118187
+ const key = `${offset}-${part}`;
118188
+ offset += part.length;
118189
+ return highlightTerms.some((term) => part.toLowerCase() === term.toLowerCase()) ? /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118190
+ bold: true,
118191
+ color: colors.selector.itemHighlighted,
118192
+ children: part
118193
+ }, key, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118194
+ children: part
118195
+ }, key, false, undefined, this);
118196
+ })
118197
+ }, undefined, false, undefined, this);
118198
+ }
117632
118199
  function MessageSearch({
117633
118200
  onClose,
117634
118201
  initialQuery,
@@ -117856,24 +118423,23 @@ function MessageSearch({
117856
118423
  const isAssistant = msgType === "assistant_message" || msgType === "reasoning_message";
117857
118424
  const typeLabel = isAssistant ? "Agent message" : "User message";
117858
118425
  const timestamp = formatLocalTime(msgData.created_at || msgData.date);
117859
- return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(jsx_dev_runtime56.Fragment, {
118426
+ return /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
118427
+ flexDirection: "column",
118428
+ paddingX: 1,
117860
118429
  children: [
117861
118430
  /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
117862
118431
  paddingLeft: 2,
117863
- children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
117864
- children: [
117865
- '"',
117866
- fullText,
117867
- '"'
117868
- ]
117869
- }, undefined, true, undefined, this)
117870
- }, undefined, false, undefined, this),
117871
- /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
117872
- height: 1
118432
+ paddingY: 1,
118433
+ marginBottom: 1,
118434
+ children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(HighlightedText, {
118435
+ text: fullText,
118436
+ query: activeQuery
118437
+ }, undefined, false, undefined, this)
117873
118438
  }, undefined, false, undefined, this),
117874
118439
  /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
117875
118440
  flexDirection: "column",
117876
118441
  paddingLeft: 2,
118442
+ gap: 0,
117877
118443
  children: [
117878
118444
  /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
117879
118445
  dimColor: true,
@@ -117883,18 +118449,30 @@ function MessageSearch({
117883
118449
  timestamp
117884
118450
  ]
117885
118451
  }, undefined, true, undefined, this),
117886
- /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
117887
- dimColor: true,
118452
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
118453
+ flexDirection: "row",
117888
118454
  children: [
117889
- "Agent ID: ",
117890
- msgData.agent_id || "unknown"
118455
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118456
+ dimColor: true,
118457
+ children: "Agent ID: "
118458
+ }, undefined, false, undefined, this),
118459
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118460
+ dimColor: true,
118461
+ children: msgData.agent_id || "unknown"
118462
+ }, undefined, false, undefined, this)
117891
118463
  ]
117892
118464
  }, undefined, true, undefined, this),
117893
- msgData.conversation_id && /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
117894
- dimColor: true,
118465
+ msgData.conversation_id && /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Box_default, {
118466
+ flexDirection: "row",
117895
118467
  children: [
117896
- "Conv ID: ",
117897
- msgData.conversation_id
118468
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118469
+ dimColor: true,
118470
+ children: "Conversation ID: "
118471
+ }, undefined, false, undefined, this),
118472
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118473
+ dimColor: true,
118474
+ children: msgData.conversation_id
118475
+ }, undefined, false, undefined, this)
117898
118476
  ]
117899
118477
  }, undefined, true, undefined, this)
117900
118478
  ]
@@ -117906,7 +118484,21 @@ function MessageSearch({
117906
118484
  paddingLeft: 2,
117907
118485
  children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
117908
118486
  dimColor: true,
117909
- children: onOpenConversation ? "Enter to open conversation · Esc cancel" : "Esc cancel"
118487
+ children: onOpenConversation ? /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(jsx_dev_runtime56.Fragment, {
118488
+ children: [
118489
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118490
+ children: "Enter to open conversation"
118491
+ }, undefined, false, undefined, this),
118492
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118493
+ children: " · "
118494
+ }, undefined, false, undefined, this),
118495
+ /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118496
+ children: "Esc cancel"
118497
+ }, undefined, false, undefined, this)
118498
+ ]
118499
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118500
+ children: "Esc cancel"
118501
+ }, undefined, false, undefined, this)
117910
118502
  }, undefined, false, undefined, this)
117911
118503
  }, undefined, false, undefined, this)
117912
118504
  ]
@@ -118072,9 +118664,11 @@ function MessageSearch({
118072
118664
  }, undefined, true, undefined, this),
118073
118665
  /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(Text2, {
118074
118666
  bold: isSelected,
118075
- italic: true,
118076
118667
  color: isSelected ? colors.selector.itemHighlighted : undefined,
118077
- children: displayText
118668
+ children: /* @__PURE__ */ jsx_dev_runtime56.jsxDEV(HighlightedText, {
118669
+ text: displayText,
118670
+ query: activeQuery
118671
+ }, undefined, false, undefined, this)
118078
118672
  }, undefined, false, undefined, this)
118079
118673
  ]
118080
118674
  }, undefined, true, undefined, this),
@@ -119326,10 +119920,10 @@ var init_PendingApprovalStub = __esm(async () => {
119326
119920
  // src/utils/aws-credentials.ts
119327
119921
  import { readFile as readFile11 } from "node:fs/promises";
119328
119922
  import { homedir as homedir32 } from "node:os";
119329
- import { join as join40 } from "node:path";
119923
+ import { join as join41 } from "node:path";
119330
119924
  async function parseAwsCredentials() {
119331
- const credentialsPath = join40(homedir32(), ".aws", "credentials");
119332
- const configPath = join40(homedir32(), ".aws", "config");
119925
+ const credentialsPath = join41(homedir32(), ".aws", "credentials");
119926
+ const configPath = join41(homedir32(), ".aws", "config");
119333
119927
  const profiles = new Map;
119334
119928
  try {
119335
119929
  const content = await readFile11(credentialsPath, "utf-8");
@@ -120437,8 +121031,8 @@ function SkillsDialog({ onClose, agentId }) {
120437
121031
  try {
120438
121032
  const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
120439
121033
  const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
120440
- const { join: join41 } = await import("node:path");
120441
- const skillsDir = getSkillsDirectory2() || join41(process.cwd(), SKILLS_DIR3);
121034
+ const { join: join42 } = await import("node:path");
121035
+ const skillsDir = getSkillsDirectory2() || join42(process.cwd(), SKILLS_DIR3);
120442
121036
  const result = await discoverSkills3(skillsDir, agentId, {
120443
121037
  sources: getSkillSources2()
120444
121038
  });
@@ -124346,8 +124940,8 @@ var init_contextChart = __esm(() => {
124346
124940
 
124347
124941
  // src/cli/helpers/initCommand.ts
124348
124942
  import { execSync as execSync2 } from "node:child_process";
124349
- import { existsSync as existsSync32, readdirSync as readdirSync13, readFileSync as readFileSync15 } from "node:fs";
124350
- import { join as join41 } from "node:path";
124943
+ import { existsSync as existsSync33, readdirSync as readdirSync13, readFileSync as readFileSync15 } from "node:fs";
124944
+ import { join as join42 } from "node:path";
124351
124945
  function hasActiveInitSubagent() {
124352
124946
  const snapshot = getSnapshot2();
124353
124947
  return snapshot.agents.some((agent) => agent.type.toLowerCase() === "init" && (agent.status === "pending" || agent.status === "running"));
@@ -124382,7 +124976,7 @@ ${git.recentCommits || "No commits yet"}
124382
124976
  }
124383
124977
  function gatherExistingMemory(agentId) {
124384
124978
  const systemDir = getMemorySystemDir(agentId);
124385
- if (!existsSync32(systemDir))
124979
+ if (!existsSync33(systemDir))
124386
124980
  return { paths: [], contents: "" };
124387
124981
  const paths = [];
124388
124982
  const sections = [];
@@ -124391,10 +124985,10 @@ function gatherExistingMemory(agentId) {
124391
124985
  for (const entry of readdirSync13(dir, { withFileTypes: true })) {
124392
124986
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
124393
124987
  if (entry.isDirectory()) {
124394
- walk(join41(dir, entry.name), rel);
124988
+ walk(join42(dir, entry.name), rel);
124395
124989
  } else if (entry.name.endsWith(".md")) {
124396
124990
  try {
124397
- const content = readFileSync15(join41(dir, entry.name), "utf-8");
124991
+ const content = readFileSync15(join42(dir, entry.name), "utf-8");
124398
124992
  paths.push(rel);
124399
124993
  sections.push(`── ${rel}
124400
124994
  ${content.slice(0, 2000)}`);
@@ -124447,7 +125041,7 @@ function gatherDirListing() {
124447
125041
  if (entry.isDirectory()) {
124448
125042
  lines.push(`${prefix}${entry.name}/`);
124449
125043
  try {
124450
- const dirPath = join41(cwd2, entry.name);
125044
+ const dirPath = join42(cwd2, entry.name);
124451
125045
  const childEntries = readdirSync13(dirPath, {
124452
125046
  withFileTypes: true
124453
125047
  }).filter((e) => !e.name.startsWith("."));
@@ -124723,7 +125317,7 @@ import {
124723
125317
  writeFile as writeFile7
124724
125318
  } from "node:fs/promises";
124725
125319
  import { homedir as homedir33, tmpdir as tmpdir5 } from "node:os";
124726
- import { join as join42 } from "node:path";
125320
+ import { join as join43 } from "node:path";
124727
125321
  function buildReflectionSubagentPrompt(input) {
124728
125322
  const lines = [];
124729
125323
  if (input.cwd) {
@@ -124756,7 +125350,7 @@ async function collectParentMemoryFiles(memoryDir) {
124756
125350
  return a.name.localeCompare(b.name);
124757
125351
  });
124758
125352
  for (const entry of sortedEntries) {
124759
- const entryPath = join42(currentDir, entry.name);
125353
+ const entryPath = join43(currentDir, entry.name);
124760
125354
  const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
124761
125355
  if (entry.isDirectory()) {
124762
125356
  await walk(entryPath, relativePath);
@@ -124916,7 +125510,7 @@ function getTranscriptRoot() {
124916
125510
  if (envRoot) {
124917
125511
  return envRoot;
124918
125512
  }
124919
- return join42(homedir33(), ".letta", DEFAULT_TRANSCRIPT_DIR);
125513
+ return join43(homedir33(), ".letta", DEFAULT_TRANSCRIPT_DIR);
124920
125514
  }
124921
125515
  function defaultState() {
124922
125516
  return { auto_cursor_line: 0 };
@@ -125028,14 +125622,14 @@ async function readTranscriptLines(paths) {
125028
125622
  }
125029
125623
  function buildPayloadPath(kind) {
125030
125624
  const nonce = Math.random().toString(36).slice(2, 8);
125031
- return join42(tmpdir5(), `letta-${kind}-${nonce}.txt`);
125625
+ return join43(tmpdir5(), `letta-${kind}-${nonce}.txt`);
125032
125626
  }
125033
125627
  function getReflectionTranscriptPaths(agentId, conversationId) {
125034
- const rootDir = join42(getTranscriptRoot(), sanitizePathSegment(agentId), sanitizePathSegment(conversationId));
125628
+ const rootDir = join43(getTranscriptRoot(), sanitizePathSegment(agentId), sanitizePathSegment(conversationId));
125035
125629
  return {
125036
125630
  rootDir,
125037
- transcriptPath: join42(rootDir, "transcript.jsonl"),
125038
- statePath: join42(rootDir, "state.json")
125631
+ transcriptPath: join43(rootDir, "transcript.jsonl"),
125632
+ statePath: join43(rootDir, "state.json")
125039
125633
  };
125040
125634
  }
125041
125635
  async function appendTranscriptDeltaJsonl(agentId, conversationId, lines) {
@@ -125865,12 +126459,12 @@ __export(exports_shellAliases, {
125865
126459
  expandAliases: () => expandAliases,
125866
126460
  clearAliasCache: () => clearAliasCache
125867
126461
  });
125868
- import { existsSync as existsSync33, readFileSync as readFileSync16 } from "node:fs";
126462
+ import { existsSync as existsSync34, readFileSync as readFileSync16 } from "node:fs";
125869
126463
  import { homedir as homedir34 } from "node:os";
125870
- import { join as join43 } from "node:path";
126464
+ import { join as join44 } from "node:path";
125871
126465
  function parseAliasesFromFile(filePath) {
125872
126466
  const aliases = new Map;
125873
- if (!existsSync33(filePath)) {
126467
+ if (!existsSync34(filePath)) {
125874
126468
  return aliases;
125875
126469
  }
125876
126470
  try {
@@ -125939,7 +126533,7 @@ function loadAliases(forceReload = false) {
125939
126533
  const home = homedir34();
125940
126534
  const allAliases = new Map;
125941
126535
  for (const file of ALIAS_FILES) {
125942
- const filePath = join43(home, file);
126536
+ const filePath = join44(home, file);
125943
126537
  const fileAliases = parseAliasesFromFile(filePath);
125944
126538
  for (const [name, value] of fileAliases) {
125945
126539
  allAliases.set(name, value);
@@ -126699,7 +127293,10 @@ __export(exports_conversationSwitchAlert, {
126699
127293
  });
126700
127294
  function buildConversationSwitchAlert(ctx) {
126701
127295
  const parts = [];
126702
- if (ctx.origin === "new" || ctx.origin === "clear") {
127296
+ if (ctx.origin === "fork") {
127297
+ parts.push("Forked conversation. This is a copy of the previous conversation with a freshly compiled system message.");
127298
+ parts.push(`Conversation: ${ctx.conversationId}`);
127299
+ } else if (ctx.origin === "new" || ctx.origin === "clear") {
126703
127300
  parts.push("New conversation started. This is a fresh conversation thread with no prior messages.");
126704
127301
  parts.push(`Conversation: ${ctx.conversationId}`);
126705
127302
  } else if (ctx.origin === "search") {
@@ -126786,9 +127383,9 @@ __export(exports_App, {
126786
127383
  default: () => App2
126787
127384
  });
126788
127385
  import { randomUUID as randomUUID9 } from "node:crypto";
126789
- import { existsSync as existsSync34, readFileSync as readFileSync17, renameSync as renameSync2, writeFileSync as writeFileSync16 } from "node:fs";
127386
+ import { existsSync as existsSync35, readFileSync as readFileSync17, renameSync as renameSync2, writeFileSync as writeFileSync17 } from "node:fs";
126790
127387
  import { homedir as homedir35, tmpdir as tmpdir6 } from "node:os";
126791
- import { join as join44, relative as relative17 } from "node:path";
127388
+ import { join as join45, relative as relative17 } from "node:path";
126792
127389
  function deriveReasoningEffort(modelSettings, llmConfig) {
126793
127390
  if (modelSettings && "provider_type" in modelSettings) {
126794
127391
  if (modelSettings.provider_type === "openai" && "reasoning" in modelSettings && modelSettings.reasoning) {
@@ -126951,23 +127548,27 @@ async function isRetriableError(stopReason, lastRunId) {
126951
127548
  }
126952
127549
  return false;
126953
127550
  }
126954
- function saveLastAgentBeforeExit() {
127551
+ function saveLastSessionBeforeExit(conversationId) {
126955
127552
  try {
126956
127553
  const currentAgentId = getCurrentAgentId();
126957
- settingsManager.updateLocalProjectSettings({ lastAgent: currentAgentId });
126958
- settingsManager.updateSettings({ lastAgent: currentAgentId });
127554
+ if (conversationId && conversationId !== "default") {
127555
+ settingsManager.persistSession(currentAgentId, conversationId);
127556
+ } else {
127557
+ settingsManager.updateLocalProjectSettings({ lastAgent: currentAgentId });
127558
+ settingsManager.updateSettings({ lastAgent: currentAgentId });
127559
+ }
126959
127560
  } catch {}
126960
127561
  }
126961
127562
  function planFileExists(fallbackPlanFilePath) {
126962
127563
  const planFilePath = permissionMode.getPlanFilePath() ?? fallbackPlanFilePath;
126963
- return !!planFilePath && existsSync34(planFilePath);
127564
+ return !!planFilePath && existsSync35(planFilePath);
126964
127565
  }
126965
127566
  function _readPlanFile(fallbackPlanFilePath) {
126966
127567
  const planFilePath = permissionMode.getPlanFilePath() ?? fallbackPlanFilePath;
126967
127568
  if (!planFilePath) {
126968
127569
  return "No plan file path set.";
126969
127570
  }
126970
- if (!existsSync34(planFilePath)) {
127571
+ if (!existsSync35(planFilePath)) {
126971
127572
  return `Plan file not found at ${planFilePath}`;
126972
127573
  }
126973
127574
  try {
@@ -127334,11 +127935,26 @@ function App2({
127334
127935
  agentStateRef.current = agentState;
127335
127936
  }, [agentState]);
127336
127937
  const [currentModelId, setCurrentModelId] = import_react101.useState(null);
127938
+ const [tempModelOverride, _setTempModelOverride] = import_react101.useState(null);
127939
+ const [tempModelOverrideContext, setTempModelOverrideContext] = import_react101.useState({ agentId, conversationId });
127940
+ const tempModelOverrideRef = import_react101.useRef(null);
127941
+ const setTempModelOverride = import_react101.useCallback((next) => {
127942
+ tempModelOverrideRef.current = next;
127943
+ _setTempModelOverride(next);
127944
+ }, []);
127945
+ if (tempModelOverrideContext.agentId !== agentId || tempModelOverrideContext.conversationId !== conversationId) {
127946
+ setTempModelOverrideContext({ agentId, conversationId });
127947
+ if (tempModelOverride !== null) {
127948
+ setTempModelOverride(null);
127949
+ } else if (tempModelOverrideRef.current !== null) {
127950
+ tempModelOverrideRef.current = null;
127951
+ }
127952
+ }
127337
127953
  const [currentModelHandle, setCurrentModelHandle] = import_react101.useState(null);
127338
127954
  const agentName = agentState?.name ?? null;
127339
127955
  const [agentDescription, setAgentDescription] = import_react101.useState(null);
127340
127956
  const [agentLastRunAt, setAgentLastRunAt] = import_react101.useState(null);
127341
- const currentModelLabel = currentModelHandle || agentState?.model || (llmConfig?.model_endpoint_type && llmConfig?.model ? `${llmConfig.model_endpoint_type}/${llmConfig.model}` : llmConfig?.model ?? null) || null;
127957
+ const currentModelLabel = tempModelOverride || currentModelHandle || agentState?.model || (llmConfig?.model_endpoint_type && llmConfig?.model ? `${llmConfig.model_endpoint_type}/${llmConfig.model}` : llmConfig?.model ?? null) || null;
127342
127958
  const effectiveModelSettings = hasConversationModelOverride ? conversationOverrideModelSettings : agentState?.model_settings;
127343
127959
  const derivedReasoningEffort = deriveReasoningEffort(effectiveModelSettings, llmConfig);
127344
127960
  const currentModelDisplay = import_react101.useMemo(() => {
@@ -127355,6 +127971,7 @@ function App2({
127355
127971
  }, [currentModelLabel, derivedReasoningEffort, llmConfig]);
127356
127972
  const currentModelProvider = llmConfig?.provider_name ?? null;
127357
127973
  const currentReasoningEffort = currentModelLabel?.startsWith("letta/auto") ? null : derivedReasoningEffort ?? inferReasoningEffortFromModelPreset(currentModelId, currentModelLabel);
127974
+ const hasTemporaryModelOverride = tempModelOverride !== null;
127358
127975
  const [billingTier, setBillingTier] = import_react101.useState(null);
127359
127976
  import_react101.useEffect(() => {
127360
127977
  setErrorContext({
@@ -127504,6 +128121,7 @@ function App2({
127504
128121
  const abortControllerRef = import_react101.useRef(null);
127505
128122
  const userCancelledRef = import_react101.useRef(false);
127506
128123
  const llmApiErrorRetriesRef = import_react101.useRef(0);
128124
+ const quotaAutoSwapAttemptedRef = import_react101.useRef(false);
127507
128125
  const emptyResponseRetriesRef = import_react101.useRef(0);
127508
128126
  const conversationBusyRetriesRef = import_react101.useRef(0);
127509
128127
  const [queueDisplay, setQueueDisplay] = import_react101.useState([]);
@@ -128112,10 +128730,16 @@ function App2({
128112
128730
  }, [commitEligibleLines]);
128113
128731
  refreshDerivedRef.current = refreshDerived;
128114
128732
  const recordCommandReminder = import_react101.useCallback((event) => {
128115
- const input = event.input.trim();
128733
+ let input = event.input.trim();
128116
128734
  if (!input.startsWith("/")) {
128117
128735
  return;
128118
128736
  }
128737
+ if (/^\/secret\s+set\s+/i.test(input)) {
128738
+ const parts = input.split(/\s+/);
128739
+ if (parts.length >= 4) {
128740
+ input = `${parts[0]} ${parts[1]} ${parts[2]} ***`;
128741
+ }
128742
+ }
128119
128743
  enqueueCommandIoReminder(sharedReminderStateRef.current, {
128120
128744
  input,
128121
128745
  output: event.output,
@@ -128263,8 +128887,8 @@ function App2({
128263
128887
  if (!planFilePath)
128264
128888
  return;
128265
128889
  try {
128266
- const { readFileSync: readFileSync18, existsSync: existsSync35 } = __require("node:fs");
128267
- if (!existsSync35(planFilePath))
128890
+ const { readFileSync: readFileSync18, existsSync: existsSync36 } = __require("node:fs");
128891
+ if (!existsSync36(planFilePath))
128268
128892
  return;
128269
128893
  const planContent = readFileSync18(planFilePath, "utf-8");
128270
128894
  const previewItem = {
@@ -128674,9 +129298,9 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
128674
129298
  (async () => {
128675
129299
  try {
128676
129300
  const { watch } = await import("node:fs");
128677
- const { existsSync: existsSync35 } = await import("node:fs");
129301
+ const { existsSync: existsSync36 } = await import("node:fs");
128678
129302
  const memRoot = getMemoryFilesystemRoot(agentId);
128679
- if (!existsSync35(memRoot))
129303
+ if (!existsSync36(memRoot))
128680
129304
  return;
128681
129305
  watcher = watch(memRoot, { recursive: true }, () => {});
128682
129306
  memfsWatcherRef.current = watcher;
@@ -128834,6 +129458,7 @@ ${newState.originalPrompt}`,
128834
129458
  llmApiErrorRetriesRef.current = 0;
128835
129459
  emptyResponseRetriesRef.current = 0;
128836
129460
  conversationBusyRetriesRef.current = 0;
129461
+ quotaAutoSwapAttemptedRef.current = false;
128837
129462
  }
128838
129463
  let currentRunId;
128839
129464
  let preserveTranscriptStartForApproval = false;
@@ -128883,7 +129508,6 @@ ${newState.originalPrompt}`,
128883
129508
  if (shouldClearCompletedSubagentsOnTurnStart(allowReentry, hasActiveSubagents())) {
128884
129509
  clearCompletedSubagents();
128885
129510
  }
128886
- const requestStartedAtMs = Date.now();
128887
129511
  let highestSeqIdSeen = null;
128888
129512
  while (true) {
128889
129513
  const signal = abortControllerRef.current?.signal;
@@ -128911,8 +129535,12 @@ ${newState.originalPrompt}`,
128911
129535
  }
128912
129536
  let stream2 = null;
128913
129537
  let turnToolContextId = null;
129538
+ let preStreamResumeResult = null;
128914
129539
  try {
128915
- const nextStream = await sendMessageStream(conversationIdRef.current, currentInput, { agentId: agentIdRef.current });
129540
+ const nextStream = await sendMessageStream(conversationIdRef.current, currentInput, {
129541
+ agentId: agentIdRef.current,
129542
+ overrideModel: tempModelOverrideRef.current ?? undefined
129543
+ });
128916
129544
  stream2 = nextStream;
128917
129545
  turnToolContextId = getStreamToolContextId(nextStream);
128918
129546
  } catch (preStreamError) {
@@ -128950,30 +129578,64 @@ ${newState.originalPrompt}`,
128950
129578
  httpStatus: preStreamError instanceof APIError2 ? preStreamError.status : undefined,
128951
129579
  modelId: currentModelId || undefined
128952
129580
  });
128953
- const statusId = uid5("status");
128954
- buffersRef.current.byId.set(statusId, {
128955
- kind: "status",
128956
- id: statusId,
128957
- lines: ["Conversation is busy, waiting and retrying…"]
128958
- });
128959
- buffersRef.current.order.push(statusId);
128960
- refreshDerived();
128961
- let cancelled = false;
128962
- const startTime = Date.now();
128963
- while (Date.now() - startTime < retryDelayMs) {
128964
- if (abortControllerRef.current?.signal.aborted || userCancelledRef.current) {
128965
- cancelled = true;
128966
- break;
129581
+ try {
129582
+ const client = await getClient2();
129583
+ const messageOtid = currentInput.map((item) => item.otid).find((v) => typeof v === "string");
129584
+ debugLog("stream", "Conversation busy: resuming via stream endpoint (otid=%s)", messageOtid ?? "none");
129585
+ if (signal?.aborted || userCancelledRef.current) {
129586
+ const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
129587
+ if (!isStaleAtAbort) {
129588
+ setStreaming(false);
129589
+ }
129590
+ return;
128967
129591
  }
128968
- await new Promise((resolve31) => setTimeout(resolve31, 100));
128969
- }
128970
- buffersRef.current.byId.delete(statusId);
128971
- buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
128972
- refreshDerived();
128973
- if (!cancelled) {
129592
+ const conversationId2 = conversationIdRef.current ?? "default";
129593
+ const resumeStream = await client.conversations.messages.stream(conversationId2, {
129594
+ agent_id: conversationId2 === "default" ? agentIdRef.current ?? undefined : undefined,
129595
+ otid: messageOtid ?? undefined,
129596
+ starting_after: 0,
129597
+ batch_size: 1000
129598
+ });
128974
129599
  buffersRef.current.interrupted = false;
128975
- restorePinnedPermissionMode();
128976
- continue;
129600
+ buffersRef.current.commitGeneration = (buffersRef.current.commitGeneration || 0) + 1;
129601
+ preStreamResumeResult = await drainStream(resumeStream, buffersRef.current, refreshDerivedThrottled, signal, undefined, undefined, contextTrackerRef.current, highestSeqIdSeen);
129602
+ debugLog("stream", "Pre-stream resume succeeded (stopReason=%s)", preStreamResumeResult.stopReason);
129603
+ } catch (resumeError) {
129604
+ if (signal?.aborted || userCancelledRef.current) {
129605
+ const isStaleAtAbort = myGeneration !== conversationGenerationRef.current;
129606
+ if (!isStaleAtAbort) {
129607
+ setStreaming(false);
129608
+ }
129609
+ return;
129610
+ }
129611
+ debugLog("stream", "Pre-stream resume failed, falling back to wait/retry: %s", resumeError instanceof Error ? resumeError.message : String(resumeError));
129612
+ }
129613
+ if (!preStreamResumeResult) {
129614
+ const statusId = uid5("status");
129615
+ buffersRef.current.byId.set(statusId, {
129616
+ kind: "status",
129617
+ id: statusId,
129618
+ lines: ["Conversation is busy, waiting and retrying…"]
129619
+ });
129620
+ buffersRef.current.order.push(statusId);
129621
+ refreshDerived();
129622
+ let cancelled = false;
129623
+ const startTime = Date.now();
129624
+ while (Date.now() - startTime < retryDelayMs) {
129625
+ if (abortControllerRef.current?.signal.aborted || userCancelledRef.current) {
129626
+ cancelled = true;
129627
+ break;
129628
+ }
129629
+ await new Promise((resolve31) => setTimeout(resolve31, 100));
129630
+ }
129631
+ buffersRef.current.byId.delete(statusId);
129632
+ buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
129633
+ refreshDerived();
129634
+ if (!cancelled) {
129635
+ buffersRef.current.interrupted = false;
129636
+ restorePinnedPermissionMode();
129637
+ continue;
129638
+ }
128977
129639
  }
128978
129640
  }
128979
129641
  if (preStreamAction === "retry_transient") {
@@ -129118,10 +129780,12 @@ ${newState.originalPrompt}`,
129118
129780
  if (hasUserMessage) {
129119
129781
  contextTrackerRef.current.currentTurnId++;
129120
129782
  }
129121
- if (!stream2) {
129122
- throw new Error("Expected stream to be set before drain");
129123
- }
129124
- const drainResult = drainStreamWithResume(stream2, buffersRef.current, refreshDerivedThrottled, signal, handleFirstMessage, undefined, contextTrackerRef.current, highestSeqIdSeen);
129783
+ const drainResult = preStreamResumeResult ? preStreamResumeResult : (() => {
129784
+ if (!stream2) {
129785
+ throw new Error("Expected stream when pre-stream resume did not succeed");
129786
+ }
129787
+ return drainStreamWithResume(stream2, buffersRef.current, refreshDerivedThrottled, signal, handleFirstMessage, undefined, contextTrackerRef.current, highestSeqIdSeen);
129788
+ })();
129125
129789
  const {
129126
129790
  stopReason,
129127
129791
  approval,
@@ -129703,6 +130367,37 @@ ${feedback}
129703
130367
  buffersRef.current.interrupted = false;
129704
130368
  continue;
129705
130369
  }
130370
+ const autoSwapOnQuotaLimitEnabled = settingsManager.getSetting("autoSwapOnQuotaLimit") !== false;
130371
+ const isQuotaLimit = isQuotaLimitErrorDetail(detailFromRun ?? fallbackError);
130372
+ const alreadyOnTempAuto = tempModelOverrideRef.current === TEMP_QUOTA_OVERRIDE_MODEL;
130373
+ const canAttemptQuotaAutoSwap = autoSwapOnQuotaLimitEnabled && isQuotaLimit && !alreadyOnTempAuto && !quotaAutoSwapAttemptedRef.current;
130374
+ if (canAttemptQuotaAutoSwap) {
130375
+ quotaAutoSwapAttemptedRef.current = true;
130376
+ setTempModelOverride(TEMP_QUOTA_OVERRIDE_MODEL);
130377
+ const statusId = uid5("status");
130378
+ buffersRef.current.byId.set(statusId, {
130379
+ kind: "status",
130380
+ id: statusId,
130381
+ lines: [
130382
+ "Quota limit reached; temporarily switching to Auto and continuing..."
130383
+ ]
130384
+ });
130385
+ buffersRef.current.order.push(statusId);
130386
+ refreshDerived();
130387
+ currentInput = [
130388
+ ...currentInput,
130389
+ {
130390
+ type: "message",
130391
+ role: "user",
130392
+ content: "Keep going."
130393
+ }
130394
+ ];
130395
+ buffersRef.current.byId.delete(statusId);
130396
+ buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
130397
+ refreshDerived();
130398
+ buffersRef.current.interrupted = false;
130399
+ continue;
130400
+ }
129706
130401
  if (isEmptyResponseRetryable(stopReasonToHandle === "llm_api_error" ? "llm_error" : undefined, detailFromRun, emptyResponseRetriesRef.current, EMPTY_RESPONSE_MAX_RETRIES3)) {
129707
130402
  emptyResponseRetriesRef.current += 1;
129708
130403
  const attempt = emptyResponseRetriesRef.current;
@@ -129780,6 +130475,7 @@ ${feedback}
129780
130475
  }
129781
130476
  if (!cancelled) {
129782
130477
  refreshCurrentInputOtids();
130478
+ highestSeqIdSeen = null;
129783
130479
  buffersRef.current.interrupted = false;
129784
130480
  continue;
129785
130481
  }
@@ -129939,7 +130635,7 @@ ${feedback}
129939
130635
  setUiPermissionMode
129940
130636
  ]);
129941
130637
  const handleExit = import_react101.useCallback(async () => {
129942
- saveLastAgentBeforeExit();
130638
+ saveLastSessionBeforeExit(conversationIdRef.current);
129943
130639
  await runEndHooks();
129944
130640
  const stats = sessionStatsRef.current.getSnapshot();
129945
130641
  telemetry.trackSessionEnd(stats, "exit_command");
@@ -130199,11 +130895,7 @@ ${feedback}
130199
130895
  const agent = await client.agents.retrieve(targetAgentId);
130200
130896
  const targetConversationId = opts?.conversationId ?? "default";
130201
130897
  await updateProjectSettings({ lastAgent: targetAgentId });
130202
- settingsManager.setLocalLastSession({ agentId: targetAgentId, conversationId: targetConversationId }, process.cwd());
130203
- settingsManager.setGlobalLastSession({
130204
- agentId: targetAgentId,
130205
- conversationId: targetConversationId
130206
- });
130898
+ settingsManager.persistSession(targetAgentId, targetConversationId);
130207
130899
  buffersRef.current.byId.clear();
130208
130900
  buffersRef.current.order = [];
130209
130901
  buffersRef.current.tokenCount = 0;
@@ -130291,11 +130983,7 @@ ${feedback}
130291
130983
  }
130292
130984
  await updateProjectSettings({ lastAgent: agent.id });
130293
130985
  const targetConversationId = "default";
130294
- settingsManager.setLocalLastSession({ agentId: agent.id, conversationId: targetConversationId }, process.cwd());
130295
- settingsManager.setGlobalLastSession({
130296
- agentId: agent.id,
130297
- conversationId: targetConversationId
130298
- });
130986
+ settingsManager.persistSession(agent.id, targetConversationId);
130299
130987
  const agentUrl = buildChatUrl(agent.id);
130300
130988
  const memfsTip = settingsManager.isMemfsEnabled(agent.id) ? "Memory will be auto-initialized on your first message." : "Tip: use /init to initialize your agent's memory system!";
130301
130989
  const successOutput = [
@@ -130641,14 +131329,14 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
130641
131329
  setDequeueEpoch((e) => e + 1);
130642
131330
  }
130643
131331
  const isSlashCommand = userTextForInput.startsWith("/");
130644
- if (isAgentBusy() && isSlashCommand) {
131332
+ const shouldBypassQueue = isSlashCommand && (isInteractiveCommand(userTextForInput) || isNonStateCommand(userTextForInput));
131333
+ if (isAgentBusy() && isSlashCommand && !shouldBypassQueue) {
130645
131334
  const attemptedCommand = userTextForInput.split(/\s+/)[0] || "/";
130646
131335
  const disabledMessage = `'${attemptedCommand}' is disabled while the agent is running.`;
130647
131336
  const cmd = commandRunner.start(userTextForInput, disabledMessage);
130648
131337
  cmd.fail(disabledMessage);
130649
131338
  return { submitted: true };
130650
131339
  }
130651
- const shouldBypassQueue = isInteractiveCommand(userTextForInput) || isNonStateCommand(userTextForInput);
130652
131340
  if (isAgentBusy() && !shouldBypassQueue) {
130653
131341
  tuiQueueRef.current?.enqueue({
130654
131342
  kind: "message",
@@ -131144,7 +131832,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
131144
131832
  }
131145
131833
  await settingsManager3.logout();
131146
131834
  cmd.finish("✓ Logged out successfully. Run 'letta' to re-authenticate.", true);
131147
- saveLastAgentBeforeExit();
131835
+ saveLastSessionBeforeExit(conversationIdRef.current);
131148
131836
  const stats = sessionStatsRef.current.getSnapshot();
131149
131837
  telemetry.trackSessionEnd(stats, "logout");
131150
131838
  try {
@@ -131278,21 +131966,60 @@ Type your task to begin the loop.`, true);
131278
131966
  conversationId: conversation.id,
131279
131967
  isDefault: false
131280
131968
  };
131281
- settingsManager.setLocalLastSession({ agentId, conversationId: conversation.id }, process.cwd());
131969
+ settingsManager.persistSession(agentId, conversation.id);
131970
+ resetContextHistory(contextTrackerRef.current);
131971
+ resetBootstrapReminderState();
131972
+ sessionHooksRanRef.current = false;
131973
+ runSessionStartHooks(true, agentId, agentName ?? undefined, conversation.id).then((result2) => {
131974
+ if (result2.feedback.length > 0) {
131975
+ sessionStartFeedbackRef.current = result2.feedback;
131976
+ }
131977
+ }).catch(() => {});
131978
+ sessionHooksRanRef.current = true;
131979
+ cmd.finish("Started new conversation (use /resume to change convos)", true);
131980
+ } catch (error) {
131981
+ const errorDetails = formatErrorDetails2(error, agentId);
131982
+ cmd.fail(`Failed: ${errorDetails}`);
131983
+ } finally {
131984
+ setCommandRunning(false);
131985
+ }
131986
+ return { submitted: true };
131987
+ }
131988
+ if (msg.trim() === "/fork") {
131989
+ if (conversationIdRef.current === "default") {
131990
+ const cmd2 = commandRunner.start(msg.trim(), "Forking conversation...");
131991
+ cmd2.fail("Cannot fork the default conversation — use /new instead");
131992
+ return { submitted: true };
131993
+ }
131994
+ const cmd = commandRunner.start(msg.trim(), "Forking conversation...");
131995
+ resetPendingReasoningCycle();
131996
+ setCommandRunning(true);
131997
+ await runEndHooks();
131998
+ try {
131999
+ const client = await getClient2();
132000
+ const forked = await client.post(`/v1/conversations/${conversationIdRef.current}/fork`);
132001
+ await maybeCarryOverActiveConversationModel(forked.id);
132002
+ setConversationId3(forked.id);
132003
+ pendingConversationSwitchRef.current = {
132004
+ origin: "fork",
132005
+ conversationId: forked.id,
132006
+ isDefault: false
132007
+ };
132008
+ settingsManager.setLocalLastSession({ agentId, conversationId: forked.id }, process.cwd());
131282
132009
  settingsManager.setGlobalLastSession({
131283
132010
  agentId,
131284
- conversationId: conversation.id
132011
+ conversationId: forked.id
131285
132012
  });
131286
132013
  resetContextHistory(contextTrackerRef.current);
131287
132014
  resetBootstrapReminderState();
131288
132015
  sessionHooksRanRef.current = false;
131289
- runSessionStartHooks(true, agentId, agentName ?? undefined, conversation.id).then((result2) => {
132016
+ runSessionStartHooks(true, agentId, agentName ?? undefined, forked.id).then((result2) => {
131290
132017
  if (result2.feedback.length > 0) {
131291
132018
  sessionStartFeedbackRef.current = result2.feedback;
131292
132019
  }
131293
132020
  }).catch(() => {});
131294
132021
  sessionHooksRanRef.current = true;
131295
- cmd.finish("Started new conversation (use /resume to change convos)", true);
132022
+ cmd.finish("Forked conversation (use /resume to switch back)", true);
131296
132023
  } catch (error) {
131297
132024
  const errorDetails = formatErrorDetails2(error, agentId);
131298
132025
  cmd.fail(`Failed: ${errorDetails}`);
@@ -131324,11 +132051,7 @@ Type your task to begin the loop.`, true);
131324
132051
  conversationId: conversation.id,
131325
132052
  isDefault: false
131326
132053
  };
131327
- settingsManager.setLocalLastSession({ agentId, conversationId: conversation.id }, process.cwd());
131328
- settingsManager.setGlobalLastSession({
131329
- agentId,
131330
- conversationId: conversation.id
131331
- });
132054
+ settingsManager.persistSession(agentId, conversation.id);
131332
132055
  resetContextHistory(contextTrackerRef.current);
131333
132056
  resetBootstrapReminderState();
131334
132057
  sessionHooksRanRef.current = false;
@@ -131591,11 +132314,7 @@ Type your task to begin the loop.`, true);
131591
132314
  messageCount: resumeData.messageHistory.length,
131592
132315
  messageHistory: resumeData.messageHistory
131593
132316
  };
131594
- settingsManager.setLocalLastSession({ agentId, conversationId: targetConvId }, process.cwd());
131595
- settingsManager.setGlobalLastSession({
131596
- agentId,
131597
- conversationId: targetConvId
131598
- });
132317
+ settingsManager.persistSession(agentId, targetConvId);
131599
132318
  const currentAgentName = agentState.name || "Unnamed Agent";
131600
132319
  const successLines = resumeData.messageHistory.length > 0 ? [
131601
132320
  `Resumed conversation with "${currentAgentName}"`,
@@ -131904,7 +132623,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
131904
132623
  fileContent = await client.agents.exportFile(agentId, exportParams);
131905
132624
  }
131906
132625
  const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
131907
- writeFileSync16(fileName, JSON.stringify(fileContent, null, 2));
132626
+ writeFileSync17(fileName, JSON.stringify(fileContent, null, 2));
131908
132627
  let summary = `AgentFile exported to ${fileName}`;
131909
132628
  if (skills.length > 0) {
131910
132629
  summary += `
@@ -131994,11 +132713,11 @@ Path: ${result2.memoryDir}`, true, msg);
131994
132713
  setCommandRunning(true);
131995
132714
  try {
131996
132715
  const memoryDir = getMemoryFilesystemRoot(agentId);
131997
- if (!existsSync34(memoryDir)) {
132716
+ if (!existsSync35(memoryDir)) {
131998
132717
  updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
131999
132718
  return { submitted: true };
132000
132719
  }
132001
- const backupDir = join44(tmpdir6(), `letta-memfs-reset-${agentId}-${Date.now()}`);
132720
+ const backupDir = join45(tmpdir6(), `letta-memfs-reset-${agentId}-${Date.now()}`);
132002
132721
  renameSync2(memoryDir, backupDir);
132003
132722
  ensureMemoryFilesystemDirs(agentId);
132004
132723
  updateMemorySyncCommand(cmdId, `Memory filesystem reset.
@@ -132026,8 +132745,8 @@ Run \`/memfs sync\` to repopulate from API.`, true, msg);
132026
132745
  await removeGitMemoryTag2(agentId);
132027
132746
  let backupInfo = "";
132028
132747
  const memoryDir = getMemoryFilesystemRoot(agentId);
132029
- if (existsSync34(memoryDir)) {
132030
- const backupDir = join44(tmpdir6(), `letta-memfs-disable-${agentId}-${Date.now()}`);
132748
+ if (existsSync35(memoryDir)) {
132749
+ const backupDir = join45(tmpdir6(), `letta-memfs-disable-${agentId}-${Date.now()}`);
132031
132750
  renameSync2(memoryDir, backupDir);
132032
132751
  backupInfo = `
132033
132752
  Local files backed up to ${backupDir}`;
@@ -132295,7 +133014,7 @@ ${SYSTEM_REMINDER_CLOSE}`),
132295
133014
  }
132296
133015
  return { submitted: true };
132297
133016
  }
132298
- const { commands: commands2, executeCommand: executeCommand2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
133017
+ const { commands: commands2, executeCommand: executeCommand2 } = await init_registry().then(() => exports_registry);
132299
133018
  const registryCommandName = trimmed.split(/\s+/)[0] ?? "";
132300
133019
  const isRegistryCommand = Boolean(commands2[registryCommandName]);
132301
133020
  const registryCmd = isRegistryCommand ? commandRunner.start(msg, `Running ${registryCommandName}...`) : null;
@@ -132884,7 +133603,8 @@ ${SYSTEM_REMINDER_CLOSE}
132884
133603
  if (isQueuedValid) {
132885
133604
  initialInput.push({
132886
133605
  type: "approval",
132887
- approvals: queuedApprovalResults
133606
+ approvals: queuedApprovalResults,
133607
+ otid: randomUUID9()
132888
133608
  });
132889
133609
  } else {
132890
133610
  debugWarn("queue", "Dropping stale queued approval results for mismatched conversation or generation");
@@ -133103,7 +133823,11 @@ ${SYSTEM_REMINDER_CLOSE}
133103
133823
  const queuedNotifications = queuedItemsToAppend ? getQueuedNotificationSummaries(queuedItemsToAppend) : [];
133104
133824
  const hadNotifications = appendTaskNotificationEvents(queuedNotifications);
133105
133825
  const input = [
133106
- { type: "approval", approvals: allResults }
133826
+ {
133827
+ type: "approval",
133828
+ approvals: allResults,
133829
+ otid: randomUUID9()
133830
+ }
133107
133831
  ];
133108
133832
  if (queuedItemsToAppend && queuedItemsToAppend.length > 0) {
133109
133833
  const queuedUserText = buildQueuedUserText(queuedItemsToAppend);
@@ -133492,6 +134216,7 @@ ${SYSTEM_REMINDER_CLOSE}
133492
134216
  } : {}
133493
134217
  });
133494
134218
  setCurrentModelId(modelId);
134219
+ setTempModelOverride(null);
133495
134220
  resetContextHistory(contextTrackerRef.current);
133496
134221
  setCurrentModelHandle(modelHandle);
133497
134222
  const persistedToolsetPreference = settingsManager.getToolsetPreference(agentId);
@@ -133554,7 +134279,8 @@ ${guidance}`);
133554
134279
  maybeRecordToolsetChangeReminder,
133555
134280
  resetPendingReasoningCycle,
133556
134281
  withCommandLock,
133557
- setHasConversationModelOverride
134282
+ setHasConversationModelOverride,
134283
+ setTempModelOverride
133558
134284
  ]);
133559
134285
  const handleSystemPromptSelect = import_react101.useCallback(async (promptId, commandId) => {
133560
134286
  const overlayCommand = commandId ? commandRunner.getHandle(commandId, "/system") : consumeOverlayCommand("system");
@@ -133811,11 +134537,7 @@ ${guidance}`);
133811
134537
  messageCount: resumeData.messageHistory.length,
133812
134538
  messageHistory: resumeData.messageHistory
133813
134539
  };
133814
- settingsManager.setLocalLastSession({ agentId, conversationId: action.conversationId }, process.cwd());
133815
- settingsManager.setGlobalLastSession({
133816
- agentId,
133817
- conversationId: action.conversationId
133818
- });
134540
+ settingsManager.persistSession(agentId, action.conversationId);
133819
134541
  resetContextHistory(contextTrackerRef.current);
133820
134542
  resetBootstrapReminderState();
133821
134543
  cmd.finish(`Switched to conversation (${resumeData.messageHistory.length} messages)`, true);
@@ -134249,7 +134971,7 @@ ${guidance}`);
134249
134971
  }
134250
134972
  if (mode === "bypassPermissions") {
134251
134973
  const planFilePath = activePlanPath ?? fallbackPlanPath;
134252
- const plansDir = join44(homedir35(), ".letta", "plans");
134974
+ const plansDir = join45(homedir35(), ".letta", "plans");
134253
134975
  handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
134254
134976
  ` + (planFilePath ? `Plan file path: ${planFilePath}
134255
134977
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
@@ -134284,7 +135006,7 @@ ${guidance}`);
134284
135006
  if (!hasUsablePlan) {
134285
135007
  lastAutoHandledExitPlanToolCallIdRef.current = approval.toolCallId;
134286
135008
  const planFilePath = activePlanPath ?? fallbackPlanPath;
134287
- const plansDir = join44(homedir35(), ".letta", "plans");
135009
+ const plansDir = join45(homedir35(), ".letta", "plans");
134288
135010
  handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
134289
135011
  ` + (planFilePath ? `Plan file path: ${planFilePath}
134290
135012
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
@@ -134883,6 +135605,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
134883
135605
  agentName,
134884
135606
  currentModel: currentModelDisplay,
134885
135607
  currentModelProvider,
135608
+ hasTemporaryModelOverride,
134886
135609
  currentReasoningEffort,
134887
135610
  messageQueue: queueDisplay,
134888
135611
  onEnterQueueEditMode: handleEnterQueueEditMode,
@@ -135092,11 +135815,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
135092
135815
  if (selectorContext?.summary) {
135093
135816
  hasSetConversationSummaryRef.current = true;
135094
135817
  }
135095
- settingsManager.setLocalLastSession({ agentId, conversationId: convId }, process.cwd());
135096
- settingsManager.setGlobalLastSession({
135097
- agentId,
135098
- conversationId: convId
135099
- });
135818
+ settingsManager.persistSession(agentId, convId);
135100
135819
  const currentAgentName = agentState.name || "Unnamed Agent";
135101
135820
  const successLines = resumeData.messageHistory.length > 0 ? [
135102
135821
  `Resumed conversation with "${currentAgentName}"`,
@@ -135206,11 +135925,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
135206
135925
  });
135207
135926
  await maybeCarryOverActiveConversationModel(conversation.id);
135208
135927
  setConversationId3(conversation.id);
135209
- settingsManager.setLocalLastSession({ agentId, conversationId: conversation.id }, process.cwd());
135210
- settingsManager.setGlobalLastSession({
135211
- agentId,
135212
- conversationId: conversation.id
135213
- });
135928
+ settingsManager.persistSession(agentId, conversation.id);
135214
135929
  const currentAgentName = agentState?.name || "Unnamed Agent";
135215
135930
  const shortConvId = conversation.id.slice(0, 20);
135216
135931
  const successLines = [
@@ -135303,11 +136018,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
135303
136018
  searchQuery: searchContext?.query,
135304
136019
  searchMessage: searchContext?.message
135305
136020
  };
135306
- settingsManager.setLocalLastSession({ agentId, conversationId: actualTargetConv }, process.cwd());
135307
- settingsManager.setGlobalLastSession({
135308
- agentId,
135309
- conversationId: actualTargetConv
135310
- });
136021
+ settingsManager.persistSession(agentId, actualTargetConv);
135311
136022
  const currentAgentName = agentState.name || "Unnamed Agent";
135312
136023
  const successOutput = [
135313
136024
  `Switched to conversation with "${currentAgentName}"`,
@@ -135488,7 +136199,7 @@ Open /mcp to attach or detach tools for this server.`, true);
135488
136199
  ]
135489
136200
  }, resumeKey, true, undefined, this);
135490
136201
  }
135491
- var import_react101, jsx_dev_runtime78, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES3 = 3, EMPTY_RESPONSE_MAX_RETRIES3 = 2, CONVERSATION_BUSY_MAX_RETRIES2 = 3, INTERRUPT_MESSAGE = "Interrupted – tell the agent what to do differently. Something went wrong? Use /feedback to report issues.", ERROR_FEEDBACK_HINT = "Something went wrong? Use /feedback to report issues.", OPUS_BEDROCK_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to Bedrock Opus 4.5", PROVIDER_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to another provider", INTERACTIVE_SLASH_COMMANDS, NON_STATE_COMMANDS, APPROVAL_OPTIONS_HEIGHT = 8, APPROVAL_PREVIEW_BUFFER = 4, MIN_WRAP_WIDTH = 10, TEXT_WRAP_GUTTER = 6, DIFF_WRAP_GUTTER = 12, SHELL_PREVIEW_MAX_LINES = 3, AUTO_REFLECTION_DESCRIPTION = "Reflect on recent conversations";
136202
+ var import_react101, jsx_dev_runtime78, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES3 = 3, EMPTY_RESPONSE_MAX_RETRIES3 = 2, TEMP_QUOTA_OVERRIDE_MODEL = "letta/auto", CONVERSATION_BUSY_MAX_RETRIES2 = 3, INTERRUPT_MESSAGE = "Interrupted – tell the agent what to do differently. Something went wrong? Use /feedback to report issues.", ERROR_FEEDBACK_HINT = "Something went wrong? Use /feedback to report issues.", OPUS_BEDROCK_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to Bedrock Opus 4.5", PROVIDER_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to another provider", INTERACTIVE_SLASH_COMMANDS, NON_STATE_COMMANDS, APPROVAL_OPTIONS_HEIGHT = 8, APPROVAL_PREVIEW_BUFFER = 4, MIN_WRAP_WIDTH = 10, TEXT_WRAP_GUTTER = 6, DIFF_WRAP_GUTTER = 12, SHELL_PREVIEW_MAX_LINES = 3, AUTO_REFLECTION_DESCRIPTION = "Reflect on recent conversations";
135492
136203
  var init_App2 = __esm(async () => {
135493
136204
  init_error();
135494
136205
  init_check_approval();
@@ -135636,7 +136347,8 @@ var init_App2 = __esm(async () => {
135636
136347
  "/export",
135637
136348
  "/download",
135638
136349
  "/statusline",
135639
- "/reasoning-tab"
136350
+ "/reasoning-tab",
136351
+ "/secret"
135640
136352
  ]);
135641
136353
  });
135642
136354
 
@@ -135658,13 +136370,13 @@ __export(exports_terminalKeybindingInstaller2, {
135658
136370
  });
135659
136371
  import {
135660
136372
  copyFileSync as copyFileSync2,
135661
- existsSync as existsSync35,
135662
- mkdirSync as mkdirSync22,
136373
+ existsSync as existsSync36,
136374
+ mkdirSync as mkdirSync23,
135663
136375
  readFileSync as readFileSync18,
135664
- writeFileSync as writeFileSync17
136376
+ writeFileSync as writeFileSync18
135665
136377
  } from "node:fs";
135666
136378
  import { homedir as homedir36, platform as platform6 } from "node:os";
135667
- import { dirname as dirname17, join as join45 } from "node:path";
136379
+ import { dirname as dirname18, join as join46 } from "node:path";
135668
136380
  function detectTerminalType2() {
135669
136381
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
135670
136382
  return "cursor";
@@ -135696,16 +136408,16 @@ function getKeybindingsPath2(terminal) {
135696
136408
  }[terminal];
135697
136409
  const os8 = platform6();
135698
136410
  if (os8 === "darwin") {
135699
- return join45(homedir36(), "Library", "Application Support", appName, "User", "keybindings.json");
136411
+ return join46(homedir36(), "Library", "Application Support", appName, "User", "keybindings.json");
135700
136412
  }
135701
136413
  if (os8 === "win32") {
135702
136414
  const appData = process.env.APPDATA;
135703
136415
  if (!appData)
135704
136416
  return null;
135705
- return join45(appData, appName, "User", "keybindings.json");
136417
+ return join46(appData, appName, "User", "keybindings.json");
135706
136418
  }
135707
136419
  if (os8 === "linux") {
135708
- return join45(homedir36(), ".config", appName, "User", "keybindings.json");
136420
+ return join46(homedir36(), ".config", appName, "User", "keybindings.json");
135709
136421
  }
135710
136422
  return null;
135711
136423
  }
@@ -135727,7 +136439,7 @@ function parseKeybindings2(content) {
135727
136439
  }
135728
136440
  }
135729
136441
  function keybindingExists2(keybindingsPath) {
135730
- if (!existsSync35(keybindingsPath))
136442
+ if (!existsSync36(keybindingsPath))
135731
136443
  return false;
135732
136444
  try {
135733
136445
  const content = readFileSync18(keybindingsPath, { encoding: "utf-8" });
@@ -135740,7 +136452,7 @@ function keybindingExists2(keybindingsPath) {
135740
136452
  }
135741
136453
  }
135742
136454
  function createBackup2(keybindingsPath) {
135743
- if (!existsSync35(keybindingsPath))
136455
+ if (!existsSync36(keybindingsPath))
135744
136456
  return null;
135745
136457
  const backupPath = `${keybindingsPath}.letta-backup`;
135746
136458
  try {
@@ -135755,13 +136467,13 @@ function installKeybinding2(keybindingsPath) {
135755
136467
  if (keybindingExists2(keybindingsPath)) {
135756
136468
  return { success: true, alreadyExists: true };
135757
136469
  }
135758
- const parentDir = dirname17(keybindingsPath);
135759
- if (!existsSync35(parentDir)) {
135760
- mkdirSync22(parentDir, { recursive: true });
136470
+ const parentDir = dirname18(keybindingsPath);
136471
+ if (!existsSync36(parentDir)) {
136472
+ mkdirSync23(parentDir, { recursive: true });
135761
136473
  }
135762
136474
  let keybindings = [];
135763
136475
  let backupPath = null;
135764
- if (existsSync35(keybindingsPath)) {
136476
+ if (existsSync36(keybindingsPath)) {
135765
136477
  backupPath = createBackup2(keybindingsPath);
135766
136478
  const content = readFileSync18(keybindingsPath, { encoding: "utf-8" });
135767
136479
  const parsed = parseKeybindings2(content);
@@ -135776,7 +136488,7 @@ function installKeybinding2(keybindingsPath) {
135776
136488
  keybindings.push(SHIFT_ENTER_KEYBINDING2);
135777
136489
  const newContent = `${JSON.stringify(keybindings, null, 2)}
135778
136490
  `;
135779
- writeFileSync17(keybindingsPath, newContent, { encoding: "utf-8" });
136491
+ writeFileSync18(keybindingsPath, newContent, { encoding: "utf-8" });
135780
136492
  return {
135781
136493
  success: true,
135782
136494
  backupPath: backupPath ?? undefined
@@ -135791,7 +136503,7 @@ function installKeybinding2(keybindingsPath) {
135791
136503
  }
135792
136504
  function removeKeybinding2(keybindingsPath) {
135793
136505
  try {
135794
- if (!existsSync35(keybindingsPath)) {
136506
+ if (!existsSync36(keybindingsPath)) {
135795
136507
  return { success: true };
135796
136508
  }
135797
136509
  const content = readFileSync18(keybindingsPath, { encoding: "utf-8" });
@@ -135805,7 +136517,7 @@ function removeKeybinding2(keybindingsPath) {
135805
136517
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
135806
136518
  const newContent = `${JSON.stringify(filtered, null, 2)}
135807
136519
  `;
135808
- writeFileSync17(keybindingsPath, newContent, { encoding: "utf-8" });
136520
+ writeFileSync18(keybindingsPath, newContent, { encoding: "utf-8" });
135809
136521
  return { success: true };
135810
136522
  } catch (error) {
135811
136523
  const message = error instanceof Error ? error.message : String(error);
@@ -135858,17 +136570,17 @@ function getWezTermConfigPath2() {
135858
136570
  }
135859
136571
  const xdgConfig = process.env.XDG_CONFIG_HOME;
135860
136572
  if (xdgConfig) {
135861
- const xdgPath = join45(xdgConfig, "wezterm", "wezterm.lua");
135862
- if (existsSync35(xdgPath))
136573
+ const xdgPath = join46(xdgConfig, "wezterm", "wezterm.lua");
136574
+ if (existsSync36(xdgPath))
135863
136575
  return xdgPath;
135864
136576
  }
135865
- const configPath = join45(homedir36(), ".config", "wezterm", "wezterm.lua");
135866
- if (existsSync35(configPath))
136577
+ const configPath = join46(homedir36(), ".config", "wezterm", "wezterm.lua");
136578
+ if (existsSync36(configPath))
135867
136579
  return configPath;
135868
- return join45(homedir36(), ".wezterm.lua");
136580
+ return join46(homedir36(), ".wezterm.lua");
135869
136581
  }
135870
136582
  function wezTermDeleteFixExists2(configPath) {
135871
- if (!existsSync35(configPath))
136583
+ if (!existsSync36(configPath))
135872
136584
  return false;
135873
136585
  try {
135874
136586
  const content = readFileSync18(configPath, { encoding: "utf-8" });
@@ -135885,7 +136597,7 @@ function installWezTermDeleteFix2() {
135885
136597
  }
135886
136598
  let content = "";
135887
136599
  let backupPath = null;
135888
- if (existsSync35(configPath)) {
136600
+ if (existsSync36(configPath)) {
135889
136601
  backupPath = `${configPath}.letta-backup`;
135890
136602
  copyFileSync2(configPath, backupPath);
135891
136603
  content = readFileSync18(configPath, { encoding: "utf-8" });
@@ -135914,11 +136626,11 @@ return config`);
135914
136626
  ${WEZTERM_DELETE_FIX2}
135915
136627
  `;
135916
136628
  }
135917
- const parentDir = dirname17(configPath);
135918
- if (!existsSync35(parentDir)) {
135919
- mkdirSync22(parentDir, { recursive: true });
136629
+ const parentDir = dirname18(configPath);
136630
+ if (!existsSync36(parentDir)) {
136631
+ mkdirSync23(parentDir, { recursive: true });
135920
136632
  }
135921
- writeFileSync17(configPath, content, { encoding: "utf-8" });
136633
+ writeFileSync18(configPath, content, { encoding: "utf-8" });
135922
136634
  return {
135923
136635
  success: true,
135924
136636
  backupPath: backupPath ?? undefined
@@ -135964,9 +136676,9 @@ __export(exports_settings2, {
135964
136676
  getSetting: () => getSetting2
135965
136677
  });
135966
136678
  import { homedir as homedir37 } from "node:os";
135967
- import { join as join46 } from "node:path";
136679
+ import { join as join47 } from "node:path";
135968
136680
  function getSettingsPath2() {
135969
- return join46(homedir37(), ".letta", "settings.json");
136681
+ return join47(homedir37(), ".letta", "settings.json");
135970
136682
  }
135971
136683
  async function loadSettings2() {
135972
136684
  const settingsPath = getSettingsPath2();
@@ -136003,7 +136715,7 @@ async function getSetting2(key) {
136003
136715
  return settings[key];
136004
136716
  }
136005
136717
  function getProjectSettingsPath2() {
136006
- return join46(process.cwd(), ".letta", "settings.local.json");
136718
+ return join47(process.cwd(), ".letta", "settings.local.json");
136007
136719
  }
136008
136720
  async function loadProjectSettings2() {
136009
136721
  const settingsPath = getProjectSettingsPath2();
@@ -136021,7 +136733,7 @@ async function loadProjectSettings2() {
136021
136733
  }
136022
136734
  async function saveProjectSettings2(settings) {
136023
136735
  const settingsPath = getProjectSettingsPath2();
136024
- const dirPath = join46(process.cwd(), ".letta");
136736
+ const dirPath = join47(process.cwd(), ".letta");
136025
136737
  try {
136026
136738
  if (!exists(dirPath)) {
136027
136739
  await mkdir(dirPath, { recursive: true });
@@ -136484,7 +137196,7 @@ __export(exports_import2, {
136484
137196
  });
136485
137197
  import { createReadStream as createReadStream2 } from "node:fs";
136486
137198
  import { chmod as chmod2, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
136487
- import { dirname as dirname18, resolve as resolve31 } from "node:path";
137199
+ import { dirname as dirname19, resolve as resolve31 } from "node:path";
136488
137200
  async function importAgentFromFile2(options) {
136489
137201
  const client = await getClient2();
136490
137202
  const resolvedPath = resolve31(options.filePath);
@@ -136543,7 +137255,7 @@ async function writeSkillFiles2(skillDir, files) {
136543
137255
  }
136544
137256
  async function writeSkillFile2(skillDir, filePath, content) {
136545
137257
  const fullPath = resolve31(skillDir, filePath);
136546
- await mkdir8(dirname18(fullPath), { recursive: true });
137258
+ await mkdir8(dirname19(fullPath), { recursive: true });
136547
137259
  await writeFile8(fullPath, content, "utf-8");
136548
137260
  const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
136549
137261
  if (isScript) {
@@ -136596,7 +137308,7 @@ function parseRegistryHandle2(handle) {
136596
137308
  }
136597
137309
  async function importAgentFromRegistry2(options) {
136598
137310
  const { tmpdir: tmpdir7 } = await import("node:os");
136599
- const { join: join47 } = await import("node:path");
137311
+ const { join: join48 } = await import("node:path");
136600
137312
  const { writeFile: writeFile9, unlink: unlink3 } = await import("node:fs/promises");
136601
137313
  const { author, name } = parseRegistryHandle2(options.handle);
136602
137314
  const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
@@ -136608,7 +137320,7 @@ async function importAgentFromRegistry2(options) {
136608
137320
  throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
136609
137321
  }
136610
137322
  const afContent = await response.text();
136611
- const tempPath = join47(tmpdir7(), `letta-import-${author}-${name}-${Date.now()}.af`);
137323
+ const tempPath = join48(tmpdir7(), `letta-import-${author}-${name}-${Date.now()}.af`);
136612
137324
  await writeFile9(tempPath, afContent, "utf-8");
136613
137325
  try {
136614
137326
  const result = await importAgentFromFile2({
@@ -136652,23 +137364,23 @@ __export(exports_memoryFilesystem2, {
136652
137364
  MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
136653
137365
  MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
136654
137366
  });
136655
- import { existsSync as existsSync36, mkdirSync as mkdirSync23 } from "node:fs";
137367
+ import { existsSync as existsSync37, mkdirSync as mkdirSync24 } from "node:fs";
136656
137368
  import { homedir as homedir38 } from "node:os";
136657
- import { join as join47 } from "node:path";
137369
+ import { join as join48 } from "node:path";
136658
137370
  function getMemoryFilesystemRoot2(agentId, homeDir = homedir38()) {
136659
- return join47(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
137371
+ return join48(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
136660
137372
  }
136661
137373
  function getMemorySystemDir2(agentId, homeDir = homedir38()) {
136662
- return join47(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
137374
+ return join48(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
136663
137375
  }
136664
137376
  function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir38()) {
136665
137377
  const root = getMemoryFilesystemRoot2(agentId, homeDir);
136666
137378
  const systemDir = getMemorySystemDir2(agentId, homeDir);
136667
- if (!existsSync36(root)) {
136668
- mkdirSync23(root, { recursive: true });
137379
+ if (!existsSync37(root)) {
137380
+ mkdirSync24(root, { recursive: true });
136669
137381
  }
136670
- if (!existsSync36(systemDir)) {
136671
- mkdirSync23(systemDir, { recursive: true });
137382
+ if (!existsSync37(systemDir)) {
137383
+ mkdirSync24(systemDir, { recursive: true });
136672
137384
  }
136673
137385
  }
136674
137386
  function labelFromRelativePath2(relativePath) {
@@ -136836,6 +137548,10 @@ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
136836
137548
  const result = await pullMemory2(agentId);
136837
137549
  pullSummary = result.summary;
136838
137550
  }
137551
+ const { initSecretsFromServer: initSecretsFromServer2 } = await init_secretsStore().then(() => exports_secretsStore);
137552
+ try {
137553
+ await initSecretsFromServer2(agentId, getMemoryFilesystemRoot2(agentId));
137554
+ } catch {}
136839
137555
  }
136840
137556
  const action = memfsFlag || shouldAutoEnableFromTag ? "enabled" : noMemfsFlag ? "disabled" : "unchanged";
136841
137557
  return {
@@ -140845,10 +141561,10 @@ async function runListenSubcommand(argv) {
140845
141561
 
140846
141562
  // src/cli/subcommands/memfs.ts
140847
141563
  await init_memoryGit();
140848
- import { cpSync, existsSync as existsSync19, mkdirSync as mkdirSync13, rmSync as rmSync2, statSync as statSync6 } from "node:fs";
141564
+ import { cpSync, existsSync as existsSync20, mkdirSync as mkdirSync14, rmSync as rmSync2, statSync as statSync6 } from "node:fs";
140849
141565
  import { readdir as readdir5 } from "node:fs/promises";
140850
141566
  import { homedir as homedir21 } from "node:os";
140851
- import { join as join24 } from "node:path";
141567
+ import { join as join25 } from "node:path";
140852
141568
  import { parseArgs as parseArgs6 } from "node:util";
140853
141569
  function printUsage3() {
140854
141570
  console.log(`
@@ -140873,7 +141589,7 @@ Examples:
140873
141589
  letta memfs export --agent agent-123 --out /tmp/letta-memfs-agent-123
140874
141590
  `.trim());
140875
141591
  }
140876
- function getAgentId3(agentFromArgs, agentIdFromArgs) {
141592
+ function getAgentId4(agentFromArgs, agentIdFromArgs) {
140877
141593
  return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
140878
141594
  }
140879
141595
  var MEMFS_OPTIONS = {
@@ -140893,10 +141609,10 @@ function parseMemfsArgs(argv) {
140893
141609
  });
140894
141610
  }
140895
141611
  function getMemoryRoot(agentId) {
140896
- return join24(homedir21(), ".letta", "agents", agentId, "memory");
141612
+ return join25(homedir21(), ".letta", "agents", agentId, "memory");
140897
141613
  }
140898
141614
  function getAgentRoot(agentId) {
140899
- return join24(homedir21(), ".letta", "agents", agentId);
141615
+ return join25(homedir21(), ".letta", "agents", agentId);
140900
141616
  }
140901
141617
  function formatBackupTimestamp(date = new Date) {
140902
141618
  const pad = (value) => String(value).padStart(2, "0");
@@ -140910,7 +141626,7 @@ function formatBackupTimestamp(date = new Date) {
140910
141626
  }
140911
141627
  async function listBackups(agentId) {
140912
141628
  const agentRoot = getAgentRoot(agentId);
140913
- if (!existsSync19(agentRoot)) {
141629
+ if (!existsSync20(agentRoot)) {
140914
141630
  return [];
140915
141631
  }
140916
141632
  const entries = await readdir5(agentRoot, { withFileTypes: true });
@@ -140920,7 +141636,7 @@ async function listBackups(agentId) {
140920
141636
  continue;
140921
141637
  if (!entry.name.startsWith("memory-backup-"))
140922
141638
  continue;
140923
- const path23 = join24(agentRoot, entry.name);
141639
+ const path23 = join25(agentRoot, entry.name);
140924
141640
  let createdAt = null;
140925
141641
  try {
140926
141642
  const stat6 = statSync6(path23);
@@ -140937,7 +141653,7 @@ function resolveBackupPath(agentId, from) {
140937
141653
  if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
140938
141654
  return from;
140939
141655
  }
140940
- return join24(getAgentRoot(agentId), from);
141656
+ return join25(getAgentRoot(agentId), from);
140941
141657
  }
140942
141658
  async function runMemfsSubcommand(argv) {
140943
141659
  let parsed;
@@ -140954,7 +141670,7 @@ async function runMemfsSubcommand(argv) {
140954
141670
  printUsage3();
140955
141671
  return 0;
140956
141672
  }
140957
- const agentId = getAgentId3(parsed.values.agent, parsed.values["agent-id"]);
141673
+ const agentId = getAgentId4(parsed.values.agent, parsed.values["agent-id"]);
140958
141674
  if (!agentId) {
140959
141675
  console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
140960
141676
  return 1;
@@ -140997,14 +141713,14 @@ async function runMemfsSubcommand(argv) {
140997
141713
  }
140998
141714
  if (action === "backup") {
140999
141715
  const root = getMemoryRoot(agentId);
141000
- if (!existsSync19(root)) {
141716
+ if (!existsSync20(root)) {
141001
141717
  console.error(`Memory directory not found for agent ${agentId}.`);
141002
141718
  return 1;
141003
141719
  }
141004
141720
  const agentRoot = getAgentRoot(agentId);
141005
141721
  const backupName = `memory-backup-${formatBackupTimestamp()}`;
141006
- const backupPath = join24(agentRoot, backupName);
141007
- if (existsSync19(backupPath)) {
141722
+ const backupPath = join25(agentRoot, backupName);
141723
+ if (existsSync20(backupPath)) {
141008
141724
  console.error(`Backup already exists at ${backupPath}`);
141009
141725
  return 1;
141010
141726
  }
@@ -141028,7 +141744,7 @@ async function runMemfsSubcommand(argv) {
141028
141744
  return 1;
141029
141745
  }
141030
141746
  const backupPath = resolveBackupPath(agentId, from);
141031
- if (!existsSync19(backupPath)) {
141747
+ if (!existsSync20(backupPath)) {
141032
141748
  console.error(`Backup not found: ${backupPath}`);
141033
141749
  return 1;
141034
141750
  }
@@ -141050,11 +141766,11 @@ async function runMemfsSubcommand(argv) {
141050
141766
  return 1;
141051
141767
  }
141052
141768
  const root = getMemoryRoot(agentId);
141053
- if (!existsSync19(root)) {
141769
+ if (!existsSync20(root)) {
141054
141770
  console.error(`Memory directory not found for agent ${agentId}.`);
141055
141771
  return 1;
141056
141772
  }
141057
- if (existsSync19(out)) {
141773
+ if (existsSync20(out)) {
141058
141774
  const stat6 = statSync6(out);
141059
141775
  if (stat6.isDirectory()) {
141060
141776
  const contents = await readdir5(out);
@@ -141067,7 +141783,7 @@ async function runMemfsSubcommand(argv) {
141067
141783
  return 1;
141068
141784
  }
141069
141785
  } else {
141070
- mkdirSync13(out, { recursive: true });
141786
+ mkdirSync14(out, { recursive: true });
141071
141787
  }
141072
141788
  cpSync(root, out, { recursive: true });
141073
141789
  console.log(JSON.stringify({ exportedFrom: root, exportedTo: out, agentId }, null, 2));
@@ -141137,7 +141853,7 @@ function parseOrder(value) {
141137
141853
  }
141138
141854
  return;
141139
141855
  }
141140
- function getAgentId4(agentFromArgs, agentIdFromArgs) {
141856
+ function getAgentId5(agentFromArgs, agentIdFromArgs) {
141141
141857
  return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
141142
141858
  }
141143
141859
  var MESSAGES_OPTIONS = {
@@ -141186,7 +141902,7 @@ async function runMessagesSubcommand(argv) {
141186
141902
  return 1;
141187
141903
  }
141188
141904
  const allAgents = parsed.values["all-agents"] ?? false;
141189
- const agentId = getAgentId4(parsed.values.agent, parsed.values["agent-id"]);
141905
+ const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
141190
141906
  if (!allAgents && !agentId) {
141191
141907
  console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
141192
141908
  return 1;
@@ -141203,7 +141919,7 @@ async function runMessagesSubcommand(argv) {
141203
141919
  return 0;
141204
141920
  }
141205
141921
  if (action === "list") {
141206
- const agentId = getAgentId4(parsed.values.agent, parsed.values["agent-id"]);
141922
+ const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
141207
141923
  if (!agentId) {
141208
141924
  console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
141209
141925
  return 1;
@@ -141281,7 +141997,7 @@ async function runSubcommand(argv) {
141281
141997
  init_readOnlyShell();
141282
141998
  init_shell_command_normalization();
141283
141999
  import { homedir as homedir22 } from "node:os";
141284
- import { isAbsolute as isAbsolute16, join as join25, relative as relative12, resolve as resolve23 } from "node:path";
142000
+ import { isAbsolute as isAbsolute16, join as join26, relative as relative12, resolve as resolve23 } from "node:path";
141285
142001
  var MODE_KEY2 = Symbol.for("@letta/permissionMode");
141286
142002
  var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
141287
142003
  var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
@@ -141510,7 +142226,7 @@ class PermissionModeManager2 {
141510
142226
  return "allow";
141511
142227
  }
141512
142228
  if (writeTools.includes(toolName)) {
141513
- const plansDir = join25(homedir22(), ".letta", "plans");
142229
+ const plansDir = join26(homedir22(), ".letta", "plans");
141514
142230
  const targetPath = toolArgs?.file_path || toolArgs?.path;
141515
142231
  let candidatePaths = [];
141516
142232
  if ((toolName === "ApplyPatch" || toolName === "apply_patch" || toolName === "memory_apply_patch") && toolArgs?.input) {
@@ -141561,7 +142277,7 @@ class PermissionModeManager2 {
141561
142277
  }
141562
142278
  const planWritePath = extractPlanFileWritePathFromShellCommand2(command);
141563
142279
  if (planWritePath) {
141564
- const plansDir = join25(homedir22(), ".letta", "plans");
142280
+ const plansDir = join26(homedir22(), ".letta", "plans");
141565
142281
  const resolvedPath = resolvePlanTargetPath2(planWritePath, workingDirectory);
141566
142282
  if (resolvedPath && isPathInPlansDir2(resolvedPath, plansDir)) {
141567
142283
  return "allow";
@@ -141590,7 +142306,7 @@ init_fs();
141590
142306
  await init_secrets();
141591
142307
  import { randomUUID as randomUUID4 } from "node:crypto";
141592
142308
  import { homedir as homedir23 } from "node:os";
141593
- import { join as join26, resolve as resolve24 } from "node:path";
142309
+ import { join as join27, resolve as resolve24 } from "node:path";
141594
142310
  var DEFAULT_SETTINGS3 = {
141595
142311
  lastAgent: null,
141596
142312
  tokenStreaming: false,
@@ -141599,6 +142315,7 @@ var DEFAULT_SETTINGS3 = {
141599
142315
  enableSleeptime: false,
141600
142316
  conversationSwitchAlertEnabled: false,
141601
142317
  sessionContextEnabled: true,
142318
+ autoSwapOnQuotaLimit: true,
141602
142319
  memoryReminderInterval: 25,
141603
142320
  reflectionTrigger: "step-count",
141604
142321
  reflectionStepCount: 25,
@@ -141958,7 +142675,7 @@ class SettingsManager2 {
141958
142675
  return;
141959
142676
  const settingsPath = this.getSettingsPath();
141960
142677
  const home = process.env.HOME || homedir23();
141961
- const dirPath = join26(home, ".letta");
142678
+ const dirPath = join27(home, ".letta");
141962
142679
  try {
141963
142680
  if (!exists(dirPath)) {
141964
142681
  await mkdir(dirPath, { recursive: true });
@@ -141997,7 +142714,7 @@ class SettingsManager2 {
141997
142714
  if (!settings)
141998
142715
  return;
141999
142716
  const settingsPath = this.getProjectSettingsPath(workingDirectory);
142000
- const dirPath = join26(workingDirectory, ".letta");
142717
+ const dirPath = join27(workingDirectory, ".letta");
142001
142718
  try {
142002
142719
  let existingSettings = {};
142003
142720
  if (exists(settingsPath)) {
@@ -142019,16 +142736,16 @@ class SettingsManager2 {
142019
142736
  }
142020
142737
  getSettingsPath() {
142021
142738
  const home = process.env.HOME || homedir23();
142022
- return join26(home, ".letta", "settings.json");
142739
+ return join27(home, ".letta", "settings.json");
142023
142740
  }
142024
142741
  getProjectSettingsPath(workingDirectory) {
142025
- return join26(workingDirectory, ".letta", "settings.json");
142742
+ return join27(workingDirectory, ".letta", "settings.json");
142026
142743
  }
142027
142744
  isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
142028
142745
  return resolve24(this.getProjectSettingsPath(workingDirectory)) === resolve24(this.getSettingsPath());
142029
142746
  }
142030
142747
  getLocalProjectSettingsPath(workingDirectory) {
142031
- return join26(workingDirectory, ".letta", "settings.local.json");
142748
+ return join27(workingDirectory, ".letta", "settings.local.json");
142032
142749
  }
142033
142750
  async loadLocalProjectSettings(workingDirectory = process.cwd()) {
142034
142751
  const cached = this.localProjectSettings.get(workingDirectory);
@@ -142089,7 +142806,7 @@ class SettingsManager2 {
142089
142806
  if (!settings)
142090
142807
  return;
142091
142808
  const settingsPath = this.getLocalProjectSettingsPath(workingDirectory);
142092
- const dirPath = join26(workingDirectory, ".letta");
142809
+ const dirPath = join27(workingDirectory, ".letta");
142093
142810
  try {
142094
142811
  if (!exists(dirPath)) {
142095
142812
  await mkdir(dirPath, { recursive: true });
@@ -142199,6 +142916,11 @@ class SettingsManager2 {
142199
142916
  }
142200
142917
  return this.getGlobalLastAgentId();
142201
142918
  }
142919
+ persistSession(agentId, conversationId, workingDirectory = process.cwd()) {
142920
+ const session = { agentId, conversationId };
142921
+ this.setLocalLastSession(session, workingDirectory);
142922
+ this.setGlobalLastSession(session);
142923
+ }
142202
142924
  getGlobalPinnedAgents() {
142203
142925
  const settings = this.getSettings();
142204
142926
  const serverKey = getCurrentServerKey2(settings);
@@ -142438,7 +143160,7 @@ class SettingsManager2 {
142438
143160
  this.upsertAgentSettings(agentId, { systemPromptPreset: "" });
142439
143161
  }
142440
143162
  hasLocalLettaDir(workingDirectory = process.cwd()) {
142441
- const dirPath = join26(workingDirectory, ".letta");
143163
+ const dirPath = join27(workingDirectory, ".letta");
142442
143164
  return exists(dirPath);
142443
143165
  }
142444
143166
  storeOAuthState(state, codeVerifier, redirectUri, provider) {
@@ -142827,6 +143549,7 @@ await __promiseAll([
142827
143549
  init_hooks(),
142828
143550
  init_openai_codex_provider(),
142829
143551
  init_telemetry(),
143552
+ init_secret_substitution(),
142830
143553
  init_toolDefinitions()
142831
143554
  ]);
142832
143555
  var FILE_MODIFYING_TOOLS2 = new Set([
@@ -143113,14 +143836,14 @@ async function clearPersistedClientToolRules2(agentId) {
143113
143836
  // src/utils/debug.ts
143114
143837
  import {
143115
143838
  appendFileSync as appendFileSync3,
143116
- existsSync as existsSync20,
143117
- mkdirSync as mkdirSync14,
143839
+ existsSync as existsSync21,
143840
+ mkdirSync as mkdirSync15,
143118
143841
  readdirSync as readdirSync10,
143119
143842
  readFileSync as readFileSync10,
143120
143843
  unlinkSync as unlinkSync6
143121
143844
  } from "node:fs";
143122
143845
  import { homedir as homedir24 } from "node:os";
143123
- import { join as join27 } from "node:path";
143846
+ import { join as join28 } from "node:path";
143124
143847
  import { format as format2 } from "node:util";
143125
143848
  function isDebugEnabled2() {
143126
143849
  const lettaDebug = process.env.LETTA_DEBUG;
@@ -143142,7 +143865,7 @@ function printDebugLine2(line, level = "log") {
143142
143865
  const colored = level === "warn" ? `\x1B[38;5;167m${line.trimEnd()}\x1B[0m` : `\x1B[38;5;179m${line.trimEnd()}\x1B[0m`;
143143
143866
  console.error(colored);
143144
143867
  }
143145
- var DEBUG_LOG_DIR2 = join27(homedir24(), ".letta", "logs", "debug");
143868
+ var DEBUG_LOG_DIR2 = join28(homedir24(), ".letta", "logs", "debug");
143146
143869
  var MAX_SESSION_FILES3 = 5;
143147
143870
  var DEFAULT_TAIL_LINES2 = 50;
143148
143871
 
@@ -143154,8 +143877,8 @@ class DebugLogFile2 {
143154
143877
  const telem = process.env.LETTA_CODE_TELEM;
143155
143878
  if (telem === "0" || telem === "false")
143156
143879
  return;
143157
- this.agentDir = join27(DEBUG_LOG_DIR2, agentId);
143158
- this.logPath = join27(this.agentDir, `${sessionId}.log`);
143880
+ this.agentDir = join28(DEBUG_LOG_DIR2, agentId);
143881
+ this.logPath = join28(this.agentDir, `${sessionId}.log`);
143159
143882
  this.dirCreated = false;
143160
143883
  this.pruneOldSessions();
143161
143884
  }
@@ -143171,7 +143894,7 @@ class DebugLogFile2 {
143171
143894
  if (!this.logPath)
143172
143895
  return;
143173
143896
  try {
143174
- if (!existsSync20(this.logPath))
143897
+ if (!existsSync21(this.logPath))
143175
143898
  return;
143176
143899
  const content = readFileSync10(this.logPath, "utf8");
143177
143900
  const lines = content.trimEnd().split(`
@@ -143186,8 +143909,8 @@ class DebugLogFile2 {
143186
143909
  if (this.dirCreated || !this.agentDir)
143187
143910
  return;
143188
143911
  try {
143189
- if (!existsSync20(this.agentDir)) {
143190
- mkdirSync14(this.agentDir, { recursive: true });
143912
+ if (!existsSync21(this.agentDir)) {
143913
+ mkdirSync15(this.agentDir, { recursive: true });
143191
143914
  }
143192
143915
  this.dirCreated = true;
143193
143916
  } catch {}
@@ -143196,14 +143919,14 @@ class DebugLogFile2 {
143196
143919
  if (!this.agentDir)
143197
143920
  return;
143198
143921
  try {
143199
- if (!existsSync20(this.agentDir))
143922
+ if (!existsSync21(this.agentDir))
143200
143923
  return;
143201
143924
  const files = readdirSync10(this.agentDir).filter((f) => f.endsWith(".log")).sort();
143202
143925
  if (files.length >= MAX_SESSION_FILES3) {
143203
143926
  const toDelete = files.slice(0, files.length - MAX_SESSION_FILES3 + 1);
143204
143927
  for (const file of toDelete) {
143205
143928
  try {
143206
- unlinkSync6(join27(this.agentDir, file));
143929
+ unlinkSync6(join28(this.agentDir, file));
143207
143930
  } catch {}
143208
143931
  }
143209
143932
  }
@@ -143334,12 +144057,12 @@ EXAMPLES
143334
144057
  console.log(usage);
143335
144058
  }
143336
144059
  async function printInfo() {
143337
- const { join: join48 } = await import("path");
144060
+ const { join: join49 } = await import("path");
143338
144061
  const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
143339
144062
  const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills2(), exports_skills2));
143340
144063
  const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
143341
144064
  const cwd2 = process.cwd();
143342
- const skillsDir = join48(cwd2, SKILLS_DIR3);
144065
+ const skillsDir = join49(cwd2, SKILLS_DIR3);
143343
144066
  const skillsExist = exists3(skillsDir);
143344
144067
  await settingsManager2.loadLocalProjectSettings(cwd2);
143345
144068
  const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
@@ -143724,9 +144447,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
143724
144447
  }
143725
144448
  } else {
143726
144449
  const { resolve: resolve32 } = await import("path");
143727
- const { existsSync: existsSync37 } = await import("fs");
144450
+ const { existsSync: existsSync38 } = await import("fs");
143728
144451
  const resolvedPath = resolve32(fromAfFile);
143729
- if (!existsSync37(resolvedPath)) {
144452
+ if (!existsSync38(resolvedPath)) {
143730
144453
  console.error(`Error: AgentFile not found: ${resolvedPath}`);
143731
144454
  process.exit(1);
143732
144455
  }
@@ -144050,6 +144773,13 @@ Error: ${message}`);
144050
144773
  process.exit(1);
144051
144774
  }
144052
144775
  if (forceNew2 || agentIdArg || fromAfFile2) {
144776
+ if (agentIdArg && !forceNew2 && !fromAfFile2 && !forceNewConversation) {
144777
+ await settingsManager2.loadLocalProjectSettings(process.cwd());
144778
+ const localSession2 = settingsManager2.getLocalLastSession(process.cwd());
144779
+ if (localSession2?.agentId === agentIdArg && localSession2.conversationId && localSession2.conversationId !== "default") {
144780
+ setSelectedConversationId(localSession2.conversationId);
144781
+ }
144782
+ }
144053
144783
  setLoadingState("assembling");
144054
144784
  return;
144055
144785
  }
@@ -144442,11 +145172,7 @@ Error: ${message}`);
144442
145172
  }
144443
145173
  }
144444
145174
  if (!isSubagent) {
144445
- settingsManager2.setLocalLastSession({ agentId: agent.id, conversationId: conversationIdToUse }, process.cwd());
144446
- settingsManager2.setGlobalLastSession({
144447
- agentId: agent.id,
144448
- conversationId: conversationIdToUse
144449
- });
145175
+ settingsManager2.persistSession(agent.id, conversationIdToUse);
144450
145176
  }
144451
145177
  setAgentId(agent.id);
144452
145178
  setAgentState(agent);
@@ -144590,4 +145316,4 @@ Error during initialization: ${message}`);
144590
145316
  }
144591
145317
  main();
144592
145318
 
144593
- //# debugId=7A6844DE3E1D139864756E2164756E21
145319
+ //# debugId=773D326804039A9D64756E2164756E21