@letta-ai/letta-code 0.21.10 → 0.21.11

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 +215 -37
  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.10",
3272
+ version: "0.21.11",
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: {
@@ -73402,18 +73402,29 @@ var init_turn_recovery_policy = __esm(() => {
73402
73402
  });
73403
73403
 
73404
73404
  // src/agent/approval-recovery.ts
73405
- async function fetchRunErrorDetail(runId) {
73405
+ async function fetchRunErrorInfo(runId) {
73406
73406
  if (!runId)
73407
73407
  return null;
73408
73408
  try {
73409
73409
  const client = await getClient();
73410
73410
  const run = await client.runs.retrieve(runId);
73411
73411
  const metaError = run.metadata?.error;
73412
- return metaError?.detail ?? metaError?.message ?? metaError?.error?.detail ?? metaError?.error?.message ?? null;
73412
+ const nestedError = metaError?.error;
73413
+ const errorInfo = {
73414
+ error_type: metaError?.error_type ?? metaError?.type ?? nestedError?.error_type ?? nestedError?.type,
73415
+ message: metaError?.message ?? nestedError?.message,
73416
+ detail: metaError?.detail ?? nestedError?.detail,
73417
+ run_id: metaError?.run_id ?? nestedError?.run_id ?? runId
73418
+ };
73419
+ return errorInfo.error_type || errorInfo.message || errorInfo.detail ? errorInfo : null;
73413
73420
  } catch {
73414
73421
  return null;
73415
73422
  }
73416
73423
  }
73424
+ async function fetchRunErrorDetail(runId) {
73425
+ const errorInfo = await fetchRunErrorInfo(runId);
73426
+ return errorInfo?.detail ?? errorInfo?.message ?? null;
73427
+ }
73417
73428
  var init_approval_recovery = __esm(async () => {
73418
73429
  init_turn_recovery_policy();
73419
73430
  await init_client2();
@@ -75857,6 +75868,7 @@ class StreamProcessor {
75857
75868
  const errorDetail = chunkWithError.error.detail || "";
75858
75869
  errorInfo = {
75859
75870
  message: errorDetail ? `${errorText}: ${errorDetail}` : errorText,
75871
+ detail: errorDetail || undefined,
75860
75872
  run_id: this.lastRunId || undefined
75861
75873
  };
75862
75874
  }
@@ -77186,13 +77198,52 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
77186
77198
  if (socket.readyState !== WebSocket.OPEN) {
77187
77199
  return Promise.reject(new Error("WebSocket not open"));
77188
77200
  }
77201
+ const abortSignal = runtime.activeAbortController?.signal ?? null;
77202
+ const isInterrupted = () => runtime.cancelRequested || abortSignal?.aborted === true;
77203
+ if (isInterrupted()) {
77204
+ return Promise.reject(new Error("Cancelled by user"));
77205
+ }
77189
77206
  return new Promise((resolve23, reject) => {
77207
+ let settled = false;
77208
+ const cleanupAbortListener = () => {
77209
+ abortSignal?.removeEventListener("abort", handleAbort);
77210
+ };
77211
+ const wrappedResolve = (response) => {
77212
+ if (settled) {
77213
+ return;
77214
+ }
77215
+ settled = true;
77216
+ cleanupAbortListener();
77217
+ resolve23(response);
77218
+ };
77219
+ const wrappedReject = (error) => {
77220
+ if (settled) {
77221
+ return;
77222
+ }
77223
+ settled = true;
77224
+ cleanupAbortListener();
77225
+ reject(error);
77226
+ };
77227
+ const handleAbort = () => {
77228
+ runtime.pendingApprovalResolvers.delete(requestId);
77229
+ runtime.listener.approvalRuntimeKeyByRequestId.delete(requestId);
77230
+ wrappedReject(new Error("Cancelled by user"));
77231
+ };
77232
+ abortSignal?.addEventListener("abort", handleAbort, { once: true });
77233
+ if (isInterrupted()) {
77234
+ handleAbort();
77235
+ return;
77236
+ }
77190
77237
  runtime.pendingApprovalResolvers.set(requestId, {
77191
- resolve: resolve23,
77192
- reject,
77238
+ resolve: wrappedResolve,
77239
+ reject: wrappedReject,
77193
77240
  controlRequest
77194
77241
  });
77195
77242
  runtime.listener.approvalRuntimeKeyByRequestId.set(requestId, runtime.key);
77243
+ if (isInterrupted()) {
77244
+ handleAbort();
77245
+ return;
77246
+ }
77196
77247
  runtime.lastStopReason = "requires_approval";
77197
77248
  setLoopStatus(runtime, "WAITING_ON_APPROVAL");
77198
77249
  emitLoopStatusIfOpen(runtime.listener, {
@@ -77489,12 +77540,18 @@ function populateInterruptQueue(runtime, input) {
77489
77540
  return false;
77490
77541
  }
77491
77542
  function consumeInterruptQueue(runtime, agentId, conversationId) {
77543
+ const ctx = runtime.pendingInterruptedContext;
77544
+ const matchingContext = !!ctx && ctx.agentId === agentId && ctx.conversationId === conversationId && ctx.continuationEpoch === runtime.continuationEpoch;
77492
77545
  if (!runtime.pendingInterruptedResults || runtime.pendingInterruptedResults.length === 0) {
77546
+ if (matchingContext) {
77547
+ runtime.pendingInterruptedResults = null;
77548
+ runtime.pendingInterruptedContext = null;
77549
+ runtime.pendingInterruptedToolCallIds = null;
77550
+ }
77493
77551
  return null;
77494
77552
  }
77495
- const ctx = runtime.pendingInterruptedContext;
77496
77553
  let result = null;
77497
- if (ctx && ctx.agentId === agentId && ctx.conversationId === conversationId && ctx.continuationEpoch === runtime.continuationEpoch) {
77554
+ if (matchingContext) {
77498
77555
  result = {
77499
77556
  approvalMessage: {
77500
77557
  type: "approval",
@@ -77691,6 +77748,104 @@ function mirrorRecoverableNoticeToDesktopDebugPanel(message) {
77691
77748
  `);
77692
77749
  } catch {}
77693
77750
  }
77751
+ function toStructuredApiError(errorInfo) {
77752
+ if (!errorInfo?.error_type || !errorInfo.run_id) {
77753
+ return;
77754
+ }
77755
+ return {
77756
+ message_type: "error_message",
77757
+ message: errorInfo.message || errorInfo.detail || "An error occurred",
77758
+ error_type: errorInfo.error_type,
77759
+ run_id: errorInfo.run_id,
77760
+ ...errorInfo.detail ? { detail: errorInfo.detail } : {}
77761
+ };
77762
+ }
77763
+ function getStructuredApiErrorFromError(error) {
77764
+ if (!(error instanceof Error)) {
77765
+ return;
77766
+ }
77767
+ const errorWithStructuredInfo = error;
77768
+ return errorWithStructuredInfo.apiError ?? toStructuredApiError(errorWithStructuredInfo.runErrorInfo);
77769
+ }
77770
+ function buildStructuredFormatInput(apiError) {
77771
+ return {
77772
+ error: {
77773
+ error: {
77774
+ type: apiError.error_type,
77775
+ message: apiError.message,
77776
+ ...apiError.detail ? { detail: apiError.detail } : {}
77777
+ },
77778
+ run_id: apiError.run_id
77779
+ }
77780
+ };
77781
+ }
77782
+ function isAbortLikeError(error) {
77783
+ if (error instanceof APIUserAbortError) {
77784
+ return true;
77785
+ }
77786
+ if (!(error instanceof Error)) {
77787
+ return false;
77788
+ }
77789
+ const errorWithCode = error;
77790
+ return error.name === "AbortError" || error.message === "The operation was aborted" || errorWithCode.code === "ABORT_ERR";
77791
+ }
77792
+ function isTerminatedProcessNoise(message) {
77793
+ return message.trim().toLowerCase() === "terminated";
77794
+ }
77795
+ function isProxyTransportError(detail, error, message) {
77796
+ if (error instanceof APIError2 && error.status >= 500 && detail.toLowerCase().includes("trying to proxy")) {
77797
+ return true;
77798
+ }
77799
+ return detail.toLowerCase().includes("error occurred while trying to proxy") || message.toLowerCase().includes("error occurred while trying to proxy");
77800
+ }
77801
+ function getLoopErrorNoticeDecision(params) {
77802
+ const apiError = params.apiError ?? toStructuredApiError(params.errorInfo) ?? toStructuredApiError(params.runErrorInfo) ?? getStructuredApiErrorFromError(params.error);
77803
+ const detail = apiError?.detail ?? params.errorInfo?.detail ?? params.runErrorInfo?.detail ?? extractConflictDetail(params.error) ?? "";
77804
+ if (params.cancelRequested || params.abortSignal?.aborted || isAbortLikeError(params.error) || isTerminatedProcessNoise(params.message)) {
77805
+ return {
77806
+ visibility: "debug_only",
77807
+ message: params.message
77808
+ };
77809
+ }
77810
+ const cloudflareMessage = checkCloudflareEdgeError2(detail) ?? checkCloudflareEdgeError2(params.message);
77811
+ if (cloudflareMessage) {
77812
+ return {
77813
+ visibility: "transcript",
77814
+ message: cloudflareMessage,
77815
+ apiError
77816
+ };
77817
+ }
77818
+ if (isProxyTransportError(detail, params.error, params.message)) {
77819
+ return {
77820
+ visibility: "transcript",
77821
+ message: "Connection to Letta service failed. Please retry.",
77822
+ apiError
77823
+ };
77824
+ }
77825
+ const formattedMessage = formatErrorDetails2(apiError ? buildStructuredFormatInput(apiError) : params.error ?? params.message, params.agentId ?? undefined, params.conversationId ?? undefined);
77826
+ return {
77827
+ visibility: "transcript",
77828
+ message: formattedMessage,
77829
+ apiError
77830
+ };
77831
+ }
77832
+ function emitLoopErrorNotice(socket, runtime, params) {
77833
+ const decision = getLoopErrorNoticeDecision(params);
77834
+ if (decision.visibility === "debug_only") {
77835
+ debugLog("recovery", `Debug-only loop error (${params.stopReason}): ${params.message}`);
77836
+ mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
77837
+ return;
77838
+ }
77839
+ emitLoopErrorDelta(socket, runtime, {
77840
+ message: decision.message,
77841
+ stopReason: params.stopReason,
77842
+ isTerminal: params.isTerminal,
77843
+ runId: params.runId,
77844
+ agentId: params.agentId,
77845
+ conversationId: params.conversationId,
77846
+ apiError: decision.apiError
77847
+ });
77848
+ }
77694
77849
  function emitRecoverableStatusNotice(socket, runtime, params) {
77695
77850
  const visibility = getRecoverableStatusNoticeVisibility(params.kind);
77696
77851
  if (visibility === "debug_only") {
@@ -77726,6 +77881,9 @@ function emitRecoverableRetryNotice(socket, runtime, params) {
77726
77881
  }
77727
77882
  var DESKTOP_DEBUG_PANEL_INFO_PREFIX = "[LETTA_DESKTOP_DEBUG_PANEL_INFO]";
77728
77883
  var init_recoverable_notices = __esm(async () => {
77884
+ init_error();
77885
+ init_turn_recovery_policy();
77886
+ init_errorFormatter();
77729
77887
  init_debug();
77730
77888
  await init_protocol_outbound();
77731
77889
  });
@@ -79309,13 +79467,15 @@ async function drainRecoveryStreamWithEmission(recoveryStream, socket, runtime,
79309
79467
  }
79310
79468
  }
79311
79469
  if (errorInfo) {
79312
- emitLoopErrorDelta(socket, runtime, {
79470
+ emitLoopErrorNotice(socket, runtime, {
79313
79471
  message: errorInfo.message || "Stream error",
79314
79472
  stopReason: errorInfo.error_type || "error",
79315
79473
  isTerminal: false,
79316
79474
  runId: runtime.activeRunId || errorInfo.run_id,
79317
79475
  agentId: params.agentId ?? undefined,
79318
- conversationId: params.conversationId
79476
+ conversationId: params.conversationId,
79477
+ errorInfo,
79478
+ abortSignal: params.abortSignal
79319
79479
  });
79320
79480
  }
79321
79481
  if (shouldOutput) {
@@ -79366,7 +79526,7 @@ function finalizeHandledRecoveryTurn(runtime, socket, params) {
79366
79526
  const runId = runtime.activeRunId;
79367
79527
  clearActiveRunState(runtime);
79368
79528
  emitRuntimeStateUpdates(runtime, scope);
79369
- emitLoopErrorDelta(socket, runtime, {
79529
+ emitLoopErrorNotice(socket, runtime, {
79370
79530
  message: `Recovery continuation ended unexpectedly: ${terminalStopReason}`,
79371
79531
  stopReason: terminalStopReason,
79372
79532
  isTerminal: true,
@@ -79703,7 +79863,8 @@ var init_recovery = __esm(async () => {
79703
79863
  init_approval_suggestions(),
79704
79864
  init_interrupts(),
79705
79865
  init_protocol_outbound(),
79706
- init_queue()
79866
+ init_queue(),
79867
+ init_recoverable_notices()
79707
79868
  ]);
79708
79869
  });
79709
79870
 
@@ -80004,8 +80165,8 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
80004
80165
  throw new Error("Cancelled by user");
80005
80166
  }
80006
80167
  }
80007
- const detail = await fetchRunErrorDetail(runtime.activeRunId);
80008
- throw new Error(detail || `Pre-stream approval conflict after ${preStreamRecoveryAttempts} recovery attempts`);
80168
+ const runErrorInfo = await fetchRunErrorInfo(runtime.activeRunId);
80169
+ throw Object.assign(new Error(runErrorInfo?.detail || runErrorInfo?.message || `Pre-stream approval conflict after ${preStreamRecoveryAttempts} recovery attempts`), { runErrorInfo });
80009
80170
  }
80010
80171
  if (action === "retry_transient") {
80011
80172
  runtime.isRecoveringApprovals = true;
@@ -80138,8 +80299,8 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
80138
80299
  }
80139
80300
  continue;
80140
80301
  }
80141
- const detail = await fetchRunErrorDetail(runtime.activeRunId);
80142
- throw new Error(detail || `Approval continuation conflict after ${preStreamRecoveryAttempts} recovery attempts`);
80302
+ const runErrorInfo = await fetchRunErrorInfo(runtime.activeRunId);
80303
+ throw Object.assign(new Error(runErrorInfo?.detail || runErrorInfo?.message || `Approval continuation conflict after ${preStreamRecoveryAttempts} recovery attempts`), { runErrorInfo });
80143
80304
  }
80144
80305
  if (action === "retry_transient") {
80145
80306
  runtime.isRecoveringApprovals = true;
@@ -80265,7 +80426,7 @@ async function handleApprovalStop(params) {
80265
80426
  agent_id: agentId,
80266
80427
  conversation_id: conversationId
80267
80428
  });
80268
- emitLoopErrorDelta(socket, runtime, {
80429
+ emitLoopErrorNotice(socket, runtime, {
80269
80430
  message: "requires_approval stop returned no approvals",
80270
80431
  stopReason: "error",
80271
80432
  isTerminal: true,
@@ -80568,6 +80729,7 @@ var init_turn_approval = __esm(async () => {
80568
80729
  init_interrupts(),
80569
80730
  init_protocol_outbound(),
80570
80731
  init_queue(),
80732
+ init_recoverable_notices(),
80571
80733
  init_recovery(),
80572
80734
  init_send()
80573
80735
  ]);
@@ -80899,13 +81061,16 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
80899
81061
  }
80900
81062
  if (errorInfo) {
80901
81063
  latestErrorText = errorInfo.message || latestErrorText;
80902
- emitLoopErrorDelta(socket, runtime, {
81064
+ emitLoopErrorNotice(socket, runtime, {
80903
81065
  message: errorInfo.message || "Stream error",
80904
81066
  stopReason: errorInfo.error_type || "error",
80905
81067
  isTerminal: false,
80906
81068
  runId: runId || errorInfo.run_id,
80907
81069
  agentId,
80908
- conversationId
81070
+ conversationId,
81071
+ errorInfo,
81072
+ cancelRequested: runtime.cancelRequested,
81073
+ abortSignal: turnAbortSignal
80909
81074
  });
80910
81075
  }
80911
81076
  if (shouldOutput) {
@@ -80965,7 +81130,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
80965
81130
  }
80966
81131
  if (stopReason !== "requires_approval") {
80967
81132
  const lastRunId = runId || msgRunIds[msgRunIds.length - 1] || null;
80968
- const errorDetail = latestErrorText || (lastRunId ? await fetchRunErrorDetail(lastRunId) : null);
81133
+ const runErrorInfo = lastRunId ? await fetchRunErrorInfo(lastRunId) : null;
81134
+ const errorDetail = latestErrorText || runErrorInfo?.detail || runErrorInfo?.message || null;
80969
81135
  if (shouldAttemptPostStopApprovalRecovery({
80970
81136
  stopReason,
80971
81137
  runIdsSeen: msgRunIds.length,
@@ -81127,13 +81293,16 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
81127
81293
  conversation_id: conversationId
81128
81294
  });
81129
81295
  const errorMessage = errorDetail || `Unexpected stop reason: ${stopReason}`;
81130
- emitLoopErrorDelta(socket, runtime, {
81296
+ emitLoopErrorNotice(socket, runtime, {
81131
81297
  message: errorMessage,
81132
81298
  stopReason: effectiveStopReason,
81133
81299
  isTerminal: true,
81134
81300
  runId,
81135
81301
  agentId,
81136
- conversationId
81302
+ conversationId,
81303
+ runErrorInfo: runErrorInfo ?? undefined,
81304
+ cancelRequested: runtime.cancelRequested,
81305
+ abortSignal: turnAbortSignal
81137
81306
  });
81138
81307
  break;
81139
81308
  }
@@ -81217,12 +81386,15 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
81217
81386
  conversation_id: conversationId
81218
81387
  });
81219
81388
  const errorMessage = error instanceof Error ? error.message : String(error);
81220
- emitLoopErrorDelta(socket, runtime, {
81389
+ emitLoopErrorNotice(socket, runtime, {
81221
81390
  message: errorMessage,
81222
81391
  stopReason: "error",
81223
81392
  isTerminal: true,
81224
81393
  agentId: agentId || undefined,
81225
- conversationId
81394
+ conversationId,
81395
+ error,
81396
+ cancelRequested: runtime.cancelRequested,
81397
+ abortSignal: turnAbortSignal
81226
81398
  });
81227
81399
  if (isDebugEnabled()) {
81228
81400
  console.error("[Listen] Error handling message:", error);
@@ -81829,7 +82001,8 @@ function emitLoopErrorDelta(socket, runtime, params) {
81829
82001
  ...createLifecycleMessageBase("loop_error", params.runId),
81830
82002
  message: params.message,
81831
82003
  stop_reason: params.stopReason,
81832
- is_terminal: params.isTerminal
82004
+ is_terminal: params.isTerminal,
82005
+ ...params.apiError ? { api_error: params.apiError } : {}
81833
82006
  }, {
81834
82007
  agent_id: params.agentId,
81835
82008
  conversation_id: params.conversationId
@@ -83072,12 +83245,13 @@ function handleModeChange(msg, socket, runtime, scope) {
83072
83245
  }
83073
83246
  } catch (error) {
83074
83247
  trackListenerError("listener_mode_change_failed", error, "listener_mode_change");
83075
- emitLoopErrorDelta(socket, runtime, {
83248
+ emitLoopErrorNotice(socket, runtime, {
83076
83249
  message: error instanceof Error ? error.message : "Mode change failed",
83077
83250
  stopReason: "error",
83078
83251
  isTerminal: false,
83079
83252
  agentId: scope?.agent_id,
83080
- conversationId: scope?.conversation_id
83253
+ conversationId: scope?.conversation_id,
83254
+ error
83081
83255
  });
83082
83256
  if (isDebugEnabled()) {
83083
83257
  console.error("[Listen] Mode change failed:", error);
@@ -83827,6 +84001,7 @@ async function handleAbortMessageInput(listener, params, deps = {}) {
83827
84001
  }
83828
84002
  const interruptedRunId = scopedRuntime.activeRunId;
83829
84003
  scopedRuntime.cancelRequested = true;
84004
+ const pendingRequestsSnapshot = hasPendingApprovals ? resolvedDeps.getPendingControlRequests(listener, scope) : [];
83830
84005
  if (scopedRuntime.activeExecutingToolCallIds.length > 0 && (!scopedRuntime.pendingInterruptedResults || scopedRuntime.pendingInterruptedResults.length === 0)) {
83831
84006
  scopedRuntime.pendingInterruptedResults = scopedRuntime.activeExecutingToolCallIds.map((toolCallId) => ({
83832
84007
  type: "tool",
@@ -83872,9 +84047,8 @@ async function handleAbortMessageInput(listener, params, deps = {}) {
83872
84047
  agentId: scope.agent_id,
83873
84048
  conversationId: scope.conversation_id
83874
84049
  });
83875
- } else if (hasPendingApprovals) {
83876
- const pendingRequests = resolvedDeps.getPendingControlRequests(listener, scope);
83877
- scopedRuntime.pendingInterruptedResults = pendingRequests.map((req) => ({
84050
+ } else if (hasPendingApprovals && (!scopedRuntime.pendingInterruptedResults || scopedRuntime.pendingInterruptedResults.length === 0) && pendingRequestsSnapshot.length > 0) {
84051
+ scopedRuntime.pendingInterruptedResults = pendingRequestsSnapshot.map((req) => ({
83878
84052
  type: "approval",
83879
84053
  tool_call_id: req.request.tool_call_id,
83880
84054
  approve: false,
@@ -83885,6 +84059,7 @@ async function handleAbortMessageInput(listener, params, deps = {}) {
83885
84059
  conversationId: scope.conversation_id,
83886
84060
  continuationEpoch: scopedRuntime.continuationEpoch
83887
84061
  };
84062
+ scopedRuntime.pendingInterruptedToolCallIds = null;
83888
84063
  resolvedDeps.emitInterruptedStatusDelta(params.socket, scopedRuntime, {
83889
84064
  runId: interruptedRunId,
83890
84065
  agentId: scope.agent_id,
@@ -83929,12 +84104,13 @@ async function handleCwdChange(msg, socket, runtime) {
83929
84104
  conversation_id: conversationId
83930
84105
  });
83931
84106
  } catch (error) {
83932
- emitLoopErrorDelta(socket, runtime, {
84107
+ emitLoopErrorNotice(socket, runtime, {
83933
84108
  message: error instanceof Error ? error.message : "Working directory change failed",
83934
84109
  stopReason: "error",
83935
84110
  isTerminal: false,
83936
84111
  agentId,
83937
- conversationId
84112
+ conversationId,
84113
+ error
83938
84114
  });
83939
84115
  }
83940
84116
  }
@@ -84153,7 +84329,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
84153
84329
  return;
84154
84330
  }
84155
84331
  if (parsed.type === "__invalid_input") {
84156
- emitLoopErrorDelta(socket, runtime, {
84332
+ emitLoopErrorNotice(socket, runtime, {
84157
84333
  message: parsed.reason,
84158
84334
  stopReason: "error",
84159
84335
  isTerminal: false,
@@ -84196,7 +84372,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
84196
84372
  }
84197
84373
  const inputPayload = parsed.payload;
84198
84374
  if (inputPayload.kind !== "create_message") {
84199
- emitLoopErrorDelta(socket, runtime, {
84375
+ emitLoopErrorNotice(socket, runtime, {
84200
84376
  message: `Unsupported input payload kind: ${String(inputPayload.kind)}`,
84201
84377
  stopReason: "error",
84202
84378
  isTerminal: false,
@@ -84213,7 +84389,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
84213
84389
  };
84214
84390
  const hasApprovalPayload = incoming.messages.some((payload) => ("type" in payload) && payload.type === "approval");
84215
84391
  if (hasApprovalPayload) {
84216
- emitLoopErrorDelta(socket, runtime, {
84392
+ emitLoopErrorNotice(socket, runtime, {
84217
84393
  message: "Protocol violation: approval payloads are not allowed in input.kind=create_message. Use input.kind=approval_response.",
84218
84394
  stopReason: "error",
84219
84395
  isTerminal: false,
@@ -84770,12 +84946,13 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
84770
84946
  if (!parsedScope) {
84771
84947
  return;
84772
84948
  }
84773
- emitLoopErrorDelta(socket, runtime, {
84949
+ emitLoopErrorNotice(socket, runtime, {
84774
84950
  message: error instanceof Error ? error.message : "Failed to process listener message",
84775
84951
  stopReason: "error",
84776
84952
  isTerminal: false,
84777
84953
  agentId: parsedScope.agent_id,
84778
- conversationId: parsedScope.conversation_id
84954
+ conversationId: parsedScope.conversation_id,
84955
+ error
84779
84956
  });
84780
84957
  }
84781
84958
  });
@@ -85073,6 +85250,7 @@ var init_client4 = __esm(async () => {
85073
85250
  init_protocol_inbound(),
85074
85251
  init_protocol_outbound(),
85075
85252
  init_queue(),
85253
+ init_recoverable_notices(),
85076
85254
  init_recovery(),
85077
85255
  init_send(),
85078
85256
  init_turn(),
@@ -152557,4 +152735,4 @@ Error during initialization: ${message}`);
152557
152735
  }
152558
152736
  main();
152559
152737
 
152560
- //# debugId=275910C1663139CA64756E2164756E21
152738
+ //# debugId=AA1793542E1A081B64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.21.10",
3
+ "version": "0.21.11",
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": {