@letta-ai/letta-code 0.34.23 → 0.34.25

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 (79) 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 +6 -5
  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/shell-launchers.d.ts.map +1 -1
  39. package/dist/types/tools/impl/wake.d.ts +4 -2
  40. package/dist/types/tools/impl/wake.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 +876 -614
  67. package/npm-shrinkwrap.json +18 -18
  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/codex-watch/release-analysis.test.ts +70 -0
  73. package/scripts/codex-watch/release-analysis.ts +5 -5
  74. package/scripts/source-file-size-baseline.json +3 -3
  75. package/skills/maintaining-deferred-memory/SKILL.md +2 -0
  76. package/skills/scheduling-tasks/SKILL.md +1 -1
  77. package/skills/working-across-computers/references/connect-a-computer-for-remote-access.md +2 -2
  78. package/dist/types/websocket/listener/mcp-originator-scope.d.ts +0 -9
  79. 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.23",
5970
+ version: "0.34.25",
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-75ArKlsNj6BLjfiYR7ejV9jl0U3L7r1mXtWLYoNBVFkpR+NgT29dy3I6c7xawN3klfWjTCPVa5kpHtS7gVbD0A==",
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 };
@@ -186483,11 +186516,11 @@ async function listCloudSchedules(agentId, options = {}) {
186483
186516
  }
186484
186517
  });
186485
186518
  }
