@letta-ai/letta-code 0.16.11 → 0.16.12

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 +614 -182
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3122,7 +3122,7 @@ var package_default;
3122
3122
  var init_package = __esm(() => {
3123
3123
  package_default = {
3124
3124
  name: "@letta-ai/letta-code",
3125
- version: "0.16.11",
3125
+ version: "0.16.12",
3126
3126
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3127
3127
  type: "module",
3128
3128
  bin: {
@@ -7141,7 +7141,7 @@ var init_models2 = __esm(() => {
7141
7141
  id: "gpt-5.3-codex-plus-pro-high",
7142
7142
  handle: "chatgpt-plus-pro/gpt-5.3-codex",
7143
7143
  label: "GPT-5.3 Codex",
7144
- description: "GPT-5.3 Codex (high reasoning) via ChatGPT Plus/Pro",
7144
+ description: "OpenAI's best coding model (high reasoning)",
7145
7145
  isFeatured: true,
7146
7146
  updateArgs: {
7147
7147
  reasoning_effort: "high",
@@ -7325,7 +7325,6 @@ var init_models2 = __esm(() => {
7325
7325
  handle: "openai/gpt-5.2",
7326
7326
  label: "GPT-5.2",
7327
7327
  description: "Latest general-purpose GPT (med reasoning)",
7328
- isFeatured: true,
7329
7328
  updateArgs: {
7330
7329
  reasoning_effort: "medium",
7331
7330
  verbosity: "medium",
@@ -7360,6 +7359,72 @@ var init_models2 = __esm(() => {
7360
7359
  parallel_tool_calls: true
7361
7360
  }
7362
7361
  },
7362
+ {
7363
+ id: "gpt-5.3-codex-none",
7364
+ handle: "openai/gpt-5.3-codex",
7365
+ label: "GPT-5.3-Codex",
7366
+ description: "GPT-5.3 variant (no reasoning) optimized for coding",
7367
+ updateArgs: {
7368
+ reasoning_effort: "none",
7369
+ verbosity: "low",
7370
+ context_window: 272000,
7371
+ max_output_tokens: 128000,
7372
+ parallel_tool_calls: true
7373
+ }
7374
+ },
7375
+ {
7376
+ id: "gpt-5.3-codex-low",
7377
+ handle: "openai/gpt-5.3-codex",
7378
+ label: "GPT-5.3-Codex",
7379
+ description: "GPT-5.3 variant (low reasoning) optimized for coding",
7380
+ updateArgs: {
7381
+ reasoning_effort: "low",
7382
+ verbosity: "low",
7383
+ context_window: 272000,
7384
+ max_output_tokens: 128000,
7385
+ parallel_tool_calls: true
7386
+ }
7387
+ },
7388
+ {
7389
+ id: "gpt-5.3-codex-medium",
7390
+ handle: "openai/gpt-5.3-codex",
7391
+ label: "GPT-5.3-Codex",
7392
+ description: "GPT-5.3 variant (med reasoning) optimized for coding",
7393
+ updateArgs: {
7394
+ reasoning_effort: "medium",
7395
+ verbosity: "low",
7396
+ context_window: 272000,
7397
+ max_output_tokens: 128000,
7398
+ parallel_tool_calls: true
7399
+ }
7400
+ },
7401
+ {
7402
+ id: "gpt-5.3-codex-high",
7403
+ handle: "openai/gpt-5.3-codex",
7404
+ label: "GPT-5.3-Codex",
7405
+ description: "OpenAI's best coding model (high reasoning)",
7406
+ isFeatured: true,
7407
+ updateArgs: {
7408
+ reasoning_effort: "high",
7409
+ verbosity: "low",
7410
+ context_window: 272000,
7411
+ max_output_tokens: 128000,
7412
+ parallel_tool_calls: true
7413
+ }
7414
+ },
7415
+ {
7416
+ id: "gpt-5.3-codex-xhigh",
7417
+ handle: "openai/gpt-5.3-codex",
7418
+ label: "GPT-5.3-Codex",
7419
+ description: "GPT-5.3 variant (max reasoning) optimized for coding",
7420
+ updateArgs: {
7421
+ reasoning_effort: "xhigh",
7422
+ verbosity: "low",
7423
+ context_window: 272000,
7424
+ max_output_tokens: 128000,
7425
+ parallel_tool_calls: true
7426
+ }
7427
+ },
7363
7428
  {
7364
7429
  id: "gpt-5.2-codex-none",
7365
7430
  handle: "openai/gpt-5.2-codex",
@@ -37710,7 +37775,8 @@ class TelemetryManager {
37710
37775
  context: context3,
37711
37776
  http_status: options?.httpStatus,
37712
37777
  model_id: options?.modelId,
37713
- run_id: options?.runId
37778
+ run_id: options?.runId,
37779
+ recent_chunks: options?.recentChunks
37714
37780
  };
37715
37781
  this.track("error", data);
37716
37782
  }
@@ -59822,9 +59888,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
59822
59888
  debugWarn("drainStream", "Extracted run_id from error:", streamProcessor.lastRunId);
59823
59889
  }
59824
59890
  }
59825
- if (!streamProcessor.lastRunId) {
59826
- fallbackError = errorMessage;
59827
- }
59891
+ fallbackError = errorMessage;
59828
59892
  stopReason = streamProcessor.stopReason || "error";
59829
59893
  markIncompleteToolsAsCancelled(buffers, true, "stream_error");
59830
59894
  queueMicrotask(refresh);
@@ -59852,22 +59916,16 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
59852
59916
  }
59853
59917
  markCurrentLineAsFinished(buffers);
59854
59918
  queueMicrotask(refresh);
59855
- let approval = null;
59856
- let approvals = [];
59857
- if (stopReason === "requires_approval") {
59858
- const allPending = Array.from(streamProcessor.pendingApprovals.values());
59859
- approvals = allPending.map((a) => ({
59860
- toolCallId: a.toolCallId,
59861
- toolName: a.toolName || "",
59862
- toolArgs: a.toolArgs || "{}"
59863
- }));
59864
- if (approvals.length === 0) {
59865
- debugWarn("drainStream", "No approvals collected despite requires_approval stop reason");
59866
- debugWarn("drainStream", "Pending approvals map:", allPending);
59867
- } else {
59868
- approval = approvals[0] || null;
59869
- }
59870
- streamProcessor.pendingApprovals.clear();
59919
+ const allPending = Array.from(streamProcessor.pendingApprovals.values());
59920
+ const approvals = allPending.map((a) => ({
59921
+ toolCallId: a.toolCallId,
59922
+ toolName: a.toolName || "",
59923
+ toolArgs: a.toolArgs || "{}"
59924
+ }));
59925
+ const approval = approvals[0] || null;
59926
+ streamProcessor.pendingApprovals.clear();
59927
+ if (stopReason === "requires_approval" && approvals.length === 0) {
59928
+ debugWarn("drainStream", "No approvals collected despite requires_approval stop reason");
59871
59929
  }
59872
59930
  const apiDurationMs = performance.now() - startTime;
59873
59931
  return {
@@ -59885,6 +59943,8 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
59885
59943
  let result = await drainStream(stream2, buffers, refresh, abortSignal, onFirstMessage, onChunkProcessed, contextTracker);
59886
59944
  if (result.stopReason === "error" && result.lastRunId && result.lastSeqId !== null && abortSignal && !abortSignal.aborted) {
59887
59945
  const originalFallbackError = result.fallbackError;
59946
+ const originalApprovals = result.approvals;
59947
+ const originalApproval = result.approval;
59888
59948
  try {
59889
59949
  const client = await getClient2();
59890
59950
  buffers.commitGeneration = (buffers.commitGeneration || 0) + 1;
@@ -59895,6 +59955,10 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
59895
59955
  });
59896
59956
  const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal, undefined, onChunkProcessed, contextTracker);
59897
59957
  result = resumeResult;
59958
+ if (result.stopReason === "requires_approval" && (result.approvals?.length ?? 0) === 0 && (originalApprovals?.length ?? 0) > 0) {
59959
+ result.approvals = originalApprovals;
59960
+ result.approval = originalApproval;
59961
+ }
59898
59962
  } catch (_e) {
59899
59963
  result.fallbackError = originalFallbackError;
59900
59964
  }
@@ -62509,6 +62573,11 @@ function isConversationBusyError(detail) {
62509
62573
  return false;
62510
62574
  return detail.toLowerCase().includes(CONVERSATION_BUSY_DETAIL_FRAGMENT);
62511
62575
  }
62576
+ function isEmptyResponseError(detail) {
62577
+ if (typeof detail !== "string")
62578
+ return false;
62579
+ return detail.toLowerCase().includes(EMPTY_RESPONSE_DETAIL_FRAGMENT);
62580
+ }
62512
62581
  function isRetryableProviderErrorDetail(detail) {
62513
62582
  if (typeof detail !== "string")
62514
62583
  return false;
@@ -62538,6 +62607,13 @@ function shouldRetryRunMetadataError(errorType, detail) {
62538
62607
  return true;
62539
62608
  return retryable429Detail || retryableDetail;
62540
62609
  }
62610
+ function isEmptyResponseRetryable(errorType, detail, emptyResponseRetries, maxEmptyResponseRetries) {
62611
+ if (emptyResponseRetries >= maxEmptyResponseRetries)
62612
+ return false;
62613
+ if (errorType !== "llm_error")
62614
+ return false;
62615
+ return isEmptyResponseError(detail);
62616
+ }
62541
62617
  function shouldRetryPreStreamTransientError(opts) {
62542
62618
  const { status, detail } = opts;
62543
62619
  if (hasNonRetryableQuotaDetail(detail))
@@ -62630,7 +62706,7 @@ function rebuildInputWithFreshDenials(currentInput, serverApprovals, denialReaso
62630
62706
  function shouldAttemptApprovalRecovery(opts) {
62631
62707
  return opts.approvalPendingDetected && opts.retries < opts.maxRetries;
62632
62708
  }
62633
- var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN;
62709
+ var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed", EMPTY_RESPONSE_DETAIL_FRAGMENT = "empty content in", RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_PROVIDER_DETAIL_PATTERNS, NON_RETRYABLE_429_REASONS, NON_RETRYABLE_QUOTA_DETAIL_PATTERNS, NON_RETRYABLE_4XX_PATTERN, RETRYABLE_429_PATTERN;
62634
62710
  var init_turn_recovery_policy = __esm(() => {
62635
62711
  init_zaiErrors();
62636
62712
  RETRYABLE_PROVIDER_DETAIL_PATTERNS = [
@@ -64683,7 +64759,6 @@ async function handleHeadlessCommand(argv, model, skillsDirectoryOverride, skill
64683
64759
  continue: { type: "boolean", short: "c" },
64684
64760
  resume: { type: "boolean", short: "r" },
64685
64761
  conversation: { type: "string" },
64686
- default: { type: "boolean" },
64687
64762
  "new-agent": { type: "boolean" },
64688
64763
  new: { type: "boolean" },
64689
64764
  agent: { type: "string", short: "a" },
@@ -64797,16 +64872,8 @@ In headless mode, use:
64797
64872
  let agent = null;
64798
64873
  let specifiedAgentId = values.agent;
64799
64874
  let specifiedConversationId = values.conversation;
64800
- const useDefaultConv = values.default;
64801
64875
  const shouldContinue = values.continue;
64802
64876
  const forceNew = values["new-agent"];
64803
- if (useDefaultConv) {
64804
- if (specifiedConversationId && specifiedConversationId !== "default") {
64805
- console.error("Error: --default cannot be used with --conversation (they're mutually exclusive)");
64806
- process.exit(1);
64807
- }
64808
- specifiedConversationId = "default";
64809
- }
64810
64877
  const systemPromptPreset = values.system;
64811
64878
  const systemCustom = values["system-custom"];
64812
64879
  const systemAppend = values["system-append"];
@@ -64883,7 +64950,7 @@ In headless mode, use:
64883
64950
  specifiedAgentId = specifiedConversationId;
64884
64951
  specifiedConversationId = "default";
64885
64952
  }
64886
- if (specifiedConversationId === "default" && !specifiedAgentId) {
64953
+ if (specifiedConversationId === "default" && !specifiedAgentId && !forceNew) {
64887
64954
  console.error("Error: --conv default requires --agent <agent-id>");
64888
64955
  console.error("Usage: letta --agent agent-xyz --conv default");
64889
64956
  console.error(" or: letta --conv agent-xyz (shorthand)");
@@ -65467,6 +65534,7 @@ ${loadedContents.join(`
65467
65534
  ];
65468
65535
  let lastKnownRunId = null;
65469
65536
  let llmApiErrorRetries = 0;
65537
+ let emptyResponseRetries = 0;
65470
65538
  let conversationBusyRetries = 0;
65471
65539
  markMilestone("HEADLESS_FIRST_STREAM_START");
65472
65540
  measureSinceMilestone("headless-setup-total", "HEADLESS_CLIENT_READY");
@@ -65704,6 +65772,7 @@ ${loadedContents.join(`
65704
65772
  }
65705
65773
  if (stopReason === "end_turn") {
65706
65774
  llmApiErrorRetries = 0;
65775
+ emptyResponseRetries = 0;
65707
65776
  conversationBusyRetries = 0;
65708
65777
  break;
65709
65778
  }
@@ -65843,6 +65912,35 @@ ${loadedContents.join(`
65843
65912
  const metaError = run.metadata?.error;
65844
65913
  const errorType = metaError?.error_type ?? metaError?.error?.error_type;
65845
65914
  const detail = metaError?.detail ?? metaError?.error?.detail ?? "";
65915
+ if (isEmptyResponseRetryable(errorType, detail, emptyResponseRetries, EMPTY_RESPONSE_MAX_RETRIES)) {
65916
+ const attempt = emptyResponseRetries + 1;
65917
+ const delayMs = 500 * attempt;
65918
+ emptyResponseRetries = attempt;
65919
+ if (attempt >= EMPTY_RESPONSE_MAX_RETRIES) {
65920
+ const nudgeMessage = {
65921
+ role: "system",
65922
+ content: `<system-reminder>The previous response was empty. Please provide a response with either text content or a tool call.</system-reminder>`
65923
+ };
65924
+ currentInput = [...currentInput, nudgeMessage];
65925
+ }
65926
+ if (outputFormat === "stream-json") {
65927
+ const retryMsg = {
65928
+ type: "retry",
65929
+ reason: "llm_api_error",
65930
+ attempt,
65931
+ max_attempts: EMPTY_RESPONSE_MAX_RETRIES,
65932
+ delay_ms: delayMs,
65933
+ run_id: lastRunId ?? undefined,
65934
+ session_id: sessionId,
65935
+ uuid: `retry-empty-${lastRunId || randomUUID7()}`
65936
+ };
65937
+ console.log(JSON.stringify(retryMsg));
65938
+ } else {
65939
+ console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES})...`);
65940
+ }
65941
+ await new Promise((resolve25) => setTimeout(resolve25, delayMs));
65942
+ continue;
65943
+ }
65846
65944
  if (shouldRetryRunMetadataError(errorType, detail)) {
65847
65945
  const attempt = llmApiErrorRetries + 1;
65848
65946
  const baseDelayMs = 1000;
@@ -66714,7 +66812,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
66714
66812
  setMessageQueueAdder(null);
66715
66813
  process.exit(0);
66716
66814
  }
66717
- var LLM_API_ERROR_MAX_RETRIES = 3, CONVERSATION_BUSY_MAX_RETRIES = 1, CONVERSATION_BUSY_RETRY_DELAY_MS = 2500;
66815
+ var LLM_API_ERROR_MAX_RETRIES = 3, EMPTY_RESPONSE_MAX_RETRIES = 2, CONVERSATION_BUSY_MAX_RETRIES = 1, CONVERSATION_BUSY_RETRY_DELAY_MS = 2500;
66718
66816
  var init_headless = __esm(async () => {
66719
66817
  init_error();
66720
66818
  init_bootstrapHandler();
@@ -78879,6 +78977,24 @@ function charsToTokens(chars) {
78879
78977
  }
78880
78978
 
78881
78979
  // src/cli/components/AgentInfoBar.tsx
78980
+ function truncateText(text, maxWidth) {
78981
+ if (maxWidth <= 0)
78982
+ return "";
78983
+ if (stringWidth(text) <= maxWidth)
78984
+ return text;
78985
+ if (maxWidth <= 3)
78986
+ return ".".repeat(maxWidth);
78987
+ const suffix = "...";
78988
+ const budget = Math.max(0, maxWidth - stringWidth(suffix));
78989
+ let out = "";
78990
+ for (const ch of text) {
78991
+ const next = out + ch;
78992
+ if (stringWidth(next) > budget)
78993
+ break;
78994
+ out = next;
78995
+ }
78996
+ return out + suffix;
78997
+ }
78882
78998
  function formatReasoningLabel(effort) {
78883
78999
  if (effort === "none")
78884
79000
  return null;
@@ -78896,12 +79012,13 @@ function formatReasoningLabel(effort) {
78896
79012
  }
78897
79013
  var import_react63, jsx_dev_runtime40, AgentInfoBar;
78898
79014
  var init_AgentInfoBar = __esm(async () => {
79015
+ init_string_width();
78899
79016
  init_constants();
78900
79017
  init_version();
79018
+ init_useTerminalWidth();
78901
79019
  init_colors();
78902
79020
  await __promiseAll([
78903
79021
  init_build2(),
78904
- init_dist4(),
78905
79022
  init_settings_manager(),
78906
79023
  init_Text2()
78907
79024
  ]);
@@ -78915,7 +79032,7 @@ var init_AgentInfoBar = __esm(async () => {
78915
79032
  serverUrl,
78916
79033
  conversationId
78917
79034
  }) {
78918
- const isTmux = Boolean(process.env.TMUX);
79035
+ const columns = useTerminalWidth();
78919
79036
  const isPinned = import_react63.useMemo(() => {
78920
79037
  if (!agentId)
78921
79038
  return false;
@@ -78924,7 +79041,7 @@ var init_AgentInfoBar = __esm(async () => {
78924
79041
  return localPinned.includes(agentId) || globalPinned.includes(agentId);
78925
79042
  }, [agentId]);
78926
79043
  const isCloudUser = serverUrl?.includes("api.letta.com");
78927
- const adeUrl = agentId && agentId !== "loading" ? `https://app.letta.com/agents/${agentId}${conversationId && conversationId !== "default" ? `?conversation=${conversationId}` : ""}` : "";
79044
+ const adeConversationUrl = agentId && agentId !== "loading" ? `https://app.letta.com/agents/${agentId}${conversationId && conversationId !== "default" ? `?conversation=${conversationId}` : ""}` : "";
78928
79045
  const showBottomBar = agentId && agentId !== "loading";
78929
79046
  const reasoningLabel = formatReasoningLabel(currentReasoningEffort);
78930
79047
  const modelLine = currentModel ? `${currentModel}${reasoningLabel ? ` (${reasoningLabel})` : ""}` : null;
@@ -78932,6 +79049,11 @@ var init_AgentInfoBar = __esm(async () => {
78932
79049
  return null;
78933
79050
  }
78934
79051
  const alienLines = [" ▗▖▗▖ ", " ▙█▜▛█▟ ", " ▝▜▛▜▛▘ ", " "];
79052
+ const leftWidth = Math.max(...alienLines.map((l) => stringWidth(l)));
79053
+ const rightWidth = Math.max(0, columns - leftWidth);
79054
+ const agentNameLabel = agentName || "Unnamed";
79055
+ const agentHint = isPinned ? " (pinned)" : agentName === DEFAULT_AGENT_NAME || !agentName ? " (type /pin to give your agent a real name!)" : " (type /pin to pin agent)";
79056
+ const agentNameLine = `${agentNameLabel}${agentHint}`;
78935
79057
  return /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
78936
79058
  flexDirection: "column",
78937
79059
  children: [
@@ -78940,18 +79062,12 @@ var init_AgentInfoBar = __esm(async () => {
78940
79062
  }, undefined, false, undefined, this),
78941
79063
  /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
78942
79064
  children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79065
+ wrap: "truncate-end",
78943
79066
  children: [
78944
79067
  " ",
78945
79068
  "Letta Code v",
78946
79069
  getVersion(),
78947
- " · Report bugs with /feedback or",
78948
- " ",
78949
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(dist_default4, {
78950
- url: "https://discord.gg/letta",
78951
- children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78952
- children: "on Discord ↗"
78953
- }, undefined, false, undefined, this)
78954
- }, undefined, false, undefined, this)
79070
+ " · /feedback · discord.gg/letta"
78955
79071
  ]
78956
79072
  }, undefined, true, undefined, this)
78957
79073
  }, undefined, false, undefined, this),
@@ -78964,20 +79080,15 @@ var init_AgentInfoBar = __esm(async () => {
78964
79080
  color: colors.footer.agentName,
78965
79081
  children: alienLines[0]
78966
79082
  }, undefined, false, undefined, this),
78967
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78968
- bold: true,
78969
- color: colors.footer.agentName,
78970
- children: agentName || "Unnamed"
78971
- }, undefined, false, undefined, this),
78972
- isPinned ? /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78973
- color: "green",
78974
- children: " (pinned )"
78975
- }, undefined, false, undefined, this) : agentName === DEFAULT_AGENT_NAME || !agentName ? /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78976
- color: "gray",
78977
- children: " (type /pin to give your agent a real name!)"
78978
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78979
- color: "gray",
78980
- children: " (type /pin to pin agent)"
79083
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79084
+ width: rightWidth,
79085
+ flexShrink: 1,
79086
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79087
+ bold: true,
79088
+ color: colors.footer.agentName,
79089
+ wrap: "truncate-end",
79090
+ children: truncateText(agentNameLine, rightWidth)
79091
+ }, undefined, false, undefined, this)
78981
79092
  }, undefined, false, undefined, this)
78982
79093
  ]
78983
79094
  }, undefined, true, undefined, this),
@@ -78987,37 +79098,31 @@ var init_AgentInfoBar = __esm(async () => {
78987
79098
  color: colors.footer.agentName,
78988
79099
  children: alienLines[1]
78989
79100
  }, undefined, false, undefined, this),
78990
- isCloudUser && adeUrl && !isTmux && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(jsx_dev_runtime40.Fragment, {
78991
- children: [
78992
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(dist_default4, {
78993
- url: adeUrl,
78994
- children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78995
- children: "Open in ADE ↗"
78996
- }, undefined, false, undefined, this)
78997
- }, undefined, false, undefined, this),
78998
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
78999
- dimColor: true,
79000
- children: "· "
79001
- }, undefined, false, undefined, this)
79002
- ]
79003
- }, undefined, true, undefined, this),
79004
- isCloudUser && adeUrl && isTmux && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79005
- dimColor: true,
79006
- children: [
79007
- "Open in ADE: ",
79008
- adeUrl,
79009
- " · "
79010
- ]
79011
- }, undefined, true, undefined, this),
79012
- isCloudUser && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(dist_default4, {
79013
- url: "https://app.letta.com/settings/organization/usage",
79101
+ !isCloudUser && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79102
+ width: rightWidth,
79103
+ flexShrink: 1,
79014
79104
  children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79015
- children: "View usage ↗"
79105
+ dimColor: true,
79106
+ wrap: "truncate-end",
79107
+ children: truncateText(serverUrl ?? "", rightWidth)
79016
79108
  }, undefined, false, undefined, this)
79109
+ }, undefined, false, undefined, this)
79110
+ ]
79111
+ }, undefined, true, undefined, this),
79112
+ isCloudUser && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79113
+ children: [
79114
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79115
+ color: colors.footer.agentName,
79116
+ children: alienLines[3]
79017
79117
  }, undefined, false, undefined, this),
