@letta-ai/letta-code 0.32.6 → 0.32.7

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
@@ -5515,7 +5515,7 @@ var package_default;
5515
5515
  var init_package = __esm(() => {
5516
5516
  package_default = {
5517
5517
  name: "@letta-ai/letta-code",
5518
- version: "0.32.6",
5518
+ version: "0.32.7",
5519
5519
  lettaStartupLogProtocol: 1,
5520
5520
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5521
5521
  type: "module",
@@ -101244,6 +101244,8 @@ function createConversationRuntime(listener, agentId, conversationId) {
101244
101244
  pendingApprovalResolvers: new Map,
101245
101245
  recoveredApprovalState: null,
101246
101246
  syncApprovalRecoveryCompleted: false,
101247
+ expectedTeleportId: null,
101248
+ expectedTeleportExpiresAt: null,
101247
101249
  get lastStopReason() {
101248
101250
  return turnLifecycle.lastStopReason;
101249
101251
  },
@@ -101319,6 +101321,8 @@ function clearConversationRuntimeState(runtime) {
101319
101321
  runtime.pendingInterruptedResults = null;
101320
101322
  runtime.pendingInterruptedContext = null;
101321
101323
  runtime.pendingInterruptedToolCallIds = null;
101324
+ runtime.expectedTeleportId = null;
101325
+ runtime.expectedTeleportExpiresAt = null;
101322
101326
  runtime.dequeuedClientMessageIdsByBatchId.clear();
101323
101327
  runtime.continuationEpoch += 1;
101324
101328
  runtime.pendingTurns = 0;
@@ -122333,6 +122337,17 @@ function actingUserRequestOptions(actingUserId) {
122333
122337
  var ACTING_USER_ID_HEADER = "X-Letta-Acting-User-Id", ACTING_USER_ID_ENV = "LETTA_ACTING_USER_ID";
122334
122338
 
122335
122339
  // src/backend/api/agent-message.ts
122340
+ function normalizeAgentMessageComputer(value) {
122341
+ if (value == null)
122342
+ return;
122343
+ if (typeof value !== "string") {
122344
+ throw new Error("computer must be a computer name, or omitted to use the conversation's current destination.");
122345
+ }
122346
+ const computer = value.trim();
122347
+ if (!computer)
122348
+ return;
122349
+ return ["cloud", "cloud-sandbox"].includes(computer.toLowerCase()) ? "cloud" : computer;
122350
+ }
122336
122351
  function buildAgentSendContent(sender, noWait, message) {
122337
122352
  const reminder = buildAgentSendReminder(sender, noWait);
122338
122353
  return [
@@ -122454,9 +122469,7 @@ async function send_agent_message(args, deps = {}) {
122454
122469
  }
122455
122470
  if (!args.message?.trim())
122456
122471
  throw new Error("Message must not be empty.");
122457
- if (args.computer !== undefined && !args.computer.trim()) {
122458
- throw new Error("Computer selector must not be empty.");
122459
- }
122472
+ const computer = normalizeAgentMessageComputer(args.computer);
122460
122473
  const context3 = getRuntimeContext();
122461
122474
  const sender = {
122462
122475
  agentId: validateAddress(context3?.agentId ?? undefined, "agent"),
@@ -122479,12 +122492,11 @@ async function send_agent_message(args, deps = {}) {
122479
122492
  }, backend, signal);
122480
122493
  signal.throwIfAborted();
122481
122494
  submissionAttempted = true;
122482
- const computer = args.computer;
122483
122495
  const receipt = await (deps.enqueue ?? enqueueConversationMessage)({
122484
122496
  ...destination,
122485
122497
  clientMessageId,
122486
122498
  content: buildAgentSendContent(sender, true, args.message),
122487
- computer: computer && ["cloud", "cloud-sandbox"].includes(computer.trim().toLowerCase()) ? "cloud" : computer,
122499
+ computer,
122488
122500
  actingUserId
122489
122501
  }, signal);
122490
122502
  return {
@@ -126548,8 +126560,8 @@ var init_SendAgentMessage2 = __esm(() => {
126548
126560
  description: "The existing message thread to send to. Each conversation has its own message history. A conv-... ID is sufficient; to use an agent's default thread, also supply agent_id."
126549
126561
  },
126550
126562
  computer: {
126551
- type: "string",
126552
- description: "Optional computer where the recipient should run: cloud, an online computer name, or its stable device ID. Omit to use its active computer or saved destination (a computer or Cloud sandbox). An offline saved computer does not trigger a Cloud-sandbox fallback."
126563
+ type: ["string", "null"],
126564
+ description: "Optional computer where the recipient should run: cloud, an online computer name, or its stable device ID. Omitted, null, and blank values use its active computer or saved destination (a computer or Cloud sandbox). An offline saved computer does not trigger a Cloud-sandbox fallback."
126553
126565
  }
126554
126566
  },
126555
126567
  required: ["message"],
@@ -222814,7 +222826,7 @@ function isRuntimeStartCommand(value) {
222814
222826
  if (!value || typeof value !== "object")
222815
222827
  return false;
222816
222828
  const c = value;
222817
- return c.type === "runtime_start" && typeof c.request_id === "string" && (c.agent_id === undefined || typeof c.agent_id === "string") && (c.create_agent === undefined || isRuntimeStartCreateAgentOptions(c.create_agent)) && (c.conversation_id === undefined || typeof c.conversation_id === "string") && (c.create_conversation === undefined || isRuntimeStartCreateConversationOptions(c.create_conversation)) && (c.conversation_source_tags === undefined || isStringArray8(c.conversation_source_tags)) && (c.cwd === undefined || c.cwd === null || typeof c.cwd === "string") && (c.mode === undefined || isDevicePermissionMode(c.mode)) && (c.execution_settings === undefined || isRuntimeExecutionSettings(c.execution_settings)) && (c.workspace_sandbox === undefined || isRuntimeStartWorkspaceSandbox(c.workspace_sandbox)) && (c.skill_sources === undefined || isSkillSourceArray(c.skill_sources)) && (c.preserve_skill_sources === undefined || typeof c.preserve_skill_sources === "boolean") && (c.client_info === undefined || isRuntimeStartClientInfo(c.client_info)) && (c.recover_approvals === undefined || typeof c.recover_approvals === "boolean") && (c.force_device_status === undefined || typeof c.force_device_status === "boolean") && (c.wait_for_replay === undefined || typeof c.wait_for_replay === "boolean") && (c.external_tools === undefined || Array.isArray(c.external_tools) && c.external_tools.every(isRuntimeStartExternalToolsGroup));
222829
+ return c.type === "runtime_start" && typeof c.request_id === "string" && (c.agent_id === undefined || typeof c.agent_id === "string") && (c.create_agent === undefined || isRuntimeStartCreateAgentOptions(c.create_agent)) && (c.conversation_id === undefined || typeof c.conversation_id === "string") && (c.create_conversation === undefined || isRuntimeStartCreateConversationOptions(c.create_conversation)) && (c.conversation_source_tags === undefined || isStringArray8(c.conversation_source_tags)) && (c.cwd === undefined || c.cwd === null || typeof c.cwd === "string") && (c.mode === undefined || isDevicePermissionMode(c.mode)) && (c.execution_settings === undefined || isRuntimeExecutionSettings(c.execution_settings)) && (c.workspace_sandbox === undefined || isRuntimeStartWorkspaceSandbox(c.workspace_sandbox)) && (c.skill_sources === undefined || isSkillSourceArray(c.skill_sources)) && (c.preserve_skill_sources === undefined || typeof c.preserve_skill_sources === "boolean") && (c.client_info === undefined || isRuntimeStartClientInfo(c.client_info)) && (c.recover_approvals === undefined || typeof c.recover_approvals === "boolean") && (c.force_device_status === undefined || typeof c.force_device_status === "boolean") && (c.wait_for_replay === undefined || typeof c.wait_for_replay === "boolean") && (c.teleport_id === undefined || typeof c.teleport_id === "string") && (c.external_tools === undefined || Array.isArray(c.external_tools) && c.external_tools.every(isRuntimeStartExternalToolsGroup));
222818
222830
  }
222819
222831
  function isRuntimeStartCreateAgentOptions(value) {
222820
222832
  if (!isObjectRecord2(value))
@@ -397765,6 +397777,497 @@ function assertRuntimeWorkspaceSandboxChangeAllowed(listener, runtime, next) {
397765
397777
  }
397766
397778
  }
397767
397779
 
397780
+ // src/channels/teleport-guard.ts
397781
+ function getLocalChannelTeleportError(scope) {
397782
+ const channels = getSupportedChannelIds().filter((channelId) => {
397783
+ return readRoutes(channelId).some((route) => route.agentId === scope.agentId && route.conversationId === scope.conversationId && route.enabled !== false && route.outboundEnabled !== false);
397784
+ });
397785
+ if (channels.length === 0)
397786
+ return null;
397787
+ return `This conversation is bound to ${channels.join(", ")} on this computer. Teleport is blocked because MessageChannel cannot follow the conversation to another computer yet. Remove the channel route or continue locally.`;
397788
+ }
397789
+ var init_teleport_guard = __esm(() => {
397790
+ init_plugin_registry();
397791
+ init_routing();
397792
+ });
397793
+
397794
+ // src/websocket/listener/recoverable-notices.ts
397795
+ function getRecoverableStatusNoticeVisibility(kind) {
397796
+ switch (kind) {
397797
+ case "stale_approval_conflict_recovery":
397798
+ return "debug_only";
397799
+ default:
397800
+ return "transcript";
397801
+ }
397802
+ }
397803
+ function getRecoverableRetryNoticeVisibility(kind) {
397804
+ switch (kind) {
397805
+ case "transient_provider_retry":
397806
+ return "transcript";
397807
+ default:
397808
+ return "transcript";
397809
+ }
397810
+ }
397811
+ function isDesktopDebugPanelMirrorEnabled() {
397812
+ return process.env.LETTA_DESKTOP_MODE === "1";
397813
+ }
397814
+ function mirrorRecoverableNoticeToDesktopDebugPanel(message) {
397815
+ if (!isDesktopDebugPanelMirrorEnabled()) {
397816
+ return;
397817
+ }
397818
+ try {
397819
+ process.stderr.write(`${DESKTOP_DEBUG_PANEL_INFO_PREFIX} ${message}
397820
+ `);
397821
+ } catch {}
397822
+ }
397823
+ function toStructuredApiError(errorInfo) {
397824
+ if (!errorInfo?.error_type || !errorInfo.run_id) {
397825
+ return;
397826
+ }
397827
+ return {
397828
+ message_type: "error_message",
397829
+ message: errorInfo.message || errorInfo.detail || "An error occurred",
397830
+ error_type: errorInfo.error_type,
397831
+ run_id: errorInfo.run_id,
397832
+ ...errorInfo.detail ? { detail: errorInfo.detail } : {}
397833
+ };
397834
+ }
397835
+ function getStructuredApiErrorFromError(error4) {
397836
+ if (!(error4 instanceof Error)) {
397837
+ return;
397838
+ }
397839
+ const errorWithStructuredInfo = error4;
397840
+ return errorWithStructuredInfo.apiError ?? toStructuredApiError(errorWithStructuredInfo.runErrorInfo);
397841
+ }
397842
+ function buildStructuredFormatInput(apiError) {
397843
+ return {
397844
+ error: {
397845
+ error: {
397846
+ type: apiError.error_type,
397847
+ message: apiError.message,
397848
+ ...apiError.detail ? { detail: apiError.detail } : {}
397849
+ },
397850
+ run_id: apiError.run_id
397851
+ }
397852
+ };
397853
+ }
397854
+ function isAbortLikeError(error4) {
397855
+ if (error4 instanceof APIUserAbortError) {
397856
+ return true;
397857
+ }
397858
+ if (!(error4 instanceof Error)) {
397859
+ return false;
397860
+ }
397861
+ const errorWithCode = error4;
397862
+ return error4.name === "AbortError" || error4.message === "The operation was aborted" || errorWithCode.code === "ABORT_ERR";
397863
+ }
397864
+ function isTerminatedProcessNoise(message) {
397865
+ return message.trim().toLowerCase() === "terminated";
397866
+ }
397867
+ function isProxyTransportError(detail, error4, message) {
397868
+ if (error4 instanceof APIError && error4.status >= 500 && detail.toLowerCase().includes("trying to proxy")) {
397869
+ return true;
397870
+ }
397871
+ return detail.toLowerCase().includes("error occurred while trying to proxy") || message.toLowerCase().includes("error occurred while trying to proxy");
397872
+ }
397873
+ function getLoopErrorNoticeDecision(params) {
397874
+ const apiError = params.apiError ?? toStructuredApiError(params.errorInfo) ?? toStructuredApiError(params.runErrorInfo) ?? getStructuredApiErrorFromError(params.error);
397875
+ const detail = apiError?.detail ?? params.errorInfo?.detail ?? params.runErrorInfo?.detail ?? extractConflictDetail(params.error) ?? "";
397876
+ if (params.cancelRequested || params.abortSignal?.aborted || isAbortLikeError(params.error) || isTerminatedProcessNoise(params.message)) {
397877
+ return {
397878
+ visibility: "debug_only",
397879
+ message: params.message
397880
+ };
397881
+ }
397882
+ const cloudflareMessage = checkCloudflareEdgeError(detail) ?? checkCloudflareEdgeError(params.message);
397883
+ if (cloudflareMessage) {
397884
+ return {
397885
+ visibility: "transcript",
397886
+ message: cloudflareMessage,
397887
+ apiError
397888
+ };
397889
+ }
397890
+ if (isProxyTransportError(detail, params.error, params.message)) {
397891
+ return {
397892
+ visibility: "transcript",
397893
+ message: "Connection to Letta service failed. Please retry.",
397894
+ apiError
397895
+ };
397896
+ }
397897
+ const formattedMessage = formatErrorDetails2(apiError ? buildStructuredFormatInput(apiError) : params.error ?? params.message, params.agentId ?? undefined, params.conversationId ?? undefined, {
397898
+ surface: params.surface,
397899
+ unclassifiedFallback: params.unclassifiedFallback
397900
+ });
397901
+ return {
397902
+ visibility: "transcript",
397903
+ message: formattedMessage,
397904
+ apiError
397905
+ };
397906
+ }
397907
+ function getTranscriptLoopErrorMessage(params) {
397908
+ const decision = getLoopErrorNoticeDecision({
397909
+ ...params,
397910
+ surface: "plain",
397911
+ unclassifiedFallback: "generic"
397912
+ });
397913
+ return decision.visibility === "transcript" ? decision.message : undefined;
397914
+ }
397915
+ function getConsumerLoopErrorMessage(params) {
397916
+ const decision = getLoopErrorNoticeDecision({
397917
+ ...params,
397918
+ surface: "plain"
397919
+ });
397920
+ return decision.visibility === "transcript" ? decision.message : undefined;
397921
+ }
397922
+ function emitLoopErrorNotice(socket, runtime, params) {
397923
+ const decision = getLoopErrorNoticeDecision(params);
397924
+ if (decision.visibility === "debug_only") {
397925
+ debugLog("recovery", `Debug-only loop error (${params.stopReason}): ${params.message}`);
397926
+ mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
397927
+ return null;
397928
+ }
397929
+ emitLoopErrorDelta(socket, runtime, {
397930
+ message: decision.message,
397931
+ stopReason: params.stopReason,
397932
+ isTerminal: params.isTerminal,
397933
+ runId: params.runId,
397934
+ agentId: params.agentId,
397935
+ conversationId: params.conversationId,
397936
+ apiError: decision.apiError
397937
+ });
397938
+ return decision.message;
397939
+ }
397940
+ function emitRecoverableStatusNotice(socket, runtime, params) {
397941
+ const visibility = getRecoverableStatusNoticeVisibility(params.kind);
397942
+ if (visibility === "debug_only") {
397943
+ debugLog("recovery", `Debug-only lifecycle notice (${params.kind}): ${params.message}`);
397944
+ mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
397945
+ return;
397946
+ }
397947
+ emitStatusDelta(socket, runtime, {
397948
+ message: params.message,
397949
+ level: params.level,
397950
+ runId: params.runId,
397951
+ agentId: params.agentId,
397952
+ conversationId: params.conversationId
397953
+ });
397954
+ }
397955
+ function emitRecoverableRetryNotice(socket, runtime, params) {
397956
+ const visibility = getRecoverableRetryNoticeVisibility(params.kind);
397957
+ if (visibility === "debug_only") {
397958
+ debugLog("recovery", `Debug-only retry notice (${params.kind}, attempt ${params.attempt}/${params.maxAttempts}): ${params.message}`);
397959
+ mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
397960
+ return;
397961
+ }
397962
+ emitRetryDelta(socket, runtime, {
397963
+ message: params.message,
397964
+ reason: params.reason,
397965
+ attempt: params.attempt,
397966
+ maxAttempts: params.maxAttempts,
397967
+ delayMs: params.delayMs,
397968
+ runId: params.runId,
397969
+ agentId: params.agentId,
397970
+ conversationId: params.conversationId
397971
+ });
397972
+ }
397973
+ var DESKTOP_DEBUG_PANEL_INFO_PREFIX = "[LETTA_DESKTOP_DEBUG_PANEL_INFO]";
397974
+ var init_recoverable_notices = __esm(() => {
397975
+ init_error();
397976
+ init_turn_recovery_policy();
397977
+ init_error_formatter();
397978
+ init_debug();
397979
+ init_protocol_outbound();
397980
+ });
397981
+
397982
+ // src/websocket/listener/teleport.ts
397983
+ function expectInboundTeleport(runtime, teleportId) {
397984
+ runtime.expectedTeleportId = teleportId;
397985
+ runtime.expectedTeleportExpiresAt = Date.now() + INBOUND_TELEPORT_CONTINUE_TTL_MS;
397986
+ }
397987
+ function isInboundTeleportExpected(runtime) {
397988
+ if (runtime.expectedTeleportId === null)
397989
+ return false;
397990
+ if (runtime.expectedTeleportExpiresAt !== null && runtime.expectedTeleportExpiresAt <= Date.now()) {
397991
+ clearExpectedInboundTeleport(runtime);
397992
+ return false;
397993
+ }
397994
+ return true;
397995
+ }
397996
+ function clearExpectedInboundTeleport(runtime) {
397997
+ runtime.expectedTeleportId = null;
397998
+ runtime.expectedTeleportExpiresAt = null;
397999
+ }
398000
+ function buildTeleportContinuationMessages(params) {
398001
+ return [
398002
+ {
398003
+ type: "approval",
398004
+ approvals: params.approvals,
398005
+ otid: params.teleportId
398006
+ },
398007
+ {
398008
+ role: "system",
398009
+ content: "<system-reminder>Teleportation to this environment is complete. Continue the existing task from this environment now.</system-reminder>",
398010
+ otid: `${params.teleportId}:continue`
398011
+ }
398012
+ ];
398013
+ }
398014
+ function escapeSystemReminderText(value) {
398015
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
398016
+ }
398017
+ function buildTeleportFailureMessages(params) {
398018
+ const messages = [];
398019
+ if (params.approvals && params.approvals.length > 0) {
398020
+ messages.push({
398021
+ type: "approval",
398022
+ approvals: params.approvals,
398023
+ otid: params.teleportId
398024
+ });
398025
+ }
398026
+ messages.push({
398027
+ role: "system",
398028
+ content: `<system-reminder>Teleportation failed.
398029
+
398030
+ Error: ${escapeSystemReminderText(params.error)}
398031
+
398032
+ Continue the existing task from this environment now.</system-reminder>`,
398033
+ otid: `${params.teleportId}:failed`
398034
+ });
398035
+ return messages;
398036
+ }
398037
+ function getPendingTeleports(runtime) {
398038
+ runtime.pendingTeleports ??= new Map;
398039
+ return runtime.pendingTeleports;
398040
+ }
398041
+ function findPendingTeleportForRuntime(runtime, agentId, conversationId) {
398042
+ for (const pending of getPendingTeleports(runtime).values()) {
398043
+ if (pending.agentId === agentId && pending.conversationId === conversationId && pending.readyAt === undefined) {
398044
+ return pending;
398045
+ }
398046
+ }
398047
+ return null;
398048
+ }
398049
+ function isRuntimeTeleportPending(runtime, agentId, conversationId) {
398050
+ if (!agentId)
398051
+ return false;
398052
+ return [...runtime.pendingTeleports?.values() ?? []].some((pending) => !pending.error && pending.agentId === agentId && pending.conversationId === conversationId);
398053
+ }
398054
+ function clearPriorReadyTeleports(params) {
398055
+ const pendingTeleports = params.listener.pendingTeleports;
398056
+ if (!pendingTeleports)
398057
+ return;
398058
+ for (const [teleportId, pending] of pendingTeleports) {
398059
+ if (teleportId === params.currentTeleportId || pending.readyAt === undefined) {
398060
+ continue;
398061
+ }
398062
+ if (pending.agentId === params.agentId && pending.conversationId === params.conversationId) {
398063
+ pendingTeleports.delete(teleportId);
398064
+ }
398065
+ }
398066
+ }
398067
+ function hasAcceptedInputsWaiting(runtime, includeQueuePump) {
398068
+ return runtime.queueRuntime.length > 0 || runtime.pendingTurns > 0 || runtime.queuedMessagesByItemId.size > 0 || includeQueuePump && (runtime.queuePumpActive || runtime.queuePumpScheduled);
398069
+ }
398070
+ function sendTeleportReady(runtime, pending, input) {
398071
+ const connection = runtime.connections.get(pending.connectionId);
398072
+ if (!connection || !isListenerTransportOpen(connection.writer))
398073
+ return false;
398074
+ const mode = getOrCreateConversationPermissionModeStateRef(runtime, pending.agentId, pending.conversationId).mode;
398075
+ const message = {
398076
+ type: "teleport_ready",
398077
+ teleport_id: pending.teleportId,
398078
+ runtime: {
398079
+ agent_id: pending.agentId,
398080
+ conversation_id: pending.conversationId
398081
+ },
398082
+ success: input.success,
398083
+ active_turn: pending.activeTurn,
398084
+ mode,
398085
+ ...pending.continuation ? { continuation: pending.continuation } : {},
398086
+ ...input.error ? { error: input.error } : {}
398087
+ };
398088
+ emitProtocolV2Message(connection.writer, runtime, message, message.runtime, toListenerConnection(pending.connectionId));
398089
+ return true;
398090
+ }
398091
+ function retainTeleportForRecovery(runtime, pending) {
398092
+ const timeout = setTimeout(() => {
398093
+ const current = runtime.pendingTeleports?.get(pending.teleportId);
398094
+ if (current === pending) {
398095
+ runtime.pendingTeleports?.delete(pending.teleportId);
398096
+ }
398097
+ }, TELEPORT_RECOVERY_TTL_MS);
398098
+ timeout.unref?.();
398099
+ }
398100
+ function handleTeleportProbe(command, socket, safeSocketSend) {
398101
+ safeSocketSend(socket, {
398102
+ type: "teleport_probe_response",
398103
+ request_id: command.request_id,
398104
+ runtime: command.runtime,
398105
+ supported: resolveBackendMode() === "api",
398106
+ drains_accepted_inputs: true,
398107
+ idempotent_continuation: true
398108
+ }, "teleport_probe_response", "teleport_probe");
398109
+ }
398110
+ function handleTeleportRequest(params) {
398111
+ const { listener, command, connectionId } = params;
398112
+ const pendingTeleports = getPendingTeleports(listener);
398113
+ const existing = pendingTeleports.get(command.teleport_id);
398114
+ if (existing) {
398115
+ if (existing.readyAt !== undefined) {
398116
+ sendTeleportReady(listener, existing, {
398117
+ success: existing.error === undefined,
398118
+ error: existing.error
398119
+ });
398120
+ }
398121
+ return;
398122
+ }
398123
+ const pending = {
398124
+ teleportId: command.teleport_id,
398125
+ connectionId,
398126
+ agentId: command.runtime.agent_id,
398127
+ conversationId: command.runtime.conversation_id,
398128
+ requestedAt: Date.now(),
398129
+ drainAcceptedInputs: false,
398130
+ activeTurn: false
398131
+ };
398132
+ const channelError = getLocalChannelTeleportError(pending);
398133
+ if (channelError) {
398134
+ pending.readyAt = Date.now();
398135
+ pending.error = channelError;
398136
+ pendingTeleports.set(pending.teleportId, pending);
398137
+ sendTeleportReady(listener, pending, {
398138
+ success: false,
398139
+ error: channelError
398140
+ });
398141
+ retainTeleportForRecovery(listener, pending);
398142
+ return;
398143
+ }
398144
+ const conflicting = findPendingTeleportForRuntime(listener, pending.agentId, pending.conversationId);
398145
+ if (conflicting) {
398146
+ pendingTeleports.set(pending.teleportId, pending);
398147
+ pending.readyAt = Date.now();
398148
+ pending.error = "Conversation already has a teleport pending";
398149
+ sendTeleportReady(listener, pending, {
398150
+ success: false,
398151
+ error: pending.error
398152
+ });
398153
+ retainTeleportForRecovery(listener, pending);
398154
+ return;
398155
+ }
398156
+ pendingTeleports.set(pending.teleportId, pending);
398157
+ const conversationRuntime = getConversationRuntime(listener, pending.agentId, pending.conversationId);
398158
+ pending.drainAcceptedInputs = conversationRuntime ? hasAcceptedInputsWaiting(conversationRuntime, true) : false;
398159
+ if (!conversationRuntime?.isProcessing && !pending.drainAcceptedInputs) {
398160
+ if (sendTeleportReady(listener, pending, { success: true })) {
398161
+ pending.readyAt = Date.now();
398162
+ retainTeleportForRecovery(listener, pending);
398163
+ }
398164
+ }
398165
+ }
398166
+ function claimPendingTeleportAtBoundary(params) {
398167
+ const pending = findPendingTeleportForRuntime(params.listener, params.agentId, params.conversationId);
398168
+ if (!pending)
398169
+ return null;
398170
+ if (pending.drainAcceptedInputs) {
398171
+ if (params.activeTurn)
398172
+ return null;
398173
+ const runtime = getConversationRuntime(params.listener, params.agentId, params.conversationId);
398174
+ if (runtime && hasAcceptedInputsWaiting(runtime, false))
398175
+ return null;
398176
+ }
398177
+ const connection = params.listener.connections.get(pending.connectionId);
398178
+ if (!connection || !isListenerTransportOpen(connection.writer))
398179
+ return null;
398180
+ pending.readyAt = Date.now();
398181
+ pending.activeTurn = params.activeTurn;
398182
+ pending.continuation = params.continuation;
398183
+ return pending;
398184
+ }
398185
+ function emitClaimedTeleportReady(listener, pending) {
398186
+ const sent = sendTeleportReady(listener, pending, { success: true });
398187
+ if (sent) {
398188
+ retainTeleportForRecovery(listener, pending);
398189
+ }
398190
+ return sent;
398191
+ }
398192
+ function finishTeleport(runtime, lease, pending) {
398193
+ const transition = runtime.turnLifecycle.finish(lease, "cancelled");
398194
+ if (!transition.finished)
398195
+ return transition;
398196
+ emitRuntimeStateUpdates(runtime, {
398197
+ agent_id: pending.agentId,
398198
+ conversation_id: pending.conversationId
398199
+ });
398200
+ emitClaimedTeleportReady(runtime.listener, pending);
398201
+ return transition;
398202
+ }
398203
+ function finishPendingTeleport(runtime) {
398204
+ if (!runtime.agentId)
398205
+ return;
398206
+ const pending = findPendingTeleportForRuntime(runtime.listener, runtime.agentId, runtime.conversationId);
398207
+ if (!pending || runtime.lastStopReason !== "end_turn" && !pending.drainAcceptedInputs) {
398208
+ return;
398209
+ }
398210
+ const claimed = claimPendingTeleportAtBoundary({
398211
+ listener: runtime.listener,
398212
+ agentId: runtime.agentId,
398213
+ conversationId: runtime.conversationId,
398214
+ activeTurn: false
398215
+ });
398216
+ if (claimed)
398217
+ emitClaimedTeleportReady(runtime.listener, claimed);
398218
+ }
398219
+ function takeFailedTeleport(params) {
398220
+ const pending = params.listener.pendingTeleports?.get(params.teleportId);
398221
+ if (!pending || pending.agentId !== params.agentId || pending.conversationId !== params.conversationId) {
398222
+ return null;
398223
+ }
398224
+ params.listener.pendingTeleports?.delete(params.teleportId);
398225
+ return pending;
398226
+ }
398227
+ function handleTeleportFailure(params) {
398228
+ const pending = takeFailedTeleport({
398229
+ listener: params.listener,
398230
+ teleportId: params.command.teleport_id,
398231
+ agentId: params.command.runtime.agent_id,
398232
+ conversationId: params.command.runtime.conversation_id
398233
+ });
398234
+ if (!pending || pending.error)
398235
+ return;
398236
+ const runtime = params.getOrCreateScopedRuntime(params.listener, pending.agentId, pending.conversationId);
398237
+ emitLoopErrorNotice(params.socket, runtime, {
398238
+ message: `Teleport failed: ${params.command.error}`,
398239
+ stopReason: "error",
398240
+ isTerminal: false,
398241
+ agentId: pending.agentId,
398242
+ conversationId: pending.conversationId
398243
+ });
398244
+ params.runDetachedListenerTask("teleport_failed", async () => {
398245
+ await params.processIncomingMessage({
398246
+ type: "message",
398247
+ connectionId: pending.connectionId,
398248
+ agentId: pending.agentId,
398249
+ conversationId: pending.conversationId,
398250
+ messages: buildTeleportFailureMessages({
398251
+ teleportId: params.command.teleport_id,
398252
+ error: params.command.error,
398253
+ approvals: pending.continuation?.approvals
398254
+ })
398255
+ }, params.socket, runtime, params.onStatusChange, pending.connectionId);
398256
+ });
398257
+ }
398258
+ var TELEPORT_RECOVERY_TTL_MS, INBOUND_TELEPORT_CONTINUE_TTL_MS = 60000;
398259
+ var init_teleport = __esm(() => {
398260
+ init_backend_mode();
398261
+ init_teleport_guard();
398262
+ init_connection();
398263
+ init_permission_mode();
398264
+ init_protocol_outbound();
398265
+ init_recoverable_notices();
398266
+ init_runtime();
398267
+ init_transport();
398268
+ TELEPORT_RECOVERY_TTL_MS = 5 * 60000;
398269
+ });
398270
+
397768
398271
  // src/websocket/listener/commands/runtime-start.ts
397769
398272
  function buildDefaultConversation(agent) {
397770
398273
  const now2 = new Date().toISOString();
@@ -397984,6 +398487,9 @@ async function handleRuntimeStartCommand(parsed, context3) {
397984
398487
  assertConnectionOpen();
397985
398488
  const scopedRuntime = context3.getOrCreateScopedRuntime(context3.runtime, runtimeScope.agent_id, runtimeScope.conversation_id);
397986
398489
  await applyRuntimeStartState(parsed, context3, runtimeScope, scopedRuntime);
398490
+ if (parsed.teleport_id) {
398491
+ expectInboundTeleport(scopedRuntime, parsed.teleport_id);
398492
+ }
397987
398493
  assertConnectionOpen();
397988
398494
  subscribeListenerConnection(context3.runtime, connectionId, runtimeScope);
397989
398495
  registerRuntimeExternalTools(context3.runtime, connectionId, runtimeScope, parsed.external_tools ?? []);
@@ -398045,6 +398551,7 @@ var init_runtime_start = __esm(async () => {
398045
398551
  init_cwd_change();
398046
398552
  init_permission_mode();
398047
398553
  init_runtime_start_validation();
398554
+ init_teleport();
398048
398555
  await init_external_tools();
398049
398556
  LEGACY_SUMMARY_PREFIX_BY_SOURCE_TAG = {
398050
398557
  "channel:discord": "discord",
@@ -398923,194 +399430,6 @@ var init_interrupts = __esm(() => {
398923
399430
  STREAMING_TOOL_OUTPUT_MAX_CHARS = LIMITS.BASH_OUTPUT_CHARS;
398924
399431
  });
398925
399432
 
398926
- // src/websocket/listener/recoverable-notices.ts
398927
- function getRecoverableStatusNoticeVisibility(kind) {
398928
- switch (kind) {
398929
- case "stale_approval_conflict_recovery":
398930
- return "debug_only";
398931
- default:
398932
- return "transcript";
398933
- }
398934
- }
398935
- function getRecoverableRetryNoticeVisibility(kind) {
398936
- switch (kind) {
398937
- case "transient_provider_retry":
398938
- return "transcript";
398939
- default:
398940
- return "transcript";
398941
- }
398942
- }
398943
- function isDesktopDebugPanelMirrorEnabled() {
398944
- return process.env.LETTA_DESKTOP_MODE === "1";
398945
- }
398946
- function mirrorRecoverableNoticeToDesktopDebugPanel(message) {
398947
- if (!isDesktopDebugPanelMirrorEnabled()) {
398948
- return;
398949
- }
398950
- try {
398951
- process.stderr.write(`${DESKTOP_DEBUG_PANEL_INFO_PREFIX} ${message}
398952
- `);
398953
- } catch {}
398954
- }
398955
- function toStructuredApiError(errorInfo) {
398956
- if (!errorInfo?.error_type || !errorInfo.run_id) {
398957
- return;
398958
- }
398959
- return {
398960
- message_type: "error_message",
398961
- message: errorInfo.message || errorInfo.detail || "An error occurred",
398962
- error_type: errorInfo.error_type,
398963
- run_id: errorInfo.run_id,
398964
- ...errorInfo.detail ? { detail: errorInfo.detail } : {}
398965
- };
398966
- }
398967
- function getStructuredApiErrorFromError(error4) {
398968
- if (!(error4 instanceof Error)) {
398969
- return;
398970
- }
398971
- const errorWithStructuredInfo = error4;
398972
- return errorWithStructuredInfo.apiError ?? toStructuredApiError(errorWithStructuredInfo.runErrorInfo);
398973
- }
398974
- function buildStructuredFormatInput(apiError) {
398975
- return {
398976
- error: {
398977
- error: {
398978
- type: apiError.error_type,
398979
- message: apiError.message,
398980
- ...apiError.detail ? { detail: apiError.detail } : {}
398981
- },
398982
- run_id: apiError.run_id
398983
- }
398984
- };
398985
- }
398986
- function isAbortLikeError(error4) {
398987
- if (error4 instanceof APIUserAbortError) {
398988
- return true;
398989
- }
398990
- if (!(error4 instanceof Error)) {
398991
- return false;
398992
- }
398993
- const errorWithCode = error4;
398994
- return error4.name === "AbortError" || error4.message === "The operation was aborted" || errorWithCode.code === "ABORT_ERR";
398995
- }
398996
- function isTerminatedProcessNoise(message) {
398997
- return message.trim().toLowerCase() === "terminated";
398998
- }
398999
- function isProxyTransportError(detail, error4, message) {
399000
- if (error4 instanceof APIError && error4.status >= 500 && detail.toLowerCase().includes("trying to proxy")) {
399001
- return true;
399002
- }
399003
- return detail.toLowerCase().includes("error occurred while trying to proxy") || message.toLowerCase().includes("error occurred while trying to proxy");
399004
- }
399005
- function getLoopErrorNoticeDecision(params) {
399006
- const apiError = params.apiError ?? toStructuredApiError(params.errorInfo) ?? toStructuredApiError(params.runErrorInfo) ?? getStructuredApiErrorFromError(params.error);
399007
- const detail = apiError?.detail ?? params.errorInfo?.detail ?? params.runErrorInfo?.detail ?? extractConflictDetail(params.error) ?? "";
399008
- if (params.cancelRequested || params.abortSignal?.aborted || isAbortLikeError(params.error) || isTerminatedProcessNoise(params.message)) {
399009
- return {
399010
- visibility: "debug_only",
399011
- message: params.message
399012
- };
399013
- }
399014
- const cloudflareMessage = checkCloudflareEdgeError(detail) ?? checkCloudflareEdgeError(params.message);
399015
- if (cloudflareMessage) {
399016
- return {
399017
- visibility: "transcript",
399018
- message: cloudflareMessage,
399019
- apiError
399020
- };
399021
- }
399022
- if (isProxyTransportError(detail, params.error, params.message)) {
399023
- return {
399024
- visibility: "transcript",
399025
- message: "Connection to Letta service failed. Please retry.",
399026
- apiError
399027
- };
399028
- }
399029
- const formattedMessage = formatErrorDetails2(apiError ? buildStructuredFormatInput(apiError) : params.error ?? params.message, params.agentId ?? undefined, params.conversationId ?? undefined, {
399030
- surface: params.surface,
399031
- unclassifiedFallback: params.unclassifiedFallback
399032
- });
399033
- return {
399034
- visibility: "transcript",
399035
- message: formattedMessage,
399036
- apiError
399037
- };
399038
- }
399039
- function getTranscriptLoopErrorMessage(params) {
399040
- const decision = getLoopErrorNoticeDecision({
399041
- ...params,
399042
- surface: "plain",
399043
- unclassifiedFallback: "generic"
399044
- });
399045
- return decision.visibility === "transcript" ? decision.message : undefined;
399046
- }
399047
- function getConsumerLoopErrorMessage(params) {
399048
- const decision = getLoopErrorNoticeDecision({
399049
- ...params,
399050
- surface: "plain"
399051
- });
399052
- return decision.visibility === "transcript" ? decision.message : undefined;
399053
- }
399054
- function emitLoopErrorNotice(socket, runtime, params) {
399055
- const decision = getLoopErrorNoticeDecision(params);
399056
- if (decision.visibility === "debug_only") {
399057
- debugLog("recovery", `Debug-only loop error (${params.stopReason}): ${params.message}`);
399058
- mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
399059
- return null;
399060
- }
399061
- emitLoopErrorDelta(socket, runtime, {
399062
- message: decision.message,
399063
- stopReason: params.stopReason,
399064
- isTerminal: params.isTerminal,
399065
- runId: params.runId,
399066
- agentId: params.agentId,
399067
- conversationId: params.conversationId,
399068
- apiError: decision.apiError
399069
- });
399070
- return decision.message;
399071
- }
399072
- function emitRecoverableStatusNotice(socket, runtime, params) {
399073
- const visibility = getRecoverableStatusNoticeVisibility(params.kind);
399074
- if (visibility === "debug_only") {
399075
- debugLog("recovery", `Debug-only lifecycle notice (${params.kind}): ${params.message}`);
399076
- mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
399077
- return;
399078
- }
399079
- emitStatusDelta(socket, runtime, {
399080
- message: params.message,
399081
- level: params.level,
399082
- runId: params.runId,
399083
- agentId: params.agentId,
399084
- conversationId: params.conversationId
399085
- });
399086
- }
399087
- function emitRecoverableRetryNotice(socket, runtime, params) {
399088
- const visibility = getRecoverableRetryNoticeVisibility(params.kind);
399089
- if (visibility === "debug_only") {
399090
- debugLog("recovery", `Debug-only retry notice (${params.kind}, attempt ${params.attempt}/${params.maxAttempts}): ${params.message}`);
399091
- mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
399092
- return;
399093
- }
399094
- emitRetryDelta(socket, runtime, {
399095
- message: params.message,
399096
- reason: params.reason,
399097
- attempt: params.attempt,
399098
- maxAttempts: params.maxAttempts,
399099
- delayMs: params.delayMs,
399100
- runId: params.runId,
399101
- agentId: params.agentId,
399102
- conversationId: params.conversationId
399103
- });
399104
- }
399105
- var DESKTOP_DEBUG_PANEL_INFO_PREFIX = "[LETTA_DESKTOP_DEBUG_PANEL_INFO]";
399106
- var init_recoverable_notices = __esm(() => {
399107
- init_error();
399108
- init_turn_recovery_policy();
399109
- init_error_formatter();
399110
- init_debug();
399111
- init_protocol_outbound();
399112
- });
399113
-
399114
399433
  // src/cli/helpers/compaction-utils.ts
399115
399434
  function extractCompactionSummary(text2) {
399116
399435
  try {
@@ -403268,292 +403587,6 @@ var init_stream_recovery_status = __esm(() => {
403268
403587
  init_protocol_outbound();
403269
403588
  });
403270
403589
 
403271
- // src/channels/teleport-guard.ts
403272
- function getLocalChannelTeleportError(scope) {
403273
- const channels = getSupportedChannelIds().filter((channelId) => {
403274
- return readRoutes(channelId).some((route) => route.agentId === scope.agentId && route.conversationId === scope.conversationId && route.enabled !== false && route.outboundEnabled !== false);
403275
- });
403276
- if (channels.length === 0)
403277
- return null;
403278
- return `This conversation is bound to ${channels.join(", ")} on this computer. Teleport is blocked because MessageChannel cannot follow the conversation to another computer yet. Remove the channel route or continue locally.`;
403279
- }
403280
- var init_teleport_guard = __esm(() => {
403281
- init_plugin_registry();
403282
- init_routing();
403283
- });
403284
-
403285
- // src/websocket/listener/teleport.ts
403286
- function buildTeleportContinuationMessages(params) {
403287
- return [
403288
- {
403289
- type: "approval",
403290
- approvals: params.approvals,
403291
- otid: params.teleportId
403292
- },
403293
- {
403294
- role: "system",
403295
- content: "<system-reminder>Teleportation to this environment is complete. Continue the existing task from this environment now.</system-reminder>",
403296
- otid: `${params.teleportId}:continue`
403297
- }
403298
- ];
403299
- }
403300
- function escapeSystemReminderText(value) {
403301
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
403302
- }
403303
- function buildTeleportFailureMessages(params) {
403304
- const messages = [];
403305
- if (params.approvals && params.approvals.length > 0) {
403306
- messages.push({
403307
- type: "approval",
403308
- approvals: params.approvals,
403309
- otid: params.teleportId
403310
- });
403311
- }
403312
- messages.push({
403313
- role: "system",
403314
- content: `<system-reminder>Teleportation failed.
403315
-
403316
- Error: ${escapeSystemReminderText(params.error)}
403317
-
403318
- Continue the existing task from this environment now.</system-reminder>`,
403319
- otid: `${params.teleportId}:failed`
403320
- });
403321
- return messages;
403322
- }
403323
- function getPendingTeleports(runtime) {
403324
- runtime.pendingTeleports ??= new Map;
403325
- return runtime.pendingTeleports;
403326
- }
403327
- function findPendingTeleportForRuntime(runtime, agentId, conversationId) {
403328
- for (const pending of getPendingTeleports(runtime).values()) {
403329
- if (pending.agentId === agentId && pending.conversationId === conversationId && pending.readyAt === undefined) {
403330
- return pending;
403331
- }
403332
- }
403333
- return null;
403334
- }
403335
- function isRuntimeTeleportPending(runtime, agentId, conversationId) {
403336
- if (!agentId)
403337
- return false;
403338
- return [...runtime.pendingTeleports?.values() ?? []].some((pending) => !pending.error && pending.agentId === agentId && pending.conversationId === conversationId);
403339
- }
403340
- function clearPriorReadyTeleports(params) {
403341
- const pendingTeleports = params.listener.pendingTeleports;
403342
- if (!pendingTeleports)
403343
- return;
403344
- for (const [teleportId, pending] of pendingTeleports) {
403345
- if (teleportId === params.currentTeleportId || pending.readyAt === undefined) {
403346
- continue;
403347
- }
403348
- if (pending.agentId === params.agentId && pending.conversationId === params.conversationId) {
403349
- pendingTeleports.delete(teleportId);
403350
- }
403351
- }
403352
- }
403353
- function hasAcceptedInputsWaiting(runtime, includeQueuePump) {
403354
- return runtime.queueRuntime.length > 0 || runtime.pendingTurns > 0 || runtime.queuedMessagesByItemId.size > 0 || includeQueuePump && (runtime.queuePumpActive || runtime.queuePumpScheduled);
403355
- }
403356
- function sendTeleportReady(runtime, pending, input) {
403357
- const connection = runtime.connections.get(pending.connectionId);
403358
- if (!connection || !isListenerTransportOpen(connection.writer))
403359
- return false;
403360
- const mode = getOrCreateConversationPermissionModeStateRef(runtime, pending.agentId, pending.conversationId).mode;
403361
- const message = {
403362
- type: "teleport_ready",
403363
- teleport_id: pending.teleportId,
403364
- runtime: {
403365
- agent_id: pending.agentId,
403366
- conversation_id: pending.conversationId
403367
- },
403368
- success: input.success,
403369
- active_turn: pending.activeTurn,
403370
- mode,
403371
- ...pending.continuation ? { continuation: pending.continuation } : {},
403372
- ...input.error ? { error: input.error } : {}
403373
- };
403374
- emitProtocolV2Message(connection.writer, runtime, message, message.runtime, toListenerConnection(pending.connectionId));
403375
- return true;
403376
- }
403377
- function retainTeleportForRecovery(runtime, pending) {
403378
- const timeout = setTimeout(() => {
403379
- const current = runtime.pendingTeleports?.get(pending.teleportId);
403380
- if (current === pending) {
403381
- runtime.pendingTeleports?.delete(pending.teleportId);
403382
- }
403383
- }, TELEPORT_RECOVERY_TTL_MS);
403384
- timeout.unref?.();
403385
- }
403386
- function handleTeleportProbe(command, socket, safeSocketSend) {
403387
- safeSocketSend(socket, {
403388
- type: "teleport_probe_response",
403389
- request_id: command.request_id,
403390
- runtime: command.runtime,
403391
- supported: resolveBackendMode() === "api",
403392
- drains_accepted_inputs: true,
403393
- idempotent_continuation: true
403394
- }, "teleport_probe_response", "teleport_probe");
403395
- }
403396
- function handleTeleportRequest(params) {
403397
- const { listener, command, connectionId } = params;
403398
- const pendingTeleports = getPendingTeleports(listener);
403399
- const existing = pendingTeleports.get(command.teleport_id);
403400
- if (existing) {
403401
- if (existing.readyAt !== undefined) {
403402
- sendTeleportReady(listener, existing, {
403403
- success: existing.error === undefined,
403404
- error: existing.error
403405
- });
403406
- }
403407
- return;
403408
- }
403409
- const pending = {
403410
- teleportId: command.teleport_id,
403411
- connectionId,
403412
- agentId: command.runtime.agent_id,
403413
- conversationId: command.runtime.conversation_id,
403414
- requestedAt: Date.now(),
403415
- drainAcceptedInputs: false,
403416
- activeTurn: false
403417
- };
403418
- const channelError = getLocalChannelTeleportError(pending);
403419
- if (channelError) {
403420
- pending.readyAt = Date.now();
403421
- pending.error = channelError;
403422
- pendingTeleports.set(pending.teleportId, pending);
403423
- sendTeleportReady(listener, pending, {
403424
- success: false,
403425
- error: channelError
403426
- });
403427
- retainTeleportForRecovery(listener, pending);
403428
- return;
403429
- }
403430
- const conflicting = findPendingTeleportForRuntime(listener, pending.agentId, pending.conversationId);
403431
- if (conflicting) {
403432
- pendingTeleports.set(pending.teleportId, pending);
403433
- pending.readyAt = Date.now();
403434
- pending.error = "Conversation already has a teleport pending";
403435
- sendTeleportReady(listener, pending, {
403436
- success: false,
403437
- error: pending.error
403438
- });
403439
- retainTeleportForRecovery(listener, pending);
403440
- return;
403441
- }
403442
- pendingTeleports.set(pending.teleportId, pending);
403443
- const conversationRuntime = getConversationRuntime(listener, pending.agentId, pending.conversationId);
403444
- pending.drainAcceptedInputs = conversationRuntime ? hasAcceptedInputsWaiting(conversationRuntime, true) : false;
403445
- if (!conversationRuntime?.isProcessing && !pending.drainAcceptedInputs) {
403446
- if (sendTeleportReady(listener, pending, { success: true })) {
403447
- pending.readyAt = Date.now();
403448
- retainTeleportForRecovery(listener, pending);
403449
- }
403450
- }
403451
- }
403452
- function claimPendingTeleportAtBoundary(params) {
403453
- const pending = findPendingTeleportForRuntime(params.listener, params.agentId, params.conversationId);
403454
- if (!pending)
403455
- return null;
403456
- if (pending.drainAcceptedInputs) {
403457
- if (params.activeTurn)
403458
- return null;
403459
- const runtime = getConversationRuntime(params.listener, params.agentId, params.conversationId);
403460
- if (runtime && hasAcceptedInputsWaiting(runtime, false))
403461
- return null;
403462
- }
403463
- const connection = params.listener.connections.get(pending.connectionId);
403464
- if (!connection || !isListenerTransportOpen(connection.writer))
403465
- return null;
403466
- pending.readyAt = Date.now();
403467
- pending.activeTurn = params.activeTurn;
403468
- pending.continuation = params.continuation;
403469
- return pending;
403470
- }
403471
- function emitClaimedTeleportReady(listener, pending) {
403472
- const sent = sendTeleportReady(listener, pending, { success: true });
403473
- if (sent) {
403474
- retainTeleportForRecovery(listener, pending);
403475
- }
403476
- return sent;
403477
- }
403478
- function finishTeleport(runtime, lease, pending) {
403479
- const transition = runtime.turnLifecycle.finish(lease, "cancelled");
403480
- if (!transition.finished)
403481
- return transition;
403482
- emitRuntimeStateUpdates(runtime, {
403483
- agent_id: pending.agentId,
403484
- conversation_id: pending.conversationId
403485
- });
403486
- emitClaimedTeleportReady(runtime.listener, pending);
403487
- return transition;
403488
- }
403489
- function finishPendingTeleport(runtime) {
403490
- if (!runtime.agentId)
403491
- return;
403492
- const pending = findPendingTeleportForRuntime(runtime.listener, runtime.agentId, runtime.conversationId);
403493
- if (!pending || runtime.lastStopReason !== "end_turn" && !pending.drainAcceptedInputs) {
403494
- return;
403495
- }
403496
- const claimed = claimPendingTeleportAtBoundary({
403497
- listener: runtime.listener,
403498
- agentId: runtime.agentId,
403499
- conversationId: runtime.conversationId,
403500
- activeTurn: false
403501
- });
403502
- if (claimed)
403503
- emitClaimedTeleportReady(runtime.listener, claimed);
403504
- }
403505
- function takeFailedTeleport(params) {
403506
- const pending = params.listener.pendingTeleports?.get(params.teleportId);
403507
- if (!pending || pending.agentId !== params.agentId || pending.conversationId !== params.conversationId) {
403508
- return null;
403509
- }
403510
- params.listener.pendingTeleports?.delete(params.teleportId);
403511
- return pending;
403512
- }
403513
- function handleTeleportFailure(params) {
403514
- const pending = takeFailedTeleport({
403515
- listener: params.listener,
403516
- teleportId: params.command.teleport_id,
403517
- agentId: params.command.runtime.agent_id,
403518
- conversationId: params.command.runtime.conversation_id
403519
- });
403520
- if (!pending || pending.error)
403521
- return;
403522
- const runtime = params.getOrCreateScopedRuntime(params.listener, pending.agentId, pending.conversationId);
403523
- emitLoopErrorNotice(params.socket, runtime, {
403524
- message: `Teleport failed: ${params.command.error}`,
403525
- stopReason: "error",
403526
- isTerminal: false,
403527
- agentId: pending.agentId,
403528
- conversationId: pending.conversationId
403529
- });
403530
- params.runDetachedListenerTask("teleport_failed", async () => {
403531
- await params.processIncomingMessage({
403532
- type: "message",
403533
- connectionId: pending.connectionId,
403534
- agentId: pending.agentId,
403535
- conversationId: pending.conversationId,
403536
- messages: buildTeleportFailureMessages({
403537
- teleportId: params.command.teleport_id,
403538
- error: params.command.error,
403539
- approvals: pending.continuation?.approvals
403540
- })
403541
- }, params.socket, runtime, params.onStatusChange, pending.connectionId);
403542
- });
403543
- }
403544
- var TELEPORT_RECOVERY_TTL_MS;
403545
- var init_teleport = __esm(() => {
403546
- init_backend_mode();
403547
- init_teleport_guard();
403548
- init_connection();
403549
- init_permission_mode();
403550
- init_protocol_outbound();
403551
- init_recoverable_notices();
403552
- init_runtime();
403553
- init_transport();
403554
- TELEPORT_RECOVERY_TTL_MS = 5 * 60000;
403555
- });
403556
-
403557
403590
  // node_modules/diff/libesm/diff/base.js
403558
403591
  class Diff2 {
403559
403592
  diff(oldStr, newStr, options = {}) {
@@ -418806,6 +418839,7 @@ function createListenerMessageHandler(params) {
418806
418839
  currentTeleportId: teleportId
418807
418840
  });
418808
418841
  const scopedRuntime2 = getOrCreateScopedRuntime2(runtime, parsed.runtime.agent_id, parsed.runtime.conversation_id);
418842
+ clearExpectedInboundTeleport(scopedRuntime2);
418809
418843
  const acceptedKey = `teleport:${teleportId}`;
418810
418844
  const previousDisposition = scopedRuntime2.acceptedInputDispositions.get(acceptedKey);
418811
418845
  if (previousDisposition) {
@@ -419453,7 +419487,7 @@ async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
419453
419487
  }
419454
419488
  }
419455
419489
  }
419456
- if (syncScopedRuntime.recoveredApprovalState && syncScopedRuntime.recoveredApprovalState.pendingRequestIds.size === 0 && (syncScopedRuntime.recoveredApprovalState.autoDecisions?.length ?? 0) > 0) {
419490
+ if (!isInboundTeleportExpected(syncScopedRuntime) && syncScopedRuntime.recoveredApprovalState && syncScopedRuntime.recoveredApprovalState.pendingRequestIds.size === 0 && (syncScopedRuntime.recoveredApprovalState.autoDecisions?.length ?? 0) > 0) {
419457
419491
  startRecoveredApprovalContinuation(syncScopedRuntime, getOrCreateProcessTransport(listenerRuntime), opts?.processIncomingMessage ?? handleIncomingMessage, {
419458
419492
  onStatusChange: opts?.onStatusChange,
419459
419493
  connectionId: opts?.connectionId,
@@ -419478,6 +419512,7 @@ var init_sync_replay = __esm(async () => {
419478
419512
  init_connection();
419479
419513
  init_connection_state_sync();
419480
419514
  init_recovery_sync();
419515
+ init_teleport();
419481
419516
  await __promiseAll([
419482
419517
  init_conversation_runtime(),
419483
419518
  init_recovery(),
@@ -440813,7 +440848,7 @@ var init_mcp_client = __esm(() => {
440813
440848
  init_streamableHttp();
440814
440849
  DEFAULT_CLIENT_INFO = {
440815
440850
  name: "letta-code",
440816
- version: "0.32.6"
440851
+ version: "0.32.7"
440817
440852
  };
440818
440853
  });
440819
440854
 
@@ -455161,9 +455196,6 @@ function shouldEnqueueCloudSend(values4, cloud, isAgentLaunch) {
455161
455196
  function validateSendOptions(values4) {
455162
455197
  if (values4.resume)
455163
455198
  throw new Error("--resume is interactive-only; use --conversation <id> in headless mode.");
455164
- const computer = values4.computer ?? values4.environment ?? values4.env;
455165
- if (computer !== undefined && !computer.trim())
455166
- throw new Error("Computer selector must not be empty.");
455167
455199
  if (values4["input-format"])
455168
455200
  throw new Error("Cloud message delivery does not support --input-format stream-json.");
455169
455201
  if (values4.new && values4.conversation)
@@ -455221,6 +455253,7 @@ async function tryCloudHeadlessSend(values4, prompt, backend3, isAgentLaunch, de
455221
455253
  if (!["text", "json", "stream-json"].includes(format5))
455222
455254
  throw new Error(`Invalid output format: ${format5}`);
455223
455255
  validateSendOptions(values4);
455256
+ const computer = normalizeAgentMessageComputer(values4.computer ?? values4.environment ?? values4.env);
455224
455257
  const explicitSender = values4["from-agent"];
455225
455258
  const ambientSender = env5.AGENT_ID || env5.LETTA_AGENT_ID;
455226
455259
  const sender = {
@@ -455253,7 +455286,7 @@ async function tryCloudHeadlessSend(values4, prompt, backend3, isAgentLaunch, de
455253
455286
  conversationId,
455254
455287
  clientMessageId,
455255
455288
  content: buildAgentSendContent(sender, noWait, prompt),
455256
- computer: isCloudEnvironmentSelector(values4.computer ?? values4.environment ?? values4.env) ? "cloud" : values4.computer ?? values4.environment ?? values4.env
455289
+ computer
455257
455290
  }, AbortSignal.any([controller.signal, AbortSignal.timeout(30000)]));
455258
455291
  clearTimeout(submissionTimeout);
455259
455292
  if (noWait) {
@@ -522119,4 +522152,4 @@ function registerBunOAuthFlows() {
522119
522152
  registerBunOAuthFlows();
522120
522153
  await init_src5().then(() => exports_src2);
522121
522154
 
522122
- //# debugId=4B57A44583E7B14564756E2164756E21
522155
+ //# debugId=84C68A57BFAD43D964756E2164756E21