186486
- async function getCloudSchedule(agentId, scheduleId) {
186487
- return apiRequest("GET", `${schedulePath(agentId)}/${encodeURIComponent(scheduleId)}`);
186519
+ async function getCloudSchedule(agentId, scheduleId, actingUserId) {
186520
+ return apiRequest("GET", `${schedulePath(agentId)}/${encodeURIComponent(scheduleId)}`, undefined, actingUserRequestOptions(actingUserId));
186488
186521
  }
186489
- async function deleteCloudSchedule(agentId, scheduleId) {
186490
- await apiRequest("DELETE", `${schedulePath(agentId)}/${encodeURIComponent(scheduleId)}`, {});
186522
+ async function deleteCloudSchedule(agentId, scheduleId, actingUserId) {
186523
+ await apiRequest("DELETE", `${schedulePath(agentId)}/${encodeURIComponent(scheduleId)}`, {}, actingUserRequestOptions(actingUserId));
186491
186524
  }
186492
186525
  async function listCloudScheduleHistory(agentId, scheduleId, options = {}) {
186493
186526
  return apiRequest("GET", `${schedulePath(agentId)}/${encodeURIComponent(scheduleId)}/history`, undefined, {
@@ -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.23"
210999
+ version: "0.34.25"
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();
@@ -240547,25 +240616,41 @@ async function cancelWake(args, scope, deps) {
240547
240616
  const id2 = args.id?.trim();
240548
240617
  if (!id2)
240549
240618
  throw new Error("Wake cancel requires id.");
240550
- const current = await listCurrentWakes(scope, args, deps);
240551
- const wake = current.wakes.find((candidate) => candidate.id === id2);
240552
- if (!wake) {
240553
- if (current.warnings.length > 0) {
240554
- throw new Error(current.warnings[0]);
240619
+ args.signal?.throwIfAborted();
240620
+ const local = (deps.getLocal ?? getTask)(id2);
240621
+ if (local?.agent_id === scope.agentId && local.conversation_id === scope.conversationId && (local.status === "active" || local.status === "paused")) {
240622
+ if (!(deps.deleteLocal ?? deleteTask)(id2)) {
240623
+ throw new Error(`Wake ${id2} was already removed.`);
240555
240624
  }
240625
+ return result2("success", {
240626
+ action: "cancelled",
240627
+ id: id2,
240628
+ runner: "local",
240629
+ warnings: []
240630
+ });
240631
+ }
240632
+ if (resolveBackendMode() === "local" || isLocalAgentId(scope.agentId)) {
240556
240633
  throw new Error(`Wake ${id2} was not found in the current conversation.`);
240557
240634
  }
240558
- args.signal?.throwIfAborted();
240559
- if (wake.runner === "cloud") {
240560
- await (deps.deleteCloud ?? deleteCloudSchedule)(scope.agentId, id2);
240561
- } else if (!(deps.deleteLocal ?? deleteTask)(id2)) {
240562
- throw new Error(`Wake ${id2} was already removed.`);
240635
+ let cloud;
240636
+ try {
240637
+ cloud = await (deps.getCloud ?? getCloudSchedule)(scope.agentId, id2, getRuntimeActingUserId());
240638
+ } catch (error5) {
240639
+ if (error5 instanceof ApiRequestError && (error5.status === 404 || error5.status === 405)) {
240640
+ throw new Error(`Wake ${id2} was not found in the current conversation.`);
240641
+ }
240642
+ throw error5;
240643
+ }
240644
+ if (cloud.conversation_id !== scope.conversationId) {
240645
+ throw new Error(`Wake ${id2} was not found in the current conversation.`);
240563
240646
  }
240647
+ args.signal?.throwIfAborted();
240648
+ await (deps.deleteCloud ?? deleteCloudSchedule)(scope.agentId, id2, getRuntimeActingUserId());
240564
240649
  return result2("success", {
240565
240650
  action: "cancelled",
240566
240651
  id: id2,
240567
- runner: wake.runner,
240568
- warnings: current.warnings
240652
+ runner: "cloud",
240653
+ warnings: []
240569
240654
  });
240570
240655
  }
240571
240656
  async function wake(args, deps = {}) {
@@ -243307,7 +243392,7 @@ class CodexAppServerClient {
243307
243392
  await this.request("initialize", {
243308
243393
  clientInfo: {
243309
243394
  name: "letta-code",
243310
- version: "0.34.23"
243395
+ version: "0.34.25"
243311
243396
  },
243312
243397
  capabilities: null
243313
243398
  });
@@ -244017,7 +244102,7 @@ var init_conversation_bootstrap = __esm(() => {
244017
244102
 
244018
244103
  // src/cli/helpers/session-context.ts
244019
244104
  import { platform as platform7 } from "node:os";
244020
- import { basename as basename20 } from "node:path";
244105
+ import { basename as basename21 } from "node:path";
244021
244106
  function getLocalTime() {
244022
244107
  const now2 = new Date;
244023
244108
  return now2.toLocaleString(undefined, {
@@ -244061,7 +244146,7 @@ function getGitInfo(cwd2) {
244061
244146
  };
244062
244147
  }
244063
244148
  function buildUnixShellLine(shellContext) {
244064
- const shellName = basename20(shellContext.displayName) || shellContext.displayName;
244149
+ const shellName = basename21(shellContext.displayName) || shellContext.displayName;
244065
244150
  return `- **Shell**: ${shellName}
244066
244151
  `;
244067
244152
  }
@@ -246771,7 +246856,7 @@ function isAppServerInfoResponseMessage(message2) {
246771
246856
  return false;
246772
246857
  }
246773
246858
  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";
246859
+ 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
246860
  }
246776
246861
  var APP_SERVER_PROTOCOL_VERSION = 1;
246777
246862
 
@@ -248740,7 +248825,7 @@ var init_memory_operation = __esm(() => {
248740
248825
  // src/agent/memory-worktree.ts
248741
248826
  import { execFile as execFileCb4 } from "node:child_process";
248742
248827
  import { randomUUID as randomUUID41 } from "node:crypto";
248743
- import { existsSync as existsSync46 } from "node:fs";
248828
+ import { existsSync as existsSync45 } from "node:fs";
248744
248829
  import { mkdir as mkdir12 } from "node:fs/promises";
248745
248830
  import { dirname as dirname29, isAbsolute as isAbsolute23, join as join67, resolve as resolve36 } from "node:path";
248746
248831
  import { promisify as promisify17 } from "node:util";
@@ -248932,7 +249017,7 @@ async function inspectReflectionMemoryWorktree(worktree) {
248932
249017
  };
248933
249018
  }
248934
249019
  async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName, options = {}) {
248935
- const removedWorktree = existsSync46(worktreeDir);
249020
+ const removedWorktree = existsSync45(worktreeDir);
248936
249021
  if (removedWorktree) {
248937
249022
  await runGit4(parentMemoryDir, [
248938
249023
  "worktree",
@@ -248948,7 +249033,7 @@ async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName
248948
249033
  ]);
248949
249034
  }
248950
249035
  async function finalizeReflectionMemoryWorktreeUnlocked(worktree, options) {
248951
- if (!existsSync46(worktree.worktreeDir) && options.knownNoChanges) {
249036
+ if (!existsSync45(worktree.worktreeDir) && options.knownNoChanges) {
248952
249037
  const branchHead = (await tryRunGit(worktree.parentMemoryDir, [
248953
249038
  "rev-parse",
248954
249039
  "--verify",
@@ -249135,7 +249220,7 @@ async function integrateMemoryWorkerWorktree(worktree, options = {}) {
249135
249220
  await cleanup(true);
249136
249221
  return { status: "no_changes" };
249137
249222
  }
249138
- if (existsSync46(worktree.worktreeDir)) {
249223
+ if (existsSync45(worktree.worktreeDir)) {
249139
249224
  await runGit4(worktree.parentMemoryDir, [
249140
249225
  "worktree",
249141
249226
  "remove",
@@ -251200,7 +251285,7 @@ __export(exports_skill, {
251200
251285
  loadRenderedSkillContent: () => loadRenderedSkillContent,
251201
251286
  getResolvedSkillsDir: () => getResolvedSkillsDir
251202
251287
  });
251203
- import { existsSync as existsSync47, readdirSync as readdirSync17 } from "node:fs";
251288
+ import { existsSync as existsSync46, readdirSync as readdirSync17 } from "node:fs";
251204
251289
  import { readFile as readFile17 } from "node:fs/promises";
251205
251290
  import { dirname as dirname30, join as join68 } from "node:path";
251206
251291
  async function readSkillFromRoot(skillsRoot, skillId) {
@@ -251222,7 +251307,7 @@ async function readSkillFromRoot(skillsRoot, skillId) {
251222
251307
  function getMemorySkillsDirs2(agentId) {
251223
251308
  const dirs = new Set;
251224
251309
  const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
251225
- if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync47(scopedMemoryDir)) {
251310
+ if (scopedMemoryDir && scopedMemoryDir.trim().length > 0 && existsSync46(scopedMemoryDir)) {
251226
251311
  dirs.add(join68(scopedMemoryDir.trim(), "skills"));
251227
251312
  } else {
251228
251313
  const fallbackMemoryDir = (process.env.LETTA_MEMORY_DIR || process.env.MEMORY_DIR || "").trim();
@@ -252799,7 +252884,7 @@ var init_watch_pr = __esm(async () => {
252799
252884
  });
252800
252885
 
252801
252886
  // src/tools/workflow/sdk-loader.ts
252802
- import { existsSync as existsSync48, readFileSync as readFileSync37 } from "node:fs";
252887
+ import { existsSync as existsSync47, readFileSync as readFileSync37 } from "node:fs";
252803
252888
  import { createRequire as createRequire6 } from "node:module";
252804
252889
  import { dirname as dirname31, join as join69 } from "node:path";
252805
252890
  import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL3 } from "node:url";
@@ -252823,7 +252908,7 @@ function preferRunningCliForSubagents() {
252823
252908
  if (process.env.LETTA_CLI_PATH)
252824
252909
  return;
252825
252910
  const entry = process.argv[1];
252826
- if (entry && /(^|[\\/])letta\.js$/.test(entry) && existsSync48(entry)) {
252911
+ if (entry && /(^|[\\/])letta\.js$/.test(entry) && existsSync47(entry)) {
252827
252912
  process.env.LETTA_CLI_PATH = entry;
252828
252913
  }
252829
252914
  }
@@ -252854,7 +252939,7 @@ function probeInstalledSdkDirs(startDirs) {
252854
252939
  let dir = start2;
252855
252940
  while (true) {
252856
252941
  const candidate = join69(dir, "node_modules", ...SDK_PACKAGE.split("/"));
252857
- if (existsSync48(join69(candidate, "package.json")) && !found.includes(candidate)) {
252942
+ if (existsSync47(join69(candidate, "package.json")) && !found.includes(candidate)) {
252858
252943
  found.push(candidate);
252859
252944
  }
252860
252945
  const parent = dirname31(dir);
@@ -255327,15 +255412,28 @@ var init_interrupted_turn_schema = __esm(async () => {
255327
255412
  await init_teleport_protocol_inbound();
255328
255413
  });
255329
255414
 
255415
+ // src/utils/rename-sync-with-retry.ts
255416
+ import { renameSync as renameSync10 } from "node:fs";
255417
+ function renameSyncWithRetry(source, destination, platform9 = process.platform, rename3 = renameSync10) {
255418
+ const sleeper = new Int32Array(new SharedArrayBuffer(4));
255419
+ for (let attempt2 = 0;; attempt2++) {
255420
+ try {
255421
+ rename3(source, destination);
255422
+ return;
255423
+ } catch (error5) {
255424
+ const code2 = error5.code;
255425
+ if (platform9 !== "win32" || attempt2 >= 9 || !["EPERM", "EACCES", "EBUSY"].includes(code2 ?? "")) {
255426
+ throw error5;
255427
+ }
255428
+ Atomics.wait(sleeper, 0, 0, 10 * (attempt2 + 1));
255429
+ }
255430
+ }
255431
+ }
255432
+ var init_rename_sync_with_retry = () => {};
255433
+
255330
255434
  // src/websocket/listener/interrupted-turn-storage.ts
255331
255435
  import { createHash as createHash11 } from "node:crypto";
255332
- import {
255333
- closeSync as closeSync7,
255334
- fsyncSync as fsyncSync4,
255335
- openSync as openSync7,
255336
- renameSync as renameSync10,
255337
- writeFileSync as writeFileSync29
255338
- } from "node:fs";
255436
+ import { closeSync as closeSync7, fsyncSync as fsyncSync4, openSync as openSync7, writeFileSync as writeFileSync29 } from "node:fs";
255339
255437
  import { homedir as homedir35 } from "node:os";
255340
255438
  import { join as join71 } from "node:path";
255341
255439
  function writeInterruptedTurnRecordFile(temporary, destination, directory, record6, syncDirectory) {
@@ -255343,7 +255441,7 @@ function writeInterruptedTurnRecordFile(temporary, destination, directory, recor
255343
255441
  mode: 384,
255344
255442
  flush: true
255345
255443
  });
255346
- renameSync10(temporary, destination);
255444
+ renameSyncWithRetry(temporary, destination);
255347
255445
  syncDirectory(directory);
255348
255446
  }
255349
255447
  function fsyncInterruptedTurnDirectory(directory, platform9 = process.platform) {
@@ -255367,6 +255465,7 @@ function defaultInterruptedTurnDirectory() {
255367
255465
  }
255368
255466
  var init_interrupted_turn_storage = __esm(() => {
255369
255467
  init_server_url();
255468
+ init_rename_sync_with_retry();
255370
255469
  });
255371
255470
 
255372
255471
  // src/websocket/listener/recorded-tool-results.ts
@@ -255432,11 +255531,10 @@ function createRecoveryAuthorityGuard(dependencies4) {
255432
255531
  // src/websocket/listener/recovery-lineage-sidecar.ts
255433
255532
  import { createHash as createHash12, randomUUID as randomUUID44 } from "node:crypto";
255434
255533
  import {
255435
- existsSync as existsSync49,
255534
+ existsSync as existsSync48,
255436
255535
  mkdirSync as mkdirSync35,
255437
255536
  readdirSync as readdirSync18,
255438
255537
  readFileSync as readFileSync39,
255439
- renameSync as renameSync11,
255440
255538
  rmSync as rmSync18,
255441
255539
  statSync as statSync19,
255442
255540
  writeFileSync as writeFileSync30
@@ -255477,7 +255575,7 @@ function createRecoveryLineageSidecarAccess(params) {
255477
255575
  mode: 384,
255478
255576
  flush: true
255479
255577
  });
255480
- renameSync11(temporary, destination);
255578
+ renameSyncWithRetry(temporary, destination);
255481
255579
  params.syncDirectory(params.directory);
255482
255580
  } finally {
255483
255581
  rmSync18(temporary, { force: true });
@@ -255727,7 +255825,7 @@ function createRecoveryLineageSidecarAccess(params) {
255727
255825
  const removeMalformedOrphan = (file) => {
255728
255826
  const separator = file.indexOf(".recovery-");
255729
255827
  const mainFile = separator >= 0 ? file.slice(0, separator) : "";
255730
- if (!mainFile || existsSync49(join72(params.directory, mainFile)))
255828
+ if (!mainFile || existsSync48(join72(params.directory, mainFile)))
255731
255829
  return;
255732
255830
  try {
255733
255831
  rmSync18(join72(params.directory, file), { force: true });
@@ -255809,6 +255907,7 @@ function createRecoveryLineageSidecarAccess(params) {
255809
255907
  }
255810
255908
  var sidecarWriterInstanceId;
255811
255909
  var init_recovery_lineage_sidecar = __esm(async () => {
255910
+ init_rename_sync_with_retry();
255812
255911
  init_durable_file_lock();
255813
255912
  await init_interrupted_turn_schema();
255814
255913
  sidecarWriterInstanceId = randomUUID44();
@@ -255817,7 +255916,7 @@ var init_recovery_lineage_sidecar = __esm(async () => {
255817
255916
  // src/websocket/listener/interrupted-turn-record.ts
255818
255917
  import { randomUUID as randomUUID45 } from "node:crypto";
255819
255918
  import {
255820
- existsSync as existsSync50,
255919
+ existsSync as existsSync49,
255821
255920
  mkdirSync as mkdirSync36,
255822
255921
  readFileSync as readFileSync40,
255823
255922
  rmSync as rmSync19,
@@ -255874,7 +255973,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255874
255973
  const recoveryAuthority = createRecoveryAuthorityGuard({
255875
255974
  path: path32,
255876
255975
  readRecord: readRecord2,
255877
- exists: existsSync50,
255976
+ exists: existsSync49,
255878
255977
  acquire: (destination) => acquireDurableFileLock(destination, {
255879
255978
  waitMs: dependencies4.lockWaitMs
255880
255979
  }),
@@ -255908,7 +256007,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255908
256007
  });
255909
256008
  try {
255910
256009
  const current = readRecord2(destination);
255911
- if (!existsSync50(destination)) {
256010
+ if (!existsSync49(destination)) {
255912
256011
  removeSidecar(sidecar);
255913
256012
  } else if (current && current.recoveryClaimCompletion?.lineageId !== sidecar.lineageId) {
255914
256013
  removeSidecar(sidecar);
@@ -255933,7 +256032,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
255933
256032
  },
255934
256033
  listDurableInputOwnership() {
255935
256034
  const snapshot2 = rawSnapshot();
255936
- return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) => existsSync50(path32(agentId, conversationId)), snapshot2.unreadableScopes);
256035
+ return collectInterruptedTurnInputOwnershipWithSidecars(snapshot2.records, readMainView, listSidecars(), (agentId, conversationId) => existsSync49(path32(agentId, conversationId)), snapshot2.unreadableScopes);
255937
256036
  },
255938
256037
  read(agentId, conversationId) {
255939
256038
  const current = readRecord2(path32(agentId, conversationId));
@@ -257492,7 +257591,7 @@ function socketForTransport(transport3) {
257492
257591
  }
257493
257592
  function refreshLegacySingleConnection(runtime) {
257494
257593
  const live = [...runtime.connections.values()].filter((connection) => isListenerTransportOpen(connection.writer));
257495
- const only = live.length === 1 ? live[0] : null;
257594
+ const only = live.find(({ id: id2 }) => id2 === runtime.connectionId) ?? (live.length === 1 ? live[0] : null);
257496
257595
  runtime.transport = runtime.processTransport ?? only?.writer ?? null;
257497
257596
  runtime.streamTransport = only?.streamWriter ?? null;
257498
257597
  runtime.socket = only ? socketForTransport(only.writer) : null;
@@ -257718,6 +257817,26 @@ function suspendListenerConnection(runtime, connectionId) {
257718
257817
  getResumeStates(runtime).set(connectionId, resumeState);
257719
257818
  return closed;
257720
257819
  }
257820
+ function resumeListenerConnectionIdentity(runtime, previousId, nextId2) {
257821
+ const states3 = getResumeStates(runtime);
257822
+ const previous = states3.get(previousId);
257823
+ states3.delete(previousId);
257824
+ if (previous)
257825
+ states3.set(nextId2, previous);
257826
+ for (const conversation of runtime.conversationRuntimes.values()) {
257827
+ for (const [itemId, message2] of conversation.queuedMessagesByItemId) {
257828
+ if (message2.connectionId === previousId) {
257829
+ conversation.queuedMessagesByItemId.set(itemId, {
257830
+ ...message2,
257831
+ connectionId: nextId2
257832
+ });
257833
+ }
257834
+ }
257835
+ if (conversation.activeConnectionId === previousId) {
257836
+ conversation.activeConnectionId = nextId2;
257837
+ }
257838
+ }
257839
+ }
257721
257840
 
257722
257841
  class ProcessRuntimeTransport {
257723
257842
  runtime;
@@ -257763,9 +257882,6 @@ var init_connection = __esm(async () => {
257763
257882
  });
257764
257883
 
257765
257884
  // src/queue/queue-runtime.ts
257766
- function isCoalescable(kind) {
257767
- return kind === "message" || kind === "task_notification" || kind === "cron_prompt" || kind === "mod_continue";
257768
- }
257769
257885
  function hasSameScope(a2, b3) {
257770
257886
  return (a2.agentId ?? null) === (b3.agentId ?? null) && (a2.conversationId ?? null) === (b3.conversationId ?? null);
257771
257887
  }
@@ -257787,7 +257903,7 @@ class QueueRuntime {
257787
257903
  this.callbacks = options.callbacks ?? {};
257788
257904
  }
257789
257905
  enqueue(input, options = {}) {
257790
- if (options.preserveExisting && (this.store.length >= this.hardMaxItems || this.store.length >= this.maxItems && isCoalescable(input.kind))) {
257906
+ if (options.preserveExisting && (this.store.length >= this.hardMaxItems || this.store.length >= this.maxItems)) {
257791
257907
  return null;
257792
257908
  }
257793
257909
  if (this.store.length >= this.hardMaxItems) {
@@ -257797,9 +257913,8 @@ class QueueRuntime {
257797
257913
  this.safeCallback("onDropped", phantom, "buffer_limit", this.store.length);
257798
257914
  return null;
257799
257915
  }
257800
- if (this.store.length >= this.maxItems && isCoalescable(input.kind)) {
257801
- const dropIdx = this.store.findIndex((i4) => isCoalescable(i4.kind));
257802
- const dropped = dropIdx !== -1 ? this.store[dropIdx] : undefined;
257916
+ if (this.store.length >= this.maxItems) {
257917
+ const dropped = this.store[0];
257803
257918
  if (dropped !== undefined) {
257804
257919
  if (!this.mutationAllowed("beforeDropped", dropped)) {
257805
257920
  const rejected = this.makeItem(input);
@@ -257808,7 +257923,7 @@ class QueueRuntime {
257808
257923
  this.safeCallback("onDropped", rejected, "buffer_limit", this.store.length);
257809
257924
  return null;
257810
257925
  }
257811
- this.store.splice(dropIdx, 1);
257926
+ this.store.shift();
257812
257927
  const item2 = this.makeItem(input);
257813
257928
  this.store.push(item2);
257814
257929
  this.safeCallback("onDropped", dropped, "buffer_limit", this.store.length);
@@ -257846,16 +257961,14 @@ class QueueRuntime {
257846
257961
  }
257847
257962
  const batch = [];
257848
257963
  const first = this.store.find((item) => !item.paused);
257849
- if (first && isCoalescable(first.kind)) {
257964
+ if (first) {
257850
257965
  for (const item of this.store) {
257851
257966
  if (item.paused)
257852
257967
  continue;
257853
- if (!isCoalescable(item.kind) || !hasSameScope(first, item))
257968
+ if (!hasSameScope(first, item))
257854
257969
  break;
257855
257970
  batch.push(item);
257856
257971
  }
257857
- } else if (first) {
257858
- batch.push(first);
257859
257972
  }
257860
257973
  if (batch.length === 0) {
257861
257974
  return null;
@@ -258248,12 +258361,11 @@ import { randomUUID as randomUUID46 } from "node:crypto";
258248
258361
  import {
258249
258362
  chmodSync as chmodSync7,
258250
258363
  closeSync as closeSync8,
258251
- existsSync as existsSync51,
258364
+ existsSync as existsSync50,
258252
258365
  fsyncSync as fsyncSync5,
258253
258366
  mkdirSync as mkdirSync37,
258254
258367
  openSync as openSync8,
258255
258368
  readFileSync as readFileSync41,
258256
- renameSync as renameSync12,
258257
258369
  statSync as statSync20,
258258
258370
  unlinkSync as unlinkSync11,
258259
258371
  writeFileSync as writeFileSync32
@@ -258392,7 +258504,7 @@ function validateDurableStore(value) {
258392
258504
  return value;
258393
258505
  }
258394
258506
  function readDurableStore(path32) {
258395
- if (!existsSync51(path32))
258507
+ if (!existsSync50(path32))
258396
258508
  return emptyDurableStore();
258397
258509
  const size2 = statSync20(path32).size;
258398
258510
  if (size2 > MAX_INPUT_DISPOSITION_STORE_BYTES) {
@@ -258420,7 +258532,7 @@ function writeDurableStore(path32, store3) {
258420
258532
  } finally {
258421
258533
  closeSync8(fd);
258422
258534
  }
258423
- renameSync12(temporaryPath, path32);
258535
+ renameSyncWithRetry(temporaryPath, path32);
258424
258536
  fsyncDirectory(dirname33(path32));
258425
258537
  } catch (error5) {
258426
258538
  try {
@@ -258822,6 +258934,7 @@ function loadDurableQueuedInputEntries(listener) {
258822
258934
  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;
258823
258935
  var init_input_disposition = __esm(async () => {
258824
258936
  init_server_url();
258937
+ init_rename_sync_with_retry();
258825
258938
  init_durable_file_lock();
258826
258939
  init_input_disposition_capacity();
258827
258940
  init_input_disposition_expiry();
@@ -258846,7 +258959,6 @@ import {
258846
258959
  openSync as openSync9,
258847
258960
  readdirSync as readdirSync19,
258848
258961
  readFileSync as readFileSync42,
258849
- renameSync as renameSync13,
258850
258962
  rmSync as rmSync20,
258851
258963
  writeFileSync as writeFileSync33
258852
258964
  } from "node:fs";
@@ -258942,7 +259054,7 @@ function createTurnFinishedStore(directory = defaultDirectory(), options = {}) {
258942
259054
  mode: 384,
258943
259055
  flush: true
258944
259056
  });
258945
- renameSync13(temporary, destination);
259057
+ renameSyncWithRetry(temporary, destination);
258946
259058
  fsyncDirectory2(directory);
258947
259059
  } finally {
258948
259060
  rmSync20(temporary, { force: true });
@@ -259294,6 +259406,7 @@ var TurnFinishedCapacityError, MAX_PENDING_TERMINALS_PER_CONVERSATION = 64, DELI
259294
259406
  var init_turn_finished_replay = __esm(async () => {
259295
259407
  init_server_url();
259296
259408
  init_debug();
259409
+ init_rename_sync_with_retry();
259297
259410
  init_durable_file_lock();
259298
259411
  await __promiseAll([
259299
259412
  init_connection(),
@@ -259958,20 +260071,6 @@ var init_image_policy = __esm(async () => {
259958
260071
  await init_message_image_normalization();
259959
260072
  });
259960
260073
 
259961
- // src/websocket/listener/mcp-originator-scope.ts
259962
- function getMcpOriginatorScope(message2) {
259963
- return message2?.mcpOriginatorSuperRunId ? {
259964
- superRunId: message2.mcpOriginatorSuperRunId,
259965
- tokenPresent: message2.mcpOriginatorTokenPresent === true
259966
- } : null;
259967
- }
259968
- function sameMcpOriginatorScope(a2, b3) {
259969
- return a2 === null || b3 === null ? a2 === b3 : a2.superRunId === b3.superRunId && a2.tokenPresent === b3.tokenPresent;
259970
- }
259971
- function getEffectiveMcpOriginatorId(message2) {
259972
- return message2.mcpOriginatorTokenPresent === true ? message2.mcpOriginatorSuperRunId : undefined;
259973
- }
259974
-
259975
260074
  // src/websocket/listener/queue.ts
259976
260075
  function getQueueItemScope(item) {
259977
260076
  if (!item) {
@@ -260030,7 +260129,7 @@ function buildQueuedTurnMessage(runtime, batch) {
260030
260129
  messageOriginatorIds.push(undefined);
260031
260130
  originatorVotes.push(null);
260032
260131
  messages.push(withMessageAttribution({ role: "user", content: item.content }, item.actingUserId ?? undefined));
260033
- } else if (isCoalescable(item.kind) && "text" in item) {
260132
+ } else {
260034
260133
  messageOriginatorIds.push(undefined);
260035
260134
  originatorVotes.push(null);
260036
260135
  messages.push({
@@ -260095,15 +260194,12 @@ function shouldProcessInboundMessageDirectly(runtime, parsed) {
260095
260194
  });
260096
260195
  return getListenerBlockedReason(runtime.turnLifecycle.snapshot(), activeScope ? getPendingControlRequestCount(runtime.listener, activeScope) : 0) === null;
260097
260196
  }
260098
- function consumeQueuedTurn(runtime, activeScope) {
260197
+ function consumeQueuedTurn(runtime) {
260099
260198
  const queuedItems = runtime.queueRuntime.peekReady();
260100
260199
  const firstQueuedItem = queuedItems[0];
260101
- if (!firstQueuedItem || !isCoalescable(firstQueuedItem.kind)) {
260200
+ if (!firstQueuedItem) {
260102
260201
  return null;
260103
260202
  }
260104
- const firstScope = getMcpOriginatorScope(firstQueuedItem.kind === "message" ? runtime.queuedMessagesByItemId.get(firstQueuedItem.id) : undefined);
260105
- if (activeScope !== undefined && !sameMcpOriginatorScope(firstScope, activeScope))
260106
- return null;
260107
260203
  let queueLen = 0;
260108
260204
  let hasMessage = false;
260109
260205
  let hasTaskNotification = false;
@@ -260114,7 +260210,7 @@ function consumeQueuedTurn(runtime, activeScope) {
260114
260210
  let batchPreferences = JSON.stringify(getStoredClientPreferences(runtime.agentId, runtime.conversationId));
260115
260211
  const isNoCoalesce = (candidate) => candidate.kind === "message" && candidate.noCoalesce === true;
260116
260212
  for (const item of queuedItems) {
260117
- if (!isCoalescable(item.kind) || !hasSameQueueScope(firstQueuedItem, item) || !sameMcpOriginatorScope(firstScope, getMcpOriginatorScope(item.kind === "message" ? runtime.queuedMessagesByItemId.get(item.id) : undefined))) {
260213
+ if (!hasSameQueueScope(firstQueuedItem, item)) {
260118
260214
  break;
260119
260215
  }
260120
260216
  const incoming = runtime.queuedMessagesByItemId.get(item.id);
@@ -260160,6 +260256,25 @@ function consumeQueuedTurn(runtime, activeScope) {
260160
260256
  if (!dequeuedBatch) {
260161
260257
  return null;
260162
260258
  }
260259
+ for (const item of dequeuedBatch.items) {
260260
+ if (item.kind !== "cron_prompt")
260261
+ continue;
260262
+ try {
260263
+ const task2 = getTask(item.cronTaskId);
260264
+ if (task2 && task2.agent_id === item.agentId) {
260265
+ safeAppendCronRunLogForTask(task2, {
260266
+ status: "ok",
260267
+ outcome: "delivered",
260268
+ reason: "dequeued",
260269
+ queueItemId: item.id,
260270
+ conversationId: item.conversationId,
260271
+ runAtMs: Date.now()
260272
+ });
260273
+ }
260274
+ } catch (error5) {
260275
+ debugWarn("Cron", "Error reading task for dequeued cron prompt:", error5);
260276
+ }
260277
+ }
260163
260278
  const clientMessageIds = getDequeuedClientMessageIds(runtime, dequeuedBatch);
260164
260279
  const queuedTurn = buildQueuedTurnMessage(runtime, dequeuedBatch);
260165
260280
  if (!queuedTurn) {
@@ -260318,7 +260433,8 @@ function scheduleQueuePump(runtime, socket, opts, processQueuedTurn) {
260318
260433
  }
260319
260434
  var init_queue = __esm(async () => {
260320
260435
  init_mcp_originator_tokens();
260321
- init_queue_runtime();
260436
+ init_cron_file();
260437
+ init_run_log();
260322
260438
  init_error_reporting();
260323
260439
  init_debug();
260324
260440
  init_transport();
@@ -261076,6 +261192,11 @@ function taskMatchesCronSchedulerScope(task2, scope) {
261076
261192
  return true;
261077
261193
  return scope === "local" ? isLocalAgentId(task2.agent_id) : !isLocalAgentId(task2.agent_id);
261078
261194
  }
261195
+ function clearSlowLeaseRetry() {
261196
+ if (slowLeaseRetryTimer)
261197
+ clearInterval(slowLeaseRetryTimer);
261198
+ slowLeaseRetryTimer = null;
261199
+ }
261079
261200
  function logScheduler(opts, message2) {
261080
261201
  if (opts.onLog) {
261081
261202
  opts.onLog(`[Cron] ${message2}`);
@@ -261466,16 +261587,31 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
261466
261587
  try {
261467
261588
  token2 = claimSchedulerLease(scope);
261468
261589
  } catch (err) {
261590
+ if (slowLeaseRetryTimer)
261591
+ return;
261469
261592
  if (_retryCount < MAX_LEASE_RETRIES) {
261470
261593
  logScheduler(opts, `Could not claim scheduler lease (attempt ${_retryCount + 1}/${MAX_LEASE_RETRIES + 1}): ${err instanceof Error ? err.message : err}`);
261471
261594
  logScheduler(opts, "Cron tasks will not fire until the scheduler starts. Retrying...");
261472
261595
  setTimeout(() => startScheduler(socket, opts, processQueuedTurn, _retryCount + 1), LEASE_RETRY_MS);
261473
261596
  } else {
261474
261597
  logScheduler(opts, `Failed to claim scheduler lease after ${MAX_LEASE_RETRIES + 1} attempts. Cron tasks will not fire.`);
261475
- logScheduler(opts, "Another process may hold the lease. Restart Letta Code to retry.");
261598
+ logScheduler(opts, `Another process may hold the lease. Retrying every ${SLOW_LEASE_RETRY_MS / 60000} minutes.`);
261599
+ slowLeaseRetryTimer = setInterval(() => {
261600
+ const ctx = listenerFireContext;
261601
+ if (!ctx || schedulerState) {
261602
+ clearSlowLeaseRetry();
261603
+ return;
261604
+ }
261605
+ startScheduler(ctx.socket, ctx.opts, ctx.processQueuedTurn, _retryCount);
261606
+ }, SLOW_LEASE_RETRY_MS);
261607
+ slowLeaseRetryTimer.unref?.();
261476
261608
  }
261477
261609
  return;
261478
261610
  }
261611
+ if (slowLeaseRetryTimer) {
261612
+ clearSlowLeaseRetry();
261613
+ logScheduler(opts, "Claimed scheduler lease on slow retry.");
261614
+ }
261479
261615
  const now2 = new Date;
261480
261616
  const state2 = {
261481
261617
  token: token2,
@@ -261523,6 +261659,7 @@ function startScheduler(socket, opts, processQueuedTurn, _retryCount = 0) {
261523
261659
  }
261524
261660
  function stopScheduler() {
261525
261661
  listenerFireContext = null;
261662
+ clearSlowLeaseRetry();
261526
261663
  if (!schedulerState)
261527
261664
  return;
261528
261665
  clearInterval(schedulerState.tickInterval);
@@ -261536,7 +261673,7 @@ function stopScheduler() {
261536
261673
  } catch {}
261537
261674
  schedulerState = null;
261538
261675
  }
261539
- 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";
261676
+ 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";
261540
261677
  var init_scheduler = __esm(async () => {
261541
261678
  init_backend2();
261542
261679
  init_debug();
@@ -261554,6 +261691,7 @@ var init_scheduler = __esm(async () => {
261554
261691
  init_runtime6()
261555
261692
  ]);
261556
261693
  GC_INTERVAL_MS = 60 * 60000;
261694
+ SLOW_LEASE_RETRY_MS = 5 * 60000;
261557
261695
  });
261558
261696
 
261559
261697
  // src/cron/index.ts
@@ -261656,8 +261794,9 @@ Add options:
261656
261794
  conversation; "default" for the agent default)
261657
261795
  --computer <id> (managed Cloud sandbox only) Run on a connected
261658
261796
  external computer (deviceId from \`letta computers
261659
- list\`). Falls back to the Cloud sandbox if that
261660
- computer is offline at fire time.
261797
+ list\`). If that computer is offline at fire
261798
+ time, that run fails (no Cloud sandbox fallback);
261799
+ omit --computer to run in the Cloud sandbox.
261661
261800
 
261662
261801
  List/filter options:
261663
261802
  --agent <id> Filter by agent ID
@@ -261882,7 +262021,7 @@ async function handleCloudAdd(params) {
261882
262021
  output.notes = notes;
261883
262022
  }
261884
262023
  console.log(JSON.stringify(output, null, 2));
261885
- 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).");
262024
+ 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).");
261886
262025
  return 0;
261887
262026
  } catch (err) {
261888
262027
  console.error(`Error: failed to create Cloud schedule: ${err instanceof Error ? err.message : String(err)}`);
@@ -264250,6 +264389,11 @@ var init_listen_first_run_welcome = __esm(async () => {
264250
264389
  await init_AnimatedLogo();
264251
264390
  });
264252
264391
 
264392
+ // src/cli/subcommands/listen-output-mode.ts
264393
+ function shouldUseNonInteractiveListenerOutput(debugMode, lifecycleOutput, stdoutIsTTY = process.stdout.isTTY) {
264394
+ return debugMode || lifecycleOutput || !stdoutIsTTY;
264395
+ }
264396
+
264253
264397
  // src/cli/subcommands/listen-process-anchor.ts
264254
264398
  import { MessageChannel as MessageChannel2 } from "node:worker_threads";
264255
264399
  function createMessageChannelProcessAnchor() {
@@ -264307,7 +264451,7 @@ function printListenUsage() {
264307
264451
  }
264308
264452
 
264309
264453
  // src/cli/subcommands/listener-readiness.ts
264310
- async function completeListenerConnectionStartup(expectedConnection, readiness, startGateway = async () => {}) {
264454
+ async function completeListenerConnectionStartup(expectedConnection, readiness, startGateway = async () => {}, onGatewayError = console.error) {
264311
264455
  const { getActiveRuntime: getActiveRuntime2 } = await init_runtime6().then(() => exports_runtime);
264312
264456
  const runtime = getActiveRuntime2();
264313
264457
  const connection = runtime?.connections.get(expectedConnection.id);
@@ -264317,12 +264461,12 @@ async function completeListenerConnectionStartup(expectedConnection, readiness,
264317
264461
  const { isListenerTransportOpen: isListenerTransportOpen2 } = await Promise.resolve().then(() => (init_transport(), exports_transport));
264318
264462
  if (!isListenerTransportOpen2(connection.writer))
264319
264463
  return false;
264320
- await startGateway();
264321
264464
  if (getActiveRuntime2()?.connections.get(connection.id) !== connection)
264322
264465
  return false;
264323
264466
  if (!connection.initialized || !connection.ingressReady || connection.cancellation.signal.aborted || !isListenerTransportOpen2(connection.writer))
264324
264467
  return false;
264325
264468
  readiness.completeCloudStartup(epoch);
264469
+ Promise.resolve().then(startGateway).catch(onGatewayError);
264326
264470
  return true;
264327
264471
  }
264328
264472
  function applyGatewayLifecycleReadiness(readiness, event) {
@@ -264475,7 +264619,7 @@ var init_service_protocol = __esm(() => {
264475
264619
  // src/websocket/listen-log.ts
264476
264620
  import {
264477
264621
  appendFileSync as appendFileSync8,
264478
- existsSync as existsSync52,
264622
+ existsSync as existsSync51,
264479
264623
  mkdirSync as mkdirSync39,
264480
264624
  readdirSync as readdirSync20,
264481
264625
  unlinkSync as unlinkSync12
@@ -264495,7 +264639,7 @@ function formatFileTimestamp(now2) {
264495
264639
  }
264496
264640
  function pruneOldLogs(dir, maxFiles) {
264497
264641
  try {
264498
- if (!existsSync52(dir))
264642
+ if (!existsSync51(dir))
264499
264643
  return;
264500
264644
  const files = readdirSync20(dir).filter((f4) => f4.endsWith(".log")).sort();
264501
264645
  if (files.length >= maxFiles) {
@@ -264547,7 +264691,7 @@ class RemoteSessionLog {
264547
264691
  const previous = this.path;
264548
264692
  this.rotation += 1;
264549
264693
  this.path = this.freshPath();
264550
- while (existsSync52(this.path)) {
264694
+ while (existsSync51(this.path)) {
264551
264695
  this.rotation += 1;
264552
264696
  this.path = this.freshPath();
264553
264697
  }
@@ -264571,7 +264715,7 @@ class RemoteSessionLog {
264571
264715
  if (this.dirCreated)
264572
264716
  return;
264573
264717
  try {
264574
- if (!existsSync52(this.dir)) {
264718
+ if (!existsSync51(this.dir)) {
264575
264719
  mkdirSync39(this.dir, { recursive: true });
264576
264720
  }
264577
264721
  this.dirCreated = true;
@@ -265180,9 +265324,10 @@ var init_auth3 = __esm(() => {
265180
265324
  });
265181
265325
 
265182
265326
  // src/websocket/listener/manual-instance-lock.ts
265327
+ import { execFileSync as execFileSync11 } from "node:child_process";
265183
265328
  import { createHash as createHash15, randomUUID as randomUUID48 } from "node:crypto";
265184
265329
  import { link as link4, mkdir as mkdir13, readFile as readFile21, rm as rm11, unlink as unlink3, writeFile as writeFile15 } from "node:fs/promises";
265185
- import { homedir as homedir39 } from "node:os";
265330
+ import { homedir as homedir39, uptime as uptime2 } from "node:os";
265186
265331
  import path32 from "node:path";
265187
265332
  function hasErrorCode3(error5, code2) {
265188
265333
  return typeof error5 === "object" && error5 !== null && "code" in error5 && error5.code === code2;
@@ -265195,6 +265340,32 @@ function defaultIsProcessAlive2(pid) {
265195
265340
  return !hasErrorCode3(error5, "ESRCH");
265196
265341
  }
265197
265342
  }
265343
+ function getDefaultBootTimeMs() {
265344
+ return Date.now() - uptime2() * 1000;
265345
+ }
265346
+ function defaultGetProcessCommand(pid) {
265347
+ if (process.platform === "win32")
265348
+ return null;
265349
+ try {
265350
+ return execFileSync11("ps", ["-p", String(pid), "-o", "command="], {
265351
+ encoding: "utf-8",
265352
+ timeout: 1000,
265353
+ stdio: ["ignore", "pipe", "ignore"]
265354
+ }).trim();
265355
+ } catch {
265356
+ return null;
265357
+ }
265358
+ }
265359
+ function isOwnerAlive2(record6, deps) {
265360
+ if (!deps.isProcessAlive(record6.pid))
265361
+ return false;
265362
+ const acquiredAtMs = Date.parse(record6.acquiredAt);
265363
+ if (!Number.isFinite(acquiredAtMs) || acquiredAtMs >= deps.bootTimeMs - BOOT_TIME_SLACK_MS2) {
265364
+ return true;
265365
+ }
265366
+ const command = deps.getProcessCommand(record6.pid);
265367
+ return !command || /letta/i.test(command);
265368
+ }
265198
265369
  function getDefaultLockRoot() {
265199
265370
  return path32.join(process.env.HOME || homedir39(), ".letta");
265200
265371
  }
@@ -265279,7 +265450,7 @@ async function recoverDeadOwner(lockPath, staleContents, recoveryOwnerContents,
265279
265450
  if (!claimOwner) {
265280
265451
  throw new ManualListenerLockUnavailableError(`Listener lock recovery record is invalid: ${claimPath}`, lockPath);
265281
265452
  }
265282
- if (deps.isProcessAlive(claimOwner.pid)) {
265453
+ if (isOwnerAlive2(claimOwner, deps)) {
265283
265454
  return false;
265284
265455
  }
265285
265456
  }
@@ -265310,6 +265481,8 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265310
265481
  processId: process.pid,
265311
265482
  ownerToken: randomUUID48(),
265312
265483
  isProcessAlive: defaultIsProcessAlive2,
265484
+ bootTimeMs: getDefaultBootTimeMs(),
265485
+ getProcessCommand: defaultGetProcessCommand,
265313
265486
  ...overrides
265314
265487
  };
265315
265488
  const listenerLockDir = path32.join(deps.lockRoot, "listeners");
@@ -265369,7 +265542,7 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265369
265542
  if (!incumbent) {
265370
265543
  throw new ManualListenerLockUnavailableError(`Listener lock is corrupt or belongs to an incompatible version: ${lockPath}`, lockPath);
265371
265544
  }
265372
- if (deps.isProcessAlive(incumbent.pid)) {
265545
+ if (isOwnerAlive2(incumbent, deps)) {
265373
265546
  throw new ManualListenerAlreadyRunningError(incumbent.pid, lockPath);
265374
265547
  }
265375
265548
  const recovered = await recoverDeadOwner(lockPath, incumbentContents, ownerContents, scopeHash, deps);
@@ -265378,7 +265551,7 @@ async function acquireManualListenerLock(scope, overrides = {}) {
265378
265551
  }
265379
265552
  }
265380
265553
  }
265381
- var RECOVERY_MAX_DEPTH2 = 64, ManualListenerAlreadyRunningError, ManualListenerLockUnavailableError;
265554
+ var RECOVERY_MAX_DEPTH2 = 64, BOOT_TIME_SLACK_MS2 = 60000, ManualListenerAlreadyRunningError, ManualListenerLockUnavailableError;
265382
265555
  var init_manual_instance_lock = __esm(() => {
265383
265556
  ManualListenerAlreadyRunningError = class ManualListenerAlreadyRunningError extends Error {
265384
265557
  holderPid;
@@ -267610,10 +267783,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267610
267783
  const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
267611
267784
  const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
267612
267785
  const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
267613
- const { existsSync: existsSync53, statSync: statSync22 } = await import("node:fs");
267614
- const { join: join78, posix: posix3 } = await import("node:path");
267786
+ const { existsSync: existsSync52, statSync: statSync22 } = await import("node:fs");
267787
+ const { join: join78, posix: posix4 } = await import("node:path");
267615
267788
  const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
267616
- let memfsInitialized = existsSync53(join78(memoryRoot, ".git"));
267789
+ let memfsInitialized = existsSync52(join78(memoryRoot, ".git"));
267617
267790
  const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
267618
267791
  if (!memfsEnabled) {
267619
267792
  safeSocketSend(socket, {
@@ -267631,7 +267804,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267631
267804
  await ensureLocalMemfsCheckout2(parsed.agent_id, {
267632
267805
  pullOnExistingRepo: true
267633
267806
  });
267634
- memfsInitialized = existsSync53(join78(memoryRoot, ".git"));
267807
+ memfsInitialized = existsSync52(join78(memoryRoot, ".git"));
267635
267808
  if (!memfsInitialized) {
267636
267809
  throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
267637
267810
  }
@@ -267660,8 +267833,8 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267660
267833
  if (!target2) {
267661
267834
  return null;
267662
267835
  }
267663
- const sourceDir = posix3.dirname(sourcePath.replace(/\\/g, "/"));
267664
- const candidate = target2.startsWith("./") || target2.startsWith("../") ? posix3.normalize(posix3.join(sourceDir, target2)) : posix3.normalize(target2.startsWith("/") ? target2.slice(1) : target2);
267836
+ const sourceDir = posix4.dirname(sourcePath.replace(/\\/g, "/"));
267837
+ const candidate = target2.startsWith("./") || target2.startsWith("../") ? posix4.normalize(posix4.join(sourceDir, target2)) : posix4.normalize(target2.startsWith("/") ? target2.slice(1) : target2);
267665
267838
  if (!candidate || candidate.startsWith("../") || candidate === "." || candidate === "..") {
267666
267839
  return null;
267667
267840
  }
@@ -267669,10 +267842,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
267669
267842
  const candidates2 = new Set([withExtension]);
267670
267843
  const isExplicitRelative = target2.startsWith("./") || target2.startsWith("../");
267671
267844
  if (!isExplicitRelative && !target2.startsWith("/") && sourceDir && sourceDir !== ".") {
267672
- candidates2.add(posix3.normalize(posix3.join(sourceDir, withExtension)));
267845
+ candidates2.add(posix4.normalize(posix4.join(sourceDir, withExtension)));
267673
267846
  }
267674
267847
  if (!withExtension.startsWith("system/")) {
267675
- candidates2.add(posix3.normalize(`system/${withExtension}`));
267848
+ candidates2.add(posix4.normalize(`system/${withExtension}`));
267676
267849
  }
267677
267850
  for (const resolved2 of candidates2) {
267678
267851
  if (allPaths.has(resolved2)) {
@@ -267931,7 +268104,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
267931
268104
  isMemfsEnabledOnServer: isMemfsEnabledOnServer2
267932
268105
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
267933
268106
  const { readFile: readFile22 } = await import("node:fs/promises");
267934
- const { existsSync: existsSync53 } = await import("node:fs");
268107
+ const { existsSync: existsSync52 } = await import("node:fs");
267935
268108
  const { isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
267936
268109
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
267937
268110
  sendFailure("path must be a non-empty relative path");
@@ -267944,14 +268117,14 @@ function handleMemoryProtocolCommand(parsed, context3) {
267944
268117
  sendFailure("path must resolve inside the memory root");
267945
268118
  return;
267946
268119
  }
267947
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268120
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
267948
268121
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
267949
268122
  if (!enabled) {
267950
268123
  sendFailure("memfs is not enabled for this agent");
267951
268124
  return;
267952
268125
  }
267953
268126
  await ensureLocalMemfsCheckout2(parsed.agent_id);
267954
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268127
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
267955
268128
  sendFailure("failed to initialize local memory checkout");
267956
268129
  return;
267957
268130
  }
@@ -267997,7 +268170,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
267997
268170
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
267998
268171
  const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
267999
268172
  const { writeFile: writeFile16, mkdir: mkdir14 } = await import("node:fs/promises");
268000
- const { existsSync: existsSync53 } = await import("node:fs");
268173
+ const { existsSync: existsSync52 } = await import("node:fs");
268001
268174
  const { dirname: dirname34, isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
268002
268175
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
268003
268176
  sendFailure("write_memory_file: path must be a non-empty relative path");
@@ -268010,14 +268183,14 @@ function handleMemoryProtocolCommand(parsed, context3) {
268010
268183
  sendFailure("write_memory_file: path must resolve inside the memory root");
268011
268184
  return;
268012
268185
  }
268013
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268186
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268014
268187
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
268015
268188
  if (!enabled) {
268016
268189
  sendFailure("write_memory_file: memfs is not enabled for this agent");
268017
268190
  return;
268018
268191
  }
268019
268192
  await ensureLocalMemfsCheckout2(parsed.agent_id);
268020
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268193
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268021
268194
  sendFailure("write_memory_file: failed to initialize local memory checkout");
268022
268195
  return;
268023
268196
  }
@@ -268095,7 +268268,7 @@ function handleMemoryProtocolCommand(parsed, context3) {
268095
268268
  } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
268096
268269
  const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
268097
268270
  const { unlink: unlink4 } = await import("node:fs/promises");
268098
- const { existsSync: existsSync53 } = await import("node:fs");
268271
+ const { existsSync: existsSync52 } = await import("node:fs");
268099
268272
  const { isAbsolute: isAbsolute25, join: join78, normalize: normalize4, relative: relative8, sep: sep8 } = await import("node:path");
268100
268273
  if (isAbsolute25(parsed.path) || parsed.path.length === 0) {
268101
268274
  sendFailure("delete_memory_file: path must be a non-empty relative path");
@@ -268108,21 +268281,21 @@ function handleMemoryProtocolCommand(parsed, context3) {
268108
268281
  sendFailure("delete_memory_file: path must resolve inside the memory root");
268109
268282
  return;
268110
268283
  }
268111
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268284
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268112
268285
  const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
268113
268286
  if (!enabled) {
268114
268287
  sendFailure("delete_memory_file: memfs is not enabled for this agent");
268115
268288
  return;
268116
268289
  }
268117
268290
  await ensureLocalMemfsCheckout2(parsed.agent_id);
268118
- if (!existsSync53(join78(memoryRoot, ".git"))) {
268291
+ if (!existsSync52(join78(memoryRoot, ".git"))) {
268119
268292
  sendFailure("delete_memory_file: failed to initialize local memory checkout");
268120
268293
  return;
268121
268294
  }
268122
268295
  }
268123
268296
  const pathspec = rel.split(sep8).join("/");
268124
268297
  const removeIfPresent = async () => {
268125
- if (!existsSync53(absolutePath))
268298
+ if (!existsSync52(absolutePath))
268126
268299
  return false;
268127
268300
  await unlink4(absolutePath);
268128
268301
  return true;
@@ -268317,7 +268490,7 @@ __export(exports_remote_model_catalog, {
268317
268490
  applyCatalogModels: () => applyCatalogModels,
268318
268491
  __testResetRemoteModelCatalog: () => __testResetRemoteModelCatalog
268319
268492
  });
268320
- import { existsSync as existsSync53, mkdirSync as mkdirSync40, readFileSync as readFileSync44, writeFileSync as writeFileSync34 } from "node:fs";
268493
+ import { existsSync as existsSync52, mkdirSync as mkdirSync40, readFileSync as readFileSync44, writeFileSync as writeFileSync34 } from "node:fs";
268321
268494
  import { homedir as homedir40 } from "node:os";
268322
268495
  import { dirname as dirname34, join as join78 } from "node:path";
268323
268496
  function catalogCachePath() {
@@ -268421,7 +268594,7 @@ function persistCatalogCache(entries2, source) {
268421
268594
  function loadPersistedModelCatalog(source) {
268422
268595
  try {
268423
268596
  const path33 = catalogCachePath();
268424
- if (!existsSync53(path33)) {
268597
+ if (!existsSync52(path33)) {
268425
268598
  return false;
268426
268599
  }
268427
268600
  const parsed = JSON.parse(readFileSync44(path33, "utf-8"));
@@ -269114,7 +269287,7 @@ function recordStaleHandleUse(collector, owner, capability, onDiagnostic) {
269114
269287
  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().";
269115
269288
 
269116
269289
  // src/mods/paths.ts
269117
- import { existsSync as existsSync54 } from "node:fs";
269290
+ import { existsSync as existsSync53 } from "node:fs";
269118
269291
  import { homedir as homedir41 } from "node:os";
269119
269292
  import path33 from "node:path";
269120
269293
  function getGlobalModsDirectory(homeDirectory = homedir41()) {
@@ -269128,10 +269301,10 @@ function resolveDefaultGlobalModsDirectory(homeDirectory = homedir41(), env6 = p
269128
269301
  if (environmentDirectory)
269129
269302
  return environmentDirectory;
269130
269303
  const modsDirectory = getGlobalModsDirectory(homeDirectory);
269131
- if (existsSync54(modsDirectory))
269304
+ if (existsSync53(modsDirectory))
269132
269305
  return modsDirectory;
269133
269306
  const legacyDirectory = getLegacyGlobalExtensionsDirectory(homeDirectory);
269134
- if (existsSync54(legacyDirectory))
269307
+ if (existsSync53(legacyDirectory))
269135
269308
  return legacyDirectory;
269136
269309
  return modsDirectory;
269137
269310
  }
@@ -377138,10 +377311,10 @@ ${lanes.join(`
377138
377311
  }
377139
377312
  function getDefaultLibFilePriority(a2) {
377140
377313
  if (containsPath(defaultLibraryPath, a2.fileName, false)) {
377141
- const basename21 = getBaseFileName(a2.fileName);
377142
- if (basename21 === "lib.d.ts" || basename21 === "lib.es6.d.ts")
377314
+ const basename22 = getBaseFileName(a2.fileName);
377315
+ if (basename22 === "lib.d.ts" || basename22 === "lib.es6.d.ts")
377143
377316
  return 0;
377144
- const name = removeSuffix(removePrefix(basename21, "lib."), ".d.ts");
377317
+ const name = removeSuffix(removePrefix(basename22, "lib."), ".d.ts");
377145
377318
  const index = libs.indexOf(name);
377146
377319
  if (index !== -1)
377147
377320
  return index + 1;
@@ -429704,8 +429877,8 @@ ${options.prefix}` : `
429704
429877
  }
429705
429878
  };
429706
429879
  for (const file of files) {
429707
- const basename21 = getBaseFileName(file);
429708
- if (basename21 === "package.json" || basename21 === "bower.json") {
429880
+ const basename22 = getBaseFileName(file);
429881
+ if (basename22 === "package.json" || basename22 === "bower.json") {
429709
429882
  createProjectWatcher(file, "FileWatcher");
429710
429883
  continue;
429711
429884
  }
@@ -432582,8 +432755,8 @@ All files are: ${JSON.stringify(names2)}`, "Err");
432582
432755
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
432583
432756
  if (!fileOrDirectoryPath)
432584
432757
  return;
432585
- const basename21 = getBaseFileName(fileOrDirectoryPath);
432586
- if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename21 === "package.json" || basename21 === "node_modules")) {
432758
+ const basename22 = getBaseFileName(fileOrDirectoryPath);
432759
+ if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename22 === "package.json" || basename22 === "node_modules")) {
432587
432760
  result3.affectedModuleSpecifierCacheProjects.forEach((project) => {
432588
432761
  var _a22;
432589
432762
  (_a22 = project.getModuleSpecifierCache()) == null || _a22.clear();
@@ -438189,7 +438362,7 @@ var init_package_manifest = __esm(() => {
438189
438362
 
438190
438363
  // src/mods/package-registry.ts
438191
438364
  import {
438192
- existsSync as existsSync55,
438365
+ existsSync as existsSync54,
438193
438366
  mkdirSync as mkdirSync42,
438194
438367
  readFileSync as readFileSync46,
438195
438368
  rmSync as rmSync21,
@@ -438261,7 +438434,7 @@ function getRegistryPath(modsRoot) {
438261
438434
  }
438262
438435
  function readRegistryObject(modsRoot) {
438263
438436
  const registryPath = getRegistryPath(modsRoot);
438264
- if (!existsSync55(registryPath)) {
438437
+ if (!existsSync54(registryPath)) {
438265
438438
  return { diagnostics: [], ok: false, registryExists: false, registryPath };
438266
438439
  }
438267
438440
  const registryResult = parseJsonFile(registryPath);
@@ -438693,7 +438866,7 @@ function writePackageRegistry(registryPath, registry4) {
438693
438866
  }
438694
438867
  function validateManagedModPackageRegistryForMutation(modsRoot) {
438695
438868
  const registryPath = getRegistryPath(modsRoot);
438696
- const contents = existsSync55(registryPath) ? readFileSync46(registryPath, "utf8") : null;
438869
+ const contents = existsSync54(registryPath) ? readFileSync46(registryPath, "utf8") : null;
438697
438870
  const registry4 = readMutablePackageRegistry(modsRoot, {
438698
438871
  createIfMissing: true
438699
438872
  });
@@ -438816,10 +438989,10 @@ var init_package_registry = __esm(() => {
438816
438989
  });
438817
438990
 
438818
438991
  // src/mods/mod-sources.ts
438819
- import { existsSync as existsSync56, readdirSync as readdirSync22 } from "node:fs";
438992
+ import { existsSync as existsSync55, readdirSync as readdirSync22 } from "node:fs";
438820
438993
  import path37 from "node:path";
438821
438994
  function listModFiles(directory) {
438822
- if (!existsSync56(directory))
438995
+ if (!existsSync55(directory))
438823
438996
  return [];
438824
438997
  return readdirSync22(directory, { withFileTypes: true }).filter((entry) => {
438825
438998
  if (!entry.isFile())
@@ -438835,7 +439008,7 @@ function resolveLocalModSources(options = {}) {
438835
439008
  const includeGlobalMods = options.includeGlobalMods !== false;
438836
439009
  const managedPackages = includeGlobalMods ? resolveManagedModPackages(globalModsDirectory) : { diagnostics: [], files: [], packages: [] };
438837
439010
  const sources = [];
438838
- if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) && existsSync56(legacyGlobalExtensionsDirectory)) {
439011
+ if (includeGlobalMods && legacyGlobalExtensionsDirectory && path37.resolve(legacyGlobalExtensionsDirectory) !== path37.resolve(globalModsDirectory) && existsSync55(legacyGlobalExtensionsDirectory)) {
438839
439012
  sources.push({
438840
439013
  files: listModFiles(legacyGlobalExtensionsDirectory),
438841
439014
  legacyMigrationTargetRoot: globalModsDirectory,
@@ -438874,7 +439047,7 @@ var init_mod_sources = __esm(() => {
438874
439047
 
438875
439048
  // src/mods/runtime-dependencies.ts
438876
439049
  import {
438877
- lstatSync as lstatSync2,
439050
+ lstatSync as lstatSync3,
438878
439051
  mkdirSync as mkdirSync43,
438879
439052
  readlinkSync,
438880
439053
  symlinkSync,
@@ -438895,7 +439068,7 @@ function ensureRuntimeDependencySymlink(cacheDirectory, packageName, resolveRunt
438895
439068
  const packageDirectory = path38.resolve(resolveRuntimePackageDirectory(packageName));
438896
439069
  mkdirSync43(nodeModulesDirectory, { recursive: true });
438897
439070
  try {
438898
- const stats = lstatSync2(linkPath);
439071
+ const stats = lstatSync3(linkPath);
438899
439072
  if (!stats.isSymbolicLink())
438900
439073
  return;
438901
439074
  const existingTarget = readlinkSync(linkPath);
@@ -439014,7 +439187,7 @@ function createNoopModPanelHandle() {
439014
439187
  // src/mods/mod-engine.ts
439015
439188
  import { createHash as createHash16 } from "node:crypto";
439016
439189
  import {
439017
- existsSync as existsSync57,
439190
+ existsSync as existsSync56,
439018
439191
  mkdirSync as mkdirSync44,
439019
439192
  readdirSync as readdirSync23,
439020
439193
  readFileSync as readFileSync47,
@@ -439204,7 +439377,7 @@ function createImportableModPath(modPath, cacheDirectory, source) {
439204
439377
  }
439205
439378
  const baseName = path39.basename(modPath, fileExtension).replace(/[^a-zA-Z0-9_-]/g, "-");
439206
439379
  const importPath = path39.join(importCacheDirectory, `.letta-mod-${baseName}-${hash3}.mjs`);
439207
- if (!existsSync57(importPath)) {
439380
+ if (!existsSync56(importPath)) {
439208
439381
  writeFileSync37(importPath, importableSource, "utf8");
439209
439382
  }
439210
439383
  try {
@@ -442627,19 +442800,19 @@ function emitSkillsUpdated(socket, safeSocketSend) {
442627
442800
  }
442628
442801
  async function handleSkillCommand(parsed, socket, safeSocketSend) {
442629
442802
  const {
442630
- existsSync: existsSync58,
442631
- lstatSync: lstatSync3,
442803
+ existsSync: existsSync57,
442804
+ lstatSync: lstatSync4,
442632
442805
  mkdirSync: mkdirSync45,
442633
442806
  rmdirSync: rmdirSync2,
442634
442807
  symlinkSync: symlinkSync2,
442635
442808
  unlinkSync: unlinkSync15
442636
442809
  } = await import("node:fs");
442637
- const { basename: basename21, join: join80 } = await import("node:path");
442810
+ const { basename: basename22, join: join80 } = await import("node:path");
442638
442811
  const lettaHome = process.env.LETTA_HOME || join80(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
442639
442812
  const globalSkillsDir = join80(lettaHome, "skills");
442640
442813
  if (parsed.type === "skill_enable") {
442641
442814
  try {
442642
- if (!existsSync58(parsed.skill_path)) {
442815
+ if (!existsSync57(parsed.skill_path)) {
442643
442816
  safeSocketSend(socket, {
442644
442817
  type: "skill_enable_response",
442645
442818
  request_id: parsed.request_id,
@@ -442649,7 +442822,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442649
442822
  return true;
442650
442823
  }
442651
442824
  const skillMdPath = join80(parsed.skill_path, "SKILL.md");
442652
- if (!existsSync58(skillMdPath)) {
442825
+ if (!existsSync57(skillMdPath)) {
442653
442826
  safeSocketSend(socket, {
442654
442827
  type: "skill_enable_response",
442655
442828
  request_id: parsed.request_id,
@@ -442658,11 +442831,11 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442658
442831
  }, "listener_skill_send_failed", "listener_skill_command");
442659
442832
  return true;
442660
442833
  }
442661
- const linkName = basename21(parsed.skill_path);
442834
+ const linkName = basename22(parsed.skill_path);
442662
442835
  const linkPath = join80(globalSkillsDir, linkName);
442663
442836
  mkdirSync45(globalSkillsDir, { recursive: true });
442664
- if (existsSync58(linkPath)) {
442665
- const stat12 = lstatSync3(linkPath);
442837
+ if (existsSync57(linkPath)) {
442838
+ const stat12 = lstatSync4(linkPath);
442666
442839
  if (stat12.isSymbolicLink()) {
442667
442840
  if (process.platform === "win32") {
442668
442841
  rmdirSync2(linkPath);
@@ -442703,7 +442876,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442703
442876
  if (parsed.type === "skill_disable") {
442704
442877
  try {
442705
442878
  const linkPath = join80(globalSkillsDir, parsed.name);
442706
- if (!existsSync58(linkPath)) {
442879
+ if (!existsSync57(linkPath)) {
442707
442880
  safeSocketSend(socket, {
442708
442881
  type: "skill_disable_response",
442709
442882
  request_id: parsed.request_id,
@@ -442712,7 +442885,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
442712
442885
  }, "listener_skill_send_failed", "listener_skill_command");
442713
442886
  return true;
442714
442887
  }
442715
- const stat12 = lstatSync3(linkPath);
442888
+ const stat12 = lstatSync4(linkPath);
442716
442889
  if (!stat12.isSymbolicLink()) {
442717
442890
  safeSocketSend(socket, {
442718
442891
  type: "skill_disable_response",
@@ -443211,7 +443384,7 @@ function populateInterruptQueue(runtime, input) {
443211
443384
  type: "approval",
443212
443385
  tool_call_id: toolCallId,
443213
443386
  approve: false,
443214
- reason: "User interrupted the stream"
443387
+ reason: input.denialReason ?? "User interrupted the stream"
443215
443388
  }));
443216
443389
  runtime.pendingInterruptedContext = {
443217
443390
  agentId: input.agentId,
@@ -443623,7 +443796,7 @@ var init_control_inputs = __esm(async () => {
443623
443796
  });
443624
443797
 
443625
443798
  // src/websocket/terminal-handler.ts
443626
- import { existsSync as existsSync58 } from "node:fs";
443799
+ import { existsSync as existsSync57 } from "node:fs";
443627
443800
  import * as os7 from "node:os";
443628
443801
  import WebSocket7 from "ws";
443629
443802
  function getTerminalKey(connectionId, terminalId) {
@@ -443639,7 +443812,7 @@ function getDefaultShell() {
443639
443812
  "/bin/bash"
443640
443813
  ];
443641
443814
  for (const candidate of candidates2) {
443642
- if (candidate && existsSync58(candidate)) {
443815
+ if (candidate && existsSync57(candidate)) {
443643
443816
  return candidate;
443644
443817
  }
443645
443818
  }
@@ -444036,6 +444209,24 @@ function revokeRecoveryClaims(listener, connectionId, connectionGeneration) {
444036
444209
  claim.revoke();
444037
444210
  }
444038
444211
  }
444212
+ function recoveryRefusals(listener) {
444213
+ const generation4 = listener.connectionGeneration ?? undefined;
444214
+ let state2 = refusalCounts.get(listener);
444215
+ if (!state2 || state2.generation !== generation4) {
444216
+ state2 = { generation: generation4, count: 0, refused: false };
444217
+ refusalCounts.set(listener, state2);
444218
+ }
444219
+ return state2;
444220
+ }
444221
+ function recoveryRetryDelay(listener, base2) {
444222
+ const state2 = recoveryRefusals(listener);
444223
+ if (!state2.refused)
444224
+ return base2;
444225
+ state2.refused = false;
444226
+ if (++state2.count === 5)
444227
+ debugWarn("recovery", "Recovery refused because another connection owns the conversation; abandoned until the next reconnect");
444228
+ return state2.count >= 5 ? Infinity : Math.min(base2 * 2 ** (state2.count - 1), 300000);
444229
+ }
444039
444230
  async function acquireRecoveryClaim(runtime, onLost = () => {}, dependencies4 = {}) {
444040
444231
  const connectionId = runtime.listener.connectionId;
444041
444232
  const connectionGeneration = runtime.listener.connectionGeneration;
@@ -444076,8 +444267,13 @@ async function acquireRecoveryClaim(runtime, onLost = () => {}, dependencies4 =
444076
444267
  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);
444077
444268
  runtime.listener.activeRecoveryClaims ??= new Set;
444078
444269
  runtime.listener.activeRecoveryClaims.add(claim);
444270
+ refusalCounts.delete(runtime.listener);
444079
444271
  return claim;
444080
444272
  } catch (error5) {
444273
+ if (error5 instanceof ApiRequestError && error5.status === 409 && /"owner_mismatch"/.test(error5.responseText)) {
444274
+ recoveryRefusals(runtime.listener).refused = true;
444275
+ return null;
444276
+ }
444081
444277
  debugWarn("recovery", "Recovery claim acquisition failed", error5);
444082
444278
  return null;
444083
444279
  }
@@ -444117,12 +444313,13 @@ async function getRecoveryEligibility(runtime, readStatus = getAgentRuntimeStatu
444117
444313
  async function canRecoverConversation(runtime, readStatus = getAgentRuntimeStatus) {
444118
444314
  return await getRecoveryEligibility(runtime, readStatus) === "owned";
444119
444315
  }
444120
- 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) });
444316
+ 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;
444121
444317
  var init_recovery_ownership = __esm(async () => {
444122
444318
  init_agents8();
444123
444319
  init_request();
444124
444320
  init_debug();
444125
444321
  await init_teleport();
444322
+ refusalCounts = new WeakMap;
444126
444323
  });
444127
444324
 
444128
444325
  // src/agent/approval-recovery.ts
@@ -445681,7 +445878,7 @@ var init_tui_perf = __esm(() => {
445681
445878
 
445682
445879
  // src/cli/helpers/chunk-log.ts
445683
445880
  import {
445684
- existsSync as existsSync59,
445881
+ existsSync as existsSync58,
445685
445882
  mkdirSync as mkdirSync46,
445686
445883
  readdirSync as readdirSync24,
445687
445884
  unlinkSync as unlinkSync15,
@@ -445782,7 +445979,7 @@ class ChunkLog {
445782
445979
  if (this.dirCreated || !this.agentDir)
445783
445980
  return;
445784
445981
  try {
445785
- if (!existsSync59(this.agentDir)) {
445982
+ if (!existsSync58(this.agentDir)) {
445786
445983
  mkdirSync46(this.agentDir, { recursive: true });
445787
445984
  }
445788
445985
  this.dirCreated = true;
@@ -445807,7 +446004,7 @@ class ChunkLog {
445807
446004
  if (!this.agentDir)
445808
446005
  return;
445809
446006
  try {
445810
- if (!existsSync59(this.agentDir))
446007
+ if (!existsSync58(this.agentDir))
445811
446008
  return;
445812
446009
  const files = readdirSync24(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
445813
446010
  if (files.length >= MAX_SESSION_FILES2) {
@@ -447235,6 +447432,7 @@ function finishListenerTurn(runtime, lease, options) {
447235
447432
  debugWarn("recovery", "Failed to retire completed listener work", error5);
447236
447433
  }
447237
447434
  }
447435
+ runtime.activeConnectionId = null;
447238
447436
  return transition2;
447239
447437
  }
447240
447438
  var init_turn_terminal = __esm(async () => {
@@ -449705,7 +449903,7 @@ __export(exports_diff, {
449705
449903
  ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
449706
449904
  ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
449707
449905
  });
449708
- import { basename as basename21 } from "node:path";
449906
+ import { basename as basename22 } from "node:path";
449709
449907
  function readFileOrNull(p2) {
449710
449908
  try {
449711
449909
  return __require("node:fs").readFileSync(p2, "utf-8");
@@ -449729,7 +449927,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
449729
449927
  return { ok: true, out: content.split(oldStr).join(newStr) };
449730
449928
  }
449731
449929
  function computeAdvancedDiff(input, opts) {
449732
- const fileName = basename21(input.filePath || "");
449930
+ const fileName = basename22(input.filePath || "");
449733
449931
  const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
449734
449932
  if (fileContent === null && input.kind !== "write") {
449735
449933
  return { mode: "fallback", reason: "File not readable" };
@@ -449761,7 +449959,7 @@ function computeAdvancedDiff(input, opts) {
449761
449959
  return { mode: "advanced", fileName, oldStr, newStr, hunks };
449762
449960
  }
449763
449961
  function parsePatchToAdvancedDiff(patchLines, filePath) {
449764
- const fileName = basename21(filePath);
449962
+ const fileName = basename22(filePath);
449765
449963
  const hunks = [];
449766
449964
  let currentHunk = null;
449767
449965
  let oldLine = 1;
@@ -450039,8 +450237,8 @@ function isFormatterSegment(tokens) {
450039
450237
  }
450040
450238
  }
450041
450239
  function isShellExecutor2(token2) {
450042
- const basename22 = token2.split("/").pop() ?? token2;
450043
- return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename22.toLowerCase());
450240
+ const basename23 = token2.split("/").pop() ?? token2;
450241
+ return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename23.toLowerCase());
450044
450242
  }
450045
450243
  function normalizeRawCommand(command) {
450046
450244
  if (Array.isArray(command)) {
@@ -450827,7 +451025,7 @@ var init_format_args_display = __esm(() => {
450827
451025
  });
450828
451026
 
450829
451027
  // src/helpers/diff-preview.ts
450830
- import path41, { basename as basename22 } from "node:path";
451028
+ import path41, { basename as basename23 } from "node:path";
450831
451029
  function parseHunkLinePrefix(raw2) {
450832
451030
  if (raw2.length === 0) {
450833
451031
  return { type: "context", content: "" };
@@ -450933,7 +451131,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450933
451131
  filePath: resolvedFilePath,
450934
451132
  content: toolArgs.content || ""
450935
451133
  });
450936
- previews.push(toDiffPreview(result3, basename22(filePath)));
451134
+ previews.push(toDiffPreview(result3, basename23(filePath)));
450937
451135
  }
450938
451136
  } else if (isFileEditTool3(toolName2)) {
450939
451137
  const filePath = toolArgs.file_path;
@@ -450946,7 +451144,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450946
451144
  newString: toolArgs.new_string || "",
450947
451145
  replaceAll: toolArgs.replace_all
450948
451146
  });
450949
- previews.push(toDiffPreview(result3, basename22(filePath)));
451147
+ previews.push(toDiffPreview(result3, basename23(filePath)));
450950
451148
  }
450951
451149
  } else if (isPatchTool2(toolName2) && toolArgs.input) {
450952
451150
  const operations2 = parsePatchOperations2(toolArgs.input);
@@ -450954,7 +451152,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
450954
451152
  if (op.kind === "add" || op.kind === "update") {
450955
451153
  const result3 = parsePatchToAdvancedDiff2(op.patchLines, op.path);
450956
451154
  if (result3) {
450957
- previews.push(toDiffPreview(result3, basename22(op.path)));
451155
+ previews.push(toDiffPreview(result3, basename23(op.path)));
450958
451156
  }
450959
451157
  }
450960
451158
  }
@@ -451010,7 +451208,28 @@ function safeJsonParseOr(json2, defaultValue) {
451010
451208
  async function getMissingRequiredArgs(toolName2, parsedArgs, toolContextId) {
451011
451209
  const schema5 = getToolSchema(toolName2, toolContextId);
451012
451210
  const required6 = schema5?.input_schema?.required || [];
451013
- return required6.filter((key3) => !(key3 in parsedArgs) || parsedArgs[key3] == null);
451211
+ const properties4 = schema5?.input_schema?.properties;
451212
+ return required6.filter((key3) => {
451213
+ if (!(key3 in parsedArgs) || parsedArgs[key3] === undefined)
451214
+ return true;
451215
+ if (parsedArgs[key3] === null)
451216
+ return !schemaAllowsNull2(properties4?.[key3]);
451217
+ return false;
451218
+ });
451219
+ }
451220
+ function typeAllowsNull(schema5) {
451221
+ if (!schema5 || typeof schema5 !== "object")
451222
+ return false;
451223
+ const type3 = schema5.type;
451224
+ return type3 === "null" || Array.isArray(type3) && type3.includes("null");
451225
+ }
451226
+ function schemaAllowsNull2(schema5) {
451227
+ if (typeAllowsNull(schema5))
451228
+ return true;
451229
+ if (!schema5 || typeof schema5 !== "object")
451230
+ return false;
451231
+ const { anyOf: anyOf3, oneOf: oneOf3 } = schema5;
451232
+ return [anyOf3, oneOf3].some((branches) => Array.isArray(branches) && branches.some(typeAllowsNull));
451014
451233
  }
451015
451234
  function formatMissingRequiredArgsReason(toolName2, parsedArgs, missingRequiredArgs, argsParse) {
451016
451235
  const received = Object.keys(parsedArgs).join(", ");
@@ -451687,7 +451906,7 @@ async function handleApprovalStop(params) {
451687
451906
  const sendOptions = buildSendOptions() ?? {};
451688
451907
  if (shouldInterrupt())
451689
451908
  return interruptTermination();
451690
- const consumedQueuedTurn = params.allowQueuedContinuation === false ? null : consumeQueuedTurn(runtime, params.activeOriginatorScope ?? null);
451909
+ const consumedQueuedTurn = params.allowQueuedContinuation === false ? null : consumeQueuedTurn(runtime);
451691
451910
  if (consumedQueuedTurn) {
451692
451911
  const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
451693
451912
  await params.onConsumeQueuedTurn?.(queuedTurn);
@@ -451799,7 +452018,7 @@ var init_turn_approval = __esm(async () => {
451799
452018
  });
451800
452019
 
451801
452020
  // src/agent/attached-repository-git-sync.ts
451802
- import { existsSync as existsSync60 } from "node:fs";
452021
+ import { existsSync as existsSync59 } from "node:fs";
451803
452022
  import { join as join81 } from "node:path";
451804
452023
  async function getPendingCommitCount(path42) {
451805
452024
  const divergence = await getMemoryAheadBehind(path42);
@@ -451830,7 +452049,7 @@ async function syncPendingAttachedRepositoryCommitsUnlocked(params) {
451830
452049
  path: path42,
451831
452050
  permissions: params.repository.permissions ?? "unknown"
451832
452051
  };
451833
- if (!existsSync60(join81(path42, ".git"))) {
452052
+ if (!existsSync59(join81(path42, ".git"))) {
451834
452053
  return {
451835
452054
  ...resultBase,
451836
452055
  status: "skipped",
@@ -452000,7 +452219,7 @@ var init_attached_repository_git_sync = __esm(() => {
452000
452219
  });
452001
452220
 
452002
452221
  // src/reminders/memory-git-sync.ts
452003
- import { existsSync as existsSync61 } from "node:fs";
452222
+ import { existsSync as existsSync60 } from "node:fs";
452004
452223
  import { join as join82 } from "node:path";
452005
452224
  function formatMemoryRepairInProgressReminder(result3) {
452006
452225
  return `${SYSTEM_REMINDER_OPEN}
@@ -452111,7 +452330,7 @@ async function runPostTurnMemorySync(params, dependencies4 = {}) {
452111
452330
  if (memorySyncEnabled) {
452112
452331
  try {
452113
452332
  const memoryDir = getScopedMemoryFilesystemRoot(params.agentId);
452114
- const release = existsSync61(join82(memoryDir, ".git")) ? await (dependencies4.claimOperation ?? claimMemoryOperation)(memoryDir) : undefined;
452333
+ const release = existsSync60(join82(memoryDir, ".git")) ? await (dependencies4.claimOperation ?? claimMemoryOperation)(memoryDir) : undefined;
452115
452334
  if (release !== null) {
452116
452335
  try {
452117
452336
  const result3 = await syncMemory(params.agentId);
@@ -452948,12 +453167,12 @@ function rowToolCalls(row, index, diagnostics2) {
452948
453167
  }
452949
453168
  return calls;
452950
453169
  }
452951
- function contentText2(content) {
453170
+ function contentText3(content) {
452952
453171
  if (typeof content === "string") {
452953
453172
  if (content.startsWith(CONTENT_JSON_PREFIX)) {
452954
453173
  const encoded = content.slice(CONTENT_JSON_PREFIX.length);
452955
453174
  try {
452956
- return contentText2(JSON.parse(encoded));
453175
+ return contentText3(JSON.parse(encoded));
452957
453176
  } catch {
452958
453177
  return encoded;
452959
453178
  }
@@ -453039,7 +453258,7 @@ var init_hermes = __esm(() => {
453039
453258
  });
453040
453259
  };
453041
453260
  if (row.role === "user") {
453042
- const content = contentText2(row.content);
453261
+ const content = contentText3(row.content);
453043
453262
  if (content) {
453044
453263
  emit({
453045
453264
  type: "message",
@@ -453059,7 +453278,7 @@ var init_hermes = __esm(() => {
453059
453278
  ...timestamp ? { timestamp } : {}
453060
453279
  });
453061
453280
  }
453062
- const content = contentText2(row.content);
453281
+ const content = contentText3(row.content);
453063
453282
  if (content) {
453064
453283
  emit({
453065
453284
  type: "message",
@@ -453082,7 +453301,7 @@ var init_hermes = __esm(() => {
453082
453301
  if (row.role === "tool") {
453083
453302
  emit({
453084
453303
  type: "tool_result",
453085
- content: contentText2(row.content),
453304
+ content: contentText3(row.content),
453086
453305
  ...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
453087
453306
  ...timestamp ? { timestamp } : {}
453088
453307
  });
@@ -454724,7 +454943,7 @@ var init_listing_shared = __esm(() => {
454724
454943
 
454725
454944
  // node_modules/@letta-ai/trajectory/dist/adapters/claude-code/list.js
454726
454945
  import { homedir as homedir45 } from "node:os";
454727
- import { basename as basename23, join as join85 } from "node:path";
454946
+ import { basename as basename24, join as join85 } from "node:path";
454728
454947
  async function listClaudeCodeTrajectories(root2) {
454729
454948
  const base2 = root2 ?? join85(homedir45(), ".claude", "projects");
454730
454949
  const items3 = [];
@@ -454736,7 +454955,7 @@ async function listClaudeCodeTrajectories(root2) {
454736
454955
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
454737
454956
  continue;
454738
454957
  const path42 = join85(projectPath, entry.name);
454739
- const listing = listingFromFile(basename23(entry.name, ".jsonl"), path42);
454958
+ const listing = listingFromFile(basename24(entry.name, ".jsonl"), path42);
454740
454959
  if (listing)
454741
454960
  items3.push(listing);
454742
454961
  }
@@ -454749,12 +454968,12 @@ var init_list = __esm(() => {
454749
454968
 
454750
454969
  // node_modules/@letta-ai/trajectory/dist/adapters/codex/list.js
454751
454970
  import { homedir as homedir46 } from "node:os";
454752
- import { basename as basename24, join as join86 } from "node:path";
454971
+ import { basename as basename25, join as join86 } from "node:path";
454753
454972
  async function listCodexTrajectories(root2) {
454754
454973
  const base2 = root2 ?? join86(homedir46(), ".codex", "sessions");
454755
454974
  const items3 = [];
454756
454975
  for (const path42 of collectFiles(base2, ".jsonl", 4)) {
454757
- const listing = listingFromFile(basename24(path42, ".jsonl"), path42);
454976
+ const listing = listingFromFile(basename25(path42, ".jsonl"), path42);
454758
454977
  if (listing)
454759
454978
  items3.push(listing);
454760
454979
  }
@@ -454859,9 +455078,9 @@ var init_list5 = __esm(() => {
454859
455078
  });
454860
455079
 
454861
455080
  // node_modules/@letta-ai/trajectory/dist/adapters/openclaw/list.js
454862
- import { existsSync as existsSync62 } from "node:fs";
455081
+ import { existsSync as existsSync61 } from "node:fs";
454863
455082
  import { homedir as homedir50 } from "node:os";
454864
- import { basename as basename25, join as join90 } from "node:path";
455083
+ import { basename as basename26, join as join90 } from "node:path";
454865
455084
  async function listOpenClawTrajectories(root2) {
454866
455085
  const base2 = root2 ?? defaultStateDir();
454867
455086
  const items3 = [];
@@ -454874,7 +455093,7 @@ async function listOpenClawTrajectories(root2) {
454874
455093
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
454875
455094
  continue;
454876
455095
  const path42 = join90(sessionsPath, entry.name);
454877
- const listing = listingFromFile(basename25(entry.name, ".jsonl"), path42);
455096
+ const listing = listingFromFile(basename26(entry.name, ".jsonl"), path42);
454878
455097
  if (listing)
454879
455098
  items3.push(listing);
454880
455099
  }
@@ -454886,7 +455105,7 @@ function defaultStateDir() {
454886
455105
  if (override)
454887
455106
  return override;
454888
455107
  const current = join90(homedir50(), ".openclaw");
454889
- if (existsSync62(current))
455108
+ if (existsSync61(current))
454890
455109
  return current;
454891
455110
  return join90(homedir50(), ".clawdbot");
454892
455111
  }
@@ -457392,6 +457611,11 @@ var init_execution_context_mcp_originator = __esm(async () => {
457392
457611
  await init_manager2();
457393
457612
  });
457394
457613
 
457614
+ // src/websocket/listener/mcp-originator-scope.ts
457615
+ function getEffectiveMcpOriginatorId(message2) {
457616
+ return message2.mcpOriginatorTokenPresent === true ? message2.mcpOriginatorSuperRunId : undefined;
457617
+ }
457618
+
457395
457619
  // src/websocket/listener/turn-finalizer.ts
457396
457620
  function applyTurnOriginSwap(parkedInput, consumedTurn, turnToolContextId) {
457397
457621
  retireMcpOriginatorTokensOnOriginSwap(parkedInput.mcpOriginatorSuperRunId, consumedTurn.mcpOriginatorSuperRunId);
@@ -457399,7 +457623,6 @@ function applyTurnOriginSwap(parkedInput, consumedTurn, turnToolContextId) {
457399
457623
  }
457400
457624
  function createQueuedTurnConsumer(params) {
457401
457625
  return {
457402
- activeOriginatorScope: getMcpOriginatorScope(params.parkedInput),
457403
457626
  allowQueuedContinuation: params.parkedInput.messages.some((message2) => ("content" in message2)),
457404
457627
  onConsumeQueuedTurn: async (queuedTurn) => {
457405
457628
  applyTurnOriginSwap(params.parkedInput, queuedTurn, params.turnToolContextId);
@@ -457503,6 +457726,37 @@ var init_turn_finalizer = __esm(async () => {
457503
457726
  ]);
457504
457727
  });
457505
457728
 
457729
+ // src/websocket/listener/turn-max-turns.ts
457730
+ function finishTurnIfMaxTurnsReached(params) {
457731
+ const { runtime, buffers, stopReason, agentId, conversationId } = params;
457732
+ const maxTurns = runtime.executionSettings?.max_turns;
457733
+ if (maxTurns === undefined || buffers.usage.stepCount < maxTurns || stopReason === "error" && params.fallbackError) {
457734
+ return false;
457735
+ }
457736
+ const message2 = `Maximum turns limit reached (${buffers.usage.stepCount}/${maxTurns} steps)`;
457737
+ if (stopReason === "requires_approval") {
457738
+ populateInterruptQueue(runtime, {
457739
+ lastExecutionResults: null,
457740
+ lastExecutingToolCallIds: [],
457741
+ lastNeedsUserInputToolCallIds: params.approvals.map((a2) => a2.toolCallId),
457742
+ agentId,
457743
+ conversationId,
457744
+ denialReason: message2
457745
+ });
457746
+ }
457747
+ params.finishTurn({
457748
+ stopReason: "max_steps",
457749
+ socket: params.socket,
457750
+ agentId,
457751
+ conversationId,
457752
+ errorNotice: { message: message2, runId: params.runId }
457753
+ });
457754
+ return true;
457755
+ }
457756
+ var init_turn_max_turns = __esm(async () => {
457757
+ await init_interrupts();
457758
+ });
457759
+
457506
457760
  // src/websocket/listener/turn-observers.ts
457507
457761
  function registerTurnObserver(otid, hooks) {
457508
457762
  hooksByOtid.set(otid, hooks);
@@ -458389,18 +458643,18 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
458389
458643
  break;
458390
458644
  }
458391
458645
  lastApprovalContinuationAccepted = false;
458392
- const maxTurns = runtime.executionSettings?.max_turns;
458393
- if (maxTurns !== undefined && buffers.usage.stepCount >= maxTurns && stopReason !== "requires_approval" && !(stopReason === "error" && fallbackError)) {
458394
- finishTurn({
458395
- stopReason: "max_steps",
458396
- socket,
458397
- agentId,
458398
- conversationId,
458399
- errorNotice: {
458400
- message: `Maximum turns limit reached (${buffers.usage.stepCount}/${maxTurns} steps)`,
458401
- runId: runId || runtime.activeRunId
458402
- }
458403
- });
458646
+ if (finishTurnIfMaxTurnsReached({
458647
+ runtime,
458648
+ socket,
458649
+ buffers,
458650
+ stopReason,
458651
+ approvals,
458652
+ fallbackError,
458653
+ runId: runId || runtime.activeRunId,
458654
+ agentId,
458655
+ conversationId,
458656
+ finishTurn
458657
+ })) {
458404
458658
  break;
458405
458659
  }
458406
458660
  if (stopReason === "end_turn") {
@@ -458927,6 +459181,7 @@ var init_turn = __esm(async () => {
458927
459181
  init_turn_correlation(),
458928
459182
  init_turn_durability_ownership(),
458929
459183
  init_turn_finalizer(),
459184
+ init_turn_max_turns(),
458930
459185
  init_turn_send(),
458931
459186
  init_turn_setup(),
458932
459187
  init_turn_status(),
@@ -460201,42 +460456,9 @@ function stampInboundUserMessageOtids(incoming) {
460201
460456
  function rejectReplacement(reason) {
460202
460457
  throw new Error(`Invalid listener replacement lineage: ${reason}`);
460203
460458
  }
460204
- function cloneRawData(frame) {
460205
- if (Array.isArray(frame))
460206
- return frame.map((chunk2) => Buffer.from(chunk2));
460207
- if (Buffer.isBuffer(frame))
460208
- return Buffer.from(frame);
460209
- if (frame instanceof ArrayBuffer)
460210
- return frame.slice(0);
460211
- return Buffer.from(new Uint8Array(frame));
460212
- }
460213
- function cloneStartupFrameHandoff(handoff) {
460214
- return handoff.kind === "overflow" ? { ...handoff } : { ...handoff, frames: handoff.frames.map(cloneRawData) };
460215
- }
460216
- function cloneDispositionLedger(ledger) {
460217
- return {
460218
- entries: new Map([...ledger.entries].map(([key3, entry]) => [key3, structuredClone(entry)])),
460219
- scopeCounts: new Map(ledger.scopeCounts),
460220
- quarantinedCount: ledger.quarantinedCount,
460221
- abandonedReservations: new Map([...ledger.abandonedReservations].map(([key3, reservation]) => [
460222
- key3,
460223
- { ...reservation }
460224
- ])),
460225
- expiryQueue: ledger.expiryQueue.map((entry) => ({ ...entry })),
460226
- expiryQueueHead: ledger.expiryQueueHead,
460227
- nextGeneration: ledger.nextGeneration,
460228
- persistentPath: ledger.persistentPath
460229
- };
460230
- }
460231
460459
  function createListenerClientReplacement(runtime, opts) {
460232
460460
  const lineageId = resolveStartupLineageId(runtime, opts);
460233
460461
  const generation4 = runtime.startupGenerationByLineage.get(lineageId) ?? 0;
460234
- const startupFrameHandoff = cloneStartupFrameHandoff(runtime.pendingStartupFramesByLineage.get(lineageId) ?? {
460235
- kind: "frames",
460236
- frames: [],
460237
- byteLength: 0
460238
- });
460239
- const clientMessageIdsByRunIdByConversation = cloneTurnCorrelationIndex(runtime.clientMessageIdsByRunIdByConversation);
460240
460462
  const replacement = Object.freeze({
460241
460463
  deviceId: opts.deviceId,
460242
460464
  connectionName: opts.connectionName,
@@ -460249,10 +460471,7 @@ function createListenerClientReplacement(runtime, opts) {
460249
460471
  connectionName: opts.connectionName,
460250
460472
  lineageId,
460251
460473
  generation: generation4,
460252
- authorityEpoch: getRuntimeAuthorityEpoch(runtime),
460253
- ledger: cloneDispositionLedger(runtime.acceptedInputDispositionLedger),
460254
- startupFrameHandoff: cloneStartupFrameHandoff(startupFrameHandoff),
460255
- clientMessageIdsByRunIdByConversation: cloneTurnCorrelationIndex(clientMessageIdsByRunIdByConversation)
460474
+ authorityEpoch: getRuntimeAuthorityEpoch(runtime)
460256
460475
  });
460257
460476
  return replacement;
460258
460477
  }
@@ -460267,54 +460486,29 @@ function resolveAdoptableReplacement(opts) {
460267
460486
  rejectReplacement("identity_mismatch");
460268
460487
  }
460269
460488
  const issuer = provenance.issuer;
460270
- if (succeededListenerRuntimes.has(issuer)) {
460271
- rejectReplacement("superseded_issuer");
460272
- }
460273
460489
  if ((issuer.startupGenerationByLineage.get(provenance.lineageId) ?? 0) !== provenance.generation) {
460274
460490
  rejectReplacement("stale_generation");
460275
460491
  }
460276
460492
  if (provenance.authorityEpoch === null || provenance.authorityEpoch !== getLatestRuntimeAuthorityEpoch()) {
460277
460493
  rejectReplacement("unauthoritative_issuer");
460278
460494
  }
460279
- const activeRuntime2 = getActiveRuntime();
460280
- if (issuer.intentionallyClosed) {
460281
- if (activeRuntime2 !== null && activeRuntime2 !== issuer) {
460282
- rejectReplacement("unauthoritative_issuer");
460283
- }
460284
- } else if (issuer !== activeRuntime2) {
460495
+ if (issuer.intentionallyClosed || issuer !== getActiveRuntime()) {
460285
460496
  rejectReplacement("unauthoritative_issuer");
460286
460497
  }
460287
460498
  return provenance;
460288
460499
  }
460289
- function assertAdoptableListenerClientReplacement(opts) {
460290
- resolveAdoptableReplacement(opts);
460291
- }
460292
- function adoptListenerClientReplacement(runtime, opts) {
460500
+ function adoptListenerClientReplacement(opts) {
460293
460501
  const provenance = resolveAdoptableReplacement(opts);
460294
- const replacement = opts.replacement;
460295
- if (!provenance || !replacement)
460296
- return;
460297
- replacementProvenance.delete(replacement);
460298
- succeededListenerRuntimes.add(provenance.issuer);
460299
- runtime.acceptedInputDispositionLedger = cloneDispositionLedger(provenance.ledger);
460300
- runtime.acceptedInputDispositionLedger.abandonedReservations = new Map([
460301
- ...provenance.issuer.acceptedInputDispositionLedger.abandonedReservations
460302
- ].map(([key3, reservation]) => [key3, { ...reservation }]));
460303
- runtime.clientMessageIdsByRunIdByConversation = mergeTurnCorrelationIndexes(provenance.clientMessageIdsByRunIdByConversation, provenance.issuer.clientMessageIdsByRunIdByConversation, runtime.clientMessageIdsByRunIdByConversation);
460304
- runtime.startupGenerationByLineage.set(provenance.lineageId, provenance.generation);
460305
- if (provenance.startupFrameHandoff.kind === "overflow" || provenance.startupFrameHandoff.frames.length > 0) {
460306
- runtime.pendingStartupFramesByLineage.set(provenance.lineageId, cloneStartupFrameHandoff(provenance.startupFrameHandoff));
460307
- }
460308
- }
460309
- var replacementProvenance, succeededListenerRuntimes;
460502
+ if (!provenance || !opts.replacement)
460503
+ return null;
460504
+ replacementProvenance.delete(opts.replacement);
460505
+ return provenance.issuer;
460506
+ }
460507
+ var replacementProvenance;
460310
460508
  var init_listener_replacement = __esm(async () => {
460311
460509
  init_startup_ingress();
460312
- await __promiseAll([
460313
- init_runtime6(),
460314
- init_turn_correlation()
460315
- ]);
460510
+ await init_runtime6();
460316
460511
  replacementProvenance = new WeakMap;
460317
- succeededListenerRuntimes = new WeakSet;
460318
460512
  });
460319
460513
 
460320
460514
  // src/websocket/listener/listener-task.ts
@@ -460553,7 +460747,14 @@ async function requestCloudReflectionRun(scope, args = "", backend3 = getBackend
460553
460747
  if (!backend3.retrieveReflectionConfig) {
460554
460748
  throw new Error("Unable to determine reflection ownership on this backend.");
460555
460749
  }
460556
- const config2 = await backend3.retrieveReflectionConfig(capturedScope.agentId, actingUserRequestOptions(capturedScope.actingUserId));
460750
+ let config2;
460751
+ try {
460752
+ config2 = await backend3.retrieveReflectionConfig(capturedScope.agentId, actingUserRequestOptions(capturedScope.actingUserId));
460753
+ } catch (error5) {
460754
+ if (error5 instanceof APIError && error5.status === 404)
460755
+ return null;
460756
+ throw error5;
460757
+ }
460557
460758
  if (config2 === null || config2.cutover === false)
460558
460759
  return null;
460559
460760
  if (config2.cutover !== true) {
@@ -460578,6 +460779,7 @@ async function requestReflectionRun(scope, args = "", backend3 = getBackend()) {
460578
460779
  return formatReflectionReceipt(receipt);
460579
460780
  }
460580
460781
  var init_reflection_runs2 = __esm(() => {
460782
+ init_error();
460581
460783
  init_backend2();
460582
460784
  init_reflection_runs();
460583
460785
  });
@@ -460594,9 +460796,9 @@ __export(exports_custom, {
460594
460796
  GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
460595
460797
  COMMANDS_DIR: () => COMMANDS_DIR
460596
460798
  });
460597
- import { existsSync as existsSync63 } from "node:fs";
460799
+ import { existsSync as existsSync62 } from "node:fs";
460598
460800
  import { readdir as readdir11, readFile as readFile25 } from "node:fs/promises";
460599
- import { basename as basename27, dirname as dirname36, join as join93 } from "node:path";
460801
+ import { basename as basename28, dirname as dirname36, join as join93 } from "node:path";
460600
460802
  async function getCustomCommands() {
460601
460803
  if (cachedCommands !== null) {
460602
460804
  return cachedCommands;
@@ -460628,7 +460830,7 @@ async function discoverCustomCommands(projectPath = join93(process.cwd(), COMMAN
460628
460830
  return result3;
460629
460831
  }
460630
460832
  async function discoverFromDirectory(dirPath, source) {
460631
- if (!existsSync63(dirPath)) {
460833
+ if (!existsSync62(dirPath)) {
460632
460834
  return [];
460633
460835
  }
460634
460836
  const commands = [];
@@ -460656,7 +460858,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source) {
460656
460858
  async function parseCommandFile(filePath, rootPath, source) {
460657
460859
  const content = await readFile25(filePath, "utf-8");
460658
460860
  const { frontmatter, body: body3 } = parseFrontmatter(content);
460659
- const id2 = basename27(filePath, ".md");
460861
+ const id2 = basename28(filePath, ".md");
460660
460862
  const relativePath = dirname36(filePath).slice(rootPath.length);
460661
460863
  const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
460662
460864
  let description = getStringField(frontmatter, "description");
@@ -461675,7 +461877,6 @@ function buildAppServerInfoResponse(command, options) {
461675
461877
  runtime_external_tools_update: true,
461676
461878
  structured_outputs: options.backend === "api",
461677
461879
  write_file_base64: true,
461678
- mcp_originator_queue_isolation: true,
461679
461880
  split_channels: false
461680
461881
  }
461681
461882
  };
@@ -463693,16 +463894,29 @@ async function preparePairedListenerTransport(params) {
463693
463894
  runtime.streamTransport = streamSocket;
463694
463895
  return { kind: "ready", transport: streamSocket, streamSocket };
463695
463896
  }
463897
+ function createListenerLifecycleLog(opts) {
463898
+ return (message2) => {
463899
+ if (opts.onLog) {
463900
+ opts.onLog(`[Listen] ${message2}`);
463901
+ return;
463902
+ }
463903
+ debugLog("Listen", message2);
463904
+ };
463905
+ }
463906
+ function formatListenerSocketClose(channel, code2, reason) {
463907
+ const text3 = reason.toString();
463908
+ const truncated = text3.length > MAX_CLOSE_REASON_LENGTH ? `${text3.slice(0, MAX_CLOSE_REASON_LENGTH)}...` : text3;
463909
+ return `${channel} socket closed (code=${code2}, reason=${JSON.stringify(truncated)})`;
463910
+ }
463696
463911
  function attachSplitStreamSocketHandlers(params) {
463697
463912
  params.streamSocket.on("error", (error5) => {
463913
+ params.log?.(`stream socket error: ${error5.message}`);
463698
463914
  params.trackListenerError("listener_stream_socket_error", error5, "listener_stream_socket");
463699
463915
  if (isDebugEnabled())
463700
463916
  console.error("[Listen] Stream WebSocket error:", error5);
463701
463917
  });
463702
463918
  params.streamSocket.on("close", (code2, reason) => {
463703
- if (isDebugEnabled()) {
463704
- console.log(`[Listen] Stream WebSocket closed (code: ${code2}, reason: ${reason.toString()})`);
463705
- }
463919
+ params.log?.(formatListenerSocketClose("stream", code2, reason));
463706
463920
  terminateControlAfterStreamClose(params.runtime, params.streamSocket, code2, reason);
463707
463921
  });
463708
463922
  }
@@ -463750,6 +463964,7 @@ function handleListenerSocketOpenFailure({
463750
463964
  }
463751
463965
  terminateCurrentSocketPair(runtime, controlSocket, streamSocket);
463752
463966
  }
463967
+ var MAX_CLOSE_REASON_LENGTH = 120;
463753
463968
  var init_split_stream_lifecycle = __esm(async () => {
463754
463969
  init_debug();
463755
463970
  init_constants3();
@@ -465414,10 +465629,10 @@ async function recoverRecordedTurns(listener, deps = {}) {
465414
465629
  }
465415
465630
  } finally {
465416
465631
  recovering.delete(listener);
465632
+ const retryDelayMs = recoveryRetryDelay(listener, deps.retryDelayMs ?? 5000);
465417
465633
  if (pendingRecoveries.delete(listener)) {
465418
465634
  scheduleRecordedTurnRecovery(listener, () => recoverRecordedTurns(listener, deps), deps.retryDelayMs);
465419
- } else if (deferred2 && !listener.intentionallyClosed) {
465420
- const retryDelayMs = deps.retryDelayMs ?? 5000;
465635
+ } else if (deferred2 && Number.isFinite(retryDelayMs) && !listener.intentionallyClosed) {
465421
465636
  const timer2 = setTimeout(() => {
465422
465637
  retryTimers.delete(listener);
465423
465638
  scheduleRecordedTurnRecovery(listener, () => recoverRecordedTurns(listener, deps), retryDelayMs);
@@ -465498,6 +465713,39 @@ var init_socket_send = __esm(() => {
465498
465713
  init_debug();
465499
465714
  });
465500
465715
 
465716
+ // src/websocket/listener/startup-deadline.ts
465717
+ function startListenerStartupDeadline(runtime, transport3, opts, enabled = true) {
465718
+ const socket = runtime.socket;
465719
+ if (!enabled || !socket || socket !== transport3)
465720
+ return () => {};
465721
+ const configured = Number(process.env.LETTA_LISTENER_STARTUP_DEADLINE_MS);
465722
+ const deadlineMs = Number.isFinite(configured) && configured > 0 ? configured : 60000;
465723
+ const clear = () => {
465724
+ clearTimeout(timer);
465725
+ socket.off("close", clear);
465726
+ };
465727
+ const timer = setTimeout(() => {
465728
+ clear();
465729
+ if (runtime.socket !== socket || runtime.intentionallyClosed)
465730
+ return;
465731
+ const message2 = `Listener startup did not finish within ${deadlineMs}ms; reconnecting`;
465732
+ try {
465733
+ if (opts.onLog)
465734
+ opts.onLog(message2);
465735
+ else
465736
+ debugLog("Listen", message2);
465737
+ } finally {
465738
+ socket.terminate();
465739
+ }
465740
+ }, deadlineMs);
465741
+ socket.once("close", clear);
465742
+ timer.unref();
465743
+ return clear;
465744
+ }
465745
+ var init_startup_deadline = __esm(() => {
465746
+ init_debug();
465747
+ });
465748
+
465501
465749
  // src/websocket/listener/recovery-sync.ts
465502
465750
  function isBackendNotFoundError2(error5) {
465503
465751
  return error5 instanceof APIError && (error5.status === 404 || error5.status === 422) || error5 instanceof Error && error5.name === "LocalBackendNotFoundError";
@@ -465852,6 +466100,7 @@ async function startConnectedListenerRuntime(runtime, transport3, opts, processQ
465852
466100
  startListenerPongHeartbeat(runtime, transport3, trackListenerError4);
465853
466101
  }
465854
466102
  const heartbeat = options.startHeartbeat !== false && runtime.heartbeatInterval;
466103
+ const clearStartupDeadline = startListenerStartupDeadline(runtime, transport3, opts, options.startStartupDeadline);
465855
466104
  let startupComplete = false;
465856
466105
  try {
465857
466106
  if (!await completeInitialConnectionStartup(runtime, startupConnection, transport3, opts, options))
@@ -465873,6 +466122,7 @@ async function startConnectedListenerRuntime(runtime, transport3, opts, processQ
465873
466122
  return;
465874
466123
  startupComplete = true;
465875
466124
  } finally {
466125
+ clearStartupDeadline();
465876
466126
  if (!startupComplete && heartbeat) {
465877
466127
  clearInterval(heartbeat);
465878
466128
  if (runtime.heartbeatInterval === heartbeat)
@@ -466023,13 +466273,15 @@ async function attachOpenListenerSocket(runtime, socket, opts, options = {}) {
466023
466273
  });
466024
466274
  }
466025
466275
  async function startListenerClient(opts) {
466026
- assertAdoptableListenerClientReplacement(opts);
466276
+ const resumedRuntime = adoptListenerClientReplacement(opts);
466027
466277
  const existingRuntime = getActiveRuntime();
466028
- if (existingRuntime) {
466278
+ if (existingRuntime && !resumedRuntime)
466029
466279
  stopRuntime(existingRuntime, true);
466280
+ const runtime = resumedRuntime ?? createRuntime();
466281
+ if (resumedRuntime && runtime.connectionId) {
466282
+ revokeRecoveryClaims(runtime, runtime.connectionId);
466283
+ resumeListenerConnectionIdentity(runtime, runtime.connectionId, opts.connectionId);
466030
466284
  }
466031
- const runtime = createRuntime();
466032
- adoptListenerClientReplacement(runtime, opts);
466033
466285
  runtime.onWsEvent = opts.onWsEvent;
466034
466286
  runtime.connectionId = opts.connectionId;
466035
466287
  runtime.connectionName = opts.connectionName;
@@ -466037,7 +466289,8 @@ async function startListenerClient(opts) {
466037
466289
  telemetry.setSurface(getListenerTelemetrySurface());
466038
466290
  telemetry.init();
466039
466291
  setExplicitOrganizationId(opts.organizationId);
466040
- await reloadListenerModAdapter(runtime);
466292
+ if (!resumedRuntime)
466293
+ await reloadListenerModAdapter(runtime);
466041
466294
  await connectWithRetry(runtime, opts);
466042
466295
  }
466043
466296
  async function startLocalChannelListener(opts) {
@@ -466085,6 +466338,9 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466085
466338
  if (attempt2 > 0) {
466086
466339
  if (elapsedTime >= MAX_RETRY_DURATION_MS) {
466087
466340
  if (runtime.everConnected && opts.onNeedsReregister) {
466341
+ rejectPendingExternalToolCallsForConnection(runtime, opts.connectionId, "Listener connection re-registered");
466342
+ killListenerConnectionTerminals(opts.connectionId);
466343
+ revokeRecoveryClaims(runtime, opts.connectionId);
466088
466344
  opts.onNeedsReregister(createListenerClientReplacement(runtime, opts));
466089
466345
  return;
466090
466346
  }
@@ -466128,6 +466384,7 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466128
466384
  const headers = { Authorization: `Bearer ${apiKey}` };
466129
466385
  const socket = new WebSocket11(url2.toString(), { headers });
466130
466386
  let streamSocket = streamUrl && !pairIdentity ? new WebSocket11(streamUrl.toString(), { headers }) : null;
466387
+ const lifecycleLog = createListenerLifecycleLog(opts);
466131
466388
  const fileCommandSession = createFileCommandSession({
466132
466389
  socket,
466133
466390
  safeSocketSend,
@@ -466166,7 +466423,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466166
466423
  attachSplitStreamSocketHandlers({
466167
466424
  runtime,
466168
466425
  streamSocket,
466169
- trackListenerError: trackListenerError4
466426
+ trackListenerError: trackListenerError4,
466427
+ log: lifecycleLog
466170
466428
  });
466171
466429
  }
466172
466430
  socket.on("open", () => {
@@ -466196,7 +466454,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466196
466454
  attachSplitStreamSocketHandlers({
466197
466455
  runtime,
466198
466456
  streamSocket: streamOpen.streamSocket,
466199
- trackListenerError: trackListenerError4
466457
+ trackListenerError: trackListenerError4,
466458
+ log: lifecycleLog
466200
466459
  });
466201
466460
  }
466202
466461
  if (!isCurrentSocketPair(runtime, socket, streamSocket))
@@ -466235,9 +466494,12 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466235
466494
  recordListenerPong(runtime, socket);
466236
466495
  return;
466237
466496
  }
466497
+ if (!isCurrentSocketPair(runtime, socket, streamSocket))
466498
+ return;
466238
466499
  pendingStartupFrames.accept(data, handleMessage);
466239
466500
  });
466240
466501
  socket.on("close", (code2, reason) => {
466502
+ lifecycleLog(formatListenerSocketClose("control", code2, reason));
466241
466503
  abortStartupIngress();
466242
466504
  if (!shouldHandleControlSocketClose(runtime, socket, opts.connectionId)) {
466243
466505
  return;
@@ -466249,14 +466511,11 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466249
466511
  });
466250
466512
  fileCommandSession.dispose();
466251
466513
  const reasonText = reason.toString();
466252
- const terminalClose = runtime.intentionallyClosed || code2 === 1008 || code2 === 1000 && reasonText === "Replaced by new connection";
466514
+ const terminalClose = runtime.intentionallyClosed || code2 === 1008 && reasonText !== CLOUD_ENVIRONMENT_NOT_FOUND_CLOSE_REASON || code2 === 1000 && reasonText === "Replaced by new connection";
466253
466515
  if (!terminalClose && runtime.hasSuccessfulConnection) {
466254
466516
  opts.onRetrying?.(0, MAX_RETRY_ATTEMPTS, 0, opts.connectionId);
466255
466517
  }
466256
466518
  clearRuntimeTimers(runtime);
466257
- if (isDebugEnabled()) {
466258
- console.log(`[Listen] WebSocket disconnected (code: ${code2}, reason: ${reason.toString()})`);
466259
- }
466260
466519
  if (!terminalClose) {
466261
466520
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
466262
466521
  rejectPendingApprovalResolversForConnection(conversationRuntime, opts.connectionId, "Listener connection closed");
@@ -466268,7 +466527,8 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466268
466527
  revokeRecoveryClaims(runtime, undefined, closingGeneration);
466269
466528
  }
466270
466529
  suspendListenerConnection(runtime, opts.connectionId);
466271
- killAllTerminals();
466530
+ if (terminalClose)
466531
+ killAllTerminals();
466272
466532
  clearListenerWarmState(runtime);
466273
466533
  if (streamSocket) {
466274
466534
  streamSocket.removeAllListeners("message");
@@ -466281,27 +466541,21 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466281
466541
  runtime.socket = null;
466282
466542
  runtime.streamSocket = null;
466283
466543
  runtime.streamTransport = null;
466284
- if (terminalClose) {
466285
- const replacement = code2 === 1008 ? createListenerClientReplacement(runtime, opts) : null;
466286
- if (getActiveRuntime() === runtime) {
466544
+ if (code2 === 1008 && !terminalClose && opts.onNeedsReregister) {
466545
+ rejectPendingExternalToolCallsForConnection(runtime, opts.connectionId, "Listener connection re-registered");
466546
+ killListenerConnectionTerminals(opts.connectionId);
466547
+ revokeRecoveryClaims(runtime, opts.connectionId);
466548
+ opts.onNeedsReregister(createListenerClientReplacement(runtime, opts));
466549
+ return;
466550
+ }
466551
+ if (terminalClose || code2 === 1008) {
466552
+ if (getActiveRuntime() === runtime)
466287
466553
  setActiveRuntime(null);
466288
- }
466289
466554
  stopRuntime(runtime, true);
466290
- if (code2 === 1008) {
466291
- if (isDebugEnabled()) {
466292
- console.log("[Listen] Environment not found, re-registering...");
466293
- }
466294
- if (opts.onNeedsReregister) {
466295
- if (!replacement) {
466296
- throw new Error("Missing listener replacement lineage");
466297
- }
466298
- opts.onNeedsReregister(replacement);
466299
- } else {
466300
- opts.onDisconnected();
466301
- }
466302
- return;
466303
- }
466304
- opts.onDisconnected();
466555
+ if (code2 === 1008 && opts.onNeedsReregister)
466556
+ opts.onNeedsReregister();
466557
+ else
466558
+ opts.onDisconnected();
466305
466559
  return;
466306
466560
  }
466307
466561
  const nextAttempt = runtime.hasSuccessfulConnection ? 0 : attempt2 + 1;
@@ -466312,7 +466566,10 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
466312
466566
  });
466313
466567
  });
466314
466568
  socket.on("error", (error5) => {
466569
+ if (runtime.socket !== socket)
466570
+ return;
466315
466571
  trackListenerError4("listener_websocket_error", error5, "listener_socket");
466572
+ lifecycleLog(`control socket error: ${error5.message}`);
466316
466573
  safeEmitWsEvent("recv", "lifecycle", {
466317
466574
  type: "_ws_error",
466318
466575
  message: error5.message
@@ -466351,6 +466608,7 @@ var init_lifecycle = __esm(async () => {
466351
466608
  init_listener_task();
466352
466609
  init_permission_mode();
466353
466610
  init_socket_send();
466611
+ init_startup_deadline();
466354
466612
  init_startup_frame_buffer();
466355
466613
  init_startup_ingress();
466356
466614
  init_stream_observers();
@@ -469673,7 +469931,7 @@ async function runListenSubcommand(argv) {
469673
469931
  },
469674
469932
  onConnected: () => {},
469675
469933
  onConnectionReady: async (connectedId) => {
469676
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
469934
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469677
469935
  if (!ready)
469678
469936
  return;
469679
469937
  sessionLog.log("Local channel listener ready.");
@@ -469756,7 +470014,8 @@ async function runListenSubcommand(argv) {
469756
470014
  console.log(`[${formatTimestamp3()}] ${arrow}${tag} ${json2}`);
469757
470015
  }
469758
470016
  };
469759
- if (debugMode || lifecycleOutput) {
470017
+ if (shouldUseNonInteractiveListenerOutput(debugMode, !!lifecycleOutput)) {
470018
+ const printPlainLines = debugMode || !lifecycleOutput;
469760
470019
  const startNonInteractiveClient = async (connId, url2, nextSupportsSplitStatusChannels, nextSupportsPairedListenerGenerations, replacement) => {
469761
470020
  await startListenerClient2({
469762
470021
  replacement,
@@ -469772,18 +470031,18 @@ async function runListenSubcommand(argv) {
469772
470031
  onStatusChange: (status) => {
469773
470032
  sessionLog.log(`status: ${status}`);
469774
470033
  readiness.setStatus(status);
469775
- if (debugMode) {
470034
+ if (printPlainLines) {
469776
470035
  console.log(`[${formatTimestamp3()}] status: ${status}`);
469777
470036
  }
469778
470037
  },
469779
470038
  onLog: logListenerMessage,
469780
470039
  onConnected: () => {},
469781
470040
  onConnectionReady: async (connectedId) => {
469782
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
470041
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469783
470042
  if (!ready)
469784
470043
  return;
469785
470044
  sessionLog.log("Connected. Awaiting instructions.");
469786
- if (debugMode) {
470045
+ if (printPlainLines) {
469787
470046
  console.log(`[${formatTimestamp3()}] Connected. Awaiting instructions.`);
469788
470047
  console.log("");
469789
470048
  }
@@ -469791,13 +470050,13 @@ async function runListenSubcommand(argv) {
469791
470050
  onRetrying: (attempt2, _maxAttempts, nextRetryIn) => {
469792
470051
  readiness.setCloudReconnecting();
469793
470052
  sessionLog.log(`Reconnecting (attempt ${attempt2}, retry in ${Math.round(nextRetryIn / 1000)}s)`);
469794
- if (debugMode) {
470053
+ if (printPlainLines) {
469795
470054
  console.log(`[${formatTimestamp3()}] Reconnecting (attempt ${attempt2}, retry in ${Math.round(nextRetryIn / 1000)}s)`);
469796
470055
  }
469797
470056
  },
469798
470057
  onNeedsReregister: async (replacement2) => {
469799
470058
  readiness.setCloudReconnecting();
469800
- if (debugMode) {
470059
+ if (printPlainLines) {
469801
470060
  console.log(`[${formatTimestamp3()}] Computer connection expired, re-registering...`);
469802
470061
  }
469803
470062
  try {
@@ -469859,7 +470118,7 @@ async function runListenSubcommand(argv) {
469859
470118
  onLog: logListenerMessage,
469860
470119
  onConnected: () => {},
469861
470120
  onConnectionReady: async (connectedId) => {
469862
- const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway);
470121
+ const ready = await completeListenerConnectionStartup(connectedId, readiness, startChannelGateway, (error5) => logListenerMessage(`[ChannelGateway] startup failed: ${error5}`));
469863
470122
  if (!ready)
469864
470123
  return;
469865
470124
  sessionLog.log("Connected. Awaiting instructions.");
@@ -469962,7 +470221,7 @@ var init_listen = __esm(async () => {
469962
470221
  import { randomUUID as randomUUID55 } from "node:crypto";
469963
470222
  import {
469964
470223
  copyFileSync as copyFileSync3,
469965
- existsSync as existsSync64,
470224
+ existsSync as existsSync63,
469966
470225
  mkdirSync as mkdirSync47,
469967
470226
  readdirSync as readdirSync26,
469968
470227
  readFileSync as readFileSync48,
@@ -469970,7 +470229,7 @@ import {
469970
470229
  } from "node:fs";
469971
470230
  import { join as join94 } from "node:path";
469972
470231
  function readJsonl(path46) {
469973
- if (!existsSync64(path46))
470232
+ if (!existsSync63(path46))
469974
470233
  return [];
469975
470234
  return readFileSync48(path46, "utf8").split(`
469976
470235
  `).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
@@ -470258,13 +470517,13 @@ function migrateLocalBackendTranscripts(input) {
470258
470517
  skipped: [],
470259
470518
  dryRun: input.dryRun === true
470260
470519
  };
470261
- if (!existsSync64(conversationsDir))
470520
+ if (!existsSync63(conversationsDir))
470262
470521
  return result3;
470263
470522
  for (const name of readdirSync26(conversationsDir)) {
470264
470523
  const conversationDir = join94(conversationsDir, name);
470265
470524
  const messagesPath = join94(conversationDir, "messages.jsonl");
470266
470525
  const manifestPath = join94(conversationDir, "manifest.json");
470267
- const hasManifest = existsSync64(manifestPath);
470526
+ const hasManifest = existsSync63(manifestPath);
470268
470527
  const existingManifest = hasManifest ? (() => {
470269
470528
  try {
470270
470529
  return JSON.parse(readFileSync48(manifestPath, "utf8"));
@@ -470308,7 +470567,7 @@ function migrateLocalBackendTranscripts(input) {
470308
470567
  copyFileSync3(messagesPath, backupPath);
470309
470568
  const conversationPath = join94(conversationDir, "conversation.json");
470310
470569
  let conversation;
470311
- if (existsSync64(conversationPath)) {
470570
+ if (existsSync63(conversationPath)) {
470312
470571
  try {
470313
470572
  conversation = JSON.parse(readFileSync48(conversationPath, "utf8"));
470314
470573
  } catch {
@@ -470502,7 +470761,7 @@ var init_memory_tokens = __esm(() => {
470502
470761
  });
470503
470762
 
470504
470763
  // src/cli/subcommands/memory.ts
470505
- import { cpSync, existsSync as existsSync65, mkdirSync as mkdirSync48, rmSync as rmSync22, statSync as statSync24 } from "node:fs";
470764
+ import { cpSync, existsSync as existsSync64, mkdirSync as mkdirSync48, rmSync as rmSync22, statSync as statSync24 } from "node:fs";
470506
470765
  import { readdir as readdir12 } from "node:fs/promises";
470507
470766
  import { dirname as dirname37, join as join95 } from "node:path";
470508
470767
  import { parseArgs as parseArgs11 } from "node:util";
@@ -470564,7 +470823,7 @@ function formatBackupTimestamp(date5 = new Date) {
470564
470823
  }
470565
470824
  async function listBackups(agentId) {
470566
470825
  const agentRoot = getAgentRoot(agentId);
470567
- if (!existsSync65(agentRoot)) {
470826
+ if (!existsSync64(agentRoot)) {
470568
470827
  return [];
470569
470828
  }
470570
470829
  const entries2 = await readdir12(agentRoot, { withFileTypes: true });
@@ -470669,14 +470928,14 @@ async function runMemorySubcommand(argv, deps = {}) {
470669
470928
  }
470670
470929
  if (action3 === "backup") {
470671
470930
  const root2 = getMemoryRoot(agentId);
470672
- if (!existsSync65(root2)) {
470931
+ if (!existsSync64(root2)) {
470673
470932
  console.error(`Memory directory not found for agent ${agentId}.`);
470674
470933
  return 1;
470675
470934
  }
470676
470935
  const agentRoot = getAgentRoot(agentId);
470677
470936
  const backupName = `memory-backup-${formatBackupTimestamp()}`;
470678
470937
  const backupPath = join95(agentRoot, backupName);
470679
- if (existsSync65(backupPath)) {
470938
+ if (existsSync64(backupPath)) {
470680
470939
  console.error(`Backup already exists at ${backupPath}`);
470681
470940
  return 1;
470682
470941
  }
@@ -470700,7 +470959,7 @@ async function runMemorySubcommand(argv, deps = {}) {
470700
470959
  return 1;
470701
470960
  }
470702
470961
  const backupPath = resolveBackupPath(agentId, from);
470703
- if (!existsSync65(backupPath)) {
470962
+ if (!existsSync64(backupPath)) {
470704
470963
  console.error(`Backup not found: ${backupPath}`);
470705
470964
  return 1;
470706
470965
  }
@@ -470722,11 +470981,11 @@ async function runMemorySubcommand(argv, deps = {}) {
470722
470981
  return 1;
470723
470982
  }
470724
470983
  const root2 = getMemoryRoot(agentId);
470725
- if (!existsSync65(root2)) {
470984
+ if (!existsSync64(root2)) {
470726
470985
  console.error(`Memory directory not found for agent ${agentId}.`);
470727
470986
  return 1;
470728
470987
  }
470729
- if (existsSync65(out)) {
470988
+ if (existsSync64(out)) {
470730
470989
  const stat15 = statSync24(out);
470731
470990
  if (stat15.isDirectory()) {
470732
470991
  const contents = await readdir12(out);
@@ -470775,10 +471034,10 @@ var init_memory7 = __esm(() => {
470775
471034
  });
470776
471035
 
470777
471036
  // src/backend/local/transcript-search.ts
470778
- import { existsSync as existsSync66, readdirSync as readdirSync27, readFileSync as readFileSync49, statSync as statSync25 } from "node:fs";
471037
+ import { existsSync as existsSync65, readdirSync as readdirSync27, readFileSync as readFileSync49, statSync as statSync25 } from "node:fs";
470779
471038
  import { join as join96 } from "node:path";
470780
471039
  function readJsonFile3(path46) {
470781
- if (!existsSync66(path46))
471040
+ if (!existsSync65(path46))
470782
471041
  return;
470783
471042
  try {
470784
471043
  return JSON.parse(readFileSync49(path46, "utf8"));
@@ -471060,7 +471319,7 @@ function collectConversationMessages(input) {
471060
471319
  }
471061
471320
  function conversationDirectories(storageDir) {
471062
471321
  const conversationsDir = join96(storageDir, "conversations");
471063
- if (!existsSync66(conversationsDir))
471322
+ if (!existsSync65(conversationsDir))
471064
471323
  return [];
471065
471324
  try {
471066
471325
  return readdirSync27(conversationsDir).map((entry) => join96(conversationsDir, entry)).filter((entryPath) => statSync25(entryPath).isDirectory());
@@ -471974,13 +472233,13 @@ var init_model2 = __esm(() => {
471974
472233
  import { spawn as spawn13 } from "node:child_process";
471975
472234
  import {
471976
472235
  copyFileSync as copyFileSync4,
471977
- existsSync as existsSync67,
471978
- lstatSync as lstatSync3,
472236
+ existsSync as existsSync66,
472237
+ lstatSync as lstatSync4,
471979
472238
  mkdirSync as mkdirSync49,
471980
472239
  mkdtempSync as mkdtempSync5,
471981
472240
  readdirSync as readdirSync28,
471982
472241
  readFileSync as readFileSync50,
471983
- renameSync as renameSync14,
472242
+ renameSync as renameSync11,
471984
472243
  rmSync as rmSync23,
471985
472244
  writeFileSync as writeFileSync40
471986
472245
  } from "node:fs";
@@ -472023,7 +472282,7 @@ function formatRepository(repository) {
472023
472282
  function isLocalLettaModPackageDirectory(packageDirectory) {
472024
472283
  const resolvedPackageDirectory = path46.resolve(packageDirectory);
472025
472284
  try {
472026
- const packageStats = lstatSync3(resolvedPackageDirectory);
472285
+ const packageStats = lstatSync4(resolvedPackageDirectory);
472027
472286
  if (packageStats.isSymbolicLink() || !packageStats.isDirectory()) {
472028
472287
  return false;
472029
472288
  }
@@ -472050,7 +472309,7 @@ function validateManifestEntriesExist(packageRoot, entries2) {
472050
472309
  const entryPath = resolvePackageRelativePath(packageRoot, entry);
472051
472310
  let stats;
472052
472311
  try {
472053
- stats = lstatSync3(entryPath);
472312
+ stats = lstatSync4(entryPath);
472054
472313
  } catch {
472055
472314
  throw new Error(`Package mod entry does not exist: ${entry}`);
472056
472315
  }
@@ -472066,7 +472325,7 @@ function resolvePackageDirectory(packageDirectory) {
472066
472325
  const resolvedPackageDirectory = path46.resolve(packageDirectory);
472067
472326
  let packageStats;
472068
472327
  try {
472069
- packageStats = lstatSync3(resolvedPackageDirectory);
472328
+ packageStats = lstatSync4(resolvedPackageDirectory);
472070
472329
  } catch {
472071
472330
  throw new Error(`Package directory does not exist: ${packageDirectory}`);
472072
472331
  }
@@ -472124,7 +472383,7 @@ function copyPackageDirectory(sourceRoot, targetRoot) {
472124
472383
  continue;
472125
472384
  const sourcePath = path46.join(sourceRoot, entry.name);
472126
472385
  const targetPath = path46.join(targetRoot, entry.name);
472127
- const stats = lstatSync3(sourcePath);
472386
+ const stats = lstatSync4(sourcePath);
472128
472387
  if (stats.isSymbolicLink()) {
472129
472388
  throw new Error(`Package contains unsupported symlink: ${sourcePath}`);
472130
472389
  }
@@ -472158,7 +472417,7 @@ function copyDependencyDirectoryFiltered(params) {
472158
472417
  }
472159
472418
  const sourcePath = path46.join(params.sourceRoot, entry.name);
472160
472419
  const targetPath = path46.join(params.targetRoot, entry.name);
472161
- const stats = lstatSync3(sourcePath);
472420
+ const stats = lstatSync4(sourcePath);
472162
472421
  if (stats.isSymbolicLink()) {
472163
472422
  throw new Error(`Package dependency contains unsupported symlink: ${sourcePath}`);
472164
472423
  }
@@ -472183,7 +472442,7 @@ function copyDependencyDirectoryFiltered(params) {
472183
472442
  return copied;
472184
472443
  }
472185
472444
  function copyDependencyNodeModules(params) {
472186
- if (!existsSync67(params.sourceNodeModulesDirectory))
472445
+ if (!existsSync66(params.sourceNodeModulesDirectory))
472187
472446
  return;
472188
472447
  copyDependencyDirectoryFiltered({
472189
472448
  installedPackageName: params.installedPackageName,
@@ -472193,7 +472452,7 @@ function copyDependencyNodeModules(params) {
472193
472452
  }
472194
472453
  function copyPackageInternalNodeModules(params) {
472195
472454
  const sourceNodeModulesDirectory = path46.join(params.packageDirectory, "node_modules");
472196
- if (!existsSync67(sourceNodeModulesDirectory))
472455
+ if (!existsSync66(sourceNodeModulesDirectory))
472197
472456
  return;
472198
472457
  copyDependencyDirectoryFiltered({
472199
472458
  sourceRoot: sourceNodeModulesDirectory,
@@ -472215,12 +472474,12 @@ function removeIfExists(targetPath) {
472215
472474
  }
472216
472475
  function restoreDestination(params) {
472217
472476
  rmSync23(params.destinationRoot, { force: true, recursive: true });
472218
- if (params.backupRoot && existsSync67(params.backupRoot)) {
472219
- renameSync14(params.backupRoot, params.destinationRoot);
472477
+ if (params.backupRoot && existsSync66(params.backupRoot)) {
472478
+ renameSync11(params.backupRoot, params.destinationRoot);
472220
472479
  }
472221
472480
  }
472222
472481
  function restoreDestinationIfNeeded(params) {
472223
- if (!params.backupRoot || !existsSync67(params.backupRoot)) {
472482
+ if (!params.backupRoot || !existsSync66(params.backupRoot)) {
472224
472483
  rmSync23(params.destinationRoot, { force: true, recursive: true });
472225
472484
  return;
472226
472485
  }
@@ -472261,13 +472520,13 @@ function installPreparedManagedModPackage(params) {
472261
472520
  targetPackageRoot: stagingRoot
472262
472521
  });
472263
472522
  }
472264
- if (existsSync67(destinationRoot)) {
472523
+ if (existsSync66(destinationRoot)) {
472265
472524
  backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
472266
472525
  rmSync23(backupRoot, { force: true, recursive: true });
472267
- renameSync14(destinationRoot, backupRoot);
472526
+ renameSync11(destinationRoot, backupRoot);
472268
472527
  destinationNeedsRollback = true;
472269
472528
  }
472270
- renameSync14(stagingRoot, destinationRoot);
472529
+ renameSync11(stagingRoot, destinationRoot);
472271
472530
  destinationNeedsRollback = true;
472272
472531
  stagingRoot = null;
472273
472532
  try {
@@ -472546,13 +472805,13 @@ function hasRuntimeDependencies(packageJson) {
472546
472805
  }
472547
472806
  function readPackageJsonIfExists(packageDirectory) {
472548
472807
  const packageJsonPath = path46.join(packageDirectory, "package.json");
472549
- if (!existsSync67(packageJsonPath))
472808
+ if (!existsSync66(packageJsonPath))
472550
472809
  return null;
472551
472810
  return readPackageJson(packageJsonPath);
472552
472811
  }
472553
472812
  function isRegularModFile(filePath) {
472554
472813
  try {
472555
- const stats = lstatSync3(filePath);
472814
+ const stats = lstatSync4(filePath);
472556
472815
  return !stats.isSymbolicLink() && stats.isFile();
472557
472816
  } catch {
472558
472817
  return false;
@@ -472560,8 +472819,8 @@ function isRegularModFile(filePath) {
472560
472819
  }
472561
472820
  function inferCompatibilityModEntries(packageDirectory) {
472562
472821
  const modsDirectory = path46.join(packageDirectory, "mods");
472563
- if (existsSync67(modsDirectory)) {
472564
- const stats = lstatSync3(modsDirectory);
472822
+ if (existsSync66(modsDirectory)) {
472823
+ const stats = lstatSync4(modsDirectory);
472565
472824
  if (stats.isSymbolicLink()) {
472566
472825
  throw new Error(`Package mods directory must not be a symlink: mods`);
472567
472826
  }
@@ -472835,8 +473094,8 @@ var init_package_installer = __esm(() => {
472835
473094
  // src/mods/package-scaffolder.ts
472836
473095
  import {
472837
473096
  copyFileSync as copyFileSync5,
472838
- existsSync as existsSync68,
472839
- lstatSync as lstatSync4,
473097
+ existsSync as existsSync67,
473098
+ lstatSync as lstatSync5,
472840
473099
  mkdirSync as mkdirSync50,
472841
473100
  rmSync as rmSync24,
472842
473101
  writeFileSync as writeFileSync41
@@ -472862,7 +473121,7 @@ function readSourceFile(sourceFile) {
472862
473121
  const resolvedSourceFile = path47.resolve(sourceFile);
472863
473122
  let stats;
472864
473123
  try {
472865
- stats = lstatSync4(resolvedSourceFile);
473124
+ stats = lstatSync5(resolvedSourceFile);
472866
473125
  } catch {
472867
473126
  throw new Error(`Mod file does not exist: ${sourceFile}`);
472868
473127
  }
@@ -472928,7 +473187,7 @@ function scaffoldLocalModPackage(options) {
472928
473187
  const sourceFile = readSourceFile(options.sourceFile);
472929
473188
  const packageName = assertValidPackageName(options.packageName);
472930
473189
  const outputDirectory = path47.resolve(options.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
472931
- if (existsSync68(outputDirectory)) {
473190
+ if (existsSync67(outputDirectory)) {
472932
473191
  throw new Error(`Output directory already exists: ${outputDirectory}`);
472933
473192
  }
472934
473193
  const modFileName = path47.basename(sourceFile);
@@ -473484,7 +473743,7 @@ var init_sandbox_files = __esm(() => {
473484
473743
 
473485
473744
  // src/cli/subcommands/sandbox.ts
473486
473745
  import { readFile as readFile27, stat as stat15, writeFile as writeFile19 } from "node:fs/promises";
473487
- import { basename as basename28, resolve as resolve40 } from "node:path";
473746
+ import { basename as basename29, resolve as resolve40 } from "node:path";
473488
473747
  import { parseArgs as parseArgs16 } from "node:util";
473489
473748
  function printUsage13() {
473490
473749
  console.log(`
@@ -473635,13 +473894,13 @@ async function runSandboxSubcommand(argv, deps = {}) {
473635
473894
  throw new Error(`${localPath2} is not a file`);
473636
473895
  const data2 = await (deps.readLocalFile ?? readFile27)(localPath2);
473637
473896
  const sandbox2 = await ensureSandbox();
473638
- const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename28(localPath2) });
473897
+ const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename29(localPath2) });
473639
473898
  console.log(JSON.stringify({ ...result3, ...targetOutput }, null, 2));
473640
473899
  return 0;
473641
473900
  }
473642
473901
  const sandbox = await ensureSandbox();
473643
473902
  const data = await (deps.downloadFile ?? downloadFileFromSandbox)(sandbox.sandboxId, path48);
473644
- const localPath = resolve40(parsed.values.to ?? basename28(path48));
473903
+ const localPath = resolve40(parsed.values.to ?? basename29(path48));
473645
473904
  await (deps.writeLocalFile ?? writeFile19)(localPath, data);
473646
473905
  console.log(JSON.stringify({
473647
473906
  path: localPath,
@@ -474551,7 +474810,7 @@ var init_setup7 = __esm(async () => {
474551
474810
  });
474552
474811
 
474553
474812
  // src/cli/subcommands/shared-memory.ts
474554
- import { existsSync as existsSync69 } from "node:fs";
474813
+ import { existsSync as existsSync68 } from "node:fs";
474555
474814
  import { join as join98 } from "node:path";
474556
474815
  import { parseArgs as parseArgs19 } from "node:util";
474557
474816
  function printUsage16() {
@@ -474744,7 +475003,7 @@ async function runSharedMemorySubcommand(argv, deps = {}) {
474744
475003
  invalidateClientSkills(agentId);
474745
475004
  const recompileError = await recompileAndReportFailure(recompileAgent, agentId);
474746
475005
  const mountDir = getRepositoryMountDir(agentId, repository.name);
474747
- const mounted = existsSync69(join98(mountDir, ".git"));
475006
+ const mounted = existsSync68(join98(mountDir, ".git"));
474748
475007
  console.log(JSON.stringify({
474749
475008
  attached: true,
474750
475009
  repository: { id: repository.id, name: repository.name },
@@ -476273,7 +476532,7 @@ var init_AgentSelector = __esm(async () => {
476273
476532
  // src/cli/subcommands/skills.ts
476274
476533
  import {
476275
476534
  cpSync as cpSync2,
476276
- existsSync as existsSync70,
476535
+ existsSync as existsSync69,
476277
476536
  mkdtempSync as mkdtempSync6,
476278
476537
  readFileSync as readFileSync51,
476279
476538
  rmSync as rmSync25,
@@ -476282,7 +476541,7 @@ import {
476282
476541
  } from "node:fs";
476283
476542
  import { mkdir as mkdir16, readdir as readdir13 } from "node:fs/promises";
476284
476543
  import { tmpdir as tmpdir14 } from "node:os";
476285
- import { basename as basename29, dirname as dirname39, join as join99, normalize as normalize4, resolve as resolve41, sep as sep8 } from "node:path";
476544
+ import { basename as basename30, dirname as dirname39, join as join99, normalize as normalize4, resolve as resolve41, sep as sep8 } from "node:path";
476286
476545
  import { parseArgs as parseArgs20, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
476287
476546
  function printUsage17() {
476288
476547
  console.log(`
@@ -476477,7 +476736,7 @@ function parseDirectSkillFileUrlSpecifier(input) {
476477
476736
  if (url2.protocol !== "https:" && !(url2.protocol === "http:" && isLocalhostHostname(url2.hostname))) {
476478
476737
  return null;
476479
476738
  }
476480
- if (basename29(url2.pathname).toLowerCase() !== "skill.md")
476739
+ if (basename30(url2.pathname).toLowerCase() !== "skill.md")
476481
476740
  return null;
476482
476741
  return { url: url2.toString() };
476483
476742
  }
@@ -476725,14 +476984,14 @@ function getSkillName(sourceDir) {
476725
476984
  const skillMd = readFileSync51(join99(sourceDir, "SKILL.md"), "utf8");
476726
476985
  const { frontmatter } = parseFrontmatter(skillMd);
476727
476986
  const frontmatterName = frontmatter.name;
476728
- const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename29(sourceDir);
476987
+ const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename30(sourceDir);
476729
476988
  return sanitizeSkillName(name);
476730
476989
  }
476731
476990
  async function installSkillDirectory(params) {
476732
476991
  const sourceDir = resolve41(params.sourceDir);
476733
476992
  const memoryDir = resolve41(params.memoryDir);
476734
476993
  const skillMdPath = join99(sourceDir, "SKILL.md");
476735
- if (!existsSync70(skillMdPath)) {
476994
+ if (!existsSync69(skillMdPath)) {
476736
476995
  throw new Error("No SKILL.md found in the skill directory.");
476737
476996
  }
476738
476997
  if (!statSync26(sourceDir).isDirectory()) {
@@ -476742,7 +477001,7 @@ async function installSkillDirectory(params) {
476742
477001
  const skillsDir = join99(memoryDir, "skills");
476743
477002
  const targetPath = join99(skillsDir, name);
476744
477003
  assertInside(skillsDir, targetPath);
476745
- if (existsSync70(targetPath)) {
477004
+ if (existsSync69(targetPath)) {
476746
477005
  if (!params.force) {
476747
477006
  throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
476748
477007
  }
@@ -476751,14 +477010,14 @@ async function installSkillDirectory(params) {
476751
477010
  await mkdir16(skillsDir, { recursive: true });
476752
477011
  cpSync2(sourceDir, targetPath, {
476753
477012
  recursive: true,
476754
- filter: (source) => basename29(source) !== ".git"
477013
+ filter: (source) => basename30(source) !== ".git"
476755
477014
  });
476756
477015
  return { name, path: normalize4(targetPath) };
476757
477016
  }
476758
477017
  async function listSkillDirectories(params) {
476759
477018
  const memoryDir = resolve41(params.memoryDir);
476760
477019
  const skillsDir = join99(memoryDir, "skills");
476761
- if (!existsSync70(skillsDir))
477020
+ if (!existsSync69(skillsDir))
476762
477021
  return [];
476763
477022
  const entries2 = await readdir13(skillsDir, { withFileTypes: true });
476764
477023
  const skills = [];
@@ -476767,7 +477026,7 @@ async function listSkillDirectories(params) {
476767
477026
  continue;
476768
477027
  const skillDir = join99(skillsDir, entry.name);
476769
477028
  const skillMdPath = join99(skillDir, "SKILL.md");
476770
- if (!existsSync70(skillMdPath))
477029
+ if (!existsSync69(skillMdPath))
476771
477030
  continue;
476772
477031
  let name = entry.name;
476773
477032
  let description;
@@ -476791,7 +477050,7 @@ async function deleteSkillDirectory(params) {
476791
477050
  const name = sanitizeSkillName(params.name);
476792
477051
  const targetPath = join99(skillsDir, name);
476793
477052
  assertInside(skillsDir, targetPath);
476794
- if (!existsSync70(targetPath)) {
477053
+ if (!existsSync69(targetPath)) {
476795
477054
  throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
476796
477055
  }
476797
477056
  if (!statSync26(targetPath).isDirectory()) {
@@ -476840,7 +477099,7 @@ async function installSkill(specifier, agentId, force) {
476840
477099
  tmpDir = downloaded.tmpDir;
476841
477100
  const sourceDir = resolve41(downloaded.sourceDir);
476842
477101
  assertInside(tmpDir, sourceDir);
476843
- if (!existsSync70(sourceDir)) {
477102
+ if (!existsSync69(sourceDir)) {
476844
477103
  const missingPath = source.type === "git" ? source.location.subdir ?? "." : source.type === "direct-file" ? source.location.url : source.location.slug;
476845
477104
  throw new Error(`Skill path not found: ${missingPath}`);
476846
477105
  }
@@ -477471,7 +477730,7 @@ import {
477471
477730
  stat as stat17,
477472
477731
  writeFile as writeFile20
477473
477732
  } from "node:fs/promises";
477474
- import { basename as basename30, join as join101 } from "node:path";
477733
+ import { basename as basename31, join as join101 } from "node:path";
477475
477734
  function fileTimestamp(startedAt) {
477476
477735
  if (!startedAt)
477477
477736
  return "unknown-date";
@@ -477639,10 +477898,10 @@ async function runTrajectoryExport(options) {
477639
477898
  if (!supported.includes(explicit.source)) {
477640
477899
  throw new Error(`Unknown source "${explicit.source}" in --transcript. The installed trajectory package supports: ${supported.join(", ")}.`);
477641
477900
  }
477642
- await exportTranscript(explicit.source, basename30(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile29(explicit.path, "utf-8"));
477901
+ await exportTranscript(explicit.source, basename31(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile29(explicit.path, "utf-8"));
477643
477902
  }
477644
477903
  for (const checkpoint of options.deepagents ?? []) {
477645
- await exportCheckpoint(checkpoint, `${basename30(checkpoint.path)}-${checkpoint.threadId}`);
477904
+ await exportCheckpoint(checkpoint, `${basename31(checkpoint.path)}-${checkpoint.threadId}`);
477646
477905
  }
477647
477906
  manifest2.sessions.sort((a2, b3) => (a2.startedAt ?? "").localeCompare(b3.startedAt ?? ""));
477648
477907
  await writeFile20(join101(options.outDir, MANIFEST_NAME), JSON.stringify(manifest2, null, 2), "utf-8");
@@ -481090,7 +481349,7 @@ var init_message_channel_gateway_tool = __esm(() => {
481090
481349
  });
481091
481350
 
481092
481351
  // src/channels/custom/scaffolding.ts
481093
- import { existsSync as existsSync71, mkdirSync as mkdirSync51, rmSync as rmSync26, writeFileSync as writeFileSync43 } from "node:fs";
481352
+ import { existsSync as existsSync70, mkdirSync as mkdirSync51, rmSync as rmSync26, writeFileSync as writeFileSync43 } from "node:fs";
481094
481353
  function removeUserPlugin(channelId) {
481095
481354
  if (FIRST_PARTY_SET.has(channelId)) {
481096
481355
  return;
@@ -481099,7 +481358,7 @@ function removeUserPlugin(channelId) {
481099
481358
  return;
481100
481359
  }
481101
481360
  const channelDir = getChannelDir(channelId);
481102
- if (!existsSync71(channelDir)) {
481361
+ if (!existsSync70(channelDir)) {
481103
481362
  return;
481104
481363
  }
481105
481364
  try {
@@ -487878,7 +488137,7 @@ var BYTES_PER_TOKEN = 4;
487878
488137
 
487879
488138
  // src/cli/helpers/window-title-config.ts
487880
488139
  import { homedir as homedir55 } from "node:os";
487881
- import { basename as basename31, resolve as resolve42 } from "node:path";
488140
+ import { basename as basename32, resolve as resolve42 } from "node:path";
487882
488141
  function isWindowTitleField(value) {
487883
488142
  return WINDOW_TITLE_FIELDS.includes(value);
487884
488143
  }
@@ -488037,7 +488296,7 @@ function terminalTitleProjectName(data) {
488037
488296
  if (!directory)
488038
488297
  return null;
488039
488298
  const resolved2 = resolve42(directory);
488040
- const name = basename31(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
488299
+ const name = basename32(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
488041
488300
  return truncateTerminalTitlePart(name, 24);
488042
488301
  }
488043
488302
  function titleDirectory(data) {
@@ -488719,7 +488978,7 @@ var init_cli_mod_context = __esm(() => {
488719
488978
 
488720
488979
  // src/cli/helpers/reflection-arena-hf-upload.ts
488721
488980
  import { execFile as execFileCb5 } from "node:child_process";
488722
- import { existsSync as existsSync73 } from "node:fs";
488981
+ import { existsSync as existsSync72 } from "node:fs";
488723
488982
  import { appendFile as appendFile3, chmod, mkdir as mkdir18, writeFile as writeFile21 } from "node:fs/promises";
488724
488983
  import { homedir as homedir56 } from "node:os";
488725
488984
  import { join as join105 } from "node:path";
@@ -488773,7 +489032,7 @@ async function writeGitAskpass(repoRoot) {
488773
489032
  }
488774
489033
  async function prepareHfRepo(env6) {
488775
489034
  await mkdir18(HF_CACHE_ROOT, { recursive: true });
488776
- if (!existsSync73(join105(HF_REPO_DIR, ".git"))) {
489035
+ if (!existsSync72(join105(HF_REPO_DIR, ".git"))) {
488777
489036
  await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env6);
488778
489037
  return HF_REPO_DIR;
488779
489038
  }
@@ -490332,7 +490591,7 @@ __export(exports_terminal_keybinding_installer, {
490332
490591
  });
490333
490592
  import {
490334
490593
  copyFileSync as copyFileSync6,
490335
- existsSync as existsSync74,
490594
+ existsSync as existsSync73,
490336
490595
  mkdirSync as mkdirSync53,
490337
490596
  readFileSync as readFileSync53,
490338
490597
  writeFileSync as writeFileSync45
@@ -490401,7 +490660,7 @@ function parseKeybindings(content) {
490401
490660
  }
490402
490661
  }
490403
490662
  function keybindingExists(keybindingsPath) {
490404
- if (!existsSync74(keybindingsPath))
490663
+ if (!existsSync73(keybindingsPath))
490405
490664
  return false;
490406
490665
  try {
490407
490666
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
@@ -490414,7 +490673,7 @@ function keybindingExists(keybindingsPath) {
490414
490673
  }
490415
490674
  }
490416
490675
  function createBackup(keybindingsPath) {
490417
- if (!existsSync74(keybindingsPath))
490676
+ if (!existsSync73(keybindingsPath))
490418
490677
  return null;
490419
490678
  const backupPath = `${keybindingsPath}.letta-backup`;
490420
490679
  try {
@@ -490430,12 +490689,12 @@ function installKeybinding(keybindingsPath) {
490430
490689
  return { success: true, alreadyExists: true };
490431
490690
  }
490432
490691
  const parentDir = dirname40(keybindingsPath);
490433
- if (!existsSync74(parentDir)) {
490692
+ if (!existsSync73(parentDir)) {
490434
490693
  mkdirSync53(parentDir, { recursive: true });
490435
490694
  }
490436
490695
  let keybindings = [];
490437
490696
  let backupPath = null;
490438
- if (existsSync74(keybindingsPath)) {
490697
+ if (existsSync73(keybindingsPath)) {
490439
490698
  backupPath = createBackup(keybindingsPath);
490440
490699
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
490441
490700
  const parsed = parseKeybindings(content);
@@ -490465,7 +490724,7 @@ function installKeybinding(keybindingsPath) {
490465
490724
  }
490466
490725
  function removeKeybinding(keybindingsPath) {
490467
490726
  try {
490468
- if (!existsSync74(keybindingsPath)) {
490727
+ if (!existsSync73(keybindingsPath)) {
490469
490728
  return { success: true };
490470
490729
  }
490471
490730
  const content = readFileSync53(keybindingsPath, { encoding: "utf-8" });
@@ -490533,11 +490792,11 @@ function getWezTermConfigPath() {
490533
490792
  const xdgConfig = process.env.XDG_CONFIG_HOME;
490534
490793
  if (xdgConfig) {
490535
490794
  const xdgPath = join107(xdgConfig, "wezterm", "wezterm.lua");
490536
- if (existsSync74(xdgPath))
490795
+ if (existsSync73(xdgPath))
490537
490796
  return xdgPath;
490538
490797
  }
490539
490798
  const configPath = join107(homedir58(), ".config", "wezterm", "wezterm.lua");
490540
- if (existsSync74(configPath))
490799
+ if (existsSync73(configPath))
490541
490800
  return configPath;
490542
490801
  return join107(homedir58(), ".wezterm.lua");
490543
490802
  }
@@ -490642,7 +490901,7 @@ ${WEZTERM_DELETE_FIX}
490642
490901
  `;
490643
490902
  }
490644
490903
  function wezTermDeleteFixExists(configPath) {
490645
- if (!existsSync74(configPath))
490904
+ if (!existsSync73(configPath))
490646
490905
  return false;
490647
490906
  try {
490648
490907
  const content = readFileSync53(configPath, { encoding: "utf-8" });
@@ -490659,14 +490918,14 @@ function installWezTermDeleteFix() {
490659
490918
  }
490660
490919
  let content = "";
490661
490920
  let backupPath = null;
490662
- if (existsSync74(configPath)) {
490921
+ if (existsSync73(configPath)) {
490663
490922
  backupPath = `${configPath}.letta-backup`;
490664
490923
  copyFileSync6(configPath, backupPath);
490665
490924
  content = readFileSync53(configPath, { encoding: "utf-8" });
490666
490925
  }
490667
490926
  content = injectWezTermDeleteFix(content);
490668
490927
  const parentDir = dirname40(configPath);
490669
- if (!existsSync74(parentDir)) {
490928
+ if (!existsSync73(parentDir)) {
490670
490929
  mkdirSync53(parentDir, { recursive: true });
490671
490930
  }
490672
490931
  writeFileSync45(configPath, content, { encoding: "utf-8" });
@@ -492663,9 +492922,9 @@ function getHeaderText(fileEdit) {
492663
492922
  const relPath = relative13(cwd2, fileEdit.filePath);
492664
492923
  const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
492665
492924
  if (t2 === "write") {
492666
- const { existsSync: existsSync75 } = __require("node:fs");
492925
+ const { existsSync: existsSync74 } = __require("node:fs");
492667
492926
  try {
492668
- if (existsSync75(fileEdit.filePath)) {
492927
+ if (existsSync74(fileEdit.filePath)) {
492669
492928
  return `Overwrite ${displayPath}?`;
492670
492929
  }
492671
492930
  } catch {}
@@ -501582,9 +501841,9 @@ var init_InputRich = __esm(async () => {
501582
501841
  });
501583
501842
 
501584
501843
  // src/cli/commands/install-github-app.ts
501585
- import { execFileSync as execFileSync10 } from "node:child_process";
501844
+ import { execFileSync as execFileSync12 } from "node:child_process";
501586
501845
  import {
501587
- existsSync as existsSync75,
501846
+ existsSync as existsSync74,
501588
501847
  mkdirSync as mkdirSync54,
501589
501848
  mkdtempSync as mkdtempSync7,
501590
501849
  readFileSync as readFileSync54,
@@ -501595,7 +501854,7 @@ import { tmpdir as tmpdir15 } from "node:os";
501595
501854
  import { dirname as dirname41, join as join109 } from "node:path";
501596
501855
  function runCommand(command, args, cwd2, input) {
501597
501856
  try {
501598
- return execFileSync10(command, args, {
501857
+ return execFileSync12(command, args, {
501599
501858
  cwd: cwd2,
501600
501859
  encoding: "utf8",
501601
501860
  stdio: [input ? "pipe" : "ignore", "pipe", "pipe"],
@@ -501826,12 +502085,12 @@ function runGit7(args, cwd2) {
501826
502085
  }
501827
502086
  function writeWorkflow(repoDir, workflowPath, content) {
501828
502087
  const absolutePath = join109(repoDir, workflowPath);
501829
- if (!existsSync75(dirname41(absolutePath))) {
502088
+ if (!existsSync74(dirname41(absolutePath))) {
501830
502089
  mkdirSync54(dirname41(absolutePath), { recursive: true });
501831
502090
  }
501832
502091
  const next = `${content.trimEnd()}
501833
502092
  `;
501834
- if (existsSync75(absolutePath)) {
502093
+ if (existsSync74(absolutePath)) {
501835
502094
  const previous = readFileSync54(absolutePath, "utf8");
501836
502095
  if (previous === next) {
501837
502096
  return false;
@@ -505721,7 +505980,7 @@ __export(exports_generate_memory_viewer, {
505721
505980
  generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
505722
505981
  });
505723
505982
  import { execFile as execFileCb7 } from "node:child_process";
505724
- import { chmodSync as chmodSync8, existsSync as existsSync76, mkdirSync as mkdirSync55, writeFileSync as writeFileSync47 } from "node:fs";
505983
+ import { chmodSync as chmodSync8, existsSync as existsSync75, mkdirSync as mkdirSync55, writeFileSync as writeFileSync47 } from "node:fs";
505725
505984
  import { homedir as homedir61 } from "node:os";
505726
505985
  import { join as join110 } from "node:path";
505727
505986
  import { promisify as promisify22 } from "node:util";
@@ -506032,7 +506291,7 @@ ${m4.body}` : m4.subject;
506032
506291
  async function generateAndOpenMemoryViewer(agentId, options) {
506033
506292
  const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
506034
506293
  const repoDir = memoryRoot;
506035
- if (!existsSync76(join110(repoDir, ".git"))) {
506294
+ if (!existsSync75(join110(repoDir, ".git"))) {
506036
506295
  throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
506037
506296
  }
506038
506297
  const data = await collectMemoryData(agentId, repoDir, memoryRoot, options?.conversationId);
@@ -506042,7 +506301,7 @@ async function generateAndOpenMemoryViewer(agentId, options) {
506042
506301
  data.context = applyContextUsageSnapshot(data.context, options?.contextUsage);
506043
506302
  const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
506044
506303
  const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
506045
- if (!existsSync76(VIEWERS_DIR)) {
506304
+ if (!existsSync75(VIEWERS_DIR)) {
506046
506305
  mkdirSync55(VIEWERS_DIR, { recursive: true, mode: 448 });
506047
506306
  }
506048
506307
  try {
@@ -506079,7 +506338,7 @@ var init_generate_memory_viewer = __esm(() => {
506079
506338
  });
506080
506339
 
506081
506340
  // src/cli/components/MemfsTreeViewer.tsx
506082
- import { existsSync as existsSync77 } from "node:fs";
506341
+ import { existsSync as existsSync76 } from "node:fs";
506083
506342
  import { join as join111 } from "node:path";
506084
506343
  function renderTreePrefix(node) {
506085
506344
  let prefix = "";
@@ -506108,8 +506367,8 @@ function MemfsTreeViewer({
506108
506367
  const [status, setStatus] = import_react88.useState(null);
506109
506368
  const statusTimerRef = import_react88.useRef(null);
506110
506369
  const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
506111
- const memoryExists = existsSync77(memoryRoot);
506112
- const hasGitRepo = import_react88.useMemo(() => existsSync77(join111(memoryRoot, ".git")), [memoryRoot]);
506370
+ const memoryExists = existsSync76(memoryRoot);
506371
+ const hasGitRepo = import_react88.useMemo(() => existsSync76(join111(memoryRoot, ".git")), [memoryRoot]);
506113
506372
  function showStatus(msg, durationMs) {
506114
506373
  if (statusTimerRef.current)
506115
506374
  clearTimeout(statusTimerRef.current);
@@ -514956,9 +515215,9 @@ function getFileEditHeader(toolName2, toolArgs) {
514956
515215
  const relPath = relative13(cwd2, filePath);
514957
515216
  const displayPath = relPath.startsWith("..") ? filePath : relPath;
514958
515217
  if (t2 === "write") {
514959
- const { existsSync: existsSync78 } = __require("node:fs");
515218
+ const { existsSync: existsSync77 } = __require("node:fs");
514960
515219
  try {
514961
- if (existsSync78(filePath)) {
515220
+ if (existsSync77(filePath)) {
514962
515221
  return `Overwrite ${displayPath}?`;
514963
515222
  }
514964
515223
  } catch {}
@@ -516726,7 +516985,7 @@ __export(exports_generate_diff_viewer, {
516726
516985
  generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
516727
516986
  });
516728
516987
  import { execFile as execFileCb8 } from "node:child_process";
516729
- import { chmodSync as chmodSync9, existsSync as existsSync78, mkdirSync as mkdirSync56, writeFileSync as writeFileSync48 } from "node:fs";
516988
+ import { chmodSync as chmodSync9, existsSync as existsSync77, mkdirSync as mkdirSync56, writeFileSync as writeFileSync48 } from "node:fs";
516730
516989
  import { homedir as homedir63 } from "node:os";
516731
516990
  import { isAbsolute as isAbsolute27, join as join113, resolve as resolve44 } from "node:path";
516732
516991
  import { promisify as promisify23 } from "node:util";
@@ -516951,7 +517210,7 @@ async function generateAndOpenDiffViewer(targetPath) {
516951
517210
  };
516952
517211
  const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
516953
517212
  const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
516954
- if (!existsSync78(VIEWERS_DIR2)) {
517213
+ if (!existsSync77(VIEWERS_DIR2)) {
516955
517214
  mkdirSync56(VIEWERS_DIR2, { recursive: true, mode: 448 });
516956
517215
  }
516957
517216
  try {
@@ -518987,12 +519246,12 @@ __export(exports_shell_aliases, {
518987
519246
  expandAliases: () => expandAliases,
518988
519247
  clearAliasCache: () => clearAliasCache
518989
519248
  });
518990
- import { existsSync as existsSync79, readFileSync as readFileSync55 } from "node:fs";
519249
+ import { existsSync as existsSync78, readFileSync as readFileSync55 } from "node:fs";
518991
519250
  import { homedir as homedir64 } from "node:os";
518992
519251
  import { join as join114 } from "node:path";
518993
519252
  function parseAliasesFromFile(filePath) {
518994
519253
  const aliases = new Map;
518995
- if (!existsSync79(filePath)) {
519254
+ if (!existsSync78(filePath)) {
518996
519255
  return aliases;
518997
519256
  }
518998
519257
  try {
@@ -520207,6 +520466,16 @@ var init_retry2 = __esm(() => {
520207
520466
  function stripSystemReminders2(text3) {
520208
520467
  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();
520209
520468
  }
520469
+ function getRestorableUserText(input) {
520470
+ const message2 = input.find((item) => item?.type === "message");
520471
+ const content = message2 && "content" in message2 ? message2.content : undefined;
520472
+ if (typeof content === "string")
520473
+ return stripSystemReminders2(content);
520474
+ if (!Array.isArray(content))
520475
+ return "";
520476
+ return content.flatMap((c) => c.type === "text" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN) ? [c.text] : []).join(`
520477
+ `).trim();
520478
+ }
520210
520479
  var init_system_reminders2 = __esm(() => {
520211
520480
  init_constants2();
520212
520481
  });
@@ -520739,20 +521008,9 @@ function useConversationLoop(ctx) {
520739
521008
  const agent = await getBackend().retrieveAgent(agentIdRef.current);
520740
521009
  const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend(agent, conversationIdRef.current);
520741
521010
  if (serverApprovals && serverApprovals.length > 0) {
520742
- const userMessage = currentInput.find((item) => item?.type === "message");
520743
- if (userMessage && "content" in userMessage) {
520744
- const content = userMessage.content;
520745
- let textToRestore = "";
520746
- if (typeof content === "string") {
520747
- textToRestore = stripSystemReminders2(content);
520748
- } else if (Array.isArray(content)) {
520749
- 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(`
520750
- `);
520751
- }
520752
- if (textToRestore.trim()) {
520753
- setRestoredInput(textToRestore);
520754
- }
520755
- }
521011
+ const textToRestore = getRestorableUserText(currentInput);
521012
+ if (textToRestore)
521013
+ setRestoredInput(textToRestore);
520756
521014
  setApprovalResults([]);
520757
521015
  setAutoHandledResults([]);
520758
521016
  setAutoDeniedApprovals([]);
@@ -520770,6 +521028,13 @@ function useConversationLoop(ctx) {
520770
521028
  sendDesktopNotification("Approval needed");
520771
521029
  return;
520772
521030
  }
521031
+ const plainInput = rebuildInputWithFreshDenials(currentInput, [], "");
521032
+ if (plainInput.length > 0 && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES3) {
521033
+ llmApiErrorRetriesRef.current += 1;
521034
+ currentInput = plainInput;
521035
+ buffersRef.current.interrupted = false;
521036
+ continue;
521037
+ }
520773
521038
  } catch {}
520774
521039
  }
520775
521040
  }
@@ -521375,20 +521640,9 @@ ${feedback}
521375
521640
  const agent = await getBackend().retrieveAgent(agentIdRef.current);
521376
521641
  const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend(agent, conversationIdRef.current);
521377
521642
  if (serverApprovals && serverApprovals.length > 0) {
521378
- const userMessage = currentInput.find((item) => item?.type === "message");
521379
- if (userMessage && "content" in userMessage) {
521380
- const content = userMessage.content;
521381
- let textToRestore = "";
521382
- if (typeof content === "string") {
521383
- textToRestore = stripSystemReminders2(content);
521384
- } else if (Array.isArray(content)) {
521385
- 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(`
521386
- `);
521387
- }
521388
- if (textToRestore.trim()) {
521389
- setRestoredInput(textToRestore);
521390
- }
521391
- }
521643
+ const textToRestore = getRestorableUserText(currentInput);
521644
+ if (textToRestore)
521645
+ setRestoredInput(textToRestore);
521392
521646
  setApprovalResults([]);
521393
521647
  setAutoHandledResults([]);
521394
521648
  setAutoDeniedApprovals([]);
@@ -521406,6 +521660,13 @@ ${feedback}
521406
521660
  sendDesktopNotification("Approval needed");
521407
521661
  return;
521408
521662
  }
521663
+ const plainInput = rebuildInputWithFreshDenials(currentInput, [], "");
521664
+ if (plainInput.length > 0 && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES3) {
521665
+ llmApiErrorRetriesRef.current += 1;
521666
+ currentInput = plainInput;
521667
+ buffersRef.current.interrupted = false;
521668
+ continue;
521669
+ }
521409
521670
  } catch {}
521410
521671
  }
521411
521672
  const approvalPendingDetected = isApprovalPendingError(detailFromRun) || isApprovalPendingError(latestErrorText);
@@ -521755,7 +522016,6 @@ var init_use_conversation_loop = __esm(async () => {
521755
522016
  init_reflection_transcript();
521756
522017
  init_thinking_messages();
521757
522018
  init_tool_name_mapping2();
521758
- init_constants2();
521759
522019
  init_hooks();
521760
522020
  init_format_denial();
521761
522021
  init_mode();
@@ -527092,7 +527352,7 @@ __export(exports_worktree_diff_list, {
527092
527352
  listWorktreeDiffOptions: () => listWorktreeDiffOptions
527093
527353
  });
527094
527354
  import { execFile as execFileCb9 } from "node:child_process";
527095
- import { basename as basename32 } from "node:path";
527355
+ import { basename as basename33 } from "node:path";
527096
527356
  import { promisify as promisify24 } from "node:util";
527097
527357
  async function runGit9(cwd2, args) {
527098
527358
  try {
@@ -527141,7 +527401,7 @@ function parseWorktreeList(output, currentPath) {
527141
527401
  if (current?.path) {
527142
527402
  worktrees.push({
527143
527403
  path: current.path,
527144
- name: basename32(current.path),
527404
+ name: basename33(current.path),
527145
527405
  branch: current.branch ?? "detached",
527146
527406
  head: current.head ?? "",
527147
527407
  isCurrent: current.path === currentPath,
@@ -527167,7 +527427,7 @@ function parseWorktreeList(output, currentPath) {
527167
527427
  if (current?.path) {
527168
527428
  worktrees.push({
527169
527429
  path: current.path,
527170
- name: basename32(current.path),
527430
+ name: basename33(current.path),
527171
527431
  branch: current.branch ?? "detached",
527172
527432
  head: current.head ?? "",
527173
527433
  isCurrent: current.path === currentPath,
@@ -527324,7 +527584,7 @@ var init_conversation_switch_alert = __esm(() => {
527324
527584
 
527325
527585
  // src/cli/app/use-submit-handler.ts
527326
527586
  import { randomUUID as randomUUID67 } from "node:crypto";
527327
- import { existsSync as existsSync80, readFileSync as readFileSync56, renameSync as renameSync15 } from "node:fs";
527587
+ import { existsSync as existsSync79, readFileSync as readFileSync56, renameSync as renameSync12 } from "node:fs";
527328
527588
  import { tmpdir as tmpdir16 } from "node:os";
527329
527589
  import { join as join115 } from "node:path";
527330
527590
  async function findCustomCommandByName(commandName) {
@@ -527937,7 +528197,7 @@ ${SYSTEM_REMINDER_CLOSE}`),
527937
528197
  join115(memoryRoot, "system", "persona.md"),
527938
528198
  join115(memoryRoot, "memory", "system", "persona.md")
527939
528199
  ];
527940
- const personaPath = personaCandidates.find((candidate) => existsSync80(candidate));
528200
+ const personaPath = personaCandidates.find((candidate) => existsSync79(candidate));
527941
528201
  if (personaPath) {
527942
528202
  const personaContent = readFileSync56(personaPath, "utf-8");
527943
528203
  setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
@@ -528779,12 +529039,12 @@ Path: ${memoryDir}`, true);
528779
529039
  setCommandRunning(true);
528780
529040
  try {
528781
529041
  const memoryDir = getScopedMemoryFilesystemRoot(agentId);
528782
- if (!existsSync80(memoryDir)) {
529042
+ if (!existsSync79(memoryDir)) {
528783
529043
  updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
528784
529044
  return { submitted: true };
528785
529045
  }
528786
529046
  const backupDir = join115(tmpdir16(), `letta-memfs-reset-${agentId}-${Date.now()}`);
528787
- renameSync15(memoryDir, backupDir);
529047
+ renameSync12(memoryDir, backupDir);
528788
529048
  if (getBackend().capabilities.localMemfs) {
528789
529049
  const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
528790
529050
  await initializeLocalMemoryRepo2({
@@ -531737,9 +531997,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
531737
531997
  (async () => {
531738
531998
  try {
531739
531999
  const { watch: watch4 } = await import("node:fs");
531740
- const { existsSync: existsSync81 } = await import("node:fs");
532000
+ const { existsSync: existsSync80 } = await import("node:fs");
531741
532001
  const memRoot = getScopedMemoryFilesystemRoot(agentId);
531742
- if (!existsSync81(memRoot))
532002
+ if (!existsSync80(memRoot))
531743
532003
  return;
531744
532004
  watcher2 = watch4(memRoot, { recursive: true }, () => {});
531745
532005
  memfsWatcherRef.current = watcher2;
@@ -533540,7 +533800,9 @@ async function main() {
533540
533800
  }
533541
533801
  const subcommandResult = await runSubcommand(subcommandArgs);
533542
533802
  if (subcommandResult !== null) {
533543
- process.exit(subcommandResult);
533803
+ process.channel?.unref();
533804
+ process.exitCode = subcommandResult;
533805
+ return;
533544
533806
  }
533545
533807
  await settingsManager.initialize();
533546
533808
  const settings3 = await settingsManager.getSettingsWithSecureTokens();
@@ -537159,4 +537421,4 @@ function registerBunOAuthFlows() {
537159
537421
  registerBunOAuthFlows();
537160
537422
  await init_src5().then(() => exports_src2);
537161
537423
 
537162
- //# debugId=B74D7424006F358464756E2164756E21
537424
+ //# debugId=F0CE6FA9F2A192C264756E2164756E21