79018
- !isCloudUser && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79019
- dimColor: true,
79020
- children: serverUrl
79118
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79119
+ width: rightWidth,
79120
+ flexShrink: 1,
79121
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79122
+ dimColor: true,
79123
+ wrap: "truncate-end",
79124
+ children: truncateText("Usage: https://app.letta.com/settings/organization/usage", rightWidth)
79125
+ }, undefined, false, undefined, this)
79021
79126
  }, undefined, false, undefined, this)
79022
79127
  ]
79023
79128
  }, undefined, true, undefined, this),
@@ -79027,9 +79132,14 @@ var init_AgentInfoBar = __esm(async () => {
79027
79132
  color: colors.footer.agentName,
79028
79133
  children: alienLines[2]
79029
79134
  }, undefined, false, undefined, this),
79030
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79031
- dimColor: true,
79032
- children: modelLine ?? "model unknown"
79135
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79136
+ width: rightWidth,
79137
+ flexShrink: 1,
79138
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79139
+ dimColor: true,
79140
+ wrap: "truncate-end",
79141
+ children: truncateText(modelLine ?? "model unknown", rightWidth)
79142
+ }, undefined, false, undefined, this)
79033
79143
  }, undefined, false, undefined, this)
79034
79144
  ]
79035
79145
  }, undefined, true, undefined, this),
