@letta-ai/letta-code 0.21.12 → 0.21.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 (2) hide show
  1. package/letta.js +274 -39
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3269,7 +3269,7 @@ var package_default;
3269
3269
  var init_package = __esm(() => {
3270
3270
  package_default = {
3271
3271
  name: "@letta-ai/letta-code",
3272
- version: "0.21.12",
3272
+ version: "0.21.14",
3273
3273
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3274
3274
  type: "module",
3275
3275
  bin: {
@@ -40508,7 +40508,7 @@ import {
40508
40508
  mkdirSync as mkdirSync8,
40509
40509
  readFileSync as readFileSync7,
40510
40510
  renameSync as renameSync2,
40511
- rmdirSync,
40511
+ rmSync as rmSync2,
40512
40512
  statSync as statSync2,
40513
40513
  writeFileSync as writeFileSync6
40514
40514
  } from "node:fs";
@@ -40586,7 +40586,7 @@ function isLockStale(lockDir) {
40586
40586
  }
40587
40587
  function stealLock(lockDir) {
40588
40588
  try {
40589
- rmdirSync(lockDir, { recursive: true });
40589
+ rmSync2(lockDir, { recursive: true, force: true });
40590
40590
  } catch {}
40591
40591
  }
40592
40592
  function acquireLock() {
@@ -40607,7 +40607,7 @@ function acquireLock() {
40607
40607
  try {
40608
40608
  const current = readLockOwner(lockDir);
40609
40609
  if (current && current.token === token) {
40610
- rmdirSync(lockDir, { recursive: true });
40610
+ rmSync2(lockDir, { recursive: true, force: true });
40611
40611
  }
40612
40612
  } catch {}
40613
40613
  }
@@ -65411,7 +65411,7 @@ async function runProcess(context3) {
65411
65411
  }
65412
65412
  async function shell(args) {
65413
65413
  validateRequiredParams(args, ["command"], "shell");
65414
- const { command, workdir, timeout_ms, signal, onOutput } = args;
65414
+ const { command, workdir, timeout_ms, env_overrides, signal, onOutput } = args;
65415
65415
  if (!Array.isArray(command) || command.length === 0) {
65416
65416
  throw new Error("command must be a non-empty array of strings");
65417
65417
  }
@@ -65422,7 +65422,10 @@ async function shell(args) {
65422
65422
  const context3 = {
65423
65423
  command,
65424
65424
  cwd: cwd2,
65425
- env: getShellEnv(),
65425
+ env: {
65426
+ ...getShellEnv(),
65427
+ ...env_overrides ?? {}
65428
+ },
65426
65429
  timeout,
65427
65430
  signal,
65428
65431
  onOutput
@@ -65543,6 +65546,7 @@ async function shell_command(args) {
65543
65546
  signal,
65544
65547
  onOutput
65545
65548
  } = args;
65549
+ const envOverrides = getMemoryGitIdentityEnvOverrides(command, workdir);
65546
65550
  const launchers = buildShellLaunchers(command, { login });
65547
65551
  if (launchers.length === 0) {
65548
65552
  throw new Error("Command must be a non-empty string");
@@ -65554,6 +65558,7 @@ async function shell_command(args) {
65554
65558
  return await shell({
65555
65559
  command: launcher,
65556
65560
  workdir,
65561
+ env_overrides: envOverrides,
65557
65562
  timeout_ms,
65558
65563
  justification,
65559
65564
  signal,
@@ -65572,7 +65577,96 @@ async function shell_command(args) {
65572
65577
  const reason = lastError?.message || "Shell unavailable";
65573
65578
  throw new Error(suffix ? `${reason} (tried: ${suffix})` : reason);
65574
65579
  }
65580
+ function getMemoryGitIdentityEnvOverrides(command, workdir) {
65581
+ const agentId = getCurrentAgentIdOrEnv();
65582
+ if (!agentId) {
65583
+ return;
65584
+ }
65585
+ if (!containsGitCommitInvocation(command)) {
65586
+ return;
65587
+ }
65588
+ const scopedToMemoryDir = isMemoryDirCommand(command, agentId) || (workdir ? isMemoryDirCommand(`cd ${shellQuote(workdir)} && ${command}`, agentId) : false);
65589
+ if (!scopedToMemoryDir) {
65590
+ return;
65591
+ }
65592
+ const agentName = (process.env.AGENT_NAME || "").trim() || agentId;
65593
+ const agentEmail = `${agentId}@letta.com`;
65594
+ return {
65595
+ GIT_AUTHOR_NAME: agentName,
65596
+ GIT_AUTHOR_EMAIL: agentEmail,
65597
+ GIT_COMMITTER_NAME: agentName,
65598
+ GIT_COMMITTER_EMAIL: agentEmail
65599
+ };
65600
+ }
65601
+ function getCurrentAgentIdOrEnv() {
65602
+ const envAgentId = (process.env.AGENT_ID || process.env.LETTA_AGENT_ID || "").trim();
65603
+ if (envAgentId) {
65604
+ return envAgentId;
65605
+ }
65606
+ try {
65607
+ const agentId = getCurrentAgentId().trim();
65608
+ if (agentId) {
65609
+ return agentId;
65610
+ }
65611
+ } catch {}
65612
+ return "";
65613
+ }
65614
+ function containsGitCommitInvocation(command) {
65615
+ const segments = command.split(/&&|\|\||;|\|/).map((segment) => segment.trim()).filter(Boolean);
65616
+ for (const segment of segments) {
65617
+ const tokens = tokenizeSegment(segment);
65618
+ if (tokens.length === 0) {
65619
+ continue;
65620
+ }
65621
+ let index = 0;
65622
+ while (index < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=.*/.test(tokens[index] ?? "")) {
65623
+ index += 1;
65624
+ }
65625
+ if (tokens[index] !== "git") {
65626
+ continue;
65627
+ }
65628
+ index += 1;
65629
+ while (index < tokens.length) {
65630
+ const token = tokens[index];
65631
+ if (!token) {
65632
+ index += 1;
65633
+ continue;
65634
+ }
65635
+ if (token === "-c" || token === "-C") {
65636
+ index += 2;
65637
+ continue;
65638
+ }
65639
+ if (token.startsWith("-")) {
65640
+ index += 1;
65641
+ continue;
65642
+ }
65643
+ if (token === "commit") {
65644
+ return true;
65645
+ }
65646
+ break;
65647
+ }
65648
+ }
65649
+ return false;
65650
+ }
65651
+ function tokenizeSegment(segment) {
65652
+ const matches = segment.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
65653
+ if (!matches) {
65654
+ return [];
65655
+ }
65656
+ return matches.map(stripWrappingQuotes);
65657
+ }
65658
+ function stripWrappingQuotes(token) {
65659
+ if (token.startsWith('"') && token.endsWith('"') || token.startsWith("'") && token.endsWith("'")) {
65660
+ return token.slice(1, -1);
65661
+ }
65662
+ return token;
65663
+ }
65664
+ function shellQuote(value) {
65665
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
65666
+ }
65575
65667
  var init_ShellCommand2 = __esm(async () => {
65668
+ init_context();
65669
+ init_readOnlyShell();
65576
65670
  init_shellRunner();
65577
65671
  await init_Shell2();
65578
65672
  });
@@ -65827,6 +65921,17 @@ var init_skillContentRegistry = __esm(() => {
65827
65921
  import { readdirSync as readdirSync7 } from "node:fs";
65828
65922
  import { readFile as readFile6 } from "node:fs/promises";
65829
65923
  import { dirname as dirname10, join as join20 } from "node:path";
65924
+ function getMemorySkillsDirs(agentId) {
65925
+ const dirs = new Set;
65926
+ const memoryDir = process.env.MEMORY_DIR || process.env.LETTA_MEMORY_DIR;
65927
+ if (memoryDir && memoryDir.trim().length > 0) {
65928
+ dirs.add(join20(memoryDir.trim(), "skills"));
65929
+ }
65930
+ if (agentId) {
65931
+ dirs.add(join20(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory", "skills"));
65932
+ }
65933
+ return Array.from(dirs);
65934
+ }
65830
65935
  function hasAdditionalFiles(skillMdPath) {
65831
65936
  try {
65832
65937
  const skillDir = dirname10(skillMdPath);
@@ -65849,6 +65954,13 @@ async function readSkillContent(skillId, skillsDir, agentId) {
65849
65954
  return { content, path: agentSkillPath };
65850
65955
  } catch {}
65851
65956
  }
65957
+ for (const memorySkillsDir of getMemorySkillsDirs(agentId)) {
65958
+ const memorySkillPath = join20(memorySkillsDir, skillId, "SKILL.md");
65959
+ try {
65960
+ const content = await readFile6(memorySkillPath, "utf-8");
65961
+ return { content, path: memorySkillPath };
65962
+ } catch {}
65963
+ }
65852
65964
  const globalSkillPath = join20(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
65853
65965
  try {
65854
65966
  const content = await readFile6(globalSkillPath, "utf-8");
@@ -74226,6 +74338,84 @@ var init_check_approval = __esm(() => {
74226
74338
  ];
74227
74339
  });
74228
74340
 
74341
+ // src/utils/createRelayedAbortController.ts
74342
+ function createRelayedAbortController(parentSignal) {
74343
+ const controller = new AbortController;
74344
+ if (!parentSignal) {
74345
+ return {
74346
+ controller,
74347
+ signal: controller.signal,
74348
+ cleanup: () => {}
74349
+ };
74350
+ }
74351
+ if (parentSignal.aborted) {
74352
+ controller.abort(parentSignal.reason);
74353
+ return {
74354
+ controller,
74355
+ signal: controller.signal,
74356
+ cleanup: () => {}
74357
+ };
74358
+ }
74359
+ const relayAbort = () => {
74360
+ controller.abort(parentSignal.reason);
74361
+ };
74362
+ parentSignal.addEventListener("abort", relayAbort, { once: true });
74363
+ return {
74364
+ controller,
74365
+ signal: controller.signal,
74366
+ cleanup: () => {
74367
+ parentSignal.removeEventListener("abort", relayAbort);
74368
+ }
74369
+ };
74370
+ }
74371
+
74372
+ // src/utils/streamAbortRelay.ts
74373
+ function composeCleanups(first, second) {
74374
+ let cleaned = false;
74375
+ return () => {
74376
+ if (cleaned) {
74377
+ return;
74378
+ }
74379
+ cleaned = true;
74380
+ first();
74381
+ second();
74382
+ };
74383
+ }
74384
+ function createStreamAbortRelay(parentSignal) {
74385
+ if (!parentSignal) {
74386
+ return null;
74387
+ }
74388
+ const requestAbort = createRelayedAbortController(parentSignal);
74389
+ let cleaned = false;
74390
+ const cleanup = () => {
74391
+ if (cleaned) {
74392
+ return;
74393
+ }
74394
+ cleaned = true;
74395
+ requestAbort.cleanup();
74396
+ };
74397
+ return {
74398
+ signal: requestAbort.signal,
74399
+ attach(stream2) {
74400
+ const existingCleanup = streamAbortRelayCleanupByStream.get(stream2);
74401
+ streamAbortRelayCleanupByStream.set(stream2, existingCleanup ? composeCleanups(existingCleanup, cleanup) : cleanup);
74402
+ },
74403
+ cleanup
74404
+ };
74405
+ }
74406
+ function cleanupStreamAbortRelay(stream2) {
74407
+ const cleanup = streamAbortRelayCleanupByStream.get(stream2);
74408
+ if (!cleanup) {
74409
+ return;
74410
+ }
74411
+ streamAbortRelayCleanupByStream.delete(stream2);
74412
+ cleanup();
74413
+ }
74414
+ var streamAbortRelayCleanupByStream;
74415
+ var init_streamAbortRelay = __esm(() => {
74416
+ streamAbortRelayCleanupByStream = new WeakMap;
74417
+ });
74418
+
74229
74419
  // src/agent/approval-result-normalization.ts
74230
74420
  function normalizeToolReturnText(value) {
74231
74421
  if (typeof value === "string")
@@ -74470,19 +74660,23 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
74470
74660
  const firstOtid = messages[0]?.otid;
74471
74661
  debugLog("send-message-stream", "request_start conversation_id=%s agent_id=%s messages=%s otid=%s stream_tokens=%s background=%s max_retries=%s", resolvedConversationId, opts.agentId ?? "none", messageSummary || "(empty)", firstOtid ?? "none", opts.streamTokens ?? true, opts.background ?? true, requestOptions.maxRetries ?? "default");
74472
74662
  let stream2;
74663
+ const abortRelay = createStreamAbortRelay(requestOptions.signal);
74473
74664
  try {
74474
74665
  stream2 = await client.conversations.messages.create(resolvedConversationId, requestBody, {
74475
74666
  ...requestOptions,
74667
+ ...abortRelay ? { signal: abortRelay.signal } : {},
74476
74668
  headers: {
74477
74669
  ...requestOptions.headers ?? {},
74478
74670
  ...extraHeaders
74479
74671
  }
74480
74672
  });
74481
74673
  } catch (error) {
74674
+ abortRelay?.cleanup();
74482
74675
  debugWarn("send-message-stream", "request_error conversation_id=%s otid=%s status=%s error=%s", resolvedConversationId, firstOtid ?? "none", error?.status ?? "none", error instanceof Error ? error.message : String(error));
74483
74676
  throw error;
74484
74677
  }
74485
74678
  debugLog("send-message-stream", "request_ok conversation_id=%s otid=%s", resolvedConversationId, firstOtid ?? "none");
74679
+ abortRelay?.attach(stream2);
74486
74680
  if (requestStartTime !== undefined) {
74487
74681
  streamRequestStartTimes.set(stream2, requestStartTime);
74488
74682
  }
@@ -74499,6 +74693,7 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
74499
74693
  var streamRequestStartTimes, streamToolContextIds, streamRequestContexts;
74500
74694
  var init_message = __esm(async () => {
74501
74695
  init_debug();
74696
+ init_streamAbortRelay();
74502
74697
  init_timing();
74503
74698
  init_approval_result_normalization();
74504
74699
  init_clientSkills();
@@ -76589,6 +76784,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
76589
76784
  if (abortSignal) {
76590
76785
  abortSignal.removeEventListener("abort", abortHandler);
76591
76786
  }
76787
+ cleanupStreamAbortRelay(stream2);
76592
76788
  clearLastSDKDiagnostic();
76593
76789
  }
76594
76790
  if (!stopReason && streamProcessor.stopReason) {
@@ -76680,15 +76876,23 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
76680
76876
  const client = await lazyClient();
76681
76877
  buffers.commitGeneration = (buffers.commitGeneration || 0) + 1;
76682
76878
  buffers.interrupted = false;
76683
- const resumeStream = runIdSource === "otid" && streamOtid && streamRequestContext ? await client.conversations.messages.stream(streamRequestContext.resolvedConversationId, {
76684
- agent_id: streamRequestContext.conversationId === "default" ? streamRequestContext.agentId ?? undefined : undefined,
76685
- otid: streamOtid,
76686
- starting_after: result.lastSeqId ?? 0,
76687
- batch_size: 1000
76688
- }) : await client.runs.messages.stream(runIdToResume, {
76689
- starting_after: result.lastSeqId ?? 0,
76690
- batch_size: 1000
76691
- });
76879
+ const resumeAbortRelay = createStreamAbortRelay(abortSignal);
76880
+ let resumeStream;
76881
+ try {
76882
+ resumeStream = runIdSource === "otid" && streamOtid && streamRequestContext ? await client.conversations.messages.stream(streamRequestContext.resolvedConversationId, {
76883
+ agent_id: streamRequestContext.conversationId === "default" ? streamRequestContext.agentId ?? undefined : undefined,
76884
+ otid: streamOtid,
76885
+ starting_after: result.lastSeqId ?? 0,
76886
+ batch_size: 1000
76887
+ }, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined) : await client.runs.messages.stream(runIdToResume, {
76888
+ starting_after: result.lastSeqId ?? 0,
76889
+ batch_size: 1000
76890
+ }, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
76891
+ } catch (resumeError) {
76892
+ resumeAbortRelay?.cleanup();
76893
+ throw resumeError;
76894
+ }
76895
+ resumeAbortRelay?.attach(resumeStream);
76692
76896
  const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal, undefined, onChunkProcessed, contextTracker, seenSeqIdThreshold, true);
76693
76897
  if (resumeResult.stopReason !== "error") {
76694
76898
  debugWarn("stream", "[MID-STREAM RESUME] ✅ Success (runId=%s, stopReason=%s)", runIdToResume, resumeResult.stopReason);
@@ -76753,6 +76957,7 @@ var FALLBACK_RUN_DISCOVERY_TIMEOUT_MS = 5000;
76753
76957
  var init_stream = __esm(async () => {
76754
76958
  init_error();
76755
76959
  init_debug();
76960
+ init_streamAbortRelay();
76756
76961
  init_timing();
76757
76962
  init_chunkLog();
76758
76963
  await __promiseAll([
@@ -80692,15 +80897,23 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
80692
80897
  try {
80693
80898
  const client = await getClient();
80694
80899
  const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
80900
+ const resumeAbortRelay = createStreamAbortRelay(abortSignal);
80695
80901
  if (abortSignal?.aborted) {
80696
80902
  throw new Error("Cancelled by user");
80697
80903
  }
80698
- return await client.conversations.messages.stream(conversationId, {
80699
- agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
80700
- otid: messageOtid ?? undefined,
80701
- starting_after: 0,
80702
- batch_size: 1000
80703
- });
80904
+ try {
80905
+ const resumeStream = await client.conversations.messages.stream(conversationId, {
80906
+ agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
80907
+ otid: messageOtid ?? undefined,
80908
+ starting_after: 0,
80909
+ batch_size: 1000
80910
+ }, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
80911
+ resumeAbortRelay?.attach(resumeStream);
80912
+ return resumeStream;
80913
+ } catch (resumeError) {
80914
+ resumeAbortRelay?.cleanup();
80915
+ throw resumeError;
80916
+ }
80704
80917
  } catch (resumeError) {
80705
80918
  if (abortSignal?.aborted) {
80706
80919
  throw new Error("Cancelled by user");
@@ -80815,15 +81028,23 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
80815
81028
  try {
80816
81029
  const client = await getClient();
80817
81030
  const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
81031
+ const resumeAbortRelay = createStreamAbortRelay(abortSignal);
80818
81032
  if (abortSignal?.aborted) {
80819
81033
  throw new Error("Cancelled by user");
80820
81034
  }
80821
- return await client.conversations.messages.stream(conversationId, {
80822
- agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
80823
- otid: messageOtid ?? undefined,
80824
- starting_after: 0,
80825
- batch_size: 1000
80826
- });
81035
+ try {
81036
+ const resumeStream = await client.conversations.messages.stream(conversationId, {
81037
+ agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
81038
+ otid: messageOtid ?? undefined,
81039
+ starting_after: 0,
81040
+ batch_size: 1000
81041
+ }, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
81042
+ resumeAbortRelay?.attach(resumeStream);
81043
+ return resumeStream;
81044
+ } catch (resumeError) {
81045
+ resumeAbortRelay?.cleanup();
81046
+ throw resumeError;
81047
+ }
80827
81048
  } catch (resumeError) {
80828
81049
  if (abortSignal?.aborted) {
80829
81050
  throw new Error("Cancelled by user");
@@ -80853,6 +81074,7 @@ var init_send = __esm(async () => {
80853
81074
  init_errorFormatter();
80854
81075
  init_diffPreview();
80855
81076
  init_interactivePolicy();
81077
+ init_streamAbortRelay();
80856
81078
  init_constants2();
80857
81079
  init_cwd();
80858
81080
  init_permissionMode();
@@ -83697,6 +83919,19 @@ function runDetachedListenerTask(commandName, task2) {
83697
83919
  }
83698
83920
  });
83699
83921
  }
83922
+ async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
83923
+ const syncScopedRuntime = getOrCreateScopedRuntime(listenerRuntime, scope.agent_id, scope.conversation_id);
83924
+ const recoverFn = opts?.recoverApprovalStateForSync ?? recoverApprovalStateForSync;
83925
+ try {
83926
+ await recoverFn(syncScopedRuntime, scope);
83927
+ } catch (error) {
83928
+ trackListenerError("listener_sync_recovery_failed", error, "listener_sync_recovery");
83929
+ if (isDebugEnabled()) {
83930
+ console.warn("[Listen] Sync approval recovery failed:", error);
83931
+ }
83932
+ }
83933
+ emitStateSync(socket, listenerRuntime, scope);
83934
+ }
83700
83935
  function getParsedRuntimeScope(parsed) {
83701
83936
  if (!parsed || typeof parsed !== "object" || !("runtime" in parsed)) {
83702
83937
  return null;
@@ -83727,7 +83962,7 @@ function handleModeChange(msg, socket, runtime, scope) {
83727
83962
  current.modeBeforePlan = null;
83728
83963
  }
83729
83964
  persistPermissionModeMapForRuntime(runtime);
83730
- emitDeviceStatusUpdate(socket, runtime, scope);
83965
+ emitRuntimeStateUpdates(runtime, scope);
83731
83966
  if (isDebugEnabled()) {
83732
83967
  console.log(`[Listen] Mode changed to: ${msg.mode}`);
83733
83968
  }
@@ -84089,7 +84324,7 @@ async function handleSkillCommand(parsed, socket) {
84089
84324
  existsSync: existsSync22,
84090
84325
  lstatSync: lstatSync2,
84091
84326
  mkdirSync: mkdirSync15,
84092
- rmdirSync: rmdirSync2,
84327
+ rmdirSync,
84093
84328
  symlinkSync,
84094
84329
  unlinkSync: unlinkSync8
84095
84330
  } = await import("node:fs");
@@ -84124,7 +84359,7 @@ async function handleSkillCommand(parsed, socket) {
84124
84359
  const stat6 = lstatSync2(linkPath);
84125
84360
  if (stat6.isSymbolicLink()) {
84126
84361
  if (process.platform === "win32") {
84127
- rmdirSync2(linkPath);
84362
+ rmdirSync(linkPath);
84128
84363
  } else {
84129
84364
  unlinkSync8(linkPath);
84130
84365
  }
@@ -84182,7 +84417,7 @@ async function handleSkillCommand(parsed, socket) {
84182
84417
  return true;
84183
84418
  }
84184
84419
  if (process.platform === "win32") {
84185
- rmdirSync2(linkPath);
84420
+ rmdirSync(linkPath);
84186
84421
  } else {
84187
84422
  unlinkSync8(linkPath);
84188
84423
  }
@@ -84832,9 +85067,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
84832
85067
  console.log(`[Listen V2] Dropping sync: runtime mismatch or closed`);
84833
85068
  return;
84834
85069
  }
84835
- const syncScopedRuntime = getOrCreateScopedRuntime(runtime, parsed.runtime.agent_id, parsed.runtime.conversation_id);
84836
- await recoverApprovalStateForSync(syncScopedRuntime, parsed.runtime);
84837
- emitStateSync(socket, runtime, parsed.runtime);
85070
+ await replaySyncStateForRuntime(runtime, socket, parsed.runtime);
84838
85071
  return;
84839
85072
  }
84840
85073
  if (parsed.type === "input") {
@@ -85749,6 +85982,7 @@ var init_client4 = __esm(async () => {
85749
85982
  __listenClientTestUtils = {
85750
85983
  createRuntime: createLegacyTestRuntime,
85751
85984
  createListenerRuntime: createRuntime,
85985
+ handleModeChange,
85752
85986
  getOrCreateScopedRuntime,
85753
85987
  buildListModelsEntries,
85754
85988
  buildListModelsResponse,
@@ -85798,6 +86032,7 @@ var init_client4 = __esm(async () => {
85798
86032
  handleCreateAgentCommand,
85799
86033
  handleReflectionSettingsCommand,
85800
86034
  scheduleQueuePump,
86035
+ replaySyncStateForRuntime,
85801
86036
  recoverApprovalStateForSync,
85802
86037
  clearRecoveredApprovalStateForScope: (runtime, scope) => clearRecoveredApprovalStateForScope(asListenerRuntimeForTests(runtime), scope),
85803
86038
  emitStateSync
@@ -119988,7 +120223,7 @@ import {
119988
120223
  mkdirSync as mkdirSync22,
119989
120224
  mkdtempSync,
119990
120225
  readFileSync as readFileSync18,
119991
- rmSync as rmSync3,
120226
+ rmSync as rmSync4,
119992
120227
  writeFileSync as writeFileSync16
119993
120228
  } from "node:fs";
119994
120229
  import { tmpdir as tmpdir5 } from "node:os";
@@ -120371,7 +120606,7 @@ async function installGithubApp(options) {
120371
120606
  agentUrl: resolvedAgentId ? buildChatUrl(resolvedAgentId) : null
120372
120607
  };
120373
120608
  } finally {
120374
- rmSync3(tempDir, { recursive: true, force: true });
120609
+ rmSync4(tempDir, { recursive: true, force: true });
120375
120610
  }
120376
120611
  }
120377
120612
  var DEFAULT_WORKFLOW_PATH = ".github/workflows/letta.yml", ALTERNATE_WORKFLOW_PATH = ".github/workflows/letta-code.yml";
@@ -149303,7 +149538,7 @@ async function runListenSubcommand(argv) {
149303
149538
 
149304
149539
  // src/cli/subcommands/memfs.ts
149305
149540
  await init_memoryGit();
149306
- import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync15, rmSync as rmSync2, statSync as statSync8 } from "node:fs";
149541
+ import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync15, rmSync as rmSync3, statSync as statSync8 } from "node:fs";
149307
149542
  import { readdir as readdir6 } from "node:fs/promises";
149308
149543
  import { homedir as homedir23 } from "node:os";
149309
149544
  import { join as join28 } from "node:path";
@@ -149496,7 +149731,7 @@ async function runMemfsSubcommand(argv) {
149496
149731
  return 1;
149497
149732
  }
149498
149733
  const root = getMemoryRoot(agentId);
149499
- rmSync2(root, { recursive: true, force: true });
149734
+ rmSync3(root, { recursive: true, force: true });
149500
149735
  cpSync(backupPath, root, { recursive: true });
149501
149736
  console.log(JSON.stringify({ restoredFrom: backupPath }, null, 2));
149502
149737
  return 0;
@@ -153311,4 +153546,4 @@ Error during initialization: ${message}`);
153311
153546
  }
153312
153547
  main();
153313
153548
 
153314
- //# debugId=1C3BE0588811294864756E2164756E21
153549
+ //# debugId=DEDBAA251791817164756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.21.12",
3
+ "version": "0.21.14",
4
4
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {