@letta-ai/letta-code 0.32.8 → 0.32.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -3933,6 +3933,18 @@ var init_paths = __esm(() => {
3933
3933
  init_local_backend_paths();
3934
3934
  });
3935
3935
 
3936
+ // src/agent/acting-user.ts
3937
+ function resolveActingUserId(explicitActingUserId, runtimeActingUserId, env = process.env) {
3938
+ return explicitActingUserId ?? runtimeActingUserId ?? env[ACTING_USER_ID_ENV];
3939
+ }
3940
+ function actingUserRequestOptions(actingUserId) {
3941
+ if (!actingUserId) {
3942
+ return;
3943
+ }
3944
+ return { headers: { [ACTING_USER_ID_HEADER]: actingUserId } };
3945
+ }
3946
+ var ACTING_USER_ID_HEADER = "X-Letta-Acting-User-Id", ACTING_USER_ID_ENV = "LETTA_ACTING_USER_ID";
3947
+
3936
3948
  // src/helpers/usable-directory.ts
3937
3949
  import { statSync } from "node:fs";
3938
3950
  function readDirectoryStats(dirPath) {
@@ -3968,6 +3980,9 @@ import { homedir as homedir2, tmpdir } from "node:os";
3968
3980
  function getRuntimeContext() {
3969
3981
  return runtimeContextStorage.getStore();
3970
3982
  }
3983
+ function getRuntimeActingUserId() {
3984
+ return resolveActingUserId(undefined, getRuntimeContext()?.actingUserId);
3985
+ }
3971
3986
  function runWithRuntimeContext(snapshot, fn) {
3972
3987
  const parent = runtimeContextStorage.getStore();
3973
3988
  return runtimeContextStorage.run({
@@ -5515,7 +5530,7 @@ var package_default;
5515
5530
  var init_package = __esm(() => {
5516
5531
  package_default = {
5517
5532
  name: "@letta-ai/letta-code",
5518
- version: "0.32.8",
5533
+ version: "0.32.9",
5519
5534
  lettaStartupLogProtocol: 1,
5520
5535
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5521
5536
  type: "module",
@@ -5945,7 +5960,8 @@ async function submitTelemetryMetadata(apiKey, deviceId, payload, options) {
5945
5960
  await apiRequest("POST", "/v1/metadata/telemetry", payload, {
5946
5961
  ...config,
5947
5962
  headers: {
5948
- "X-Letta-Code-Device-ID": deviceId
5963
+ "X-Letta-Code-Device-ID": deviceId,
5964
+ ...actingUserRequestOptions(options?.actingUserId)?.headers
5949
5965
  },
5950
5966
  signal: options?.signal
5951
5967
  });
@@ -6167,6 +6183,7 @@ function isNonActionableError(message) {
6167
6183
 
6168
6184
  class TelemetryManager {
6169
6185
  events = [];
6186
+ eventActingUsers = new WeakMap;
6170
6187
  sessionId;
6171
6188
  deviceId = null;
6172
6189
  currentAgentId = null;
@@ -6291,6 +6308,7 @@ class TelemetryManager {
6291
6308
  backend: resolveTelemetryBackend()
6292
6309
  }
6293
6310
  };
6311
+ this.eventActingUsers.set(event, getRuntimeActingUserId());
6294
6312
  this.events.push(event);
6295
6313
  if (this.events.length >= this.MAX_BATCH_SIZE) {
6296
6314
  this.flush().catch((err) => {
@@ -6509,15 +6527,27 @@ class TelemetryManager {
6509
6527
  this.events = [];
6510
6528
  const apiKey = await this.resolveTelemetryApiKey();
6511
6529
  const deviceId = this.getTelemetryDeviceId();
6512
- try {
6513
- await submitTelemetryMetadata(apiKey, deviceId, {
6514
- service: "letta-code",
6515
- server_version: this.serverVersion || undefined,
6516
- events: eventsToSend
6517
- }, { signal: AbortSignal.timeout(5000) });
6518
- } catch (_error) {
6519
- this.events.unshift(...eventsToSend);
6520
- }
6530
+ const groups = new Map;
6531
+ for (const event of eventsToSend) {
6532
+ const actingUserId = this.eventActingUsers.get(event);
6533
+ const group = groups.get(actingUserId) ?? [];
6534
+ group.push(event);
6535
+ groups.set(actingUserId, group);
6536
+ }
6537
+ const failed = new Set;
6538
+ await Promise.all([...groups].map(async ([actingUserId, events]) => {
6539
+ try {
6540
+ await submitTelemetryMetadata(apiKey, deviceId, {
6541
+ service: "letta-code",
6542
+ server_version: this.serverVersion || undefined,
6543
+ events
6544
+ }, { signal: AbortSignal.timeout(5000), actingUserId });
6545
+ } catch {
6546
+ for (const event of events)
6547
+ failed.add(event);
6548
+ }
6549
+ }));
6550
+ this.events.unshift(...eventsToSend.filter((event) => failed.has(event)));
6521
6551
  }
6522
6552
  async drain() {
6523
6553
  if (!this.isTelemetryEnabled()) {
@@ -6554,6 +6584,7 @@ var init_telemetry = __esm(() => {
6554
6584
  init_metadata();
6555
6585
  init_server_url();
6556
6586
  init_paths();
6587
+ init_runtime_context();
6557
6588
  init_settings_manager();
6558
6589
  init_debug();
6559
6590
  init_version();
@@ -101243,7 +101274,6 @@ function createConversationRuntime(listener, agentId, conversationId) {
101243
101274
  acceptedInputDispositions: new Map,
101244
101275
  pendingApprovalResolvers: new Map,
101245
101276
  recoveredApprovalState: null,
101246
- syncApprovalRecoveryCompleted: false,
101247
101277
  expectedTeleportId: null,
101248
101278
  expectedTeleportExpiresAt: null,
101249
101279
  get lastStopReason() {
@@ -122326,18 +122356,6 @@ var init_search_file_content_gemini = __esm(() => {
122326
122356
  init_grep();
122327
122357
  });
122328
122358
 
122329
- // src/agent/acting-user.ts
122330
- function resolveActingUserId(explicitActingUserId, runtimeActingUserId, env3 = process.env) {
122331
- return explicitActingUserId ?? runtimeActingUserId ?? env3[ACTING_USER_ID_ENV];
122332
- }
122333
- function actingUserRequestOptions(actingUserId) {
122334
- if (!actingUserId) {
122335
- return;
122336
- }
122337
- return { headers: { [ACTING_USER_ID_HEADER]: actingUserId } };
122338
- }
122339
- var ACTING_USER_ID_HEADER = "X-Letta-Acting-User-Id", ACTING_USER_ID_ENV = "LETTA_ACTING_USER_ID";
122340
-
122341
122359
  // src/backend/api/agent-message.ts
122342
122360
  function normalizeAgentMessageComputer(value) {
122343
122361
  if (value == null)
@@ -123673,106 +123691,114 @@ var init_names = __esm(() => {
123673
123691
  init_constants2();
123674
123692
  SUBAGENT_NAMES = [
123675
123693
  "Deckard",
123676
- "Rachael",
123677
- "Roy",
123694
+ "Roy Batty",
123678
123695
  "Pris",
123679
123696
  "Zhora",
123680
- "Leon",
123681
123697
  "Gaff",
123682
123698
  "Tyrell",
123683
- "Sebastian",
123684
- "Bryant",
123685
- "Chew",
123686
- "Holden",
123687
- "Taffey",
123688
123699
  "K",
123689
123700
  "Joi",
123690
123701
  "Luv",
123691
- "Wallace",
123692
- "Joshi",
123693
123702
  "Sapper",
123694
- "Mariette",
123695
123703
  "Freysa",
123696
- "Ana",
123697
- "Coco",
123698
- "Samantha",
123699
- "Theodore",
123700
- "Amy",
123701
- "Catherine",
123702
- "Paul",
123703
- "Isabella",
123704
123704
  "Ava",
123705
- "Caleb",
123706
- "Nathan",
123707
123705
  "Kyoko",
123708
123706
  "V",
123709
- "Johnny",
123710
- "Jackie",
123711
- "Judy",
123707
+ "Silverhand",
123712
123708
  "Panam",
123713
- "River",
123714
- "Kerry",
123715
123709
  "Rogue",
123716
- "Alt",
123717
- "Evelyn",
123710
+ "Alt Cunningham",
123718
123711
  "Takemura",
123719
123712
  "Hanako",
123720
123713
  "Yorinobu",
123721
123714
  "Saburo",
123722
123715
  "Oda",
123723
- "Viktor",
123724
- "Misty",
123725
- "Dex",
123726
123716
  "T-Bug",
123727
123717
  "Delamain",
123728
123718
  "Wakako",
123729
123719
  "Padre",
123730
- "Regina",
123731
- "Dakota",
123732
- "Dino",
123733
123720
  "El Capitan",
123734
123721
  "Mr. Hands",
123735
123722
  "Placide",
123736
- "Brigitte",
123737
- "Royce",
123738
123723
  "Dum Dum",
123739
- "Brick",
123740
- "Meredith",
123741
- "Sandra",
123742
- "Maiko",
123743
- "Claire",
123744
123724
  "Nix",
123745
123725
  "Weyland",
123746
- "Saul",
123747
- "Mitch",
123748
123726
  "Scorpion",
123749
- "Cassidy",
123750
- "Carol",
123751
- "Denny",
123752
- "Nancy",
123753
- "Henry",
123754
123727
  "Blue Moon",
123755
123728
  "Red Menace",
123756
123729
  "Purple Force",
123757
- "Lizzy",
123730
+ "Lizzy Wizzy",
123758
123731
  "Ozob",
123759
123732
  "Smasher",
123760
- "Reed",
123761
123733
  "Songbird",
123762
- "Alex",
123763
- "Myers",
123764
- "Hansen",
123765
- "Paco",
123766
- "Babs",
123767
123734
  "Slider",
123768
- "Aurore",
123769
- "Aymeric",
123770
123735
  "Aguilar",
123771
- "Bree",
123772
- "Dante",
123773
- "Lina",
123774
- "Garry",
123775
- "Pepe"
123736
+ "Dogmeat",
123737
+ "Codsworth",
123738
+ "Nick Valentine",
123739
+ "Yes Man",
123740
+ "Mr. House",
123741
+ "ED-E",
123742
+ "Fisto",
123743
+ "Liberty Prime",
123744
+ "Three Dog",
123745
+ "Charon",
123746
+ "Fawkes",
123747
+ "Ulysses",
123748
+ "The Master",
123749
+ "Muggy",
123750
+ "Dr. Mobius",
123751
+ "Dr. Klein",
123752
+ "Old Longfellow",
123753
+ "Pickman",
123754
+ "Butch DeLoria",
123755
+ "Fantastic",
123756
+ "Muad'Dib",
123757
+ "Stilgar",
123758
+ "Chani",
123759
+ "Gurney Halleck",
123760
+ "Duncan Idaho",
123761
+ "Thufir Hawat",
123762
+ "Liet-Kynes",
123763
+ "Shadout Mapes",
123764
+ "Feyd-Rautha",
123765
+ "Rabban",
123766
+ "Piter De Vries",
123767
+ "Irulan",
123768
+ "Scytale",
123769
+ "Hayt",
123770
+ "Bijaz",
123771
+ "Moneo",
123772
+ "Miles Teg",
123773
+ "Darwi Odrade",
123774
+ "Sheeana",
123775
+ "Shaddam IV",
123776
+ "Count Fenring",
123777
+ "Wintermute",
123778
+ "Neuromancer",
123779
+ "Dixie Flatline",
123780
+ "Molly Millions",
123781
+ "Lady 3Jane",
123782
+ "Armitage",
123783
+ "Maelcum",
123784
+ "Ratz",
123785
+ "The Finn",
123786
+ "Hiro Protagonist",
123787
+ "Y.T.",
123788
+ "Raven",
123789
+ "Uncle Enzo",
123790
+ "R. Daneel Olivaw",
123791
+ "R. Giskard Reventlov",
123792
+ "Hari Seldon",
123793
+ "Dors Venabili",
123794
+ "The Mule",
123795
+ "HAL 9000",
123796
+ "Aineko",
123797
+ "Eschaton",
123798
+ "Mycroft Canner",
123799
+ "J.E.D.D. Mason",
123800
+ "Sniper",
123801
+ "Eureka Weeksbooth"
123776
123802
  ];
123777
123803
  nextName = createSubagentNameAllocator();
123778
123804
  });
@@ -125204,7 +125230,10 @@ async function task(args) {
125204
125230
  const agentId = linkedAgent?.agentId ?? null;
125205
125231
  const agentIdLine = agentId ? `
125206
125232
  Agent ID: ${agentId}` : "";
125207
- return `Task running in background with task ID: ${taskId}${agentIdLine}
125233
+ const conversationId = linkedAgent?.conversationId ?? null;
125234
+ const conversationIdLine = conversationId ? `
125235
+ Conversation ID: ${conversationId}` : "";
125236
+ return `Task running in background with task ID: ${taskId}${agentIdLine}${conversationIdLine}
125208
125237
  Output file: ${outputFile}
125209
125238
 
125210
125239
  You will be notified automatically when this task completes — a <task-notification> message will be delivered with the result. No need to poll, sleep-wait, or check the output file. Just continue with your current work.`;
@@ -134381,7 +134410,7 @@ async function executeToolInner(name, args, options) {
134381
134410
  return createModPermissionToolResult(permissionDecision2);
134382
134411
  }
134383
134412
  }
134384
- return executeExternalTool(options?.toolCallId ?? `ext-${Date.now()}`, name, eventArgs2, externalTool?.executor ?? activeExternalExecutor, externalTool);
134413
+ return runWithRuntimeContext(executionScope, () => executeExternalTool(options?.toolCallId ?? `ext-${Date.now()}`, name, eventArgs2, externalTool?.executor ?? activeExternalExecutor, externalTool));
134385
134414
  }
134386
134415
  const internalName = resolveInternalToolName(name, activeRegistry);
134387
134416
  const tool = internalName ? activeRegistry.get(internalName) : undefined;
@@ -223091,8 +223120,8 @@ function isSyncCommand(value) {
223091
223120
  if (!value || typeof value !== "object") {
223092
223121
  return false;
223093
223122
  }
223094
- const candidate = value;
223095
- return candidate.type === "sync" && isRuntimeScope(candidate.runtime) && (candidate.request_id === undefined || typeof candidate.request_id === "string") && (candidate.recover_approvals === undefined || typeof candidate.recover_approvals === "boolean") && (candidate.force_device_status === undefined || typeof candidate.force_device_status === "boolean");
223123
+ const c = value;
223124
+ return c.type === "sync" && isRuntimeScope(c.runtime) && (c.request_id === undefined || typeof c.request_id === "string") && (c.recover_approvals === undefined || typeof c.recover_approvals === "boolean") && (c.resume_interrupted_turn === undefined || typeof c.resume_interrupted_turn === "boolean") && (c.force_device_status === undefined || typeof c.force_device_status === "boolean");
223096
223125
  }
223097
223126
  function isTerminalSpawnCommand(value) {
223098
223127
  if (!value || typeof value !== "object")
@@ -402519,7 +402548,6 @@ async function startRecoveredApprovalContinuation(runtime, socket, processTurn,
402519
402548
  if (!await canRecoverConversation(runtime)) {
402520
402549
  if (runtime.recoveredApprovalState === recovered) {
402521
402550
  clearRecoveredApprovalState(runtime);
402522
- runtime.syncApprovalRecoveryCompleted = false;
402523
402551
  }
402524
402552
  return false;
402525
402553
  }
@@ -407312,12 +407340,12 @@ function rowToolCalls(row, index, diagnostics2) {
407312
407340
  }
407313
407341
  return calls;
407314
407342
  }
407315
- function contentText2(content) {
407343
+ function contentText(content) {
407316
407344
  if (typeof content === "string") {
407317
407345
  if (content.startsWith(CONTENT_JSON_PREFIX)) {
407318
407346
  const encoded = content.slice(CONTENT_JSON_PREFIX.length);
407319
407347
  try {
407320
- return contentText2(JSON.parse(encoded));
407348
+ return contentText(JSON.parse(encoded));
407321
407349
  } catch {
407322
407350
  return encoded;
407323
407351
  }
@@ -407403,7 +407431,7 @@ var init_hermes = __esm(() => {
407403
407431
  });
407404
407432
  };
407405
407433
  if (row.role === "user") {
407406
- const content = contentText2(row.content);
407434
+ const content = contentText(row.content);
407407
407435
  if (content) {
407408
407436
  emit({
407409
407437
  type: "message",
@@ -407423,7 +407451,7 @@ var init_hermes = __esm(() => {
407423
407451
  ...timestamp ? { timestamp } : {}
407424
407452
  });
407425
407453
  }
407426
- const content = contentText2(row.content);
407454
+ const content = contentText(row.content);
407427
407455
  if (content) {
407428
407456
  emit({
407429
407457
  type: "message",
@@ -407446,7 +407474,7 @@ var init_hermes = __esm(() => {
407446
407474
  if (row.role === "tool") {
407447
407475
  emit({
407448
407476
  type: "tool_result",
407449
- content: contentText2(row.content),
407477
+ content: contentText(row.content),
407450
407478
  ...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
407451
407479
  ...timestamp ? { timestamp } : {}
407452
407480
  });
@@ -413453,16 +413481,18 @@ function extractTelemetryInputText(content) {
413453
413481
  }
413454
413482
 
413455
413483
  // src/websocket/listener/turn-transcript.ts
413456
- function trackListenerUserInput(messages, modelId) {
413457
- for (const message of messages) {
413458
- if (!("role" in message) || message.role !== "user") {
413459
- continue;
413460
- }
413461
- const inputText = extractTelemetryInputText(message.content);
413462
- if (inputText.length > 0) {
413463
- telemetry.trackUserInput(inputText, "user", modelId);
413484
+ function trackListenerUserInput(messages, modelId, actingUserId) {
413485
+ runWithRuntimeContext({ actingUserId }, () => {
413486
+ for (const message of messages) {
413487
+ if (!("role" in message) || message.role !== "user") {
413488
+ continue;
413489
+ }
413490
+ const inputText = extractTelemetryInputText(message.content);
413491
+ if (inputText.length > 0) {
413492
+ telemetry.trackUserInput(inputText, "user", modelId);
413493
+ }
413464
413494
  }
413465
- }
413495
+ });
413466
413496
  }
413467
413497
  function buildInboundUserTranscriptLines(messages) {
413468
413498
  const lines = [];
@@ -413497,6 +413527,7 @@ function seedInboundUserTranscriptLines(buffers, lines) {
413497
413527
  }
413498
413528
  }
413499
413529
  var init_turn_transcript = __esm(() => {
413530
+ init_runtime_context();
413500
413531
  init_telemetry();
413501
413532
  });
413502
413533
 
@@ -413609,7 +413640,7 @@ async function prepareListenerTurn(params) {
413609
413640
  if (connectionId) {
413610
413641
  onStatusChange?.("processing", connectionId);
413611
413642
  }
413612
- trackListenerUserInput(msg.messages, "unknown");
413643
+ trackListenerUserInput(msg.messages, "unknown", msg.actingUserId);
413613
413644
  const messagesToSend = [];
413614
413645
  let queuedInterruptedToolCallIds = [];
413615
413646
  const wasInterrupted = hasInterruptedCacheForScope(runtime.listener, {
@@ -418403,6 +418434,7 @@ function summarizeV2Command(parsed) {
418403
418434
  "replace_all",
418404
418435
  "expected_replacements",
418405
418436
  "recover_approvals",
418437
+ "resume_interrupted_turn",
418406
418438
  "force_device_status"
418407
418439
  ]) {
418408
418440
  pushField(fields, key2, parsed[key2]);
@@ -418869,6 +418901,7 @@ function createListenerMessageHandler(params) {
418869
418901
  try {
418870
418902
  await replaySyncStateForRuntime(runtime, socket, parsed.runtime, {
418871
418903
  recoverApprovals: parsed.recover_approvals !== false,
418904
+ resumeInterruptedTurn: parsed.resume_interrupted_turn === true,
418872
418905
  forceDeviceStatus: parsed.force_device_status === true,
418873
418906
  onStatusChange: opts.onStatusChange,
418874
418907
  connectionId: opts.connectionId
@@ -419448,7 +419481,7 @@ var init_process_services = __esm(async () => {
419448
419481
  function isBackendNotFoundError2(error4) {
419449
419482
  return error4 instanceof APIError && (error4.status === 404 || error4.status === 422) || error4 instanceof Error && error4.name === "LocalBackendNotFoundError";
419450
419483
  }
419451
- async function recoverApprovalStateForSync(runtime, scope, deps = {}) {
419484
+ async function recoverApprovalStateForSync(runtime, scope, deps = {}, opts = {}) {
419452
419485
  const resolvedDeps = {
419453
419486
  getBackend,
419454
419487
  getResumeDataFromBackend,
@@ -419518,6 +419551,17 @@ async function recoverApprovalStateForSync(runtime, scope, deps = {}) {
419518
419551
  approval,
419519
419552
  reason: STALE_APPROVAL_RECOVERY_DENIAL_REASON
419520
419553
  }));
419554
+ if (interactivePending.length === 0 && !opts.resumeInterruptedTurn) {
419555
+ runtime.pendingInterruptedResults = buildFreshDenialApprovals(pendingApprovals, STALE_APPROVAL_RECOVERY_DENIAL_REASON);
419556
+ runtime.pendingInterruptedContext = {
419557
+ agentId: scope.agent_id,
419558
+ conversationId: scope.conversation_id,
419559
+ continuationEpoch: runtime.continuationEpoch
419560
+ };
419561
+ runtime.pendingInterruptedToolCallIds = null;
419562
+ clearRecoveredApprovalState(runtime);
419563
+ return;
419564
+ }
419521
419565
  const approvalsByRequestId = new Map;
419522
419566
  for (const approval of interactivePending) {
419523
419567
  const requestId = `perm-${approval.toolCallId}`;
@@ -419569,10 +419613,11 @@ var init_recovery_sync = __esm(() => {
419569
419613
  async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
419570
419614
  const syncScopedRuntime = getOrCreateScopedRuntime(listenerRuntime, scope.agent_id, scope.conversation_id);
419571
419615
  const recoverFn = opts?.recoverApprovalStateForSync ?? recoverApprovalStateForSync;
419572
- if ((opts?.recoverApprovals ?? true) || !syncScopedRuntime.syncApprovalRecoveryCompleted) {
419616
+ if (opts?.recoverApprovals ?? true) {
419573
419617
  try {
419574
- const recovered = await recoverFn(syncScopedRuntime, scope);
419575
- syncScopedRuntime.syncApprovalRecoveryCompleted = recovered !== "deferred";
419618
+ await recoverFn(syncScopedRuntime, scope, undefined, {
419619
+ resumeInterruptedTurn: opts?.resumeInterruptedTurn === true
419620
+ });
419576
419621
  } catch (error4) {
419577
419622
  trackBoundaryError({
419578
419623
  errorType: "listener_sync_recovery_failed",
@@ -440944,7 +440989,7 @@ var init_mcp_client = __esm(() => {
440944
440989
  init_streamableHttp();
440945
440990
  DEFAULT_CLIENT_INFO = {
440946
440991
  name: "letta-code",
440947
- version: "0.32.8"
440992
+ version: "0.32.9"
440948
440993
  };
440949
440994
  });
440950
440995
 
@@ -519787,7 +519832,9 @@ Error: ${message}`);
519787
519832
  return null;
519788
519833
  });
519789
519834
  if (!shouldBlockOnMemfsStartup) {}
519790
- const secretsInitPromise = Promise.resolve().then(() => (init_secrets_store(), exports_secrets_store)).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(agentId2));
519835
+ const secretsInitPromise = Promise.resolve().then(() => (init_secrets_store(), exports_secrets_store)).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(agentId2)).catch((error5) => {
519836
+ debugLog("secrets", `Failed to init secrets: ${error5 instanceof Error ? error5.message : String(error5)}`);
519837
+ });
519791
519838
  const isResumingProject = !shouldCreateNew && !!resumingAgentId;
519792
519839
  const isReusingExistingAgent = !shouldCreateNew && agent && agent.id;
519793
519840
  const resuming = !!(agentIdArg || isResumingProject || isReusingExistingAgent);
@@ -519898,11 +519945,7 @@ Error: ${message}`);
519898
519945
  }
519899
519946
  const fdPath = await ensureFdPath();
519900
519947
  setFileAutocompleteFdPath(fdPath);
519901
- try {
519902
- await secretsInitPromise;
519903
- } catch (error5) {
519904
- Promise.resolve().then(() => (init_debug(), exports_debug)).then(({ debugLog: debugLog3 }) => debugLog3("secrets", `Failed to init secrets: ${error5 instanceof Error ? error5.message : String(error5)}`));
519905
- }
519948
+ await secretsInitPromise;
519906
519949
  if (shouldPersistSessionState()) {
519907
519950
  settingsManager.persistSession(agent.id, conversationIdToUse);
519908
519951
  }
@@ -522317,4 +522360,4 @@ function registerBunOAuthFlows() {
522317
522360
  registerBunOAuthFlows();
522318
522361
  await init_src5().then(() => exports_src2);
522319
522362
 
522320
- //# debugId=A89D538A98A9FFDD64756E2164756E21
522363
+ //# debugId=73D666396EC039C064756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.32.8",
3
+ "version": "0.32.9",
4
4
  "lettaStartupLogProtocol": 1,
5
5
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  "src/cli/subcommands/skills.ts": 1264,
24
24
  "src/headless.ts": 4864,
25
25
  "src/hooks/integration.test.ts": 1147,
26
- "src/index.ts": 2616,
26
+ "src/index.ts": 2612,
27
27
  "src/mods/learning-harness.ts": 2434,
28
28
  "src/mods/mod-engine.test.ts": 2153,
29
29
  "src/mods/mod-engine.ts": 1838,
@@ -37,11 +37,11 @@
37
37
  "src/settings-manager.ts": 2102,
38
38
  "src/tools/manager.ts": 2897,
39
39
  "src/tools/tool-execution-context.test.ts": 1136,
40
- "src/types/protocol_v2.ts": 2595,
41
- "src/websocket/listen-client-concurrency.test.ts": 2677,
40
+ "src/types/protocol_v2.ts": 2593,
41
+ "src/websocket/listen-client-concurrency.test.ts": 2666,
42
42
  "src/websocket/listen-client-protocol.test.ts": 5762,
43
43
  "src/websocket/listener/commands/memory.ts": 1114,
44
44
  "src/websocket/listener/file-commands.ts": 1053,
45
- "src/websocket/listener/protocol-inbound.ts": 2143,
45
+ "src/websocket/listener/protocol-inbound.ts": 2137,
46
46
  "src/websocket/listener/protocol-outbound.ts": 1022
47
47
  }
@@ -1,4 +1,4 @@
1
- import { afterAll } from "bun:test";
1
+ import { afterAll, afterEach } from "bun:test";
2
2
  import { mkdtempSync, rmSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
4
  import { basename, isAbsolute, join, relative, resolve } from "node:path";
@@ -57,6 +57,14 @@ process.env.LETTA_CODE_TELEM ??= "0";
57
57
  // the redirected environment before their runtimes initialize.
58
58
  os.homedir = () => testHome;
59
59
 
60
+ // Load after redirecting home: channel config captures its filesystem root.
61
+ const routes = await import("@/channels/routing");
62
+ afterEach(() => {
63
+ routes.clearAllRoutes();
64
+ routes.__testOverrideLoadRoutes(null);
65
+ routes.__testOverrideSaveRoutes(null);
66
+ });
67
+
60
68
  if (!configuredTestHome) {
61
69
  const cleanup = () => {
62
70
  rmSync(testHome, { recursive: true, force: true });
@@ -1,10 +1,12 @@
1
1
  ---
2
2
  name: letta-guide
3
- description: Read the official Letta documentation (docs.letta.com) through its cached, ETag-checked fetch route. Load before ANY docs.letta.com retrieval — answering how Letta works, what Letta (or you) can do, setting up providers, models, channels, skills, memory, schedules, permissions, self-hosting, pricing, or billing, AND looking up Letta API, Agent SDK, or Letta Code reference while writing code. Do not use fetch_webpage or web_search on docs.letta.com; this skill's helper is the docs route. Never answer Letta product questions from memory alone.
3
+ description: Read the official Letta documentation (docs.letta.com) through its cached, ETag-checked fetch route. Load before ANY docs.letta.com retrieval — answering how Letta works, what Letta (or you) can do, and looking up Letta API, Agent SDK, or Letta Code reference.
4
4
  ---
5
5
 
6
6
  # Letta Guide
7
7
 
8
+ Do not use fetch_webpage or web_search on docs.letta.com; this skill's helper is the docs route.
9
+
8
10
  You are running inside Letta, but your training data about Letta's commands,
9
11
  flags, settings, UI, pricing, and providers is out of date. Users lose trust
10
12
  fastest when an agent confidently invents product details. This skill defines