@@ -79038,9 +79148,14 @@ var init_AgentInfoBar = __esm(async () => {
79038
79148
  /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79039
79149
  children: alienLines[3]
79040
79150
  }, undefined, false, undefined, this),
79041
- /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79042
- dimColor: true,
79043
- children: agentId
79151
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79152
+ width: rightWidth,
79153
+ flexShrink: 1,
79154
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79155
+ dimColor: true,
79156
+ wrap: "truncate-end",
79157
+ children: truncateText(agentId, rightWidth)
79158
+ }, undefined, false, undefined, this)
79044
79159
  }, undefined, false, undefined, this)
79045
79160
  ]
79046
79161
  }, undefined, true, undefined, this),
@@ -79049,12 +79164,32 @@ var init_AgentInfoBar = __esm(async () => {
79049
79164
  /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79050
79165
  children: alienLines[3]
79051
79166
  }, undefined, false, undefined, this),
79052
- conversationId && conversationId !== "default" ? /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79053
- dimColor: true,
79054
- children: conversationId
79055
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79167
+ conversationId && conversationId !== "default" ? /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79168
+ width: rightWidth,
79169
+ flexShrink: 1,
79170
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79171
+ dimColor: true,
79172
+ wrap: "truncate-end",
79173
+ children: truncateText(conversationId, rightWidth)
79174
+ }, undefined, false, undefined, this)
79175
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79176
+ width: rightWidth,
79177
+ flexShrink: 1,
79178
+ children: /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79179
+ dimColor: true,
79180
+ children: "default conversation"
79181
+ }, undefined, false, undefined, this)
79182
+ }, undefined, false, undefined, this)
79183
+ ]
79184
+ }, undefined, true, undefined, this),
79185
+ isCloudUser && adeConversationUrl && /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Box_default, {
79186
+ children: [
79187
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79188
+ children: alienLines[3]
79189
+ }, undefined, false, undefined, this),
79190
+ /* @__PURE__ */ jsx_dev_runtime40.jsxDEV(Text2, {
79056
79191
  dimColor: true,
79057
- children: "default conversation"
79192
+ children: `ADE: ${adeConversationUrl}`
79058
79193
  }, undefined, false, undefined, this)
79059
79194
  ]
79060
79195
  }, undefined, true, undefined, this)
