@letta-ai/letta-code 0.23.0 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/letta.js +472 -250
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3269,7 +3269,7 @@ var package_default;
3269
3269
  var init_package = __esm(() => {
3270
3270
  package_default = {
3271
3271
  name: "@letta-ai/letta-code",
3272
- version: "0.23.0",
3272
+ version: "0.23.2",
3273
3273
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3274
3274
  type: "module",
3275
3275
  bin: {
@@ -41452,10 +41452,22 @@ var init_runtime2 = __esm(() => {
41452
41452
  // src/channels/slack/adapter.ts
41453
41453
  import { readFile as readFile4 } from "node:fs/promises";
41454
41454
  import { basename as basename4, extname as extname3 } from "node:path";
41455
+ function isConstructorFunction(value) {
41456
+ return typeof value === "function";
41457
+ }
41458
+ function resolveSlackAppModule(value) {
41459
+ if (!value || typeof value !== "object") {
41460
+ return null;
41461
+ }
41462
+ const app = Reflect.get(value, "App");
41463
+ return isConstructorFunction(app) ? app : null;
41464
+ }
41455
41465
  function resolveSlackAppConstructor(mod) {
41456
- const App2 = mod.default;
41466
+ const defaultExport = mod && typeof mod === "object" ? Reflect.get(mod, "default") : undefined;
41467
+ const nestedDefault = defaultExport && typeof defaultExport === "object" ? Reflect.get(defaultExport, "default") : undefined;
41468
+ const App2 = resolveSlackAppModule(mod) ?? resolveSlackAppModule(defaultExport) ?? resolveSlackAppModule(nestedDefault) ?? (isConstructorFunction(defaultExport) ? defaultExport : null);
41457
41469
  if (!App2) {
41458
- throw new Error('Installed Slack runtime did not export default "App".');
41470
+ throw new Error('Installed Slack runtime did not export constructor "App".');
41459
41471
  }
41460
41472
  return App2;
41461
41473
  }
@@ -43143,6 +43155,7 @@ __export(exports_service, {
43143
43155
  removeChannelAccountLive: () => removeChannelAccountLive,
43144
43156
  refreshChannelAccountDisplayNameLive: () => refreshChannelAccountDisplayNameLive,
43145
43157
  listPendingPairingSnapshots: () => listPendingPairingSnapshots,
43158
+ listEnabledChannelIds: () => listEnabledChannelIds,
43146
43159
  listChannelTargetSnapshots: () => listChannelTargetSnapshots,
43147
43160
  listChannelSummaries: () => listChannelSummaries,
43148
43161
  listChannelRouteSnapshots: () => listChannelRouteSnapshots,
@@ -43400,6 +43413,9 @@ function listChannelSummaries() {
43400
43413
  };
43401
43414
  });
43402
43415
  }
43416
+ function listEnabledChannelIds() {
43417
+ return getSupportedChannelIds().filter((channelId) => listChannelAccounts(channelId).some((account) => account.enabled));
43418
+ }
43403
43419
  function getChannelConfigSnapshot(channelId, accountId) {
43404
43420
  assertSupportedChannelId(channelId);
43405
43421
  const account = getSelectedChannelAccount(channelId, accountId);
@@ -55627,7 +55643,8 @@ async function executeSingleDecision(decision, onChunk, options) {
55627
55643
  toolCallId: decision.approval.toolCallId,
55628
55644
  toolContextId: options?.toolContextId,
55629
55645
  parentScope: options?.parentScope,
55630
- onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined
55646
+ onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined,
55647
+ onFileWrite: options?.onFileWrite
55631
55648
  });
55632
55649
  if (onChunk) {
55633
55650
  onChunk({
@@ -77520,6 +77537,8 @@ var init_analyzer = __esm(() => {
77520
77537
  });
77521
77538
 
77522
77539
  // src/tools/manager.ts
77540
+ import * as nodeFs from "node:fs/promises";
77541
+ import * as nodePath from "node:path";
77523
77542
  function maybeAppendChannelTools(toolNames) {
77524
77543
  if (getActiveChannelIds().length > 0 && !toolNames.includes("MessageChannel")) {
77525
77544
  return [...toolNames, "MessageChannel"];
@@ -77590,8 +77609,8 @@ function acquireSwitchLock() {
77590
77609
  const lock = getSwitchLock();
77591
77610
  lock.refCount++;
77592
77611
  if (lock.refCount === 1) {
77593
- lock.promise = new Promise((resolve24) => {
77594
- lock.resolve = resolve24;
77612
+ lock.promise = new Promise((resolve25) => {
77613
+ lock.resolve = resolve25;
77595
77614
  });
77596
77615
  }
77597
77616
  }
@@ -78120,6 +78139,16 @@ async function executeTool(name, args, options) {
78120
78139
  const result = await withExecutionWorkingDirectory(workingDirectory, () => tool.fn(enhancedArgs));
78121
78140
  const duration = Date.now() - startTime;
78122
78141
  refreshFileIndex();
78142
+ if (options?.onFileWrite && FILE_MUTATING_TOOLS.has(internalName)) {
78143
+ const filePath = enhancedArgs.file_path;
78144
+ if (filePath) {
78145
+ try {
78146
+ const resolvedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.resolve(process.env.USER_CWD || process.cwd(), filePath);
78147
+ const content = await nodeFs.readFile(resolvedPath, "utf-8");
78148
+ options.onFileWrite(resolvedPath, content);
78149
+ } catch {}
78150
+ }
78151
+ }
78123
78152
  const recordResult = isRecord(result) ? result : undefined;
78124
78153
  const stdoutValue = recordResult?.stdout;
78125
78154
  const stderrValue = recordResult?.stderr;
@@ -78253,7 +78282,7 @@ function clearToolsWithLock() {
78253
78282
  releaseSwitchLock();
78254
78283
  }
78255
78284
  }
78256
- var TOOL_NAMES, STREAMING_SHELL_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, REGISTRY_KEY, SWITCH_LOCK_KEY, EXECUTION_CONTEXTS_KEY, toolRegistry, toolExecutionContextCounter = 0, EXTERNAL_TOOLS_KEY, EXTERNAL_EXECUTOR_KEY;
78285
+ var TOOL_NAMES, STREAMING_SHELL_TOOLS, FILE_MUTATING_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, REGISTRY_KEY, SWITCH_LOCK_KEY, EXECUTION_CONTEXTS_KEY, toolRegistry, toolExecutionContextCounter = 0, EXTERNAL_TOOLS_KEY, EXTERNAL_EXECUTOR_KEY;
78257
78286
  var init_manager3 = __esm(async () => {
78258
78287
  init_model2();
78259
78288
  init_subagents();
@@ -78283,6 +78312,7 @@ var init_manager3 = __esm(async () => {
78283
78312
  "run_shell_command",
78284
78313
  "RunShellCommand"
78285
78314
  ]);
78315
+ FILE_MUTATING_TOOLS = new Set(["Edit", "Write", "MultiEdit", "replace"]);
78286
78316
  TOOL_NAME_MAPPINGS = {
78287
78317
  glob_gemini: "glob",
78288
78318
  write_todos: "write_todos",
@@ -81705,7 +81735,7 @@ import {
81705
81735
  appendFile,
81706
81736
  mkdir as mkdir7,
81707
81737
  readdir as readdir5,
81708
- readFile as readFile9,
81738
+ readFile as readFile10,
81709
81739
  writeFile as writeFile7
81710
81740
  } from "node:fs/promises";
81711
81741
  import { homedir as homedir21, tmpdir as tmpdir3 } from "node:os";
@@ -81752,7 +81782,7 @@ async function collectParentMemoryFiles(memoryDir) {
81752
81782
  continue;
81753
81783
  }
81754
81784
  try {
81755
- const content = await readFile9(entryPath, "utf-8");
81785
+ const content = await readFile10(entryPath, "utf-8");
81756
81786
  const { frontmatter } = parseFrontmatter(content);
81757
81787
  const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
81758
81788
  files.push({
@@ -82012,7 +82042,7 @@ async function ensurePaths(paths) {
82012
82042
  }
82013
82043
  async function readState(paths) {
82014
82044
  try {
82015
- const raw = await readFile9(paths.statePath, "utf-8");
82045
+ const raw = await readFile10(paths.statePath, "utf-8");
82016
82046
  const parsed = parseJsonLine(raw);
82017
82047
  if (!parsed) {
82018
82048
  return defaultState();
@@ -82032,7 +82062,7 @@ async function writeState(paths, state) {
82032
82062
  }
82033
82063
  async function readTranscriptLines(paths) {
82034
82064
  try {
82035
- const raw = await readFile9(paths.transcriptPath, "utf-8");
82065
+ const raw = await readFile10(paths.transcriptPath, "utf-8");
82036
82066
  return raw.split(`
82037
82067
  `).map((line) => line.trim()).filter((line) => line.length > 0);
82038
82068
  } catch {
@@ -82391,11 +82421,11 @@ async function discoverFallbackRunIdWithTimeout(client, ctx) {
82391
82421
  return withTimeout(discoverFallbackRunIdForResume(client, ctx), FALLBACK_RUN_DISCOVERY_TIMEOUT_MS, `Fallback run discovery timed out after ${FALLBACK_RUN_DISCOVERY_TIMEOUT_MS}ms`);
82392
82422
  }
82393
82423
  function withTimeout(promise, timeoutMs, timeoutMessage) {
82394
- return new Promise((resolve24, reject) => {
82424
+ return new Promise((resolve25, reject) => {
82395
82425
  const timer = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
82396
82426
  promise.then((value) => {
82397
82427
  clearTimeout(timer);
82398
- resolve24(value);
82428
+ resolve25(value);
82399
82429
  }, (error) => {
82400
82430
  clearTimeout(timer);
82401
82431
  reject(error);
@@ -83535,7 +83565,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
83535
83565
  if (isInterrupted()) {
83536
83566
  return Promise.reject(new Error("Cancelled by user"));
83537
83567
  }
83538
- return new Promise((resolve24, reject) => {
83568
+ return new Promise((resolve25, reject) => {
83539
83569
  let settled = false;
83540
83570
  const cleanupAbortListener = () => {
83541
83571
  abortSignal?.removeEventListener("abort", handleAbort);
@@ -83546,7 +83576,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
83546
83576
  }
83547
83577
  settled = true;
83548
83578
  cleanupAbortListener();
83549
- resolve24(response);
83579
+ resolve25(response);
83550
83580
  };
83551
83581
  const wrappedReject = (error) => {
83552
83582
  if (settled) {
@@ -87209,7 +87239,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
87209
87239
  conversationId
87210
87240
  });
87211
87241
  }
87212
- await new Promise((resolve24) => setTimeout(resolve24, delayMs));
87242
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
87213
87243
  if (abortSignal?.aborted) {
87214
87244
  throw new Error("Cancelled by user");
87215
87245
  }
@@ -87264,7 +87294,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
87264
87294
  agentId: runtime.agentId ?? undefined,
87265
87295
  conversationId
87266
87296
  });
87267
- await new Promise((resolve24) => setTimeout(resolve24, delayMs));
87297
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
87268
87298
  if (abortSignal?.aborted) {
87269
87299
  throw new Error("Cancelled by user");
87270
87300
  }
@@ -87339,7 +87369,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
87339
87369
  retryAfterMs
87340
87370
  });
87341
87371
  transientRetries = attempt;
87342
- await new Promise((resolve24) => setTimeout(resolve24, delayMs));
87372
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
87343
87373
  if (abortSignal?.aborted) {
87344
87374
  throw new Error("Cancelled by user");
87345
87375
  }
@@ -87384,7 +87414,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
87384
87414
  category: "conversation_busy",
87385
87415
  attempt: conversationBusyRetries
87386
87416
  });
87387
- await new Promise((resolve24) => setTimeout(resolve24, retryDelayMs));
87417
+ await new Promise((resolve25) => setTimeout(resolve25, retryDelayMs));
87388
87418
  if (abortSignal?.aborted) {
87389
87419
  throw new Error("Cancelled by user");
87390
87420
  }
@@ -87422,6 +87452,7 @@ var init_send = __esm(async () => {
87422
87452
  });
87423
87453
 
87424
87454
  // src/websocket/listener/turn-approval.ts
87455
+ import WebSocket2 from "ws";
87425
87456
  async function handleApprovalStop(params) {
87426
87457
  const {
87427
87458
  approvals,
@@ -87647,11 +87678,24 @@ async function handleApprovalStop(params) {
87647
87678
  if (shouldInterrupt()) {
87648
87679
  return interruptTermination();
87649
87680
  }
87681
+ const onFileWrite = (filePath, content) => {
87682
+ if (socket.readyState === WebSocket2.OPEN) {
87683
+ socket.send(JSON.stringify({
87684
+ type: "file_ops",
87685
+ path: filePath,
87686
+ cg_entries: [],
87687
+ ops: [],
87688
+ source: "agent",
87689
+ document_content: content
87690
+ }));
87691
+ }
87692
+ };
87650
87693
  const executionResults = await executeApprovalBatch(decisions, undefined, {
87651
87694
  toolContextId: turnToolContextId ?? undefined,
87652
87695
  abortSignal: abortController.signal,
87653
87696
  workingDirectory: turnWorkingDirectory,
87654
- parentScope: agentId && conversationId ? { agentId, conversationId } : undefined
87697
+ parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
87698
+ onFileWrite
87655
87699
  });
87656
87700
  const persistedExecutionResults = normalizeExecutionResultsForInterruptParity(runtime, executionResults, lastExecutingToolCallIds);
87657
87701
  validateApprovalResultIds(decisions.map((decision) => ({
@@ -88276,7 +88320,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
88276
88320
  agentId,
88277
88321
  conversationId
88278
88322
  });
88279
- await new Promise((resolve24) => setTimeout(resolve24, delayMs));
88323
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
88280
88324
  if (turnAbortSignal.aborted) {
88281
88325
  throw new Error("Cancelled by user");
88282
88326
  }
@@ -88321,7 +88365,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
88321
88365
  agentId,
88322
88366
  conversationId
88323
88367
  });
88324
- await new Promise((resolve24) => setTimeout(resolve24, delayMs));
88368
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
88325
88369
  if (turnAbortSignal.aborted) {
88326
88370
  throw new Error("Cancelled by user");
88327
88371
  }
@@ -88811,7 +88855,7 @@ var init_commands = __esm(async () => {
88811
88855
  });
88812
88856
 
88813
88857
  // src/websocket/listener/protocol-outbound.ts
88814
- import WebSocket2 from "ws";
88858
+ import WebSocket3 from "ws";
88815
88859
  function getCachedDeviceGitContext(cwd2) {
88816
88860
  const now = Date.now();
88817
88861
  const cached = gitContextCache.get(cwd2);
@@ -88928,7 +88972,7 @@ function buildDeviceStatus(runtime, params) {
88928
88972
  return {
88929
88973
  current_connection_id: listener.connectionId,
88930
88974
  connection_name: listener.connectionName,
88931
- is_online: listener.socket?.readyState === WebSocket2.OPEN,
88975
+ is_online: listener.socket?.readyState === WebSocket3.OPEN,
88932
88976
  is_processing: !!conversationRuntime?.isProcessing,
88933
88977
  current_permission_mode: conversationPermissionModeState.mode,
88934
88978
  current_working_directory: resolvedCwd,
@@ -88996,7 +89040,7 @@ function setLoopStatus(runtime, status, scope) {
88996
89040
  emitLoopStatusIfOpen(runtime, scope);
88997
89041
  }
88998
89042
  function emitProtocolV2Message(socket, runtime, message, scope) {
88999
- if (socket.readyState !== WebSocket2.OPEN) {
89043
+ if (socket.readyState !== WebSocket3.OPEN) {
89000
89044
  return;
89001
89045
  }
89002
89046
  const listener = getListenerRuntime(runtime);
@@ -89048,13 +89092,13 @@ function emitLoopStatusUpdate(socket, runtime, scope) {
89048
89092
  }
89049
89093
  function emitLoopStatusIfOpen(runtime, scope) {
89050
89094
  const listener = getListenerRuntime(runtime);
89051
- if (listener?.socket?.readyState === WebSocket2.OPEN) {
89095
+ if (listener?.socket?.readyState === WebSocket3.OPEN) {
89052
89096
  emitLoopStatusUpdate(listener.socket, runtime, scope);
89053
89097
  }
89054
89098
  }
89055
89099
  function emitDeviceStatusIfOpen(runtime, scope) {
89056
89100
  const listener = getListenerRuntime(runtime);
89057
- if (listener?.socket?.readyState === WebSocket2.OPEN) {
89101
+ if (listener?.socket?.readyState === WebSocket3.OPEN) {
89058
89102
  emitDeviceStatusUpdate(listener.socket, runtime, scope);
89059
89103
  }
89060
89104
  }
@@ -89113,7 +89157,7 @@ function emitDequeuedUserMessage(socket, runtime, incoming, batch) {
89113
89157
  }
89114
89158
  function emitQueueUpdateIfOpen(runtime, scope) {
89115
89159
  const listener = getListenerRuntime(runtime);
89116
- if (listener?.socket?.readyState === WebSocket2.OPEN) {
89160
+ if (listener?.socket?.readyState === WebSocket3.OPEN) {
89117
89161
  emitQueueUpdate(listener.socket, runtime, scope);
89118
89162
  }
89119
89163
  }
@@ -89169,7 +89213,7 @@ function emitSubagentStateUpdate(socket, runtime, scope) {
89169
89213
  }
89170
89214
  function emitSubagentStateIfOpen(runtime, scope) {
89171
89215
  const listener = getListenerRuntime(runtime);
89172
- if (listener?.socket?.readyState === WebSocket2.OPEN) {
89216
+ if (listener?.socket?.readyState === WebSocket3.OPEN) {
89173
89217
  emitSubagentStateUpdate(listener.socket, runtime, scope);
89174
89218
  }
89175
89219
  }
@@ -89787,7 +89831,7 @@ var init_toolset_labels = __esm(() => {
89787
89831
 
89788
89832
  // src/websocket/terminalHandler.ts
89789
89833
  import * as os4 from "node:os";
89790
- import WebSocket3 from "ws";
89834
+ import WebSocket4 from "ws";
89791
89835
  function getDefaultShell() {
89792
89836
  if (os4.platform() === "win32") {
89793
89837
  return process.env.COMSPEC || "cmd.exe";
@@ -89795,7 +89839,7 @@ function getDefaultShell() {
89795
89839
  return process.env.SHELL || "/bin/zsh";
89796
89840
  }
89797
89841
  function sendTerminalMessage(socket, message) {
89798
- if (socket.readyState === WebSocket3.OPEN) {
89842
+ if (socket.readyState === WebSocket4.OPEN) {
89799
89843
  socket.send(JSON.stringify(message));
89800
89844
  }
89801
89845
  }
@@ -90163,6 +90207,12 @@ function isEditFileCommand(value) {
90163
90207
  const c = value;
90164
90208
  return c.type === "edit_file" && typeof c.file_path === "string" && typeof c.old_string === "string" && typeof c.new_string === "string" && typeof c.request_id === "string" && (c.replace_all === undefined || typeof c.replace_all === "boolean") && (c.expected_replacements === undefined || typeof c.expected_replacements === "number" && Number.isInteger(c.expected_replacements) && c.expected_replacements > 0);
90165
90209
  }
90210
+ function isFileOpsCommand(value) {
90211
+ if (!value || typeof value !== "object")
90212
+ return false;
90213
+ const c = value;
90214
+ return c.type === "file_ops" && typeof c.path === "string" && Array.isArray(c.cg_entries) && Array.isArray(c.ops) && typeof c.source === "string";
90215
+ }
90166
90216
  function isListMemoryCommand(value) {
90167
90217
  if (!value || typeof value !== "object")
90168
90218
  return false;
@@ -90453,7 +90503,7 @@ function parseServerMessage(data) {
90453
90503
  try {
90454
90504
  const raw = typeof data === "string" ? data : data.toString();
90455
90505
  const parsed = JSON.parse(raw);
90456
- if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelAccountsListCommand(parsed) || isChannelAccountCreateCommand(parsed) || isChannelAccountUpdateCommand(parsed) || isChannelAccountBindCommand(parsed) || isChannelAccountUnbindCommand(parsed) || isChannelAccountDeleteCommand(parsed) || isChannelAccountStartCommand(parsed) || isChannelAccountStopCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelTargetsListCommand(parsed) || isChannelTargetBindCommand(parsed) || isChannelRouteUpdateCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
90506
+ if (isInputCommand(parsed) || isChangeDeviceStateCommand(parsed) || isAbortMessageCommand(parsed) || isSyncCommand(parsed) || isTerminalSpawnCommand(parsed) || isTerminalInputCommand(parsed) || isTerminalResizeCommand(parsed) || isTerminalKillCommand(parsed) || isSearchFilesCommand(parsed) || isListInDirectoryCommand(parsed) || isReadFileCommand(parsed) || isWriteFileCommand(parsed) || isWatchFileCommand(parsed) || isUnwatchFileCommand(parsed) || isEditFileCommand(parsed) || isFileOpsCommand(parsed) || isListMemoryCommand(parsed) || isMemoryHistoryCommand(parsed) || isMemoryFileAtRefCommand(parsed) || isEnableMemfsCommand(parsed) || isListModelsCommand(parsed) || isUpdateModelCommand(parsed) || isCronListCommand(parsed) || isCronAddCommand(parsed) || isCronGetCommand(parsed) || isCronDeleteCommand(parsed) || isCronDeleteAllCommand(parsed) || isSkillEnableCommand(parsed) || isSkillDisableCommand(parsed) || isCreateAgentCommand(parsed) || isGetReflectionSettingsCommand(parsed) || isSetReflectionSettingsCommand(parsed) || isChannelsListCommand(parsed) || isChannelAccountsListCommand(parsed) || isChannelAccountCreateCommand(parsed) || isChannelAccountUpdateCommand(parsed) || isChannelAccountBindCommand(parsed) || isChannelAccountUnbindCommand(parsed) || isChannelAccountDeleteCommand(parsed) || isChannelAccountStartCommand(parsed) || isChannelAccountStopCommand(parsed) || isChannelGetConfigCommand(parsed) || isChannelSetConfigCommand(parsed) || isChannelStartCommand(parsed) || isChannelStopCommand(parsed) || isChannelPairingsListCommand(parsed) || isChannelPairingBindCommand(parsed) || isChannelRoutesListCommand(parsed) || isChannelTargetsListCommand(parsed) || isChannelTargetBindCommand(parsed) || isChannelRouteUpdateCommand(parsed) || isChannelRouteRemoveCommand(parsed) || isExecuteCommandCommand(parsed) || isSearchBranchesCommand(parsed) || isCheckoutBranchCommand(parsed)) {
90457
90507
  return parsed;
90458
90508
  }
90459
90509
  const invalidInput = getInvalidInputReason(parsed);
@@ -90474,6 +90524,135 @@ var init_protocol_inbound = __esm(async () => {
90474
90524
  await init_approval();
90475
90525
  });
90476
90526
 
90527
+ // src/websocket/listener/worktree-watcher.ts
90528
+ import { readdir as readdir6, stat as stat5, watch } from "node:fs/promises";
90529
+ import path22 from "node:path";
90530
+ function startWorktreeWatcher(params) {
90531
+ const { runtime, agentId, conversationId } = params;
90532
+ const cwd2 = getConversationWorkingDirectory(runtime, agentId, conversationId);
90533
+ const worktreesDir = path22.join(cwd2, WORKTREES_DIR);
90534
+ const abort = new AbortController;
90535
+ const state = { abort, watchedDir: worktreesDir };
90536
+ runWatchLoop({
90537
+ worktreesDir,
90538
+ abort,
90539
+ runtime,
90540
+ agentId,
90541
+ conversationId
90542
+ }).catch((err) => {
90543
+ if (err.name === "AbortError")
90544
+ return;
90545
+ console.error("[WorktreeWatcher] watch loop error:", err);
90546
+ });
90547
+ return state;
90548
+ }
90549
+ function stopWorktreeWatcher(state) {
90550
+ state.abort.abort();
90551
+ }
90552
+ function stopAllWorktreeWatchers(runtime) {
90553
+ for (const watcher of runtime.worktreeWatcherByConversation.values()) {
90554
+ stopWorktreeWatcher(watcher);
90555
+ }
90556
+ runtime.worktreeWatcherByConversation.clear();
90557
+ }
90558
+ function restartWorktreeWatcher(params) {
90559
+ const { runtime, agentId, conversationId } = params;
90560
+ const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
90561
+ const existing = runtime.worktreeWatcherByConversation.get(scopeKey);
90562
+ if (existing) {
90563
+ stopWorktreeWatcher(existing);
90564
+ runtime.worktreeWatcherByConversation.delete(scopeKey);
90565
+ }
90566
+ const state = startWorktreeWatcher(params);
90567
+ if (state) {
90568
+ runtime.worktreeWatcherByConversation.set(scopeKey, state);
90569
+ }
90570
+ }
90571
+ async function runWatchLoop(params) {
90572
+ const { worktreesDir, abort, runtime, agentId, conversationId } = params;
90573
+ const dirExists = await directoryExists(worktreesDir);
90574
+ if (!dirExists) {
90575
+ const lettaDir = path22.dirname(worktreesDir);
90576
+ const lettaDirExists = await directoryExists(lettaDir);
90577
+ if (!lettaDirExists) {
90578
+ return;
90579
+ }
90580
+ await waitForDirectoryCreation(lettaDir, "worktrees", abort.signal);
90581
+ }
90582
+ const existingEntries = new Set(await safeReaddir(worktreesDir));
90583
+ let debounceTimer = null;
90584
+ const watcher = watch(worktreesDir, { signal: abort.signal });
90585
+ for await (const event of watcher) {
90586
+ if (event.eventType !== "rename" || !event.filename)
90587
+ continue;
90588
+ if (existingEntries.has(event.filename))
90589
+ continue;
90590
+ if (debounceTimer)
90591
+ clearTimeout(debounceTimer);
90592
+ const filename = event.filename;
90593
+ debounceTimer = setTimeout(() => {
90594
+ handleNewWorktree({
90595
+ worktreesDir,
90596
+ filename,
90597
+ runtime,
90598
+ agentId,
90599
+ conversationId
90600
+ });
90601
+ }, DEBOUNCE_MS);
90602
+ }
90603
+ }
90604
+ async function handleNewWorktree(params) {
90605
+ const { worktreesDir, filename, runtime, agentId, conversationId } = params;
90606
+ const newWorktreePath = path22.join(worktreesDir, filename);
90607
+ if (!await directoryExists(newWorktreePath))
90608
+ return;
90609
+ const currentCwd = getConversationWorkingDirectory(runtime, agentId, conversationId);
90610
+ if (currentCwd === newWorktreePath)
90611
+ return;
90612
+ console.log(`[WorktreeWatcher] New worktree detected: ${newWorktreePath} — switching CWD`);
90613
+ setConversationWorkingDirectory(runtime, agentId, conversationId, newWorktreePath);
90614
+ const scopeKey = getWorkingDirectoryScopeKey(agentId, conversationId);
90615
+ const reminderState = runtime.reminderStateByConversation.get(scopeKey);
90616
+ if (reminderState) {
90617
+ reminderState.hasSentSessionContext = false;
90618
+ reminderState.pendingSessionContextReason = "cwd_changed";
90619
+ }
90620
+ if (runtime.socket) {
90621
+ emitDeviceStatusUpdate(runtime.socket, runtime, {
90622
+ agent_id: agentId,
90623
+ conversation_id: conversationId
90624
+ });
90625
+ }
90626
+ }
90627
+ async function waitForDirectoryCreation(parentDir, targetName, signal) {
90628
+ const watcher = watch(parentDir, { signal });
90629
+ for await (const event of watcher) {
90630
+ if (event.eventType === "rename" && event.filename === targetName && await directoryExists(path22.join(parentDir, targetName))) {
90631
+ return;
90632
+ }
90633
+ }
90634
+ }
90635
+ async function directoryExists(dir) {
90636
+ try {
90637
+ const stats = await stat5(dir);
90638
+ return stats.isDirectory();
90639
+ } catch {
90640
+ return false;
90641
+ }
90642
+ }
90643
+ async function safeReaddir(dir) {
90644
+ try {
90645
+ return await readdir6(dir);
90646
+ } catch {
90647
+ return [];
90648
+ }
90649
+ }
90650
+ var WORKTREES_DIR = ".letta/worktrees", DEBOUNCE_MS = 500;
90651
+ var init_worktree_watcher = __esm(async () => {
90652
+ init_cwd();
90653
+ await init_protocol_outbound();
90654
+ });
90655
+
90477
90656
  // src/agent/memoryScanner.ts
90478
90657
  var exports_memoryScanner = {};
90479
90658
  __export(exports_memoryScanner, {
@@ -90555,10 +90734,10 @@ var init_memoryScanner = () => {};
90555
90734
 
90556
90735
  // src/websocket/listener/client.ts
90557
90736
  import { execFile as execFile13 } from "node:child_process";
90558
- import { realpath as realpath3, stat as stat5 } from "node:fs/promises";
90559
- import path22 from "node:path";
90737
+ import { realpath as realpath3, stat as stat6 } from "node:fs/promises";
90738
+ import path23 from "node:path";
90560
90739
  import { promisify as promisify13 } from "node:util";
90561
- import WebSocket4 from "ws";
90740
+ import WebSocket5 from "ws";
90562
90741
  async function loadChannelsService() {
90563
90742
  if (channelsServiceLoaderOverride) {
90564
90743
  return channelsServiceLoaderOverride();
@@ -90573,7 +90752,7 @@ function trackListenerError(errorType, error, context3) {
90573
90752
  });
90574
90753
  }
90575
90754
  function safeSocketSend(socket, payload, errorType, context3) {
90576
- if (socket.readyState !== WebSocket4.OPEN) {
90755
+ if (socket.readyState !== WebSocket5.OPEN) {
90577
90756
  return false;
90578
90757
  }
90579
90758
  try {
@@ -91760,8 +91939,8 @@ async function handleSkillCommand(parsed, socket) {
91760
91939
  const linkPath = join31(globalSkillsDir, linkName);
91761
91940
  mkdirSync19(globalSkillsDir, { recursive: true });
91762
91941
  if (existsSync26(linkPath)) {
91763
- const stat6 = lstatSync2(linkPath);
91764
- if (stat6.isSymbolicLink()) {
91942
+ const stat7 = lstatSync2(linkPath);
91943
+ if (stat7.isSymbolicLink()) {
91765
91944
  if (process.platform === "win32") {
91766
91945
  rmdirSync(linkPath);
91767
91946
  } else {
@@ -91810,8 +91989,8 @@ async function handleSkillCommand(parsed, socket) {
91810
91989
  }, "listener_skill_send_failed", "listener_skill_command");
91811
91990
  return true;
91812
91991
  }
91813
- const stat6 = lstatSync2(linkPath);
91814
- if (!stat6.isSymbolicLink()) {
91992
+ const stat7 = lstatSync2(linkPath);
91993
+ if (!stat7.isSymbolicLink()) {
91815
91994
  safeSocketSend(socket, {
91816
91995
  type: "skill_disable_response",
91817
91996
  request_id: parsed.request_id,
@@ -92263,9 +92442,9 @@ async function handleCwdChange(msg, socket, runtime) {
92263
92442
  if (!requestedPath) {
92264
92443
  throw new Error("Working directory cannot be empty");
92265
92444
  }
92266
- const resolvedPath = path22.isAbsolute(requestedPath) ? requestedPath : path22.resolve(currentWorkingDirectory, requestedPath);
92445
+ const resolvedPath = path23.isAbsolute(requestedPath) ? requestedPath : path23.resolve(currentWorkingDirectory, requestedPath);
92267
92446
  const normalizedPath = await realpath3(resolvedPath);
92268
- const stats = await stat5(normalizedPath);
92447
+ const stats = await stat6(normalizedPath);
92269
92448
  if (!stats.isDirectory()) {
92270
92449
  throw new Error(`Not a directory: ${normalizedPath}`);
92271
92450
  }
@@ -92276,10 +92455,16 @@ async function handleCwdChange(msg, socket, runtime) {
92276
92455
  if (!normalizedPath.startsWith(currentRoot)) {
92277
92456
  setIndexRoot(normalizedPath);
92278
92457
  }
92458
+ ensureFileIndex2();
92279
92459
  emitDeviceStatusUpdate(socket, runtime, {
92280
92460
  agent_id: agentId,
92281
92461
  conversation_id: conversationId
92282
92462
  });
92463
+ restartWorktreeWatcher({
92464
+ runtime: runtime.listener,
92465
+ agentId,
92466
+ conversationId
92467
+ });
92283
92468
  } catch (error) {
92284
92469
  emitLoopErrorNotice(socket, runtime, {
92285
92470
  message: error instanceof Error ? error.message : "Working directory change failed",
@@ -92309,6 +92494,7 @@ function createRuntime() {
92309
92494
  reminderState: createSharedReminderState(),
92310
92495
  bootWorkingDirectory,
92311
92496
  workingDirectoryByConversation: loadPersistedCwdMap(),
92497
+ worktreeWatcherByConversation: new Map,
92312
92498
  permissionModeByConversation: loadPersistedPermissionModeMap(),
92313
92499
  reminderStateByConversation: new Map,
92314
92500
  contextTrackerByConversation: new Map,
@@ -92340,6 +92526,7 @@ function stopRuntime(runtime, suppressCallbacks) {
92340
92526
  runtime.contextTrackerByConversation.clear();
92341
92527
  runtime.systemPromptRecompileByConversation.clear();
92342
92528
  runtime.queuedSystemPromptRecompileByConversation.clear();
92529
+ stopAllWorktreeWatchers(runtime);
92343
92530
  if (!runtime.socket) {
92344
92531
  return;
92345
92532
  }
@@ -92348,7 +92535,7 @@ function stopRuntime(runtime, suppressCallbacks) {
92348
92535
  if (suppressCallbacks) {
92349
92536
  socket.removeAllListeners();
92350
92537
  }
92351
- if (socket.readyState === WebSocket4.OPEN || socket.readyState === WebSocket4.CONNECTING) {
92538
+ if (socket.readyState === WebSocket5.OPEN || socket.readyState === WebSocket5.CONNECTING) {
92352
92539
  socket.close();
92353
92540
  }
92354
92541
  }
@@ -92383,8 +92570,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92383
92570
  const delay = Math.min(INITIAL_RETRY_DELAY_MS * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
92384
92571
  const maxAttempts = Math.ceil(Math.log2(MAX_RETRY_DURATION_MS / INITIAL_RETRY_DELAY_MS));
92385
92572
  opts.onRetrying?.(attempt, maxAttempts, delay, opts.connectionId);
92386
- await new Promise((resolve24) => {
92387
- runtime.reconnectTimeout = setTimeout(resolve24, delay);
92573
+ await new Promise((resolve25) => {
92574
+ runtime.reconnectTimeout = setTimeout(resolve25, delay);
92388
92575
  });
92389
92576
  runtime.reconnectTimeout = null;
92390
92577
  if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
@@ -92403,7 +92590,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92403
92590
  const url = new URL(opts.wsUrl);
92404
92591
  url.searchParams.set("deviceId", opts.deviceId);
92405
92592
  url.searchParams.set("connectionName", opts.connectionName);
92406
- const socket = new WebSocket4(url.toString(), {
92593
+ const socket = new WebSocket5(url.toString(), {
92407
92594
  headers: {
92408
92595
  Authorization: `Bearer ${apiKey}`
92409
92596
  }
@@ -92457,7 +92644,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92457
92644
  });
92458
92645
  runtime._unsubscribeSubagentStreamEvents?.();
92459
92646
  runtime._unsubscribeSubagentStreamEvents = subscribeToStreamEvents((subagentId, event) => {
92460
- if (socket.readyState !== WebSocket4.OPEN)
92647
+ if (socket.readyState !== WebSocket5.OPEN)
92461
92648
  return;
92462
92649
  const subagent = getSubagents().find((entry) => entry.id === subagentId);
92463
92650
  if (subagent?.silent === true) {
@@ -92483,7 +92670,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92483
92670
  scheduleQueuePump(targetRuntime, socket, opts, processQueuedTurn);
92484
92671
  });
92485
92672
  runtime.heartbeatInterval = setInterval(() => {
92486
- if (socket.readyState === WebSocket4.OPEN) {
92673
+ if (socket.readyState === WebSocket5.OPEN) {
92487
92674
  safeSocketSend(socket, { type: "ping" }, "listener_ping_send_failed", "listener_heartbeat");
92488
92675
  }
92489
92676
  }, 30000);
@@ -92644,14 +92831,14 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92644
92831
  try {
92645
92832
  if (parsed.cwd) {
92646
92833
  const currentRoot = getIndexRoot();
92647
- if (!parsed.cwd.startsWith(currentRoot + path22.sep) && parsed.cwd !== currentRoot) {
92834
+ if (!parsed.cwd.startsWith(currentRoot + path23.sep) && parsed.cwd !== currentRoot) {
92648
92835
  setIndexRoot(parsed.cwd);
92649
92836
  }
92650
92837
  }
92651
92838
  await ensureFileIndex2();
92652
92839
  let searchDir = ".";
92653
92840
  if (parsed.cwd) {
92654
- const rel = path22.relative(getIndexRoot(), parsed.cwd);
92841
+ const rel = path23.relative(getIndexRoot(), parsed.cwd);
92655
92842
  if (rel && !rel.startsWith("..") && rel !== "") {
92656
92843
  searchDir = rel;
92657
92844
  }
@@ -92685,9 +92872,9 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92685
92872
  console.log(`[Listen] Received list_in_directory command: path=${parsed.path}`);
92686
92873
  runDetachedListenerTask("list_in_directory", async () => {
92687
92874
  try {
92688
- const { readdir: readdir6 } = await import("node:fs/promises");
92875
+ const { readdir: readdir7 } = await import("node:fs/promises");
92689
92876
  console.log(`[Listen] Reading directory: ${parsed.path}`);
92690
- const entries = await readdir6(parsed.path, { withFileTypes: true });
92877
+ const entries = await readdir7(parsed.path, { withFileTypes: true });
92691
92878
  console.log(`[Listen] Directory read success, ${entries.length} entries`);
92692
92879
  const IGNORED_NAMES = new Set([
92693
92880
  ".DS_Store",
@@ -92746,8 +92933,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92746
92933
  console.log(`[Listen] Received read_file command: path=${parsed.path}, request_id=${parsed.request_id}`);
92747
92934
  runDetachedListenerTask("read_file", async () => {
92748
92935
  try {
92749
- const { readFile: readFile10 } = await import("node:fs/promises");
92750
- const content = await readFile10(parsed.path, "utf-8");
92936
+ const { readFile: readFile11 } = await import("node:fs/promises");
92937
+ const content = await readFile11(parsed.path, "utf-8");
92751
92938
  console.log(`[Listen] read_file success: ${parsed.path} (${content.length} bytes)`);
92752
92939
  safeSocketSend(socket, {
92753
92940
  type: "read_file_response",
@@ -92777,10 +92964,10 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92777
92964
  try {
92778
92965
  const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
92779
92966
  const { write: write2 } = await Promise.resolve().then(() => (init_Write2(), exports_Write));
92780
- const { readFile: readFile10 } = await import("node:fs/promises");
92967
+ const { readFile: readFile11 } = await import("node:fs/promises");
92781
92968
  let currentContent = null;
92782
92969
  try {
92783
- currentContent = await readFile10(parsed.path, "utf-8");
92970
+ currentContent = await readFile11(parsed.path, "utf-8");
92784
92971
  } catch (readErr) {
92785
92972
  const e = readErr;
92786
92973
  if (e.code !== "ENOENT")
@@ -92829,11 +93016,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92829
93016
  return;
92830
93017
  }
92831
93018
  try {
92832
- const { watch } = await import("node:fs");
92833
- const { stat: stat6 } = await import("node:fs/promises");
93019
+ const { watch: watch2 } = await import("node:fs");
93020
+ const { stat: stat7 } = await import("node:fs/promises");
92834
93021
  if (cancelledWatches.delete(parsed.path))
92835
93022
  return;
92836
- const watcher = watch(parsed.path, { persistent: false }, (eventType) => {
93023
+ const watcher = watch2(parsed.path, { persistent: false }, (eventType) => {
92837
93024
  if (eventType !== "change" && eventType !== "rename")
92838
93025
  return;
92839
93026
  const existing2 = watchDebounceTimers.get(parsed.path);
@@ -92841,7 +93028,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92841
93028
  clearTimeout(existing2);
92842
93029
  watchDebounceTimers.set(parsed.path, setTimeout(() => {
92843
93030
  watchDebounceTimers.delete(parsed.path);
92844
- stat6(parsed.path).then((s) => {
93031
+ stat7(parsed.path).then((s) => {
92845
93032
  safeSocketSend(socket, {
92846
93033
  type: "file_changed",
92847
93034
  path: parsed.path,
@@ -92887,6 +93074,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92887
93074
  console.log(`[Listen] Received edit_file command: file_path=${parsed.file_path}, request_id=${parsed.request_id}`);
92888
93075
  runDetachedListenerTask("edit_file", async () => {
92889
93076
  try {
93077
+ const { readFile: readFile11 } = await import("node:fs/promises");
92890
93078
  const { edit: edit2 } = await Promise.resolve().then(() => (init_Edit2(), exports_Edit));
92891
93079
  console.log(`[Listen] Executing edit: old_string="${parsed.old_string.slice(0, 50)}${parsed.old_string.length > 50 ? "..." : ""}"`);
92892
93080
  const result = await edit2({
@@ -92897,6 +93085,19 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92897
93085
  expected_replacements: parsed.expected_replacements
92898
93086
  });
92899
93087
  console.log(`[Listen] edit_file success: ${result.replacements} replacement(s) at line ${result.startLine}`);
93088
+ if (result.replacements > 0) {
93089
+ try {
93090
+ const contentAfter = await readFile11(parsed.file_path, "utf-8");
93091
+ safeSocketSend(socket, {
93092
+ type: "file_ops",
93093
+ path: parsed.file_path,
93094
+ cg_entries: [],
93095
+ ops: [],
93096
+ source: "agent",
93097
+ document_content: contentAfter
93098
+ }, "listener_edit_file_ops_send_failed", "listener_edit_file");
93099
+ } catch {}
93100
+ }
92900
93101
  safeSocketSend(socket, {
92901
93102
  type: "edit_file_response",
92902
93103
  request_id: parsed.request_id,
@@ -92922,6 +93123,21 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
92922
93123
  });
92923
93124
  return;
92924
93125
  }
93126
+ if (isFileOpsCommand(parsed)) {
93127
+ if (parsed.document_content !== undefined) {
93128
+ runDetachedListenerTask("file_ops", async () => {
93129
+ try {
93130
+ const { writeFile: writeFile9 } = await import("node:fs/promises");
93131
+ const content = parsed.document_content;
93132
+ await writeFile9(parsed.path, content, "utf-8");
93133
+ console.log(`[Listen] file_ops: wrote ${content.length} bytes to ${parsed.path}`);
93134
+ } catch (err) {
93135
+ console.error(`[Listen] file_ops error: ${err instanceof Error ? err.message : "Unknown error"}`);
93136
+ }
93137
+ });
93138
+ }
93139
+ return;
93140
+ }
92925
93141
  if (isListMemoryCommand(parsed)) {
92926
93142
  runDetachedListenerTask("list_memory", async () => {
92927
93143
  try {
@@ -93606,6 +93822,12 @@ function createLegacyTestRuntime() {
93606
93822
  listener.memfsSyncedAgents = value;
93607
93823
  }
93608
93824
  },
93825
+ worktreeWatcherByConversation: {
93826
+ get: () => listener.worktreeWatcherByConversation,
93827
+ set: (value) => {
93828
+ listener.worktreeWatcherByConversation = value;
93829
+ }
93830
+ },
93609
93831
  lastEmittedStatus: {
93610
93832
  get: () => listener.lastEmittedStatus,
93611
93833
  set: (value) => {
@@ -93675,6 +93897,7 @@ var init_client4 = __esm(async () => {
93675
93897
  init_recovery(),
93676
93898
  init_send(),
93677
93899
  init_turn(),
93900
+ init_worktree_watcher(),
93678
93901
  init_approval(),
93679
93902
  init_protocol_inbound(),
93680
93903
  init_protocol_outbound()
@@ -93788,8 +94011,8 @@ function isDebugEnabled2() {
93788
94011
  return lettaDebug === "1" || lettaDebug === "true" || legacyDebug === "1" || legacyDebug === "true";
93789
94012
  }
93790
94013
  function getDebugFile2() {
93791
- const path23 = process.env.LETTA_DEBUG_FILE;
93792
- return path23 && path23.trim().length > 0 ? path23 : null;
94014
+ const path24 = process.env.LETTA_DEBUG_FILE;
94015
+ return path24 && path24.trim().length > 0 ? path24 : null;
93793
94016
  }
93794
94017
  function printDebugLine2(line, level = "log") {
93795
94018
  const debugFile = getDebugFile2();
@@ -93913,7 +94136,7 @@ __export(exports_skills2, {
93913
94136
  GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
93914
94137
  });
93915
94138
  import { existsSync as existsSync28 } from "node:fs";
93916
- import { readdir as readdir7, readFile as readFile10, realpath as realpath4, stat as stat6 } from "node:fs/promises";
94139
+ import { readdir as readdir8, readFile as readFile11, realpath as realpath4, stat as stat7 } from "node:fs/promises";
93917
94140
  import { dirname as dirname13, join as join35 } from "node:path";
93918
94141
  import { fileURLToPath as fileURLToPath8 } from "node:url";
93919
94142
  function getBundledSkillsPath2() {
@@ -94003,14 +94226,14 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
94003
94226
  return;
94004
94227
  }
94005
94228
  try {
94006
- const entries = await readdir7(currentPath, { withFileTypes: true });
94229
+ const entries = await readdir8(currentPath, { withFileTypes: true });
94007
94230
  for (const entry of entries) {
94008
94231
  const fullPath = join35(currentPath, entry.name);
94009
94232
  try {
94010
94233
  let isDirectory = entry.isDirectory();
94011
94234
  let isFile = entry.isFile();
94012
94235
  if (entry.isSymbolicLink()) {
94013
- const entryStat = await stat6(fullPath);
94236
+ const entryStat = await stat7(fullPath);
94014
94237
  isDirectory = entryStat.isDirectory();
94015
94238
  isFile = entryStat.isFile();
94016
94239
  }
@@ -94044,7 +94267,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source, vi
94044
94267
  }
94045
94268
  }
94046
94269
  async function parseSkillFile2(filePath, rootPath, source) {
94047
- const content = await readFile10(filePath, "utf-8");
94270
+ const content = await readFile11(filePath, "utf-8");
94048
94271
  const { frontmatter, body } = parseFrontmatter(content);
94049
94272
  const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
94050
94273
  const relativePath = filePath.slice(normalizedRoot.length + 1);
@@ -94103,7 +94326,7 @@ __export(exports_fs, {
94103
94326
  writeJsonFile: () => writeJsonFile,
94104
94327
  writeFile: () => writeFile10,
94105
94328
  readJsonFile: () => readJsonFile,
94106
- readFile: () => readFile11,
94329
+ readFile: () => readFile12,
94107
94330
  mkdir: () => mkdir9,
94108
94331
  exists: () => exists2
94109
94332
  });
@@ -94114,31 +94337,31 @@ import {
94114
94337
  mkdirSync as mkdirSync21
94115
94338
  } from "node:fs";
94116
94339
  import { dirname as dirname14 } from "node:path";
94117
- async function readFile11(path23) {
94118
- return fsReadFileSync2(path23, { encoding: "utf-8" });
94340
+ async function readFile12(path24) {
94341
+ return fsReadFileSync2(path24, { encoding: "utf-8" });
94119
94342
  }
94120
- async function writeFile10(path23, content) {
94121
- const dir = dirname14(path23);
94343
+ async function writeFile10(path24, content) {
94344
+ const dir = dirname14(path24);
94122
94345
  if (!existsSync29(dir)) {
94123
94346
  mkdirSync21(dir, { recursive: true });
94124
94347
  }
94125
- fsWriteFileSync2(path23, content, { encoding: "utf-8", flush: true });
94348
+ fsWriteFileSync2(path24, content, { encoding: "utf-8", flush: true });
94126
94349
  }
94127
- function exists2(path23) {
94128
- return existsSync29(path23);
94350
+ function exists2(path24) {
94351
+ return existsSync29(path24);
94129
94352
  }
94130
- async function mkdir9(path23, options) {
94131
- mkdirSync21(path23, options);
94353
+ async function mkdir9(path24, options) {
94354
+ mkdirSync21(path24, options);
94132
94355
  }
94133
- async function readJsonFile(path23) {
94134
- const text = await readFile11(path23);
94356
+ async function readJsonFile(path24) {
94357
+ const text = await readFile12(path24);
94135
94358
  return JSON.parse(text);
94136
94359
  }
94137
- async function writeJsonFile(path23, data, options) {
94360
+ async function writeJsonFile(path24, data, options) {
94138
94361
  const indent = options?.indent ?? 2;
94139
94362
  const content = `${JSON.stringify(data, null, indent)}
94140
94363
  `;
94141
- await writeFile10(path23, content);
94364
+ await writeFile10(path24, content);
94142
94365
  }
94143
94366
  var init_fs2 = () => {};
94144
94367
 
@@ -94163,7 +94386,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
94163
94386
  }
94164
94387
  const wasRaw = process.stdin.isRaw;
94165
94388
  const wasFlowing = process.stdin.readableFlowing;
94166
- return new Promise((resolve26) => {
94389
+ return new Promise((resolve27) => {
94167
94390
  let response = "";
94168
94391
  let resolved = false;
94169
94392
  const cleanup = () => {
@@ -94180,7 +94403,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
94180
94403
  };
94181
94404
  const timeout = setTimeout(() => {
94182
94405
  cleanup();
94183
- resolve26(null);
94406
+ resolve27(null);
94184
94407
  }, timeoutMs);
94185
94408
  const onData = (data) => {
94186
94409
  response += data.toString();
@@ -94190,7 +94413,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
94190
94413
  if (match3) {
94191
94414
  clearTimeout(timeout);
94192
94415
  cleanup();
94193
- resolve26({
94416
+ resolve27({
94194
94417
  r: parseHexComponent(match3[1] ?? "0"),
94195
94418
  g: parseHexComponent(match3[2] ?? "0"),
94196
94419
  b: parseHexComponent(match3[3] ?? "0")
@@ -94205,7 +94428,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
94205
94428
  } catch {
94206
94429
  clearTimeout(timeout);
94207
94430
  cleanup();
94208
- resolve26(null);
94431
+ resolve27(null);
94209
94432
  }
94210
94433
  });
94211
94434
  }
@@ -94291,7 +94514,7 @@ __export(exports_manager2, {
94291
94514
  lspManager: () => lspManager2,
94292
94515
  LSPManager: () => LSPManager2
94293
94516
  });
94294
- import * as path23 from "node:path";
94517
+ import * as path24 from "node:path";
94295
94518
 
94296
94519
  class LSPManager2 {
94297
94520
  static instance = null;
@@ -94319,7 +94542,7 @@ class LSPManager2 {
94319
94542
  async getOrStartServer(filePath) {
94320
94543
  if (!this.enabled)
94321
94544
  return null;
94322
- const ext3 = path23.extname(filePath).toLowerCase();
94545
+ const ext3 = path24.extname(filePath).toLowerCase();
94323
94546
  const serverDef = this.serverDefinitions.find((s) => s.extensions.includes(ext3));
94324
94547
  if (!serverDef) {
94325
94548
  return null;
@@ -94387,7 +94610,7 @@ class LSPManager2 {
94387
94610
  const client = await this.getOrStartServer(filePath);
94388
94611
  if (!client)
94389
94612
  return;
94390
- const absolutePath = path23.isAbsolute(filePath) ? filePath : path23.resolve(process.cwd(), filePath);
94613
+ const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
94391
94614
  const uri = `file://${absolutePath}`;
94392
94615
  const existing = this.openDocuments.get(absolutePath);
94393
94616
  if (!existing) {
@@ -94415,7 +94638,7 @@ class LSPManager2 {
94415
94638
  if (!this.enabled)
94416
94639
  return [];
94417
94640
  if (filePath) {
94418
- const absolutePath = path23.isAbsolute(filePath) ? filePath : path23.resolve(process.cwd(), filePath);
94641
+ const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(process.cwd(), filePath);
94419
94642
  return this.diagnostics.get(absolutePath) || [];
94420
94643
  }
94421
94644
  const all = [];
@@ -94425,7 +94648,7 @@ class LSPManager2 {
94425
94648
  return all;
94426
94649
  }
94427
94650
  getLanguageId(filePath) {
94428
- const ext3 = path23.extname(filePath).toLowerCase();
94651
+ const ext3 = path24.extname(filePath).toLowerCase();
94429
94652
  const languageMap = {
94430
94653
  ".ts": "typescript",
94431
94654
  ".tsx": "typescriptreact",
@@ -94476,7 +94699,7 @@ __export(exports_auto_update, {
94476
94699
  });
94477
94700
  import { execFile as execFile14 } from "node:child_process";
94478
94701
  import { realpathSync as realpathSync3 } from "node:fs";
94479
- import { readdir as readdir8, rm as rm3 } from "node:fs/promises";
94702
+ import { readdir as readdir9, rm as rm3 } from "node:fs/promises";
94480
94703
  import { join as join37 } from "node:path";
94481
94704
  import { promisify as promisify14 } from "node:util";
94482
94705
  function debugLog4(...args) {
@@ -94644,7 +94867,7 @@ async function getNpmGlobalPath() {
94644
94867
  async function cleanupOrphanedDirs(globalPath) {
94645
94868
  const lettaAiDir = join37(globalPath, "lib/node_modules/@letta-ai");
94646
94869
  try {
94647
- const entries = await readdir8(lettaAiDir);
94870
+ const entries = await readdir9(lettaAiDir);
94648
94871
  for (const entry of entries) {
94649
94872
  if (entry.startsWith(".letta-code-")) {
94650
94873
  const orphanPath = join37(lettaAiDir, entry);
@@ -94895,13 +95118,13 @@ __export(exports_overflow, {
94895
95118
  import { randomUUID as randomUUID10 } from "node:crypto";
94896
95119
  import * as fs15 from "node:fs";
94897
95120
  import * as os5 from "node:os";
94898
- import * as path24 from "node:path";
95121
+ import * as path25 from "node:path";
94899
95122
  function getOverflowDirectory2(workingDirectory) {
94900
95123
  const homeDir = os5.homedir();
94901
- const lettaDir = path24.join(homeDir, ".letta");
94902
- const normalizedPath = path24.normalize(workingDirectory);
95124
+ const lettaDir = path25.join(homeDir, ".letta");
95125
+ const normalizedPath = path25.normalize(workingDirectory);
94903
95126
  const sanitizedPath = normalizedPath.replace(/^[/\\]/, "").replace(/[/\\:]/g, "_").replace(/\s+/g, "_");
94904
- const overflowDir = path24.join(lettaDir, "projects", sanitizedPath, "agent-tools");
95127
+ const overflowDir = path25.join(lettaDir, "projects", sanitizedPath, "agent-tools");
94905
95128
  return overflowDir;
94906
95129
  }
94907
95130
  function ensureOverflowDirectory2(workingDirectory) {
@@ -94915,7 +95138,7 @@ function writeOverflowFile2(content, workingDirectory, toolName) {
94915
95138
  const overflowDir = ensureOverflowDirectory2(workingDirectory);
94916
95139
  const uuid = randomUUID10();
94917
95140
  const filename = toolName ? `${toolName.toLowerCase()}-${uuid}.txt` : `${uuid}.txt`;
94918
- const filePath = path24.join(overflowDir, filename);
95141
+ const filePath = path25.join(overflowDir, filename);
94919
95142
  fs15.writeFileSync(filePath, content, "utf-8");
94920
95143
  return filePath;
94921
95144
  }
@@ -94933,7 +95156,7 @@ function cleanupOldOverflowFiles(workingDirectory, maxAgeMs = 24 * 60 * 60 * 100
94933
95156
  const now = Date.now();
94934
95157
  let deletedCount = 0;
94935
95158
  for (const file of files) {
94936
- const filePath = path24.join(overflowDir, file);
95159
+ const filePath = path25.join(overflowDir, file);
94937
95160
  try {
94938
95161
  const stats = fs15.statSync(filePath);
94939
95162
  if (stats.isDirectory()) {
@@ -94960,7 +95183,7 @@ function getOverflowStats(workingDirectory) {
94960
95183
  const files = fs15.readdirSync(overflowDir);
94961
95184
  let totalSize = 0;
94962
95185
  for (const file of files) {
94963
- const filePath = path24.join(overflowDir, file);
95186
+ const filePath = path25.join(overflowDir, file);
94964
95187
  const stats = fs15.statSync(filePath);
94965
95188
  totalSize += stats.size;
94966
95189
  }
@@ -95438,10 +95661,10 @@ __export(exports_setup, {
95438
95661
  runSetup: () => runSetup
95439
95662
  });
95440
95663
  async function runSetup() {
95441
- return new Promise((resolve27) => {
95664
+ return new Promise((resolve28) => {
95442
95665
  const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
95443
95666
  onComplete: () => {
95444
- resolve27();
95667
+ resolve28();
95445
95668
  }
95446
95669
  }));
95447
95670
  waitUntilExit().catch((error) => {
@@ -95936,8 +96159,8 @@ __export(exports_github_utils, {
95936
96159
  parseDirNames: () => parseDirNames,
95937
96160
  fetchGitHubContents: () => fetchGitHubContents
95938
96161
  });
95939
- async function fetchGitHubContents(owner, repo, branch, path25) {
95940
- const apiPath = path25 ? `repos/${owner}/${repo}/contents/${path25}?ref=${branch}` : `repos/${owner}/${repo}/contents?ref=${branch}`;
96162
+ async function fetchGitHubContents(owner, repo, branch, path26) {
96163
+ const apiPath = path26 ? `repos/${owner}/${repo}/contents/${path26}?ref=${branch}` : `repos/${owner}/${repo}/contents?ref=${branch}`;
95941
96164
  try {
95942
96165
  const { execSync: execSync2 } = await import("node:child_process");
95943
96166
  const result = execSync2(`gh api ${apiPath}`, {
@@ -95946,7 +96169,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
95946
96169
  });
95947
96170
  return JSON.parse(result);
95948
96171
  } catch {}
95949
- const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path25}?ref=${branch}`;
96172
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path26}?ref=${branch}`;
95950
96173
  const response = await fetch(url, {
95951
96174
  headers: {
95952
96175
  Accept: "application/vnd.github.v3+json",
@@ -95954,7 +96177,7 @@ async function fetchGitHubContents(owner, repo, branch, path25) {
95954
96177
  }
95955
96178
  });
95956
96179
  if (!response.ok) {
95957
- throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${path25}: ${response.statusText}`);
96180
+ throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${path26}: ${response.statusText}`);
95958
96181
  }
95959
96182
  return await response.json();
95960
96183
  }
@@ -95970,11 +96193,11 @@ __export(exports_import, {
95970
96193
  extractSkillsFromAf: () => extractSkillsFromAf
95971
96194
  });
95972
96195
  import { createReadStream } from "node:fs";
95973
- import { chmod, mkdir as mkdir10, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
95974
- import { dirname as dirname15, resolve as resolve27 } from "node:path";
96196
+ import { chmod, mkdir as mkdir10, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
96197
+ import { dirname as dirname15, resolve as resolve28 } from "node:path";
95975
96198
  async function importAgentFromFile(options) {
95976
96199
  const client = await getClient();
95977
- const resolvedPath = resolve27(options.filePath);
96200
+ const resolvedPath = resolve28(options.filePath);
95978
96201
  const file = createReadStream(resolvedPath);
95979
96202
  const importResponse = await client.agents.importFile({
95980
96203
  file,
@@ -96003,13 +96226,13 @@ async function importAgentFromFile(options) {
96003
96226
  }
96004
96227
  async function extractSkillsFromAf(afPath, destDir) {
96005
96228
  const extracted = [];
96006
- const content = await readFile12(afPath, "utf-8");
96229
+ const content = await readFile13(afPath, "utf-8");
96007
96230
  const afData = JSON.parse(content);
96008
96231
  if (!afData.skills || !Array.isArray(afData.skills)) {
96009
96232
  return [];
96010
96233
  }
96011
96234
  for (const skill2 of afData.skills) {
96012
- const skillDir = resolve27(destDir, skill2.name);
96235
+ const skillDir = resolve28(destDir, skill2.name);
96013
96236
  await mkdir10(skillDir, { recursive: true });
96014
96237
  if (skill2.files) {
96015
96238
  await writeSkillFiles(skillDir, skill2.files);
@@ -96029,7 +96252,7 @@ async function writeSkillFiles(skillDir, files) {
96029
96252
  }
96030
96253
  }
96031
96254
  async function writeSkillFile(skillDir, filePath, content) {
96032
- const fullPath = resolve27(skillDir, filePath);
96255
+ const fullPath = resolve28(skillDir, filePath);
96033
96256
  await mkdir10(dirname15(fullPath), { recursive: true });
96034
96257
  await writeFile11(fullPath, content, "utf-8");
96035
96258
  const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
@@ -96048,13 +96271,13 @@ async function fetchSkillFromUrl(skillDir, sourceUrl) {
96048
96271
  const owner = parts[0];
96049
96272
  const repo = parts[1];
96050
96273
  const branch = parts[2];
96051
- const path25 = parts.slice(3).join("/");
96274
+ const path26 = parts.slice(3).join("/");
96052
96275
  const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
96053
- const entries = await fetchGitHubContents2(owner, repo, branch, path25);
96276
+ const entries = await fetchGitHubContents2(owner, repo, branch, path26);
96054
96277
  if (!Array.isArray(entries)) {
96055
96278
  throw new Error(`Expected directory at ${sourceUrl}, got file`);
96056
96279
  }
96057
- await downloadGitHubDirectory(entries, skillDir, owner, repo, branch, path25);
96280
+ await downloadGitHubDirectory(entries, skillDir, owner, repo, branch, path26);
96058
96281
  }
96059
96282
  async function downloadGitHubDirectory(entries, destDir, owner, repo, branch, basePath) {
96060
96283
  const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
@@ -96361,12 +96584,12 @@ async function prepareHeadlessToolExecutionContext(params) {
96361
96584
  };
96362
96585
  }
96363
96586
  async function flushAndExit(code) {
96364
- const flushWritable = (stream2) => new Promise((resolve28) => {
96587
+ const flushWritable = (stream2) => new Promise((resolve29) => {
96365
96588
  if (stream2.destroyed || stream2.writableEnded) {
96366
- resolve28();
96589
+ resolve29();
96367
96590
  return;
96368
96591
  }
96369
- stream2.write("", () => resolve28());
96592
+ stream2.write("", () => resolve29());
96370
96593
  });
96371
96594
  await Promise.allSettled([
96372
96595
  flushWritable(process.stdout),
@@ -97325,7 +97548,7 @@ ${loadedContents.join(`
97325
97548
  } else {
97326
97549
  console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
97327
97550
  }
97328
- await new Promise((resolve28) => setTimeout(resolve28, retryDelayMs));
97551
+ await new Promise((resolve29) => setTimeout(resolve29, retryDelayMs));
97329
97552
  continue;
97330
97553
  }
97331
97554
  }
@@ -97374,7 +97597,7 @@ ${loadedContents.join(`
97374
97597
  const delaySeconds = Math.round(delayMs / 1000);
97375
97598
  console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
97376
97599
  }
97377
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
97600
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
97378
97601
  conversationBusyRetries = 0;
97379
97602
  continue;
97380
97603
  }
@@ -97613,7 +97836,7 @@ ${loadedContents.join(`
97613
97836
  const delaySeconds = Math.round(delayMs / 1000);
97614
97837
  console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
97615
97838
  }
97616
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
97839
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
97617
97840
  refreshCurrentInputOtids();
97618
97841
  continue;
97619
97842
  }
@@ -97703,7 +97926,7 @@ ${loadedContents.join(`
97703
97926
  } else {
97704
97927
  console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
97705
97928
  }
97706
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
97929
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
97707
97930
  refreshCurrentInputOtids();
97708
97931
  continue;
97709
97932
  }
@@ -97731,7 +97954,7 @@ ${loadedContents.join(`
97731
97954
  const delaySeconds = Math.round(delayMs / 1000);
97732
97955
  console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
97733
97956
  }
97734
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
97957
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
97735
97958
  refreshCurrentInputOtids();
97736
97959
  continue;
97737
97960
  }
@@ -97761,7 +97984,7 @@ ${loadedContents.join(`
97761
97984
  const delaySeconds = Math.round(delayMs / 1000);
97762
97985
  console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
97763
97986
  }
97764
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
97987
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
97765
97988
  refreshCurrentInputOtids();
97766
97989
  continue;
97767
97990
  }
@@ -98101,9 +98324,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
98101
98324
  const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
98102
98325
  maybeNotifyBlocked(syntheticUserLine);
98103
98326
  if (lineResolver) {
98104
- const resolve28 = lineResolver;
98327
+ const resolve29 = lineResolver;
98105
98328
  lineResolver = null;
98106
- resolve28(syntheticUserLine);
98329
+ resolve29(syntheticUserLine);
98107
98330
  return;
98108
98331
  }
98109
98332
  lineQueue.push(syntheticUserLine);
@@ -98111,9 +98334,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
98111
98334
  rl.on("line", (line) => {
98112
98335
  maybeNotifyBlocked(line);
98113
98336
  if (lineResolver) {
98114
- const resolve28 = lineResolver;
98337
+ const resolve29 = lineResolver;
98115
98338
  lineResolver = null;
98116
- resolve28(line);
98339
+ resolve29(line);
98117
98340
  } else {
98118
98341
  lineQueue.push(line);
98119
98342
  }
@@ -98122,17 +98345,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
98122
98345
  setMessageQueueAdder(null);
98123
98346
  msgQueueRuntime.clear("shutdown");
98124
98347
  if (lineResolver) {
98125
- const resolve28 = lineResolver;
98348
+ const resolve29 = lineResolver;
98126
98349
  lineResolver = null;
98127
- resolve28(null);
98350
+ resolve29(null);
98128
98351
  }
98129
98352
  });
98130
98353
  async function getNextLine() {
98131
98354
  if (lineQueue.length > 0) {
98132
98355
  return lineQueue.shift() ?? null;
98133
98356
  }
98134
- return new Promise((resolve28) => {
98135
- lineResolver = resolve28;
98357
+ return new Promise((resolve29) => {
98358
+ lineResolver = resolve29;
98136
98359
  });
98137
98360
  }
98138
98361
  async function requestPermission(toolCallId, toolName, toolInput) {
@@ -98623,7 +98846,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
98623
98846
  uuid: `retry-bidir-${randomUUID13()}`
98624
98847
  };
98625
98848
  console.log(JSON.stringify(retryMsg));
98626
- await new Promise((resolve28) => setTimeout(resolve28, delayMs));
98849
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
98627
98850
  continue;
98628
98851
  }
98629
98852
  throw preStreamError;
@@ -98925,10 +99148,10 @@ async function detectAndEnableKittyProtocol() {
98925
99148
  detectionComplete = true;
98926
99149
  return;
98927
99150
  }
98928
- return new Promise((resolve28) => {
99151
+ return new Promise((resolve29) => {
98929
99152
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
98930
99153
  detectionComplete = true;
98931
- resolve28();
99154
+ resolve29();
98932
99155
  return;
98933
99156
  }
98934
99157
  const originalRawMode = process.stdin.isRaw;
@@ -98961,7 +99184,7 @@ async function detectAndEnableKittyProtocol() {
98961
99184
  console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
98962
99185
  }
98963
99186
  detectionComplete = true;
98964
- resolve28();
99187
+ resolve29();
98965
99188
  };
98966
99189
  const handleData = (data) => {
98967
99190
  if (timeoutId === undefined) {
@@ -99174,13 +99397,13 @@ var init_reconcileExistingAgentState = __esm(() => {
99174
99397
  // src/agent/sessionHistory.ts
99175
99398
  import * as fs17 from "node:fs";
99176
99399
  import * as os6 from "node:os";
99177
- import * as path25 from "node:path";
99400
+ import * as path26 from "node:path";
99178
99401
  function getHistoryDir() {
99179
99402
  const homeDir = os6.homedir();
99180
- return path25.join(homeDir, ".letta");
99403
+ return path26.join(homeDir, ".letta");
99181
99404
  }
99182
99405
  function getHistoryFilePath() {
99183
- return path25.join(getHistoryDir(), "sessions.jsonl");
99406
+ return path26.join(getHistoryDir(), "sessions.jsonl");
99184
99407
  }
99185
99408
  function recordSessionEnd(agentId, sessionId, stats, sessionInfo, cost, metadata) {
99186
99409
  const entry = {
@@ -117444,8 +117667,8 @@ function getHeader(command) {
117444
117667
  return `Run memory ${command}?`;
117445
117668
  }
117446
117669
  }
117447
- function displayPath(path26) {
117448
- return path26.replace(/\.md$/, "");
117670
+ function displayPath(path27) {
117671
+ return path27.replace(/\.md$/, "");
117449
117672
  }
117450
117673
  function truncate2(text, max) {
117451
117674
  if (text.length <= max)
@@ -117549,7 +117772,7 @@ var init_InlineMemoryApproval = __esm(async () => {
117549
117772
  const {
117550
117773
  command,
117551
117774
  reason,
117552
- path: path26,
117775
+ path: path27,
117553
117776
  oldPath,
117554
117777
  newPath,
117555
117778
  oldString,
@@ -117596,9 +117819,9 @@ var init_InlineMemoryApproval = __esm(async () => {
117596
117819
  }, undefined, false, undefined, this)
117597
117820
  ]
117598
117821
  }, undefined, true, undefined, this)
117599
- }, undefined, false, undefined, this) : path26 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text2, {
117822
+ }, undefined, false, undefined, this) : path27 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text2, {
117600
117823
  bold: true,
117601
- children: displayPath(path26)
117824
+ children: displayPath(path27)
117602
117825
  }, undefined, false, undefined, this),
117603
117826
  command === "str_replace" && oldString != null && newString != null && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
117604
117827
  flexDirection: "column",
@@ -121237,7 +121460,7 @@ var init_pasteRegistry = __esm(() => {
121237
121460
  import { execFileSync as execFileSync3 } from "node:child_process";
121238
121461
  import { existsSync as existsSync34, readFileSync as readFileSync20, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
121239
121462
  import { tmpdir as tmpdir4 } from "node:os";
121240
- import { basename as basename9, extname as extname8, isAbsolute as isAbsolute19, join as join42, resolve as resolve28 } from "node:path";
121463
+ import { basename as basename9, extname as extname8, isAbsolute as isAbsolute20, join as join42, resolve as resolve29 } from "node:path";
121241
121464
  function countLines2(text) {
121242
121465
  return (text.match(/\r\n|\r|\n/g) || []).length + 1;
121243
121466
  }
@@ -121284,8 +121507,8 @@ function translatePasteForImages(paste) {
121284
121507
  }
121285
121508
  } catch {}
121286
121509
  }
121287
- if (!isAbsolute19(filePath))
121288
- filePath = resolve28(process.cwd(), filePath);
121510
+ if (!isAbsolute20(filePath))
121511
+ filePath = resolve29(process.cwd(), filePath);
121289
121512
  const ext3 = extname8(filePath || "").toLowerCase();
121290
121513
  if (IMAGE_EXTS.has(ext3) && existsSync34(filePath) && statSync10(filePath).isFile()) {
121291
121514
  const buf = readFileSync20(filePath);
@@ -122220,14 +122443,14 @@ function installKeybindingForCurrentTerminal() {
122220
122443
  error: "Not running in a VS Code-like terminal"
122221
122444
  };
122222
122445
  }
122223
- const path26 = getKeybindingsPath(terminal);
122224
- if (!path26) {
122446
+ const path27 = getKeybindingsPath(terminal);
122447
+ if (!path27) {
122225
122448
  return {
122226
122449
  success: false,
122227
122450
  error: `Could not determine keybindings.json path for ${terminal}`
122228
122451
  };
122229
122452
  }
122230
- return installKeybinding(path26);
122453
+ return installKeybinding(path27);
122231
122454
  }
122232
122455
  function removeKeybindingForCurrentTerminal() {
122233
122456
  const terminal = detectTerminalType();
@@ -122237,14 +122460,14 @@ function removeKeybindingForCurrentTerminal() {
122237
122460
  error: "Not running in a VS Code-like terminal"
122238
122461
  };
122239
122462
  }
122240
- const path26 = getKeybindingsPath(terminal);
122241
- if (!path26) {
122463
+ const path27 = getKeybindingsPath(terminal);
122464
+ if (!path27) {
122242
122465
  return {
122243
122466
  success: false,
122244
122467
  error: `Could not determine keybindings.json path for ${terminal}`
122245
122468
  };
122246
122469
  }
122247
- return removeKeybinding(path26);
122470
+ return removeKeybinding(path27);
122248
122471
  }
122249
122472
  function isWezTerm() {
122250
122473
  return process.env.TERM_PROGRAM === "WezTerm";
@@ -122900,7 +123123,7 @@ __export(exports_custom, {
122900
123123
  COMMANDS_DIR: () => COMMANDS_DIR
122901
123124
  });
122902
123125
  import { existsSync as existsSync36 } from "node:fs";
122903
- import { readdir as readdir9, readFile as readFile13 } from "node:fs/promises";
123126
+ import { readdir as readdir10, readFile as readFile14 } from "node:fs/promises";
122904
123127
  import { basename as basename10, dirname as dirname17, join as join44 } from "node:path";
122905
123128
  async function getCustomCommands() {
122906
123129
  if (cachedCommands !== null) {
@@ -122942,7 +123165,7 @@ async function discoverFromDirectory(dirPath, source2) {
122942
123165
  }
122943
123166
  async function findCommandFiles(currentPath, rootPath, commands2, source2) {
122944
123167
  try {
122945
- const entries = await readdir9(currentPath, { withFileTypes: true });
123168
+ const entries = await readdir10(currentPath, { withFileTypes: true });
122946
123169
  for (const entry of entries) {
122947
123170
  const fullPath = join44(currentPath, entry.name);
122948
123171
  if (entry.isDirectory()) {
@@ -122959,7 +123182,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source2) {
122959
123182
  } catch (_error) {}
122960
123183
  }
122961
123184
  async function parseCommandFile(filePath, rootPath, source2) {
122962
- const content = await readFile13(filePath, "utf-8");
123185
+ const content = await readFile14(filePath, "utf-8");
122963
123186
  const { frontmatter, body } = parseFrontmatter(content);
122964
123187
  const id = basename10(filePath, ".md");
122965
123188
  const relativePath = dirname17(filePath).slice(rootPath.length);
@@ -123311,11 +123534,11 @@ var init_HelpDialog = __esm(async () => {
123311
123534
 
123312
123535
  // src/hooks/writer.ts
123313
123536
  import { homedir as homedir34 } from "node:os";
123314
- import { resolve as resolve29 } from "node:path";
123537
+ import { resolve as resolve30 } from "node:path";
123315
123538
  function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
123316
123539
  const home = process.env.HOME || homedir34();
123317
- const globalSettingsPath = resolve29(home, ".letta", "settings.json");
123318
- const projectSettingsPath = resolve29(workingDirectory, ".letta", "settings.json");
123540
+ const globalSettingsPath = resolve30(home, ".letta", "settings.json");
123541
+ const projectSettingsPath = resolve30(workingDirectory, ".letta", "settings.json");
123319
123542
  return globalSettingsPath === projectSettingsPath;
123320
123543
  }
123321
123544
  function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
@@ -125953,7 +126176,7 @@ var init_AgentInfoBar = __esm(async () => {
125953
126176
 
125954
126177
  // src/cli/helpers/fileSearch.ts
125955
126178
  import { readdirSync as readdirSync12, statSync as statSync11 } from "node:fs";
125956
- import { join as join45, relative as relative16, resolve as resolve30 } from "node:path";
126179
+ import { join as join45, relative as relative16, resolve as resolve31 } from "node:path";
125957
126180
  function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
125958
126181
  if (results.length >= maxResults || depth >= maxDepth) {
125959
126182
  return results;
@@ -125996,7 +126219,7 @@ async function searchFiles(query, deep = false) {
125996
126219
  const dirPart = query.slice(0, lastSlashIndex);
125997
126220
  const pattern = query.slice(lastSlashIndex + 1);
125998
126221
  try {
125999
- const resolvedDir = resolve30(getIndexRoot(), dirPart);
126222
+ const resolvedDir = resolve31(getIndexRoot(), dirPart);
126000
126223
  try {
126001
126224
  statSync11(resolvedDir);
126002
126225
  searchDir = resolvedDir;
@@ -128321,9 +128544,9 @@ function buildInstallPrBody(workflowPath) {
128321
128544
  ].join(`
128322
128545
  `);
128323
128546
  }
128324
- function checkRemoteFileExists(repo, path26) {
128547
+ function checkRemoteFileExists(repo, path27) {
128325
128548
  try {
128326
- runCommand("gh", ["api", `repos/${repo}/contents/${path26}`]);
128549
+ runCommand("gh", ["api", `repos/${repo}/contents/${path27}`]);
128327
128550
  return true;
128328
128551
  } catch {
128329
128552
  return false;
@@ -135684,7 +135907,7 @@ var init_PersonalitySelector = __esm(async () => {
135684
135907
  });
135685
135908
 
135686
135909
  // src/utils/aws-credentials.ts
135687
- import { readFile as readFile14 } from "node:fs/promises";
135910
+ import { readFile as readFile15 } from "node:fs/promises";
135688
135911
  import { homedir as homedir36 } from "node:os";
135689
135912
  import { join as join48 } from "node:path";
135690
135913
  async function parseAwsCredentials() {
@@ -135692,11 +135915,11 @@ async function parseAwsCredentials() {
135692
135915
  const configPath = join48(homedir36(), ".aws", "config");
135693
135916
  const profiles = new Map;
135694
135917
  try {
135695
- const content = await readFile14(credentialsPath, "utf-8");
135918
+ const content = await readFile15(credentialsPath, "utf-8");
135696
135919
  parseIniFile(content, profiles, false);
135697
135920
  } catch {}
135698
135921
  try {
135699
- const content = await readFile14(configPath, "utf-8");
135922
+ const content = await readFile15(configPath, "utf-8");
135700
135923
  parseIniFile(content, profiles, true);
135701
135924
  } catch {}
135702
135925
  return Array.from(profiles.values());
@@ -138303,8 +138526,8 @@ function MemoryDiffRenderer({
138303
138526
  }, undefined, false, undefined, this);
138304
138527
  }
138305
138528
  const command = args.command;
138306
- const path26 = args.path || args.old_path || "unknown";
138307
- const blockName = path26.split("/").pop() || path26;
138529
+ const path27 = args.path || args.old_path || "unknown";
138530
+ const blockName = path27.split("/").pop() || path27;
138308
138531
  switch (command) {
138309
138532
  case "str_replace": {
138310
138533
  const oldStr = args.old_string || args.old_str || "";
@@ -141176,7 +141399,7 @@ async function executeStatusLineCommand(command, payload, options) {
141176
141399
  };
141177
141400
  }
141178
141401
  function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
141179
- return new Promise((resolve31, reject) => {
141402
+ return new Promise((resolve32, reject) => {
141180
141403
  const [executable, ...args] = launcher;
141181
141404
  if (!executable) {
141182
141405
  reject(new Error("Empty launcher"));
@@ -141189,7 +141412,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
141189
141412
  const safeResolve = (result) => {
141190
141413
  if (!resolved) {
141191
141414
  resolved = true;
141192
- resolve31(result);
141415
+ resolve32(result);
141193
141416
  }
141194
141417
  };
141195
141418
  let child;
@@ -142361,28 +142584,28 @@ var exports_export = {};
142361
142584
  __export(exports_export, {
142362
142585
  packageSkills: () => packageSkills
142363
142586
  });
142364
- import { readdir as readdir10, readFile as readFile15 } from "node:fs/promises";
142365
- import { relative as relative17, resolve as resolve31 } from "node:path";
142587
+ import { readdir as readdir11, readFile as readFile16 } from "node:fs/promises";
142588
+ import { relative as relative17, resolve as resolve32 } from "node:path";
142366
142589
  async function packageSkills(agentId, skillsDir) {
142367
142590
  const skills = [];
142368
142591
  const skillNames = new Set;
142369
142592
  const dirsToCheck = skillsDir ? [skillsDir] : [
142370
142593
  agentId && getAgentSkillsDir(agentId),
142371
- resolve31(process.cwd(), ".skills"),
142372
- resolve31(process.env.HOME || "~", ".letta", "skills")
142594
+ resolve32(process.cwd(), ".skills"),
142595
+ resolve32(process.env.HOME || "~", ".letta", "skills")
142373
142596
  ].filter((dir) => Boolean(dir));
142374
142597
  for (const baseDir of dirsToCheck) {
142375
142598
  try {
142376
- const entries = await readdir10(baseDir, { withFileTypes: true });
142599
+ const entries = await readdir11(baseDir, { withFileTypes: true });
142377
142600
  for (const entry of entries) {
142378
142601
  if (!entry.isDirectory())
142379
142602
  continue;
142380
142603
  if (skillNames.has(entry.name))
142381
142604
  continue;
142382
- const skillDir = resolve31(baseDir, entry.name);
142383
- const skillMdPath = resolve31(skillDir, "SKILL.md");
142605
+ const skillDir = resolve32(baseDir, entry.name);
142606
+ const skillMdPath = resolve32(skillDir, "SKILL.md");
142384
142607
  try {
142385
- await readFile15(skillMdPath, "utf-8");
142608
+ await readFile16(skillMdPath, "utf-8");
142386
142609
  } catch {
142387
142610
  console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
142388
142611
  continue;
@@ -142408,13 +142631,13 @@ async function packageSkills(agentId, skillsDir) {
142408
142631
  async function readSkillFiles(skillDir) {
142409
142632
  const files = {};
142410
142633
  async function walk(dir) {
142411
- const entries = await readdir10(dir, { withFileTypes: true });
142634
+ const entries = await readdir11(dir, { withFileTypes: true });
142412
142635
  for (const entry of entries) {
142413
- const fullPath = resolve31(dir, entry.name);
142636
+ const fullPath = resolve32(dir, entry.name);
142414
142637
  if (entry.isDirectory()) {
142415
142638
  await walk(fullPath);
142416
142639
  } else {
142417
- const content = await readFile15(fullPath, "utf-8");
142640
+ const content = await readFile16(fullPath, "utf-8");
142418
142641
  const relativePath = relative17(skillDir, fullPath).replace(/\\/g, "/");
142419
142642
  files[relativePath] = content;
142420
142643
  }
@@ -142434,8 +142657,8 @@ async function findSkillSourceUrl(skillName) {
142434
142657
  }
142435
142658
  return null;
142436
142659
  }
142437
- async function fetchGitHubDirs(path26) {
142438
- const [owner, repo, branch, ...pathParts] = path26.split("/");
142660
+ async function fetchGitHubDirs(path27) {
142661
+ const [owner, repo, branch, ...pathParts] = path27.split("/");
142439
142662
  if (!owner || !repo || !branch)
142440
142663
  return new Set;
142441
142664
  try {
@@ -144592,12 +144815,12 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
144592
144815
  let watcher = null;
144593
144816
  (async () => {
144594
144817
  try {
144595
- const { watch } = await import("node:fs");
144818
+ const { watch: watch2 } = await import("node:fs");
144596
144819
  const { existsSync: existsSync43 } = await import("node:fs");
144597
144820
  const memRoot = getMemoryFilesystemRoot(agentId);
144598
144821
  if (!existsSync43(memRoot))
144599
144822
  return;
144600
- watcher = watch(memRoot, { recursive: true }, () => {});
144823
+ watcher = watch2(memRoot, { recursive: true }, () => {});
144601
144824
  memfsWatcherRef.current = watcher;
144602
144825
  debugLog("memfs", `Watching memory directory: ${memRoot}`);
144603
144826
  watcher.on("error", (err) => {
@@ -144924,7 +145147,7 @@ ${newState.originalPrompt}`,
144924
145147
  cancelled = true;
144925
145148
  break;
144926
145149
  }
144927
- await new Promise((resolve32) => setTimeout(resolve32, 100));
145150
+ await new Promise((resolve33) => setTimeout(resolve33, 100));
144928
145151
  }
144929
145152
  buffersRef.current.byId.delete(statusId);
144930
145153
  buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
@@ -144988,7 +145211,7 @@ ${newState.originalPrompt}`,
144988
145211
  cancelled = true;
144989
145212
  break;
144990
145213
  }
144991
- await new Promise((resolve32) => setTimeout(resolve32, 100));
145214
+ await new Promise((resolve33) => setTimeout(resolve33, 100));
144992
145215
  }
144993
145216
  if (retryStatusId) {
144994
145217
  buffersRef.current.byId.delete(retryStatusId);
@@ -145746,7 +145969,7 @@ ${feedback}
145746
145969
  });
145747
145970
  buffersRef.current.order.push(statusId);
145748
145971
  refreshDerived();
145749
- await new Promise((resolve32) => setTimeout(resolve32, delayMs));
145972
+ await new Promise((resolve33) => setTimeout(resolve33, delayMs));
145750
145973
  buffersRef.current.byId.delete(statusId);
145751
145974
  buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
145752
145975
  refreshDerived();
@@ -145806,7 +146029,7 @@ ${feedback}
145806
146029
  cancelled = true;
145807
146030
  break;
145808
146031
  }
145809
- await new Promise((resolve32) => setTimeout(resolve32, 100));
146032
+ await new Promise((resolve33) => setTimeout(resolve33, 100));
145810
146033
  }
145811
146034
  if (retryStatusId) {
145812
146035
  buffersRef.current.byId.delete(retryStatusId);
@@ -152514,14 +152737,14 @@ function installKeybindingForCurrentTerminal2() {
152514
152737
  error: "Not running in a VS Code-like terminal"
152515
152738
  };
152516
152739
  }
152517
- const path26 = getKeybindingsPath2(terminal);
152518
- if (!path26) {
152740
+ const path27 = getKeybindingsPath2(terminal);
152741
+ if (!path27) {
152519
152742
  return {
152520
152743
  success: false,
152521
152744
  error: `Could not determine keybindings.json path for ${terminal}`
152522
152745
  };
152523
152746
  }
152524
- return installKeybinding2(path26);
152747
+ return installKeybinding2(path27);
152525
152748
  }
152526
152749
  function removeKeybindingForCurrentTerminal2() {
152527
152750
  const terminal = detectTerminalType2();
@@ -152531,14 +152754,14 @@ function removeKeybindingForCurrentTerminal2() {
152531
152754
  error: "Not running in a VS Code-like terminal"
152532
152755
  };
152533
152756
  }
152534
- const path26 = getKeybindingsPath2(terminal);
152535
- if (!path26) {
152757
+ const path27 = getKeybindingsPath2(terminal);
152758
+ if (!path27) {
152536
152759
  return {
152537
152760
  success: false,
152538
152761
  error: `Could not determine keybindings.json path for ${terminal}`
152539
152762
  };
152540
152763
  }
152541
- return removeKeybinding2(path26);
152764
+ return removeKeybinding2(path27);
152542
152765
  }
152543
152766
  function isWezTerm2() {
152544
152767
  return process.env.TERM_PROGRAM === "WezTerm";
@@ -153174,11 +153397,11 @@ __export(exports_import2, {
153174
153397
  extractSkillsFromAf: () => extractSkillsFromAf2
153175
153398
  });
153176
153399
  import { createReadStream as createReadStream2 } from "node:fs";
153177
- import { chmod as chmod2, mkdir as mkdir11, readFile as readFile16, writeFile as writeFile12 } from "node:fs/promises";
153178
- import { dirname as dirname20, resolve as resolve32 } from "node:path";
153400
+ import { chmod as chmod2, mkdir as mkdir11, readFile as readFile17, writeFile as writeFile12 } from "node:fs/promises";
153401
+ import { dirname as dirname20, resolve as resolve33 } from "node:path";
153179
153402
  async function importAgentFromFile2(options) {
153180
153403
  const client = await getClient();
153181
- const resolvedPath = resolve32(options.filePath);
153404
+ const resolvedPath = resolve33(options.filePath);
153182
153405
  const file = createReadStream2(resolvedPath);
153183
153406
  const importResponse = await client.agents.importFile({
153184
153407
  file,
@@ -153207,13 +153430,13 @@ async function importAgentFromFile2(options) {
153207
153430
  }
153208
153431
  async function extractSkillsFromAf2(afPath, destDir) {
153209
153432
  const extracted = [];
153210
- const content = await readFile16(afPath, "utf-8");
153433
+ const content = await readFile17(afPath, "utf-8");
153211
153434
  const afData = JSON.parse(content);
153212
153435
  if (!afData.skills || !Array.isArray(afData.skills)) {
153213
153436
  return [];
153214
153437
  }
153215
153438
  for (const skill2 of afData.skills) {
153216
- const skillDir = resolve32(destDir, skill2.name);
153439
+ const skillDir = resolve33(destDir, skill2.name);
153217
153440
  await mkdir11(skillDir, { recursive: true });
153218
153441
  if (skill2.files) {
153219
153442
  await writeSkillFiles2(skillDir, skill2.files);
@@ -153233,7 +153456,7 @@ async function writeSkillFiles2(skillDir, files) {
153233
153456
  }
153234
153457
  }
153235
153458
  async function writeSkillFile2(skillDir, filePath, content) {
153236
- const fullPath = resolve32(skillDir, filePath);
153459
+ const fullPath = resolve33(skillDir, filePath);
153237
153460
  await mkdir11(dirname20(fullPath), { recursive: true });
153238
153461
  await writeFile12(fullPath, content, "utf-8");
153239
153462
  const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
@@ -153252,13 +153475,13 @@ async function fetchSkillFromUrl2(skillDir, sourceUrl) {
153252
153475
  const owner = parts[0];
153253
153476
  const repo = parts[1];
153254
153477
  const branch = parts[2];
153255
- const path26 = parts.slice(3).join("/");
153478
+ const path27 = parts.slice(3).join("/");
153256
153479
  const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
153257
- const entries = await fetchGitHubContents2(owner, repo, branch, path26);
153480
+ const entries = await fetchGitHubContents2(owner, repo, branch, path27);
153258
153481
  if (!Array.isArray(entries)) {
153259
153482
  throw new Error(`Expected directory at ${sourceUrl}, got file`);
153260
153483
  }
153261
- await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch, path26);
153484
+ await downloadGitHubDirectory2(entries, skillDir, owner, repo, branch, path27);
153262
153485
  }
153263
153486
  async function downloadGitHubDirectory2(entries, destDir, owner, repo, branch, basePath) {
153264
153487
  const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
@@ -158271,23 +158494,21 @@ async function runListenSubcommand(argv) {
158271
158494
  process.exit(code);
158272
158495
  };
158273
158496
  await settingsManager.loadLocalProjectSettings();
158274
- if (values.channels) {
158275
- const channelNames = values.channels.split(",").map((s) => s.trim()).filter(Boolean);
158276
- if (channelNames.length > 0) {
158277
- if (values["install-channel-runtimes"]) {
158278
- const { ensureChannelRuntimeInstalled: ensureChannelRuntimeInstalled2 } = await Promise.resolve().then(() => (init_runtimeDeps(), exports_runtimeDeps));
158279
- const { isSupportedChannelId: isSupportedChannelId2 } = await Promise.resolve().then(() => (init_pluginRegistry(), exports_pluginRegistry));
158280
- for (const channelName of channelNames) {
158281
- if (!isSupportedChannelId2(channelName)) {
158282
- console.error(`Unknown channel "${channelName}" passed to --channels.`);
158283
- return 1;
158284
- }
158285
- await ensureChannelRuntimeInstalled2(channelName);
158497
+ const channelNames = values.channels ? values.channels.split(",").map((s) => s.trim()).filter(Boolean) : process.env.LETTA_RESTORE_ENABLED_CHANNELS === "1" ? (await Promise.resolve().then(() => (init_service(), exports_service))).listEnabledChannelIds() : [];
158498
+ if (channelNames.length > 0) {
158499
+ if (values.channels && values["install-channel-runtimes"]) {
158500
+ const { ensureChannelRuntimeInstalled: ensureChannelRuntimeInstalled2 } = await Promise.resolve().then(() => (init_runtimeDeps(), exports_runtimeDeps));
158501
+ const { isSupportedChannelId: isSupportedChannelId2 } = await Promise.resolve().then(() => (init_pluginRegistry(), exports_pluginRegistry));
158502
+ for (const channelName of channelNames) {
158503
+ if (!isSupportedChannelId2(channelName)) {
158504
+ console.error(`Unknown channel "${channelName}" passed to --channels.`);
158505
+ return 1;
158286
158506
  }
158507
+ await ensureChannelRuntimeInstalled2(channelName);
158287
158508
  }
158288
- const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
158289
- await initializeChannels2(channelNames);
158290
158509
  }
158510
+ const { initializeChannels: initializeChannels2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
158511
+ await initializeChannels2(channelNames);
158291
158512
  }
158292
158513
  let connectionName;
158293
158514
  if (values["env-name"]) {
@@ -158301,11 +158522,11 @@ async function runListenSubcommand(argv) {
158301
158522
  connectionName = hostname3();
158302
158523
  settingsManager.setListenerEnvName(connectionName);
158303
158524
  } else {
158304
- connectionName = await new Promise((resolve24) => {
158525
+ connectionName = await new Promise((resolve25) => {
158305
158526
  const { unmount } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(PromptEnvName, {
158306
158527
  onSubmit: (name) => {
158307
158528
  unmount();
158308
- resolve24(name);
158529
+ resolve25(name);
158309
158530
  }
158310
158531
  }, undefined, false, undefined, this));
158311
158532
  });
@@ -158508,7 +158729,7 @@ async function runListenSubcommand(argv) {
158508
158729
  // src/cli/subcommands/memfs.ts
158509
158730
  init_memoryGit();
158510
158731
  import { cpSync, existsSync as existsSync26, mkdirSync as mkdirSync19, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
158511
- import { readdir as readdir6 } from "node:fs/promises";
158732
+ import { readdir as readdir7 } from "node:fs/promises";
158512
158733
  import { homedir as homedir24 } from "node:os";
158513
158734
  import { join as join31 } from "node:path";
158514
158735
  import { parseArgs as parseArgs8 } from "node:util";
@@ -158575,22 +158796,22 @@ async function listBackups(agentId) {
158575
158796
  if (!existsSync26(agentRoot)) {
158576
158797
  return [];
158577
158798
  }
158578
- const entries = await readdir6(agentRoot, { withFileTypes: true });
158799
+ const entries = await readdir7(agentRoot, { withFileTypes: true });
158579
158800
  const backups = [];
158580
158801
  for (const entry of entries) {
158581
158802
  if (!entry.isDirectory())
158582
158803
  continue;
158583
158804
  if (!entry.name.startsWith("memory-backup-"))
158584
158805
  continue;
158585
- const path23 = join31(agentRoot, entry.name);
158806
+ const path24 = join31(agentRoot, entry.name);
158586
158807
  let createdAt = null;
158587
158808
  try {
158588
- const stat6 = statSync8(path23);
158589
- createdAt = stat6.mtime.toISOString();
158809
+ const stat7 = statSync8(path24);
158810
+ createdAt = stat7.mtime.toISOString();
158590
158811
  } catch {
158591
158812
  createdAt = null;
158592
158813
  }
158593
- backups.push({ name: entry.name, path: path23, createdAt });
158814
+ backups.push({ name: entry.name, path: path24, createdAt });
158594
158815
  }
158595
158816
  backups.sort((a, b) => a.name.localeCompare(b.name));
158596
158817
  return backups;
@@ -158694,8 +158915,8 @@ async function runMemfsSubcommand(argv) {
158694
158915
  console.error(`Backup not found: ${backupPath}`);
158695
158916
  return 1;
158696
158917
  }
158697
- const stat6 = statSync8(backupPath);
158698
- if (!stat6.isDirectory()) {
158918
+ const stat7 = statSync8(backupPath);
158919
+ if (!stat7.isDirectory()) {
158699
158920
  console.error(`Backup path is not a directory: ${backupPath}`);
158700
158921
  return 1;
158701
158922
  }
@@ -158717,9 +158938,9 @@ async function runMemfsSubcommand(argv) {
158717
158938
  return 1;
158718
158939
  }
158719
158940
  if (existsSync26(out)) {
158720
- const stat6 = statSync8(out);
158721
- if (stat6.isDirectory()) {
158722
- const contents = await readdir6(out);
158941
+ const stat7 = statSync8(out);
158942
+ if (stat7.isDirectory()) {
158943
+ const contents = await readdir7(out);
158723
158944
  if (contents.length > 0) {
158724
158945
  console.error(`Export directory not empty: ${out}`);
158725
158946
  return 1;
@@ -158748,7 +158969,7 @@ async function runMemfsSubcommand(argv) {
158748
158969
  init_client2();
158749
158970
  init_settings_manager();
158750
158971
  import { writeFile as writeFile9 } from "node:fs/promises";
158751
- import { resolve as resolve24 } from "node:path";
158972
+ import { resolve as resolve25 } from "node:path";
158752
158973
  import { parseArgs as parseArgs9 } from "node:util";
158753
158974
  function printUsage6() {
158754
158975
  console.log(`
@@ -159053,7 +159274,7 @@ async function runMessagesSubcommand(argv) {
159053
159274
 
159054
159275
  `).trim();
159055
159276
  if (outputPathRaw && typeof outputPathRaw === "string") {
159056
- const outputPath = resolve24(process.cwd(), outputPathRaw);
159277
+ const outputPath = resolve25(process.cwd(), outputPathRaw);
159057
159278
  await writeFile9(outputPath, `${transcript}
159058
159279
  `, "utf-8");
159059
159280
  console.log(JSON.stringify({
@@ -159115,13 +159336,13 @@ init_memoryScope();
159115
159336
  init_readOnlyShell();
159116
159337
  init_shell_command_normalization();
159117
159338
  import { homedir as homedir25 } from "node:os";
159118
- import { isAbsolute as isAbsolute17, join as join32, relative as relative13 } from "node:path";
159339
+ import { isAbsolute as isAbsolute18, join as join32, relative as relative13 } from "node:path";
159119
159340
  var MODE_KEY2 = Symbol.for("@letta/permissionMode");
159120
159341
  var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
159121
159342
  var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
159122
159343
  function everyResolvedTargetIsWithinRoots2(candidatePaths, roots, workingDirectory) {
159123
- return candidatePaths.length > 0 && candidatePaths.every((path23) => {
159124
- const resolvedPath = resolveScopedTargetPath(path23, workingDirectory);
159344
+ return candidatePaths.length > 0 && candidatePaths.every((path24) => {
159345
+ const resolvedPath = resolveScopedTargetPath(path24, workingDirectory);
159125
159346
  return resolvedPath ? isPathWithinRoots(resolvedPath, roots) : false;
159126
159347
  });
159127
159348
  }
@@ -159155,11 +159376,11 @@ function setGlobalModeBeforePlan2(value) {
159155
159376
  function resolvePlanTargetPath2(targetPath, workingDirectory) {
159156
159377
  return resolveScopedTargetPath(targetPath, workingDirectory);
159157
159378
  }
159158
- function isPathInPlansDir2(path23, plansDir) {
159159
- if (!path23.endsWith(".md"))
159379
+ function isPathInPlansDir2(path24, plansDir) {
159380
+ if (!path24.endsWith(".md"))
159160
159381
  return false;
159161
- const rel = relative13(plansDir, path23);
159162
- return rel !== "" && !rel.startsWith("..") && !isAbsolute17(rel);
159382
+ const rel = relative13(plansDir, path24);
159383
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute18(rel);
159163
159384
  }
159164
159385
  function extractApplyPatchPaths2(input) {
159165
159386
  const paths = [];
@@ -159260,8 +159481,8 @@ class PermissionModeManager2 {
159260
159481
  getMode() {
159261
159482
  return this.currentMode;
159262
159483
  }
159263
- setPlanFilePath(path23) {
159264
- setGlobalPlanFilePath2(path23);
159484
+ setPlanFilePath(path24) {
159485
+ setGlobalPlanFilePath2(path24);
159265
159486
  }
159266
159487
  getPlanFilePath() {
159267
159488
  return getGlobalPlanFilePath2();
@@ -159356,8 +159577,8 @@ class PermissionModeManager2 {
159356
159577
  } else if (typeof targetPath === "string") {
159357
159578
  candidatePaths = [targetPath];
159358
159579
  }
159359
- if (candidatePaths.length > 0 && candidatePaths.every((path23) => {
159360
- const resolvedPath = resolvePlanTargetPath2(path23, workingDirectory);
159580
+ if (candidatePaths.length > 0 && candidatePaths.every((path24) => {
159581
+ const resolvedPath = resolvePlanTargetPath2(path24, workingDirectory);
159361
159582
  return resolvedPath ? isPathInPlansDir2(resolvedPath, plansDir) : false;
159362
159583
  })) {
159363
159584
  return "allow";
@@ -159516,7 +159737,7 @@ init_fs();
159516
159737
  init_secrets();
159517
159738
  import { randomUUID as randomUUID9 } from "node:crypto";
159518
159739
  import { homedir as homedir26 } from "node:os";
159519
- import { join as join33, resolve as resolve25 } from "node:path";
159740
+ import { join as join33, resolve as resolve26 } from "node:path";
159520
159741
  var DEFAULT_SETTINGS3 = {
159521
159742
  lastAgent: null,
159522
159743
  tokenStreaming: false,
@@ -159970,7 +160191,7 @@ class SettingsManager2 {
159970
160191
  return join33(workingDirectory, ".letta", "settings.json");
159971
160192
  }
159972
160193
  isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
159973
- return resolve25(this.getProjectSettingsPath(workingDirectory)) === resolve25(this.getSettingsPath());
160194
+ return resolve26(this.getProjectSettingsPath(workingDirectory)) === resolve26(this.getSettingsPath());
159974
160195
  }
159975
160196
  getLocalProjectSettingsPath(workingDirectory) {
159976
160197
  return join33(workingDirectory, ".letta", "settings.local.json");
@@ -160915,6 +161136,7 @@ var STREAMING_SHELL_TOOLS2 = new Set([
160915
161136
  "run_shell_command",
160916
161137
  "RunShellCommand"
160917
161138
  ]);
161139
+ var FILE_MUTATING_TOOLS2 = new Set(["Edit", "Write", "MultiEdit", "replace"]);
160918
161140
  var ANTHROPIC_DEFAULT_TOOLS2 = [
160919
161141
  "AskUserQuestion",
160920
161142
  "Bash",
@@ -160985,8 +161207,8 @@ function acquireSwitchLock2() {
160985
161207
  const lock = getSwitchLock2();
160986
161208
  lock.refCount++;
160987
161209
  if (lock.refCount === 1) {
160988
- lock.promise = new Promise((resolve26) => {
160989
- lock.resolve = resolve26;
161210
+ lock.promise = new Promise((resolve27) => {
161211
+ lock.resolve = resolve27;
160990
161212
  });
160991
161213
  }
160992
161214
  }
@@ -161475,7 +161697,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
161475
161697
  printHelp();
161476
161698
  const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
161477
161699
  if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
161478
- await new Promise((resolve33) => setTimeout(resolve33, helpDelayMs));
161700
+ await new Promise((resolve34) => setTimeout(resolve34, helpDelayMs));
161479
161701
  }
161480
161702
  process.exit(0);
161481
161703
  }
@@ -161697,9 +161919,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
161697
161919
  process.exit(1);
161698
161920
  }
161699
161921
  } else {
161700
- const { resolve: resolve33 } = await import("path");
161922
+ const { resolve: resolve34 } = await import("path");
161701
161923
  const { existsSync: existsSync45 } = await import("fs");
161702
- const resolvedPath = resolve33(fromAfFile);
161924
+ const resolvedPath = resolve34(fromAfFile);
161703
161925
  if (!existsSync45(resolvedPath)) {
161704
161926
  console.error(`Error: AgentFile not found: ${resolvedPath}`);
161705
161927
  process.exit(1);
@@ -162579,4 +162801,4 @@ Error during initialization: ${message}`);
162579
162801
  }
162580
162802
  main();
162581
162803
 
162582
- //# debugId=F6C28381AA0FA8FC64756E2164756E21
162804
+ //# debugId=50A69FA1631D153664756E2164756E21