@letta-ai/letta-code 0.34.22 → 0.34.24

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 (76) hide show
  1. package/dist/app-server-client.cjs +2 -2
  2. package/dist/app-server-client.cjs.map +3 -3
  3. package/dist/app-server-client.js +2 -2
  4. package/dist/app-server-client.js.map +3 -3
  5. package/dist/gateway-core.js +7 -4
  6. package/dist/gateway-core.js.map +3 -3
  7. package/dist/mcp-client.js +2 -2
  8. package/dist/mcp-client.js.map +1 -1
  9. package/dist/mcp-oauth.js +2 -2
  10. package/dist/mcp-oauth.js.map +1 -1
  11. package/dist/types/agent/memory-constraints.d.ts +1 -1
  12. package/dist/types/agent/turn-recovery-policy.d.ts +3 -3
  13. package/dist/types/agent/turn-recovery-policy.d.ts.map +1 -1
  14. package/dist/types/backend/api/schedules.d.ts +4 -3
  15. package/dist/types/backend/api/schedules.d.ts.map +1 -1
  16. package/dist/types/backend/api/unified-mcp.d.ts.map +1 -1
  17. package/dist/types/backend/dev/fake-headless-backend.d.ts +1 -0
  18. package/dist/types/backend/dev/fake-headless-backend.d.ts.map +1 -1
  19. package/dist/types/backend/dev/provider-turn-executor.d.ts.map +1 -1
  20. package/dist/types/backend/local/local-conversation-key.d.ts +6 -0
  21. package/dist/types/backend/local/local-conversation-key.d.ts.map +1 -0
  22. package/dist/types/backend/local/local-store.d.ts.map +1 -1
  23. package/dist/types/channels/control-request-coordinator.d.ts.map +1 -1
  24. package/dist/types/cli/helpers/git-context.d.ts +5 -2
  25. package/dist/types/cli/helpers/git-context.d.ts.map +1 -1
  26. package/dist/types/cron/cron-file.d.ts +2 -3
  27. package/dist/types/cron/cron-file.d.ts.map +1 -1
  28. package/dist/types/cron/process-identity.d.ts +9 -0
  29. package/dist/types/cron/process-identity.d.ts.map +1 -1
  30. package/dist/types/cron/runner.d.ts +2 -2
  31. package/dist/types/cron/runner.d.ts.map +1 -1
  32. package/dist/types/cron/scheduler.d.ts +3 -2
  33. package/dist/types/cron/scheduler.d.ts.map +1 -1
  34. package/dist/types/permissions/checker.d.ts +8 -0
  35. package/dist/types/permissions/checker.d.ts.map +1 -1
  36. package/dist/types/queue/queue-runtime.d.ts +7 -19
  37. package/dist/types/queue/queue-runtime.d.ts.map +1 -1
  38. package/dist/types/tools/impl/external-coding-agent-task.d.ts +9 -0
  39. package/dist/types/tools/impl/external-coding-agent-task.d.ts.map +1 -1
  40. package/dist/types/tools/impl/shell-launchers.d.ts.map +1 -1
  41. package/dist/types/types/app-server-info.d.ts +0 -2
  42. package/dist/types/types/app-server-info.d.ts.map +1 -1
  43. package/dist/types/types/protocol.d.ts +2 -3
  44. package/dist/types/types/protocol.d.ts.map +1 -1
  45. package/dist/types/types/protocol_v2.d.ts +1 -1
  46. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  47. package/dist/types/types/schedule-protocol.d.ts +2 -2
  48. package/dist/types/types/schedule-protocol.d.ts.map +1 -1
  49. package/dist/types/utils/rename-sync-with-retry.d.ts +3 -0
  50. package/dist/types/utils/rename-sync-with-retry.d.ts.map +1 -0
  51. package/dist/types/websocket/listener/connection.d.ts +2 -0
  52. package/dist/types/websocket/listener/connection.d.ts.map +1 -1
  53. package/dist/types/websocket/listener/constants.d.ts +1 -0
  54. package/dist/types/websocket/listener/constants.d.ts.map +1 -1
  55. package/dist/types/websocket/listener/device-git-context.d.ts.map +1 -1
  56. package/dist/types/websocket/listener/interrupted-turn-record.d.ts.map +1 -1
  57. package/dist/types/websocket/listener/interrupted-turn-storage.d.ts.map +1 -1
  58. package/dist/types/websocket/listener/queue.d.ts +1 -2
  59. package/dist/types/websocket/listener/queue.d.ts.map +1 -1
  60. package/dist/types/websocket/listener/recovery-lineage-sidecar.d.ts.map +1 -1
  61. package/dist/types/websocket/listener/turn-correlation.d.ts +0 -8
  62. package/dist/types/websocket/listener/turn-correlation.d.ts.map +1 -1
  63. package/dist/types/websocket/listener/turn-finished-replay.d.ts.map +1 -1
  64. package/dist/types/websocket/listener/types.d.ts +14 -1
  65. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  66. package/letta.js +840 -598
  67. package/npm-shrinkwrap.json +2 -2
  68. package/package.json +7 -4
  69. package/scripts/build-pypi.py +6 -6
  70. package/scripts/claude-watch/runtime-probe.test.ts +1 -1
  71. package/scripts/claude-watch/runtime-sandbox.ts +1 -1
  72. package/scripts/source-file-size-baseline.json +3 -3
  73. package/skills/scheduling-tasks/SKILL.md +1 -1
  74. package/skills/working-across-computers/references/connect-a-computer-for-remote-access.md +2 -2
  75. package/dist/types/websocket/listener/mcp-originator-scope.d.ts +0 -9
  76. package/dist/types/websocket/listener/mcp-originator-scope.d.ts.map +0 -1