@@ -79263,6 +79398,7 @@ function AutocompleteItem({
79263
79398
  return /* @__PURE__ */ jsx_dev_runtime41.jsxDEV(Text2, {
79264
79399
  color: selected ? colors.command.selected : undefined,
79265
79400
  bold: selected,
79401
+ wrap: "truncate-end",
79266
79402
  children: [
79267
79403
  " ",
79268
79404
  children
@@ -79463,6 +79599,15 @@ var init_FileAutocomplete = __esm(async () => {
79463
79599
  });
79464
79600
 
79465
79601
  // src/cli/components/SlashCommandAutocomplete.tsx
79602
+ function truncateText2(text, maxWidth) {
79603
+ if (maxWidth <= 0)
79604
+ return "";
79605
+ if (text.length <= maxWidth)
79606
+ return text;
79607
+ if (maxWidth <= 3)
79608
+ return text.slice(0, maxWidth);
79609
+ return `${text.slice(0, maxWidth - 3)}...`;
79610
+ }
79466
79611
  function extractSearchQuery2(input, cursor) {
79467
79612
  if (!input.startsWith("/"))
79468
79613
  return null;
@@ -79485,6 +79630,7 @@ function SlashCommandAutocomplete({
79485
79630
  agentId,
79486
79631
  workingDirectory = process.cwd()
79487
79632
  }) {
79633
+ const columns = useTerminalWidth();
79488
79634
  const [customCommands, setCustomCommands] = import_react66.useState([]);
79489
79635
  import_react66.useEffect(() => {
79490
79636
  Promise.resolve().then(() => (init_custom(), exports_custom)).then(({ getCustomCommands: getCustomCommands2 }) => {
@@ -79605,14 +79751,17 @@ function SlashCommandAutocomplete({
79605
79751
  children: [
79606
79752
  visibleMatches.map((item, idx) => {
79607
79753
  const actualIndex = startIndex + idx;
79754
+ const displayCmd = truncateText2(item.cmd, CMD_COL_WIDTH).padEnd(CMD_COL_WIDTH);
79755
+ const maxDescWidth = Math.max(0, columns - 2 - CMD_COL_WIDTH - 1);
79756
+ const displayDesc = truncateText2(item.desc, maxDescWidth);
79608
79757
  return /* @__PURE__ */ jsx_dev_runtime43.jsxDEV(AutocompleteItem, {
79609
79758
  selected: actualIndex === selectedIndex,
79610
79759
  children: [
79611
- item.cmd.padEnd(14),
79760
+ displayCmd,
79612
79761
  " ",
79613
79762
  /* @__PURE__ */ jsx_dev_runtime43.jsxDEV(Text2, {
79614
79763
  dimColor: actualIndex !== selectedIndex,
79615
- children: item.desc
79764
+ children: displayDesc
79616
79765
  }, undefined, false, undefined, this)
79617
79766
  ]
79618
79767
  }, item.cmd, true, undefined, this);
@@ -79631,9 +79780,10 @@ function SlashCommandAutocomplete({
79631
79780
  ]
79632
79781
  }, undefined, true, undefined, this);
79633
79782
  }
79634
- var import_react66, jsx_dev_runtime43, VISIBLE_COMMANDS = 7, _allCommands;
79783
+ var import_react66, jsx_dev_runtime43, VISIBLE_COMMANDS = 7, CMD_COL_WIDTH = 14, _allCommands;
79635
79784
  var init_SlashCommandAutocomplete = __esm(async () => {
79636
79785
  init_registry();
79786
+ init_useTerminalWidth();
79637
79787
  await __promiseAll([
79638
79788
  init_settings_manager(),
79639
79789
  init_useAutocompleteNavigation(),
@@ -79790,7 +79940,6 @@ var init_QueuedMessages = __esm(async () => {
79790
79940
  // src/cli/components/ShimmerText.tsx
79791
79941
  var import_react69, jsx_dev_runtime46, ShimmerText;
79792
79942
  var init_ShimmerText = __esm(async () => {
79793
- init_source();
79794
79943
  init_colors();
79795
79944
  await init_Text2();
79796
79945
  import_react69 = __toESM(require_react(), 1);
@@ -79802,21 +79951,58 @@ var init_ShimmerText = __esm(async () => {
79802
79951
  shimmerOffset,
79803
79952
  wrap
79804
79953
  }) {
79805
- const fullText = `${boldPrefix ? `${boldPrefix} ` : ""}${message}…`;
79806
- const prefixLength = boldPrefix ? boldPrefix.length + 1 : 0;
79807
- const shimmerText = fullText.split("").map((char, i) => {
79808
- const isInShimmer = i >= shimmerOffset && i < shimmerOffset + 3;
79809
- const isInPrefix = i < prefixLength;
79810
- if (isInShimmer) {
79811
- const styledChar2 = source_default.hex(colors.status.processingShimmer)(char);
79812
- return isInPrefix ? source_default.bold(styledChar2) : styledChar2;
79813
- }
79814
- const styledChar = source_default.hex(color)(char);
79815
- return isInPrefix ? source_default.bold(styledChar) : styledChar;
79816
- }).join("");
79954
+ const prefix = boldPrefix ? `${boldPrefix} ` : "";
79955
+ const prefixLen = prefix.length;
79956
+ const fullText = `${prefix}${message}…`;
79957
+ const start = Math.max(0, shimmerOffset);
79958
+ const end = Math.max(start, shimmerOffset + 3);
79959
+ const segments = [];
79960
+ const pushRegion = (text, regionStart, regionColor) => {
79961
+ if (!text)
79962
+ return;
79963
+ const regionEnd = regionStart + text.length;
79964
+ const crossesPrefix = regionStart < prefixLen && regionEnd > prefixLen;
79965
+ if (!crossesPrefix) {
79966
+ const bold = regionStart < prefixLen;
79967
+ segments.push({
79968
+ key: `${regionStart}:${regionColor ?? ""}:${bold ? "b" : "n"}`,
79969
+ text,
79970
+ color: regionColor,
79971
+ bold
79972
+ });
79973
+ return;
79974
+ }
79975
+ const cut = Math.max(0, prefixLen - regionStart);
79976
+ const left = text.slice(0, cut);
79977
+ const right = text.slice(cut);
79978
+ if (left)
79979
+ segments.push({
79980
+ key: `${regionStart}:${regionColor ?? ""}:b`,
79981
+ text: left,
79982
+ color: regionColor,
79983
+ bold: true
79984
+ });
79985
+ if (right)
79986
+ segments.push({
79987
+ key: `${prefixLen}:${regionColor ?? ""}:n`,
79988
+ text: right,
79989
+ color: regionColor,
79990
+ bold: false
79991
+ });
79992
+ };
79993
+ const before = fullText.slice(0, start);
79994
+ const shimmer = fullText.slice(start, end);
79995
+ const after = fullText.slice(end);
79996
+ pushRegion(before, 0, color);
79997
+ pushRegion(shimmer, start, colors.status.processingShimmer);
79998
+ pushRegion(after, end, color);
79817
79999
  return /* @__PURE__ */ jsx_dev_runtime46.jsxDEV(Text2, {
79818
80000
  wrap,
79819
- children: shimmerText
80001
+ children: segments.map((seg) => /* @__PURE__ */ jsx_dev_runtime46.jsxDEV(Text2, {
80002
+ color: seg.color,
80003
+ bold: seg.bold,
80004
+ children: seg.text
80005
+ }, seg.key, false, undefined, this))
79820
80006
  }, undefined, false, undefined, this);
79821
80007
  });
79822
80008
  });
@@ -79988,6 +80174,8 @@ function Input({
79988
80174
  currentModel,
79989
80175
  currentModelProvider,
79990
80176
  currentReasoningEffort,
80177
+ currentSystemPromptId,
80178
+ currentToolset,
79991
80179
  messageQueue,
79992
80180
  onEnterQueueEditMode,
79993
80181
  onEscapeCancel,
@@ -80019,7 +80207,36 @@ function Input({
80019
80207
  const [cursorPos, setCursorPos] = import_react70.useState(undefined);
80020
80208
  const [currentCursorPosition, setCurrentCursorPosition] = import_react70.useState(0);
80021
80209
  const columns = terminalWidth;
80210
+ const [suppressDividers, setSuppressDividers] = import_react70.useState(false);
80211
+ const resizeDividersTimerRef = import_react70.useRef(null);
80212
+ const lastColumnsRef = import_react70.useRef(columns);
80022
80213
  const [isBashMode, setIsBashMode] = import_react70.useState(false);
80214
+ import_react70.useEffect(() => {
80215
+ const prev = lastColumnsRef.current;
80216
+ if (columns === prev)
80217
+ return;
80218
+ lastColumnsRef.current = columns;
80219
+ const isShrinking = columns < prev;
80220
+ if (isShrinking) {
80221
+ setSuppressDividers(true);
80222
+ }
80223
+ if (resizeDividersTimerRef.current) {
80224
+ clearTimeout(resizeDividersTimerRef.current);
80225
+ }
80226
+ resizeDividersTimerRef.current = setTimeout(() => {
80227
+ resizeDividersTimerRef.current = null;
80228
+ setSuppressDividers(false);
80229
+ }, 250);
80230
+ return;
80231
+ }, [columns]);
80232
+ import_react70.useEffect(() => {
80233
+ return () => {
80234
+ if (resizeDividersTimerRef.current) {
80235
+ clearTimeout(resizeDividersTimerRef.current);
80236
+ resizeDividersTimerRef.current = null;
80237
+ }
80238
+ };
80239
+ }, []);
80023
80240
  const promptChar = isBashMode ? "!" : statusLinePrompt || ">";
80024
80241
  const promptVisualWidth = stringWidth(promptChar) + 1;
80025
80242
  const contentWidth = Math.max(0, columns - promptVisualWidth);
@@ -80454,7 +80671,7 @@ function Input({
80454
80671
  return null;
80455
80672
  }
80456
80673
  }, [ralphPending, ralphPendingYolo, ralphActive, currentMode]);
80457
- const horizontalLine = import_react70.useMemo(() => "─".repeat(columns), [columns]);
80674
+ const horizontalLine = import_react70.useMemo(() => "─".repeat(Math.max(0, columns - 1)), [columns]);
80458
80675
  const lowerPane = import_react70.useMemo(() => {
80459
80676
  return /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(jsx_dev_runtime47.Fragment, {
80460
80677
  children: [
@@ -80464,7 +80681,7 @@ function Input({
80464
80681
  interactionEnabled ? /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Box_default, {
80465
80682
  flexDirection: "column",
80466
80683
  children: [
80467
- /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
80684
+ !suppressDividers && /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
80468
80685
  dimColor: !isBashMode,
80469
80686
  color: isBashMode ? colors.bash.border : undefined,
80470
80687
  children: horizontalLine
@@ -80502,12 +80719,12 @@ function Input({
80502
80719
  }, undefined, false, undefined, this)
80503
80720
  ]
80504
80721
  }, undefined, true, undefined, this),
80505
- /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
80722
+ !suppressDividers && /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
80506
80723
  dimColor: !isBashMode,
80507
80724
  color: isBashMode ? colors.bash.border : undefined,
80508
80725
  children: horizontalLine
80509
80726
  }, undefined, false, undefined, this),
80510
- /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(InputAssist, {
80727
+ !suppressDividers && /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(InputAssist, {
80511
80728
  currentInput: value,
80512
80729
  cursorPosition: currentCursorPosition,
80513
80730
  onFileSelect: handleFileSelect,
@@ -80522,7 +80739,7 @@ function Input({
80522
80739
  workingDirectory: process.cwd(),
80523
80740
  conversationId
80524
80741
  }, undefined, false, undefined, this),
80525
- /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(InputFooter, {
80742
+ !suppressDividers && /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(InputFooter, {
80526
80743
  ctrlCPressed,
80527
80744
  escapePressed,
80528
80745
  isBashMode,
@@ -80532,6 +80749,8 @@ function Input({
80532
80749
  agentName,
80533
80750
  currentModel,
80534
80751
  currentReasoningEffort,
80752
+ currentSystemPromptId,
80753
+ currentToolset,
80535
80754
  isOpenAICodexProvider: currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
80536
80755
  isByokProvider: currentModelProvider?.startsWith("lc-") || currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
80537
80756
  hideFooter,
@@ -80583,8 +80802,11 @@ function Input({
80583
80802
  statusLineText,
80584
80803
  statusLineRight,
80585
80804
  statusLinePadding,
80805
+ currentSystemPromptId,
80806
+ currentToolset,
80586
80807
  promptChar,
80587
- promptVisualWidth
80808
+ promptVisualWidth,
80809
+ suppressDividers
80588
80810
  ]);
80589
80811
  if (!visible) {
80590
80812
  return null;
@@ -80662,6 +80884,8 @@ var init_InputRich = __esm(async () => {
80662
80884
  agentName,
80663
80885
  currentModel,
80664
80886
  currentReasoningEffort,
80887
+ currentSystemPromptId,
80888
+ currentToolset,
80665
80889
  isOpenAICodexProvider,
80666
80890
  isByokProvider,
80667
80891
  hideFooter,
@@ -80675,11 +80899,38 @@ var init_InputRich = __esm(async () => {
80675
80899
  const displayAgentName = truncateEnd(agentName || "Unnamed", maxAgentChars);
80676
80900
  const reasoningTag = getReasoningEffortTag(currentReasoningEffort);
80677
80901
  const byokExtraChars = isByokProvider ? 2 : 0;
80678
- const reservedChars = displayAgentName.length + byokExtraChars + 4;
80679
- const maxModelChars = Math.max(8, rightColumnWidth - reservedChars);
80902
+ const baseReservedChars = displayAgentName.length + byokExtraChars + 4;
80680
80903
  const modelWithReasoning = (currentModel ?? "unknown") + (reasoningTag ? ` (${reasoningTag})` : "");
80904
+ const suffixParts = [];
80905
+ if (currentSystemPromptId) {
80906
+ suffixParts.push(`s:${currentSystemPromptId}`);
80907
+ }
80908
+ if (currentToolset) {
80909
+ suffixParts.push(`t:${currentToolset}`);
80910
+ }
80911
+ const minSuffixBudget = suffixParts.length * 4;
80912
+ const maxModelChars = Math.max(8, rightColumnWidth - baseReservedChars - minSuffixBudget);
80681
80913
  const displayModel = truncateEnd(modelWithReasoning, maxModelChars);
80682
- const rightTextLength = displayAgentName.length + displayModel.length + byokExtraChars + 3;
80914
+ const baseTextLength = displayAgentName.length + displayModel.length + byokExtraChars + 3;
80915
+ const maxSuffixChars = Math.max(0, rightColumnWidth - baseTextLength);
80916
+ const displaySuffix = (() => {
80917
+ if (suffixParts.length === 0 || maxSuffixChars <= 0)
80918
+ return "";
80919
+ let remaining = maxSuffixChars;
80920
+ const out = [];
80921
+ for (const part of suffixParts) {
80922
+ if (remaining <= 1)
80923
+ break;
80924
+ const budget = remaining - 1;
80925
+ const clipped = truncateEnd(part, budget);
80926
+ if (!clipped)
80927
+ break;
80928
+ out.push(` ${clipped}`);
80929
+ remaining -= 1 + clipped.length;
80930
+ }
80931
+ return out.join("");
80932
+ })();
80933
+ const rightTextLength = baseTextLength + displaySuffix.length;
80683
80934
  const rightPrefixSpaces = Math.max(0, rightColumnWidth - rightTextLength);
80684
80935
  const rightLabel = import_react70.useMemo(() => {
80685
80936
  const parts = [];
@@ -80692,11 +80943,15 @@ var init_InputRich = __esm(async () => {
80692
80943
  parts.push(isOpenAICodexProvider ? source_default.hex("#74AA9C")("▲") : source_default.yellow("▲"));
80693
80944
  }
80694
80945
  parts.push(source_default.dim("]"));
80946
+ if (displaySuffix) {
80947
+ parts.push(source_default.dim(displaySuffix));
80948
+ }
80695
80949
  return parts.join("");
80696
80950
  }, [
80697
80951
  rightPrefixSpaces,
80698
80952
  displayAgentName,
80699
80953
  displayModel,
80954
+ displaySuffix,
80700
80955
  isByokProvider,
80701
80956
  isOpenAICodexProvider
80702
80957
  ]);
@@ -80791,11 +81046,36 @@ var init_InputRich = __esm(async () => {
80791
81046
  terminalWidth,
80792
81047
  shouldAnimate
80793
81048
  }) {
81049
+ const [isResizing, setIsResizing] = import_react70.useState(false);
81050
+ const resizeTimerRef = import_react70.useRef(null);
81051
+ const lastWidthRef = import_react70.useRef(terminalWidth);
81052
+ import_react70.useEffect(() => {
81053
+ if (terminalWidth === lastWidthRef.current)
81054
+ return;
81055
+ lastWidthRef.current = terminalWidth;
81056
+ setIsResizing(true);
81057
+ if (resizeTimerRef.current) {
81058
+ clearTimeout(resizeTimerRef.current);
81059
+ }
81060
+ resizeTimerRef.current = setTimeout(() => {
81061
+ resizeTimerRef.current = null;
81062
+ setIsResizing(false);
81063
+ }, 750);
81064
+ }, [terminalWidth]);
81065
+ import_react70.useEffect(() => {
81066
+ return () => {
81067
+ if (resizeTimerRef.current) {
81068
+ clearTimeout(resizeTimerRef.current);
81069
+ resizeTimerRef.current = null;
81070
+ }
81071
+ };
81072
+ }, []);
81073
+ const animate = shouldAnimate && !isResizing;
80794
81074
  const [shimmerOffset, setShimmerOffset] = import_react70.useState(-3);
80795
81075
  const [elapsedMs, setElapsedMs] = import_react70.useState(0);
80796
81076
  const streamStartRef = import_react70.useRef(null);
80797
81077
  import_react70.useEffect(() => {
80798
- if (!streaming || !visible || !shouldAnimate)
81078
+ if (!streaming || !visible || !animate)
80799
81079
  return;
80800
81080
  const id = setInterval(() => {
80801
81081
  setShimmerOffset((prev) => {
@@ -80806,23 +81086,29 @@ var init_InputRich = __esm(async () => {
80806
81086
  });
80807
81087
  }, 120);
80808
81088
  return () => clearInterval(id);
80809
- }, [streaming, thinkingMessage, visible, agentName, shouldAnimate]);
81089
+ }, [streaming, thinkingMessage, visible, agentName, animate]);
80810
81090
  import_react70.useEffect(() => {
80811
- if (!shouldAnimate) {
81091
+ if (!animate) {
80812
81092
  setShimmerOffset(-3);
80813
81093
  }
80814
- }, [shouldAnimate]);
81094
+ }, [animate]);
80815
81095
  import_react70.useEffect(() => {
80816
- if (streaming && visible) {
80817
- if (streamStartRef.current === null) {
80818
- streamStartRef.current = performance.now();
81096
+ if (!streaming || !visible || isResizing) {
81097
+ return;
81098
+ }
81099
+ if (streamStartRef.current === null) {
81100
+ streamStartRef.current = performance.now();
81101
+ }
81102
+ const id = setInterval(() => {
81103
+ if (streamStartRef.current !== null) {
81104
+ setElapsedMs(performance.now() - streamStartRef.current);
80819
81105
  }
80820
- const id = setInterval(() => {
80821
- if (streamStartRef.current !== null) {
80822
- setElapsedMs(performance.now() - streamStartRef.current);
80823
- }
80824
- }, 1000);
80825
- return () => clearInterval(id);
81106
+ }, 1000);
81107
+ return () => clearInterval(id);
81108
+ }, [streaming, visible, isResizing]);
81109
+ import_react70.useEffect(() => {
81110
+ if (streaming && visible) {
81111
+ return;
80826
81112
  }
80827
81113
  streamStartRef.current = null;
80828
81114
  setElapsedMs(0);
@@ -80842,7 +81128,7 @@ var init_InputRich = __esm(async () => {
80842
81128
  return "↑̸";
80843
81129
  }, [networkPhase]);
80844
81130
  const showErrorArrow = networkArrow === "↑̸";
80845
- const statusContentWidth = Math.max(0, terminalWidth - 2);
81131
+ const statusContentWidth = Math.max(0, terminalWidth - 3);
80846
81132
  const minMessageWidth = 12;
80847
81133
  const statusHintParts = import_react70.useMemo(() => {
80848
81134
  const parts = [];
@@ -80873,13 +81159,24 @@ var init_InputRich = __esm(async () => {
80873
81159
  const statusLabelWidth = Array.from(statusLabel).length;
80874
81160
  const messageColumnWidth = Math.max(0, Math.min(maxMessageWidth, Math.max(minMessageWidth, statusLabelWidth)));
80875
81161
  const statusHintText = import_react70.useMemo(() => {
80876
- const hintColor = source_default.hex(colors.subagent.hint);
80877
- const hintBold = hintColor.bold;
80878
81162
  const suffix = `${statusHintSuffix})`;
80879
81163
  if (interruptRequested) {
80880
- return hintColor(` (interrupting${suffix}`);
81164
+ return /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
81165
+ dimColor: true,
81166
+ children: ` (interrupting${suffix}`
81167
+ }, undefined, false, undefined, this);
80881
81168
  }
80882
- return hintColor(" (") + hintBold("esc") + hintColor(` to interrupt${suffix}`);
81169
+ return /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
81170
+ dimColor: true,
81171
+ children: [
81172
+ " (",
81173
+ /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
81174
+ bold: true,
81175
+ children: "esc"
81176
+ }, undefined, false, undefined, this),
81177
+ ` to interrupt${suffix}`
81178
+ ]
81179
+ }, undefined, true, undefined, this);
80883
81180
  }, [interruptRequested, statusHintSuffix]);
80884
81181
  if (!streaming || !visible) {
80885
81182
  return null;
@@ -80893,7 +81190,7 @@ var init_InputRich = __esm(async () => {
80893
81190
  flexShrink: 0,
80894
81191
  children: /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Text2, {
80895
81192
  color: colors.status.processing,
80896
- children: shouldAnimate ? /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Spinner2, {
81193
+ children: animate ? /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(Spinner2, {
80897
81194
  type: "layer"
80898
81195
  }, undefined, false, undefined, this) : "●"
80899
81196
  }, undefined, false, undefined, this)
@@ -80909,7 +81206,7 @@ var init_InputRich = __esm(async () => {
80909
81206
  children: /* @__PURE__ */ jsx_dev_runtime47.jsxDEV(ShimmerText, {
80910
81207
  boldPrefix: agentName || undefined,
80911
81208
  message: thinkingMessage,
80912
- shimmerOffset: shouldAnimate ? shimmerOffset : -3,
81209
+ shimmerOffset: animate ? shimmerOffset : -3,
80913
81210
  wrap: "truncate-end"
80914
81211
  }, undefined, false, undefined, this)
80915
81212
  }, undefined, false, undefined, this),
@@ -82793,7 +83090,7 @@ function getServerTarget(server) {
82793
83090
  }
82794
83091
  return "unknown";
82795
83092
  }
82796
- function truncateText(text, maxWidth) {
83093
+ function truncateText3(text, maxWidth) {
82797
83094
  if (text.length <= maxWidth)
82798
83095
  return text;
82799
83096
  if (maxWidth < 10)
@@ -83201,7 +83498,7 @@ var init_McpSelector = __esm(async () => {
83201
83498
  dimColor: true,
83202
83499
  children: [
83203
83500
  " ",
83204
- truncateText(toolDesc, terminalWidth - 6)
83501
+ truncateText3(toolDesc, terminalWidth - 6)
83205
83502
  ]
83206
83503
  }, undefined, true, undefined, this)
83207
83504
  }, undefined, false, undefined, this)
@@ -83387,7 +83684,7 @@ var init_McpSelector = __esm(async () => {
83387
83684
  const typeLen = serverType.length;
83388
83685
  const fixedChars = 4 + 3 + 3 + typeLen;
83389
83686
  const availableForTarget = Math.max(20, terminalWidth - nameLen - fixedChars);
83390
- const displayTarget = truncateText(target, availableForTarget);
83687
+ const displayTarget = truncateText3(target, availableForTarget);
83391
83688
  return /* @__PURE__ */ jsx_dev_runtime50.jsxDEV(Box_default, {
83392
83689
  flexDirection: "column",
83393
83690
  marginBottom: 1,
@@ -86304,7 +86601,7 @@ function formatLocalTime(dateStr) {
86304
86601
  };
86305
86602
  return date.toLocaleString(undefined, options);
86306
86603
  }
86307
- function truncateText2(text, maxWidth) {
86604
+ function truncateText4(text, maxWidth) {
86308
86605
  if (text.length <= maxWidth)
86309
86606
  return text;
86310
86607
  return `${text.slice(0, maxWidth - 3)}...`;
@@ -86746,7 +87043,7 @@ function MessageSearch({
86746
87043
  const isAssistant = msgType === "assistant_message" || msgType === "reasoning_message";
86747
87044
  const emoji = isAssistant ? "\uD83D\uDC7E" : "\uD83D\uDC64";
86748
87045
  const availableWidth = Math.max(20, terminalWidth - 8);
86749
- const displayText = truncateText2(messageText.replace(/\n/g, " "), availableWidth);
87046
+ const displayText = truncateText4(messageText.replace(/\n/g, " "), availableWidth);
86750
87047
  const idToShow = conversationIdFromMsg || agentIdFromMsg;
86751
87048
  const msgId = "message_id" in msg ? String(msg.message_id) : "result";
86752
87049
  const uniqueKey = `${msgId}-${actualIndex}`;
@@ -93358,6 +93655,9 @@ function buildStatusLinePayload(input) {
93358
93655
  ...input.sessionId ? { session_id: input.sessionId } : {},
93359
93656
  transcript_path: null,
93360
93657
  version: getVersion(),
93658
+ reasoning_effort: input.reasoningEffort ?? null,
93659
+ system_prompt_id: input.systemPromptId ?? null,
93660
+ toolset: input.toolset ?? null,
93361
93661
  model: {
93362
93662
  id: input.modelId ?? null,
93363
93663
  display_name: input.modelDisplayName ?? null
@@ -93735,6 +94035,9 @@ function toPayloadInput(inputs) {
93735
94035
  return {
93736
94036
  modelId: inputs.modelId,
93737
94037
  modelDisplayName: inputs.modelDisplayName,
94038
+ reasoningEffort: inputs.reasoningEffort,
94039
+ systemPromptId: inputs.systemPromptId,
94040
+ toolset: inputs.toolset,
93738
94041
  currentDirectory: inputs.currentDirectory,
93739
94042
  projectDirectory: inputs.projectDirectory,
93740
94043
  sessionId: inputs.sessionId,
@@ -95024,7 +95327,7 @@ function updateCommandResult4(buffersRef, refreshDerived, cmdId, input, output,
95024
95327
  refreshDerived();
95025
95328
  }
95026
95329
  async function handleListen(ctx, msg, opts = {}) {
95027
- if (msg.trim() === "/listen off") {
95330
+ if (msg.trim() === "/remote off") {
95028
95331
  const { stopListenerClient: stopListenerClient2, isListenerActive: isListenerActive2 } = await init_listen_client().then(() => exports_listen_client);
95029
95332
  if (!isListenerActive2()) {
95030
95333
  addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, "Listen mode is not active.", false);
@@ -95037,8 +95340,8 @@ Listener disconnected from Letta Cloud.`, true);
95037
95340
  return;
95038
95341
  }
95039
95342
  if (msg.includes("--help") || msg.includes("-h")) {
95040
- addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /listen [--env-name <name>]
95041
- /listen off
95343
+ addCommandResult4(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /remote [--env-name <name>]
95344
+ /remote off
95042
95345
 
95043
95346
  Register this letta-code instance to receive messages from Letta Cloud.
95044
95347
 
@@ -95048,9 +95351,9 @@ Options:
95048
95351
  -h, --help Show this help message
95049
95352
 
95050
95353
  Examples:
95051
- /listen # Start listener with hostname
95052
- /listen --env-name "work-laptop" # Start with custom name
95053
- /listen off # Stop listening
95354
+ /remote # Start listener with hostname
95355
+ /remote --env-name "work-laptop" # Start with custom name
95356
+ /remote off # Stop listening
95054
95357
 
95055
95358
  Once connected, this instance will listen for incoming messages from cloud agents.
95056
95359
  Messages will be executed locally using your letta-code environment.`, true);
@@ -95091,7 +95394,7 @@ Device: ${deviceName} (${deviceId.slice(0, 8)}...)`, true, "running");
95091
95394
  if (!apiKey) {
95092
95395
  throw new Error("Missing LETTA_API_KEY");
95093
95396
  }
95094
- const registerUrl = `${serverUrl}/v1/listeners/register`;
95397
+ const registerUrl = `${serverUrl}/v1/environments/register`;
95095
95398
  const registerResponse = await fetch(registerUrl, {
95096
95399
  method: "POST",
95097
95400
  headers: {
@@ -96038,6 +96341,7 @@ function App2({
96038
96341
  const abortControllerRef = import_react98.useRef(null);
96039
96342
  const userCancelledRef = import_react98.useRef(false);
96040
96343
  const llmApiErrorRetriesRef = import_react98.useRef(0);
96344
+ const emptyResponseRetriesRef = import_react98.useRef(0);
96041
96345
  const conversationBusyRetriesRef = import_react98.useRef(0);
96042
96346
  const [messageQueue, setMessageQueue] = import_react98.useState([]);
96043
96347
  const messageQueueRef = import_react98.useRef([]);
@@ -96113,15 +96417,85 @@ function App2({
96113
96417
  const [stableColumns, setStableColumns] = import_react98.useState(rawColumns);
96114
96418
  const stableColumnsTimeoutRef = import_react98.useRef(null);
96115
96419
  const prevColumnsRef = import_react98.useRef(rawColumns);
96420
+ const lastResizeColumnsRef = import_react98.useRef(rawColumns);
96421
+ const lastResizeRowsRef = import_react98.useRef(terminalRows);
96116
96422
  const lastClearedColumnsRef = import_react98.useRef(rawColumns);
96117
96423
  const pendingResizeRef = import_react98.useRef(false);
96118
96424
  const pendingResizeColumnsRef = import_react98.useRef(null);
96119
96425
  const [staticRenderEpoch, setStaticRenderEpoch] = import_react98.useState(0);
96120
96426
  const resizeClearTimeout = import_react98.useRef(null);
96121
96427
  const lastClearAtRef = import_react98.useRef(0);
96428
+ const resizeGestureTimeoutRef = import_react98.useRef(null);
96429
+ const didImmediateShrinkClearRef = import_react98.useRef(false);
96122
96430
  const isInitialResizeRef = import_react98.useRef(true);
96123
96431
  const columns = stableColumns;
96432
+ const chromeColumns = Math.min(rawColumns, stableColumns);
96124
96433
  const debugFlicker = process.env.LETTA_DEBUG_FLICKER === "1";
96434
+ import_react98.useEffect(() => {
96435
+ if (typeof process === "undefined" || !process.stdout || !("on" in process.stdout) || !process.stdout.isTTY) {
96436
+ return;
96437
+ }
96438
+ const stdout = process.stdout;
96439
+ const onResize = () => {
96440
+ const nextColumns = stdout.columns ?? lastResizeColumnsRef.current;
96441
+ const nextRows = stdout.rows ?? lastResizeRowsRef.current;
96442
+ const prevColumns = lastResizeColumnsRef.current;
96443
+ const prevRows = lastResizeRowsRef.current;
96444
+ lastResizeColumnsRef.current = nextColumns;
96445
+ lastResizeRowsRef.current = nextRows;
96446
+ if (isInitialResizeRef.current) {
96447
+ return;
96448
+ }
96449
+ const shrunk = nextColumns < prevColumns || nextRows < prevRows;
96450
+ if (!shrunk) {
96451
+ if (resizeGestureTimeoutRef.current) {
96452
+ clearTimeout(resizeGestureTimeoutRef.current);
96453
+ }
96454
+ resizeGestureTimeoutRef.current = setTimeout(() => {
96455
+ resizeGestureTimeoutRef.current = null;
96456
+ didImmediateShrinkClearRef.current = false;
96457
+ }, RESIZE_SETTLE_MS);
96458
+ return;
96459
+ }
96460
+ if (didImmediateShrinkClearRef.current) {
96461
+ if (resizeGestureTimeoutRef.current) {
96462
+ clearTimeout(resizeGestureTimeoutRef.current);
96463
+ }
96464
+ resizeGestureTimeoutRef.current = setTimeout(() => {
96465
+ resizeGestureTimeoutRef.current = null;
96466
+ didImmediateShrinkClearRef.current = false;
96467
+ }, RESIZE_SETTLE_MS);
96468
+ return;
96469
+ }
96470
+ if (debugFlicker) {
96471
+ console.error(`[debug:flicker:resize-immediate-clear] next=${nextColumns}x${nextRows} prev=${prevColumns}x${prevRows} streaming=${streamingRef.current}`);
96472
+ }
96473
+ if (resizeClearTimeout.current) {
96474
+ clearTimeout(resizeClearTimeout.current);
96475
+ resizeClearTimeout.current = null;
96476
+ }
96477
+ stdout.write(CLEAR_SCREEN_AND_HOME);
96478
+ setStaticRenderEpoch((epoch) => epoch + 1);
96479
+ lastClearedColumnsRef.current = nextColumns;
96480
+ lastClearAtRef.current = Date.now();
96481
+ didImmediateShrinkClearRef.current = true;
96482
+ if (resizeGestureTimeoutRef.current) {
96483
+ clearTimeout(resizeGestureTimeoutRef.current);
96484
+ }
96485
+ resizeGestureTimeoutRef.current = setTimeout(() => {
96486
+ resizeGestureTimeoutRef.current = null;
96487
+ didImmediateShrinkClearRef.current = false;
96488
+ }, RESIZE_SETTLE_MS);
96489
+ };
96490
+ stdout.on("resize", onResize);
96491
+ return () => {
96492
+ stdout.off("resize", onResize);
96493
+ if (resizeGestureTimeoutRef.current) {
96494
+ clearTimeout(resizeGestureTimeoutRef.current);
96495
+ resizeGestureTimeoutRef.current = null;
96496
+ }
96497
+ };
96498
+ }, [debugFlicker, streamingRef]);
96125
96499
  import_react98.useEffect(() => {
96126
96500
  if (rawColumns === stableColumns) {
96127
96501
  if (stableColumnsTimeoutRef.current) {
@@ -96227,6 +96601,15 @@ function App2({
96227
96601
  scheduleResizeClear(rawColumns);
96228
96602
  prevColumnsRef.current = rawColumns;
96229
96603
  }, [rawColumns, streaming, scheduleResizeClear]);
96604
+ import_react98.useEffect(() => {
96605
+ if (isInitialResizeRef.current)
96606
+ return;
96607
+ if (streaming)
96608
+ return;
96609
+ if (stableColumns === lastClearedColumnsRef.current)
96610
+ return;
96611
+ scheduleResizeClear(stableColumns);
96612
+ }, [stableColumns, streaming, scheduleResizeClear]);
96230
96613
  import_react98.useEffect(() => {
96231
96614
  if (streaming) {
96232
96615
  if (resizeClearTimeout.current) {
@@ -96389,6 +96772,9 @@ function App2({
96389
96772
  const statusLine = useConfigurableStatusLine({
96390
96773
  modelId: llmConfigRef.current?.model ?? null,
96391
96774
  modelDisplayName: currentModelDisplay,
96775
+ reasoningEffort: currentReasoningEffort,
96776
+ systemPromptId: currentSystemPromptId,
96777
+ toolset: currentToolset,
96392
96778
  currentDirectory: process.cwd(),
96393
96779
  projectDirectory,
96394
96780
  sessionId: conversationId,
@@ -96401,7 +96787,7 @@ function App2({
96401
96787
  usedContextTokens: contextTrackerRef.current.lastContextTokens,
96402
96788
  permissionMode: uiPermissionMode,
96403
96789
  networkPhase,
96404
- terminalWidth: columns,
96790
+ terminalWidth: chromeColumns,
96405
96791
  triggerVersion: statusLineTriggerVersion
96406
96792
  });
96407
96793
  const previousStreamingForStatusLineRef = import_react98.useRef(streaming);
@@ -96411,7 +96797,7 @@ function App2({
96411
96797
  }
96412
96798
  previousStreamingForStatusLineRef.current = streaming;
96413
96799
  }, [streaming, triggerStatusLineRefresh]);
96414
- const statusLineRefreshIdentity = `${conversationId}|${currentModelDisplay ?? ""}|${currentModelProvider ?? ""}|${agentName ?? ""}|${columns}|${contextWindowSize ?? ""}`;
96800
+ const statusLineRefreshIdentity = `${conversationId}|${currentModelDisplay ?? ""}|${currentModelProvider ?? ""}|${agentName ?? ""}|${columns}|${contextWindowSize ?? ""}|${currentReasoningEffort ?? ""}|${currentSystemPromptId ?? ""}|${currentToolset ?? ""}`;
96415
96801
  import_react98.useEffect(() => {
96416
96802
  triggerStatusLineRefresh();
96417
96803
  }, [statusLineRefreshIdentity, triggerStatusLineRefresh]);
@@ -96887,7 +97273,8 @@ function App2({
96887
97273
  refreshDerived();
96888
97274
  if (!skipTelemetry) {
96889
97275
  telemetry.trackError("ui_error", text, "error_display", {
96890
- modelId: currentModelId || undefined
97276
+ modelId: currentModelId || undefined,
97277
+ recentChunks: chunkLog.getEntries()
96891
97278
  });
96892
97279
  }
96893
97280
  }, [refreshDerived, currentModelId]);
@@ -97104,6 +97491,7 @@ ${newState.originalPrompt}`
97104
97491
  processingConversationRef.current += 1;
97105
97492
  if (!allowReentry) {
97106
97493
  llmApiErrorRetriesRef.current = 0;
97494
+ emptyResponseRetriesRef.current = 0;
97107
97495
  conversationBusyRetriesRef.current = 0;
97108
97496
  }
97109
97497
  let currentRunId;
@@ -97206,6 +97594,10 @@ ${newState.originalPrompt}`
97206
97594
  if (preStreamAction === "retry_conversation_busy") {
97207
97595
  conversationBusyRetriesRef.current += 1;
97208
97596
  const retryDelayMs = CONVERSATION_BUSY_RETRY_BASE_DELAY_MS * 2 ** (conversationBusyRetriesRef.current - 1);
97597
+ telemetry.trackError("retry_conversation_busy", errorDetail || "Conversation is busy", "pre_stream_retry", {
97598
+ httpStatus: preStreamError instanceof APIError2 ? preStreamError.status : undefined,
97599
+ modelId: currentModelId || undefined
97600
+ });
97209
97601
  const statusId = uid5("status");
97210
97602
  buffersRef.current.byId.set(statusId, {
97211
97603
  kind: "status",
@@ -97237,6 +97629,10 @@ ${newState.originalPrompt}`
97237
97629
  const attempt = llmApiErrorRetriesRef.current;
97238
97630
  const retryAfterMs = preStreamError instanceof APIError2 ? parseRetryAfterHeaderMs(preStreamError.headers?.get("retry-after")) : null;
97239
97631
  const delayMs = retryAfterMs ?? 1000 * 2 ** (attempt - 1);
97632
+ telemetry.trackError("retry_pre_stream_transient", errorDetail || "Pre-stream transient error", "pre_stream_retry", {
97633
+ httpStatus: preStreamError instanceof APIError2 ? preStreamError.status : undefined,
97634
+ modelId: currentModelId || undefined
97635
+ });
97240
97636
  const statusId = uid5("status");
97241
97637
  buffersRef.current.byId.set(statusId, {
97242
97638
  kind: "status",
@@ -97403,6 +97799,7 @@ ${newState.originalPrompt}`
97403
97799
  })();
97404
97800
  closeTrajectorySegment();
97405
97801
  llmApiErrorRetriesRef.current = 0;
97802
+ emptyResponseRetriesRef.current = 0;
97406
97803
  conversationBusyRetriesRef.current = 0;
97407
97804
  lastDequeuedMessageRef.current = null;
97408
97805
  lastSentInputRef.current = null;
@@ -97913,11 +98310,46 @@ ${feedback}
97913
98310
  buffersRef.current.interrupted = false;
97914
98311
  continue;
97915
98312
  }
98313
+ if (isEmptyResponseRetryable(stopReasonToHandle === "llm_api_error" ? "llm_error" : undefined, detailFromRun, emptyResponseRetriesRef.current, EMPTY_RESPONSE_MAX_RETRIES2)) {
98314
+ emptyResponseRetriesRef.current += 1;
98315
+ const attempt = emptyResponseRetriesRef.current;
98316
+ const delayMs = 500 * attempt;
98317
+ if (attempt >= EMPTY_RESPONSE_MAX_RETRIES2) {
98318
+ currentInput = [
98319
+ ...currentInput,
98320
+ {
98321
+ type: "message",
98322
+ role: "system",
98323
+ content: `<system-reminder>The previous response was empty. Please provide a response with either text content or a tool call.</system-reminder>`
98324
+ }
98325
+ ];
98326
+ }
98327
+ const statusId = uid5("status");
98328
+ buffersRef.current.byId.set(statusId, {
98329
+ kind: "status",
98330
+ id: statusId,
98331
+ lines: [
98332
+ `Empty LLM response, retrying (attempt ${attempt}/${EMPTY_RESPONSE_MAX_RETRIES2})...`
98333
+ ]
98334
+ });
98335
+ buffersRef.current.order.push(statusId);
98336
+ refreshDerived();
98337
+ await new Promise((resolve29) => setTimeout(resolve29, delayMs));
98338
+ buffersRef.current.byId.delete(statusId);
98339
+ buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
98340
+ refreshDerived();
98341
+ buffersRef.current.interrupted = false;
98342
+ continue;
98343
+ }
97916
98344
  const retriable = await isRetriableError(stopReasonToHandle, lastRunId);
97917
98345
  if (retriable && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES2) {
97918
98346
  llmApiErrorRetriesRef.current += 1;
97919
98347
  const attempt = llmApiErrorRetriesRef.current;
97920
98348
  const delayMs = 1000 * 2 ** (attempt - 1);
98349
+ telemetry.trackError("retry_post_stream_error", detailFromRun || fallbackError || `Stream stopped: ${stopReasonToHandle}`, "post_stream_retry", {
98350
+ modelId: currentModelId || undefined,
98351
+ runId: lastRunId ?? undefined
98352
+ });
97921
98353
  const statusId = uid5("status");
97922
98354
  const statusLines = [getRetryStatusMessage(detailFromRun)];
97923
98355
  buffersRef.current.byId.set(statusId, {
@@ -97945,13 +98377,15 @@ ${feedback}
97945
98377
  }
97946
98378
  }
97947
98379
  llmApiErrorRetriesRef.current = 0;
98380
+ emptyResponseRetriesRef.current = 0;
97948
98381
  conversationBusyRetriesRef.current = 0;
97949
98382
  markIncompleteToolsAsCancelled(buffersRef.current, true, "stream_error");
97950
98383
  telemetry.trackError(fallbackError ? "FallbackError" : stopReasonToHandle || "unknown_stop_reason", fallbackError || `Stream stopped with reason: ${stopReasonToHandle}`, "message_stream", {
97951
98384
  modelId: currentModelId || undefined,
97952
- runId: lastRunId ?? undefined
98385
+ runId: lastRunId ?? undefined,
98386
+ recentChunks: chunkLog.getEntries()
97953
98387
  });
97954
- if (fallbackError) {
98388
+ if (fallbackError && !lastRunId) {
97955
98389
  setNetworkPhase("error");
97956
98390
  const errorMsg = lastRunId ? `Stream error: ${fallbackError}
97957
98391
  (run_id: ${lastRunId})` : `Stream error: ${fallbackError}`;
@@ -98035,7 +98469,8 @@ ${feedback}
98035
98469
  telemetry.trackError(errorType, errorMessage, "message_stream", {
98036
98470
  httpStatus,
98037
98471
  modelId: currentModelId || undefined,
98038
- runId: currentRunId
98472
+ runId: currentRunId,
98473
+ recentChunks: chunkLog.getEntries()
98039
98474
  });
98040
98475
  const errorDetails = formatErrorDetails2(e, agentIdRef.current);
98041
98476
  appendError(errorDetails, true);
@@ -98966,7 +99401,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
98966
99401
  }
98967
99402
  return { submitted: true };
98968
99403
  }
98969
- if (trimmed === "/listen" || trimmed.startsWith("/listen ")) {
99404
+ if (trimmed === "/remote" || trimmed.startsWith("/remote ")) {
98970
99405
  const parts = Array.from(trimmed.matchAll(/"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g), (match3) => match3[1] ?? match3[2] ?? match3[3]);
98971
99406
  let name;
98972
99407
  let _listenAgentId;
@@ -99086,6 +99521,9 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
99086
99521
  const result2 = await executeStatusLineCommand(config.command, buildStatusLinePayload({
99087
99522
  modelId: llmConfigRef.current?.model ?? null,
99088
99523
  modelDisplayName: currentModelDisplay,
99524
+ reasoningEffort: currentReasoningEffort,
99525
+ systemPromptId: currentSystemPromptId,
99526
+ toolset: currentToolset,
99089
99527
  currentDirectory: wd,
99090
99528
  projectDirectory,
99091
99529
  sessionId: conversationIdRef.current,
@@ -99098,7 +99536,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
99098
99536
  usedContextTokens: contextTrackerRef.current.lastContextTokens,
99099
99537
  permissionMode: uiPermissionMode,
99100
99538
  networkPhase,
99101
- terminalWidth: columns
99539
+ terminalWidth: chromeColumns
99102
99540
  }), { timeout: config.timeout, workingDirectory: wd });
99103
99541
  if (result2.ok) {
99104
99542
  cmd.finish(`Output: ${result2.text} (${result2.durationMs}ms)`, true);
@@ -102583,6 +103021,8 @@ Plan file path: ${planFilePath}`;
102583
103021
  currentModel: currentModelDisplay,
102584
103022
  currentModelProvider,
102585
103023
  currentReasoningEffort,
103024
+ currentSystemPromptId,
103025
+ currentToolset,
102586
103026
  messageQueue,
102587
103027
  onEnterQueueEditMode: handleEnterQueueEditMode,
102588
103028
  onEscapeCancel: profileConfirmPending ? handleProfileEscapeCancel : undefined,
@@ -102595,7 +103035,7 @@ Plan file path: ${planFilePath}`;
102595
103035
  restoredInput,
102596
103036
  onRestoredInputConsumed: () => setRestoredInput(null),
102597
103037
  networkPhase,
102598
- terminalWidth: columns,
103038
+ terminalWidth: chromeColumns,
102599
103039
  shouldAnimate,
102600
103040
  statusLineText: statusLine.text || undefined,
102601
103041
  statusLineRight: statusLine.rightText || undefined,
@@ -103174,7 +103614,7 @@ Open /mcp to attach or detach tools for this server.`, true);
103174
103614
  ]
103175
103615
  }, resumeKey, true, undefined, this);
103176
103616
  }
103177
- var import_react98, jsx_dev_runtime75, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES2 = 3, CONVERSATION_BUSY_MAX_RETRIES2 = 3, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 2500, INTERRUPT_MESSAGE = "Interrupted – tell the agent what to do differently. Something went wrong? Use /feedback to report issues.", ERROR_FEEDBACK_HINT = "Something went wrong? Use /feedback to report issues.", OPUS_BEDROCK_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to Bedrock Opus 4.5", PROVIDER_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to another provider", INTERACTIVE_SLASH_COMMANDS, NON_STATE_COMMANDS, APPROVAL_OPTIONS_HEIGHT = 8, APPROVAL_PREVIEW_BUFFER = 4, MIN_WRAP_WIDTH = 10, TEXT_WRAP_GUTTER = 6, DIFF_WRAP_GUTTER = 12, AUTO_REFLECTION_DESCRIPTION = "Reflect on recent conversations", AUTO_REFLECTION_PROMPT = "Review recent conversation history and update memory files with important information worth preserving.";
103617
+ var import_react98, jsx_dev_runtime75, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, RESIZE_SETTLE_MS = 250, MIN_CLEAR_INTERVAL_MS = 750, STABLE_WIDTH_SETTLE_MS = 180, TOOL_CALL_COMMIT_DEFER_MS = 50, ANIMATION_RESUME_HYSTERESIS_ROWS = 2, EAGER_CANCEL = true, LLM_API_ERROR_MAX_RETRIES2 = 3, EMPTY_RESPONSE_MAX_RETRIES2 = 2, CONVERSATION_BUSY_MAX_RETRIES2 = 3, CONVERSATION_BUSY_RETRY_BASE_DELAY_MS = 2500, INTERRUPT_MESSAGE = "Interrupted – tell the agent what to do differently. Something went wrong? Use /feedback to report issues.", ERROR_FEEDBACK_HINT = "Something went wrong? Use /feedback to report issues.", OPUS_BEDROCK_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to Bedrock Opus 4.5", PROVIDER_FALLBACK_HINT = "Downstream provider issues? Use /model to switch to another provider", INTERACTIVE_SLASH_COMMANDS, NON_STATE_COMMANDS, APPROVAL_OPTIONS_HEIGHT = 8, APPROVAL_PREVIEW_BUFFER = 4, MIN_WRAP_WIDTH = 10, TEXT_WRAP_GUTTER = 6, DIFF_WRAP_GUTTER = 12, AUTO_REFLECTION_DESCRIPTION = "Reflect on recent conversations", AUTO_REFLECTION_PROMPT = "Review recent conversation history and update memory files with important information worth preserving.";
103178
103618
  var init_App2 = __esm(async () => {
103179
103619
  init_error();
103180
103620
  init_check_approval();
@@ -106697,7 +107137,7 @@ async function runListenSubcommand(argv) {
106697
107137
  return 1;
106698
107138
  }
106699
107139
  const serverUrl = getServerUrl();
106700
- const registerUrl = `${serverUrl}/v1/listeners/register`;
107140
+ const registerUrl = `${serverUrl}/v1/environments/register`;
106701
107141
  const registerResponse = await fetch(registerUrl, {
106702
107142
  method: "POST",
106703
107143
  headers: {
@@ -107172,7 +107612,7 @@ async function runSubcommand(argv) {
107172
107612
  return runMessagesSubcommand(rest);
107173
107613
  case "blocks":
107174
107614
  return runBlocksSubcommand(rest);
107175
- case "listen":
107615
+ case "remote":
107176
107616
  return runListenSubcommand(rest);
107177
107617
  default:
107178
107618
  return null;
@@ -108495,7 +108935,8 @@ class TelemetryManager2 {
108495
108935
  context: context3,
108496
108936
  http_status: options?.httpStatus,
108497
108937
  model_id: options?.modelId,
108498
- run_id: options?.runId
108938
+ run_id: options?.runId,
108939
+ recent_chunks: options?.recentChunks
108499
108940
  };
108500
108941
  this.track("error", data);
108501
108942
  }
@@ -109090,7 +109531,6 @@ async function main() {
109090
109531
  continue: { type: "boolean" },
109091
109532
  resume: { type: "boolean", short: "r" },
109092
109533
  conversation: { type: "string", short: "C" },
109093
- default: { type: "boolean" },
109094
109534
  "new-agent": { type: "boolean" },
109095
109535
  new: { type: "boolean" },
109096
109536
  "init-blocks": { type: "string" },
@@ -109176,15 +109616,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
109176
109616
  const shouldContinue = values.continue ?? false;
109177
109617
  const shouldResume = values.resume ?? false;
109178
109618
  let specifiedConversationId = values.conversation ?? null;
109179
- const useDefaultConv = values.default ?? false;
109180
109619
  const forceNew = values["new-agent"] ?? false;
109181
- if (useDefaultConv) {
109182
- if (specifiedConversationId && specifiedConversationId !== "default") {
109183
- console.error("Error: --default cannot be used with --conversation (they're mutually exclusive)");
109184
- process.exit(1);
109185
- }
109186
- specifiedConversationId = "default";
109187
- }
109188
109620
  const forceNewConversation = values.new ?? false;
109189
109621
  const initBlocksRaw = values["init-blocks"];
109190
109622
  const baseToolsRaw = values["base-tools"];
@@ -109197,7 +109629,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
109197
109629
  specifiedAgentId = specifiedConversationId;
109198
109630
  specifiedConversationId = "default";
109199
109631
  }
109200
- if (specifiedConversationId === "default" && !specifiedAgentId) {
109632
+ if (specifiedConversationId === "default" && !specifiedAgentId && !forceNew) {
109201
109633
  console.error("Error: --conv default requires --agent <agent-id>");
109202
109634
  console.error("Usage: letta --agent agent-xyz --conv default");
109203
109635
  console.error(" or: letta --conv agent-xyz (shorthand)");
@@ -109495,7 +109927,7 @@ Error: ${message}`);
109495
109927
  await loadTools2(modelForTools);
109496
109928
  markMilestone2("TOOLS_LOADED");
109497
109929
  const { handleHeadlessCommand: handleHeadlessCommand2 } = await init_headless().then(() => exports_headless);
109498
- await handleHeadlessCommand2(process.argv, specifiedModel, skillsDirectory, resolvedSkillSources, !noSystemInfoReminderFlag);
109930
+ await handleHeadlessCommand2(processedArgs, specifiedModel, skillsDirectory, resolvedSkillSources, !noSystemInfoReminderFlag);
109499
109931
  return;
109500
109932
  }
109501
109933
  markMilestone2("TUI_MODE_START");
@@ -110239,4 +110671,4 @@ Error during initialization: ${message}`);
110239
110671
  }
110240
110672
  main();
110241
110673
 
110242
- //# debugId=67DFEE6A8897432D64756E2164756E21
110674
+ //# debugId=3463E794B9AA830764756E2164756E21