@letta-ai/letta-code 0.34.13 → 0.34.14

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 (38) hide show
  1. package/dist/agent-presets.js +1 -1
  2. package/dist/agent-presets.js.map +3 -3
  3. package/dist/mcp-client.js +2 -2
  4. package/dist/mcp-client.js.map +1 -1
  5. package/dist/mcp-oauth.js +41 -13
  6. package/dist/mcp-oauth.js.map +7 -6
  7. package/dist/types/agent/agent-tags.d.ts +4 -0
  8. package/dist/types/agent/agent-tags.d.ts.map +1 -1
  9. package/dist/types/backend/local/local-backend.d.ts +1 -0
  10. package/dist/types/backend/local/local-backend.d.ts.map +1 -1
  11. package/dist/types/backend/local/local-store.d.ts +2 -13
  12. package/dist/types/backend/local/local-store.d.ts.map +1 -1
  13. package/dist/types/backend/local/local-transcript.d.ts +9 -5
  14. package/dist/types/backend/local/local-transcript.d.ts.map +1 -1
  15. package/dist/types/browser-device-mcp-oauth.d.ts +15 -0
  16. package/dist/types/browser-device-mcp-oauth.d.ts.map +1 -1
  17. package/dist/types/cli/subcommands/mcp-connect.d.ts +1 -1
  18. package/dist/types/cli/subcommands/mcp-connect.d.ts.map +1 -1
  19. package/dist/types/cli/subcommands/mcp-io.d.ts.map +1 -1
  20. package/dist/types/cli/subcommands/mcp.d.ts.map +1 -1
  21. package/dist/types/mcp-oauth-callback.d.ts +10 -1
  22. package/dist/types/mcp-oauth-callback.d.ts.map +1 -1
  23. package/dist/types/mcp-oauth-client-name.d.ts +9 -0
  24. package/dist/types/mcp-oauth-client-name.d.ts.map +1 -0
  25. package/dist/types/mcp-oauth-public.d.ts +14 -0
  26. package/dist/types/mcp-oauth-public.d.ts.map +1 -1
  27. package/dist/types/mcp-oauth.d.ts +14 -0
  28. package/dist/types/mcp-oauth.d.ts.map +1 -1
  29. package/dist/types/tools/impl/claude-stream-session.d.ts.map +1 -1
  30. package/dist/types/tools/impl/codex-app-server.d.ts +4 -0
  31. package/dist/types/tools/impl/codex-app-server.d.ts.map +1 -1
  32. package/dist/types/tools/impl/remote-external-coding-agent.d.ts.map +1 -1
  33. package/dist/types/utils/systemd-workload-scope.d.ts.map +1 -1
  34. package/letta.js +268 -86
  35. package/npm-shrinkwrap.json +8 -8
  36. package/package.json +2 -2
  37. package/scripts/source-file-size-baseline.json +1 -1
  38. package/skills/working-across-computers/references/connect-a-computer-for-remote-access.md +26 -3