package/letta.js CHANGED
@@ -5967,7 +5967,7 @@ var package_default;
5967
5967
  var init_package = __esm(() => {
5968
5968
  package_default = {
5969
5969
  name: "@letta-ai/letta-code",
5970
- version: "0.34.22",
5970
+ version: "0.34.24",
5971
5971
  lettaStartupLogProtocol: 1,
5972
5972
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5973
5973
  type: "module",
@@ -6110,7 +6110,7 @@ var init_package = __esm(() => {
6110
6110
  license: "Apache-2.0",
6111
6111
  engines: {
6112
6112
  bun: ">=1.3.2",
6113
- node: ">=22.19.0"
6113
+ node: "^22.23.4 || ^24.22.1 || ^26.12.1"
6114
6114
  },
6115
6115
  publishConfig: {
6116
6116
  access: "public"
@@ -6187,7 +6187,7 @@ var init_package = __esm(() => {
6187
6187
  prepublishOnly: "bun run runtime-graph:verify && bun run build",
6188
6188
  postinstall: `node scripts/postinstall-patches.js || echo letta: vendor patches skipped && node -e "try{require('fs').chmodSync(require('path').join(require.resolve('node-pty/package.json'),'../prebuilds/darwin-arm64/spawn-helper'),0o755)}catch(e){}" || true`,
6189
6189
  "mod-learning:memory-citations": "bun scripts/mod-learning/learn-mod.ts --env docs/examples/mods/learning/memory-citations.env.json",
6190
- "test:built-entrypoints": 'LETTA_TEST_CLI_BUNDLE="$PWD/letta.js" LETTA_TEST_BUILT_ARTIFACT=1 bun test src/cli/subcommands/lifecycle-output.test.ts src/websocket/app-server-dream.test.ts --timeout 60000'
6190
+ "test:built-entrypoints": 'LETTA_TEST_CLI_BUNDLE="$PWD/letta.js" LETTA_TEST_BUILT_ARTIFACT=1 bun test src/subcommand-exit.test.ts src/cli/subcommands/lifecycle-output.test.ts src/websocket/app-server-dream.test.ts --timeout 60000'
6191
6191
  },
6192
6192
  "lint-staged": {
6193
6193
  "*.{ts,tsx,js,jsx,json}": [
@@ -6242,7 +6242,10 @@ var init_package = __esm(() => {
6242
6242
  },
6243
6243
  lettaLifecycleProtocol: 1,
6244
6244
  lettaRuntimeGraphProtocol: 1,
6245
- lettaRuntimeGraphSha512: "sha512-xHwgmxBsCCiYY3o9bJl2DPx84chNPq1OsLFGac23DBEoU+h6hGCcX7rZezQxutCYhG/yFzjQ65L3pZ5j6BzNbg=="
6245
+ lettaRuntimeGraphSha512: "sha512-xHwgmxBsCCiYY3o9bJl2DPx84chNPq1OsLFGac23DBEoU+h6hGCcX7rZezQxutCYhG/yFzjQ65L3pZ5j6BzNbg==",
6246
+ patchedDependencies: {
6247
+ "@earendil-works/pi-ai@0.99.1": "patches/@earendil-works%2Fpi-ai@0.99.1.patch"
6248
+ }
6246
6249
  };
6247
6250
  });
6248
6251
 
@@ -26753,6 +26756,16 @@ function addCacheControlToTextContent(message, cacheControl) {
26753
26756
  }
26754
26757
  return false;
26755
26758
  }
26759
+ function isOpenAIHost(baseUrl) {
26760
+ if (!baseUrl)
26761
+ return true;
26762
+ try {
26763
+ const host = new URL(baseUrl).hostname.toLowerCase();
26764
+ return host === "api.openai.com" || host.endsWith(".azure.com");
26765
+ } catch {
26766
+ return true;
26767
+ }
26768
+ }
26756
26769
  function convertMessages(model, context, compat, options) {
26757
26770
  const normalizedContext = resolveTranscript(context, compat.supportsMidConvoSystemMessages);
26758
26771
  const params = [];
@@ -26769,7 +26782,7 @@ function convertMessages(model, context, compat, options) {
26769
26782
  const prefix = callId.slice(0, Math.max(1, 40 - hash.length - 1));
26770
26783
  return `${prefix}_${hash}`;
26771
26784
  }
26772
- if (model.provider === "openai")
26785
+ if (model.provider === "openai" && isOpenAIHost(model.baseUrl))
26773
26786
  return id.length > 40 ? id.slice(0, 40) : id;
26774
26787
  return id;
26775
26788
  };
@@ -109083,6 +109096,11 @@ var init_memory_filesystem2 = __esm(() => {
109083
109096
  MEMORY_TREE_MAX_CHILDREN_PER_DIR = DIRECTORY_LIMIT_DEFAULTS.memfsTreeMaxChildrenPerDir;
109084
109097
  });
109085
109098
 
109099
+ // src/backend/local/local-conversation-key.ts
109100
+ function localConversationKey(conversationId, agentId) {
109101
+ return conversationId === "default" ? `default:${agentId}` : `conversation:${conversationId}`;
109102
+ }
109103
+
109086
109104
  // src/backend/local/local-model-normalization.ts
109087
109105
  function supportedModelSettingsFromBody(bodyRecord) {
109088
109106
  const modelSettings = isRecord2(bodyRecord.model_settings) ? { ...bodyRecord.model_settings } : {};
@@ -112419,7 +112437,7 @@ class LocalStore {
112419
112437
  return conversation.agent_free ? this.executionAgentIdForConversation(conversationId) : conversation.agent_id;
112420
112438
  }
112421
112439
  conversationKey(conversationId, agentId) {
112422
- return conversationId === "default" ? `default:${agentId}` : `conversation:${conversationId}`;
112440
+ return localConversationKey(conversationId, agentId);
112423
112441
  }
112424
112442
  }
112425
112443
  var DEFAULT_LOCAL_AGENT_NAME = "Letta Code", DEFAULT_LOCAL_MODEL = "local/default", LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT2 = 128000, DEFAULT_LOCAL_CONVERSATION_ID_PREFIX = "local-conv-", DEFAULT_LOCAL_STORED_MESSAGE_ID_PREFIX = "letta-msg-", DEFAULT_LOCAL_UI_MESSAGE_ID_PREFIX = "ui-msg-", DEFAULT_RESIDENT_MESSAGE_TAIL_LIMIT = 100, LocalBackendNotFoundError;
@@ -113576,12 +113594,22 @@ function refreshInputOtidsForNewRequest(currentInput) {
113576
113594
  }));
113577
113595
  }
113578
113596
  function rebuildInputWithFreshDenials(currentInput, serverApprovals, denialReason, preserveMessageOtids = false) {
113597
+ const localResults = new Map;
113598
+ for (const item of currentInput) {
113599
+ if (item?.type === "approval") {
113600
+ for (const result of item.approvals ?? []) {
113601
+ if (result.tool_call_id) {
113602
+ localResults.set(result.tool_call_id, result);
113603
+ }
113604
+ }
113605
+ }
113606
+ }
113579
113607
  const content = currentInput.filter((item) => item?.type !== "approval");
113580
113608
  const stripped = preserveMessageOtids ? content : refreshInputOtidsForNewRequest(content);
113581
113609
  if (serverApprovals.length > 0) {
113582
113610
  const denials = {
113583
113611
  type: "approval",
113584
- approvals: buildFreshDenialApprovals(serverApprovals, denialReason),
113612
+ approvals: buildFreshDenialApprovals(serverApprovals, denialReason).map((denial) => localResults.get(denial.tool_call_id) ?? denial),
113585
113613
  otid: randomUUID9()
113586
113614
  };
113587
113615
  return [denials, ...stripped];
@@ -113684,7 +113712,7 @@ function selectChatGPTQuotaFailoverHandle(params) {
113684
113712
  const index = Math.min(Math.floor(random() * candidates2.length), candidates2.length - 1);
113685
113713
  return candidates2[index]?.handle ?? null;
113686
113714
  }
113687
- var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENTS, CONVERSATION_BUSY_RUN_ID_PATTERN, EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_RUN_ERROR_TYPES, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN, DEFAULT_TRANSIENT_RETRY_BASE_DELAY_MS = 1000, CLOUDFLARE_EDGE_52X_RETRY_BASE_DELAY_MS = 5000, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4, EMPTY_RESPONSE_RETRY_BASE_DELAY_MS = 500, STALE_APPROVAL_RECOVERY_DENIAL_REASON = "The agent harness automatically closed this stale pending tool call to recover from a client/server state desync: the server was still waiting on a result for it, but the harness had no matching tool execution in flight and no result was ever recorded. It was not denied by the user or a permissions policy. Re-issue the tool call if you still need it.", STARTED_TOOL_CALL_RECOVERY_DENIAL_REASON = "The agent harness closed this pending tool call while recovering from an interrupted turn. The call had started, but its result was not recorded, so it may or may not have run. Check whether its effect already happened before running it again.", CHATGPT_USAGE_LIMIT_FRAGMENT = "usage_limit_reached", CHATGPT_OAUTH_PROVIDER_TYPE2 = "chatgpt_oauth", BYOK_PROVIDER_CATEGORY = "byok";
113715
+ var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENTS, CONVERSATION_BUSY_RUN_ID_PATTERN, EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_RUN_ERROR_TYPES, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN, DEFAULT_TRANSIENT_RETRY_BASE_DELAY_MS = 1000, CLOUDFLARE_EDGE_52X_RETRY_BASE_DELAY_MS = 5000, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 1e4, EMPTY_RESPONSE_RETRY_BASE_DELAY_MS = 500, STALE_APPROVAL_RECOVERY_DENIAL_REASON = "The agent harness automatically closed this stale pending tool call to recover from a client/server state desync: the server was still waiting on a result for it, but the harness had no matching tool execution in flight and no result was ever recorded. It was not denied by the user or a permissions policy. The harness can't tell whether it ran, so check whether its effect already happened before running it again.", STARTED_TOOL_CALL_RECOVERY_DENIAL_REASON = "The agent harness closed this pending tool call while recovering from an interrupted turn. The call had started, but its result was not recorded, so it may or may not have run. Check whether its effect already happened before running it again.", CHATGPT_USAGE_LIMIT_FRAGMENT = "usage_limit_reached", CHATGPT_OAUTH_PROVIDER_TYPE2 = "chatgpt_oauth", BYOK_PROVIDER_CATEGORY = "byok";
113688
113716
  var init_turn_recovery_policy = __esm(() => {
113689
113717
  init_error_formatter();
113690
113718
  init_zai_errors();
@@ -114248,7 +114276,7 @@ class HeadlessBackend {
114248
114276
  }
114249
114277
  async cancelConversation(...args) {
114250
114278
  const [conversationIdOrAgentId] = args;
114251
- const runId = this.activeRunByConversation.get(conversationIdOrAgentId) ?? this.findActiveRunByAgentId(conversationIdOrAgentId);
114279
+ const runId = this.activeRunByConversation.get(localConversationKey(conversationIdOrAgentId, this.store.resolveAgentIdForConversation(conversationIdOrAgentId))) ?? this.activeRunByConversation.get(localConversationKey("default", conversationIdOrAgentId)) ?? this.findActiveRunByAgentId(conversationIdOrAgentId);
114252
114280
  const run = runId ? this.runs.get(runId) : undefined;
114253
114281
  if (run?.conversation_id && run.agent_id) {
114254
114282
  this.store.settleInterruptedToolCalls(run.conversation_id, {
@@ -114303,7 +114331,7 @@ class HeadlessBackend {
114303
114331
  }
114304
114332
  async cancelConversationRun(...args) {
114305
114333
  const [conversationId, requestedRunId] = args;
114306
- const runId = requestedRunId ?? this.activeRunByConversation.get(conversationId);
114334
+ const runId = requestedRunId ?? this.activeRunByConversation.get(localConversationKey(conversationId, this.store.resolveAgentIdForConversation(conversationId)));
114307
114335
  if (!runId)
114308
114336
  return {};
114309
114337
  const run = this.runs.get(runId);
@@ -114338,7 +114366,8 @@ class HeadlessBackend {
114338
114366
  if (options?.signal?.aborted) {
114339
114367
  throw new APIUserAbortError;
114340
114368
  }
114341
- const activeRunId = this.activeRunByConversation.get(conversationId);
114369
+ const turnAgentId = body.agent_id ?? this.store.resolveAgentIdForConversation(conversationId);
114370
+ const activeRunId = this.activeRunByConversation.get(localConversationKey(conversationId, turnAgentId));
114342
114371
  const activeRun = activeRunId ? this.runs.get(activeRunId) : undefined;
114343
114372
  if (activeRun && !isTerminalRun(activeRun)) {
114344
114373
  throw new Error(`Conversation ${conversationId} already has an active run (${activeRun.id})`);
@@ -114447,7 +114476,7 @@ class HeadlessBackend {
114447
114476
  }
114448
114477
  };
114449
114478
  this.runs.set(run.id, run);
114450
- this.activeRunByConversation.set(conversationId, run.id);
114479
+ this.activeRunByConversation.set(localConversationKey(conversationId, agentId), run.id);
114451
114480
  return run;
114452
114481
  }
114453
114482
  completeRun(runId, stopReason, errorInfo) {
@@ -114471,9 +114500,7 @@ class HeadlessBackend {
114471
114500
  }
114472
114501
  } : run.metadata
114473
114502
  });
114474
- if (run.conversation_id) {
114475
- this.activeRunByConversation.delete(run.conversation_id);
114476
- }
114503
+ this.releaseActiveRun(run);
114477
114504
  this.runControllerByRunId.delete(runId);
114478
114505
  this.runStartupPreemptByRunId.delete(runId);
114479
114506
  }
@@ -114500,9 +114527,7 @@ class HeadlessBackend {
114500
114527
  }
114501
114528
  }
114502
114529
  });
114503
- if (run.conversation_id) {
114504
- this.activeRunByConversation.delete(run.conversation_id);
114505
- }
114530
+ this.releaseActiveRun(run);
114506
114531
  this.runControllerByRunId.delete(runId);
114507
114532
  this.runStartupPreemptByRunId.delete(runId);
114508
114533
  }
@@ -114522,6 +114547,14 @@ class HeadlessBackend {
114522
114547
  const run = this.runs.get(runId);
114523
114548
  return run ? isTerminalRun(run) : false;
114524
114549
  }
114550
+ releaseActiveRun(run) {
114551
+ if (!run.conversation_id)
114552
+ return;
114553
+ const key = localConversationKey(run.conversation_id, run.agent_id);
114554
+ if (this.activeRunByConversation.get(key) === run.id) {
114555
+ this.activeRunByConversation.delete(key);
114556
+ }
114557
+ }
114525
114558
  findActiveRunByAgentId(agentId) {
114526
114559
  for (const [runId, run] of this.runs.entries()) {
114527
114560
  if (run.agent_id === agentId && !isTerminalRun(run))
@@ -117167,11 +117200,9 @@ function createUsageStatisticsChunk(usage, contextTokensEstimate) {
117167
117200
  const cachedInputTokens = usage?.cacheRead;
117168
117201
  const cacheWriteTokens = usage?.cacheWrite;
117169
117202
  const reasoningTokens = usage?.reasoning;
117170
- if (promptTokens === undefined && completionTokens === undefined && totalTokens === undefined && cachedInputTokens === undefined && cacheWriteTokens === undefined && reasoningTokens === undefined && contextTokens === undefined) {
117171
- return;
117172
- }
117173
117203
  return {
117174
117204
  message_type: "usage_statistics",
117205
+ step_count: 1,
117175
117206
  ...promptTokens !== undefined ? { prompt_tokens: promptTokens } : {},
117176
117207
  ...completionTokens !== undefined ? { completion_tokens: completionTokens } : {},
117177
117208
  ...totalTokens !== undefined ? { total_tokens: totalTokens } : {},
@@ -117284,11 +117315,8 @@ function createProviderLettaStream(events, contextTokensEstimate) {
117284
117315
  }
117285
117316
  if (part.type === "done") {
117286
117317
  if (!sawUsageStatistics) {
117287
- const usageChunk = createUsageStatisticsChunk(part.message.usage, contextTokensEstimate);
117288
- if (usageChunk) {
117289
- sawUsageStatistics = true;
117290
- yield usageChunk;
117291
- }
117318
+ sawUsageStatistics = true;
117319
+ yield createUsageStatisticsChunk(part.message.usage, contextTokensEstimate);
117292
117320
  }
117293
117321
  pendingStopReason = {
117294
117322
  message_type: "stop_reason",
@@ -163406,14 +163434,14 @@ function buildLatestVersionUrl(packageName, registryBaseUrl) {
163406
163434
  function buildInstallCommand(pm, env6 = process.env) {
163407
163435
  return `${pm} ${buildInstallArgs(pm, env6).join(" ")}`;
163408
163436
  }
163409
- function buildUpdateExecOptions(timeout, platform4 = process.platform) {
163437
+ function buildUpdateExecOptions(timeout = 0, platform4 = process.platform) {
163410
163438
  return {
163411
163439
  timeout,
163412
163440
  encoding: "utf8",
163413
163441
  shell: platform4 === "win32"
163414
163442
  };
163415
163443
  }
163416
- async function runUpdateCommand(command, args, timeout) {
163444
+ async function runUpdateCommand(command, args, timeout = 0) {
163417
163445
  return execFileAsync3(command, args, buildUpdateExecOptions(timeout));
163418
163446
  }
163419
163447
  function getResolvedEntrypoint() {
@@ -163616,7 +163644,7 @@ async function performUpdate(progressLog) {
163616
163644
  try {
163617
163645
  debugLog2(`Running ${installCmd}...`);
163618
163646
  progressLog?.(`Running update command: ${installCmd}`);
163619
- await runUpdateCommand(pm, installArgs, UPDATE_INSTALL_TIMEOUT_MS);
163647
+ await runUpdateCommand(pm, installArgs);
163620
163648
  debugLog2("Update completed successfully");
163621
163649
  progressLog?.("Update command completed successfully.");
163622
163650
  return { success: true };
@@ -163633,7 +163661,7 @@ async function performUpdate(progressLog) {
163633
163661
  debugLog2("ENOTEMPTY detected, attempting cleanup and retry...");
163634
163662
  await cleanupOrphanedDirs(globalPath);
163635
163663
  try {
163636
- await runUpdateCommand(pm, installArgs, UPDATE_INSTALL_TIMEOUT_MS);
163664
+ await runUpdateCommand(pm, installArgs);
163637
163665
  debugLog2("Update succeeded after cleanup retry");
163638
163666
  return { success: true };
163639
163667
  } catch (retryError) {
@@ -163661,7 +163689,7 @@ async function performUpdate(progressLog) {
163661
163689
  await cleanupOrphanedDirs(globalPath);
163662
163690
  }
163663
163691
  try {
163664
- await runUpdateCommand(pm, installArgs, UPDATE_INSTALL_TIMEOUT_MS);
163692
+ await runUpdateCommand(pm, installArgs);
163665
163693
  debugLog2("Update succeeded after race condition retry");
163666
163694
  return { success: true };
163667
163695
  } catch (retryError) {
@@ -163755,7 +163783,7 @@ async function manualUpdate(options) {
163755
163783
  To update manually: ${installCmd}`
163756
163784
  };
163757
163785
  }
163758
- var execFileAsync3, DEBUG, DEFAULT_UPDATE_PACKAGE_NAME = "@letta-ai/letta-code", DEFAULT_UPDATE_REGISTRY_BASE_URL = "https://registry.npmjs.org", UPDATE_PACKAGE_NAME_ENV = "LETTA_UPDATE_PACKAGE_NAME", UPDATE_REGISTRY_BASE_URL_ENV = "LETTA_UPDATE_REGISTRY_BASE_URL", UPDATE_INSTALL_REGISTRY_URL_ENV = "LETTA_UPDATE_INSTALL_REGISTRY_URL", DESKTOP_MANAGED_ENV = "LETTA_CODE_DESKTOP_MANAGED", INSTALL_ARG_PREFIX, VALID_PACKAGE_MANAGERS, NPM_PREFIX_TIMEOUT_MS = 5000, UPDATE_INSTALL_TIMEOUT_MS = 60000, PYTHON_UPDATE_COMMAND = "Upgrade with your installer: uv tool upgrade letta, pipx upgrade letta, or python -m pip install --upgrade letta";
163786
+ var execFileAsync3, DEBUG, DEFAULT_UPDATE_PACKAGE_NAME = "@letta-ai/letta-code", DEFAULT_UPDATE_REGISTRY_BASE_URL = "https://registry.npmjs.org", UPDATE_PACKAGE_NAME_ENV = "LETTA_UPDATE_PACKAGE_NAME", UPDATE_REGISTRY_BASE_URL_ENV = "LETTA_UPDATE_REGISTRY_BASE_URL", UPDATE_INSTALL_REGISTRY_URL_ENV = "LETTA_UPDATE_INSTALL_REGISTRY_URL", DESKTOP_MANAGED_ENV = "LETTA_CODE_DESKTOP_MANAGED", INSTALL_ARG_PREFIX, VALID_PACKAGE_MANAGERS, NPM_PREFIX_TIMEOUT_MS = 5000, PYTHON_UPDATE_COMMAND = "Upgrade with your installer: uv tool upgrade letta, pipx upgrade letta, or python -m pip install --upgrade letta";
163759
163787
  var init_auto_update = __esm(() => {
163760
163788
  init_error_reporting();
163761
163789
  init_version();
@@ -180737,9 +180765,12 @@ class ChannelControlRequestCoordinator {
180737
180765
  return true;
180738
180766
  }
180739
180767
  await this.clear(requestId);
180740
- if (result2 === "expired") {
180741
- await this.options.deliverReprompt(cloneEvent(pending.event), input, "That approval prompt expired before I could use your reply. Please ask the agent to try again.");
180742
- }
180768
+ if (result2 !== "expired")
180769
+ return true;
180770
+ const wasApproval = "decision" in parsed.response && parsed.response.decision?.behavior === "allow";
180771
+ if (!wasApproval)
180772
+ return false;
180773
+ await this.options.deliverReprompt(cloneEvent(pending.event), input, "That approval prompt expired before I could use your reply. Please ask the agent to try again.");
180743
180774
  return true;
180744
180775
  }
180745
180776
  async clear(requestId) {
@@ -181380,7 +181411,8 @@ function createChannelInboundRouter(deps) {
181380
181411
  content: formatChannelNotification(preparedMessage2),
181381
181412
  turnSources: [
181382
181413
  buildChannelTurnSource(discordResult.route, preparedMessage2)
181383
- ]
181414
+ ],
181415
+ defaultPermissionMode: config.defaultPermissionMode
181384
181416
  });
181385
181417
  return;
181386
181418
  }
@@ -181445,7 +181477,8 @@ function createChannelInboundRouter(deps) {
181445
181477
  deps.deliver({
181446
181478
  route,
181447
181479
  content,
181448
- turnSources: [buildChannelTurnSource(route, preparedMessage)]
181480
+ turnSources: [buildChannelTurnSource(route, preparedMessage)],
181481
+ ...isDiscordChannelAccount(config) || isSlackChannelAccount(config) ? { defaultPermissionMode: config.defaultPermissionMode } : {}
181449
181482
  });
181450
181483
  }
181451
181484
  return { handleInboundMessage };
@@ -193257,7 +193290,10 @@ var init_parse_interval = __esm(() => {
193257
193290
  });
193258
193291
 
193259
193292
  // src/cron/process-identity.ts
193293
+ import { execFileSync as execFileSync7 } from "node:child_process";
193260
193294
  import { readFileSync as readFileSync26 } from "node:fs";
193295
+ import { uptime } from "node:os";
193296
+ import { basename as basename15 } from "node:path";
193261
193297
  function readLinuxProcessIdentity(pid) {
193262
193298
  try {
193263
193299
  const stat5 = readFileSync26(`/proc/${pid}/stat`, "utf8");
@@ -193309,10 +193345,51 @@ function isProcessAlive2(pid, owner) {
193309
193345
  }
193310
193346
  }
193311
193347
  }
193348
+ if (pid === process.pid)
193349
+ return true;
193350
+ if (owner && pidReuseProbe.platform !== "linux") {
193351
+ return !isPidReusedSinceBoot(pid, owner.started_at);
193352
+ }
193312
193353
  return true;
193313
193354
  }
193314
- var readProcessIdentityOverride = null;
193315
- var init_process_identity = () => {};
193355
+ function isPidReusedSinceBoot(pid, startedAt) {
193356
+ const startedAtMs = startedAt ? Date.parse(startedAt) : Number.NaN;
193357
+ if (!Number.isFinite(startedAtMs) || startedAtMs >= pidReuseProbe.bootTimeMs() - BOOT_TIME_SLACK_MS) {
193358
+ return false;
193359
+ }
193360
+ const command = pidReuseProbe.getProcessCommand(pid);
193361
+ return Boolean(command) && !isLettaCommand(command ?? "");
193362
+ }
193363
+ function isLettaCommand(command) {
193364
+ if (/letta/i.test(command))
193365
+ return true;
193366
+ const script4 = process.argv[1];
193367
+ if (script4 && command.includes(script4))
193368
+ return true;
193369
+ const argv0 = command.split(/\s+/)[0] ?? "";
193370
+ return argv0 === process.execPath || basename15(argv0) === basename15(process.execPath);
193371
+ }
193372
+ var BOOT_TIME_SLACK_MS = 60000, defaultPidReuseProbe, pidReuseProbe, readProcessIdentityOverride = null;
193373
+ var init_process_identity = __esm(() => {
193374
+ defaultPidReuseProbe = {
193375
+ platform: process.platform,
193376
+ bootTimeMs: () => Date.now() - uptime() * 1000,
193377
+ getProcessCommand: (pid) => {
193378
+ if (process.platform === "win32")
193379
+ return null;
193380
+ try {
193381
+ return execFileSync7("ps", ["-p", String(pid), "-o", "command="], {
193382
+ encoding: "utf-8",
193383
+ timeout: 1000,
193384
+ stdio: ["ignore", "pipe", "ignore"]
193385
+ }).trim();
193386
+ } catch {
193387
+ return null;
193388
+ }
193389
+ }
193390
+ };
193391
+ pidReuseProbe = defaultPidReuseProbe;
193392
+ });
193316
193393
 
193317
193394
  // src/cron/cron-file.ts
193318
193395
  import { randomBytes as randomBytes2 } from "node:crypto";
@@ -210919,7 +210996,7 @@ var init_mcp_client = __esm(() => {
210919
210996
  init_streamableHttp();
210920
210997
  DEFAULT_CLIENT_INFO = {
210921
210998
  name: "letta-code",
210922
- version: "0.34.22"
210999
+ version: "0.34.24"
210923
211000
  };
210924
211001
  });
210925
211002
 
@@ -214052,7 +214129,7 @@ var init_cwd = __esm(() => {
214052
214129
  });
214053
214130
 
214054
214131
  // src/websocket/listener/durable-file-lock.ts
214055
- import { execFileSync as execFileSync7 } from "node:child_process";
214132
+ import { execFileSync as execFileSync8 } from "node:child_process";
214056
214133
  import { randomUUID as randomUUID29 } from "node:crypto";
214057
214134
  import {
214058
214135
  chmodSync as chmodSync5,
@@ -214071,7 +214148,7 @@ import {
214071
214148
  unlinkSync as unlinkSync7,
214072
214149
  writeFileSync as writeFileSync23
214073
214150
  } from "node:fs";
214074
- import { basename as basename15, dirname as dirname15, join as join43 } from "node:path";
214151
+ import { basename as basename16, dirname as dirname15, join as join43 } from "node:path";
214075
214152
  function installCandidateDirectory(candidatePath, lockPath, hooks) {
214076
214153
  mkdirSync27(lockPath, { mode: 448 });
214077
214154
  const directoryIdentity = pathIdentity(lockPath);
@@ -214121,7 +214198,7 @@ function fsyncDirectory(path12, platform5 = process.platform) {
214121
214198
  closeSync4(fd);
214122
214199
  }
214123
214200
  }
214124
- function getProcessStart(pid, platform5 = process.platform, run = (executable, args, options) => execFileSync7(executable, args, {
214201
+ function getProcessStart(pid, platform5 = process.platform, run = (executable, args, options) => execFileSync8(executable, args, {
214125
214202
  ...options,
214126
214203
  encoding: "utf8",
214127
214204
  windowsHide: true
@@ -214298,7 +214375,7 @@ function removeDeadOwner(lockPath, parent, ownerPath, afterOwnerUnlink) {
214298
214375
  return true;
214299
214376
  }
214300
214377
  function sweepDeadCandidates(lockPath, parent, isOwnerAlive, ignoredPath) {
214301
- const prefix = `${basename15(lockPath)}.candidate-`;
214378
+ const prefix = `${basename16(lockPath)}.candidate-`;
214302
214379
  const allCandidates = readdirSync9(parent, { withFileTypes: true }).filter((entry) => entry.name.startsWith(prefix) && entry.isDirectory());
214303
214380
  let hasUnresolvedCandidate = allCandidates.length > MAX_CANDIDATE_SWEEP;
214304
214381
  const candidates2 = allCandidates.slice(0, MAX_CANDIDATE_SWEEP);
@@ -217047,8 +217124,8 @@ function isGitExecutable(command) {
217047
217124
  }
217048
217125
  function isShellExecutable(command) {
217049
217126
  const normalized = command.replace(/\\/g, "/").toLowerCase();
217050
- const basename16 = path13.basename(normalized);
217051
- return basename16 === "bash" || basename16 === "sh" || basename16 === "zsh" || basename16 === "ash" || basename16 === "cmd.exe" || basename16.includes("powershell") || basename16.includes("pwsh");
217127
+ const basename17 = path13.basename(normalized);
217128
+ return basename17 === "bash" || basename17 === "sh" || basename17 === "zsh" || basename17 === "ash" || basename17 === "cmd.exe" || basename17.includes("powershell") || basename17.includes("pwsh");
217052
217129
  }
217053
217130
  function extractShellCommandArgument(launcher, startIndex) {
217054
217131
  const argIndex = launcher.findIndex((token2, index) => {
@@ -218133,7 +218210,7 @@ function detectShellContext(env6 = process.env, currentPlatform = platform6()) {
218133
218210
  var init_shell_context = () => {};
218134
218211
 
218135
218212
  // src/tools/impl/shell-launchers.ts
218136
- import { existsSync as existsSync35 } from "node:fs";
218213
+ import { lstatSync as lstatSync2 } from "node:fs";
218137
218214
  import { delimiter as delimiter3, isAbsolute as isAbsolute11, join as join48 } from "node:path";
218138
218215
  function isValidEnvAlias(name) {
218139
218216
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
@@ -218244,12 +218321,20 @@ function hasPathSeparator(executable) {
218244
218321
  return executable.includes("/") || executable.includes("\\");
218245
218322
  }
218246
218323
  function hasFileExtension(executable) {
218247
- const basename17 = executable.split(/[\\/]/).pop() ?? executable;
218248
- return /\.[^.]+$/.test(basename17);
218324
+ const basename18 = executable.split(/[\\/]/).pop() ?? executable;
218325
+ return /\.[^.]+$/.test(basename18);
218326
+ }
218327
+ function shellCandidateExists(candidate) {
218328
+ try {
218329
+ lstatSync2(candidate);
218330
+ return true;
218331
+ } catch {
218332
+ return false;
218333
+ }
218249
218334
  }
218250
218335
  function resolveExecutablePath(executable, env6) {
218251
218336
  if (isAbsolute11(executable) || hasPathSeparator(executable)) {
218252
- return existsSync35(executable) ? executable : null;
218337
+ return shellCandidateExists(executable) ? executable : null;
218253
218338
  }
218254
218339
  const pathDelimiter = process.platform === "win32" ? ";" : delimiter3;
218255
218340
  const pathEntries = pathEnvValue(env6).split(pathDelimiter).filter(Boolean);
@@ -218262,7 +218347,7 @@ function resolveExecutablePath(executable, env6) {
218262
218347
  for (const entry of pathEntries) {
218263
218348
  for (const name of executableNames) {
218264
218349
  const candidate = join48(entry, name);
218265
- if (existsSync35(candidate)) {
218350
+ if (shellCandidateExists(candidate)) {
218266
218351
  return candidate;
218267
218352
  }
218268
218353
  }
@@ -219069,7 +219154,7 @@ var SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
219069
219154
 
219070
219155
  // src/sandbox/availability.ts
219071
219156
  import { spawnSync as spawnSync5 } from "node:child_process";
219072
- import { existsSync as existsSync36 } from "node:fs";
219157
+ import { existsSync as existsSync35 } from "node:fs";
219073
219158
  import { delimiter as delimiter4, isAbsolute as isAbsolute12, join as join49 } from "node:path";
219074
219159
  function detectSandboxBackend(options = {}) {
219075
219160
  const platform7 = options.platform ?? process.platform;
@@ -219101,7 +219186,7 @@ function warnSandboxBackendUnavailable(availability, context3) {
219101
219186
  }
219102
219187
  function probe(platform7) {
219103
219188
  if (platform7 === "darwin") {
219104
- if (existsSync36(SANDBOX_EXEC_PATH)) {
219189
+ if (existsSync35(SANDBOX_EXEC_PATH)) {
219105
219190
  return { backend: "seatbelt", reason: "sandbox-exec available" };
219106
219191
  }
219107
219192
  return {
@@ -219136,13 +219221,13 @@ function probeBwrap() {
219136
219221
  return { backend: "bwrap", bwrapPath, reason: "bwrap available" };
219137
219222
  }
219138
219223
  function resolveExecutableOnPath(executable, envPath = process.env.PATH) {
219139
- if (isAbsolute12(executable) && existsSync36(executable))
219224
+ if (isAbsolute12(executable) && existsSync35(executable))
219140
219225
  return executable;
219141
219226
  for (const dir of (envPath ?? "").split(delimiter4)) {
219142
219227
  if (!dir)
219143
219228
  continue;
219144
219229
  const candidate = join49(dir, executable);
219145
- if (existsSync36(candidate))
219230
+ if (existsSync35(candidate))
219146
219231
  return candidate;
219147
219232
  }
219148
219233
  return null;
@@ -219183,7 +219268,7 @@ var init_policy = () => {};
219183
219268
 
219184
219269
  // src/permissions/memory-paths.ts
219185
219270
  import { homedir as homedir19 } from "node:os";
219186
- import { basename as basename17, dirname as dirname20, isAbsolute as isAbsolute13, resolve as resolve16 } from "node:path";
219271
+ import { basename as basename18, dirname as dirname20, isAbsolute as isAbsolute13, resolve as resolve16 } from "node:path";
219187
219272
  function normalizeMemoryPath(path15) {
219188
219273
  const resolvedPath = resolve16(expandHomePath(path15));
219189
219274
  const normalized = resolvedPath.replace(/\\/g, "/");
@@ -219228,7 +219313,7 @@ function addRootAndSiblingWorktree(root2, acc) {
219228
219313
  return;
219229
219314
  }
219230
219315
  acc.add(normalizedRoot);
219231
- const leaf = basename17(normalizedRoot);
219316
+ const leaf = basename18(normalizedRoot);
219232
219317
  if (leaf === "memory") {
219233
219318
  acc.add(normalizeMemoryPath(resolve16(dirname20(normalizedRoot), "memory-worktrees")));
219234
219319
  }
@@ -219309,9 +219394,9 @@ var init_memory_paths = __esm(() => {
219309
219394
  });
219310
219395
 
219311
219396
  // src/permissions/sandbox-policy.ts
219312
- import { existsSync as existsSync37, realpathSync as realpathSync5 } from "node:fs";
219397
+ import { existsSync as existsSync36, realpathSync as realpathSync5 } from "node:fs";
219313
219398
  import { homedir as homedir20 } from "node:os";
219314
- import { basename as basename18, dirname as dirname21, isAbsolute as isAbsolute14, join as join50, resolve as resolve17 } from "node:path";
219399
+ import { basename as basename19, dirname as dirname21, isAbsolute as isAbsolute14, join as join50, resolve as resolve17 } from "node:path";
219315
219400
  function getDefaultAgentsTreeRoot(homeDir = homedir20()) {
219316
219401
  return canonicalizeRoot(join50(homeDir, ".letta", "agents"));
219317
219402
  }
@@ -219330,8 +219415,8 @@ function canonicalizeRoot(input) {
219330
219415
  const abs = isAbsolute14(input) ? input : resolve17(input);
219331
219416
  let dir = abs;
219332
219417
  const tail2 = [];
219333
- while (!existsSync37(dir)) {
219334
- tail2.unshift(basename18(dir));
219418
+ while (!existsSync36(dir)) {
219419
+ tail2.unshift(basename19(dir));
219335
219420
  const parent = dirname21(dir);
219336
219421
  if (parent === dir) {
219337
219422
  return normalizeSandboxPath(abs);
@@ -219365,8 +219450,8 @@ function deriveSelfAgentRootsForTrees(memoryRoots, agentsTreeRoots = getCrossBac
219365
219450
  const canon = canonicalizeRoot(root2);
219366
219451
  const containingTree = canonicalTrees.find((tree) => canon !== tree && isWithinRoot(canon, tree));
219367
219452
  if (containingTree) {
219368
- const leaf = basename18(canon);
219369
- const parentLeaf = basename18(dirname21(canon));
219453
+ const leaf = basename19(canon);
219454
+ const parentLeaf = basename19(dirname21(canon));
219370
219455
  out.add(leaf === "memory" || leaf === "memory-worktrees" ? dirname21(canon) : parentLeaf === "memory-worktrees" || parentLeaf === "memory" && leaf === ".git" ? dirname21(dirname21(canon)) : canon);
219371
219456
  continue;
219372
219457
  }
@@ -220579,8 +220664,8 @@ function resolveRemovalTarget(rawTarget, cwd2, env6) {
220579
220664
  let target2 = expandEnvironment(rawTarget, env6).replace(/[),]+$/g, "").replace(/(?<=[\\/:])\$(?:env:)?[A-Za-z_][A-Za-z0-9_]*/gi, "").replaceAll("/", "\\");
220580
220665
  if (!target2 || target2 === "*")
220581
220666
  return null;
220582
- const basename19 = win323.basename(target2);
220583
- if (basename19.includes("*") || basename19.includes("?")) {
220667
+ const basename20 = win323.basename(target2);
220668
+ if (basename20.includes("*") || basename20.includes("?")) {
220584
220669
  target2 = win323.dirname(target2);
220585
220670
  }
220586
220671
  return win323.normalize(win323.resolve(cwd2, target2));
@@ -223861,10 +223946,10 @@ var init_memory_runtime = __esm(() => {
223861
223946
  });
223862
223947
 
223863
223948
  // src/tools/impl/memory.ts
223864
- import { execFileSync as execFileSync8 } from "node:child_process";
223949
+ import { execFileSync as execFileSync9 } from "node:child_process";
223865
223950
  import {
223866
223951
  closeSync as closeSync5,
223867
- existsSync as existsSync39,
223952
+ existsSync as existsSync38,
223868
223953
  openSync as openSync5,
223869
223954
  readdirSync as readdirSync13,
223870
223955
  readFileSync as readFileSync32,
@@ -223971,7 +224056,7 @@ function lastEditedByChild(dir, names2) {
223971
224056
  if (time3 > (edited.get(name) ?? 0))
223972
224057
  edited.set(name, time3);
223973
224058
  };
223974
- const git = (args) => execFileSync8("git", ["-C", dir, ...args], {
224059
+ const git = (args) => execFileSync9("git", ["-C", dir, ...args], {
223975
224060
  encoding: "utf8",
223976
224061
  timeout: 5000,
223977
224062
  maxBuffer: 64 * 1024 * 1024,
@@ -224056,7 +224141,7 @@ function renderDirectory(memoryDir, relPath, fullPath) {
224056
224141
  const open4 = `<memory_content path="${escapeXmlText2(relPath).replace(/"/g, "&quot;")}">`;
224057
224142
  const close = "</memory_content>";
224058
224143
  let head4;
224059
- if (existsSync39(indexPath)) {
224144
+ if (existsSync38(indexPath)) {
224060
224145
  const budget = Math.max(2000, LIMITS.READ_OUTPUT_CHARS - tailText.length - open4.length - close.length - 16);
224061
224146
  head4 = clampContent(readFileSync32(indexPath, "utf8").trimEnd(), indexPath, budget);
224062
224147
  } else {
@@ -224107,8 +224192,8 @@ async function memory2(args) {
224107
224192
  throw new Error(`skills/ is reserved for skills. Use Skill("${segments[1] ?? "<name>"}").`);
224108
224193
  }
224109
224194
  const fullPath = join52(memoryDir, ...segments);
224110
- if (!existsSync39(fullPath)) {
224111
- const candidates2 = !relPath.endsWith(".md") && existsSync39(`${fullPath}.md`) ? [`${relPath}.md`] : findByBasename(memoryDir, segments[segments.length - 1] ?? relPath);
224195
+ if (!existsSync38(fullPath)) {
224196
+ const candidates2 = !relPath.endsWith(".md") && existsSync38(`${fullPath}.md`) ? [`${relPath}.md`] : findByBasename(memoryDir, segments[segments.length - 1] ?? relPath);
224112
224197
  const hint = candidates2.length ? ` Did you mean ${candidates2.join(" or ")}? Paths are relative to the memory directory.` : "";
224113
224198
  throw new Error(`No memory at ${relPath}.${hint}`);
224114
224199
  }
@@ -227176,10 +227261,11 @@ var init_read_only_shell = __esm(() => {
227176
227261
  // src/permissions/checker.ts
227177
227262
  var exports_checker = {};
227178
227263
  __export(exports_checker, {
227264
+ isPathWithin: () => isPathWithin,
227179
227265
  checkPermissionWithHooks: () => checkPermissionWithHooks,
227180
227266
  checkPermission: () => checkPermission
227181
227267
  });
227182
- import { resolve as resolve24 } from "node:path";
227268
+ import { posix as posix3, resolve as resolve24, win32 as win324 } from "node:path";
227183
227269
  function envFlagEnabled(name) {
227184
227270
  const value = process.env[name];
227185
227271
  if (!value)
@@ -227542,15 +227628,25 @@ function checkPermissionForEngine(engine4, toolName2, toolArgs, permissions, wor
227542
227628
  trace
227543
227629
  };
227544
227630
  }
227631
+ function isPathWithin(child, root2, pathImpl = process.platform === "win32" ? win324 : posix3) {
227632
+ const caseInsensitive = pathImpl === win324;
227633
+ const normalizedChild = caseInsensitive ? child.toLowerCase() : child;
227634
+ const normalizedRoot = caseInsensitive ? root2.toLowerCase() : root2;
227635
+ const rel = pathImpl.relative(normalizedRoot, normalizedChild);
227636
+ if (rel === "") {
227637
+ return true;
227638
+ }
227639
+ return rel !== ".." && !rel.startsWith(`..${pathImpl.sep}`) && !pathImpl.isAbsolute(rel);
227640
+ }
227545
227641
  function isWithinAllowedDirectories(filePath, permissions, workingDirectory) {
227546
227642
  const absolutePath = resolve24(workingDirectory, filePath);
227547
- if (absolutePath.startsWith(workingDirectory)) {
227643
+ if (isPathWithin(absolutePath, resolve24(workingDirectory))) {
227548
227644
  return true;
227549
227645
  }
227550
227646
  if (permissions.additionalDirectories) {
227551
227647
  for (const dir of permissions.additionalDirectories) {
227552
227648
  const resolvedDir = resolve24(workingDirectory, dir);
227553
- if (absolutePath.startsWith(resolvedDir)) {
227649
+ if (isPathWithin(absolutePath, resolvedDir)) {
227554
227650
  return true;
227555
227651
  }
227556
227652
  }
@@ -228016,7 +228112,7 @@ __export(exports_analyzer, {
228016
228112
  analyzeApprovalContext: () => analyzeApprovalContext
228017
228113
  });
228018
228114
  import { homedir as homedir28 } from "node:os";
228019
- import { dirname as dirname23, relative as relative5, resolve as resolve26, win32 as win324 } from "node:path";
228115
+ import { dirname as dirname23, relative as relative5, resolve as resolve26, win32 as win325 } from "node:path";
228020
228116
  function normalizeOsPath(path18) {
228021
228117
  return path18.replace(/\\/g, "/");
228022
228118
  }
@@ -228025,24 +228121,24 @@ function isWindowsPath(path18) {
228025
228121
  }
228026
228122
  function resolvePathForContext(basePath, targetPath) {
228027
228123
  const windows = isWindowsPath(basePath) || isWindowsPath(targetPath);
228028
- return windows ? win324.resolve(basePath, targetPath) : resolve26(basePath, targetPath);
228124
+ return windows ? win325.resolve(basePath, targetPath) : resolve26(basePath, targetPath);
228029
228125
  }
228030
228126
  function relativePathForContext(basePath, targetPath) {
228031
228127
  const windows = isWindowsPath(basePath) || isWindowsPath(targetPath);
228032
- return windows ? win324.relative(basePath, targetPath) : relative5(basePath, targetPath);
228128
+ return windows ? win325.relative(basePath, targetPath) : relative5(basePath, targetPath);
228033
228129
  }
228034
228130
  function isPathWithinDirectory(path18, directory) {
228035
228131
  const windows = isWindowsPath(path18) || isWindowsPath(directory);
228036
228132
  const normalizedPath = normalizeOsPath(path18);
228037
228133
  const normalizedDirectory = normalizeOsPath(directory);
228038
- const relativePath = normalizeOsPath(windows ? win324.relative(normalizedDirectory.toLowerCase(), normalizedPath.toLowerCase()) : relativePathForContext(normalizedDirectory, normalizedPath));
228134
+ const relativePath = normalizeOsPath(windows ? win325.relative(normalizedDirectory.toLowerCase(), normalizedPath.toLowerCase()) : relativePathForContext(normalizedDirectory, normalizedPath));
228039
228135
  if (relativePath === "") {
228040
228136
  return true;
228041
228137
  }
228042
228138
  return !relativePath.startsWith("../") && relativePath !== ".." && !relativePath.startsWith("/") && !/^[a-zA-Z]:\//.test(relativePath);
228043
228139
  }
228044
228140
  function dirnameForContext(path18) {
228045
- return isWindowsPath(path18) ? win324.dirname(path18) : dirname23(path18);
228141
+ return isWindowsPath(path18) ? win325.dirname(path18) : dirname23(path18);
228046
228142
  }
228047
228143
  function formatAbsoluteRulePath(path18) {
228048
228144
  const normalized = normalizeOsPath(path18).replace(/\/+$/, "");
@@ -228938,7 +229034,7 @@ var init_approval_result_normalization = __esm(() => {
228938
229034
 
228939
229035
  // src/agent/client-skills-watcher.ts
228940
229036
  import {
228941
- existsSync as existsSync40,
229037
+ existsSync as existsSync39,
228942
229038
  readdirSync as readdirSync14,
228943
229039
  realpathSync as realpathSync7,
228944
229040
  statSync as statSync17,
@@ -229038,7 +229134,7 @@ class ClientSkillsWatcher {
229038
229134
  const watchPaths = new Set;
229039
229135
  let recursive = false;
229040
229136
  let awaitedChild = null;
229041
- if (existsSync40(root2)) {
229137
+ if (existsSync39(root2)) {
229042
229138
  recursive = true;
229043
229139
  watchPaths.add(root2);
229044
229140
  collectSymlinkDirectoryTargets(root2, watchPaths, new Set);
@@ -229091,7 +229187,7 @@ __export(exports_skills2, {
229091
229187
  PROJECT_SKILLS_DIR: () => PROJECT_SKILLS_DIR,
229092
229188
  GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR
229093
229189
  });
229094
- import { existsSync as existsSync41 } from "node:fs";
229190
+ import { existsSync as existsSync40 } from "node:fs";
229095
229191
  import { readdir as readdir4, readFile as readFile11, realpath as realpath3, stat as stat6 } from "node:fs/promises";
229096
229192
  import { dirname as dirname25, join as join54 } from "node:path";
229097
229193
  import { fileURLToPath as fileURLToPath6 } from "node:url";
@@ -229156,7 +229252,7 @@ async function getBundledSkills() {
229156
229252
  }
229157
229253
  async function discoverSkillsFromDir(skillsPath, source) {
229158
229254
  const errors6 = [];
229159
- if (!existsSync41(skillsPath)) {
229255
+ if (!existsSync40(skillsPath)) {
229160
229256
  return { skills: [], errors: [] };
229161
229257
  }
229162
229258
  const skills = [];
@@ -229328,7 +229424,7 @@ var init_skills5 = __esm(() => {
229328
229424
  });
229329
229425
 
229330
229426
  // src/agent/shared-memory-skills.ts
229331
- import { existsSync as existsSync42 } from "node:fs";
229427
+ import { existsSync as existsSync41 } from "node:fs";
229332
229428
  import { dirname as dirname26, join as join55 } from "node:path";
229333
229429
  function getAttachedRepositoriesCache() {
229334
229430
  const global2 = globalThis;
@@ -229421,7 +229517,7 @@ async function discoverSharedMemorySkills(skillsDirs) {
229421
229517
  const repositoryMount = dirname26(dir);
229422
229518
  if (isCheckoutPending(repositoryMount))
229423
229519
  continue;
229424
- if (!existsSync42(repositoryMount)) {
229520
+ if (!existsSync41(repositoryMount)) {
229425
229521
  errors6.push({
229426
229522
  path: repositoryMount,
229427
229523
  message: "Attached repository is not mounted locally"
@@ -229467,7 +229563,7 @@ __export(exports_client_skills, {
229467
229563
  buildClientSkillsUpdateReminder: () => buildClientSkillsUpdateReminder,
229468
229564
  buildClientSkillsPayload: () => buildClientSkillsPayload
229469
229565
  });
229470
- import { existsSync as existsSync43 } from "node:fs";
229566
+ import { existsSync as existsSync42 } from "node:fs";
229471
229567
  import { join as join56, resolve as resolve28 } from "node:path";
229472
229568
  function getCache2() {
229473
229569
  const global2 = globalThis;
@@ -229596,7 +229692,7 @@ function buildClientSkillsUpdateReminder(previous, current) {
229596
229692
  function getMemorySkillsDirs(agentId) {
229597
229693
  const dirs = new Set;
229598
229694
  const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
229599
- if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync43(scopedMemoryDir)) {
229695
+ if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync42(scopedMemoryDir)) {
229600
229696
  dirs.add(join56(scopedMemoryDir.trim(), "skills"));
229601
229697
  } else {
229602
229698
  const fallbackMemoryDir = (process.env.LETTA_MEMORY_DIR || process.env.MEMORY_DIR || "").trim();
@@ -231602,7 +231698,7 @@ var init_manager2 = __esm(async () => {
231602
231698
  import { createHash as createHash9, randomUUID as randomUUID31 } from "node:crypto";
231603
231699
  import {
231604
231700
  closeSync as closeSync6,
231605
- existsSync as existsSync44,
231701
+ existsSync as existsSync43,
231606
231702
  fsyncSync as fsyncSync3,
231607
231703
  mkdirSync as mkdirSync31,
231608
231704
  openSync as openSync6,
@@ -231655,7 +231751,7 @@ function mergeRecords(a2, b3) {
231655
231751
  }
231656
231752
  function readAuthorityRecords(path18) {
231657
231753
  const records = new Map;
231658
- if (!existsSync44(path18))
231754
+ if (!existsSync43(path18))
231659
231755
  return { records, degraded: false };
231660
231756
  try {
231661
231757
  const parsed = JSON.parse(readFileSync34(path18, "utf8"));
@@ -234976,7 +235072,7 @@ var init_memory_reminder = __esm(() => {
234976
235072
  });
234977
235073
 
234978
235074
  // src/agent/system-prompt-size.ts
234979
- import { existsSync as existsSync45, readdirSync as readdirSync15, readFileSync as readFileSync35 } from "node:fs";
235075
+ import { existsSync as existsSync44, readdirSync as readdirSync15, readFileSync as readFileSync35 } from "node:fs";
234980
235076
  import { join as join59 } from "node:path";
234981
235077
  function estimateSystemTokens(text2) {
234982
235078
  return Math.ceil(Buffer.byteLength(text2, "utf8") / SYSTEM_PROMPT_BYTES_PER_TOKEN);
@@ -234985,7 +235081,7 @@ function normalizePath3(value) {
234985
235081
  return value.replaceAll("\\", "/");
234986
235082
  }
234987
235083
  function walkMarkdownFiles(dir) {
234988
- if (!existsSync45(dir)) {
235084
+ if (!existsSync44(dir)) {
234989
235085
  return [];
234990
235086
  }
234991
235087
  const out = [];
@@ -235006,7 +235102,7 @@ function walkMarkdownFiles(dir) {
235006
235102
  return out;
235007
235103
  }
235008
235104
  function estimateSystemPromptSize(memoryDir, localMemfs = false) {
235009
- if (!existsSync45(memoryDir)) {
235105
+ if (!existsSync44(memoryDir)) {
235010
235106
  return { total: 0, files: [] };
235011
235107
  }
235012
235108
  const memoryFormat = detectMemoryFormat(memoryDir, localMemfs);
@@ -235319,7 +235415,7 @@ var init_background_process_snapshot = __esm(() => {
235319
235415
  });
235320
235416
 
235321
235417
  // src/websocket/listener/constants.ts
235322
- var MAX_RETRY_DURATION_MS, INITIAL_RETRY_DELAY_MS2 = 1000, MAX_RETRY_DELAY_MS = 30000, MAX_RETRY_ATTEMPTS, LISTENER_STREAM_OPEN_TIMEOUT_MS = 30000, LISTENER_HEARTBEAT_INTERVAL_MS = 30000, LISTENER_PONG_TIMEOUT_MS = 90000, SYSTEM_REMINDER_RE, LISTENER_STREAM_RESUME_POLICY, LLM_API_ERROR_MAX_RETRIES = 3, CLOUD_API_DEPLOYMENT_RECOVERY_MAX_ATTEMPTS = 3, EMPTY_RESPONSE_MAX_RETRIES = 2, MAX_PRE_STREAM_RECOVERY = 2, MAX_POST_STOP_APPROVAL_RECOVERY = 2;
235418
+ var CLOUD_ENVIRONMENT_NOT_FOUND_CLOSE_REASON = "Environment not found", MAX_RETRY_DURATION_MS, INITIAL_RETRY_DELAY_MS2 = 1000, MAX_RETRY_DELAY_MS = 30000, MAX_RETRY_ATTEMPTS, LISTENER_STREAM_OPEN_TIMEOUT_MS = 30000, LISTENER_HEARTBEAT_INTERVAL_MS = 30000, LISTENER_PONG_TIMEOUT_MS = 90000, SYSTEM_REMINDER_RE, LISTENER_STREAM_RESUME_POLICY, LLM_API_ERROR_MAX_RETRIES = 3, CLOUD_API_DEPLOYMENT_RECOVERY_MAX_ATTEMPTS = 3, EMPTY_RESPONSE_MAX_RETRIES = 2, MAX_PRE_STREAM_RECOVERY = 2, MAX_POST_STOP_APPROVAL_RECOVERY = 2;
235323
235419
  var init_constants3 = __esm(() => {
235324
235420
  MAX_RETRY_DURATION_MS = 5 * 60 * 1000;
235325
235421
  MAX_RETRY_ATTEMPTS = Math.ceil(Math.log2(MAX_RETRY_DURATION_MS / INITIAL_RETRY_DELAY_MS2));
@@ -235332,11 +235428,11 @@ var init_constants3 = __esm(() => {
235332
235428
  });
235333
235429
 
235334
235430
  // src/cli/helpers/git-context.ts
235335
- import { execFile as execFile13, execFileSync as execFileSync9 } from "node:child_process";
235431
+ import { execFile as execFile13, execFileSync as execFileSync10 } from "node:child_process";
235336
235432
  import { promisify as promisify13 } from "node:util";
235337
235433
  function runGit2(args, cwd2) {
235338
235434
  try {
235339
- return execFileSync9("git", args, {
235435
+ return execFileSync10("git", args, {
235340
235436
  cwd: cwd2,
235341
235437
  encoding: "utf-8",
235342
235438
  stdio: ["ignore", "pipe", "ignore"],
@@ -235346,15 +235442,20 @@ function runGit2(args, cwd2) {
235346
235442
  return null;
235347
235443
  }
235348
235444
  }
235349
- async function runGitAsync(args, cwd2) {
235445
+ async function runGitAsync(args, cwd2, timeoutMs) {
235350
235446
  try {
235351
235447
  const { stdout } = await execFileAsync8("git", args, {
235352
235448
  cwd: cwd2,
235353
235449
  encoding: "utf-8",
235354
- windowsHide: true
235450
+ windowsHide: true,
235451
+ timeout: timeoutMs,
235452
+ killSignal: "SIGKILL"
235355
235453
  });
235356
235454
  return stdout.trim();
235357
- } catch {
235455
+ } catch (error5) {
235456
+ if (error5?.killed) {
235457
+ throw new Error(`git ${args[0] ?? ""} timed out after ${timeoutMs}ms`);
235458
+ }
235358
235459
  return null;
235359
235460
  }
235360
235461
  }
@@ -235419,22 +235520,23 @@ function gatherGitContextSnapshot(options = {}) {
235419
235520
  gitUser
235420
235521
  };
235421
235522
  }
235422
- async function getGitContextAsync(cwd2) {
235423
- if (!await runGitAsync(["rev-parse", "--git-dir"], cwd2)) {
235523
+ async function getGitContextAsync(cwd2, options = {}) {
235524
+ const timeoutMs = options.timeoutMs ?? GIT_ASYNC_TIMEOUT_MS;
235525
+ if (!await runGitAsync(["rev-parse", "--git-dir"], cwd2, timeoutMs)) {
235424
235526
  return null;
235425
235527
  }
235426
- const branch = await runGitAsync(["branch", "--show-current"], cwd2);
235528
+ const branch = await runGitAsync(["branch", "--show-current"], cwd2, timeoutMs);
235427
235529
  const branchList = await runGitAsync([
235428
235530
  "branch",
235429
235531
  "--sort=-committerdate",
235430
235532
  "--format=%(refname:short)",
235431
235533
  "--no-color"
235432
- ], cwd2);
235534
+ ], cwd2, timeoutMs);
235433
235535
  const recentBranches = branchList ? branchList.split(`
235434
235536
  `).map((b3) => b3.trim()).filter((b3) => b3.length > 0 && b3 !== branch).slice(0, 10) : [];
235435
235537
  return { branch, recent_branches: recentBranches };
235436
235538
  }
235437
- var execFileAsync8;
235539
+ var execFileAsync8, GIT_ASYNC_TIMEOUT_MS = 1e4;
235438
235540
  var init_git_context = __esm(() => {
235439
235541
  execFileAsync8 = promisify13(execFile13);
235440
235542
  });
@@ -235472,7 +235574,7 @@ class DeviceGitContextCache {
235472
235574
  });
235473
235575
  this.prune();
235474
235576
  return value;
235475
- }).finally(() => {
235577
+ }, () => this.entries.get(cwd2)?.value ?? null).finally(() => {
235476
235578
  this.pending.delete(cwd2);
235477
235579
  });
235478
235580
  this.pending.set(cwd2, load);
@@ -235914,39 +236016,6 @@ function enqueueInboundUserMessage(runtime, incoming, actingUserId, options = {}
235914
236016
  }
235915
236017
 
235916
236018
  // src/websocket/listener/turn-correlation.ts
235917
- function mergeTurnCorrelationIndexes(...sources) {
235918
- const merged = new Map;
235919
- for (const source of sources) {
235920
- for (const [conversationKey, runs2] of source ?? []) {
235921
- const mergedRuns = merged.get(conversationKey) ?? new Map;
235922
- for (const [runId, clientMessageIds] of runs2) {
235923
- const mergedClientMessageIds = [
235924
- ...new Set([...mergedRuns.get(runId) ?? [], ...clientMessageIds])
235925
- ].slice(-MAX_CLIENT_MESSAGE_IDS_PER_RUN);
235926
- mergedRuns.delete(runId);
235927
- mergedRuns.set(runId, mergedClientMessageIds);
235928
- while (mergedRuns.size > MAX_RECENT_RUN_CORRELATIONS) {
235929
- const oldestRunId = mergedRuns.keys().next().value;
235930
- if (!oldestRunId)
235931
- break;
235932
- mergedRuns.delete(oldestRunId);
235933
- }
235934
- }
235935
- merged.delete(conversationKey);
235936
- merged.set(conversationKey, mergedRuns);
235937
- while (merged.size > MAX_RECENT_CONVERSATIONS) {
235938
- const oldestConversationKey = merged.keys().next().value;
235939
- if (!oldestConversationKey)
235940
- break;
235941
- merged.delete(oldestConversationKey);
235942
- }
235943
- }
235944
- }
235945
- return merged;
235946
- }
235947
- function cloneTurnCorrelationIndex(source) {
235948
- return mergeTurnCorrelationIndexes(source);
235949
- }
235950
236019
  function takeDequeuedClientMessageIds(runtime, batchId) {
235951
236020
  const clientMessageIds = runtime.dequeuedClientMessageIdsByBatchId.get(batchId) ?? [];
235952
236021
  runtime.dequeuedClientMessageIdsByBatchId.delete(batchId);
@@ -237007,7 +237076,7 @@ async function resolveDefaultBaseRef(repoRoot) {
237007
237076
  const branch = currentBranch.stdout.trim();
237008
237077
  return currentBranch.exitCode === 0 && branch && branch !== "HEAD" ? branch : "HEAD";
237009
237078
  }
237010
- function isPathWithin(child, parent) {
237079
+ function isPathWithin2(child, parent) {
237011
237080
  const resolvedChild = path21.resolve(child);
237012
237081
  const resolvedParent = path21.resolve(parent);
237013
237082
  return resolvedChild === resolvedParent || resolvedChild.startsWith(resolvedParent + path21.sep);
@@ -237368,7 +237437,7 @@ async function claimWorktreeLock(params) {
237368
237437
  if (result2.outcome === "conflict") {
237369
237438
  throw new Error(formatLockConflict(result2.heldBy, params.worktreePath));
237370
237439
  }
237371
- if (isPathWithin(params.previousCwd, params.managedDir)) {
237440
+ if (isPathWithin2(params.previousCwd, params.managedDir)) {
237372
237441
  const previousGitDir = await resolveWorktreeGitDir(params.previousCwd);
237373
237442
  if (previousGitDir && previousGitDir !== targetGitDir) {
237374
237443
  await releaseWorktreeLock({ worktreeGitDir: previousGitDir, owner });
@@ -238210,7 +238279,7 @@ No worktree session to exit.`, "success");
238210
238279
  }
238211
238280
  const primaryRoot = await resolvePrimaryWorktreeRoot(repoRoot);
238212
238281
  const managedDir = path24.join(primaryRoot, ".letta", "worktrees");
238213
- if (!isPathWithin(currentCwd, managedDir)) {
238282
+ if (!isPathWithin2(currentCwd, managedDir)) {
238214
238283
  return textResult([
238215
238284
  `Not in a managed worktree (current directory: ${currentCwd}).`,
238216
238285
  "ExitWorktree only applies to worktrees under .letta/worktrees/; nothing to do."
@@ -238667,8 +238736,8 @@ var require_constants2 = __commonJS((exports, module3) => {
238667
238736
  "@": { type: "at", open: "(?:", close: ")" }
238668
238737
  };
238669
238738
  },
238670
- globChars(win325) {
238671
- return win325 === true ? WINDOWS_CHARS : POSIX_CHARS;
238739
+ globChars(win326) {
238740
+ return win326 === true ? WINDOWS_CHARS : POSIX_CHARS;
238672
238741
  }
238673
238742
  };
238674
238743
  });
@@ -238676,7 +238745,7 @@ var require_constants2 = __commonJS((exports, module3) => {
238676
238745
  // node_modules/picomatch/lib/utils.js
238677
238746
  var require_utils2 = __commonJS((exports) => {
238678
238747
  var path27 = __require("path");
238679
- var win325 = process.platform === "win32";
238748
+ var win326 = process.platform === "win32";
238680
238749
  var {
238681
238750
  REGEX_BACKSLASH,
238682
238751
  REGEX_REMOVE_BACKSLASH,
@@ -238704,7 +238773,7 @@ var require_utils2 = __commonJS((exports) => {
238704
238773
  if (options && typeof options.windows === "boolean") {
238705
238774
  return options.windows;
238706
238775
  }
238707
- return win325 === true || path27.sep === "\\";
238776
+ return win326 === true || path27.sep === "\\";
238708
238777
  };
238709
238778
  exports.escapeLast = (input, char, lastIdx) => {
238710
238779
  const idx = input.lastIndexOf(char, lastIdx);
@@ -239089,8 +239158,8 @@ var require_parse3 = __commonJS((exports, module3) => {
239089
239158
  const bos = { type: "bos", value: "", output: opts.prepend || "" };
239090
239159
  const tokens = [bos];
239091
239160
  const capture = opts.capture ? "" : "?:";
239092
- const win325 = utils.isWindows(options);
239093
- const PLATFORM_CHARS = constants6.globChars(win325);
239161
+ const win326 = utils.isWindows(options);
239162
+ const PLATFORM_CHARS = constants6.globChars(win326);
239094
239163
  const EXTGLOB_CHARS = constants6.extglobChars(PLATFORM_CHARS);
239095
239164
  const {
239096
239165
  DOT_LITERAL,
@@ -239324,9 +239393,9 @@ var require_parse3 = __commonJS((exports, module3) => {
239324
239393
  const idx = prev.value.lastIndexOf("[");
239325
239394
  const pre = prev.value.slice(0, idx);
239326
239395
  const rest5 = prev.value.slice(idx + 2);
239327
- const posix3 = POSIX_REGEX_SOURCE[rest5];
239328
- if (posix3) {
239329
- prev.value = pre + posix3;
239396
+ const posix4 = POSIX_REGEX_SOURCE[rest5];
239397
+ if (posix4) {
239398
+ prev.value = pre + posix4;
239330
239399
  state2.backtrack = true;
239331
239400
  advance();
239332
239401
  if (!bos.output && tokens.indexOf(prev) === 1) {
@@ -239762,7 +239831,7 @@ var require_parse3 = __commonJS((exports, module3) => {
239762
239831
  throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max2}`);
239763
239832
  }
239764
239833
  input = REPLACEMENTS[input] || input;
239765
- const win325 = utils.isWindows(options);
239834
+ const win326 = utils.isWindows(options);
239766
239835
  const {
239767
239836
  DOT_LITERAL,
239768
239837
  SLASH_LITERAL,
@@ -239773,7 +239842,7 @@ var require_parse3 = __commonJS((exports, module3) => {
239773
239842
  NO_DOTS_SLASH,
239774
239843
  STAR,
239775
239844
  START_ANCHOR
239776
- } = constants6.globChars(win325);
239845
+ } = constants6.globChars(win326);
239777
239846
  const nodot = opts.dot ? NO_DOTS : NO_DOT;
239778
239847
  const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
239779
239848
  const capture = opts.capture ? "" : "?:";
@@ -239852,7 +239921,7 @@ var require_picomatch = __commonJS((exports, module3) => {
239852
239921
  throw new TypeError("Expected pattern to be a non-empty string");
239853
239922
  }
239854
239923
  const opts = options || {};
239855
- const posix3 = utils.isWindows(options);
239924
+ const posix4 = utils.isWindows(options);
239856
239925
  const regex4 = isState ? picomatch.compileRe(glob3, options) : picomatch.makeRe(glob3, options, false, true);
239857
239926
  const state2 = regex4.state;
239858
239927
  delete regex4.state;
@@ -239862,8 +239931,8 @@ var require_picomatch = __commonJS((exports, module3) => {
239862
239931
  isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
239863
239932
  }
239864
239933
  const matcher = (input, returnObject = false) => {
239865
- const { isMatch: isMatch2, match: match3, output } = picomatch.test(input, regex4, options, { glob: glob3, posix: posix3 });
239866
- const result2 = { glob: glob3, state: state2, regex: regex4, posix: posix3, input, output, match: match3, isMatch: isMatch2 };
239934
+ const { isMatch: isMatch2, match: match3, output } = picomatch.test(input, regex4, options, { glob: glob3, posix: posix4 });
239935
+ const result2 = { glob: glob3, state: state2, regex: regex4, posix: posix4, input, output, match: match3, isMatch: isMatch2 };
239867
239936
  if (typeof opts.onResult === "function") {
239868
239937
  opts.onResult(result2);
239869
239938
  }
@@ -239888,7 +239957,7 @@ var require_picomatch = __commonJS((exports, module3) => {
239888
239957
  }
239889
239958
  return matcher;
239890
239959
  };
239891
- picomatch.test = (input, regex4, options, { glob: glob3, posix: posix3 } = {}) => {
239960
+ picomatch.test = (input, regex4, options, { glob: glob3, posix: posix4 } = {}) => {
239892
239961
  if (typeof input !== "string") {
239893
239962
  throw new TypeError("Expected input to be a string");
239894
239963
  }
@@ -239896,7 +239965,7 @@ var require_picomatch = __commonJS((exports, module3) => {
239896
239965
  return { isMatch: false, output: "" };
239897
239966
  }
239898
239967
  const opts = options || {};
239899
- const format6 = opts.format || (posix3 ? utils.toPosixSlashes : null);
239968
+ const format6 = opts.format || (posix4 ? utils.toPosixSlashes : null);
239900
239969
  let match3 = input === glob3;
239901
239970
  let output = match3 && format6 ? format6(input) : input;
239902
239971
  if (match3 === false) {
@@ -239905,14 +239974,14 @@ var require_picomatch = __commonJS((exports, module3) => {
239905
239974
  }
239906
239975
  if (match3 === false || opts.capture === true) {
239907
239976
  if (opts.matchBase === true || opts.basename === true) {
239908
- match3 = picomatch.matchBase(input, regex4, options, posix3);
239977
+ match3 = picomatch.matchBase(input, regex4, options, posix4);
239909
239978
  } else {
239910
239979
  match3 = regex4.exec(output);
239911
239980
  }
239912
239981
  }
239913
239982
  return { isMatch: Boolean(match3), match: match3, output };
239914
239983
  };
239915
- picomatch.matchBase = (input, glob3, options, posix3 = utils.isWindows(options)) => {
239984
+ picomatch.matchBase = (input, glob3, options, posix4 = utils.isWindows(options)) => {
239916
239985
  const regex4 = glob3 instanceof RegExp ? glob3 : picomatch.makeRe(glob3, options);
239917
239986
  return regex4.test(path27.basename(input));
239918
239987
  };
@@ -240308,7 +240377,7 @@ function buildCloudScheduleInput(params) {
240308
240377
  }
240309
240378
  const targetDeviceId = params.targetDeviceId?.trim();
240310
240379
  if (targetDeviceId) {
240311
- notes.push(CLOUD_DEVICE_FALLBACK_NOTE);
240380
+ notes.push(CLOUD_DEVICE_OFFLINE_NOTE);
240312
240381
  }
240313
240382
  return {
240314
240383
  input: {
@@ -240322,7 +240391,7 @@ function buildCloudScheduleInput(params) {
240322
240391
  notes
240323
240392
  };
240324
240393
  }
240325
- var CLOUD_EXECUTION_TARGET = "cloud-sandbox", SYNTHETIC_CLOUD_DEVICE_ID = "__letta_cloud__", SYNTHETIC_LOCAL_PLACEHOLDER_ID = "local", CLOUD_CRON_UTC_NOTE = "Recurring Cloud schedules currently interpret cron expressions in UTC (timezone support is tracked in LET-9815).", CLOUD_DEVICE_FALLBACK_NOTE = "If the target computer is offline when the schedule fires, execution falls back to the agent's cloud sandbox.";
240394
+ var CLOUD_EXECUTION_TARGET = "cloud-sandbox", SYNTHETIC_CLOUD_DEVICE_ID = "__letta_cloud__", SYNTHETIC_LOCAL_PLACEHOLDER_ID = "local", CLOUD_CRON_UTC_NOTE = "Recurring Cloud schedules currently interpret cron expressions in UTC (timezone support is tracked in LET-9815).", CLOUD_DEVICE_OFFLINE_NOTE = "If the target computer is offline when the schedule fires, that occurrence fails (TARGET_DEVICE_UNAVAILABLE) and does not run; omit --computer to run in the Cloud sandbox.";
240326
240395
  var init_runner = __esm(() => {
240327
240396
  init_request();
240328
240397
  init_schedules();
@@ -243307,7 +243376,7 @@ class CodexAppServerClient {
243307
243376
  await this.request("initialize", {
243308
243377
  clientInfo: {
243309
243378
  name: "letta-code",
243310
- version: "0.34.22"
243379
+ version: "0.34.24"
243311
243380
  },
243312
243381
  capabilities: null
243313
243382
  });
@@ -244017,7 +244086,7 @@ var init_conversation_bootstrap = __esm(() => {
244017
244086
 
244018
244087
  // src/cli/helpers/session-context.ts
244019
244088
  import { platform as platform7 } from "node:os";
244020
- import { basename as basename20 } from "node:path";
244089
+ import { basename as basename21 } from "node:path";
244021
244090
  function getLocalTime() {
244022
244091
  const now2 = new Date;
244023
244092
  return now2.toLocaleString(undefined, {
@@ -244061,7 +244130,7 @@ function getGitInfo(cwd2) {
244061
244130
  };
244062
244131
  }
244063
244132
  function buildUnixShellLine(shellContext) {
244064
- const shellName = basename20(shellContext.displayName) || shellContext.displayName;
244133
+ const shellName = basename21(shellContext.displayName) || shellContext.displayName;
244065
244134
  return `- **Shell**: ${shellName}
244066
244135
  `;
244067
244136
  }
@@ -246771,7 +246840,7 @@ function isAppServerInfoResponseMessage(message2) {
246771
246840
  return false;
246772
246841
  }
246773
246842
  const capabilityRecord = capabilities;
246774
- return candidate.type === "app_server_info_response" && typeof candidate.request_id === "string" && candidate.request_id.length > 0 && candidate.success === true && (candidate.backend === "local" || candidate.backend === "api") && typeof candidate.letta_code_version === "string" && typeof candidate.protocol_version === "number" && Number.isInteger(candidate.protocol_version) && typeof capabilityRecord.agent_management === "boolean" && typeof capabilityRecord.conversation_management === "boolean" && typeof capabilityRecord.memory_management === "boolean" && typeof capabilityRecord.runtime_start === "boolean" && (capabilityRecord.agent_free_conversations === undefined || typeof capabilityRecord.agent_free_conversations === "boolean") && (capabilityRecord.launch_subagent === undefined || typeof capabilityRecord.launch_subagent === "boolean") && (capabilityRecord.launch_subagent_notify_caller === undefined || typeof capabilityRecord.launch_subagent_notify_caller === "boolean") && (capabilityRecord.subagent_message === undefined || typeof capabilityRecord.subagent_message === "boolean") && (capabilityRecord.runtime_workspace_sandbox === undefined || typeof capabilityRecord.runtime_workspace_sandbox === "boolean") && (capabilityRecord.runtime_external_tools_update === undefined || typeof capabilityRecord.runtime_external_tools_update === "boolean") && (capabilityRecord.structured_outputs === undefined || typeof capabilityRecord.structured_outputs === "boolean") && (capabilityRecord.write_file_base64 === undefined || typeof capabilityRecord.write_file_base64 === "boolean") && (capabilityRecord.mcp_originator_queue_isolation === undefined || typeof capabilityRecord.mcp_originator_queue_isolation === "boolean") && typeof capabilityRecord.split_channels === "boolean";
246843
+ return candidate.type === "app_server_info_response" && typeof candidate.request_id === "string" && candidate.request_id.length > 0 && candidate.success === true && (candidate.backend === "local" || candidate.backend === "api") && typeof candidate.letta_code_version === "string" && typeof candidate.protocol_version === "number" && Number.isInteger(candidate.protocol_version) && typeof capabilityRecord.agent_management === "boolean" && typeof capabilityRecord.conversation_management === "boolean" && typeof capabilityRecord.memory_management === "boolean" && typeof capabilityRecord.runtime_start === "boolean" && (capabilityRecord.agent_free_conversations === undefined || typeof capabilityRecord.agent_free_conversations === "boolean") && (capabilityRecord.launch_subagent === undefined || typeof capabilityRecord.launch_subagent === "boolean") && (capabilityRecord.launch_subagent_notify_caller === undefined || typeof capabilityRecord.launch_subagent_notify_caller === "boolean") && (capabilityRecord.subagent_message === undefined || typeof capabilityRecord.subagent_message === "boolean") && (capabilityRecord.runtime_workspace_sandbox === undefined || typeof capabilityRecord.runtime_workspace_sandbox === "boolean") && (capabilityRecord.runtime_external_tools_update === undefined || typeof capabilityRecord.runtime_external_tools_update === "boolean") && (capabilityRecord.structured_outputs === undefined || typeof capabilityRecord.structured_outputs === "boolean") && (capabilityRecord.write_file_base64 === undefined || typeof capabilityRecord.write_file_base64 === "boolean") && typeof capabilityRecord.split_channels === "boolean";
246775
246844
  }
246776
246845
  var APP_SERVER_PROTOCOL_VERSION = 1;
246777
246846
 
@@ -248740,7 +248809,7 @@ var init_memory_operation = __esm(() => {
248740
248809
  // src/agent/memory-worktree.ts
248741
248810
  import { execFile as execFileCb4 } from "node:child_process";
248742
248811
  import { randomUUID as randomUUID41 } from "node:crypto";
248743
- import { existsSync as existsSync46 } from "node:fs";
248812
+ import { existsSync as existsSync45 } from "node:fs";
248744
248813
  import { mkdir as mkdir12 } from "node:fs/promises";
248745
248814
  import { dirname as dirname29, isAbsolute as isAbsolute23, join as join67, resolve as resolve36 } from "node:path";
248746
248815
  import { promisify as promisify17 } from "node:util";
@@ -248932,7 +249001,7 @@ async function inspectReflectionMemoryWorktree(worktree) {
248932
249001
  };
248933
249002
  }
248934
249003
  async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName, options = {}) {
248935
- const removedWorktree = existsSync46(worktreeDir);
249004
+ const removedWorktree = existsSync45(worktreeDir);
248936
249005
  if (removedWorktree) {
248937
249006
  await runGit4(parentMemoryDir, [
248938
249007
  "worktree",
@@ -248948,7 +249017,7 @@ async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName
248948
249017
  ]);
248949
249018
  }
248950
249019
  async function finalizeReflectionMemoryWorktreeUnlocked(worktree, options) {
248951
- if (!existsSync46(worktree.worktreeDir) && options.knownNoChanges) {
249020
+ if (!existsSync45(worktree.worktreeDir) && options.knownNoChanges) {
248952
249021
  const branchHead = (await tryRunGit(worktree.parentMemoryDir, [
248953
249022
  "rev-parse",
248954
249023
  "--verify",
@@ -249135,7 +249204,7 @@ async function integrateMemoryWorkerWorktree(worktree, options = {}) {
249135
249204
  await cleanup(true);
249136
249205
  return { status: "no_changes" };
249137
249206
  }
249138
- if (existsSync46(worktree.worktreeDir)) {
249207
+ if (existsSync45(worktree.worktreeDir)) {
249139
249208
  await runGit4(worktree.parentMemoryDir, [
249140
249209
  "worktree",
249141
249210
  "remove",
@@ -250694,6 +250763,8 @@ function trackExternalFollowupCompletion(args) {
250694
250763
  existingAgentId: args.agentId,
250695
250764
  toolCallId: args.toolCallId,
250696
250765
  publishResult: args.publishResult,
250766
+ emitCompletionNotification: args.emitCompletionNotification,
250767
+ claimsParentRuntime: args.claimsParentRuntime,
250697
250768
  parentScope: args.parentScope,
250698
250769
  actingUserId: args.parentScope.actingUserId,
250699
250770
  deps: {
@@ -251198,7 +251269,7 @@ __export(exports_skill, {
251198
251269
  loadRenderedSkillContent: () => loadRenderedSkillContent,
251199
251270
  getResolvedSkillsDir: () => getResolvedSkillsDir
251200
251271
  });
251201
- import { existsSync as existsSync47, readdirSync as readdirSync17 } from "node:fs";
251272
+ import { existsSync as existsSync46, readdirSync as readdirSync17 } from "node:fs";
251202
251273
  import { readFile as readFile17 } from "node:fs/promises";
251203
251274
  import { dirname as dirname30, join as join68 } from "node:path";
251204
251275
  async function readSkillFromRoot(skillsRoot, skillId) {
@@ -251220,7 +251291,7 @@ async function readSkillFromRoot(skillsRoot, skillId) {
251220
251291
  function getMemorySkillsDirs2(agentId) {
251221
251292
  const dirs = new Set;
251222
251293
  const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
251223
- if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync47(scopedMemoryDir)) {
251294
+ if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync46(scopedMemoryDir)) {
251224
251295
  dirs.add(join68(scopedMemoryDir.trim(), "skills"));
251225
251296
  } else {
251226
251297
  const fallbackMemoryDir = (process.env.LETTA_MEMORY_DIR || process.env.MEMORY_DIR || "").trim();
@@ -252797,7 +252868,7 @@ var init_watch_pr = __esm(async () => {
252797
252868
  });
252798
252869
 
252799
252870
  // src/tools/workflow/sdk-loader.ts
252800
- import { existsSync as existsSync48, readFileSync as readFileSync37 } from "node:fs";
252871
+ import { existsSync as existsSync47, readFileSync as readFileSync37 } from "node:fs";
252801
252872
  import { createRequire as createRequire6 } from "node:module";
252802
252873
  import { dirname as dirname31, join as join69 } from "node:path";
252803
252874
  import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL3 } from "node:url";
@@ -252821,7 +252892,7 @@ function preferRunningCliForSubagents() {
252821
252892
  if (process.env.LETTA_CLI_PATH)
252822
252893
  return;
252823
252894
  const entry = process.argv[1];
252824
- if (entry && /(^|[\\/])letta\.js$/.test(entry) && existsSync48(entry)) {
252895
+ if (entry && /(^|[\\/])letta\.js$/.test(entry) && existsSync47(entry)) {
252825
252896
  process.env.LETTA_CLI_PATH = entry;
252826
252897
  }
252827
252898
  }
@@ -252852,7 +252923,7 @@ function probeInstalledSdkDirs(startDirs) {
252852
252923
  let dir = start2;
252853
252924
  while (true) {
252854
252925
  const candidate = join69(dir, "node_modules", ...SDK_PACKAGE.split("/"));
252855
- if (existsSync48(join69(candidate, "package.json")) && !found.includes(candidate)) {
252926
+ if (existsSync47(join69(candidate, "package.json")) && !found.includes(candidate)) {
252856
252927
  found.push(candidate);
252857
252928
  }
252858
252929
  const parent = dirname31(dir);
@@ -255325,15 +255396,28 @@ var init_interrupted_turn_schema = __esm(async () => {
255325
255396
  await init_teleport_protocol_inbound();
255326
255397
  });
255327
255398
 
255399
+ // src/utils/rename-sync-with-retry.ts
255400
+ import { renameSync as renameSync10 } from "node:fs";
255401
+ function renameSyncWithRetry(source, destination, platform9 = process.platform, rename3 = renameSync10) {
255402
+ const sleeper = new Int32Array(new SharedArrayBuffer(4));
255403
+ for (let attempt2 = 0;; attempt2++) {
255404
+ try {
255405
+ rename3(source, destination);
255406
+ return;
255407
+ } catch (error5) {
255408
+ const code2 = error5.code;
255409
+ if (platform9 !== "win32" || attempt2 >= 9 || !["EPERM", "EACCES", "EBUSY"].includes(code2 ?? "")) {
255410
+ throw error5;
255411
+ }
255412
+ Atomics.wait(sleeper, 0, 0, 10 * (attempt2 + 1));
255413
+ }
255414
+ }
255415
+ }
255416
+ var init_rename_sync_with_retry = () => {};
255417
+
255328
255418
  // src/websocket/listener/interrupted-turn-storage.ts
255329
255419
  import { createHash as createHash11 } from "node:crypto";
255330
- import {
255331
- closeSync as closeSync7,
255332
- fsyncSync as fsyncSync4,
255333
- openSync as openSync7,
255334
- renameSync as renameSync10,
255335
- writeFileSync as writeFileSync29
255336
- } from "node:fs";
255420
+ import { closeSync as closeSync7, fsyncSync as fsyncSync4, openSync as openSync7, writeFileSync as writeFileSync29 } from "node:fs";
255337
255421
  import { homedir as homedir35 } from "node:os";
255338
255422
  import { join as join71 } from "node:path";
255339
255423
  function writeInterruptedTurnRecordFile(temporary, destination, directory, record6, syncDirectory) {
@@ -255341,7 +255425,7 @@ function writeInterruptedTurnRecordFile(temporary, destination, directory, recor
255341
255425
  mode: 384,
255342
255426
  flush: true
255343
255427
  });
255344
- renameSync10(temporary, destination);
255428
+ renameSyncWithRetry(temporary, destination);
255345
255429
  syncDirectory(directory);
255346
255430
  }
255347
255431
  function fsyncInterruptedTurnDirectory(directory, platform9 = process.platform) {
@@ -255365,6 +255449,7 @@ function defaultInterruptedTurnDirectory() {
255365
255449
  }
255366
255450
  var init_interrupted_turn_storage = __esm(() => {
255367
255451
  init_server_url();
255452
+ init_rename_sync_with_retry();
255368
255453
  });
255369
255454
 
255370
255455
  // src/websocket/listener/recorded-tool-results.ts
@@ -255430,11 +255515,10 @@ function createRecoveryAuthorityGuard(dependencies4) {
255430
255515
  // src/websocket/listener/recovery-lineage-sidecar.ts
255431
255516
  import { createHash as createHash12, randomUUID as randomUUID44 } from "node:crypto";
255432
255517
  import {
255433
- existsSync as existsSync49,
255518
+ existsSync as existsSync48,
255434
255519
  mkdirSync as mkdirSync35,
255435
255520
  readdirSync as readdirSync18,
255436
255521
  readFileSync as readFileSync39,
255437
- renameSync as renameSync11,
255438
255522
  rmSync as rmSync18,
255439
255523
  statSync as statSync19,
255440
255524
  writeFileSync as writeFileSync30
@@ -255475,7 +255559,7 @@ function createRecoveryLineageSidecarAccess(params) {
255475
255559
  mode: 384,
255476
255560
  flush: true
255477
255561
  });
255478
- renameSync11(temporary, destination);
255562
+ renameSyncWithRetry(temporary, destination);
255479
255563
  params.syncDirectory(params.directory);
255480
255564
  } finally {
255481
255565
  rmSync18(temporary, { force: true });
@@ -255725,7 +255809,7 @@ function createRecoveryLineageSidecarAccess(params) {
255725
255809
  const removeMalformedOrphan = (file) => {
255726
255810
  const separator = file.indexOf(".recovery-");
255727
255811
  const mainFile = separator >= 0 ? file.slice(0, separator) : "";
255728
- if (!mainFile || existsSync49(join72(params.directory, mainFile)))
255812
+ if (!mainFile || existsSync48(join72(params.directory, mainFile)))
255729
255813
  return;
255730
255814
  try {
255731
255815
  rmSync18(join72(params.directory, file), { force: true });
@@ -255807,6 +255891,7 @@ function createRecoveryLineageSidecarAccess(params) {
255807
255891
  }
255808
255892
  var sidecarWriterInstanceId;
255809
255893
  var init_recovery_lineage_sidecar = __esm(async () => {
255894
+ init_rename_sync_with_retry();
255810
255895
  init_durable_file_lock();
255811
255896
  await init_interrupted_turn_schema();
255812
255897
  sidecarWriterInstanceId = randomUUID44();
@@ -255815,7 +255900,7 @@ var init_recovery_lineage_sidecar = __esm(async () => {
255815
255900
  // src/websocket/listener/interrupted-turn-record.ts
255816
255901
  import { randomUUID as randomUUID45 } from "node:crypto";
255817
255902
  import {
255818
- existsSync as existsSync50,
255903
+ existsSync as existsSync49,
255819
255904
  mkdirSync as mkdirSync36,
255820
255905
  readFileSync as readFileSync40,
255821
255906
  rmSync as rmSync19,
@@ -255872,7 +255957,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255872
255957
  const recoveryAuthority = createRecoveryAuthorityGuard({
255873
255958
  path: path32,
255874
255959
  readRecord: readRecord2,
255875
- exists: existsSync50,
255960
+ exists: existsSync49,
255876
255961
  acquire: (destination) => acquireDurableFileLock(destination, {
255877
255962
  waitMs: dependencies4.lockWaitMs
255878
255963
  }),
@@ -255906,7 +255991,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255906
255991
  });
255907
255992
  try {
255908
255993
  const current = readRecord2(destination);
255909
- if (!existsSync50(destination)) {
255994
+ if (!existsSync49(destination)) {
255910
255995
  removeSidecar(sidecar);
255911
255996
  } else if (current && current.recoveryClaimCompletion?.lineageId !== sidecar.lineageId) {
255912
255997
  removeSidecar(sidecar);
@@ -255931,7 +256016,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255931
256016
  },
255932
256017
  listDurableInputOwnership() {
255933
256018
  const snapshot2 = rawSnapshot();
255934
- return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) => existsSync50(path32(agentId, conversationId)), snapshot2.unreadableScopes);
256019
+ return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) => existsSync49(path32(agentId, conversationId)), snapshot2.unreadableScopes);
255935
256020
  },
255936
256021
  read(agentId, conversationId) {
255937
256022
  const current = readRecord2(path32(agentId, conversationId));
@@ -257490,7 +257575,7 @@ function socketForTransport(transport3) {
257490
257575
  }
257491
257576
  function refreshLegacySingleConnection(runtime) {
257492
257577
  const live = [...runtime.connections.values()].filter((connection) => isListenerTransportOpen(connection.writer));
257493
- const only = live.length === 1 ? live[0] : null;
257578
+ const only = live.find(({ id: id2 }) => id2 === runtime.connectionId) ?? (live.length === 1 ? live[0] : null);
257494
257579
  runtime.transport = runtime.processTransport ?? only?.writer ?? null;
257495
257580
  runtime.streamTransport = only?.streamWriter ?? null;
257496
257581
  runtime.socket = only ? socketForTransport(only.writer) : null;
@@ -257716,6 +257801,26 @@ function suspendListenerConnection(runtime, connectionId) {
257716
257801
  getResumeStates(runtime).set(connectionId, resumeState);
257717
257802
  return closed;
257718
257803
  }
257804
+ function resumeListenerConnectionIdentity(runtime, previousId, nextId2) {
257805
+ const states3 = getResumeStates(runtime);
257806
+ const previous = states3.get(previousId);
257807
+ states3.delete(previousId);
257808
+ if (previous)
257809
+ states3.set(nextId2, previous);
257810
+ for (const conversation of runtime.conversationRuntimes.values()) {
257811
+ for (const [itemId, message2] of conversation.queuedMessagesByItemId) {
257812
+ if (message2.connectionId === previousId) {
257813
+ conversation.queuedMessagesByItemId.set(itemId, {
257814
+ ...message2,
257815
+ connectionId: nextId2
257816
+ });
257817
+ }
257818
+ }
257819
+ if (conversation.activeConnectionId === previousId) {
257820
+ conversation.activeConnectionId = nextId2;
257821
+ }
257822
+ }
257823
+ }
257719
257824
 
257720
257825
  class ProcessRuntimeTransport {
257721
257826
  runtime;
@@ -257761,9 +257866,6 @@ var init_connection = __esm(async () => {
257761
257866
  });
257762
257867
 
257763
257868
  // src/queue/queue-runtime.ts
257764
- function isCoalescable(kind) {
257765
- return kind === "message" || kind === "task_notification" || kind === "cron_prompt" || kind === "mod_continue";
257766
- }
257767
257869
  function hasSameScope(a2, b3) {
257768
257870
  return (a2.agentId ?? null) === (b3.agentId ?? null) && (a2.conversationId ?? null) === (b3.conversationId ?? null);
257769
257871
  }
@@ -257785,7 +257887,7 @@ class QueueRuntime {
257785
257887
  this.callbacks = options.callbacks ?? {};
257786
257888
  }
257787
257889
  enqueue(input, options = {}) {
257788
- if (options.preserveExisting && (this.store.length >= this.hardMaxItems || this.store.length >= this.maxItems && isCoalescable(input.kind))) {
257890
+ if (options.preserveExisting && (this.store.length >= this.hardMaxItems || this.store.length >= this.maxItems)) {
257789
257891
  return null;
257790
257892
  }
257791
257893
  if (this.store.length >= this.hardMaxItems) {
@@ -257795,9 +257897,8 @@ class QueueRuntime {
257795
257897
  this.safeCallback("onDropped", phantom, "buffer_limit", this.store.length);
257796
257898
  return null;
257797
257899
  }
257798
- if (this.store.length >= this.maxItems && isCoalescable(input.kind)) {
257799
- const dropIdx = this.store.findIndex((i4) => isCoalescable(i4.kind));
257800
- const dropped = dropIdx !== -1 ? this.store[dropIdx] : undefined;
257900
+ if (this.store.length >= this.maxItems) {
257901
+ const dropped = this.store[0];
257801
257902
  if (dropped !== undefined) {
257802
257903
  if (!this.mutationAllowed("beforeDropped", dropped)) {
257803
257904
  const rejected = this.makeItem(input);
@@ -257806,7 +257907,7 @@ class QueueRuntime {
257806
257907
  this.safeCallback("onDropped", rejected, "buffer_limit", this.store.length);
257807
257908
  return null;
257808
257909
  }
257809
- this.store.splice(dropIdx, 1);
257910
+ this.store.shift();
257810
257911
  const item2 = this.makeItem(input);
257811
257912
  this.store.push(item2);
257812
257913
  this.safeCallback("onDropped", dropped, "buffer_limit", this.store.length);
@@ -257844,16 +257945,14 @@ class QueueRuntime {
257844
257945
  }
257845
257946
  const batch = [];
257846
257947
  const first = this.store.find((item) => !item.paused);
257847
- if (first && isCoalescable(first.kind)) {
257948
+ if (first) {
257848
257949
  for (const item of this.store) {
257849
257950
  if (item.paused)
257850
257951
  continue;
257851
- if (!isCoalescable(item.kind) || !hasSameScope(first, item))
257952
+ if (!hasSameScope(first, item))
257852
257953
  break;
257853
257954
  batch.push(item);
257854
257955
  }
257855
- } else if (first) {
257856
- batch.push(first);
257857
257956
  }
257858
257957
  if (batch.length === 0) {
257859
257958
  return null;
@@ -258246,12 +258345,11 @@ import { randomUUID as randomUUID46 } from "node:crypto";
258246
258345
  import {
258247
258346
  chmodSync as chmodSync7,
258248
258347
  closeSync as closeSync8,
258249
- existsSync as existsSync51,
258348
+ existsSync as existsSync50,
258250
258349
  fsyncSync as fsyncSync5,
258251
258350
  mkdirSync as mkdirSync37,
258252
258351
  openSync as openSync8,
258253
258352
  readFileSync as readFileSync41,
258254
- renameSync as renameSync12,
258255
258353
  statSync as statSync20,
258256
258354
  unlinkSync as unlinkSync11,
258257
258355
  writeFileSync as writeFileSync32
@@ -258390,7 +258488,7 @@ function validateDurableStore(value) {
258390
258488
  return value;
258391
258489
  }
258392
258490
  function readDurableStore(path32) {
258393
- if (!existsSync51(path32))
258491
+ if (!existsSync50(path32))
258394
258492
  return emptyDurableStore();
258395
258493
  const size2 = statSync20(path32).size;
258396
258494
  if (size2 > MAX_INPUT_DISPOSITION_STORE_BYTES) {
@@ -258418,7 +258516,7 @@ function writeDurableStore(path32, store3) {
258418
258516
  } finally {
258419
258517
  closeSync8(fd);
258420
258518
  }
258421
- renameSync12(temporaryPath, path32);
258519
+ renameSyncWithRetry(temporaryPath, path32);
258422
258520
  fsyncDirectory(dirname33(path32));
258423
258521
  } catch (error5) {
258424
258522
  try {
@@ -258820,6 +258918,7 @@ function loadDurableQueuedInputEntries(listener) {
258820
258918
  var ACCEPTED_INPUT_DISPOSITION_TTL_MS, MAX_ACCEPTED_INPUT_DISPOSITIONS_PER_SCOPE = 4096, MAX_ACCEPTED_INPUT_DISPOSITIONS = 65536, MAX_DURABLE_QUEUED_INPUT_BYTES, MAX_INPUT_DISPOSITION_STORE_BYTES, LOCK_WAIT_MS = 2000;
258821
258919
  var init_input_disposition = __esm(async () => {
258822
258920
  init_server_url();
258921
+ init_rename_sync_with_retry();
258823
258922
  init_durable_file_lock();
258824
258923
  init_input_disposition_capacity();
258825
258924
  init_input_disposition_expiry();
@@ -258844,7 +258943,6 @@ import {
258844
258943
  openSync as openSync9,
258845
258944
  readdirSync as readdirSync19,
258846
258945
  readFileSync as readFileSync42,
258847
- renameSync as renameSync13,
258848
258946
  rmSync as rmSync20,
258849
258947
  writeFileSync as writeFileSync33
258850
258948
  } from "node:fs";
@@ -258940,7 +259038,7 @@ function createTurnFinishedStore(directory = defaultDirectory(), options = {}) {
258940
259038
  mode: 384,
258941
259039
  flush: true
258942
259040
  });
258943
- renameSync13(temporary, destination);
259041
+ renameSyncWithRetry(temporary, destination);
258944
259042
  fsyncDirectory2(directory);
258945
259043
  } finally {
258946
259044
  rmSync20(temporary, { force: true });
@@ -259292,6 +259390,7 @@ var TurnFinishedCapacityError, MAX_PENDING_TERMINALS_PER_CONVERSATION = 64, DELI
259292
259390
  var init_turn_finished_replay = __esm(async () => {
259293
259391
  init_server_url();
259294
259392
  init_debug();
259393
+ init_rename_sync_with_retry();
259295
259394
  init_durable_file_lock();
259296
259395
  await __promiseAll([
259297
259396
  init_connection(),
@@ -259956,20 +260055,6 @@ var init_image_policy = __esm(async () => {
259956
260055
  await init_message_image_normalization();
259957
260056
  });
259958
260057
 
259959
- // src/websocket/listener/mcp-originator-scope.ts
259960
- function getMcpOriginatorScope(message2) {
259961
- return message2?.mcpOriginatorSuperRunId ? {
259962
- superRunId: message2.mcpOriginatorSuperRunId,
259963
- tokenPresent: message2.mcpOriginatorTokenPresent === true
259964
- } : null;
259965
- }
259966
- function sameMcpOriginatorScope(a2, b3) {
259967
- return a2 === null || b3 === null ? a2 === b3 : a2.superRunId === b3.superRunId && a2.tokenPresent === b3.tokenPresent;
259968
- }
259969
- function getEffectiveMcpOriginatorId(message2) {
259970
- return message2.mcpOriginatorTokenPresent === true ? message2.mcpOriginatorSuperRunId : undefined;
259971
- }
259972
-
259973
260058
  // src/websocket/listener/queue.ts
259974
260059
  function getQueueItemScope(item) {
259975
260060
  if (!item) {
@@ -260028,7 +260113,7 @@ function buildQueuedTurnMessage(runtime, batch) {
260028
260113
  messageOriginatorIds.push(undefined);
260029
260114
  originatorVotes.push(null);
260030
260115
  messages.push(withMessageAttribution({ role: "user", content: item.content }, item.actingUserId ?? undefined));
260031
- } else if (isCoalescable(item.kind) && "text" in item) {
260116
+ } else {
260032
260117
  messageOriginatorIds.push(undefined);
260033
260118
  originatorVotes.push(null);
260034
260119
  messages.push({
@@ -260093,15 +260178,12 @@ function shouldProcessInboundMessageDirectly(runtime, parsed) {
260093
260178
  });
260094
260179
  return getListenerBlockedReason(runtime.turnLifecycle.snapshot(), activeScope ? getPendingControlRequestCount(runtime.listener, activeScope) : 0) === null;
260095
260180
  }
260096
- function consumeQueuedTurn(runtime, activeScope) {
260181
+ function consumeQueuedTurn(runtime) {
260097
260182
  const queuedItems = runtime.queueRuntime.peekReady();
260098
260183
  const firstQueuedItem = queuedItems[0];
260099
- if (!firstQueuedItem || !isCoalescable(firstQueuedItem.kind)) {
260184
+ if (!firstQueuedItem) {
260100
260185
  return null;
260101
260186
  }
260102
- const firstScope = getMcpOriginatorScope(firstQueuedItem.kind === "message" ? runtime.queuedMessagesByItemId.get(firstQueuedItem.id) : undefined);
260103
- if (activeScope !== undefined && !sameMcpOriginatorScope(firstScope, activeScope))
260104
- return null;
260105
260187
  let queueLen = 0;
260106
260188
  let hasMessage = false;
260107
260189
  let hasTaskNotification = false;
@@ -260112,7 +260194,7 @@ function consumeQueuedTurn(runtime, activeScope) {
260112
260194
  let batchPreferences = JSON.stringify(getStoredClientPreferences(runtime.agentId, runtime.conversationId));
260113
260195
  const isNoCoalesce = (candidate) => candidate.kind === "message" && candidate.noCoalesce === true;
260114
260196
  for (const item of queuedItems) {
260115
- if (!isCoalescable(item.kind) || !hasSameQueueScope(firstQueuedItem, item) || !sameMcpOriginatorScope(firstScope, getMcpOriginatorScope(item.kind === "message" ? runtime.queuedMessagesByItemId.get(item.id) : undefined))) {
260197
+ if (!hasSameQueueScope(firstQueuedItem, item)) {
260116
260198
  break;
260117
260199
  }
260118
260200
  const incoming = runtime.queuedMessagesByItemId.get(item.id);
@@ -260158,6 +260240,25 @@ function consumeQueuedTurn(runtime, activeScope) {
260158
260240
  if (!dequeuedBatch) {
260159
260241
  return null;
260160
260242
  }
260243
+ for (const item of dequeuedBatch.items) {
260244
+ if (item.kind !== "cron_prompt")
260245
+ continue;
260246
+ try {
260247
+ const task2 = getTask(item.cronTaskId);
260248
+ if (task2 && task2.agent_id === item.agentId) {
260249
+ safeAppendCronRunLogForTask(task2, {
260250
+ status: "ok",
260251
+ outcome: "delivered",
260252
+ reason: "dequeued",
260253
+ queueItemId: item.id,
260254
+ conversationId: item.conversationId,
260255
+ runAtMs: Date.now()
260256
+ });
260257
+ }
260258
+ } catch (error5) {
260259
+ debugWarn("Cron", "Error reading task for dequeued cron prompt:", error5);
260260
+ }
260261
+ }
260161
260262
  const clientMessageIds = getDequeuedClientMessageIds(runtime, dequeuedBatch);
260162
260263
  const queuedTurn = buildQueuedTurnMessage(runtime, dequeuedBatch);
260163
260264
  if (!queuedTurn) {
@@ -260316,7 +260417,8 @@ function scheduleQueuePump(runtime, socket, opts, processQueuedTurn) {
260316
260417
  }
260317
260418
  var init_queue = __esm(async () => {
260318
260419
  init_mcp_originator_tokens();
260319
- init_queue_runtime();
260420
+ init_cron_file();
260421
+ init_run_log();
260320
260422
  init_error_reporting();
260321
260423
  init_debug();
260322
260424
  init_transport();
@@ -261074,6 +261176,11 @@ function taskMatchesCronSchedulerScope(task2, scope) {
261074
261176
  return true;
261075
261177
  return scope === "local" ? isLocalAgentId(task2.agent_id) : !isLocalAgentId(task2.agent_id);
261076
261178
  }
261179
+ function clearSlowLeaseRetry() {
261180
+ if (slowLeaseRetryTimer)
261181
+ clearInterval(slowLeaseRetryTimer);
261182
+ slowLeaseRetryTimer = null;
261183
+ }
261077
261184
  function logScheduler(opts, message2) {
261078
261185
  if (opts.onLog) {
261079
261186
  opts.onLog(`[Cron] ${message2}`);
@@ -261464,16 +261571,31 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
261464
261571
  try {
261465
261572
  token2 = claimSchedulerLease(scope);
261466
261573
  } catch (err) {
261574
+ if (slowLeaseRetryTimer)
261575
+ return;
261467
261576
  if (_retryCount < MAX_LEASE_RETRIES) {
261468
261577
  logScheduler(opts, `Could not claim scheduler lease (attempt ${_retryCount + 1}/${MAX_LEASE_RETRIES + 1}): ${err instanceof Error ? err.message : err}`);
261469
261578
  logScheduler(opts, "Cron tasks will not fire until the scheduler starts. Retrying...");
261470
261579
  setTimeout(() => startScheduler(socket, opts, processQueuedTurn, _retryCount + 1), LEASE_RETRY_MS);
261471
261580
  } else {
261472
261581
  logScheduler(opts, `Failed to claim scheduler lease after ${MAX_LEASE_RETRIES + 1} attempts. Cron tasks will not fire.`);
261473
- logScheduler(opts, "Another process may hold the lease. Restart Letta Code to retry.");
261582
+ logScheduler(opts, `Another process may hold the lease. Retrying every ${SLOW_LEASE_RETRY_MS / 60000} minutes.`);
261583
+ slowLeaseRetryTimer = setInterval(() => {
261584
+ const ctx = listenerFireContext;
261585
+ if (!ctx || schedulerState) {
261586
+ clearSlowLeaseRetry();
261587
+ return;
261588
+ }
261589
+ startScheduler(ctx.socket, ctx.opts, ctx.processQueuedTurn, _retryCount);
261590
+ }, SLOW_LEASE_RETRY_MS);
261591
+ slowLeaseRetryTimer.unref?.();
261474
261592
  }
261475
261593
  return;
261476
261594
  }
261595
+ if (slowLeaseRetryTimer) {
261596
+ clearSlowLeaseRetry();
261597
+ logScheduler(opts, "Claimed scheduler lease on slow retry.");
261598
+ }
261477
261599
  const now2 = new Date;
261478
261600
  const state2 = {
261479
261601
  token: token2,
@@ -261521,6 +261643,7 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
261521
261643
  }
261522
261644
  function stopScheduler() {
261523
261645
  listenerFireContext = null;
261646
+ clearSlowLeaseRetry();
261524
261647
  if (!schedulerState)
261525
261648
  return;
261526
261649
  clearInterval(schedulerState.tickInterval);
@@ -261534,7 +261657,7 @@ function stopScheduler() {
261534
261657
  } catch {}
261535
261658
  schedulerState = null;
261536
261659
  }
261537
- var schedulerState = null, CRON_SCHEDULER_SCOPE_ENV = "LETTA_CRON_SCHEDULER_SCOPE", listenerFireContext = null, TICK_INTERVAL_MS = 60000, GC_INTERVAL_MS, TOMBSTONE_HEARTBEAT_MS = 1000, LEASE_RETRY_MS = 30000, MAX_LEASE_RETRIES = 3, NEW_CONVERSATION_TARGET = "new";
261660
+ var schedulerState = null, CRON_SCHEDULER_SCOPE_ENV = "LETTA_CRON_SCHEDULER_SCOPE", listenerFireContext = null, TICK_INTERVAL_MS = 60000, GC_INTERVAL_MS, TOMBSTONE_HEARTBEAT_MS = 1000, LEASE_RETRY_MS = 30000, MAX_LEASE_RETRIES = 3, SLOW_LEASE_RETRY_MS, slowLeaseRetryTimer = null, NEW_CONVERSATION_TARGET = "new";
261538
261661
  var init_scheduler = __esm(async () => {
261539
261662
  init_backend2();
261540
261663
  init_debug();
@@ -261552,6 +261675,7 @@ var init_scheduler = __esm(async () => {
261552
261675
  init_runtime6()
261553
261676
  ]);
261554
261677
  GC_INTERVAL_MS = 60 * 60000;
261678
+ SLOW_LEASE_RETRY_MS = 5 * 60000;
261555
261679
  });
261556
261680
 
261557
261681
  // src/cron/index.ts
@@ -261654,8 +261778,9 @@ Add options:
261654
261778
  conversation; "default" for the agent default)
261655
261779
  --computer <id> (managed Cloud sandbox only) Run on a connected
261656
261780
  external computer (deviceId from \`letta computers
261657
- list\`). Falls back to the Cloud sandbox if that
261658
- computer is offline at fire time.
261781
+ list\`). If that computer is offline at fire
261782
+ time, that run fails (no Cloud sandbox fallback);
261783
+ omit --computer to run in the Cloud sandbox.
261659
261784
 
261660
261785
  List/filter options:
261661
261786
  --agent <id> Filter by agent ID
@@ -261880,7 +262005,7 @@ async function handleCloudAdd(params) {
261880
262005
  output.notes = notes;
261881
262006
  }
261882
262007
  console.log(JSON.stringify(output, null, 2));
261883
- console.error(targetDeviceId ? `Created Cloud schedule: it fires from the cloud and runs on computer "${targetDeviceId}" (sandbox fallback if offline).` : "Created Cloud schedule: it fires from the cloud and runs in this agent's managed cloud sandbox (survives local shutdown).");
262008
+ console.error(targetDeviceId ? `Created Cloud schedule: it fires from the cloud and runs on computer "${targetDeviceId}" (if it is offline at fire time, that run fails; no sandbox fallback).` : "Created Cloud schedule: it fires from the cloud and runs in this agent's managed cloud sandbox (survives local shutdown).");
261884
262009
  return 0;
261885
262010
  } catch (err) {
261886
262011
  console.error(`Error: failed to create Cloud schedule: ${err instanceof Error ? err.message : String(err)}`);
@@ -264248,6 +264373,11 @@ var init_listen_first_run_welcome = __esm(async () => {
264248
264373
  await init_AnimatedLogo();
264249
264374
  });
264250
264375
 
264376
+ // src/cli/subcommands/listen-output-mode.ts
264377
+ function shouldUseNonInteractiveListenerOutput(debugMode, lifecycleOutput, stdoutIsTTY = process.stdout.isTTY) {
264378
+ return debugMode || lifecycleOutput || !stdoutIsTTY;
264379
+ }
264380
+
264251
264381
  // src/cli/subcommands/listen-process-anchor.ts
264252
264382
  import { MessageChannel as MessageChannel2 } from "node:worker_threads";
264253
264383
  function createMessageChannelProcessAnchor() {
@@ -264305,7 +264435,7 @@ function printListenUsage() {
264305
264435
  }
264306
264436
 
264307
264437
  // src/cli/subcommands/listener-readiness.ts
264308
- async function completeListenerConnectionStartup(expectedConnection, readiness, startGateway = async () => {}) {
264438
+ async function completeListenerConnectionStartup(expectedConnection, readiness, startGateway = async () => {}, onGatewayError = console.error) {
264309
264439
  const { getActiveRuntime: getActiveRuntime2 } = await init_runtime6().then(() => exports_runtime);
264310
264440
  const runtime = getActiveRuntime2();
264311
264441
  const connection = runtime?.connections.get(expectedConnection.id);
@@ -264315,12 +264445,12 @@ async function completeListenerConnectionStartup(expectedConnection, readiness,
264315
264445
  const { isListenerTransportOpen: isListenerTransportOpen2 } = await Promise.resolve().then(() => (init_transport(), exports_transport));
264316
264446
  if (!isListenerTransportOpen2(connection.writer))
264317
264447
  return false;
264318
- await startGateway();
264319
264448
  if (getActiveRuntime2()?.connections.get(connection.id) !== connection)
264320
264449
  return false;
264321
264450
  if (!connection.initialized || !connection.ingressReady || connection.cancellation.signal.aborted || !isListenerTransportOpen2(connection.writer))
264322
264451
  return false;
264323
264452
  readiness.completeCloudStartup(epoch);
264453
+ Promise.resolve().then(startGateway).catch(onGatewayError);
264324
264454
  return true;
264325
264455
  }
264326
264456
  function applyGatewayLifecycleReadiness(readiness, event) {
@@ -264473,7 +264603,7 @@ var init_service_protocol = __esm(() => {
264473
264603
  // src/websocket/listen-log.ts
264474
264604
  import {
264475
264605
  appendFileSync as appendFileSync8,
264476
- existsSync as existsSync52,
264606
+ existsSync as existsSync51,
264477
264607
  mkdirSync as mkdirSync39,
264478
264608
  readdirSync as readdirSync20,
264479
264609
  unlinkSync as unlinkSync12
@@ -264493,7 +264623,7 @@ function formatFileTimestamp(now2) {
264493
264623
  }
264494
264624
  function pruneOldLogs(dir, maxFiles) {
264495
264625
  try {
264496
- if (!existsSync52(dir))
264626
+ if (!existsSync51(dir))
264497
264627
  return;
264498
264628
  const files = readdirSync20(dir).filter((f4) => f4.endsWith(".log")).sort();
264499
264629
  if (files.length >= maxFiles) {
@@ -264545,7 +264675,7 @@ class RemoteSessionLog {
264545
264675
  const previous = this.path;
264546
264676
  this.rotation += 1;
264547
264677
  this.path = this.freshPath();
264548
- while (existsSync52(this.path)) {
264678
+ while (existsSync51(this.path)) {
264549
264679
  this.rotation += 1;
264550
264680
  this.path = this.freshPath();
264551
264681
  }
@@ -264569,7 +264699,7 @@ class RemoteSessionLog {
264569
264699
  if (this.dirCreated)
264570
264700
  return;
264571
264701
  try {
264572
- if (!existsSync52(this.dir)) {
264702
+ if (!existsSync51(this.dir)) {
264573
264703
  mkdirSync39(this.dir, { recursive: true });
264574
264704
  }
264575
264705
  this.dirCreated = true;
@@ -265178,9 +265308,10 @@ var init_auth3 = __esm(() => {
265178
265308
  });
265179
265309
 
265180
265310
  // src/websocket/listener/manual-instance-lock.ts
265311
+ import { execFileSync as execFileSync11 } from "node:child_process";
265181
265312
  import { createHash as createHash15, randomUUID as randomUUID48 } from "node:crypto";
265182
265313
  import { link as link4, mkdir as mkdir13, readFile as readFile21, rm as rm11, unlink as unlink3, writeFile as writeFile15 } from "node:fs/promises";
265183
- import { homedir as homedir39 } from "node:os";
265314
+ import { homedir as homedir39, uptime as uptime2 } from "node:os";
265184
265315
  import path32 from "node:path";
265185
265316
  function hasErrorCode3(error5, code2) {
265186
265317
  return typeof error5 === "object" && error5 !== null && "code" in error5 && error5.code === code2;
@@ -265193,6 +265324,32 @@ function defaultIsProcessAlive2(pid) {
265193
265324
  return !hasErrorCode3(error5, "ESRCH");
265194
265325
  }
265195
265326
  }
265327
+ function getDefaultBootTimeMs() {
265328
+ return Date.now() - uptime2() * 1000;
265329
+ }
265330
+ function defaultGetProcessCommand(pid) {
265331
+ if (process.platform === "win32")
265332
+ return null;
265333
+ try {
265334
+ return execFileSync11("ps", ["-p", String(pid), "-o", "command="], {
265335
+ encoding: "utf-8",
265336
+ timeout: 1000,
265337
+ stdio: ["ignore", "pipe", "ignore"]
265338
+ }).trim();
265339
+ } catch {
265340
+ return null;
265341
+ }
265342
+ }
265343
+ function isOwnerAlive2(record6, deps) {
265344
+ if (!deps.isProcessAlive(record6.pid))
265345
+ return false;
265346
+ const acquiredAtMs = Date.parse(record6.acquiredAt);
265347
+ if (!Number.isFinite(acquiredAtMs) || acquiredAtMs >= deps.bootTimeMs - BOOT_TIME_SLACK_MS2) {
265348
+ return true;
265349
+ }
265350
+ const command = deps.getProcessCommand(record6.pid);
265351
+ return !command || /letta/i.test(command);
265352
+ }
265196
265353
  function getDefaultLockRoot() {
265197
265354
  return path32.join(process.env.HOME || homedir39(), ".letta");
265198
265355
  }
@@ -265277,7 +265434,7 @@ async function recoverDeadOwner(lockPath, staleContents, recoveryOwnerContents,
265277
265434
  if (!claimOwner) {
265278
265435
  throw new ManualListenerLockUnavailableError(`Listener lock recovery record is invalid: ${claimPath}`, lockPath);
265279
265436
  }
265280
- if (deps.isProcessAlive(claimOwner.pid)) {
265437
+ if (isOwnerAlive2(claimOwner, deps)) {
265281
265438
  return false;
265282
265439
  }
265283
265440
  }
@@ -265308,6 +265465,8 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265308
265465
  processId: process.pid,
265309
265466
  ownerToken: randomUUID48(),
265310
265467
  isProcessAlive: defaultIsProcessAlive2,
265468
+ bootTimeMs: getDefaultBootTimeMs(),
265469
+ getProcessCommand: defaultGetProcessCommand,
265311
265470
  ...overrides
265312
265471
  };
265313
265472
  const listenerLockDir = path32.join(deps.lockRoot, "listeners");
@@ -265367,7 +265526,7 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265367
265526
  if (!incumbent) {
265368
265527
  throw new ManualListenerLockUnavailableError(`Listener lock is corrupt or belongs to an incompatible version: ${lockPath}`, lockPath);
265369
265528
  }
265370
- if (deps.isProcessAlive(incumbent.pid)) {
265529
+ if (isOwnerAlive2(incumbent, deps)) {
265371
265530
  throw new ManualListenerAlreadyRunningError(incumbent.pid, lockPath);
265372
265531
  }
265373
265532
  const recovered = await recoverDeadOwner(lockPath, incumbentContents, ownerContents, scopeHash, deps);
@@ -265376,7 +265535,7 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265376
265535
  }
265377
265536
  }
265378
265537
  }
265379
- var RECOVERY_MAX_DEPTH2 = 64, ManualListenerAlreadyRunningError, ManualListenerLockUnavailableError;
265538
+ var RECOVERY_MAX_DEPTH2 = 64, BOOT_TIME_SLACK_MS2 = 60000, ManualListenerAlreadyRunningError, ManualListenerLockUnavailableError;
265380
265539
  var init_manual_instance_lock = __esm(() => {
265381
265540
  ManualListenerAlreadyRunningError = class ManualListenerAlreadyRunningError extends Error {
265382
265541
  holderPid;
@@ -267608,10 +267767,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267608
267767
  const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
267609
267768
  const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
267610
267769
  const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
267611
- const { existsSync: existsSync53, statSync: statSync22 } = await import("node:fs");
267612
- const { join: join78, posix: posix3 } = await import("node:path");
267770
+ const { existsSync: existsSync52, statSync: statSync22 } = await import("node:fs");
267771
+ const { join: join78, posix: posix4 } = await import("node:path");
267613
267772
  const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
267614
- let memfsInitialized = existsSync53(join78(memoryRoot, ".git"));
267773
+ let memfsInitialized = existsSync52(join78(memoryRoot, ".git"));
267615
267774
  const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
267616
267775
  if (!memfsEnabled) {
267617
267776
  safeSocketSend(socket, {
@@ -267629,7 +267788,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267629
267788
  await ensureLocalMemfsCheckout2(parsed.agent_id, {
267630
267789
  pullOnExistingRepo: true
267631
267790
  });
267632
- memfsInitialized = existsSync53(join78(memoryRoot, ".git"));
267791
+ memfsInitialized = existsSync52(join78(memoryRoot, ".git"));
267633
267792
  if (!memfsInitialized) {
267634
267793
  throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
267635
267794
  }
@@ -267658,8 +267817,8 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267658
267817
  if (!target2) {
267659
267818
  return null;
267660
267819
  }
267661
- const sourceDir = posix3.dirname(sourcePath.replace(/\\/g, "/"));
267662
- const candidate = target2.startsWith("./") || target2.startsWith("../") ? posix3.normalize(posix3.join(sourceDir, target2)) : posix3.normalize(target2.startsWith("/") ? target2.slice(1) : target2);
267820
+ const sourceDir = posix4.dirname(sourcePath.replace(/\\/g, "/"));
267821
+ const candidate = target2.startsWith("./") || target2.startsWith("../") ? posix4.normalize(posix4.join(sourceDir, target2)) : posix4.normalize(target2.startsWith("/") ? target2.slice(1) : target2);
267663
267822
  if (!candidate || candidate.startsWith("../") || candidate === "." || candidate === "..") {
267664
267823
  return null;
267665
267824
  }
@@ -267667,10 +267826,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267667
267826
  const candidates2 = new Set([withExtension]);
267668
267827
  const isExplicitRelative = target2.startsWith("./") || target2.startsWith("../");
267669
267828
  if (!isExplicitRelative && !target2.startsWith("/") && sourceDir && sourceDir !== ".") {
267670
- candidates2.add(posix3.normalize(posix3.join(sourceDir, withExtension)));
267829
+ candidates2.add(posix4.normalize(posix4.join(sourceDir, withExtension)));
267671
267830
  }
267672
267831
  if (!withExtension.startsWith("system/")) {
267673
- candidates2.add(posix3.normalize(`system/${withExtension}`));
267832
+ candidates2.add(posix4.normalize(`system/${withExtension}`));
267674
267833
  }
267675
267834
  for (const resolved2 of candidates2) {
267676
267835
  if (allPaths.has(resolved2)) {
@@ -267929,7 +268088,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
267929
268088
  isMemfsEnabledOnServer: isMemfsEnabledOnServer2
267930
268089
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
267931
268090
  const { readFile: readFile22 } = await import("node:fs/promises");
267932
- const { existsSync: existsSync53 } = await import("node:fs");
268091
+ const { existsSync: existsSync52 } = await import("node:fs");
267933
268092
  const { isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
267934
268093
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
267935
268094
  sendFailure("path must be a non-empty relative path");
@@ -267942,14 +268101,14 @@ function handleMemoryProtocolCommand(parsed, context3) {
267942
268101
  sendFailure("path must resolve inside the memory root");
267943
268102
  return;
267944
268103
  }
267945
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268104
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
267946
268105
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
267947
268106
  if (!enabled) {
267948
268107
  sendFailure("memfs is not enabled for this agent");
267949
268108
  return;
267950
268109
  }
267951
268110
  await ensureLocalMemfsCheckout2(parsed.agent_id);
267952
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268111
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
267953
268112
  sendFailure("failed to initialize local memory checkout");
267954
268113
  return;
267955
268114
  }
@@ -267995,7 +268154,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
267995
268154
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
267996
268155
  const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
267997
268156
  const { writeFile: writeFile16, mkdir: mkdir14 } = await import("node:fs/promises");
267998
- const { existsSync: existsSync53 } = await import("node:fs");
268157
+ const { existsSync: existsSync52 } = await import("node:fs");
267999
268158
  const { dirname: dirname34, isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
268000
268159
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
268001
268160
  sendFailure("write_memory_file: path must be a non-empty relative path");
@@ -268008,14 +268167,14 @@ function handleMemoryProtocolCommand(parsed, context3) {
268008
268167
  sendFailure("write_memory_file: path must resolve inside the memory root");
268009
268168
  return;
268010
268169
  }
268011
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268170
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268012
268171
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
268013
268172
  if (!enabled) {
268014
268173
  sendFailure("write_memory_file: memfs is not enabled for this agent");
268015
268174
  return;
268016
268175
  }
268017
268176
  await ensureLocalMemfsCheckout2(parsed.agent_id);
268018
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268177
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268019
268178
  sendFailure("write_memory_file: failed to initialize local memory checkout");
268020
268179
  return;
268021
268180
  }
@@ -268093,7 +268252,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
268093
268252
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
268094
268253
  const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
268095
268254
  const { unlink: unlink4 } = await import("node:fs/promises");
268096
- const { existsSync: existsSync53 } = await import("node:fs");
268255
+ const { existsSync: existsSync52 } = await import("node:fs");
268097
268256
  const { isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
268098
268257
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
268099
268258
  sendFailure("delete_memory_file: path must be a non-empty relative path");
@@ -268106,21 +268265,21 @@ function handleMemoryProtocolCommand(parsed, context3) {
268106
268265
  sendFailure("delete_memory_file: path must resolve inside the memory root");
268107
268266
  return;
268108
268267
  }
268109
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268268
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268110
268269
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
268111
268270
  if (!enabled) {
268112
268271
  sendFailure("delete_memory_file: memfs is not enabled for this agent");
268113
268272
  return;
268114
268273
  }
268115
268274
  await ensureLocalMemfsCheckout2(parsed.agent_id);
268116
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268275
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268117
268276
  sendFailure("delete_memory_file: failed to initialize local memory checkout");
268118
268277
  return;
268119
268278
  }
268120
268279
  }
268121
268280
  const pathspec = rel.split(sep8).join("/");
268122
268281
  const removeIfPresent = async () => {
268123
- if (!existsSync53(absolutePath))
268282
+ if (!existsSync52(absolutePath))
268124
268283
  return false;
268125
268284
  await unlink4(absolutePath);
268126
268285
  return true;
@@ -268315,7 +268474,7 @@ __export(exports_remote_model_catalog, {
268315
268474
  applyCatalogModels: () => applyCatalogModels,
268316
268475
  __testResetRemoteModelCatalog: () => __testResetRemoteModelCatalog
268317
268476
  });
268318
- import { existsSync as existsSync53, mkdirSync as mkdirSync40, readFileSync as readFileSync44, writeFileSync as writeFileSync34 } from "node:fs";
268477
+ import { existsSync as existsSync52, mkdirSync as mkdirSync40, readFileSync as readFileSync44, writeFileSync as writeFileSync34 } from "node:fs";
268319
268478
  import { homedir as homedir40 } from "node:os";
268320
268479
  import { dirname as dirname34, join as join78 } from "node:path";
268321
268480
  function catalogCachePath() {
@@ -268419,7 +268578,7 @@ function persistCatalogCache(entries2, source) {
268419
268578
  function loadPersistedModelCatalog(source) {
268420
268579
  try {
268421
268580
  const path33 = catalogCachePath();
268422
- if (!existsSync53(path33)) {
268581
+ if (!existsSync52(path33)) {
268423
268582
  return false;
268424
268583
  }
268425
268584
  const parsed = JSON.parse(readFileSync44(path33, "utf-8"));
@@ -269112,7 +269271,7 @@ function recordStaleHandleUse(collector, owner, capability, onDiagnostic) {
269112
269271
  var MOD_DIAGNOSTICS_MAX_COUNT = 200, MOD_DIAGNOSTICS_RESET_COUNT = 50, MOD_DYNAMIC_CONTEXT_MIGRATION_HINT = "Dynamic context is now passed as ctx to commands, tools, events, permissions, and UI renderers. Use ctx.agent, ctx.cwd, ctx.conversation, ctx.model, etc.", MOD_LETTA_GET_CONTEXT_MIGRATION_HINT = "letta.getContext has been removed. Activation has no dynamic invocation context. Move dynamic work into a command, tool, event, permission, status, or statusline callback that receives ctx, or use explicit/global state such as process.cwd() for activation-time background work.", MOD_CTX_GET_CONTEXT_MIGRATION_HINT = "ctx.getContext has been removed. Use ctx directly; scoped fields are available as ctx.agent, ctx.cwd, ctx.conversation, ctx.model, etc.", MOD_GENERIC_GET_CONTEXT_MIGRATION_HINT = "getContext helpers have been removed. If this is callback ctx, use ctx directly; if activation/background code needs runtime state, move it into a callback that receives ctx or use explicit/global state such as process.cwd().";
269113
269272
 
269114
269273
  // src/mods/paths.ts
269115
- import { existsSync as existsSync54 } from "node:fs";
269274
+ import { existsSync as existsSync53 } from "node:fs";
269116
269275
  import { homedir as homedir41 } from "node:os";
269117
269276
  import path33 from "node:path";
269118
269277
  function getGlobalModsDirectory(homeDirectory = homedir41()) {
@@ -269126,10 +269285,10 @@ function resolveDefaultGlobalModsDirectory(homeDirectory = homedir41(), env6 = p
269126
269285
  if (environmentDirectory)
269127
269286
  return environmentDirectory;
269128
269287
  const modsDirectory = getGlobalModsDirectory(homeDirectory);
269129
- if (existsSync54(modsDirectory))
269288
+ if (existsSync53(modsDirectory))
269130
269289
  return modsDirectory;
269131
269290
  const legacyDirectory = getLegacyGlobalExtensionsDirectory(homeDirectory);
269132
- if (existsSync54(legacyDirectory))
269291
+ if (existsSync53(legacyDirectory))
269133
269292
  return legacyDirectory;
269134
269293
  return modsDirectory;
269135
269294
  }
@@ -377136,10 +377295,10 @@ ${lanes.join(`
377136
377295
  }
377137
377296
  function getDefaultLibFilePriority(a2) {
377138
377297
  if (containsPath(defaultLibraryPath, a2.fileName, false)) {
377139
- const basename21 = getBaseFileName(a2.fileName);
377140
- if (basename21 === "lib.d.ts" || basename21 === "lib.es6.d.ts")
377298
+ const basename22 = getBaseFileName(a2.fileName);
377299
+ if (basename22 === "lib.d.ts" || basename22 === "lib.es6.d.ts")
377141
377300
  return 0;
377142
- const name = removeSuffix(removePrefix(basename21, "lib."), ".d.ts");
377301
+ const name = removeSuffix(removePrefix(basename22, "lib."), ".d.ts");
377143
377302
  const index = libs.indexOf(name);
377144
377303
  if (index !== -1)
377145
377304
  return index + 1;
@@ -429702,8 +429861,8 @@ ${options.prefix}` : `
429702
429861
  }
429703
429862
  };
429704
429863
  for (const file of files) {
429705
- const basename21 = getBaseFileName(file);
429706
- if (basename21 === "package.json" || basename21 === "bower.json") {
429864
+ const basename22 = getBaseFileName(file);
429865
+ if (basename22 === "package.json" || basename22 === "bower.json") {
429707
429866
  createProjectWatcher(file, "FileWatcher");
429708
429867
  continue;
429709
429868
  }
@@ -432580,8 +432739,8 @@ All files are: ${JSON.stringify(names2)}`, "Err");
432580
432739
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
432581
432740
  if (!fileOrDirectoryPath)
432582
432741
  return;
432583
- const basename21 = getBaseFileName(fileOrDirectoryPath);
432584
- if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename21 === "package.json" || basename21 === "node_modules")) {
432742
+ const basename22 = getBaseFileName(fileOrDirectoryPath);
432743
+ if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename22 === "package.json" || basename22 === "node_modules")) {
432585
432744
  result3.affectedModuleSpecifierCacheProjects.forEach((project) => {
432586
432745
  var _a22;
432587
432746
  (_a22 = project.getModuleSpecifierCache()) == null || _a22.clear();
@@ -438187,7 +438346,7 @@ var init_package_manifest = __esm(() => {
438187
438346
 
438188
438347
  // src/mods/package-registry.ts
438189
438348
  import {
438190
- existsSync as existsSync55,
438349
+ existsSync as existsSync54,
438191
438350
  mkdirSync as mkdirSync42,
438192
438351
  readFileSync as readFileSync46,
438193
438352
  rmSync as rmSync21,
@@ -438259,7 +438418,7 @@ function getRegistryPath(modsRoot) {
438259
438418
  }
438260
438419
  function readRegistryObject(modsRoot) {
438261
438420
  const registryPath = getRegistryPath(modsRoot);
438262
- if (!existsSync55(registryPath)) {
438421
+ if (!existsSync54(registryPath)) {
438263
438422
  return { diagnostics: [], ok: false, registryExists: false, registryPath };
438264
438423
  }
438265
438424
  const registryResult = parseJsonFile(registryPath);
@@ -438691,7 +438850,7 @@ function writePackageRegistry(registryPath, registry4) {
438691
438850
  }
438692
438851
  function validateManagedModPackageRegistryForMutation(modsRoot) {
438693
438852
  const registryPath = getRegistryPath(modsRoot);
438694
- const contents = existsSync55(registryPath) ? readFileSync46(registryPath, "utf8") : null;
438853
+ const contents = existsSync54(registryPath) ? readFileSync46(registryPath, "utf8") : null;
438695
438854
  const registry4 = readMutablePackageRegistry(modsRoot, {
438696
438855
  createIfMissing: true
438697
438856
  });
@@ -438814,10 +438973,10 @@ var init_package_registry = __esm(() => {
438814
438973
  });
438815
438974
 
438816
438975
  // src/mods/mod-sources.ts
438817
- import { existsSync as existsSync56, readdirSync as readdirSync22 } from "node:fs";
438976
+ import { existsSync as existsSync55, readdirSync as readdirSync22 } from "node:fs";
438818
438977
  import path37 from "node:path";
438819
438978
  function listModFiles(directory) {
438820
- if (!existsSync56(directory))
438979
+ if (!existsSync55(directory))
438821
438980
  return [];
438822
438981
  return readdirSync22(directory, { withFileTypes: true }).filter((entry) => {
438823
438982
  if (!entry.isFile())
@@ -438833,7 +438992,7 @@ function resolveLocalModSources(options = {}) {
438833
438992
  const includeGlobalMods = options.includeGlobalMods !== false;
438834
438993
  const managedPackages = includeGlobalMods ? resolveManagedModPackages(globalModsDirectory) : { diagnostics: [], files: [], packages: [] };
438835
438994
  const sources = [];
438836
- if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) && existsSync56(legacyGlobalExtensionsDirectory)) {
438995
+ if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) && existsSync55(legacyGlobalExtensionsDirectory)) {
438837
438996
  sources.push({
438838
438997
  files: listModFiles(legacyGlobalExtensionsDirectory),
438839
438998
  legacyMigrationTargetRoot: globalModsDirectory,
@@ -438872,7 +439031,7 @@ var init_mod_sources = __esm(() => {
438872
439031
 
438873
439032
  // src/mods/runtime-dependencies.ts
438874
439033
  import {
438875
- lstatSync as lstatSync2,
439034
+ lstatSync as lstatSync3,
438876
439035
  mkdirSync as mkdirSync43,
438877
439036
  readlinkSync,
438878
439037
  symlinkSync,
@@ -438893,7 +439052,7 @@ function ensureRuntimeDependencySymlink(cacheDirectory, packageName, resolveRunt
438893
439052
  const packageDirectory = path38.resolve(resolveRuntimePackageDirectory(packageName));
438894
439053
  mkdirSync43(nodeModulesDirectory, { recursive: true });
438895
439054
  try {
438896
- const stats = lstatSync2(linkPath);
439055
+ const stats = lstatSync3(linkPath);
438897
439056
  if (!stats.isSymbolicLink())
438898
439057
  return;
438899
439058
  const existingTarget = readlinkSync(linkPath);
@@ -439012,7 +439171,7 @@ function createNoopModPanelHandle() {
439012
439171
  // src/mods/mod-engine.ts
439013
439172
  import { createHash as createHash16 } from "node:crypto";
439014
439173
  import {
439015
- existsSync as existsSync57,
439174
+ existsSync as existsSync56,
439016
439175
  mkdirSync as mkdirSync44,
439017
439176
  readdirSync as readdirSync23,
439018
439177
  readFileSync as readFileSync47,
@@ -439202,7 +439361,7 @@ function createImportableModPath(modPath, cacheDirectory, source) {
439202
439361
  }
439203
439362
  const baseName = path39.basename(modPath, fileExtension).replace(/[^a-zA-Z0-9_-]/g, "-");
439204
439363
  const importPath = path39.join(importCacheDirectory, `.letta-mod-${baseName}-${hash3}.mjs`);
439205
- if (!existsSync57(importPath)) {
439364
+ if (!existsSync56(importPath)) {
439206
439365
  writeFileSync37(importPath, importableSource, "utf8");
439207
439366
  }
439208
439367
  try {
@@ -442625,19 +442784,19 @@ function emitSkillsUpdated(socket, safeSocketSend) {
442625
442784
  }
442626
442785
  async function handleSkillCommand(parsed, socket, safeSocketSend) {
442627
442786
  const {
442628
- existsSync: existsSync58,
442629
- lstatSync: lstatSync3,
442787
+ existsSync: existsSync57,
442788
+ lstatSync: lstatSync4,
442630
442789
  mkdirSync: mkdirSync45,
442631
442790
  rmdirSync: rmdirSync2,
442632
442791
  symlinkSync: symlinkSync2,
442633
442792
  unlinkSync: unlinkSync15
442634
442793
  } = await import("node:fs");
442635
- const { basename: basename21, join: join80 } = await import("node:path");
442794
+ const { basename: basename22, join: join80 } = await import("node:path");
442636
442795
  const lettaHome = process.env.LETTA_HOME || join80(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
442637
442796
  const globalSkillsDir = join80(lettaHome, "skills");
442638
442797
  if (parsed.type === "skill_enable") {
442639
442798
  try {
442640
- if (!existsSync58(parsed.skill_path)) {
442799
+ if (!existsSync57(parsed.skill_path)) {
442641
442800
  safeSocketSend(socket, {
442642
442801
  type: "skill_enable_response",
442643
442802
  request_id: parsed.request_id,
@@ -442647,7 +442806,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442647
442806
  return true;
442648
442807
  }
442649
442808
  const skillMdPath = join80(parsed.skill_path, "SKILL.md");
442650
- if (!existsSync58(skillMdPath)) {
442809
+ if (!existsSync57(skillMdPath)) {
442651
442810
  safeSocketSend(socket, {
442652
442811
  type: "skill_enable_response",
442653
442812
  request_id: parsed.request_id,
@@ -442656,11 +442815,11 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442656
442815
  }, "listener_skill_send_failed", "listener_skill_command");
442657
442816
  return true;
442658
442817
  }
442659
- const linkName = basename21(parsed.skill_path);
442818
+ const linkName = basename22(parsed.skill_path);
442660
442819
  const linkPath = join80(globalSkillsDir, linkName);
442661
442820
  mkdirSync45(globalSkillsDir, { recursive: true });
442662
- if (existsSync58(linkPath)) {
442663
- const stat12 = lstatSync3(linkPath);
442821
+ if (existsSync57(linkPath)) {
442822
+ const stat12 = lstatSync4(linkPath);
442664
442823
  if (stat12.isSymbolicLink()) {
442665
442824
  if (process.platform === "win32") {
442666
442825
  rmdirSync2(linkPath);
@@ -442701,7 +442860,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442701
442860
  if (parsed.type === "skill_disable") {
442702
442861
  try {
442703
442862
  const linkPath = join80(globalSkillsDir, parsed.name);
442704
- if (!existsSync58(linkPath)) {
442863
+ if (!existsSync57(linkPath)) {
442705
442864
  safeSocketSend(socket, {
442706
442865
  type: "skill_disable_response",
442707
442866
  request_id: parsed.request_id,
@@ -442710,7 +442869,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442710
442869
  }, "listener_skill_send_failed", "listener_skill_command");
442711
442870
  return true;
442712
442871
  }
442713
- const stat12 = lstatSync3(linkPath);
442872
+ const stat12 = lstatSync4(linkPath);
442714
442873
  if (!stat12.isSymbolicLink()) {
442715
442874
  safeSocketSend(socket, {
442716
442875
  type: "skill_disable_response",
@@ -443209,7 +443368,7 @@ function populateInterruptQueue(runtime, input) {
443209
443368
  type: "approval",
443210
443369
  tool_call_id: toolCallId,
443211
443370
  approve: false,
443212
- reason: "User interrupted the stream"
443371
+ reason: input.denialReason ?? "User interrupted the stream"
443213
443372
  }));
443214
443373
  runtime.pendingInterruptedContext = {
443215
443374
  agentId: input.agentId,
@@ -443621,7 +443780,7 @@ var init_control_inputs = __esm(async () => {
443621
443780
  });
443622
443781
 
443623
443782
  // src/websocket/terminal-handler.ts
443624
- import { existsSync as existsSync58 } from "node:fs";
443783
+ import { existsSync as existsSync57 } from "node:fs";
443625
443784
  import * as os7 from "node:os";
443626
443785
  import WebSocket7 from "ws";
443627
443786
  function getTerminalKey(connectionId, terminalId) {
@@ -443637,7 +443796,7 @@ function getDefaultShell() {
443637
443796
  "/bin/bash"
443638
443797
  ];
443639
443798
  for (const candidate of candidates2) {
443640
- if (candidate && existsSync58(candidate)) {
443799
+ if (candidate && existsSync57(candidate)) {
443641
443800
  return candidate;
443642
443801
  }
443643
443802
  }
@@ -444034,6 +444193,24 @@ function revokeRecoveryClaims(listener, connectionId, connectionGeneration) {
444034
444193
  claim.revoke();
444035
444194
  }
444036
444195
  }
444196
+ function recoveryRefusals(listener) {
444197
+ const generation4 = listener.connectionGeneration ?? undefined;
444198
+ let state2 = refusalCounts.get(listener);
444199
+ if (!state2 || state2.generation !== generation4) {
444200
+ state2 = { generation: generation4, count: 0, refused: false };
444201
+ refusalCounts.set(listener, state2);
444202
+ }
444203
+ return state2;
444204
+ }
444205
+ function recoveryRetryDelay(listener, base2) {
444206
+ const state2 = recoveryRefusals(listener);
444207
+ if (!state2.refused)
444208
+ return base2;
444209
+ state2.refused = false;
444210
+ if (++state2.count === 5)
444211
+ debugWarn("recovery", "Recovery refused because another connection owns the conversation; abandoned until the next reconnect");
444212
+ return state2.count >= 5 ? Infinity : Math.min(base2 * 2 ** (state2.count - 1), 300000);
444213
+ }
444037
444214
  async function acquireRecoveryClaim(runtime, onLost = () => {}, dependencies4 = {}) {
444038
444215
  const connectionId = runtime.listener.connectionId;
444039
444216
  const connectionGeneration = runtime.listener.connectionGeneration;
@@ -444074,8 +444251,13 @@ async function acquireRecoveryClaim(runtime, onLost = () => {}, dependencies4 =
444074
444251
  const claim = new RecoveryClaim(runtime, runtime.agentId, runtime.conversationId, connectionId, connectionGeneration, response.token, response.fence, request2, dependencies4.schedule ?? ((callback, delay6) => setTimeout(callback, delay6)), dependencies4.cancel ?? ((timer) => clearTimeout(timer)), onLost, now2, requestedAt + RECOVERY_CLAIM_TTL_MS - RECOVERY_CLAIM_EXPIRY_MARGIN_MS);
444075
444252
  runtime.listener.activeRecoveryClaims ??= new Set;
444076
444253
  runtime.listener.activeRecoveryClaims.add(claim);
444254
+ refusalCounts.delete(runtime.listener);
444077
444255
  return claim;
444078
444256
  } catch (error5) {
444257
+ if (error5 instanceof ApiRequestError && error5.status === 409 && /"owner_mismatch"/.test(error5.responseText)) {
444258
+ recoveryRefusals(runtime.listener).refused = true;
444259
+ return null;
444260
+ }
444079
444261
  debugWarn("recovery", "Recovery claim acquisition failed", error5);
444080
444262
  return null;
444081
444263
  }
@@ -444115,12 +444297,13 @@ async function getRecoveryEligibility(runtime, readStatus = getAgentRuntimeStatu
444115
444297
  async function canRecoverConversation(runtime, readStatus = getAgentRuntimeStatus) {
444116
444298
  return await getRecoveryEligibility(runtime, readStatus) === "owned";
444117
444299
  }
444118
- var RECOVERY_CLAIM_TTL_MS = 15000, RECOVERY_CLAIM_RENEW_MS = 5000, RECOVERY_CLAIM_EXPIRY_MARGIN_MS = 500, defaultRecoveryClaimRequest = (agentId, body3) => apiRequest("POST", `/v1/agents/${encodeURIComponent(agentId)}/recovery-claims`, body3, { signal: AbortSignal.timeout(5000) });
444300
+ var RECOVERY_CLAIM_TTL_MS = 15000, RECOVERY_CLAIM_RENEW_MS = 5000, RECOVERY_CLAIM_EXPIRY_MARGIN_MS = 500, defaultRecoveryClaimRequest = (agentId, body3) => apiRequest("POST", `/v1/agents/${encodeURIComponent(agentId)}/recovery-claims`, body3, { signal: AbortSignal.timeout(5000) }), refusalCounts;
444119
444301
  var init_recovery_ownership = __esm(async () => {
444120
444302
  init_agents8();
444121
444303
  init_request();
444122
444304
  init_debug();
444123
444305
  await init_teleport();
444306
+ refusalCounts = new WeakMap;
444124
444307
  });
444125
444308
 
444126
444309
  // src/agent/approval-recovery.ts
@@ -445679,7 +445862,7 @@ var init_tui_perf = __esm(() => {
445679
445862
 
445680
445863
  // src/cli/helpers/chunk-log.ts
445681
445864
  import {
445682
- existsSync as existsSync59,
445865
+ existsSync as existsSync58,
445683
445866
  mkdirSync as mkdirSync46,
445684
445867
  readdirSync as readdirSync24,
445685
445868
  unlinkSync as unlinkSync15,
@@ -445780,7 +445963,7 @@ class ChunkLog {
445780
445963
  if (this.dirCreated || !this.agentDir)
445781
445964
  return;
445782
445965
  try {
445783
- if (!existsSync59(this.agentDir)) {
445966
+ if (!existsSync58(this.agentDir)) {
445784
445967
  mkdirSync46(this.agentDir, { recursive: true });
445785
445968
  }
445786
445969
  this.dirCreated = true;
@@ -445805,7 +445988,7 @@ class ChunkLog {
445805
445988
  if (!this.agentDir)
445806
445989
  return;
445807
445990
  try {
445808
- if (!existsSync59(this.agentDir))
445991
+ if (!existsSync58(this.agentDir))
445809
445992
  return;
445810
445993
  const files = readdirSync24(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
445811
445994
  if (files.length >= MAX_SESSION_FILES2) {
@@ -447233,6 +447416,7 @@ function finishListenerTurn(runtime, lease, options) {
447233
447416
  debugWarn("recovery", "Failed to retire completed listener work", error5);
447234
447417
  }
447235
447418
  }
447419
+ runtime.activeConnectionId = null;
447236
447420
  return transition2;
447237
447421
  }
447238
447422
  var init_turn_terminal = __esm(async () => {
@@ -449703,7 +449887,7 @@ __export(exports_diff, {
449703
449887
  ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
449704
449888
  ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
449705
449889
  });
449706
- import { basename as basename21 } from "node:path";
449890
+ import { basename as basename22 } from "node:path";
449707
449891
  function readFileOrNull(p2) {
449708
449892
  try {
449709
449893
  return __require("node:fs").readFileSync(p2, "utf-8");
@@ -449727,7 +449911,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
449727
449911
  return { ok: true, out: content.split(oldStr).join(newStr) };
449728
449912
  }
449729
449913
  function computeAdvancedDiff(input, opts) {
449730
- const fileName = basename21(input.filePath || "");
449914
+ const fileName = basename22(input.filePath || "");
449731
449915
  const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
449732
449916
  if (fileContent === null && input.kind !== "write") {
449733
449917
  return { mode: "fallback", reason: "File not readable" };
@@ -449759,7 +449943,7 @@ function computeAdvancedDiff(input, opts) {
449759
449943
  return { mode: "advanced", fileName, oldStr, newStr, hunks };
449760
449944
  }
449761
449945
  function parsePatchToAdvancedDiff(patchLines, filePath) {
449762
- const fileName = basename21(filePath);
449946
+ const fileName = basename22(filePath);
449763
449947
  const hunks = [];
449764
449948
  let currentHunk = null;
449765
449949
  let oldLine = 1;
@@ -450037,8 +450221,8 @@ function isFormatterSegment(tokens) {
450037
450221
  }
450038
450222
  }
450039
450223
  function isShellExecutor2(token2) {
450040
- const basename22 = token2.split("/").pop() ?? token2;
450041
- return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename22.toLowerCase());
450224
+ const basename23 = token2.split("/").pop() ?? token2;
450225
+ return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename23.toLowerCase());
450042
450226
  }
450043
450227
  function normalizeRawCommand(command) {
450044
450228
  if (Array.isArray(command)) {
@@ -450825,7 +451009,7 @@ var init_format_args_display = __esm(() => {
450825
451009
  });
450826
451010
 
450827
451011
  // src/helpers/diff-preview.ts
450828
- import path41, { basename as basename22 } from "node:path";
451012
+ import path41, { basename as basename23 } from "node:path";
450829
451013
  function parseHunkLinePrefix(raw2) {
450830
451014
  if (raw2.length === 0) {
450831
451015
  return { type: "context", content: "" };
@@ -450931,7 +451115,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450931
451115
  filePath: resolvedFilePath,
450932
451116
  content: toolArgs.content || ""
450933
451117
  });
450934
- previews.push(toDiffPreview(result3, basename22(filePath)));
451118
+ previews.push(toDiffPreview(result3, basename23(filePath)));
450935
451119
  }
450936
451120
  } else if (isFileEditTool3(toolName2)) {
450937
451121
  const filePath = toolArgs.file_path;
@@ -450944,7 +451128,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450944
451128
  newString: toolArgs.new_string || "",
450945
451129
  replaceAll: toolArgs.replace_all
450946
451130
  });
450947
- previews.push(toDiffPreview(result3, basename22(filePath)));
451131
+ previews.push(toDiffPreview(result3, basename23(filePath)));
450948
451132
  }
450949
451133
  } else if (isPatchTool2(toolName2) && toolArgs.input) {
450950
451134
  const operations2 = parsePatchOperations2(toolArgs.input);
@@ -450952,7 +451136,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450952
451136
  if (op.kind === "add" || op.kind === "update") {
450953
451137
  const result3 = parsePatchToAdvancedDiff2(op.patchLines, op.path);
450954
451138
  if (result3) {
450955
- previews.push(toDiffPreview(result3, basename22(op.path)));
451139
+ previews.push(toDiffPreview(result3, basename23(op.path)));
450956
451140
  }
450957
451141
  }
450958
451142
  }
@@ -451008,7 +451192,28 @@ function safeJsonParseOr(json2, defaultValue) {
451008
451192
  async function getMissingRequiredArgs(toolName2, parsedArgs, toolContextId) {
451009
451193
  const schema5 = getToolSchema(toolName2, toolContextId);
451010
451194
  const required6 = schema5?.input_schema?.required || [];
451011
- return required6.filter((key3) => !(key3 in parsedArgs) || parsedArgs[key3] == null);
451195
+ const properties4 = schema5?.input_schema?.properties;
451196
+ return required6.filter((key3) => {
451197
+ if (!(key3 in parsedArgs) || parsedArgs[key3] === undefined)
451198
+ return true;
451199
+ if (parsedArgs[key3] === null)
451200
+ return !schemaAllowsNull2(properties4?.[key3]);
451201
+ return false;
451202
+ });
451203
+ }
451204
+ function typeAllowsNull(schema5) {
451205
+ if (!schema5 || typeof schema5 !== "object")
451206
+ return false;
451207
+ const type3 = schema5.type;
451208
+ return type3 === "null" || Array.isArray(type3) && type3.includes("null");
451209
+ }
451210
+ function schemaAllowsNull2(schema5) {
451211
+ if (typeAllowsNull(schema5))
451212
+ return true;
451213
+ if (!schema5 || typeof schema5 !== "object")
451214
+ return false;
451215
+ const { anyOf: anyOf3, oneOf: oneOf3 } = schema5;
451216
+ return [anyOf3, oneOf3].some((branches) => Array.isArray(branches) && branches.some(typeAllowsNull));
451012
451217
  }
451013
451218
  function formatMissingRequiredArgsReason(toolName2, parsedArgs, missingRequiredArgs, argsParse) {
451014
451219
  const received = Object.keys(parsedArgs).join(", ");
@@ -451685,7 +451890,7 @@ async function handleApprovalStop(params) {
451685
451890
  const sendOptions = buildSendOptions() ?? {};
451686
451891
  if (shouldInterrupt())
451687
451892
  return interruptTermination();
451688
- const consumedQueuedTurn = params.allowQueuedContinuation === false ? null : consumeQueuedTurn(runtime, params.activeOriginatorScope ?? null);
451893
+ const consumedQueuedTurn = params.allowQueuedContinuation === false ? null : consumeQueuedTurn(runtime);
451689
451894
  if (consumedQueuedTurn) {
451690
451895
  const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
451691
451896
  await params.onConsumeQueuedTurn?.(queuedTurn);
@@ -451797,7 +452002,7 @@ var init_turn_approval = __esm(async () => {
451797
452002
  });
451798
452003
 
451799
452004
  // src/agent/attached-repository-git-sync.ts
451800
- import { existsSync as existsSync60 } from "node:fs";
452005
+ import { existsSync as existsSync59 } from "node:fs";
451801
452006
  import { join as join81 } from "node:path";
451802
452007
  async function getPendingCommitCount(path42) {
451803
452008
  const divergence = await getMemoryAheadBehind(path42);
@@ -451828,7 +452033,7 @@ async function syncPendingAttachedRepositoryCommitsUnlocked(params) {
451828
452033
  path: path42,
451829
452034
  permissions: params.repository.permissions ?? "unknown"
451830
452035
  };
451831
- if (!existsSync60(join81(path42, ".git"))) {
452036
+ if (!existsSync59(join81(path42, ".git"))) {
451832
452037
  return {
451833
452038
  ...resultBase,
451834
452039
  status: "skipped",
@@ -451998,7 +452203,7 @@ var init_attached_repository_git_sync = __esm(() => {
451998
452203
  });
451999
452204
 
452000
452205
  // src/reminders/memory-git-sync.ts
452001
- import { existsSync as existsSync61 } from "node:fs";
452206
+ import { existsSync as existsSync60 } from "node:fs";
452002
452207
  import { join as join82 } from "node:path";
452003
452208
  function formatMemoryRepairInProgressReminder(result3) {
452004
452209
  return `${SYSTEM_REMINDER_OPEN}
@@ -452109,7 +452314,7 @@ async function runPostTurnMemorySync(params, dependencies4 = {}) {
452109
452314
  if (memorySyncEnabled) {
452110
452315
  try {
452111
452316
  const memoryDir = getScopedMemoryFilesystemRoot(params.agentId);
452112
- const release = existsSync61(join82(memoryDir, ".git")) ? await (dependencies4.claimOperation ?? claimMemoryOperation)(memoryDir) : undefined;
452317
+ const release = existsSync60(join82(memoryDir, ".git")) ? await (dependencies4.claimOperation ?? claimMemoryOperation)(memoryDir) : undefined;
452113
452318
  if (release !== null) {
452114
452319
  try {
452115
452320
  const result3 = await syncMemory(params.agentId);
@@ -452946,12 +453151,12 @@ function rowToolCalls(row, index, diagnostics2) {
452946
453151
  }
452947
453152
  return calls;
452948
453153
  }
452949
- function contentText2(content) {
453154
+ function contentText3(content) {
452950
453155
  if (typeof content === "string") {
452951
453156
  if (content.startsWith(CONTENT_JSON_PREFIX)) {
452952
453157
  const encoded = content.slice(CONTENT_JSON_PREFIX.length);
452953
453158
  try {
452954
- return contentText2(JSON.parse(encoded));
453159
+ return contentText3(JSON.parse(encoded));
452955
453160
  } catch {
452956
453161
  return encoded;
452957
453162
  }
@@ -453037,7 +453242,7 @@ var init_hermes = __esm(() => {
453037
453242
  });
453038
453243
  };
453039
453244
  if (row.role === "user") {
453040
- const content = contentText2(row.content);
453245
+ const content = contentText3(row.content);
453041
453246
  if (content) {
453042
453247
  emit({
453043
453248
  type: "message",
@@ -453057,7 +453262,7 @@ var init_hermes = __esm(() => {
453057
453262
  ...timestamp ? { timestamp } : {}
453058
453263
  });
453059
453264
  }
453060
- const content = contentText2(row.content);
453265
+ const content = contentText3(row.content);
453061
453266
  if (content) {
453062
453267
  emit({
453063
453268
  type: "message",
@@ -453080,7 +453285,7 @@ var init_hermes = __esm(() => {
453080
453285
  if (row.role === "tool") {
453081
453286
  emit({
453082
453287
  type: "tool_result",
453083
- content: contentText2(row.content),
453288
+ content: contentText3(row.content),
453084
453289
  ...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
453085
453290
  ...timestamp ? { timestamp } : {}
453086
453291
  });
@@ -454722,7 +454927,7 @@ var init_listing_shared = __esm(() => {
454722
454927
 
454723
454928
  // node_modules/@letta-ai/trajectory/dist/adapters/claude-code/list.js
454724
454929
  import { homedir as homedir45 } from "node:os";
454725
- import { basename as basename23, join as join85 } from "node:path";
454930
+ import { basename as basename24, join as join85 } from "node:path";
454726
454931
  async function listClaudeCodeTrajectories(root2) {
454727
454932
  const base2 = root2 ?? join85(homedir45(), ".claude", "projects");
454728
454933
  const items3 = [];
@@ -454734,7 +454939,7 @@ async function listClaudeCodeTrajectories(root2) {
454734
454939
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
454735
454940
  continue;
454736
454941
  const path42 = join85(projectPath, entry.name);
454737
- const listing = listingFromFile(basename23(entry.name, ".jsonl"), path42);
454942
+ const listing = listingFromFile(basename24(entry.name, ".jsonl"), path42);
454738
454943
  if (listing)
454739
454944
  items3.push(listing);
454740
454945
  }
@@ -454747,12 +454952,12 @@ var init_list = __esm(() => {
454747
454952
 
454748
454953
  // node_modules/@letta-ai/trajectory/dist/adapters/codex/list.js
454749
454954
  import { homedir as homedir46 } from "node:os";
454750
- import { basename as basename24, join as join86 } from "node:path";
454955
+ import { basename as basename25, join as join86 } from "node:path";
454751
454956
  async function listCodexTrajectories(root2) {
454752
454957
  const base2 = root2 ?? join86(homedir46(), ".codex", "sessions");
454753
454958
  const items3 = [];
454754
454959
  for (const path42 of collectFiles(base2, ".jsonl", 4)) {
454755
- const listing = listingFromFile(basename24(path42, ".jsonl"), path42);
454960
+ const listing = listingFromFile(basename25(path42, ".jsonl"), path42);
454756
454961
  if (listing)
454757
454962
  items3.push(listing);
454758
454963
  }
@@ -454857,9 +455062,9 @@ var init_list5 = __esm(() => {
454857
455062
  });
454858
455063
 
454859
455064
  // node_modules/@letta-ai/trajectory/dist/adapters/openclaw/list.js
454860
- import { existsSync as existsSync62 } from "node:fs";
455065
+ import { existsSync as existsSync61 } from "node:fs";
454861
455066
  import { homedir as homedir50 } from "node:os";
454862
- import { basename as basename25, join as join90 } from "node:path";
455067
+ import { basename as basename26, join as join90 } from "node:path";
454863
455068
  async function listOpenClawTrajectories(root2) {
454864
455069
  const base2 = root2 ?? defaultStateDir();
454865
455070
  const items3 = [];
@@ -454872,7 +455077,7 @@ async function listOpenClawTrajectories(root2) {
454872
455077
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
454873
455078
  continue;
454874
455079
  const path42 = join90(sessionsPath, entry.name);
454875
- const listing = listingFromFile(basename25(entry.name, ".jsonl"), path42);
455080
+ const listing = listingFromFile(basename26(entry.name, ".jsonl"), path42);
454876
455081
  if (listing)
454877
455082
  items3.push(listing);
454878
455083
  }
@@ -454884,7 +455089,7 @@ function defaultStateDir() {
454884
455089
  if (override)
454885
455090
  return override;
454886
455091
  const current = join90(homedir50(), ".openclaw");
454887
- if (existsSync62(current))
455092
+ if (existsSync61(current))
454888
455093
  return current;
454889
455094
  return join90(homedir50(), ".clawdbot");
454890
455095
  }
@@ -457390,6 +457595,11 @@ var init_execution_context_mcp_originator = __esm(async () => {
457390
457595
  await init_manager2();
457391
457596
  });
457392
457597
 
457598
+ // src/websocket/listener/mcp-originator-scope.ts
457599
+ function getEffectiveMcpOriginatorId(message2) {
457600
+ return message2.mcpOriginatorTokenPresent === true ? message2.mcpOriginatorSuperRunId : undefined;
457601
+ }
457602
+
457393
457603
  // src/websocket/listener/turn-finalizer.ts
457394
457604
  function applyTurnOriginSwap(parkedInput, consumedTurn, turnToolContextId) {
457395
457605
  retireMcpOriginatorTokensOnOriginSwap(parkedInput.mcpOriginatorSuperRunId, consumedTurn.mcpOriginatorSuperRunId);
@@ -457397,7 +457607,6 @@ function applyTurnOriginSwap(parkedInput, consumedTurn, turnToolContextId) {
457397
457607
  }
457398
457608
  function createQueuedTurnConsumer(params) {
457399
457609
  return {
457400
- activeOriginatorScope: getMcpOriginatorScope(params.parkedInput),
457401
457610
  allowQueuedContinuation: params.parkedInput.messages.some((message2) => ("content" in message2)),
457402
457611
  onConsumeQueuedTurn: async (queuedTurn) => {
457403
457612
  applyTurnOriginSwap(params.parkedInput, queuedTurn, params.turnToolContextId);
@@ -457501,6 +457710,37 @@ var init_turn_finalizer = __esm(async () => {
457501
457710
  ]);
457502
457711
  });
457503
457712
 
457713
+ // src/websocket/listener/turn-max-turns.ts
457714
+ function finishTurnIfMaxTurnsReached(params) {
457715
+ const { runtime, buffers, stopReason, agentId, conversationId } = params;
457716
+ const maxTurns = runtime.executionSettings?.max_turns;
457717
+ if (maxTurns === undefined || buffers.usage.stepCount < maxTurns || stopReason === "error" && params.fallbackError) {
457718
+ return false;
457719
+ }
457720
+ const message2 = `Maximum turns limit reached (${buffers.usage.stepCount}/${maxTurns} steps)`;
457721
+ if (stopReason === "requires_approval") {
457722
+ populateInterruptQueue(runtime, {
457723
+ lastExecutionResults: null,
457724
+ lastExecutingToolCallIds: [],
457725
+ lastNeedsUserInputToolCallIds: params.approvals.map((a2) => a2.toolCallId),
457726
+ agentId,
457727
+ conversationId,
457728
+ denialReason: message2
457729
+ });
457730
+ }
457731
+ params.finishTurn({
457732
+ stopReason: "max_steps",
457733
+ socket: params.socket,
457734
+ agentId,
457735
+ conversationId,
457736
+ errorNotice: { message: message2, runId: params.runId }
457737
+ });
457738
+ return true;
457739
+ }
457740
+ var init_turn_max_turns = __esm(async () => {
457741
+ await init_interrupts();
457742
+ });
457743
+
457504
457744
  // src/websocket/listener/turn-observers.ts
457505
457745
  function registerTurnObserver(otid, hooks) {
457506
457746
  hooksByOtid.set(otid, hooks);
@@ -458387,18 +458627,18 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
458387
458627
  break;
458388
458628
  }
458389
458629
  lastApprovalContinuationAccepted = false;
458390
- const maxTurns = runtime.executionSettings?.max_turns;
458391
- if (maxTurns !== undefined && buffers.usage.stepCount >= maxTurns && stopReason !== "requires_approval" && !(stopReason === "error" && fallbackError)) {
458392
- finishTurn({
458393
- stopReason: "max_steps",
458394
- socket,
458395
- agentId,
458396
- conversationId,
458397
- errorNotice: {
458398
- message: `Maximum turns limit reached (${buffers.usage.stepCount}/${maxTurns} steps)`,
458399
- runId: runId || runtime.activeRunId
458400
- }
458401
- });
458630
+ if (finishTurnIfMaxTurnsReached({
458631
+ runtime,
458632
+ socket,
458633
+ buffers,
458634
+ stopReason,
458635
+ approvals,
458636
+ fallbackError,
458637
+ runId: runId || runtime.activeRunId,
458638
+ agentId,
458639
+ conversationId,
458640
+ finishTurn
458641
+ })) {
458402
458642
  break;
458403
458643
  }
458404
458644
  if (stopReason === "end_turn") {
@@ -458925,6 +459165,7 @@ var init_turn = __esm(async () => {
458925
459165
  init_turn_correlation(),
458926
459166
  init_turn_durability_ownership(),
458927
459167
  init_turn_finalizer(),
459168
+ init_turn_max_turns(),
458928
459169
  init_turn_send(),
458929
459170
  init_turn_setup(),
458930
459171
  init_turn_status(),
@@ -460199,42 +460440,9 @@ function stampInboundUserMessageOtids(incoming) {
460199
460440
  function rejectReplacement(reason) {
460200
460441
  throw new Error(`Invalid listener replacement lineage: ${reason}`);
460201
460442
  }
460202
- function cloneRawData(frame) {
460203
- if (Array.isArray(frame))
460204
- return frame.map((chunk2) => Buffer.from(chunk2));
460205
- if (Buffer.isBuffer(frame))
460206
- return Buffer.from(frame);
460207
- if (frame instanceof ArrayBuffer)
460208
- return frame.slice(0);
460209
- return Buffer.from(new Uint8Array(frame));
460210
- }
460211
- function cloneStartupFrameHandoff(handoff) {
460212
- return handoff.kind === "overflow" ? { ...handoff } : { ...handoff, frames: handoff.frames.map(cloneRawData) };
460213
- }
460214
- function cloneDispositionLedger(ledger) {
460215
- return {
460216
- entries: new Map([...ledger.entries].map(([key3, entry]) => [key3, structuredClone(entry)])),
460217
- scopeCounts: new Map(ledger.scopeCounts),
460218
- quarantinedCount: ledger.quarantinedCount,
460219
- abandonedReservations: new Map([...ledger.abandonedReservations].map(([key3, reservation]) => [
460220
- key3,
460221
- { ...reservation }
460222
- ])),
460223
- expiryQueue: ledger.expiryQueue.map((entry) => ({ ...entry })),
460224
- expiryQueueHead: ledger.expiryQueueHead,
460225
- nextGeneration: ledger.nextGeneration,
460226
- persistentPath: ledger.persistentPath
460227
- };
460228
- }
460229
460443
  function createListenerClientReplacement(runtime, opts) {
460230
460444
  const lineageId = resolveStartupLineageId(runtime, opts);
460231
460445
  const generation4 = runtime.startupGenerationByLineage.get(lineageId) ?? 0;
460232
- const startupFrameHandoff = cloneStartupFrameHandoff(runtime.pendingStartupFramesByLineage.get(lineageId) ?? {
460233
- kind: "frames",
460234
- frames: [],
460235
- byteLength: 0
460236
- });
460237
- const clientMessageIdsByRunIdByConversation = cloneTurnCorrelationIndex(runtime.clientMessageIdsByRunIdByConversation);
460238
460446
  const replacement = Object.freeze({
460239
460447
  deviceId: opts.deviceId,
460240
460448
  connectionName: opts.connectionName,
@@ -460247,10 +460455,7 @@ function createListenerClientReplacement(runtime, opts) {
460247
460455
  connectionName: opts.connectionName,
460248
460456
  lineageId,
460249
460457
  generation: generation4,
460250
- authorityEpoch: getRuntimeAuthorityEpoch(runtime),
460251
- ledger: cloneDispositionLedger(runtime.acceptedInputDispositionLedger),
460252
- startupFrameHandoff: cloneStartupFrameHandoff(startupFrameHandoff),
460253
- clientMessageIdsByRunIdByConversation: cloneTurnCorrelationIndex(clientMessageIdsByRunIdByConversation)
460458
+ authorityEpoch: getRuntimeAuthorityEpoch(runtime)
460254
460459
  });
460255
460460
  return replacement;
460256
460461
  }
@@ -460265,54 +460470,29 @@ function resolveAdoptableReplacement(opts) {
460265
460470
  rejectReplacement("identity_mismatch");
460266
460471
  }
460267
460472
  const issuer = provenance.issuer;
460268
- if (succeededListenerRuntimes.has(issuer)) {
460269
- rejectReplacement("superseded_issuer");
460270
- }
460271
460473
  if ((issuer.startupGenerationByLineage.get(provenance.lineageId) ?? 0) !== provenance.generation) {
460272
460474
  rejectReplacement("stale_generation");
460273
460475
  }
460274
460476
  if (provenance.authorityEpoch === null || provenance.authorityEpoch !== getLatestRuntimeAuthorityEpoch()) {
460275
460477
  rejectReplacement("unauthoritative_issuer");
460276
460478
  }
460277
- const activeRuntime2 = getActiveRuntime();
460278
- if (issuer.intentionallyClosed) {
460279
- if (activeRuntime2 !== null && activeRuntime2 !== issuer) {
460280
- rejectReplacement("unauthoritative_issuer");
460281
- }
460282
- } else if (issuer !== activeRuntime2) {
460479
+ if (issuer.intentionallyClosed || issuer !== getActiveRuntime()) {
460283
460480
  rejectReplacement("unauthoritative_issuer");
460284
460481
  }
460285
460482
  return provenance;
460286
460483
  }
460287
- function assertAdoptableListenerClientReplacement(opts) {
460288
- resolveAdoptableReplacement(opts);
460289
- }
460290
- function adoptListenerClientReplacement(runtime, opts) {
460484
+ function adoptListenerClientReplacement(opts) {
460291
460485
  const provenance = resolveAdoptableReplacement(opts);
460292
- const replacement = opts.replacement;
460293
- if (!provenance || !replacement)
460294
- return;
460295
- replacementProvenance.delete(replacement);
460296
- succeededListenerRuntimes.add(provenance.issuer);
460297
- runtime.acceptedInputDispositionLedger = cloneDispositionLedger(provenance.ledger);
460298
- runtime.acceptedInputDispositionLedger.abandonedReservations = new Map([
460299
- ...provenance.issuer.acceptedInputDispositionLedger.abandonedReservations
460300
- ].map(([key3, reservation]) => [key3, { ...reservation }]));
460301
- runtime.clientMessageIdsByRunIdByConversation = mergeTurnCorrelationIndexes(provenance.clientMessageIdsByRunIdByConversation, provenance.issuer.clientMessageIdsByRunIdByConversation, runtime.clientMessageIdsByRunIdByConversation);
460302
- runtime.startupGenerationByLineage.set(provenance.lineageId, provenance.generation);
460303
- if (provenance.startupFrameHandoff.kind === "overflow" || provenance.startupFrameHandoff.frames.length > 0) {
460304
- runtime.pendingStartupFramesByLineage.set(provenance.lineageId, cloneStartupFrameHandoff(provenance.startupFrameHandoff));
460305
- }
460306
- }
460307
- var replacementProvenance, succeededListenerRuntimes;
460486
+ if (!provenance || !opts.replacement)
460487
+ return null;
460488
+ replacementProvenance.delete(opts.replacement);
460489
+ return provenance.issuer;
460490
+ }
460491
+ var replacementProvenance;
460308
460492
  var init_listener_replacement = __esm(async () => {
460309
460493
  init_startup_ingress();
460310
- await __promiseAll([
460311
- init_runtime6(),
460312
- init_turn_correlation()
460313
- ]);
460494
+ await init_runtime6();
460314
460495
  replacementProvenance = new WeakMap;
460315
- succeededListenerRuntimes = new WeakSet;
460316
460496
  });
460317
460497
 
460318
460498
  // src/websocket/listener/listener-task.ts
@@ -460592,9 +460772,9 @@ __export(exports_custom, {
460592
460772
  GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
460593
460773
  COMMANDS_DIR: () => COMMANDS_DIR
460594
460774
  });
460595
- import { existsSync as existsSync63 } from "node:fs";
460775
+ import { existsSync as existsSync62 } from "node:fs";
460596
460776
  import { readdir as readdir11, readFile as readFile25 } from "node:fs/promises";
460597
- import { basename as basename27, dirname as dirname36, join as join93 } from "node:path";
460777
+ import { basename as basename28, dirname as dirname36, join as join93 } from "node:path";
460598
460778
  async function getCustomCommands() {
460599
460779
  if (cachedCommands !== null) {
460600
460780
  return cachedCommands;
@@ -460626,7 +460806,7 @@ async function discoverCustomCommands(projectPath = join93(process.cwd(), COMMAN
460626
460806
  return result3;
460627
460807
  }
460628
460808
  async function discoverFromDirectory(dirPath, source) {
460629
- if (!existsSync63(dirPath)) {
460809
+ if (!existsSync62(dirPath)) {
460630
460810
  return [];
460631
460811
  }
460632
460812
  const commands = [];
@@ -460654,7 +460834,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source) {
460654
460834
  async function parseCommandFile(filePath, rootPath, source) {
460655
460835
  const content = await readFile25(filePath, "utf-8");
460656
460836
  const { frontmatter, body: body3 } = parseFrontmatter(content);
460657
- const id2 = basename27(filePath, ".md");
460837
+ const id2 = basename28(filePath, ".md");
460658
460838
  const relativePath = dirname36(filePath).slice(rootPath.length);
460659
460839
  const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
460660
460840
  let description = getStringField(frontmatter, "description");
@@ -461673,7 +461853,6 @@ function buildAppServerInfoResponse(command, options) {
461673
461853
  runtime_external_tools_update: true,
461674
461854
  structured_outputs: options.backend === "api",
461675
461855
  write_file_base64: true,
461676
- mcp_originator_queue_isolation: true,
461677
461856
  split_channels: false
461678
461857
  }
461679
461858
  };
@@ -463691,16 +463870,29 @@ async function preparePairedListenerTransport(params) {
463691
463870
  runtime.streamTransport = streamSocket;
463692
463871
  return { kind: "ready", transport: streamSocket, streamSocket };
463693
463872
  }
463873
+ function createListenerLifecycleLog(opts) {
463874
+ return (message2) => {
463875
+ if (opts.onLog) {
463876
+ opts.onLog(`[Listen] ${message2}`);
463877
+ return;
463878
+ }
463879
+ debugLog("Listen", message2);
463880
+ };
463881
+ }
463882
+ function formatListenerSocketClose(channel, code2, reason) {
463883
+ const text3 = reason.toString();
463884
+ const truncated = text3.length > MAX_CLOSE_REASON_LENGTH ? `${text3.slice(0, MAX_CLOSE_REASON_LENGTH)}...` : text3;
463885
+ return `${channel} socket closed (code=${code2}, reason=${JSON.stringify(truncated)})`;
463886
+ }
463694
463887
  function attachSplitStreamSocketHandlers(params) {
463695
463888
  params.streamSocket.on("error", (error5) => {
463889
+ params.log?.(`stream socket error: ${error5.message}`);
463696
463890
  params.trackListenerError("listener_stream_socket_error", error5, "listener_stream_socket");
463697
463891
  if (isDebugEnabled())
463698
463892
  console.error("[Listen] Stream WebSocket error:", error5);
463699
463893
  });
463700
463894
  params.streamSocket.on("close", (code2, reason) => {
463701
- if (isDebugEnabled()) {
463702
- console.log(`[Listen] Stream WebSocket closed (code: ${code2}, reason: ${reason.toString()})`);
463703
- }
463895
+ params.log?.(formatListenerSocketClose("stream", code2, reason));
463704
463896
  terminateControlAfterStreamClose(params.runtime, params.streamSocket, code2, reason);
463705
463897
  });
463706
463898
  }
@@ -463748,6 +463940,7 @@ function handleListenerSocketOpenFailure({
463748
463940
  }
463749
463941
  terminateCurrentSocketPair(runtime, controlSocket, streamSocket);
463750
463942
  }
463943
+ var MAX_CLOSE_REASON_LENGTH = 120;
463751
463944
  var init_split_stream_lifecycle = __esm(async () => {
463752
463945
  init_debug();
463753
463946
  init_constants3();
@@ -463945,7 +464138,9 @@ async function handleSubagentMessageCommand(command, parent, deps = {}) {
463945
464138
  interrupt: receipt.interrupt,
463946
464139
  captureReservation,
463947
464140
  toolCallId: command.tool_call_id,
463948
- publishResult: true
464141
+ publishResult: true,
464142
+ emitCompletionNotification: false,
464143
+ claimsParentRuntime: false
463949
464144
  });
463950
464145
  } catch (error5) {
463951
464146
  await receipt.interrupt().catch(() => {
@@ -465410,10 +465605,10 @@ async function recoverRecordedTurns(listener, deps = {}) {
465410
465605
  }
465411
465606
  } finally {
465412
465607
  recovering.delete(listener);
465608
+ const retryDelayMs = recoveryRetryDelay(listener, deps.retryDelayMs ?? 5000);
465413
465609
  if (pendingRecoveries.delete(listener)) {
465414
465610
  scheduleRecordedTurnRecovery(listener, () => recoverRecordedTurns(listener, deps), deps.retryDelayMs);
465415
- } else if (deferred2 && !listener.intentionallyClosed) {
465416
- const retryDelayMs = deps.retryDelayMs ?? 5000;
465611
+ } else if (deferred2 && Number.isFinite(retryDelayMs) && !listener.intentionallyClosed) {
465417
465612
  const timer2 = setTimeout(() => {
465418
465613
  retryTimers.delete(listener);
465419
465614
  scheduleRecordedTurnRecovery(listener, () => recoverRecordedTurns(listener, deps), retryDelayMs);
@@ -465494,6 +465689,39 @@ var init_socket_send = __esm(() => {
465494
465689
  init_debug();
465495
465690
  });
465496
465691
 
465692
+ // src/websocket/listener/startup-deadline.ts
465693
+ function startListenerStartupDeadline(runtime, transport3, opts, enabled = true) {
465694
+ const socket = runtime.socket;
465695
+ if (!enabled || !socket || socket !== transport3)
465696
+ return () => {};
465697
+ const configured = Number(process.env.LETTA_LISTENER_STARTUP_DEADLINE_MS);
465698
+ const deadlineMs = Number.isFinite(configured) && configured > 0 ? configured : 60000;
465699
+ const clear = () => {
465700
+ clearTimeout(timer);
465701
+ socket.off("close", clear);
465702
+ };
465703
+ const timer = setTimeout(() => {
465704
+ clear();
465705
+ if (runtime.socket !== socket || runtime.intentionallyClosed)
465706
+ return;
465707
+ const message2 = `Listener startup did not finish within ${deadlineMs}ms; reconnecting`;
465708
+ try {
465709
+ if (opts.onLog)
465710
+ opts.onLog(message2);
465711
+ else
465712
+ debugLog("Listen", message2);
465713
+ } finally {
465714
+ socket.terminate();
465715
+ }
465716
+ }, deadlineMs);
465717
+ socket.once("close", clear);
465718
+ timer.unref();
465719
+ return clear;
465720
+ }
465721
+ var init_startup_deadline = __esm(() => {
465722
+ init_debug();
465723
+ });
465724
+
465497
465725
  // src/websocket/listener/recovery-sync.ts
465498
465726
  function isBackendNotFoundError2(error5) {
465499
465727
  return error5 instanceof APIError && (error5.status === 404 || error5.status === 422) || error5 instanceof Error && error5.name === "LocalBackendNotFoundError";
@@ -465848,6 +466076,7 @@ async function startConnectedListenerRuntime(runtime, transport3, opts, processQ
465848
466076
  startListenerPongHeartbeat(runtime, transport3, trackListenerError4);
465849
466077
  }
465850
466078
  const heartbeat = options.startHeartbeat !== false && runtime.heartbeatInterval;
466079
+ const clearStartupDeadline = startListenerStartupDeadline(runtime, transport3, opts, options.startStartupDeadline);
465851
466080
  let startupComplete = false;
465852
466081
  try {
465853
466082
  if (!await completeInitialConnectionStartup(runtime, startupConnection, transport3, opts, options))
@@ -465869,6 +466098,7 @@ async function startConnectedListenerRuntime(runtime, transport3, opts, processQ
465869
466098
  return;
465870
466099
  startupComplete = true;
465871
466100
  } finally {
466101
+ clearStartupDeadline();
465872
466102
  if (!startupComplete && heartbeat) {
465873
466103
  clearInterval(heartbeat);
465874
466104
  if (runtime.heartbeatInterval === heartbeat)
@@ -466019,13 +466249,15 @@ async function attachOpenListenerSocket(runtime, socket, opts, options = {}) {
466019
466249
  });
466020
466250
  }
466021
466251
  async function startListenerClient(opts) {
466022
- assertAdoptableListenerClientReplacement(opts);
466252
+ const resumedRuntime = adoptListenerClientReplacement(opts);
466023
466253
  const existingRuntime = getActiveRuntime();
466024
- if (existingRuntime) {
466254
+ if (existingRuntime && !resumedRuntime)
466025
466255
  stopRuntime(existingRuntime, true);
466256
+ const runtime = resumedRuntime ?? createRuntime();
466257
+ if (resumedRuntime && runtime.connectionId) {
466258
+ revokeRecoveryClaims(runtime, runtime.connectionId);
466259
+ resumeListenerConnectionIdentity(runtime, runtime.connectionId, opts.connectionId);
466026
466260
  }
466027
- const runtime = createRuntime();
466028
- adoptListenerClientReplacement(runtime, opts);
466029
466261
  runtime.onWsEvent = opts.onWsEvent;
466030
466262
  runtime.connectionId = opts.connectionId;
466031
466263
  runtime.connectionName = opts.connectionName;
@@ -466033,7 +466265,8 @@ async function startListenerClient(opts) {
466033
466265
  telemetry.setSurface(getListenerTelemetrySurface());
466034
466266
  telemetry.init();
466035
466267
  setExplicitOrganizationId(opts.organizationId);
466036
- await reloadListenerModAdapter(runtime);
466268
+ if (!resumedRuntime)
466269
+ await reloadListenerModAdapter(runtime);
466037
466270
  await connectWithRetry(runtime, opts);
466038
466271
  }
466039
466272
  async function startLocalChannelListener(opts) {
@@ -466081,6 +466314,9 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466081
466314
  if (attempt2 > 0) {
466082
466315
  if (elapsedTime >= MAX_RETRY_DURATION_MS) {
466083
466316
  if (runtime.everConnected && opts.onNeedsReregister) {
466317
+ rejectPendingExternalToolCallsForConnection(runtime, opts.connectionId, "Listener connection re-registered");
466318
+ killListenerConnectionTerminals(opts.connectionId);
466319
+ revokeRecoveryClaims(runtime, opts.connectionId);
466084
466320
  opts.onNeedsReregister(createListenerClientReplacement(runtime, opts));
466085
466321
  return;
466086
466322
  }
@@ -466124,6 +466360,7 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466124
466360
  const headers = { Authorization: `Bearer ${apiKey}` };
466125
466361
  const socket = new WebSocket11(url2.toString(), { headers });
466126
466362
  let streamSocket = streamUrl && !pairIdentity ? new WebSocket11(streamUrl.toString(), { headers }) : null;
466363
+ const lifecycleLog = createListenerLifecycleLog(opts);
466127
466364
  const fileCommandSession = createFileCommandSession({
466128
466365
  socket,
466129
466366
  safeSocketSend,
@@ -466162,7 +466399,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466162
466399
  attachSplitStreamSocketHandlers({
466163
466400
  runtime,
466164
466401
  streamSocket,
466165
- trackListenerError: trackListenerError4
466402
+ trackListenerError: trackListenerError4,
466403
+ log: lifecycleLog
466166
466404
  });
466167
466405
  }
466168
466406
  socket.on("open", () => {
@@ -466192,7 +466430,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466192
466430
  attachSplitStreamSocketHandlers({
466193
466431
  runtime,
466194
466432
  streamSocket: streamOpen.streamSocket,
466195
- trackListenerError: trackListenerError4
466433
+ trackListenerError: trackListenerError4,
466434
+ log: lifecycleLog
466196
466435
  });
466197
466436
  }
466198
466437
  if (!isCurrentSocketPair(runtime, socket, streamSocket))
@@ -466231,9 +466470,12 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466231
466470
  recordListenerPong(runtime, socket);
466232
466471
  return;
466233
466472
  }
466473
+ if (!isCurrentSocketPair(runtime, socket, streamSocket))
466474
+ return;
466234
466475
  pendingStartupFrames.accept(data, handleMessage);
466235
466476
  });
466236
466477
  socket.on("close", (code2, reason) => {
466478
+ lifecycleLog(formatListenerSocketClose("control", code2, reason));
466237
466479
  abortStartupIngress();
466238
466480
  if (!shouldHandleControlSocketClose(runtime, socket, opts.connectionId)) {
466239
466481
  return;
@@ -466245,14 +466487,11 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466245
466487
  });
466246
466488
  fileCommandSession.dispose();
466247
466489
  const reasonText = reason.toString();
466248
- const terminalClose = runtime.intentionallyClosed || code2 === 1008 || code2 === 1000 && reasonText === "Replaced by new connection";
466490
+ const terminalClose = runtime.intentionallyClosed || code2 === 1008 && reasonText !== CLOUD_ENVIRONMENT_NOT_FOUND_CLOSE_REASON || code2 === 1000 && reasonText === "Replaced by new connection";
466249
466491
  if (!terminalClose && runtime.hasSuccessfulConnection) {
466250
466492
  opts.onRetrying?.(0, MAX_RETRY_ATTEMPTS, 0, opts.connectionId);
466251
466493
  }
466252
466494
  clearRuntimeTimers(runtime);
466253
- if (isDebugEnabled()) {
466254
- console.log(`[Listen] WebSocket disconnected (code: ${code2}, reason: ${reason.toString()})`);
466255
- }
466256
466495
  if (!terminalClose) {
466257
466496
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
466258
466497
  rejectPendingApprovalResolversForConnection(conversationRuntime, opts.connectionId, "Listener connection closed");
@@ -466264,7 +466503,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466264
466503
  revokeRecoveryClaims(runtime, undefined, closingGeneration);
466265
466504
  }
466266
466505
  suspendListenerConnection(runtime, opts.connectionId);
466267
- killAllTerminals();
466506
+ if (terminalClose)
466507
+ killAllTerminals();
466268
466508
  clearListenerWarmState(runtime);
466269
466509
  if (streamSocket) {
466270
466510
  streamSocket.removeAllListeners("message");
@@ -466277,27 +466517,21 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466277
466517
  runtime.socket = null;
466278
466518
  runtime.streamSocket = null;
466279
466519
  runtime.streamTransport = null;
466280
- if (terminalClose) {
466281
- const replacement = code2 === 1008 ? createListenerClientReplacement(runtime, opts) : null;
466282
- if (getActiveRuntime() === runtime) {
466520
+ if (code2 === 1008 && !terminalClose && opts.onNeedsReregister) {
466521
+ rejectPendingExternalToolCallsForConnection(runtime, opts.connectionId, "Listener connection re-registered");
466522
+ killListenerConnectionTerminals(opts.connectionId);
466523
+ revokeRecoveryClaims(runtime, opts.connectionId);
466524
+ opts.onNeedsReregister(createListenerClientReplacement(runtime, opts));
466525
+ return;
466526
+ }
466527
+ if (terminalClose || code2 === 1008) {
466528
+ if (getActiveRuntime() === runtime)
466283
466529
  setActiveRuntime(null);
466284
- }
466285
466530
  stopRuntime(runtime, true);
466286
- if (code2 === 1008) {
466287
- if (isDebugEnabled()) {
466288
- console.log("[Listen] Environment not found, re-registering...");
466289
- }
466290
- if (opts.onNeedsReregister) {
466291
- if (!replacement) {
466292
- throw new Error("Missing listener replacement lineage");
466293
- }
466294
- opts.onNeedsReregister(replacement);
466295
- } else {
466296
- opts.onDisconnected();
466297
- }
466298
- return;
466299
- }
466300
- opts.onDisconnected();
466531
+ if (code2 === 1008 && opts.onNeedsReregister)
466532
+ opts.onNeedsReregister();
466533
+ else
466534
+ opts.onDisconnected();
466301
466535
  return;
466302
466536
  }
466303
466537
  const nextAttempt = runtime.hasSuccessfulConnection ? 0 : attempt2 + 1;
@@ -466308,7 +466542,10 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466308
466542
  });
466309
466543
  });
466310
466544
  socket.on("error", (error5) => {
466545
+ if (runtime.socket !== socket)
466546
+ return;
466311
466547
  trackListenerError4("listener_websocket_error", error5, "listener_socket");
466548
+ lifecycleLog(`control socket error: ${error5.message}`);
466312
466549
  safeEmitWsEvent("recv", "lifecycle", {
466313
466550
  type: "_ws_error",
466314
466551
  message: error5.message
@@ -466347,6 +466584,7 @@ var init_lifecycle = __esm(async () => {
466347
466584
  init_listener_task();
466348
466585
  init_permission_mode();
466349
466586
  init_socket_send();
466587
+ init_startup_deadline();
466350
466588
  init_startup_frame_buffer();
466351
466589
  init_startup_ingress();
466352
466590
  init_stream_observers();
@@ -469669,7 +469907,7 @@ async function runListenSubcommand(argv) {
469669
469907
  },
469670
469908
  onConnected: () => {},
469671
469909
  onConnectionReady: async (connectedId) => {
469672
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
469910
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469673
469911
  if (!ready)
469674
469912
  return;
469675
469913
  sessionLog.log("Local channel listener ready.");
@@ -469752,7 +469990,8 @@ async function runListenSubcommand(argv) {
469752
469990
  console.log(`[${formatTimestamp3()}] ${arrow}${tag} ${json2}`);
469753
469991
  }
469754
469992
  };
469755
- if (debugMode || lifecycleOutput) {
469993
+ if (shouldUseNonInteractiveListenerOutput(debugMode, !!lifecycleOutput)) {
469994
+ const printPlainLines = debugMode || !lifecycleOutput;
469756
469995
  const startNonInteractiveClient = async (connId, url2, nextSupportsSplitStatusChannels, nextSupportsPairedListenerGenerations, replacement) => {
469757
469996
  await startListenerClient2({
469758
469997
  replacement,
@@ -469768,18 +470007,18 @@ async function runListenSubcommand(argv) {
469768
470007
  onStatusChange: (status) => {
469769
470008
  sessionLog.log(`status: ${status}`);
469770
470009
  readiness.setStatus(status);
469771
- if (debugMode) {
470010
+ if (printPlainLines) {
469772
470011
  console.log(`[${formatTimestamp3()}] status: ${status}`);
469773
470012
  }
469774
470013
  },
469775
470014
  onLog: logListenerMessage,
469776
470015
  onConnected: () => {},
469777
470016
  onConnectionReady: async (connectedId) => {
469778
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
470017
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469779
470018
  if (!ready)
469780
470019
  return;
469781
470020
  sessionLog.log("Connected. Awaiting instructions.");
469782
- if (debugMode) {
470021
+ if (printPlainLines) {
469783
470022
  console.log(`[${formatTimestamp3()}] Connected. Awaiting instructions.`);
469784
470023
  console.log("");
469785
470024
  }
@@ -469787,13 +470026,13 @@ async function runListenSubcommand(argv) {
469787
470026
  onRetrying: (attempt2, _maxAttempts, nextRetryIn) => {
469788
470027
  readiness.setCloudReconnecting();
469789
470028
  sessionLog.log(`Reconnecting (attempt ${attempt2}, retry in ${Math.round(nextRetryIn / 1000)}s)`);
469790
- if (debugMode) {
470029
+ if (printPlainLines) {
469791
470030
  console.log(`[${formatTimestamp3()}] Reconnecting (attempt ${attempt2}, retry in ${Math.round(nextRetryIn / 1000)}s)`);
469792
470031
  }
469793
470032
  },
469794
470033
  onNeedsReregister: async (replacement2) => {
469795
470034
  readiness.setCloudReconnecting();
469796
- if (debugMode) {
470035
+ if (printPlainLines) {
469797
470036
  console.log(`[${formatTimestamp3()}] Computer connection expired, re-registering...`);
469798
470037
  }
469799
470038
  try {
@@ -469855,7 +470094,7 @@ async function runListenSubcommand(argv) {
469855
470094
  onLog: logListenerMessage,
469856
470095
  onConnected: () => {},
469857
470096
  onConnectionReady: async (connectedId) => {
469858
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
470097
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469859
470098
  if (!ready)
469860
470099
  return;
469861
470100
  sessionLog.log("Connected. Awaiting instructions.");
@@ -469958,7 +470197,7 @@ var init_listen = __esm(async () => {
469958
470197
  import { randomUUID as randomUUID55 } from "node:crypto";
469959
470198
  import {
469960
470199
  copyFileSync as copyFileSync3,
469961
- existsSync as existsSync64,
470200
+ existsSync as existsSync63,
469962
470201
  mkdirSync as mkdirSync47,
469963
470202
  readdirSync as readdirSync26,
469964
470203
  readFileSync as readFileSync48,
@@ -469966,7 +470205,7 @@ import {
469966
470205
  } from "node:fs";
469967
470206
  import { join as join94 } from "node:path";
469968
470207
  function readJsonl(path46) {
469969
- if (!existsSync64(path46))
470208
+ if (!existsSync63(path46))
469970
470209
  return [];
469971
470210
  return readFileSync48(path46, "utf8").split(`
469972
470211
  `).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
@@ -470254,13 +470493,13 @@ function migrateLocalBackendTranscripts(input) {
470254
470493
  skipped: [],
470255
470494
  dryRun: input.dryRun === true
470256
470495
  };
470257
- if (!existsSync64(conversationsDir))
470496
+ if (!existsSync63(conversationsDir))
470258
470497
  return result3;
470259
470498
  for (const name of readdirSync26(conversationsDir)) {
470260
470499
  const conversationDir = join94(conversationsDir, name);
470261
470500
  const messagesPath = join94(conversationDir, "messages.jsonl");
470262
470501
  const manifestPath = join94(conversationDir, "manifest.json");
470263
- const hasManifest = existsSync64(manifestPath);
470502
+ const hasManifest = existsSync63(manifestPath);
470264
470503
  const existingManifest = hasManifest ? (() => {
470265
470504
  try {
470266
470505
  return JSON.parse(readFileSync48(manifestPath, "utf8"));
@@ -470304,7 +470543,7 @@ function migrateLocalBackendTranscripts(input) {
470304
470543
  copyFileSync3(messagesPath, backupPath);
470305
470544
  const conversationPath = join94(conversationDir, "conversation.json");
470306
470545
  let conversation;
470307
- if (existsSync64(conversationPath)) {
470546
+ if (existsSync63(conversationPath)) {
470308
470547
  try {
470309
470548
  conversation = JSON.parse(readFileSync48(conversationPath, "utf8"));
470310
470549
  } catch {
@@ -470498,7 +470737,7 @@ var init_memory_tokens = __esm(() => {
470498
470737
  });
470499
470738
 
470500
470739
  // src/cli/subcommands/memory.ts
470501
- import { cpSync, existsSync as existsSync65, mkdirSync as mkdirSync48, rmSync as rmSync22, statSync as statSync24 } from "node:fs";
470740
+ import { cpSync, existsSync as existsSync64, mkdirSync as mkdirSync48, rmSync as rmSync22, statSync as statSync24 } from "node:fs";
470502
470741
  import { readdir as readdir12 } from "node:fs/promises";
470503
470742
  import { dirname as dirname37, join as join95 } from "node:path";
470504
470743
  import { parseArgs as parseArgs11 } from "node:util";
@@ -470560,7 +470799,7 @@ function formatBackupTimestamp(date5 = new Date) {
470560
470799
  }
470561
470800
  async function listBackups(agentId) {
470562
470801
  const agentRoot = getAgentRoot(agentId);
470563
- if (!existsSync65(agentRoot)) {
470802
+ if (!existsSync64(agentRoot)) {
470564
470803
  return [];
470565
470804
  }
470566
470805
  const entries2 = await readdir12(agentRoot, { withFileTypes: true });
@@ -470665,14 +470904,14 @@ async function runMemorySubcommand(argv, deps = {}) {
470665
470904
  }
470666
470905
  if (action3 === "backup") {
470667
470906
  const root2 = getMemoryRoot(agentId);
470668
- if (!existsSync65(root2)) {
470907
+ if (!existsSync64(root2)) {
470669
470908
  console.error(`Memory directory not found for agent ${agentId}.`);
470670
470909
  return 1;
470671
470910
  }
470672
470911
  const agentRoot = getAgentRoot(agentId);
470673
470912
  const backupName = `memory-backup-${formatBackupTimestamp()}`;
470674
470913
  const backupPath = join95(agentRoot, backupName);
470675
- if (existsSync65(backupPath)) {
470914
+ if (existsSync64(backupPath)) {
470676
470915
  console.error(`Backup already exists at ${backupPath}`);
470677
470916
  return 1;
470678
470917
  }
@@ -470696,7 +470935,7 @@ async function runMemorySubcommand(argv, deps = {}) {
470696
470935
  return 1;
470697
470936
  }
470698
470937
  const backupPath = resolveBackupPath(agentId, from);
470699
- if (!existsSync65(backupPath)) {
470938
+ if (!existsSync64(backupPath)) {
470700
470939
  console.error(`Backup not found: ${backupPath}`);
470701
470940
  return 1;
470702
470941
  }
@@ -470718,11 +470957,11 @@ async function runMemorySubcommand(argv, deps = {}) {
470718
470957
  return 1;
470719
470958
  }
470720
470959
  const root2 = getMemoryRoot(agentId);
470721
- if (!existsSync65(root2)) {
470960
+ if (!existsSync64(root2)) {
470722
470961
  console.error(`Memory directory not found for agent ${agentId}.`);
470723
470962
  return 1;
470724
470963
  }
470725
- if (existsSync65(out)) {
470964
+ if (existsSync64(out)) {
470726
470965
  const stat15 = statSync24(out);
470727
470966
  if (stat15.isDirectory()) {
470728
470967
  const contents = await readdir12(out);
@@ -470771,10 +471010,10 @@ var init_memory7 = __esm(() => {
470771
471010
  });
470772
471011
 
470773
471012
  // src/backend/local/transcript-search.ts
470774
- import { existsSync as existsSync66, readdirSync as readdirSync27, readFileSync as readFileSync49, statSync as statSync25 } from "node:fs";
471013
+ import { existsSync as existsSync65, readdirSync as readdirSync27, readFileSync as readFileSync49, statSync as statSync25 } from "node:fs";
470775
471014
  import { join as join96 } from "node:path";
470776
471015
  function readJsonFile3(path46) {
470777
- if (!existsSync66(path46))
471016
+ if (!existsSync65(path46))
470778
471017
  return;
470779
471018
  try {
470780
471019
  return JSON.parse(readFileSync49(path46, "utf8"));
@@ -471056,7 +471295,7 @@ function collectConversationMessages(input) {
471056
471295
  }
471057
471296
  function conversationDirectories(storageDir) {
471058
471297
  const conversationsDir = join96(storageDir, "conversations");
471059
- if (!existsSync66(conversationsDir))
471298
+ if (!existsSync65(conversationsDir))
471060
471299
  return [];
471061
471300
  try {
471062
471301
  return readdirSync27(conversationsDir).map((entry) => join96(conversationsDir, entry)).filter((entryPath) => statSync25(entryPath).isDirectory());
@@ -471970,13 +472209,13 @@ var init_model2 = __esm(() => {
471970
472209
  import { spawn as spawn13 } from "node:child_process";
471971
472210
  import {
471972
472211
  copyFileSync as copyFileSync4,
471973
- existsSync as existsSync67,
471974
- lstatSync as lstatSync3,
472212
+ existsSync as existsSync66,
472213
+ lstatSync as lstatSync4,
471975
472214
  mkdirSync as mkdirSync49,
471976
472215
  mkdtempSync as mkdtempSync5,
471977
472216
  readdirSync as readdirSync28,
471978
472217
  readFileSync as readFileSync50,
471979
- renameSync as renameSync14,
472218
+ renameSync as renameSync11,
471980
472219
  rmSync as rmSync23,
471981
472220
  writeFileSync as writeFileSync40
471982
472221
  } from "node:fs";
@@ -472019,7 +472258,7 @@ function formatRepository(repository) {
472019
472258
  function isLocalLettaModPackageDirectory(packageDirectory) {
472020
472259
  const resolvedPackageDirectory = path46.resolve(packageDirectory);
472021
472260
  try {
472022
- const packageStats = lstatSync3(resolvedPackageDirectory);
472261
+ const packageStats = lstatSync4(resolvedPackageDirectory);
472023
472262
  if (packageStats.isSymbolicLink() || !packageStats.isDirectory()) {
472024
472263
  return false;
472025
472264
  }
@@ -472046,7 +472285,7 @@ function validateManifestEntriesExist(packageRoot, entries2) {
472046
472285
  const entryPath = resolvePackageRelativePath(packageRoot, entry);
472047
472286
  let stats;
472048
472287
  try {
472049
- stats = lstatSync3(entryPath);
472288
+ stats = lstatSync4(entryPath);
472050
472289
  } catch {
472051
472290
  throw new Error(`Package mod entry does not exist: ${entry}`);
472052
472291
  }
@@ -472062,7 +472301,7 @@ function resolvePackageDirectory(packageDirectory) {
472062
472301
  const resolvedPackageDirectory = path46.resolve(packageDirectory);
472063
472302
  let packageStats;
472064
472303
  try {
472065
- packageStats = lstatSync3(resolvedPackageDirectory);
472304
+ packageStats = lstatSync4(resolvedPackageDirectory);
472066
472305
  } catch {
472067
472306
  throw new Error(`Package directory does not exist: ${packageDirectory}`);
472068
472307
  }
@@ -472120,7 +472359,7 @@ function copyPackageDirectory(sourceRoot, targetRoot) {
472120
472359
  continue;
472121
472360
  const sourcePath = path46.join(sourceRoot, entry.name);
472122
472361
  const targetPath = path46.join(targetRoot, entry.name);
472123
- const stats = lstatSync3(sourcePath);
472362
+ const stats = lstatSync4(sourcePath);
472124
472363
  if (stats.isSymbolicLink()) {
472125
472364
  throw new Error(`Package contains unsupported symlink: ${sourcePath}`);
472126
472365
  }
@@ -472154,7 +472393,7 @@ function copyDependencyDirectoryFiltered(params) {
472154
472393
  }
472155
472394
  const sourcePath = path46.join(params.sourceRoot, entry.name);
472156
472395
  const targetPath = path46.join(params.targetRoot, entry.name);
472157
- const stats = lstatSync3(sourcePath);
472396
+ const stats = lstatSync4(sourcePath);
472158
472397
  if (stats.isSymbolicLink()) {
472159
472398
  throw new Error(`Package dependency contains unsupported symlink: ${sourcePath}`);
472160
472399
  }
@@ -472179,7 +472418,7 @@ function copyDependencyDirectoryFiltered(params) {
472179
472418
  return copied;
472180
472419
  }
472181
472420
  function copyDependencyNodeModules(params) {
472182
- if (!existsSync67(params.sourceNodeModulesDirectory))
472421
+ if (!existsSync66(params.sourceNodeModulesDirectory))
472183
472422
  return;
472184
472423
  copyDependencyDirectoryFiltered({
472185
472424
  installedPackageName: params.installedPackageName,
@@ -472189,7 +472428,7 @@ function copyDependencyNodeModules(params) {
472189
472428
  }
472190
472429
  function copyPackageInternalNodeModules(params) {
472191
472430
  const sourceNodeModulesDirectory = path46.join(params.packageDirectory, "node_modules");
472192
- if (!existsSync67(sourceNodeModulesDirectory))
472431
+ if (!existsSync66(sourceNodeModulesDirectory))
472193
472432
  return;
472194
472433
  copyDependencyDirectoryFiltered({
472195
472434
  sourceRoot: sourceNodeModulesDirectory,
@@ -472211,12 +472450,12 @@ function removeIfExists(targetPath) {
472211
472450
  }
472212
472451
  function restoreDestination(params) {
472213
472452
  rmSync23(params.destinationRoot, { force: true, recursive: true });
472214
- if (params.backupRoot && existsSync67(params.backupRoot)) {
472215
- renameSync14(params.backupRoot, params.destinationRoot);
472453
+ if (params.backupRoot && existsSync66(params.backupRoot)) {
472454
+ renameSync11(params.backupRoot, params.destinationRoot);
472216
472455
  }
472217
472456
  }
472218
472457
  function restoreDestinationIfNeeded(params) {
472219
- if (!params.backupRoot || !existsSync67(params.backupRoot)) {
472458
+ if (!params.backupRoot || !existsSync66(params.backupRoot)) {
472220
472459
  rmSync23(params.destinationRoot, { force: true, recursive: true });
472221
472460
  return;
472222
472461
  }
@@ -472257,13 +472496,13 @@ function installPreparedManagedModPackage(params) {
472257
472496
  targetPackageRoot: stagingRoot
472258
472497
  });
472259
472498
  }
472260
- if (existsSync67(destinationRoot)) {
472499
+ if (existsSync66(destinationRoot)) {
472261
472500
  backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
472262
472501
  rmSync23(backupRoot, { force: true, recursive: true });
472263
- renameSync14(destinationRoot, backupRoot);
472502
+ renameSync11(destinationRoot, backupRoot);
472264
472503
  destinationNeedsRollback = true;
472265
472504
  }
472266
- renameSync14(stagingRoot, destinationRoot);
472505
+ renameSync11(stagingRoot, destinationRoot);
472267
472506
  destinationNeedsRollback = true;
472268
472507
  stagingRoot = null;
472269
472508
  try {
@@ -472542,13 +472781,13 @@ function hasRuntimeDependencies(packageJson) {
472542
472781
  }
472543
472782
  function readPackageJsonIfExists(packageDirectory) {
472544
472783
  const packageJsonPath = path46.join(packageDirectory, "package.json");
472545
- if (!existsSync67(packageJsonPath))
472784
+ if (!existsSync66(packageJsonPath))
472546
472785
  return null;
472547
472786
  return readPackageJson(packageJsonPath);
472548
472787
  }
472549
472788
  function isRegularModFile(filePath) {
472550
472789
  try {
472551
- const stats = lstatSync3(filePath);
472790
+ const stats = lstatSync4(filePath);
472552
472791
  return !stats.isSymbolicLink() && stats.isFile();
472553
472792
  } catch {
472554
472793
  return false;
@@ -472556,8 +472795,8 @@ function isRegularModFile(filePath) {
472556
472795
  }
472557
472796
  function inferCompatibilityModEntries(packageDirectory) {
472558
472797
  const modsDirectory = path46.join(packageDirectory, "mods");
472559
- if (existsSync67(modsDirectory)) {
472560
- const stats = lstatSync3(modsDirectory);
472798
+ if (existsSync66(modsDirectory)) {
472799
+ const stats = lstatSync4(modsDirectory);
472561
472800
  if (stats.isSymbolicLink()) {
472562
472801
  throw new Error(`Package mods directory must not be a symlink: mods`);
472563
472802
  }
@@ -472831,8 +473070,8 @@ var init_package_installer = __esm(() => {
472831
473070
  // src/mods/package-scaffolder.ts
472832
473071
  import {
472833
473072
  copyFileSync as copyFileSync5,
472834
- existsSync as existsSync68,
472835
- lstatSync as lstatSync4,
473073
+ existsSync as existsSync67,
473074
+ lstatSync as lstatSync5,
472836
473075
  mkdirSync as mkdirSync50,
472837
473076
  rmSync as rmSync24,
472838
473077
  writeFileSync as writeFileSync41
@@ -472858,7 +473097,7 @@ function readSourceFile(sourceFile) {
472858
473097
  const resolvedSourceFile = path47.resolve(sourceFile);
472859
473098
  let stats;
472860
473099
  try {
472861
- stats = lstatSync4(resolvedSourceFile);
473100
+ stats = lstatSync5(resolvedSourceFile);
472862
473101
  } catch {
472863
473102
  throw new Error(`Mod file does not exist: ${sourceFile}`);
472864
473103
  }
@@ -472924,7 +473163,7 @@ function scaffoldLocalModPackage(options) {
472924
473163
  const sourceFile = readSourceFile(options.sourceFile);
472925
473164
  const packageName = assertValidPackageName(options.packageName);
472926
473165
  const outputDirectory = path47.resolve(options.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
472927
- if (existsSync68(outputDirectory)) {
473166
+ if (existsSync67(outputDirectory)) {
472928
473167
  throw new Error(`Output directory already exists: ${outputDirectory}`);
472929
473168
  }
472930
473169
  const modFileName = path47.basename(sourceFile);
@@ -473480,7 +473719,7 @@ var init_sandbox_files = __esm(() => {
473480
473719
 
473481
473720
  // src/cli/subcommands/sandbox.ts
473482
473721
  import { readFile as readFile27, stat as stat15, writeFile as writeFile19 } from "node:fs/promises";
473483
- import { basename as basename28, resolve as resolve40 } from "node:path";
473722
+ import { basename as basename29, resolve as resolve40 } from "node:path";
473484
473723
  import { parseArgs as parseArgs16 } from "node:util";
473485
473724
  function printUsage13() {
473486
473725
  console.log(`
@@ -473631,13 +473870,13 @@ async function runSandboxSubcommand(argv, deps = {}) {
473631
473870
  throw new Error(`${localPath2} is not a file`);
473632
473871
  const data2 = await (deps.readLocalFile ?? readFile27)(localPath2);
473633
473872
  const sandbox2 = await ensureSandbox();
473634
- const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename28(localPath2) });
473873
+ const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename29(localPath2) });
473635
473874
  console.log(JSON.stringify({ ...result3, ...targetOutput }, null, 2));
473636
473875
  return 0;
473637
473876
  }
473638
473877
  const sandbox = await ensureSandbox();
473639
473878
  const data = await (deps.downloadFile ?? downloadFileFromSandbox)(sandbox.sandboxId, path48);
473640
- const localPath = resolve40(parsed.values.to ?? basename28(path48));
473879
+ const localPath = resolve40(parsed.values.to ?? basename29(path48));
473641
473880
  await (deps.writeLocalFile ?? writeFile19)(localPath, data);
473642
473881
  console.log(JSON.stringify({
473643
473882
  path: localPath,
@@ -474547,7 +474786,7 @@ var init_setup7 = __esm(async () => {
474547
474786
  });
474548
474787
 
474549
474788
  // src/cli/subcommands/shared-memory.ts
474550
- import { existsSync as existsSync69 } from "node:fs";
474789
+ import { existsSync as existsSync68 } from "node:fs";
474551
474790
  import { join as join98 } from "node:path";
474552
474791
  import { parseArgs as parseArgs19 } from "node:util";
474553
474792
  function printUsage16() {
@@ -474740,7 +474979,7 @@ async function runSharedMemorySubcommand(argv, deps = {}) {
474740
474979
  invalidateClientSkills(agentId);
474741
474980
  const recompileError = await recompileAndReportFailure(recompileAgent, agentId);
474742
474981
  const mountDir = getRepositoryMountDir(agentId, repository.name);
474743
- const mounted = existsSync69(join98(mountDir, ".git"));
474982
+ const mounted = existsSync68(join98(mountDir, ".git"));
474744
474983
  console.log(JSON.stringify({
474745
474984
  attached: true,
474746
474985
  repository: { id: repository.id, name: repository.name },
@@ -476269,7 +476508,7 @@ var init_AgentSelector = __esm(async () => {
476269
476508
  // src/cli/subcommands/skills.ts
476270
476509
  import {
476271
476510
  cpSync as cpSync2,
476272
- existsSync as existsSync70,
476511
+ existsSync as existsSync69,
476273
476512
  mkdtempSync as mkdtempSync6,
476274
476513
  readFileSync as readFileSync51,
476275
476514
  rmSync as rmSync25,
@@ -476278,7 +476517,7 @@ import {
476278
476517
  } from "node:fs";
476279
476518
  import { mkdir as mkdir16, readdir as readdir13 } from "node:fs/promises";
476280
476519
  import { tmpdir as tmpdir14 } from "node:os";
476281
- import { basename as basename29, dirname as dirname39, join as join99, normalize as normalize4, resolve as resolve41, sep as sep8 } from "node:path";
476520
+ import { basename as basename30, dirname as dirname39, join as join99, normalize as normalize4, resolve as resolve41, sep as sep8 } from "node:path";
476282
476521
  import { parseArgs as parseArgs20, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
476283
476522
  function printUsage17() {
476284
476523
  console.log(`
@@ -476473,7 +476712,7 @@ function parseDirectSkillFileUrlSpecifier(input) {
476473
476712
  if (url2.protocol !== "https:" && !(url2.protocol === "http:" && isLocalhostHostname(url2.hostname))) {
476474
476713
  return null;
476475
476714
  }
476476
- if (basename29(url2.pathname).toLowerCase() !== "skill.md")
476715
+ if (basename30(url2.pathname).toLowerCase() !== "skill.md")
476477
476716
  return null;
476478
476717
  return { url: url2.toString() };
476479
476718
  }
@@ -476721,14 +476960,14 @@ function getSkillName(sourceDir) {
476721
476960
  const skillMd = readFileSync51(join99(sourceDir, "SKILL.md"), "utf8");
476722
476961
  const { frontmatter } = parseFrontmatter(skillMd);
476723
476962
  const frontmatterName = frontmatter.name;
476724
- const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename29(sourceDir);
476963
+ const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename30(sourceDir);
476725
476964
  return sanitizeSkillName(name);
476726
476965
  }
476727
476966
  async function installSkillDirectory(params) {
476728
476967
  const sourceDir = resolve41(params.sourceDir);
476729
476968
  const memoryDir = resolve41(params.memoryDir);
476730
476969
  const skillMdPath = join99(sourceDir, "SKILL.md");
476731
- if (!existsSync70(skillMdPath)) {
476970
+ if (!existsSync69(skillMdPath)) {
476732
476971
  throw new Error("No SKILL.md found in the skill directory.");
476733
476972
  }
476734
476973
  if (!statSync26(sourceDir).isDirectory()) {
@@ -476738,7 +476977,7 @@ async function installSkillDirectory(params) {
476738
476977
  const skillsDir = join99(memoryDir, "skills");
476739
476978
  const targetPath = join99(skillsDir, name);
476740
476979
  assertInside(skillsDir, targetPath);
476741
- if (existsSync70(targetPath)) {
476980
+ if (existsSync69(targetPath)) {
476742
476981
  if (!params.force) {
476743
476982
  throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
476744
476983
  }
@@ -476747,14 +476986,14 @@ async function installSkillDirectory(params) {
476747
476986
  await mkdir16(skillsDir, { recursive: true });
476748
476987
  cpSync2(sourceDir, targetPath, {
476749
476988
  recursive: true,
476750
- filter: (source) => basename29(source) !== ".git"
476989
+ filter: (source) => basename30(source) !== ".git"
476751
476990
  });
476752
476991
  return { name, path: normalize4(targetPath) };
476753
476992
  }
476754
476993
  async function listSkillDirectories(params) {
476755
476994
  const memoryDir = resolve41(params.memoryDir);
476756
476995
  const skillsDir = join99(memoryDir, "skills");
476757
- if (!existsSync70(skillsDir))
476996
+ if (!existsSync69(skillsDir))
476758
476997
  return [];
476759
476998
  const entries2 = await readdir13(skillsDir, { withFileTypes: true });
476760
476999
  const skills = [];
@@ -476763,7 +477002,7 @@ async function listSkillDirectories(params) {
476763
477002
  continue;
476764
477003
  const skillDir = join99(skillsDir, entry.name);
476765
477004
  const skillMdPath = join99(skillDir, "SKILL.md");
476766
- if (!existsSync70(skillMdPath))
477005
+ if (!existsSync69(skillMdPath))
476767
477006
  continue;
476768
477007
  let name = entry.name;
476769
477008
  let description;
@@ -476787,7 +477026,7 @@ async function deleteSkillDirectory(params) {
476787
477026
  const name = sanitizeSkillName(params.name);
476788
477027
  const targetPath = join99(skillsDir, name);
476789
477028
  assertInside(skillsDir, targetPath);
476790
- if (!existsSync70(targetPath)) {
477029
+ if (!existsSync69(targetPath)) {
476791
477030
  throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
476792
477031
  }
476793
477032
  if (!statSync26(targetPath).isDirectory()) {
@@ -476836,7 +477075,7 @@ async function installSkill(specifier, agentId, force) {
476836
477075
  tmpDir = downloaded.tmpDir;
476837
477076
  const sourceDir = resolve41(downloaded.sourceDir);
476838
477077
  assertInside(tmpDir, sourceDir);
476839
- if (!existsSync70(sourceDir)) {
477078
+ if (!existsSync69(sourceDir)) {
476840
477079
  const missingPath = source.type === "git" ? source.location.subdir ?? "." : source.type === "direct-file" ? source.location.url : source.location.slug;
476841
477080
  throw new Error(`Skill path not found: ${missingPath}`);
476842
477081
  }
@@ -477467,7 +477706,7 @@ import {
477467
477706
  stat as stat17,
477468
477707
  writeFile as writeFile20
477469
477708
  } from "node:fs/promises";
477470
- import { basename as basename30, join as join101 } from "node:path";
477709
+ import { basename as basename31, join as join101 } from "node:path";
477471
477710
  function fileTimestamp(startedAt) {
477472
477711
  if (!startedAt)
477473
477712
  return "unknown-date";
@@ -477635,10 +477874,10 @@ async function runTrajectoryExport(options) {
477635
477874
  if (!supported.includes(explicit.source)) {
477636
477875
  throw new Error(`Unknown source "${explicit.source}" in --transcript. The installed trajectory package supports: ${supported.join(", ")}.`);
477637
477876
  }
477638
- await exportTranscript(explicit.source, basename30(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile29(explicit.path, "utf-8"));
477877
+ await exportTranscript(explicit.source, basename31(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile29(explicit.path, "utf-8"));
477639
477878
  }
477640
477879
  for (const checkpoint of options.deepagents ?? []) {
477641
- await exportCheckpoint(checkpoint, `${basename30(checkpoint.path)}-${checkpoint.threadId}`);
477880
+ await exportCheckpoint(checkpoint, `${basename31(checkpoint.path)}-${checkpoint.threadId}`);
477642
477881
  }
477643
477882
  manifest2.sessions.sort((a2, b3) => (a2.startedAt ?? "").localeCompare(b3.startedAt ?? ""));
477644
477883
  await writeFile20(join101(options.outDir, MANIFEST_NAME), JSON.stringify(manifest2, null, 2), "utf-8");
@@ -481086,7 +481325,7 @@ var init_message_channel_gateway_tool = __esm(() => {
481086
481325
  });
481087
481326
 
481088
481327
  // src/channels/custom/scaffolding.ts
481089
- import { existsSync as existsSync71, mkdirSync as mkdirSync51, rmSync as rmSync26, writeFileSync as writeFileSync43 } from "node:fs";
481328
+ import { existsSync as existsSync70, mkdirSync as mkdirSync51, rmSync as rmSync26, writeFileSync as writeFileSync43 } from "node:fs";
481090
481329
  function removeUserPlugin(channelId) {
481091
481330
  if (FIRST_PARTY_SET.has(channelId)) {
481092
481331
  return;
@@ -481095,7 +481334,7 @@ function removeUserPlugin(channelId) {
481095
481334
  return;
481096
481335
  }
481097
481336
  const channelDir = getChannelDir(channelId);
481098
- if (!existsSync71(channelDir)) {
481337
+ if (!existsSync70(channelDir)) {
481099
481338
  return;
481100
481339
  }
481101
481340
  try {
@@ -487874,7 +488113,7 @@ var BYTES_PER_TOKEN = 4;
487874
488113
 
487875
488114
  // src/cli/helpers/window-title-config.ts
487876
488115
  import { homedir as homedir55 } from "node:os";
487877
- import { basename as basename31, resolve as resolve42 } from "node:path";
488116
+ import { basename as basename32, resolve as resolve42 } from "node:path";
487878
488117
  function isWindowTitleField(value) {
487879
488118
  return WINDOW_TITLE_FIELDS.includes(value);
487880
488119
  }
@@ -488033,7 +488272,7 @@ function terminalTitleProjectName(data) {
488033
488272
  if (!directory)
488034
488273
  return null;
488035
488274
  const resolved2 = resolve42(directory);
488036
- const name = basename31(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
488275
+ const name = basename32(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
488037
488276
  return truncateTerminalTitlePart(name, 24);
488038
488277
  }
488039
488278
  function titleDirectory(data) {
@@ -488715,7 +488954,7 @@ var init_cli_mod_context = __esm(() => {
488715
488954
 
488716
488955
  // src/cli/helpers/reflection-arena-hf-upload.ts
488717
488956
  import { execFile as execFileCb5 } from "node:child_process";
488718
- import { existsSync as existsSync73 } from "node:fs";
488957
+ import { existsSync as existsSync72 } from "node:fs";
488719
488958
  import { appendFile as appendFile3, chmod, mkdir as mkdir18, writeFile as writeFile21 } from "node:fs/promises";
488720
488959
  import { homedir as homedir56 } from "node:os";
488721
488960
  import { join as join105 } from "node:path";
@@ -488769,7 +489008,7 @@ async function writeGitAskpass(repoRoot) {
488769
489008
  }
488770
489009
  async function prepareHfRepo(env6) {
488771
489010
  await mkdir18(HF_CACHE_ROOT, { recursive: true });
488772
- if (!existsSync73(join105(HF_REPO_DIR, ".git"))) {
489011
+ if (!existsSync72(join105(HF_REPO_DIR, ".git"))) {
488773
489012
  await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env6);
488774
489013
  return HF_REPO_DIR;
488775
489014
  }
@@ -490328,7 +490567,7 @@ __export(exports_terminal_keybinding_installer, {
490328
490567
  });
490329
490568
  import {
490330
490569
  copyFileSync as copyFileSync6,
490331
- existsSync as existsSync74,
490570
+ existsSync as existsSync73,
490332
490571
  mkdirSync as mkdirSync53,
490333
490572
  readFileSync as readFileSync53,
490334
490573
  writeFileSync as writeFileSync45
@@ -490397,7 +490636,7 @@ function parseKeybindings(content) {
490397
490636
  }
490398
490637
  }
490399
490638
  function keybindingExists(keybindingsPath) {
490400
- if (!existsSync74(keybindingsPath))
490639
+ if (!existsSync73(keybindingsPath))
490401
490640
  return false;
490402
490641
  try {
490403
490642
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
@@ -490410,7 +490649,7 @@ function keybindingExists(keybindingsPath) {
490410
490649
  }
490411
490650
  }
490412
490651
  function createBackup(keybindingsPath) {
490413
- if (!existsSync74(keybindingsPath))
490652
+ if (!existsSync73(keybindingsPath))
490414
490653
  return null;
490415
490654
  const backupPath = `${keybindingsPath}.letta-backup`;
490416
490655
  try {
@@ -490426,12 +490665,12 @@ function installKeybinding(keybindingsPath) {
490426
490665
  return { success: true, alreadyExists: true };
490427
490666
  }
490428
490667
  const parentDir = dirname40(keybindingsPath);
490429
- if (!existsSync74(parentDir)) {
490668
+ if (!existsSync73(parentDir)) {
490430
490669
  mkdirSync53(parentDir, { recursive: true });
490431
490670
  }
490432
490671
  let keybindings = [];
490433
490672
  let backupPath = null;
490434
- if (existsSync74(keybindingsPath)) {
490673
+ if (existsSync73(keybindingsPath)) {
490435
490674
  backupPath = createBackup(keybindingsPath);
490436
490675
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
490437
490676
  const parsed = parseKeybindings(content);
@@ -490461,7 +490700,7 @@ function installKeybinding(keybindingsPath) {
490461
490700
  }
490462
490701
  function removeKeybinding(keybindingsPath) {
490463
490702
  try {
490464
- if (!existsSync74(keybindingsPath)) {
490703
+ if (!existsSync73(keybindingsPath)) {
490465
490704
  return { success: true };
490466
490705
  }
490467
490706
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
@@ -490529,11 +490768,11 @@ function getWezTermConfigPath() {
490529
490768
  const xdgConfig = process.env.XDG_CONFIG_HOME;
490530
490769
  if (xdgConfig) {
490531
490770
  const xdgPath = join107(xdgConfig, "wezterm", "wezterm.lua");
490532
- if (existsSync74(xdgPath))
490771
+ if (existsSync73(xdgPath))
490533
490772
  return xdgPath;
490534
490773
  }
490535
490774
  const configPath = join107(homedir58(), ".config", "wezterm", "wezterm.lua");
490536
- if (existsSync74(configPath))
490775
+ if (existsSync73(configPath))
490537
490776
  return configPath;
490538
490777
  return join107(homedir58(), ".wezterm.lua");
490539
490778
  }
@@ -490638,7 +490877,7 @@ ${WEZTERM_DELETE_FIX}
490638
490877
  `;
490639
490878
  }
490640
490879
  function wezTermDeleteFixExists(configPath) {
490641
- if (!existsSync74(configPath))
490880
+ if (!existsSync73(configPath))
490642
490881
  return false;
490643
490882
  try {
490644
490883
  const content = readFileSync53(configPath, { encoding: "utf-8" });
@@ -490655,14 +490894,14 @@ function installWezTermDeleteFix() {
490655
490894
  }
490656
490895
  let content = "";
490657
490896
  let backupPath = null;
490658
- if (existsSync74(configPath)) {
490897
+ if (existsSync73(configPath)) {
490659
490898
  backupPath = `${configPath}.letta-backup`;
490660
490899
  copyFileSync6(configPath, backupPath);
490661
490900
  content = readFileSync53(configPath, { encoding: "utf-8" });
490662
490901
  }
490663
490902
  content = injectWezTermDeleteFix(content);
490664
490903
  const parentDir = dirname40(configPath);
490665
- if (!existsSync74(parentDir)) {
490904
+ if (!existsSync73(parentDir)) {
490666
490905
  mkdirSync53(parentDir, { recursive: true });
490667
490906
  }
490668
490907
  writeFileSync45(configPath, content, { encoding: "utf-8" });
@@ -492659,9 +492898,9 @@ function getHeaderText(fileEdit) {
492659
492898
  const relPath = relative13(cwd2, fileEdit.filePath);
492660
492899
  const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
492661
492900
  if (t2 === "write") {
492662
- const { existsSync: existsSync75 } = __require("node:fs");
492901
+ const { existsSync: existsSync74 } = __require("node:fs");
492663
492902
  try {
492664
- if (existsSync75(fileEdit.filePath)) {
492903
+ if (existsSync74(fileEdit.filePath)) {
492665
492904
  return `Overwrite ${displayPath}?`;
492666
492905
  }
492667
492906
  } catch {}
@@ -501578,9 +501817,9 @@ var init_InputRich = __esm(async () => {
501578
501817
  });
501579
501818
 
501580
501819
  // src/cli/commands/install-github-app.ts
501581
- import { execFileSync as execFileSync10 } from "node:child_process";
501820
+ import { execFileSync as execFileSync12 } from "node:child_process";
501582
501821
  import {
501583
- existsSync as existsSync75,
501822
+ existsSync as existsSync74,
501584
501823
  mkdirSync as mkdirSync54,
501585
501824
  mkdtempSync as mkdtempSync7,
501586
501825
  readFileSync as readFileSync54,
@@ -501591,7 +501830,7 @@ import { tmpdir as tmpdir15 } from "node:os";
501591
501830
  import { dirname as dirname41, join as join109 } from "node:path";
501592
501831
  function runCommand(command, args, cwd2, input) {
501593
501832
  try {
501594
- return execFileSync10(command, args, {
501833
+ return execFileSync12(command, args, {
501595
501834
  cwd: cwd2,
501596
501835
  encoding: "utf8",
501597
501836
  stdio: [input ? "pipe" : "ignore", "pipe", "pipe"],
@@ -501822,12 +502061,12 @@ function runGit7(args, cwd2) {
501822
502061
  }
501823
502062
  function writeWorkflow(repoDir, workflowPath, content) {
501824
502063
  const absolutePath = join109(repoDir, workflowPath);
501825
- if (!existsSync75(dirname41(absolutePath))) {
502064
+ if (!existsSync74(dirname41(absolutePath))) {
501826
502065
  mkdirSync54(dirname41(absolutePath), { recursive: true });
501827
502066
  }
501828
502067
  const next = `${content.trimEnd()}
501829
502068
  `;
501830
- if (existsSync75(absolutePath)) {
502069
+ if (existsSync74(absolutePath)) {
501831
502070
  const previous = readFileSync54(absolutePath, "utf8");
501832
502071
  if (previous === next) {
501833
502072
  return false;
@@ -505717,7 +505956,7 @@ __export(exports_generate_memory_viewer, {
505717
505956
  generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
505718
505957
  });
505719
505958
  import { execFile as execFileCb7 } from "node:child_process";
505720
- import { chmodSync as chmodSync8, existsSync as existsSync76, mkdirSync as mkdirSync55, writeFileSync as writeFileSync47 } from "node:fs";
505959
+ import { chmodSync as chmodSync8, existsSync as existsSync75, mkdirSync as mkdirSync55, writeFileSync as writeFileSync47 } from "node:fs";
505721
505960
  import { homedir as homedir61 } from "node:os";
505722
505961
  import { join as join110 } from "node:path";
505723
505962
  import { promisify as promisify22 } from "node:util";
@@ -506028,7 +506267,7 @@ ${m4.body}` : m4.subject;
506028
506267
  async function generateAndOpenMemoryViewer(agentId, options) {
506029
506268
  const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
506030
506269
  const repoDir = memoryRoot;
506031
- if (!existsSync76(join110(repoDir, ".git"))) {
506270
+ if (!existsSync75(join110(repoDir, ".git"))) {
506032
506271
  throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
506033
506272
  }
506034
506273
  const data = await collectMemoryData(agentId, repoDir, memoryRoot, options?.conversationId);
@@ -506038,7 +506277,7 @@ async function generateAndOpenMemoryViewer(agentId, options) {
506038
506277
  data.context = applyContextUsageSnapshot(data.context, options?.contextUsage);
506039
506278
  const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
506040
506279
  const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
506041
- if (!existsSync76(VIEWERS_DIR)) {
506280
+ if (!existsSync75(VIEWERS_DIR)) {
506042
506281
  mkdirSync55(VIEWERS_DIR, { recursive: true, mode: 448 });
506043
506282
  }
506044
506283
  try {
@@ -506075,7 +506314,7 @@ var init_generate_memory_viewer = __esm(() => {
506075
506314
  });
506076
506315
 
506077
506316
  // src/cli/components/MemfsTreeViewer.tsx
506078
- import { existsSync as existsSync77 } from "node:fs";
506317
+ import { existsSync as existsSync76 } from "node:fs";
506079
506318
  import { join as join111 } from "node:path";
506080
506319
  function renderTreePrefix(node) {
506081
506320
  let prefix = "";
@@ -506104,8 +506343,8 @@ function MemfsTreeViewer({
506104
506343
  const [status, setStatus] = import_react88.useState(null);
506105
506344
  const statusTimerRef = import_react88.useRef(null);
506106
506345
  const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
506107
- const memoryExists = existsSync77(memoryRoot);
506108
- const hasGitRepo = import_react88.useMemo(() => existsSync77(join111(memoryRoot, ".git")), [memoryRoot]);
506346
+ const memoryExists = existsSync76(memoryRoot);
506347
+ const hasGitRepo = import_react88.useMemo(() => existsSync76(join111(memoryRoot, ".git")), [memoryRoot]);
506109
506348
  function showStatus(msg, durationMs) {
506110
506349
  if (statusTimerRef.current)
506111
506350
  clearTimeout(statusTimerRef.current);
@@ -514952,9 +515191,9 @@ function getFileEditHeader(toolName2, toolArgs) {
514952
515191
  const relPath = relative13(cwd2, filePath);
514953
515192
  const displayPath = relPath.startsWith("..") ? filePath : relPath;
514954
515193
  if (t2 === "write") {
514955
- const { existsSync: existsSync78 } = __require("node:fs");
515194
+ const { existsSync: existsSync77 } = __require("node:fs");
514956
515195
  try {
514957
- if (existsSync78(filePath)) {
515196
+ if (existsSync77(filePath)) {
514958
515197
  return `Overwrite ${displayPath}?`;
514959
515198
  }
514960
515199
  } catch {}
@@ -516722,7 +516961,7 @@ __export(exports_generate_diff_viewer, {
516722
516961
  generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
516723
516962
  });
516724
516963
  import { execFile as execFileCb8 } from "node:child_process";
516725
- import { chmodSync as chmodSync9, existsSync as existsSync78, mkdirSync as mkdirSync56, writeFileSync as writeFileSync48 } from "node:fs";
516964
+ import { chmodSync as chmodSync9, existsSync as existsSync77, mkdirSync as mkdirSync56, writeFileSync as writeFileSync48 } from "node:fs";
516726
516965
  import { homedir as homedir63 } from "node:os";
516727
516966
  import { isAbsolute as isAbsolute27, join as join113, resolve as resolve44 } from "node:path";
516728
516967
  import { promisify as promisify23 } from "node:util";
@@ -516947,7 +517186,7 @@ async function generateAndOpenDiffViewer(targetPath) {
516947
517186
  };
516948
517187
  const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
516949
517188
  const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
516950
- if (!existsSync78(VIEWERS_DIR2)) {
517189
+ if (!existsSync77(VIEWERS_DIR2)) {
516951
517190
  mkdirSync56(VIEWERS_DIR2, { recursive: true, mode: 448 });
516952
517191
  }
516953
517192
  try {
@@ -518983,12 +519222,12 @@ __export(exports_shell_aliases, {
518983
519222
  expandAliases: () => expandAliases,
518984
519223
  clearAliasCache: () => clearAliasCache
518985
519224
  });
518986
- import { existsSync as existsSync79, readFileSync as readFileSync55 } from "node:fs";
519225
+ import { existsSync as existsSync78, readFileSync as readFileSync55 } from "node:fs";
518987
519226
  import { homedir as homedir64 } from "node:os";
518988
519227
  import { join as join114 } from "node:path";
518989
519228
  function parseAliasesFromFile(filePath) {
518990
519229
  const aliases = new Map;
518991
- if (!existsSync79(filePath)) {
519230
+ if (!existsSync78(filePath)) {
518992
519231
  return aliases;
518993
519232
  }
518994
519233
  try {
@@ -520203,6 +520442,16 @@ var init_retry2 = __esm(() => {
520203
520442
  function stripSystemReminders2(text3) {
520204
520443
  return text3.replace(new RegExp(`${SYSTEM_REMINDER_OPEN}[\\s\\S]*?${SYSTEM_REMINDER_CLOSE}`, "g"), "").replace(new RegExp(`${SYSTEM_ALERT_OPEN}[\\s\\S]*?${SYSTEM_ALERT_CLOSE}`, "g"), "").trim();
520205
520444
  }
520445
+ function getRestorableUserText(input) {
520446
+ const message2 = input.find((item) => item?.type === "message");
520447
+ const content = message2 && "content" in message2 ? message2.content : undefined;
520448
+ if (typeof content === "string")
520449
+ return stripSystemReminders2(content);
520450
+ if (!Array.isArray(content))
520451
+ return "";
520452
+ return content.flatMap((c) => c.type === "text" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN) ? [c.text] : []).join(`
520453
+ `).trim();
520454
+ }
520206
520455
  var init_system_reminders2 = __esm(() => {
520207
520456
  init_constants2();
520208
520457
  });
@@ -520735,20 +520984,9 @@ function useConversationLoop(ctx) {
520735
520984
  const agent = await getBackend().retrieveAgent(agentIdRef.current);
520736
520985
  const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend(agent, conversationIdRef.current);
520737
520986
  if (serverApprovals && serverApprovals.length > 0) {
520738
- const userMessage = currentInput.find((item) => item?.type === "message");
520739
- if (userMessage && "content" in userMessage) {
520740
- const content = userMessage.content;
520741
- let textToRestore = "";
520742
- if (typeof content === "string") {
520743
- textToRestore = stripSystemReminders2(content);
520744
- } else if (Array.isArray(content)) {
520745
- textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN)).map((c) => c.text).join(`
520746
- `);
520747
- }
520748
- if (textToRestore.trim()) {
520749
- setRestoredInput(textToRestore);
520750
- }
520751
- }
520987
+ const textToRestore = getRestorableUserText(currentInput);
520988
+ if (textToRestore)
520989
+ setRestoredInput(textToRestore);
520752
520990
  setApprovalResults([]);
520753
520991
  setAutoHandledResults([]);
520754
520992
  setAutoDeniedApprovals([]);
@@ -520766,6 +521004,13 @@ function useConversationLoop(ctx) {
520766
521004
  sendDesktopNotification("Approval needed");
520767
521005
  return;
520768
521006
  }
521007
+ const plainInput = rebuildInputWithFreshDenials(currentInput, [], "");
521008
+ if (plainInput.length > 0 && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES3) {
521009
+ llmApiErrorRetriesRef.current += 1;
521010
+ currentInput = plainInput;
521011
+ buffersRef.current.interrupted = false;
521012
+ continue;
521013
+ }
520769
521014
  } catch {}
520770
521015
  }
520771
521016
  }
@@ -521371,20 +521616,9 @@ ${feedback}
521371
521616
  const agent = await getBackend().retrieveAgent(agentIdRef.current);
521372
521617
  const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend(agent, conversationIdRef.current);
521373
521618
  if (serverApprovals && serverApprovals.length > 0) {
521374
- const userMessage = currentInput.find((item) => item?.type === "message");
521375
- if (userMessage && "content" in userMessage) {
521376
- const content = userMessage.content;
521377
- let textToRestore = "";
521378
- if (typeof content === "string") {
521379
- textToRestore = stripSystemReminders2(content);
521380
- } else if (Array.isArray(content)) {
521381
- textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN)).map((c) => c.text).join(`
521382
- `);
521383
- }
521384
- if (textToRestore.trim()) {
521385
- setRestoredInput(textToRestore);
521386
- }
521387
- }
521619
+ const textToRestore = getRestorableUserText(currentInput);
521620
+ if (textToRestore)
521621
+ setRestoredInput(textToRestore);
521388
521622
  setApprovalResults([]);
521389
521623
  setAutoHandledResults([]);
521390
521624
  setAutoDeniedApprovals([]);
@@ -521402,6 +521636,13 @@ ${feedback}
521402
521636
  sendDesktopNotification("Approval needed");
521403
521637
  return;
521404
521638
  }
521639
+ const plainInput = rebuildInputWithFreshDenials(currentInput, [], "");
521640
+ if (plainInput.length > 0 && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES3) {
521641
+ llmApiErrorRetriesRef.current += 1;
521642
+ currentInput = plainInput;
521643
+ buffersRef.current.interrupted = false;
521644
+ continue;
521645
+ }
521405
521646
  } catch {}
521406
521647
  }
521407
521648
  const approvalPendingDetected = isApprovalPendingError(detailFromRun) || isApprovalPendingError(latestErrorText);
@@ -521751,7 +521992,6 @@ var init_use_conversation_loop = __esm(async () => {
521751
521992
  init_reflection_transcript();
521752
521993
  init_thinking_messages();
521753
521994
  init_tool_name_mapping2();
521754
- init_constants2();
521755
521995
  init_hooks();
521756
521996
  init_format_denial();
521757
521997
  init_mode();
@@ -527088,7 +527328,7 @@ __export(exports_worktree_diff_list, {
527088
527328
  listWorktreeDiffOptions: () => listWorktreeDiffOptions
527089
527329
  });
527090
527330
  import { execFile as execFileCb9 } from "node:child_process";
527091
- import { basename as basename32 } from "node:path";
527331
+ import { basename as basename33 } from "node:path";
527092
527332
  import { promisify as promisify24 } from "node:util";
527093
527333
  async function runGit9(cwd2, args) {
527094
527334
  try {
@@ -527137,7 +527377,7 @@ function parseWorktreeList(output, currentPath) {
527137
527377
  if (current?.path) {
527138
527378
  worktrees.push({
527139
527379
  path: current.path,
527140
- name: basename32(current.path),
527380
+ name: basename33(current.path),
527141
527381
  branch: current.branch ?? "detached",
527142
527382
  head: current.head ?? "",
527143
527383
  isCurrent: current.path === currentPath,
@@ -527163,7 +527403,7 @@ function parseWorktreeList(output, currentPath) {
527163
527403
  if (current?.path) {
527164
527404
  worktrees.push({
527165
527405
  path: current.path,
527166
- name: basename32(current.path),
527406
+ name: basename33(current.path),
527167
527407
  branch: current.branch ?? "detached",
527168
527408
  head: current.head ?? "",
527169
527409
  isCurrent: current.path === currentPath,
@@ -527320,7 +527560,7 @@ var init_conversation_switch_alert = __esm(() => {
527320
527560
 
527321
527561
  // src/cli/app/use-submit-handler.ts
527322
527562
  import { randomUUID as randomUUID67 } from "node:crypto";
527323
- import { existsSync as existsSync80, readFileSync as readFileSync56, renameSync as renameSync15 } from "node:fs";
527563
+ import { existsSync as existsSync79, readFileSync as readFileSync56, renameSync as renameSync12 } from "node:fs";
527324
527564
  import { tmpdir as tmpdir16 } from "node:os";
527325
527565
  import { join as join115 } from "node:path";
527326
527566
  async function findCustomCommandByName(commandName) {
@@ -527933,7 +528173,7 @@ ${SYSTEM_REMINDER_CLOSE}`),
527933
528173
  join115(memoryRoot, "system", "persona.md"),
527934
528174
  join115(memoryRoot, "memory", "system", "persona.md")
527935
528175
  ];
527936
- const personaPath = personaCandidates.find((candidate) => existsSync80(candidate));
528176
+ const personaPath = personaCandidates.find((candidate) => existsSync79(candidate));
527937
528177
  if (personaPath) {
527938
528178
  const personaContent = readFileSync56(personaPath, "utf-8");
527939
528179
  setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
@@ -528775,12 +529015,12 @@ Path: ${memoryDir}`, true);
528775
529015
  setCommandRunning(true);
528776
529016
  try {
528777
529017
  const memoryDir = getScopedMemoryFilesystemRoot(agentId);
528778
- if (!existsSync80(memoryDir)) {
529018
+ if (!existsSync79(memoryDir)) {
528779
529019
  updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
528780
529020
  return { submitted: true };
528781
529021
  }
528782
529022
  const backupDir = join115(tmpdir16(), `letta-memfs-reset-${agentId}-${Date.now()}`);
528783
- renameSync15(memoryDir, backupDir);
529023
+ renameSync12(memoryDir, backupDir);
528784
529024
  if (getBackend().capabilities.localMemfs) {
528785
529025
  const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
528786
529026
  await initializeLocalMemoryRepo2({
@@ -531733,9 +531973,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
531733
531973
  (async () => {
531734
531974
  try {
531735
531975
  const { watch: watch4 } = await import("node:fs");
531736
- const { existsSync: existsSync81 } = await import("node:fs");
531976
+ const { existsSync: existsSync80 } = await import("node:fs");
531737
531977
  const memRoot = getScopedMemoryFilesystemRoot(agentId);
531738
- if (!existsSync81(memRoot))
531978
+ if (!existsSync80(memRoot))
531739
531979
  return;
531740
531980
  watcher2 = watch4(memRoot, { recursive: true }, () => {});
531741
531981
  memfsWatcherRef.current = watcher2;
@@ -533536,7 +533776,9 @@ async function main() {
533536
533776
  }
533537
533777
  const subcommandResult = await runSubcommand(subcommandArgs);
533538
533778
  if (subcommandResult !== null) {
533539
- process.exit(subcommandResult);
533779
+ process.channel?.unref();
533780
+ process.exitCode = subcommandResult;
533781
+ return;
533540
533782
  }
533541
533783
  await settingsManager.initialize();
533542
533784
  const settings3 = await settingsManager.getSettingsWithSecureTokens();
@@ -537155,4 +537397,4 @@ function registerBunOAuthFlows() {
537155
537397
  registerBunOAuthFlows();
537156
537398
  await init_src5().then(() => exports_src2);
537157
537399
 
537158
- //# debugId=835D7F3E2C67DB2C64756E2164756E21
537400
+ //# debugId=B1F6CA2886AACEA464756E2164756E21