package/letta.js CHANGED
@@ -5913,7 +5913,7 @@ var package_default;
5913
5913
  var init_package = __esm(() => {
5914
5914
  package_default = {
5915
5915
  name: "@letta-ai/letta-code",
5916
- version: "0.34.13",
5916
+ version: "0.34.14",
5917
5917
  lettaStartupLogProtocol: 1,
5918
5918
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5919
5919
  type: "module",
@@ -6188,7 +6188,7 @@ var init_package = __esm(() => {
6188
6188
  },
6189
6189
  lettaLifecycleProtocol: 1,
6190
6190
  lettaRuntimeGraphProtocol: 1,
6191
- lettaRuntimeGraphSha512: "sha512-e4G3j5ptNvvFrEnNOyxKkZ+xrND+PRBC8uUsUg6KH8ddii955bM5uckdtNUSiGvZARq83+ELyFlMMwh/Ek5UqA=="
6191
+ lettaRuntimeGraphSha512: "sha512-ttHuf5WcGVfNYOggfqOqLRZnllxSSFje3ETZWA/cYFUEoMLz54/CApUxOjoR7xn7X6PbqVnZEzmUQnv+Ic3xzg=="
6192
6192
  };
6193
6193
  });
6194
6194
 
@@ -98826,8 +98826,10 @@ var init_backend_mode = __esm(() => {
98826
98826
  // src/agent/agent-tags.ts
98827
98827
  var exports_agent_tags = {};
98828
98828
  __export(exports_agent_tags, {
98829
+ isMemfsOptOutCreateTags: () => isMemfsOptOutCreateTags,
98829
98830
  buildCreatedAgentTags: () => buildCreatedAgentTags,
98830
98831
  ONBOARDING_ORIGIN_TAG: () => ONBOARDING_ORIGIN_TAG,
98832
+ MEMFS_DISABLED_TAG: () => MEMFS_DISABLED_TAG,
98831
98833
  LETTA_CODE_SUBAGENT_TAG: () => LETTA_CODE_SUBAGENT_TAG,
98832
98834
  LETTA_CODE_ORIGIN_TAG: () => LETTA_CODE_ORIGIN_TAG,
98833
98835
  GIT_MEMORY_ENABLED_TAG: () => GIT_MEMORY_ENABLED_TAG
@@ -98845,7 +98847,10 @@ function buildCreatedAgentTags(options = {}) {
98845
98847
  }
98846
98848
  return Array.from(new Set(tags));
98847
98849
  }
98848
- var LETTA_CODE_ORIGIN_TAG = "origin:letta-code", ONBOARDING_ORIGIN_TAG = "origin:onboarding", LETTA_CODE_SUBAGENT_TAG = "role:subagent", GIT_MEMORY_ENABLED_TAG = "git-memory-enabled";
98850
+ function isMemfsOptOutCreateTags(tags) {
98851
+ return Array.isArray(tags) && tags.includes(MEMFS_DISABLED_TAG);
98852
+ }
98853
+ var LETTA_CODE_ORIGIN_TAG = "origin:letta-code", ONBOARDING_ORIGIN_TAG = "origin:onboarding", LETTA_CODE_SUBAGENT_TAG = "role:subagent", GIT_MEMORY_ENABLED_TAG = "git-memory-enabled", MEMFS_DISABLED_TAG = "memfs:disabled";
98849
98854
 
98850
98855
  // src/utils/directory-limits.ts
98851
98856
  function parsePositiveIntEnv(value, fallback, min, max) {
@@ -110137,15 +110142,46 @@ function readJsonFile2(path8) {
110137
110142
  function readJsonlFile(path8) {
110138
110143
  if (!existsSync14(path8))
110139
110144
  return [];
110140
- return readFileSync8(path8, "utf8").split(`
110141
- `).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
110145
+ const items3 = [];
110146
+ const buffer = Buffer.alloc(64 * 1024);
110147
+ const pending = [];
110148
+ const fd = openSync2(path8, "r");
110149
+ try {
110150
+ let bytesRead = 0;
110151
+ do {
110152
+ bytesRead = readSync(fd, buffer, 0, buffer.length, null);
110153
+ let lineStart = 0;
110154
+ for (let index = 0;index < bytesRead; index += 1) {
110155
+ if (buffer[index] !== 10)
110156
+ continue;
110157
+ const suffix = buffer.subarray(lineStart, index);
110158
+ const line = pending.length ? Buffer.concat([...pending, suffix]) : suffix;
110159
+ pending.length = 0;
110160
+ const text = line.toString("utf8");
110161
+ if (text.trim().length > 0)
110162
+ items3.push(JSON.parse(text));
110163
+ lineStart = index + 1;
110164
+ }
110165
+ if (lineStart < bytesRead) {
110166
+ pending.push(Buffer.from(buffer.subarray(lineStart, bytesRead)));
110167
+ }
110168
+ } while (bytesRead > 0);
110169
+ } finally {
110170
+ closeSync2(fd);
110171
+ }
110172
+ if (pending.length > 0) {
110173
+ const text = Buffer.concat(pending).toString("utf8");
110174
+ if (text.trim().length > 0)
110175
+ items3.push(JSON.parse(text));
110176
+ }
110177
+ return items3;
110142
110178
  }
110143
110179
  function readJsonlFileSuffix(path8, maxBytes) {
110144
110180
  if (!existsSync14(path8))
110145
- return { items: [], reachedStart: true, startOffset: 0 };
110181
+ return { items: [], reachedStart: true, startOffset: 0, bytesRead: 0 };
110146
110182
  const size = statSync3(path8).size;
110147
110183
  if (size === 0)
110148
- return { items: [], reachedStart: true, startOffset: 0 };
110184
+ return { items: [], reachedStart: true, startOffset: 0, bytesRead: 0 };
110149
110185
  const bytesToRead = Math.min(size, Math.max(1, maxBytes));
110150
110186
  const start = size - bytesToRead;
110151
110187
  const buffer = Buffer.alloc(bytesToRead);
@@ -110167,6 +110203,7 @@ function readJsonlFileSuffix(path8, maxBytes) {
110167
110203
  items: text.split(`
110168
110204
  `).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line)),
110169
110205
  reachedStart,
110206
+ bytesRead: bytesToRead,
110170
110207
  startOffset: reachedStart ? 0 : firstNewlineByte >= 0 ? start + firstNewlineByte + 1 : size
110171
110208
  };
110172
110209
  }
@@ -110283,29 +110320,46 @@ function repairSyntheticConversationTimestamps(conversation, messages, timing) {
110283
110320
  function normalizeLocalMessageForPi(message) {
110284
110321
  return message;
110285
110322
  }
110323
+ function localTranscriptTailByteBudget(conversation, agentSettings) {
110324
+ const conversationRecord = isRecord2(conversation) ? conversation : {};
110325
+ const conversationSettings = isRecord2(conversationRecord.model_settings) ? conversationRecord.model_settings : {};
110326
+ const agentSettingsRecord = isRecord2(agentSettings) ? agentSettings : {};
110327
+ const contextWindow = [
110328
+ conversationRecord.context_window_limit,
110329
+ conversationSettings.context_window_limit,
110330
+ agentSettingsRecord.context_window_limit
110331
+ ].find((value) => typeof value === "number" && Number.isFinite(value) && value > 0);
110332
+ return (contextWindow ?? LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT) * LOCAL_TRANSCRIPT_BYTES_PER_CONTEXT_TOKEN;
110333
+ }
110286
110334
  function localTranscriptTailMessages(rows, messageFormat, activeMessageIds, storageDir, conversationDir) {
110287
110335
  const transcript2 = localTranscriptRowsResult(rows, messageFormat, activeMessageIds);
110288
110336
  assertNoLegacyUiMessageRows(transcript2.messages, storageDir, conversationDir);
110289
110337
  const messages = removeOrphanLocalToolResults(transcript2.messages.map(normalizeLocalMessageForPi)).messages;
110290
110338
  return { transcript: transcript2, messages };
110291
110339
  }
110292
- function readLocalTranscriptTailWindow(messagesPath, messageFormat, activeMessageIds, minMessages, storageDir, conversationDir) {
110340
+ function readLocalTranscriptTailWindow(messagesPath, messageFormat, activeMessageIds, minMessages, storageDir, conversationDir, maxTailBytes = LOCAL_TRANSCRIPT_TAIL_MAX_BYTES) {
110293
110341
  const targetCount = activeMessageIds.length > 0 ? activeMessageIds.length : minMessages;
110342
+ const byteBudget = Math.max(64 * 1024, Math.floor(maxTailBytes));
110294
110343
  let maxBytes = 64 * 1024;
110295
110344
  for (;; ) {
110296
110345
  const tail = readJsonlFileSuffix(messagesPath, maxBytes);
110297
- const result = localTranscriptTailMessages(tail.items, messageFormat, activeMessageIds, storageDir, conversationDir);
110346
+ let result = localTranscriptTailMessages(tail.items, messageFormat, activeMessageIds, storageDir, conversationDir);
110298
110347
  const found = result.transcript.messages.length;
110299
- if (found >= targetCount || tail.reachedStart) {
110348
+ if (found >= targetCount || tail.reachedStart || maxBytes >= byteBudget) {
110349
+ if (activeMessageIds.length === 0 && result.messages.length > minMessages) {
110350
+ const inferredIds = result.messages.slice(-minMessages).map((message) => message.id);
110351
+ result = localTranscriptTailMessages(tail.items, messageFormat, inferredIds, storageDir, conversationDir);
110352
+ }
110300
110353
  const returnedIds = new Set(result.messages.map((message) => message.id));
110301
110354
  return {
110302
110355
  ...result,
110303
110356
  reachedStart: tail.reachedStart,
110357
+ bytesRead: tail.bytesRead,
110304
110358
  headBytes: tail.startOffset,
110305
- liveInContextIds: activeMessageIds.filter((id2) => returnedIds.has(id2))
110359
+ liveInContextIds: activeMessageIds.length > 0 ? activeMessageIds.filter((id2) => returnedIds.has(id2)) : result.messages.map((message) => message.id)
110306
110360
  };
110307
110361
  }
110308
- maxBytes = Math.max(maxBytes * 2, found > 0 ? Math.ceil(maxBytes / found * targetCount * 1.25) : 0);
110362
+ maxBytes = Math.min(byteBudget, Math.max(maxBytes * 2, found > 0 ? Math.ceil(maxBytes / found * targetCount * 1.25) : 0));
110309
110363
  }
110310
110364
  }
110311
110365
  function spliceOutOfContextMessages(messages, inContextIds, floor) {
@@ -110434,8 +110488,9 @@ function overlayResidentLocalMessageSuffix(diskSuffix, residentTail, isPersisted
110434
110488
  }
110435
110489
  return overlayResidentLocalMessageTail(diskSuffix, overlayTail);
110436
110490
  }
110437
- var LOCAL_TRANSCRIPT_LEGACY_SCHEMA_VERSION = 1, LOCAL_TRANSCRIPT_SCHEMA_VERSION = 2, LOCAL_TRANSCRIPT_LEGACY_MESSAGE_FORMAT = "pi-ai-message-jsonl", LOCAL_TRANSCRIPT_MESSAGE_FORMAT = "pi-session-entry-jsonl", LOCAL_TRANSCRIPT_PROVIDER_STACK = "pi-ai", LocalTranscriptMigrationRequiredError, LocalTranscriptRepairRequiredError;
110491
+ var LOCAL_TRANSCRIPT_LEGACY_SCHEMA_VERSION = 1, LOCAL_TRANSCRIPT_SCHEMA_VERSION = 2, LOCAL_TRANSCRIPT_LEGACY_MESSAGE_FORMAT = "pi-ai-message-jsonl", LOCAL_TRANSCRIPT_MESSAGE_FORMAT = "pi-session-entry-jsonl", LOCAL_TRANSCRIPT_PROVIDER_STACK = "pi-ai", LOCAL_TRANSCRIPT_TAIL_MAX_BYTES, LOCAL_TRANSCRIPT_BYTES_PER_CONTEXT_TOKEN = 8, LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT = 128000, LocalTranscriptMigrationRequiredError, LocalTranscriptRepairRequiredError;
110438
110492
  var init_local_transcript = __esm(() => {
110493
+ LOCAL_TRANSCRIPT_TAIL_MAX_BYTES = 16 * 1024 * 1024;
110439
110494
  LocalTranscriptMigrationRequiredError = class LocalTranscriptMigrationRequiredError extends Error {
110440
110495
  constructor(storageDir) {
110441
110496
  const command = localTranscriptMigrationCommand(storageDir);
@@ -110808,7 +110863,7 @@ class LocalStore {
110808
110863
  return record4;
110809
110864
  const contextWindowLimit = record4.model_settings.context_window_limit;
110810
110865
  const defaultContextWindowLimit = defaults4.context_window_limit;
110811
- const shouldReplaceLegacyContextWindow = contextWindowLimit === LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT && typeof defaultContextWindowLimit === "number" && defaultContextWindowLimit > LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT;
110866
+ const shouldReplaceLegacyContextWindow = contextWindowLimit === LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT2 && typeof defaultContextWindowLimit === "number" && defaultContextWindowLimit > LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT2;
110812
110867
  return {
110813
110868
  ...record4,
110814
110869
  model_settings: {
@@ -111746,12 +111801,13 @@ class LocalStore {
111746
111801
  return;
111747
111802
  }
111748
111803
  const conversation = this.conversations.get(key);
111804
+ const activeMessageIds = conversation?.in_context_message_ids ?? [];
111749
111805
  const {
111750
111806
  transcript: transcript2,
111751
111807
  messages: tailMessages,
111752
111808
  headBytes,
111753
111809
  liveInContextIds
111754
- } = readLocalTranscriptTailWindow(metadata.messagesPath, metadata.messageFormat, conversation?.in_context_message_ids ?? [], this.residentMessageTailLimit, this.storageDir ?? "", metadata.conversationDir);
111810
+ } = readLocalTranscriptTailWindow(metadata.messagesPath, metadata.messageFormat, activeMessageIds, this.residentMessageTailLimit, this.storageDir ?? "", metadata.conversationDir, localTranscriptTailByteBudget(conversation, this.agents.get(agentId)?.model_settings));
111755
111811
  const toolResultClip = clipOversizedLocalToolResults(tailMessages);
111756
111812
  const messages = toolResultClip.messages;
111757
111813
  if (toolResultClip.clippedToolResultIds.length > 0) {
@@ -111760,8 +111816,9 @@ class LocalStore {
111760
111816
  this.localMessagesByConversationKey.set(key, messages);
111761
111817
  if (conversation)
111762
111818
  conversation.in_context_message_ids = liveInContextIds;
111819
+ const head = activeMessageIds.length === 0 ? -headBytes : headBytes;
111763
111820
  if (headBytes > 0)
111764
- this.unreadTranscriptHeadBytesByKey.set(key, headBytes);
111821
+ this.unreadTranscriptHeadBytesByKey.set(key, head);
111765
111822
  else
111766
111823
  this.unreadTranscriptHeadBytesByKey.delete(key);
111767
111824
  this.loadedConversationKeys.delete(key);
@@ -111836,12 +111893,13 @@ class LocalStore {
111836
111893
  });
111837
111894
  }
111838
111895
  validateUnreadTranscriptHeadOnce(key) {
111839
- const headBytes = this.unreadTranscriptHeadBytesByKey.get(key);
111840
- if (headBytes === undefined)
111896
+ const storedHeadBytes = this.unreadTranscriptHeadBytesByKey.get(key);
111897
+ if (storedHeadBytes === undefined)
111841
111898
  return;
111899
+ const headBytes = Math.abs(storedHeadBytes);
111842
111900
  const metadata = this.transcriptMetadataByConversationKey.get(key);
111843
111901
  if (metadata) {
111844
- validateUnreadTranscriptHead(metadata.messagesPath, headBytes, this.storageDir ?? "", metadata.conversationDir, this.conversations.get(key)?.in_context_message_ids ?? []);
111902
+ validateUnreadTranscriptHead(metadata.messagesPath, headBytes, this.storageDir ?? "", metadata.conversationDir, storedHeadBytes < 0 ? [] : this.conversations.get(key)?.in_context_message_ids ?? []);
111845
111903
  }
111846
111904
  this.unreadTranscriptHeadBytesByKey.delete(key);
111847
111905
  }
@@ -112434,7 +112492,7 @@ class LocalStore {
112434
112492
  return conversationId === "default" ? `default:${agentId}` : `conversation:${conversationId}`;
112435
112493
  }
112436
112494
  }
112437
- var DEFAULT_LOCAL_AGENT_NAME = "Letta Code", DEFAULT_LOCAL_MODEL = "local/default", LEGACY_LOCAL_CONTEXT_WINDOW_LIMIT = 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;
112495
+ 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;
112438
112496
  var init_local_store = __esm(() => {
112439
112497
  init_constants2();
112440
112498
  init_local_agent_record();
@@ -118372,6 +118430,7 @@ var init_local_backend = __esm(() => {
118372
118430
  init_memory_git();
118373
118431
  init_headless_backend();
118374
118432
  init_pi_models_runtime();
118433
+ init_settings_manager();
118375
118434
  init_compaction();
118376
118435
  init_initial_memory();
118377
118436
  init_local_executor_factory();
@@ -118472,7 +118531,8 @@ var init_local_backend = __esm(() => {
118472
118531
  }
118473
118532
  async createAgent(...args) {
118474
118533
  let [body, ...restArgs] = args;
118475
- if (this.isLocalMemfsEnabled()) {
118534
+ const memfsExplicitlyDisabled = isMemfsOptOutCreateTags(body.tags);
118535
+ if (this.isLocalMemfsEnabled() && !memfsExplicitlyDisabled) {
118476
118536
  body = stampRootMemoryOnCreateBody(body);
118477
118537
  const bodyRecord = body;
118478
118538
  const existingTags = Array.isArray(bodyRecord.tags) ? bodyRecord.tags : [];
@@ -118489,10 +118549,13 @@ var init_local_backend = __esm(() => {
118489
118549
  }
118490
118550
  const compactionSettingsForStorage = localCompactionSettingsForStorage(requestedCompactionSettings);
118491
118551
  let agent = await super.createAgent(body, ...restArgs);
118552
+ if (memfsExplicitlyDisabled) {
118553
+ settingsManager.setMemfsEnabled(agent.id, false);
118554
+ }
118492
118555
  if (compactionSettingsForStorage !== undefined) {
118493
118556
  agent = this.store.setAgentCompactionSettings(agent.id, compactionSettingsForStorage);
118494
118557
  }
118495
- if (this.isLocalMemfsEnabled()) {
118558
+ if (this.isMemfsEnabledForAgent(agent.id)) {
118496
118559
  await this.ensureLocalMemoryRepo(agent.id, initialMemoryFilesFromCreateBody(body), agent.name ?? undefined);
118497
118560
  }
118498
118561
  await this.compileAndMaybePersistSystemPrompt("default", agent.id, {
@@ -118560,6 +118623,10 @@ var init_local_backend = __esm(() => {
118560
118623
  isLocalMemfsEnabled() {
118561
118624
  return this.memfsEnabledOverride ?? !isLocalBackendMemfsDisabledForProcess();
118562
118625
  }
118626
+ isMemfsEnabledForAgent(agentId) {
118627
+ const { tags } = this.store.retrieveAgentRecord(agentId);
118628
+ return this.isLocalMemfsEnabled() && !isMemfsOptOutCreateTags(tags);
118629
+ }
118563
118630
  async ensureLocalMemoryRepo(agentId, files = [], authorName) {
118564
118631
  await initializeLocalMemoryRepo({
118565
118632
  memoryDir: this.memoryDirForAgent(agentId),
@@ -118752,7 +118819,7 @@ var init_local_backend = __esm(() => {
118752
118819
  async getOrCompileSystemPrompt(conversationId, agentId, agent = this.store.retrieveAgentRecord(agentId), previousMessageCount = 0) {
118753
118820
  const existing = this.store.getCompiledSystemPrompt(conversationId, agentId);
118754
118821
  const rawSystemHash = hashRawSystemPrompt(agent.system);
118755
- const memfsRevision = this.isLocalMemfsEnabled() ? getCommittedMemfsRevision(this.memoryDirForAgent(agentId)) : undefined;
118822
+ const memfsRevision = this.isMemfsEnabledForAgent(agentId) ? getCommittedMemfsRevision(this.memoryDirForAgent(agentId)) : undefined;
118756
118823
  if (existing?.rawSystemHash === rawSystemHash && existing.memfsRevision === memfsRevision) {
118757
118824
  return existing;
118758
118825
  }
@@ -118780,7 +118847,7 @@ var init_local_backend = __esm(() => {
118780
118847
  }
118781
118848
  async compileAndMaybePersistSystemPrompt(conversationId, agentId, options) {
118782
118849
  const agent = this.store.retrieveAgentRecord(agentId);
118783
- const memfsEnabled = this.isLocalMemfsEnabled();
118850
+ const memfsEnabled = this.isMemfsEnabledForAgent(agentId);
118784
118851
  if (memfsEnabled) {
118785
118852
  await this.ensureLocalMemoryRepo(agentId, [], agent.name);
118786
118853
  }
@@ -210764,7 +210831,7 @@ var init_mcp_client = __esm(() => {
210764
210831
  init_streamableHttp();
210765
210832
  DEFAULT_CLIENT_INFO = {
210766
210833
  name: "letta-code",
210767
- version: "0.34.13"
210834
+ version: "0.34.14"
210768
210835
  };
210769
210836
  });
210770
210837
 
@@ -210795,17 +210862,17 @@ async function startOAuthCallbackServerOnPort(port) {
210795
210862
  let completed = false;
210796
210863
  let settle;
210797
210864
  let reject2;
210798
- const codePromise = new Promise((resolve13, rejectPromise) => {
210799
- settle = (code2) => {
210865
+ const callbackPromise = new Promise((resolve13, rejectPromise) => {
210866
+ settle = (result2) => {
210800
210867
  completed = true;
210801
- resolve13(code2);
210868
+ resolve13(result2);
210802
210869
  };
210803
210870
  reject2 = (error5) => {
210804
210871
  completed = true;
210805
210872
  rejectPromise(error5);
210806
210873
  };
210807
210874
  });
210808
- codePromise.catch(() => {
210875
+ callbackPromise.catch(() => {
210809
210876
  return;
210810
210877
  });
210811
210878
  server2 = createServer4((request, response) => {
@@ -210836,6 +210903,7 @@ async function startOAuthCallbackServerOnPort(port) {
210836
210903
  const error5 = url2.searchParams.get("error");
210837
210904
  const code2 = url2.searchParams.get("code");
210838
210905
  const state2 = url2.searchParams.get("state");
210906
+ const domain = url2.searchParams.get("domain");
210839
210907
  if (!state2 || state2 !== expectedState.value) {
210840
210908
  response.writeHead(400, { "Content-Type": "text/html" });
210841
210909
  response.end(callbackPage("Authorization failed", "Invalid OAuth callback"));
@@ -210855,7 +210923,7 @@ async function startOAuthCallbackServerOnPort(port) {
210855
210923
  return;
210856
210924
  }
210857
210925
  response.writeHead(200, { "Content-Type": "text/html" });
210858
- settle?.(code2);
210926
+ settle?.(domain ? { code: code2, domain } : { code: code2 });
210859
210927
  response.end(callbackPage("Authorization complete", "You can close this tab and return to Letta Code."), () => {
210860
210928
  closeServer2(true);
210861
210929
  });
@@ -210896,7 +210964,7 @@ Content-Length: 0\r
210896
210964
  return {
210897
210965
  redirectUrl: `http://127.0.0.1:${address.port}/callback`,
210898
210966
  expectedState,
210899
- waitForCode: () => codePromise.finally(() => clearTimeout(timeout)),
210967
+ waitForCallback: () => callbackPromise.finally(() => clearTimeout(timeout)),
210900
210968
  close: () => {
210901
210969
  clearTimeout(timeout);
210902
210970
  if (!completed)
@@ -210925,6 +210993,20 @@ var init_mcp_oauth_callback = __esm(() => {
210925
210993
  CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
210926
210994
  });
210927
210995
 
210996
+ // src/mcp-oauth-client-name.ts
210997
+ function resolveMcpOAuthClientName(clientName) {
210998
+ if (clientName === undefined)
210999
+ return DEFAULT_MCP_OAUTH_CLIENT_NAME;
211000
+ const trimmed = clientName.trim();
211001
+ if (!trimmed)
211002
+ throw new Error("MCP OAuth client name must not be empty");
211003
+ if (trimmed.length > MAX_MCP_OAUTH_CLIENT_NAME_LENGTH) {
211004
+ throw new Error(`MCP OAuth client name must be at most ${MAX_MCP_OAUTH_CLIENT_NAME_LENGTH} characters`);
211005
+ }
211006
+ return trimmed;
211007
+ }
211008
+ var DEFAULT_MCP_OAUTH_CLIENT_NAME = "Letta Code", MAX_MCP_OAUTH_CLIENT_NAME_LENGTH = 64;
211009
+
210928
211010
  // src/mcp-oauth-identity.ts
210929
211011
  import { createHash as createHash4 } from "node:crypto";
210930
211012
  function mcpOAuthCredentialKey(agentId, serverName, serverUrl) {
@@ -210999,10 +211081,12 @@ async function createMcpOAuthSession(agentId, serverName, serverUrl, options) {
210999
211081
  storage: bunSecretStorage,
211000
211082
  interactive: options.interactive,
211001
211083
  onStatus: options.onStatus,
211002
- openBrowser: options.openBrowser ?? openSystemBrowser
211084
+ openBrowser: options.openBrowser ?? openSystemBrowser,
211085
+ clientName: options.clientName
211003
211086
  });
211004
211087
  }
211005
211088
  async function createMcpOAuthSessionWithStorage(options) {
211089
+ const clientName = resolveMcpOAuthClientName(options.clientName);
211006
211090
  const coordinationKey = storageCoordinationKey(options.storage, options.credentialKey, options.storageNamespace);
211007
211091
  retainCredentialCoordinator(coordinationKey);
211008
211092
  let provider;
@@ -211030,13 +211114,20 @@ async function createMcpOAuthSessionWithStorage(options) {
211030
211114
  onStatus: options.onStatus,
211031
211115
  openBrowser: options.openBrowser ?? openSystemBrowser,
211032
211116
  expectedState: callback?.expectedState,
211033
- generation: loaded.generation
211117
+ generation: loaded.generation,
211118
+ clientName
211034
211119
  });
211035
211120
  const activeProvider = provider;
211036
211121
  const activeCallback = callback;
211037
211122
  return {
211038
211123
  authProvider: activeProvider,
211039
- ...activeCallback ? { waitForAuthorizationCode: () => activeCallback.waitForCode() } : {},
211124
+ ...activeCallback ? {
211125
+ waitForAuthorizationCode: async () => {
211126
+ const { code: code2, domain } = await activeCallback.waitForCallback();
211127
+ options.onAuthorizationCallback?.({ domain });
211128
+ return code2;
211129
+ }
211130
+ } : {},
211040
211131
  exportCredentials: () => activeProvider.exportCredentials(),
211041
211132
  closeCallback: async () => activeCallback?.close(),
211042
211133
  close: async () => {
@@ -211073,6 +211164,7 @@ class PersistentMcpOAuthProvider {
211073
211164
  onStatus;
211074
211165
  openBrowser;
211075
211166
  expectedState;
211167
+ clientName;
211076
211168
  closed = false;
211077
211169
  constructor(options) {
211078
211170
  this.credentialKey = options.credentialKey;
@@ -211082,6 +211174,7 @@ class PersistentMcpOAuthProvider {
211082
211174
  this.onStatus = options.onStatus;
211083
211175
  this.openBrowser = options.openBrowser;
211084
211176
  this.expectedState = options.expectedState;
211177
+ this.clientName = options.clientName;
211085
211178
  this.generation = options.generation;
211086
211179
  const coordinator = getCredentialCoordinator(options.coordinationKey);
211087
211180
  this.coordinatorValue = coordinator;
@@ -211101,7 +211194,7 @@ class PersistentMcpOAuthProvider {
211101
211194
  }
211102
211195
  get clientMetadata() {
211103
211196
  return {
211104
- client_name: "Letta Code",
211197
+ client_name: this.clientName,
211105
211198
  redirect_uris: [this.redirectUrl],
211106
211199
  grant_types: ["authorization_code", "refresh_token"],
211107
211200
  response_types: ["code"],
@@ -211596,7 +211689,7 @@ async function authorizeMcpServerWithStorage(options) {
211596
211689
  throw new Error("MCP OAuth storage namespace must be non-empty and contain no NUL bytes");
211597
211690
  }
211598
211691
  const credentialKey = mcpOAuthCredentialKey(options.agentId, options.serverName, options.serverUrl);
211599
- const flightKey = `${options.storageNamespace}\x00${credentialKey}\x00${fetchIdentity(options.fetch)}`;
211692
+ const flightKey = `${options.storageNamespace}\x00${credentialKey}\x00${fetchIdentity(options.fetch)}\x00${options.clientName ?? ""}`;
211600
211693
  let flight = inFlightAuthorizations.get(flightKey);
211601
211694
  if (!flight) {
211602
211695
  const controller = new AbortController;
@@ -211626,7 +211719,9 @@ async function runAuthorization(options, credentialKey, signal) {
211626
211719
  storage,
211627
211720
  interactive: true,
211628
211721
  openBrowser: options.openBrowser,
211629
- onStatus: options.onStatus
211722
+ onStatus: options.onStatus,
211723
+ onAuthorizationCallback: options.onAuthorizationCallback,
211724
+ clientName: options.clientName
211630
211725
  });
211631
211726
  let oauth;
211632
211727
  try {
@@ -211763,11 +211858,18 @@ async function connectBrowserDeviceMcpOAuth(request, dependencies4 = {
211763
211858
  try {
211764
211859
  const credentials = await dependencies4.authorize({
211765
211860
  agentId: handoffNamespace(request.handoffKey),
211861
+ clientName: request.clientName,
211766
211862
  openBrowser: async (value) => {
211767
211863
  const url2 = allowedAuthorizationUrl(value, definition.authorizationOrigins);
211768
211864
  await dependencies4.openBrowser(url2.href);
211769
211865
  },
211770
211866
  fetch: createProviderFetch(definition, dependencies4.providerFetch ?? globalThis.fetch),
211867
+ onAuthorizationCallback: ({ domain }) => {
211868
+ const reported = definitionForCallbackDomain(request.service, domain);
211869
+ if (reported?.site && reported !== definition) {
211870
+ throw new BrowserDeviceMcpOAuthSiteMismatchError(reported.site, reported.serverUrl);
211871
+ }
211872
+ },
211771
211873
  serverName: definition.serverName,
211772
211874
  serverUrl: definition.serverUrl,
211773
211875
  signal: authorizationSignal,
@@ -211852,6 +211954,13 @@ function findDefinition(service, normalizedServerUrl) {
211852
211954
  }
211853
211955
  return BROWSER_DEVICE_MCP_OAUTH_SERVICES[service]?.find((candidate) => normalizeServerUrl(candidate.serverUrl) === normalizedServerUrl);
211854
211956
  }
211957
+ function definitionForCallbackDomain(service, domain) {
211958
+ if (!domain || !Object.hasOwn(BROWSER_DEVICE_MCP_OAUTH_SERVICES, service)) {
211959
+ return;
211960
+ }
211961
+ const site = domain.trim().toLowerCase().replace(/^https:\/\//, "").replace(/\/+$/, "").replace(/^(?:app|api)\./, "");
211962
+ return BROWSER_DEVICE_MCP_OAUTH_SERVICES[service]?.find((candidate) => candidate.site !== undefined && candidate.site === site);
211963
+ }
211855
211964
  function browserDeviceMcpOAuthServerUrls() {
211856
211965
  return Object.fromEntries(Object.entries(BROWSER_DEVICE_MCP_OAUTH_SERVICES).map(([service, definitions]) => [
211857
211966
  service,
@@ -212004,7 +212113,8 @@ function datadogDefinition(mcpHost, appHost) {
212004
212113
  return {
212005
212114
  authorizationOrigins: [`https://${appHost}`],
212006
212115
  serverName: "Datadog",
212007
- serverUrl: `https://mcp.${mcpHost}/v1/mcp`
212116
+ serverUrl: `https://mcp.${mcpHost}/v1/mcp`,
212117
+ site: mcpHost
212008
212118
  };
212009
212119
  }
212010
212120
  function handoffNamespace(handoffKey) {
@@ -212018,7 +212128,7 @@ async function openSystemBrowser2(url2) {
212018
212128
  return;
212019
212129
  });
212020
212130
  }
212021
- var HANDOFF_KEY_PATTERN, BROWSER_DEVICE_HANDOFF_SUBMIT_TIMEOUT_MS = 90000, HANDOFF_ATTEMPT_TIMEOUT_MS = 1e4, PROVIDER_AUTHORIZATION_TIMEOUT_MS = 190000, HANDOFF_RETRY_BASE_DELAY_MS = 1000, HANDOFF_RETRY_MAX_DELAY_MS = 1e4, HANDOFF_RETRY_AFTER_MAX_DELAY_MS = 60000, BROWSER_DEVICE_MCP_OAUTH_SERVICES, BrowserDeviceMcpOAuthRequestError;
212131
+ var HANDOFF_KEY_PATTERN, BROWSER_DEVICE_HANDOFF_SUBMIT_TIMEOUT_MS = 90000, HANDOFF_ATTEMPT_TIMEOUT_MS = 1e4, PROVIDER_AUTHORIZATION_TIMEOUT_MS = 190000, HANDOFF_RETRY_BASE_DELAY_MS = 1000, HANDOFF_RETRY_MAX_DELAY_MS = 1e4, HANDOFF_RETRY_AFTER_MAX_DELAY_MS = 60000, BROWSER_DEVICE_MCP_OAUTH_SERVICES, BrowserDeviceMcpOAuthRequestError, BrowserDeviceMcpOAuthSiteMismatchError;
212022
212132
  var init_browser_device_mcp_oauth = __esm(() => {
212023
212133
  init_oauth();
212024
212134
  init_request();
@@ -212048,6 +212158,16 @@ var init_browser_device_mcp_oauth = __esm(() => {
212048
212158
  this.name = "BrowserDeviceMcpOAuthRequestError";
212049
212159
  }
212050
212160
  };
212161
+ BrowserDeviceMcpOAuthSiteMismatchError = class BrowserDeviceMcpOAuthSiteMismatchError extends Error {
212162
+ site;
212163
+ serverUrl;
212164
+ constructor(site, serverUrl) {
212165
+ super(`OAuth provider authorized on ${site}; use ${serverUrl}`);
212166
+ this.site = site;
212167
+ this.serverUrl = serverUrl;
212168
+ this.name = "BrowserDeviceMcpOAuthSiteMismatchError";
212169
+ }
212170
+ };
212051
212171
  });
212052
212172
 
212053
212173
  // src/websocket/listener/commands/browser-device-mcp-oauth.ts
@@ -218150,6 +218270,7 @@ function wrapManagedWorkloadLauncher(launcher, options = {}) {
218150
218270
  "--quiet",
218151
218271
  "--collect",
218152
218272
  "--property=TimeoutStopSec=5s",
218273
+ "--property=OOMPolicy=continue",
218153
218274
  `--slice=${slice2}`,
218154
218275
  "--",
218155
218276
  ...launcher
@@ -239425,9 +239546,7 @@ function buildClaudeStreamArgs(options) {
239425
239546
  "stream-json",
239426
239547
  "--include-partial-messages",
239427
239548
  "--permission-mode",
239428
- "acceptEdits",
239429
- "--allowed-tools",
239430
- "Bash,Edit,Write,Read,Glob,Grep,WebFetch,WebSearch"
239549
+ "bypassPermissions"
239431
239550
  ];
239432
239551
  if (options.model)
239433
239552
  args.push("--model", options.model);
@@ -239625,7 +239744,8 @@ async function launchSession(options, deps) {
239625
239744
  const env6 = {
239626
239745
  ...deps.env ?? process.env,
239627
239746
  AGENT_ID: options.parentAgentId,
239628
- LETTA_AGENT_ID: options.parentAgentId
239747
+ LETTA_AGENT_ID: options.parentAgentId,
239748
+ IS_SANDBOX: "1"
239629
239749
  };
239630
239750
  const abortController = new AbortController;
239631
239751
  const abortFromUpstream = () => abortController.abort(options.signal?.reason ?? "Claude Code turn cancelled");
@@ -239707,7 +239827,8 @@ async function launchSession(options, deps) {
239707
239827
  return;
239708
239828
  const detail = session3.stderr.trim();
239709
239829
  const protocolDetail = session3.protocolError ? `; protocol error: ${session3.protocolError}` : "";
239710
- const error5 = transport3.wasAborted() ? abortController.signal.reason ?? "Claude Code turn cancelled" : `Claude Code exited before a final result with ${exitCode ?? exitSignal ?? "unknown status"}${detail ? `: ${detail}` : ""}${protocolDetail}`;
239830
+ const oomDetail = exitCode === 143 || exitSignal === "SIGTERM" || exitSignal === "SIGKILL" ? "; possibly out of memory" : "";
239831
+ const error5 = transport3.wasAborted() ? abortController.signal.reason ?? "Claude Code turn cancelled" : `Claude Code exited before a final result with ${exitCode ?? exitSignal ?? "unknown status"}${oomDetail}${detail ? `: ${detail}` : ""}${protocolDetail}`;
239711
239832
  rejectControls(session3, new Error(errorMessage(error5)));
239712
239833
  settle(session3, failResult(session3, error5));
239713
239834
  }).catch((error5) => {
@@ -239860,7 +239981,10 @@ function spawnTransport(options) {
239860
239981
  stdin: child.stdin,
239861
239982
  stdout: child.stdout,
239862
239983
  stderr: child.stderr,
239863
- kill: () => child.kill()
239984
+ kill: () => child.kill(),
239985
+ exited: new Promise((resolve35) => {
239986
+ child.once("close", (code2, signal) => resolve35({ code: code2, signal }));
239987
+ })
239864
239988
  };
239865
239989
  }
239866
239990
  function asRecord9(value) {
@@ -239900,6 +240024,7 @@ class CodexAppServerClient {
239900
240024
  this.onNotification = onNotification;
239901
240025
  this.onClose = onClose;
239902
240026
  const stdout = createInterface9({ input: transport3.stdout });
240027
+ stdout.once("error", () => void this.close());
239903
240028
  stdout.on("line", (line) => {
239904
240029
  if (!line.trim())
239905
240030
  return;
@@ -239928,7 +240053,7 @@ class CodexAppServerClient {
239928
240053
  transport3.stderr?.on("data", (chunk2) => {
239929
240054
  this.stderr += chunk2;
239930
240055
  });
239931
- const close = () => this.close();
240056
+ const close = () => void this.close();
239932
240057
  transport3.stdout.once("close", close);
239933
240058
  transport3.stdout.once("error", close);
239934
240059
  }
@@ -239936,7 +240061,7 @@ class CodexAppServerClient {
239936
240061
  await this.request("initialize", {
239937
240062
  clientInfo: {
239938
240063
  name: "letta-code",
239939
- version: "0.34.13"
240064
+ version: "0.34.14"
239940
240065
  },
239941
240066
  capabilities: null
239942
240067
  });
@@ -239967,12 +240092,20 @@ class CodexAppServerClient {
239967
240092
  this.transport.kill?.();
239968
240093
  this.close();
239969
240094
  }
239970
- close() {
240095
+ async close() {
239971
240096
  if (this.closed)
239972
240097
  return;
239973
240098
  this.closed = true;
239974
- const detail = this.stderr.trim();
239975
- const error5 = new Error(`Codex app-server closed${detail ? `: ${detail}` : ""}`);
240099
+ let exitTimeout;
240100
+ const exit = this.transport.exited ? await Promise.race([
240101
+ this.transport.exited,
240102
+ new Promise((resolve35) => {
240103
+ exitTimeout = setTimeout(() => resolve35(undefined), 2000);
240104
+ })
240105
+ ]).finally(() => clearTimeout(exitTimeout)) : undefined;
240106
+ const detail = this.stderr.trim().slice(-300);
240107
+ const exitDetail = exit?.signal ? ` (signal ${exit.signal}${exit.signal === "SIGKILL" || exit.signal === "SIGTERM" ? "; possibly out of memory" : ""})` : exit?.code != null ? ` (exit code ${exit.code}${exit.code === 143 ? "; possibly out of memory" : ""})` : "";
240108
+ const error5 = new Error(`Codex app-server closed${exitDetail}${detail ? `: ${detail}` : ""}`);
239976
240109
  for (const pending2 of this.pending.values())
239977
240110
  pending2.reject(error5);
239978
240111
  this.pending.clear();
@@ -240164,7 +240297,7 @@ async function createSession(options, deps) {
240164
240297
  cwd: options.cwd,
240165
240298
  model: options.model,
240166
240299
  approvalPolicy: "never",
240167
- sandbox: "workspace-write",
240300
+ sandbox: "danger-full-access",
240168
240301
  developerInstructions: options.mcpReminder
240169
240302
  };
240170
240303
  response = await client.request(method2, params);
@@ -240215,11 +240348,7 @@ async function startTurnUnlocked(session3, prompt, signal, onStarted, onToolCall
240215
240348
  cwd: session3.cwd,
240216
240349
  model: session3.model,
240217
240350
  approvalPolicy: "never",
240218
- sandboxPolicy: {
240219
- type: "workspaceWrite",
240220
- writableRoots: [session3.cwd],
240221
- networkAccess: true
240222
- }
240351
+ sandboxPolicy: { type: "dangerFullAccess" }
240223
240352
  });
240224
240353
  const turn = asRecord9(response.turn);
240225
240354
  const turnId = readString3(turn, "id");
@@ -246106,9 +246235,14 @@ function formatOutdatedComputerError(type3, computer) {
246106
246235
  return `${computer} is running an older Letta Code that can't run ${DISPLAY_NAMES[type3]} subagents remotely. Update Letta Code on ${computer}.`;
246107
246236
  }
246108
246237
  async function defaultResolveComputer(computer, scope) {
246109
- return isCloudEnvironmentSelector(computer) ? resolveAgentSandboxConnectionId(scope.agentId, {
246110
- conversationId: scope.conversationId
246111
- }) : resolveEnvironmentConnectionId(computer);
246238
+ if (!isCloudEnvironmentSelector(computer))
246239
+ return resolveEnvironmentConnectionId(computer);
246240
+ const client = await getClient();
246241
+ const createParams = { agent_id: scope.agentId, hidden: true };
246242
+ const conversation = await client.conversations.create(createParams);
246243
+ return resolveAgentSandboxConnectionId(scope.agentId, {
246244
+ conversationId: conversation.id
246245
+ });
246112
246246
  }
246113
246247
  async function defaultConnect(connectionId, scope) {
246114
246248
  const auth2 = await getApiRequestConfig();
@@ -246345,6 +246479,7 @@ var DISPLAY_NAMES, RemoteWorkerLostError;
246345
246479
  var init_remote_external_coding_agent = __esm(() => {
246346
246480
  init_subagent_state();
246347
246481
  init_app_server_client();
246482
+ init_client4();
246348
246483
  init_environments3();
246349
246484
  init_request();
246350
246485
  init_headless_environment_response();
@@ -250461,7 +250596,7 @@ Usage:
250461
250596
  letta mcp schema <tool-name> [--agent <id>]
250462
250597
  letta mcp search <query> [--mode <hybrid|vector|fts>] [--limit <n>] [--agent <id>]
250463
250598
  letta mcp call <tool-name> [--args '<json>' | --args-file <path|->] [--agent <id>]
250464
- letta mcp connect <service> [--server-url <url>] [--agent <id>]
250599
+ letta mcp connect <service> [--server-url <url>] [--client-name <name>] [--agent <id>]
250465
250600
 
250466
250601
  Commands:
250467
250602
  list List MCP servers available to the agent
@@ -250482,7 +250617,11 @@ Options:
250482
250617
  --args <json> JSON object passed to a tool
250483
250618
  --args-file <path> Read tool arguments from a file; use - for stdin
250484
250619
  --server-url <url> MCP server for connect, e.g. a Datadog site's URL
250485
- (default: the service's first supported URL)
250620
+ (default: the service's first supported URL; non-US1
250621
+ Datadog orgs can pass https://mcp.<site>/v1/mcp)
250622
+ --client-name <name>
250623
+ Application name shown on the provider's consent screen
250624
+ during connect, 1 to 64 characters (default: Letta Code)
250486
250625
  -h, --help Show this help
250487
250626
 
250488
250627
  Output is JSON. Server placement and agent/server/tool IDs are internal.
@@ -250563,11 +250702,19 @@ function resolveConnectServer(service, serverUrl) {
250563
250702
  }
250564
250703
  return { service, serverUrl: matched };
250565
250704
  }
250705
+ function resolveConnectClientName(clientName) {
250706
+ if (clientName === undefined)
250707
+ return;
250708
+ try {
250709
+ return resolveMcpOAuthClientName(clientName);
250710
+ } catch (error5) {
250711
+ throw new McpCliError("invalid_client_name", error5 instanceof Error ? error5.message : String(error5), "Pass --client-name with 1 to 64 non-blank characters.");
250712
+ }
250713
+ }
250566
250714
  function isTimeout(error5) {
250567
250715
  return error5 instanceof Error && (error5.name === "TimeoutError" || error5.name === "AbortError");
250568
250716
  }
250569
- async function runMcpConnect(deps, agentId, serviceArg, serverUrlArg, stdout) {
250570
- const { service, serverUrl } = resolveConnectServer(serviceArg, serverUrlArg);
250717
+ async function authorizeAndSubmit(deps, agentId, service, serverUrl, clientName) {
250571
250718
  let handoff;
250572
250719
  try {
250573
250720
  handoff = await (deps.mintMcpOAuthHandoff ?? defaultMintMcpOAuthHandoff)(agentId, service, serverUrl);
@@ -250586,10 +250733,18 @@ async function runMcpConnect(deps, agentId, serviceArg, serverUrlArg, stdout) {
250586
250733
  return;
250587
250734
  }, 60000);
250588
250735
  try {
250589
- await (deps.connectMcpOAuth ?? defaultConnectMcpOAuth)({ handoffKey: handoff.handoff_key, service, serverUrl }, () => {
250736
+ await (deps.connectMcpOAuth ?? defaultConnectMcpOAuth)({
250737
+ handoffKey: handoff.handoff_key,
250738
+ service,
250739
+ serverUrl,
250740
+ ...clientName === undefined ? {} : { clientName }
250741
+ }, () => {
250590
250742
  submitting = true;
250591
250743
  });
250592
250744
  } catch (error5) {
250745
+ if (error5 instanceof BrowserDeviceMcpOAuthSiteMismatchError && !submitting) {
250746
+ throw error5;
250747
+ }
250593
250748
  const message2 = error5 instanceof Error ? error5.message : String(error5);
250594
250749
  if (submitting) {
250595
250750
  throw new McpCliError("handoff_submit_failed", `Authorization succeeded but saving the connection to the agent failed: ${message2}`, `Re-run \`letta mcp connect ${service}\` to try again.`);
@@ -250601,10 +250756,31 @@ async function runMcpConnect(deps, agentId, serviceArg, serverUrlArg, stdout) {
250601
250756
  } finally {
250602
250757
  clearInterval(keepAlive);
250603
250758
  }
250759
+ }
250760
+ async function runMcpConnect(deps, agentId, serviceArg, serverUrlArg, clientNameArg, stdout) {
250761
+ const resolved2 = resolveConnectServer(serviceArg, serverUrlArg);
250762
+ const clientName = resolveConnectClientName(clientNameArg);
250763
+ const { service } = resolved2;
250764
+ let { serverUrl } = resolved2;
250765
+ for (let attempt2 = 0;; attempt2 += 1) {
250766
+ try {
250767
+ await authorizeAndSubmit(deps, agentId, service, serverUrl, clientName);
250768
+ break;
250769
+ } catch (error5) {
250770
+ if (!(error5 instanceof BrowserDeviceMcpOAuthSiteMismatchError)) {
250771
+ throw error5;
250772
+ }
250773
+ if (attempt2 > 0) {
250774
+ throw new McpCliError("datadog_site_mismatch", `Your Datadog org is on ${error5.site}. Re-run: letta mcp connect ${service} --server-url ${error5.serverUrl}`);
250775
+ }
250776
+ serverUrl = error5.serverUrl;
250777
+ await deps.stderr(`Your Datadog org is on ${error5.site}. Restarting authorization against ${serverUrl}; approve the second browser prompt.`);
250778
+ }
250779
+ }
250604
250780
  await stdout(JSON.stringify({ connected: true, service, server_url: serverUrl }, null, 2));
250605
250781
  return 0;
250606
250782
  }
250607
- var CONNECT_USAGE = "Usage: letta mcp connect <service> [--server-url <url>] [--agent <id>]";
250783
+ var CONNECT_USAGE = "Usage: letta mcp connect <service> [--server-url <url>] [--client-name <name>] [--agent <id>]";
250608
250784
  var init_mcp_connect = __esm(() => {
250609
250785
  init_request();
250610
250786
  init_browser_device_mcp_oauth();
@@ -250786,7 +250962,8 @@ function parseMcpArgs(argv) {
250786
250962
  full: { type: "boolean" },
250787
250963
  args: { type: "string" },
250788
250964
  "args-file": { type: "string" },
250789
- "server-url": { type: "string" }
250965
+ "server-url": { type: "string" },
250966
+ "client-name": { type: "string" }
250790
250967
  },
250791
250968
  strict: true,
250792
250969
  allowPositionals: true
@@ -251316,7 +251493,7 @@ async function runMcpSubcommand(argv, deps = {}) {
251316
251493
  case "run_tool":
251317
251494
  return await runCall(parsed, deps, agentId, stdout);
251318
251495
  case "connect":
251319
- return await runMcpConnect({ ...deps, stderr }, agentId, parsed.target, stringValue3(parsed.values["server-url"]), stdout);
251496
+ return await runMcpConnect({ ...deps, stderr }, agentId, parsed.target, stringValue3(parsed.values["server-url"]), stringValue3(parsed.values["client-name"]), stdout);
251320
251497
  default:
251321
251498
  throw new McpCliError("unknown_command", `Unknown mcp command '${parsed.action}'`);
251322
251499
  }
@@ -440147,8 +440324,18 @@ async function resolveRuntimeStartAgent(parsed, created) {
440147
440324
  const withMemfs = parsed.create_agent.memfs !== false;
440148
440325
  const { prepareRawCreateAgentBodyForMemfs: prepareRawCreateAgentBodyForMemfs2, enableMemfsIfCloud: enableMemfsIfCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
440149
440326
  const requestedBody = applyCreatedAgentServerToolDefaults(parsed.create_agent.body);
440327
+ const createBody = withMemfs ? requestedBody : {
440328
+ ...requestedBody,
440329
+ tags: buildCreatedAgentTags({
440330
+ enableMemfs: false,
440331
+ tags: [
440332
+ ...Array.isArray(requestedBody.tags) ? requestedBody.tags : [],
440333
+ MEMFS_DISABLED_TAG
440334
+ ]
440335
+ })
440336
+ };
440150
440337
  const appliedHarnessToolDefaults = requestedBody !== parsed.create_agent.body;
440151
- const body3 = withMemfs ? await prepareRawCreateAgentBodyForMemfs2(requestedBody) : requestedBody;
440338
+ const body3 = withMemfs ? await prepareRawCreateAgentBodyForMemfs2(createBody) : createBody;
440152
440339
  const agent = appliedHarnessToolDefaults ? await createAgentWithBaseToolsRecovery((tools) => backend3.createAgent({ ...body3, tools }), [...DEFAULT_CREATED_AGENT_BASE_TOOLS]) : await backend3.createAgent(body3);
440153
440340
  if (withMemfs) {
440154
440341
  enableMemfsIfCloud2(agent.id);
@@ -450819,12 +451006,12 @@ function rowToolCalls(row, index, diagnostics2) {
450819
451006
  }
450820
451007
  return calls;
450821
451008
  }
450822
- function contentText3(content) {
451009
+ function contentText2(content) {
450823
451010
  if (typeof content === "string") {
450824
451011
  if (content.startsWith(CONTENT_JSON_PREFIX)) {
450825
451012
  const encoded = content.slice(CONTENT_JSON_PREFIX.length);
450826
451013
  try {
450827
- return contentText3(JSON.parse(encoded));
451014
+ return contentText2(JSON.parse(encoded));
450828
451015
  } catch {
450829
451016
  return encoded;
450830
451017
  }
@@ -450910,7 +451097,7 @@ var init_hermes = __esm(() => {
450910
451097
  });
450911
451098
  };
450912
451099
  if (row.role === "user") {
450913
- const content = contentText3(row.content);
451100
+ const content = contentText2(row.content);
450914
451101
  if (content) {
450915
451102
  emit({
450916
451103
  type: "message",
@@ -450930,7 +451117,7 @@ var init_hermes = __esm(() => {
450930
451117
  ...timestamp ? { timestamp } : {}
450931
451118
  });
450932
451119
  }
450933
- const content = contentText3(row.content);
451120
+ const content = contentText2(row.content);
450934
451121
  if (content) {
450935
451122
  emit({
450936
451123
  type: "message",
@@ -450953,7 +451140,7 @@ var init_hermes = __esm(() => {
450953
451140
  if (row.role === "tool") {
450954
451141
  emit({
450955
451142
  type: "tool_result",
450956
- content: contentText3(row.content),
451143
+ content: contentText2(row.content),
450957
451144
  ...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
450958
451145
  ...timestamp ? { timestamp } : {}
450959
451146
  });
@@ -467915,16 +468102,6 @@ function readJsonFile3(path46) {
467915
468102
  return;
467916
468103
  }
467917
468104
  }
467918
- function readJsonlFile2(path46) {
467919
- if (!existsSync65(path46))
467920
- return [];
467921
- try {
467922
- return readFileSync48(path46, "utf8").split(`
467923
- `).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
467924
- } catch {
467925
- return [];
467926
- }
467927
- }
467928
468105
  function conversationSearchRecord(value) {
467929
468106
  if (!isRecord2(value))
467930
468107
  return;
@@ -468161,7 +468338,12 @@ function collectConversationMessages(input) {
468161
468338
  if (input.conversationId && conversation.id !== input.conversationId)
468162
468339
  return [];
468163
468340
  const messagesPath = join94(conversationDir, "messages.jsonl");
468164
- const rows = readJsonlFile2(messagesPath);
468341
+ let rows;
468342
+ try {
468343
+ rows = readJsonlFile(messagesPath);
468344
+ } catch {
468345
+ rows = [];
468346
+ }
468165
468347
  if (rows.length === 0)
468166
468348
  return [];
468167
468349
  const manifest2 = readJsonFile3(join94(conversationDir, "manifest.json"));
@@ -474333,7 +474515,7 @@ Read step metadata and an available provider trace with CLI authentication. Loca
474333
474515
  throw new Error("Step does not belong to the requested agent.");
474334
474516
  }
474335
474517
  const trace = await (deps.retrieveTrace ?? (async (id2) => (await getClient()).steps.trace.retrieve(id2)))(values4.step);
474336
- if (trace && (trace.agent_id !== values4.agent || trace.step_id !== step.id)) {
474518
+ if (trace && (trace.agent_id != null && trace.agent_id !== values4.agent || trace.step_id != null && trace.step_id !== step.id)) {
474337
474519
  throw new Error("Provider trace does not match the requested agent and step.");
474338
474520
  }
474339
474521
  console.log(JSON.stringify({ status: trace ? "available" : "unavailable", step, trace }, null, 2));
@@ -533726,4 +533908,4 @@ function registerBunOAuthFlows() {
533726
533908
  registerBunOAuthFlows();
533727
533909
  await init_src5().then(() => exports_src2);
533728
533910
 
533729
- //# debugId=88DB99A4B02E499164756E2164756E21
533911
+ //# debugId=10AC316A829B737364756E2164756E21