@letta-ai/letta-code 0.26.0 → 0.26.1

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 +343 -162
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -6429,7 +6429,7 @@ var package_default;
6429
6429
  var init_package = __esm(() => {
6430
6430
  package_default = {
6431
6431
  name: "@letta-ai/letta-code",
6432
- version: "0.26.0",
6432
+ version: "0.26.1",
6433
6433
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
6434
6434
  type: "module",
6435
6435
  packageManager: "bun@1.3.0",
@@ -235572,57 +235572,13 @@ var init_local_agent_listing = __esm(() => {
235572
235572
  init_paths();
235573
235573
  });
235574
235574
 
235575
- // src/cli/helpers/recent-agent-options.ts
235576
- function sortRecentAgents(agents, currentAgentId) {
235577
- return agents.toSorted((a2, b3) => {
235578
- if (currentAgentId) {
235579
- if (a2.agent.id === currentAgentId)
235580
- return -1;
235581
- if (b3.agent.id === currentAgentId)
235582
- return 1;
235583
- }
235584
- const aTime = a2.agent.last_run_completion ? new Date(a2.agent.last_run_completion).getTime() : 0;
235585
- const bTime = b3.agent.last_run_completion ? new Date(b3.agent.last_run_completion).getTime() : 0;
235586
- return bTime - aTime;
235587
- });
235588
- }
235589
- async function getRecentAgentOptions(options3) {
235590
- const includeLocal = options3?.includeLocal !== false;
235591
- const includeConstellation = options3?.includeConstellation !== false;
235592
- const limit3 = options3?.limit ?? 5;
235593
- const localAgents = includeLocal ? listLocalAgentsFromDisk().map((agent2) => ({ agent: agent2, isLocal: true })) : [];
235594
- const constellationAgents = includeConstellation ? await (async () => {
235595
- try {
235596
- const client = await getClient();
235597
- const result = await client.agents.list({
235598
- limit: limit3,
235599
- include: ["agent.blocks"],
235600
- order: "desc",
235601
- order_by: "last_run_completion"
235602
- });
235603
- return result.items.map((agent2) => ({ agent: agent2, isLocal: false }));
235604
- } catch {
235605
- return [];
235606
- }
235607
- })() : [];
235608
- const seen = new Set;
235609
- const deduped = sortRecentAgents([...localAgents, ...constellationAgents].filter((item) => {
235610
- if (seen.has(item.agent.id))
235611
- return false;
235612
- seen.add(item.agent.id);
235613
- return true;
235614
- }), options3?.currentAgentId);
235615
- return deduped.slice(0, limit3);
235616
- }
235617
- var init_recent_agent_options = __esm(() => {
235618
- init_client2();
235619
- init_local_agent_listing();
235620
- });
235621
-
235622
235575
  // src/cli/helpers/startup-model-display.ts
235576
+ function shouldHideReasoningForModelDisplay(modelDisplay) {
235577
+ return modelDisplay === STARTUP_NO_MODEL_LABEL;
235578
+ }
235623
235579
  function getStartupModelDisplayOverride(options3) {
235624
- const { isLocalBackend, startupHasAvailableLocalModels, agentProvenance } = options3;
235625
- if (isLocalBackend && !startupHasAvailableLocalModels && agentProvenance?.isNew) {
235580
+ const { isLocalBackend, startupHasAvailableLocalModels } = options3;
235581
+ if (isLocalBackend && !startupHasAvailableLocalModels) {
235626
235582
  return STARTUP_NO_MODEL_LABEL;
235627
235583
  }
235628
235584
  return null;
@@ -235830,7 +235786,6 @@ function WelcomeScreen({
235830
235786
  loadingState,
235831
235787
  continueSession,
235832
235788
  agentState,
235833
- agentProvenance,
235834
235789
  startupHasAvailableLocalModels = true
235835
235790
  }) {
235836
235791
  useTerminalWidth();
@@ -235841,8 +235796,7 @@ function WelcomeScreen({
235841
235796
  const fullModel = llmConfig?.model_endpoint_type && llmConfig?.model ? `${llmConfig.model_endpoint_type}/${llmConfig.model}` : llmConfig?.model ?? null;
235842
235797
  const startupModelDisplayOverride = getStartupModelDisplayOverride({
235843
235798
  isLocalBackend: isLocalBackendEnabled(),
235844
- startupHasAvailableLocalModels,
235845
- agentProvenance
235799
+ startupHasAvailableLocalModels
235846
235800
  });
235847
235801
  const model = startupModelDisplayOverride ?? (fullModel ? getModelDisplayName(fullModel) ?? fullModel.split("/").pop() : undefined);
235848
235802
  const initialAuth = getInitialAuthMethod();
@@ -237767,8 +237721,37 @@ async function generatePKCE2() {
237767
237721
  const codeChallenge = await generateCodeChallenge(codeVerifier);
237768
237722
  return { codeVerifier, codeChallenge };
237769
237723
  }
237770
- function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaultPort) {
237724
+ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaultPort, signal) {
237771
237725
  return new Promise((resolve29, reject) => {
237726
+ if (signal?.aborted) {
237727
+ const error54 = new Error("OAuth callback server cancelled");
237728
+ error54.name = "AbortError";
237729
+ reject(error54);
237730
+ return;
237731
+ }
237732
+ let settled = false;
237733
+ let timeout = null;
237734
+ const finish = (callback) => {
237735
+ if (settled)
237736
+ return;
237737
+ settled = true;
237738
+ if (timeout) {
237739
+ clearTimeout(timeout);
237740
+ timeout = null;
237741
+ }
237742
+ if (signal) {
237743
+ signal.removeEventListener("abort", onAbort);
237744
+ }
237745
+ callback();
237746
+ };
237747
+ const onAbort = () => {
237748
+ server.close();
237749
+ finish(() => {
237750
+ const error54 = new Error("OAuth callback server cancelled");
237751
+ error54.name = "AbortError";
237752
+ reject(error54);
237753
+ });
237754
+ };
237772
237755
  const server = http3.createServer((req, res) => {
237773
237756
  const url2 = new URL(req.url || "", `http://localhost:${port}`);
237774
237757
  if (url2.pathname === OPENAI_OAUTH_CONFIG.callbackPath) {
@@ -237784,7 +237767,9 @@ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaul
237784
237767
  message: `Error: ${error54}`,
237785
237768
  detail: errorDescription || undefined
237786
237769
  }));
237787
- reject(new Error(`OAuth error: ${error54} - ${errorDescription || ""}`));
237770
+ finish(() => {
237771
+ reject(new Error(`OAuth error: ${error54} - ${errorDescription || ""}`));
237772
+ });
237788
237773
  return;
237789
237774
  }
237790
237775
  if (!code2 || !state) {
@@ -237794,7 +237779,9 @@ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaul
237794
237779
  title: "Authentication Failed",
237795
237780
  message: "Missing authorization code or state parameter."
237796
237781
  }));
237797
- reject(new Error("Missing authorization code or state parameter"));
237782
+ finish(() => {
237783
+ reject(new Error("Missing authorization code or state parameter"));
237784
+ });
237798
237785
  return;
237799
237786
  }
237800
237787
  if (state !== expectedState) {
@@ -237804,7 +237791,9 @@ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaul
237804
237791
  title: "Authentication Failed",
237805
237792
  message: "State mismatch - the authorization may have been tampered with."
237806
237793
  }));
237807
- reject(new Error("State mismatch - the authorization may have been tampered with"));
237794
+ finish(() => {
237795
+ reject(new Error("State mismatch - the authorization may have been tampered with"));
237796
+ });
237808
237797
  return;
237809
237798
  }
237810
237799
  res.writeHead(200, { "Content-Type": "text/html" });
@@ -237814,7 +237803,9 @@ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaul
237814
237803
  message: "You can close this window and return to Letta Code.",
237815
237804
  autoClose: true
237816
237805
  }));
237817
- resolve29({ result: { code: code2, state }, server });
237806
+ finish(() => {
237807
+ resolve29({ result: { code: code2, state }, server });
237808
+ });
237818
237809
  } else {
237819
237810
  res.writeHead(404, { "Content-Type": "text/plain" });
237820
237811
  res.end("Not found");
@@ -237822,15 +237813,24 @@ function startLocalOAuthServer2(expectedState, port = OPENAI_OAUTH_CONFIG.defaul
237822
237813
  });
237823
237814
  server.on("error", (err) => {
237824
237815
  if (err.code === "EADDRINUSE") {
237825
- reject(new Error(`Port ${port} is already in use. Please close any application using this port and try again.`));
237816
+ finish(() => {
237817
+ reject(new Error(`Port ${port} is already in use. Please close any application using this port and try again.`));
237818
+ });
237826
237819
  } else {
237827
- reject(err);
237820
+ finish(() => {
237821
+ reject(err);
237822
+ });
237828
237823
  }
237829
237824
  });
237825
+ if (signal) {
237826
+ signal.addEventListener("abort", onAbort, { once: true });
237827
+ }
237830
237828
  server.listen(port, "127.0.0.1", () => {});
237831
- setTimeout(() => {
237829
+ timeout = setTimeout(() => {
237832
237830
  server.close();
237833
- reject(new Error("OAuth timeout - no callback received within 5 minutes"));
237831
+ finish(() => {
237832
+ reject(new Error("OAuth timeout - no callback received within 5 minutes"));
237833
+ });
237834
237834
  }, 5 * 60 * 1000);
237835
237835
  });
237836
237836
  }
@@ -238442,13 +238442,15 @@ Opening browser for authorization...
238442
238442
  If the browser doesn't open automatically, visit:
238443
238443
 
238444
238444
  ${authorizationUrl}`);
238445
- const serverPromise = mergedDeps.startCallbackServer(state, OPENAI_OAUTH_CONFIG.defaultPort);
238445
+ const serverPromise = mergedDeps.startCallbackServer(state, OPENAI_OAUTH_CONFIG.defaultPort, callbacks.signal);
238446
238446
  await browserOpener(authorizationUrl);
238447
238447
  await callbacks.onStatus(`Waiting for authorization...
238448
238448
 
238449
238449
  Please complete the sign-in process in your browser.
238450
238450
  The page will redirect automatically when done.
238451
238451
 
238452
+ Press Esc to cancel.
238453
+
238452
238454
  If needed, visit:
238453
238455
  ${authorizationUrl}`);
238454
238456
  const { result, server } = await serverPromise;
@@ -257327,6 +257329,10 @@ function ConstellationLoginView({
257327
257329
  const startedRef = import_react32.useRef(false);
257328
257330
  const cancelledRef = import_react32.useRef(false);
257329
257331
  const abortControllerRef = import_react32.useRef(null);
257332
+ const onCompleteRef = import_react32.useRef(onComplete);
257333
+ const onAlreadyLoggedInRef = import_react32.useRef(onAlreadyLoggedIn);
257334
+ onCompleteRef.current = onComplete;
257335
+ onAlreadyLoggedInRef.current = onAlreadyLoggedIn;
257330
257336
  use_input_default((input, key2) => {
257331
257337
  if (key2.escape || key2.ctrl && input === "c") {
257332
257338
  cancelledRef.current = true;
@@ -257344,7 +257350,7 @@ function ConstellationLoginView({
257344
257350
  const currentSettings = await settingsManager.getSettingsWithSecureTokens();
257345
257351
  const hasApiKey = process.env.LETTA_API_KEY || currentSettings.env?.LETTA_API_KEY;
257346
257352
  if (hasApiKey) {
257347
- onAlreadyLoggedIn?.();
257353
+ onAlreadyLoggedInRef.current?.();
257348
257354
  return;
257349
257355
  }
257350
257356
  const deviceData = await requestDeviceCode();
@@ -257373,7 +257379,7 @@ function ConstellationLoginView({
257373
257379
  await settingsManager.flush();
257374
257380
  configureBackendMode("api");
257375
257381
  setDoneMessage("Signed in to Constellation. Switch to a Constellation agent with /agents.");
257376
- setTimeout(() => onComplete?.(), 500);
257382
+ setTimeout(() => onCompleteRef.current?.(), 500);
257377
257383
  } catch (err) {
257378
257384
  if (cancelledRef.current || err instanceof Error && err.name === "AbortError") {
257379
257385
  return;
@@ -257386,7 +257392,7 @@ function ConstellationLoginView({
257386
257392
  cancelledRef.current = true;
257387
257393
  abortControllerRef.current?.abort();
257388
257394
  };
257389
- }, [onAlreadyLoggedIn, onComplete]);
257395
+ }, []);
257390
257396
  if (doneMessage) {
257391
257397
  return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
257392
257398
  flexDirection: "column",
@@ -262711,6 +262717,22 @@ function recordSessionEnd(agentId, sessionId, stats, sessionInfo, cost, metadata
262711
262717
  }
262712
262718
  var init_session_history = () => {};
262713
262719
 
262720
+ // src/cli/commands/connect-command-state.ts
262721
+ function setActiveConnectAbortController(controller) {
262722
+ activeConnectAbortController = controller;
262723
+ }
262724
+ function isActiveConnectOperationCancellable() {
262725
+ return activeConnectAbortController !== null;
262726
+ }
262727
+ function cancelActiveConnectOperation() {
262728
+ if (!activeConnectAbortController) {
262729
+ return false;
262730
+ }
262731
+ activeConnectAbortController.abort();
262732
+ return true;
262733
+ }
262734
+ var activeConnectAbortController = null;
262735
+
262714
262736
  // src/cli/commands/runner.ts
262715
262737
  function upsertCommandLine(buffers, id2, input, update2) {
262716
262738
  const existing = buffers.byId.get(id2);
@@ -265216,6 +265238,7 @@ function AgentSelector({
265216
265238
  currentAgentId,
265217
265239
  onSelect,
265218
265240
  onCancel,
265241
+ onLogin,
265219
265242
  onCreateNewAgent,
265220
265243
  command = "/agents"
265221
265244
  }) {
@@ -265236,7 +265259,6 @@ function AgentSelector({
265236
265259
  }, [activeTab, hasLocalAgents]);
265237
265260
  const [pinnedAgents, setPinnedAgents] = import_react41.useState([]);
265238
265261
  const [pinnedLoading, setPinnedLoading] = import_react41.useState(true);
265239
- const [pinnedFallbackAgents, setPinnedFallbackAgents] = import_react41.useState([]);
265240
265262
  const [pinnedSelectedIndex, setPinnedSelectedIndex] = import_react41.useState(0);
265241
265263
  const [pinnedPage, setPinnedPage] = import_react41.useState(0);
265242
265264
  const [localAgents, setLocalAgents] = import_react41.useState([]);
@@ -265297,25 +265319,16 @@ function AgentSelector({
265297
265319
  const validPinnedData = pinnedData.filter((p2) => p2.agent !== null);
265298
265320
  if (validPinnedData.length === 0) {
265299
265321
  setPinnedAgents([]);
265300
- const recentAgents = await getRecentAgentOptions({
265301
- includeLocal: true,
265302
- includeConstellation: hasCloudCredentials(),
265303
- limit: PINNED_FALLBACK_DISPLAY_SIZE,
265304
- currentAgentId
265305
- });
265306
- setPinnedFallbackAgents(recentAgents.map((item) => ({ ...item, isPinnedFallback: true })));
265307
265322
  setPinnedLoading(false);
265308
265323
  return;
265309
265324
  }
265310
265325
  setPinnedAgents(pinnedData);
265311
- setPinnedFallbackAgents([]);
265312
265326
  } catch {
265313
265327
  setPinnedAgents([]);
265314
- setPinnedFallbackAgents([]);
265315
265328
  } finally {
265316
265329
  setPinnedLoading(false);
265317
265330
  }
265318
- }, [currentAgentId]);
265331
+ }, []);
265319
265332
  const loadLocalAgents = import_react41.useCallback(() => {
265320
265333
  setLocalLoading(true);
265321
265334
  try {
@@ -265422,11 +265435,9 @@ function AgentSelector({
265422
265435
  hasCloudAuth
265423
265436
  ]);
265424
265437
  const validPinnedAgents = pinnedAgents.filter((p2) => p2.agent !== null);
265425
- const showingPinnedFallback = validPinnedAgents.length === 0 && pinnedFallbackAgents.length > 0;
265426
- const pinnedTotalPages = Math.ceil((showingPinnedFallback ? pinnedFallbackAgents.length : validPinnedAgents.length) / DISPLAY_PAGE_SIZE2);
265438
+ const pinnedTotalPages = Math.ceil(validPinnedAgents.length / DISPLAY_PAGE_SIZE2);
265427
265439
  const pinnedStartIndex = pinnedPage * DISPLAY_PAGE_SIZE2;
265428
265440
  const pinnedPageAgents = validPinnedAgents.slice(pinnedStartIndex, pinnedStartIndex + DISPLAY_PAGE_SIZE2);
265429
- const pinnedFallbackPageAgents = pinnedFallbackAgents.slice(pinnedStartIndex, pinnedStartIndex + DISPLAY_PAGE_SIZE2);
265430
265441
  const sortedLocalAgents = import_react41.useMemo(() => localAgents.toSorted((a2, b3) => {
265431
265442
  if (a2.id === currentAgentId)
265432
265443
  return -1;
@@ -265443,7 +265454,7 @@ function AgentSelector({
265443
265454
  const constellationCanGoNext = constellationPage < constellationTotalPages - 1 || constellationHasMore;
265444
265455
  const currentLoading = activeTab === "pinned" ? pinnedLoading : activeTab === "local" ? localLoading : constellationLoading;
265445
265456
  const currentError = activeTab === "constellation" ? constellationError : null;
265446
- const currentAgents = activeTab === "pinned" ? showingPinnedFallback ? pinnedFallbackPageAgents.map((p2) => p2.agent) : pinnedPageAgents.map((p2) => p2.agent).filter(Boolean) : activeTab === "local" ? localPageAgents : constellationPageAgents;
265457
+ const currentAgents = activeTab === "pinned" ? pinnedPageAgents.map((p2) => p2.agent).filter(Boolean) : activeTab === "local" ? localPageAgents : constellationPageAgents;
265447
265458
  const setCurrentSelectedIndex = activeTab === "pinned" ? setPinnedSelectedIndex : activeTab === "local" ? setLocalSelectedIndex : setConstellationSelectedIndex;
265448
265459
  const submitSearch = import_react41.useCallback(() => {
265449
265460
  if (searchInput !== activeQuery) {
@@ -265532,18 +265543,10 @@ function AgentSelector({
265532
265543
  return;
265533
265544
  }
265534
265545
  if (activeTab === "pinned") {
265535
- if (showingPinnedFallback) {
265536
- const selected = pinnedFallbackPageAgents[pinnedSelectedIndex];
265537
- if (selected?.agent) {
265538
- const mode = selected.isLocal ? "local" : "api";
265539
- onSelect(selected.agent.id, mode);
265540
- }
265541
- } else {
265542
- const selected = pinnedPageAgents[pinnedSelectedIndex];
265543
- if (selected?.agent) {
265544
- const mode = selected.isLocal ? "local" : "api";
265545
- onSelect(selected.agentId, mode);
265546
- }
265546
+ const selected = pinnedPageAgents[pinnedSelectedIndex];
265547
+ if (selected?.agent) {
265548
+ const mode = selected.isLocal ? "local" : "api";
265549
+ onSelect(selected.agentId, mode);
265547
265550
  }
265548
265551
  } else if (activeTab === "local") {
265549
265552
  const selected = localPageAgents[localSelectedIndex];
@@ -265554,6 +265557,8 @@ function AgentSelector({
265554
265557
  const selected = constellationPageAgents[constellationSelectedIndex];
265555
265558
  if (selected?.id) {
265556
265559
  onSelect(selected.id, "api");
265560
+ } else if (hasCloudAuth === false) {
265561
+ onLogin?.();
265557
265562
  }
265558
265563
  }
265559
265564
  } else if (key2.escape) {
@@ -265606,26 +265611,14 @@ function AgentSelector({
265606
265611
  }
265607
265612
  }
265608
265613
  } else if (activeTab === "pinned" && (input === "p" || input === "P")) {
265609
- if (showingPinnedFallback) {
265610
- const selected = pinnedFallbackPageAgents[pinnedSelectedIndex];
265611
- if (selected) {
265612
- if (selected.isLocal) {
265613
- settingsManager.pinLocal(selected.agent.id);
265614
- } else {
265615
- settingsManager.pinGlobal(selected.agent.id);
265616
- }
265617
- loadPinnedAgents();
265618
- }
265619
- } else {
265620
- const selected = pinnedPageAgents[pinnedSelectedIndex];
265621
- if (selected) {
265622
- if (selected.isLocal) {
265623
- settingsManager.unpinLocal(selected.agentId);
265624
- } else {
265625
- settingsManager.unpinGlobal(selected.agentId);
265626
- }
265627
- loadPinnedAgents();
265614
+ const selected = pinnedPageAgents[pinnedSelectedIndex];
265615
+ if (selected) {
265616
+ if (selected.isLocal) {
265617
+ settingsManager.unpinLocal(selected.agentId);
265618
+ } else {
265619
+ settingsManager.unpinGlobal(selected.agentId);
265628
265620
  }
265621
+ loadPinnedAgents();
265629
265622
  }
265630
265623
  } else if (input === "D") {
265631
265624
  let selectedAgent = null;
@@ -265787,10 +265780,25 @@ function AgentSelector({
265787
265780
  dimColor: true,
265788
265781
  children: "Connect to Letta Constellation to see hosted agents here."
265789
265782
  }, undefined, false, undefined, this),
265790
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265791
- dimColor: true,
265792
- children: "Run /login to sign in."
265793
- }, undefined, false, undefined, this)
265783
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265784
+ height: 1
265785
+ }, undefined, false, undefined, this),
265786
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265787
+ flexDirection: "column",
265788
+ children: [
265789
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265790
+ color: colors.selector.itemHighlighted,
265791
+ children: "> /login"
265792
+ }, undefined, false, undefined, this),
265793
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265794
+ paddingLeft: 2,
265795
+ children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265796
+ dimColor: true,
265797
+ children: "Sign in to Letta Constellation"
265798
+ }, undefined, false, undefined, this)
265799
+ }, undefined, false, undefined, this)
265800
+ ]
265801
+ }, undefined, true, undefined, this)
265794
265802
  ]
265795
265803
  }, undefined, true, undefined, this);
265796
265804
  const renderDeleteConfirm = () => {
@@ -265862,10 +265870,29 @@ function AgentSelector({
265862
265870
  return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(OverlayShell, {
265863
265871
  command,
265864
265872
  title: "Swap to a different agent",
265865
- footer: activeTab !== "new" && !currentLoading && (activeTab === "pinned" && validPinnedAgents.length > 0 || activeTab === "pinned" && showingPinnedFallback || activeTab === "local" && localAgents.length > 0 || activeTab === "constellation" && !constellationError && constellationAgents.length > 0) ? (() => {
265873
+ footer: activeTab !== "new" && !currentLoading && (activeTab === "pinned" || activeTab === "local" && localAgents.length > 0 || activeTab === "constellation" && !constellationError && constellationAgents.length > 0) ? (() => {
265866
265874
  const footerWidth = Math.max(0, terminalWidth - 2);
265875
+ if (activeTab === "pinned" && validPinnedAgents.length === 0) {
265876
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265877
+ flexDirection: "row",
265878
+ children: [
265879
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265880
+ width: 2,
265881
+ flexShrink: 0
265882
+ }, undefined, false, undefined, this),
265883
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265884
+ flexGrow: 1,
265885
+ width: footerWidth,
265886
+ children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(MarkdownDisplay, {
265887
+ text: "Tab switch · Esc cancel",
265888
+ dimColor: true
265889
+ }, undefined, false, undefined, this)
265890
+ }, undefined, false, undefined, this)
265891
+ ]
265892
+ }, undefined, true, undefined, this);
265893
+ }
265867
265894
  const pageText = activeTab === "pinned" ? `Page ${pinnedPage + 1}/${pinnedTotalPages || 1}` : activeTab === "local" ? `Page ${localPage + 1}/${localTotalPages || 1}` : `Page ${constellationPage + 1}${constellationHasMore ? "+" : `/${constellationTotalPages || 1}`}${constellationLoadingMore ? " (loading...)" : ""}`;
265868
- const pinnedHint = showingPinnedFallback ? " · Shift+P pin" : " · Shift+P unpin";
265895
+ const pinnedHint = " · Shift+P unpin";
265869
265896
  const hintsText = `Enter select · ↑↓ ←→ navigate · Tab switch · Shift+D delete${activeTab === "pinned" ? pinnedHint : ""} · Esc cancel`;
265870
265897
  return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265871
265898
  flexDirection: "column",
@@ -265925,19 +265952,7 @@ function AgentSelector({
265925
265952
  TAB_DESCRIPTIONS[activeTab]
265926
265953
  ]
265927
265954
  }, undefined, true, undefined, this),
265928
- activeTab === "pinned" && showingPinnedFallback && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265929
- height: 2
265930
- }, undefined, false, undefined, this),
265931
- activeTab === "pinned" && showingPinnedFallback && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265932
- dimColor: true,
265933
- children: [
265934
- " ",
265935
- "No pinned agents yet, showing recent agents instead."
265936
- ]
265937
- }, undefined, true, undefined, this),
265938
- activeTab === "pinned" && showingPinnedFallback ? /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265939
- height: 1
265940
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265955
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265941
265956
  height: 2
265942
265957
  }, undefined, false, undefined, this)
265943
265958
  ]
@@ -265988,26 +266003,21 @@ function AgentSelector({
265988
266003
  }, undefined, true, undefined, this)
265989
266004
  }, undefined, false, undefined, this),
265990
266005
  activeTab === "constellation" && !currentLoading && hasCloudAuth === false && renderConstellationUpsell(),
265991
- !currentLoading && (activeTab === "pinned" && validPinnedAgents.length === 0 && !showingPinnedFallback || activeTab === "local" && localAgents.length === 0 || activeTab === "constellation" && !constellationError && hasCloudAuth && constellationAgents.length === 0) && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
266006
+ !currentLoading && (activeTab === "pinned" && validPinnedAgents.length === 0 || activeTab === "local" && localAgents.length === 0 || activeTab === "constellation" && !constellationError && hasCloudAuth && constellationAgents.length === 0) && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
265992
266007
  flexDirection: "column",
266008
+ paddingLeft: activeTab === "pinned" ? 2 : 0,
265993
266009
  children: [
265994
266010
  /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265995
266011
  dimColor: true,
265996
266012
  children: TAB_EMPTY_STATES[activeTab]
265997
266013
  }, undefined, false, undefined, this),
265998
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
266014
+ activeTab !== "pinned" && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text2, {
265999
266015
  dimColor: true,
266000
266016
  children: "Press ESC to cancel"
266001
266017
  }, undefined, false, undefined, this)
266002
266018
  ]
266003
266019
  }, undefined, true, undefined, this),
266004
- activeTab === "pinned" && !pinnedLoading && showingPinnedFallback && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
266005
- flexDirection: "column",
266006
- children: pinnedFallbackPageAgents.map((data, index) => renderAgentItem(data.agent, index, index === pinnedSelectedIndex, {
266007
- backend: data.isLocal ? "local" : "constellation"
266008
- }))
266009
- }, undefined, false, undefined, this),
266010
- activeTab === "pinned" && !pinnedLoading && !showingPinnedFallback && validPinnedAgents.length > 0 && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
266020
+ activeTab === "pinned" && !pinnedLoading && validPinnedAgents.length > 0 && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
266011
266021
  flexDirection: "column",
266012
266022
  children: pinnedPageAgents.map((data, index) => renderPinnedItem(data, index, index === pinnedSelectedIndex))
266013
266023
  }, undefined, false, undefined, this),
@@ -266129,12 +266139,11 @@ function AgentSelector({
266129
266139
  ]
266130
266140
  }, undefined, true, undefined, this);
266131
266141
  }
266132
- var import_react41, jsx_dev_runtime17, ALL_TABS, TAB_DESCRIPTIONS, TAB_EMPTY_STATES, DISPLAY_PAGE_SIZE2 = 5, FETCH_PAGE_SIZE2 = 20, PINNED_FALLBACK_DISPLAY_SIZE = 3, NEW_AGENT_DEFAULT_BACKEND = "api";
266142
+ var import_react41, jsx_dev_runtime17, ALL_TABS, TAB_DESCRIPTIONS, TAB_EMPTY_STATES, DISPLAY_PAGE_SIZE2 = 5, FETCH_PAGE_SIZE2 = 20, NEW_AGENT_DEFAULT_BACKEND = "api";
266133
266143
  var init_AgentSelector = __esm(async () => {
266134
266144
  init_model();
266135
266145
  init_backend();
266136
266146
  init_local_agent_listing();
266137
- init_recent_agent_options();
266138
266147
  init_use_terminal_width();
266139
266148
  init_constants2();
266140
266149
  init_settings_manager();
@@ -275312,7 +275321,7 @@ var init_AgentInfoBar = __esm(async () => {
275312
275321
  const isCloudUser = serverUrl?.includes("api.letta.com");
275313
275322
  const adeConversationUrl = agentId && agentId !== "loading" ? buildChatUrl(agentId, { conversationId }) : "";
275314
275323
  const showBottomBar = agentId && agentId !== "loading";
275315
- const reasoningLabel = formatReasoningLabel(currentReasoningEffort);
275324
+ const reasoningLabel = shouldHideReasoningForModelDisplay(currentModel) ? null : formatReasoningLabel(currentReasoningEffort);
275316
275325
  const modelLine = currentModel ? `${currentModel}${reasoningLabel ? ` (${reasoningLabel})` : ""}` : null;
275317
275326
  if (!showBottomBar) {
275318
275327
  return null;
@@ -277083,6 +277092,7 @@ function Input({
277083
277092
  messageQueue,
277084
277093
  onQueueEdit,
277085
277094
  onEscapeCancel,
277095
+ onEscapeCommandCancel,
277086
277096
  inputDisabled = false,
277087
277097
  goalLoopActive = false,
277088
277098
  onGoalLoopExit,
@@ -277097,7 +277107,8 @@ function Input({
277097
277107
  statusLineRight,
277098
277108
  statusLinePrompt,
277099
277109
  onCycleReasoningEffort,
277100
- footerNotification
277110
+ footerNotification,
277111
+ showInspirationalPromptHints = false
277101
277112
  }) {
277102
277113
  const [value, setValue] = import_react81.useState("");
277103
277114
  const [escapePressed, setEscapePressed] = import_react81.useState(false);
@@ -277106,6 +277117,8 @@ function Input({
277106
277117
  const ctrlCTimerRef = import_react81.useRef(null);
277107
277118
  const previousValueRef = import_react81.useRef(value);
277108
277119
  const [currentMode, setCurrentMode] = import_react81.useState(externalMode || permissionMode.getMode());
277120
+ const [emptyPromptHintIndex, setEmptyPromptHintIndex] = import_react81.useState(0);
277121
+ const [emptyPromptHintReady, setEmptyPromptHintReady] = import_react81.useState(false);
277109
277122
  const [isAutocompleteActive, setIsAutocompleteActive] = import_react81.useState(false);
277110
277123
  const [cursorPos, setCursorPos] = import_react81.useState(undefined);
277111
277124
  const [currentCursorPosition, setCurrentCursorPosition] = import_react81.useState(0);
@@ -277197,6 +277210,28 @@ function Input({
277197
277210
  onRestoredInputConsumed?.();
277198
277211
  }
277199
277212
  }, [restoredInput, value, onRestoredInputConsumed]);
277213
+ import_react81.useEffect(() => {
277214
+ if (!showInspirationalPromptHints || value !== "") {
277215
+ setEmptyPromptHintIndex(0);
277216
+ setEmptyPromptHintReady(false);
277217
+ return;
277218
+ }
277219
+ const timer = setTimeout(() => {
277220
+ setEmptyPromptHintReady(true);
277221
+ }, EMPTY_COMPOSER_PROMPT_ROTATION_MS);
277222
+ return () => clearTimeout(timer);
277223
+ }, [showInspirationalPromptHints, value]);
277224
+ import_react81.useEffect(() => {
277225
+ if (!showInspirationalPromptHints || value !== "" || !emptyPromptHintReady) {
277226
+ return;
277227
+ }
277228
+ const timer = setInterval(() => {
277229
+ setEmptyPromptHintIndex((prev) => (prev + 1) % EMPTY_COMPOSER_PROMPT_HINTS.length);
277230
+ }, EMPTY_COMPOSER_PROMPT_ROTATION_MS);
277231
+ return () => clearInterval(timer);
277232
+ }, [showInspirationalPromptHints, value, emptyPromptHintReady]);
277233
+ const inspirationalPlaceholder = showInspirationalPromptHints ? EMPTY_COMPOSER_PROMPT_HINTS[emptyPromptHintIndex] ?? undefined : undefined;
277234
+ const showInspirationalPlaceholder = showInspirationalPromptHints && emptyPromptHintReady && value === "" && !!inspirationalPlaceholder;
277200
277235
  const handleBangAtEmpty = import_react81.useCallback(() => {
277201
277236
  if (isBashMode)
277202
277237
  return false;
@@ -277251,6 +277286,27 @@ function Input({
277251
277286
  setIsAutocompleteActive(false);
277252
277287
  }
277253
277288
  }, [interactionEnabled]);
277289
+ const interactionEnabledRef = import_react81.useRef(interactionEnabled);
277290
+ import_react81.useEffect(() => {
277291
+ interactionEnabledRef.current = interactionEnabled;
277292
+ }, [interactionEnabled]);
277293
+ const onEscapeCommandCancelRef = import_react81.useRef(onEscapeCommandCancel);
277294
+ import_react81.useEffect(() => {
277295
+ onEscapeCommandCancelRef.current = onEscapeCommandCancel;
277296
+ }, [onEscapeCommandCancel]);
277297
+ import_react81.useEffect(() => {
277298
+ const handleRawInput = (data) => {
277299
+ if (!interactionEnabledRef.current)
277300
+ return;
277301
+ if (data.toString("utf8") !== "\x1B")
277302
+ return;
277303
+ onEscapeCommandCancelRef.current?.();
277304
+ };
277305
+ stdin.on("data", handleRawInput);
277306
+ return () => {
277307
+ stdin.off("data", handleRawInput);
277308
+ };
277309
+ }, []);
277254
277310
  const settings3 = settingsManager.getSettings();
277255
277311
  const serverUrl = process.env.LETTA_BASE_URL || settings3.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
277256
277312
  use_input_default((_input, key2) => {
@@ -277281,6 +277337,9 @@ function Input({
277281
277337
  onInterrupt();
277282
277338
  return;
277283
277339
  }
277340
+ if (onEscapeCommandCancel?.()) {
277341
+ return;
277342
+ }
277284
277343
  if (value) {
277285
277344
  if (escapePressed) {
277286
277345
  setValue("");
@@ -277632,6 +277691,7 @@ function Input({
277632
277691
  value,
277633
277692
  onChange: setValue,
277634
277693
  onSubmit: handleSubmit,
277694
+ placeholder: showInspirationalPlaceholder ? inspirationalPlaceholder : undefined,
277635
277695
  cursorPosition: cursorPos,
277636
277696
  onCursorMove: setCurrentCursorPosition,
277637
277697
  focus: interactionEnabled && !onEscapeCancel,
@@ -277701,6 +277761,7 @@ function Input({
277701
277761
  contentWidth,
277702
277762
  value,
277703
277763
  handleSubmit,
277764
+ showInspirationalPlaceholder,
277704
277765
  cursorPos,
277705
277766
  onEscapeCancel,
277706
277767
  handleBangAtEmpty,
@@ -277738,7 +277799,8 @@ function Input({
277738
277799
  suppressDividers,
277739
277800
  queueMode,
277740
277801
  deferModeSupported,
277741
- isLocalBackend
277802
+ isLocalBackend,
277803
+ inspirationalPlaceholder
277742
277804
  ]);
277743
277805
  if (!visible) {
277744
277806
  return null;
@@ -277784,7 +277846,7 @@ function formatElapsedLabel(ms) {
277784
277846
  }
277785
277847
  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
277786
277848
  }
277787
- var import_react81, jsx_dev_runtime56, ESC_CLEAR_WINDOW_MS = 2500, FOOTER_WIDTH_STREAMING_DELTA = 2, COMBINED_STYLE_REGEX, InputFooter, StreamingStatus;
277849
+ var import_react81, jsx_dev_runtime56, ESC_CLEAR_WINDOW_MS = 2500, FOOTER_WIDTH_STREAMING_DELTA = 2, EMPTY_COMPOSER_PROMPT_ROTATION_MS = 6000, EMPTY_COMPOSER_PROMPT_HINTS, COMBINED_STYLE_REGEX, InputFooter, StreamingStatus;
277788
277850
  var init_InputRich = __esm(async () => {
277789
277851
  init_source2();
277790
277852
  init_string_width();
@@ -277813,6 +277875,13 @@ var init_InputRich = __esm(async () => {
277813
277875
  ]);
277814
277876
  import_react81 = __toESM(require_react(), 1);
277815
277877
  jsx_dev_runtime56 = __toESM(require_jsx_dev_runtime(), 1);
277878
+ EMPTY_COMPOSER_PROMPT_HINTS = [
277879
+ 'Try "help me understand this codebase"',
277880
+ 'Try "help me organize my desktop"',
277881
+ 'Try "debug this error"',
277882
+ 'Try "explain what this function does"',
277883
+ 'Try "review this pull request"'
277884
+ ];
277816
277885
  COMBINED_STYLE_REGEX = /\x1b\[(\d+)(?:;(\d+)(?:;(\d+)(?:;(\d+)(?:;(\d+))?)?)?)?m|\x1b\]8;;([^\x1b]*)\x1b\\([^\x1b]*)\x1b\]8;;\x1b\\/g;
277817
277886
  InputFooter = import_react81.memo(function InputFooter2({
277818
277887
  ctrlCPressed,
@@ -277879,7 +277948,7 @@ var init_InputRich = __esm(async () => {
277879
277948
  });
277880
277949
  const maxAgentChars = Math.max(10, Math.floor(rightColumnWidth * 0.45));
277881
277950
  const displayAgentName = truncateEnd(agentName || "Unnamed", maxAgentChars);
277882
- const reasoningTag = getReasoningEffortTag(currentReasoningEffort);
277951
+ const reasoningTag = shouldHideReasoningForModelDisplay(currentModel) ? null : getReasoningEffortTag(currentReasoningEffort);
277883
277952
  const byokExtraChars = isByokProvider ? 2 : 0;
277884
277953
  const tempOverrideExtraChars = hasTemporaryModelOverride ? 2 : 0;
277885
277954
  const baseReservedChars = displayAgentName.length + byokExtraChars + tempOverrideExtraChars + 4;
@@ -291473,9 +291542,12 @@ Use /disconnect chatgpt (or /disconnect codex) to remove the current connection
291473
291542
  return;
291474
291543
  }
291475
291544
  ctx.setCommandRunning(true);
291545
+ const abortController = new AbortController;
291546
+ setActiveConnectAbortController(abortController);
291476
291547
  const cmdId = addCommandResult(ctx.buffersRef, ctx.refreshDerived, msg, "Checking account eligibility...", true, "running");
291477
291548
  try {
291478
291549
  await runChatGPTOAuthConnectFlow({
291550
+ signal: abortController.signal,
291479
291551
  onStatus: (status) => updateCommandResult(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, status, true, "running")
291480
291552
  });
291481
291553
  updateCommandResult(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✓ Successfully connected to ChatGPT!
@@ -291486,8 +291558,10 @@ Use /disconnect chatgpt (or /disconnect codex) to remove the current connection
291486
291558
  setTimeout(() => ctx.onCodexConnected?.(), 500);
291487
291559
  }
291488
291560
  } catch (error54) {
291489
- updateCommandResult(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to connect: ${getErrorMessage2(error54)}`, false, "finished");
291561
+ const isCancelled = error54 instanceof Error && error54.name === "AbortError";
291562
+ updateCommandResult(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, isCancelled ? "Cancelled ChatGPT connection." : `✗ Failed to connect: ${getErrorMessage2(error54)}`, false, "finished");
291490
291563
  } finally {
291564
+ setActiveConnectAbortController(null);
291491
291565
  ctx.setCommandRunning(false);
291492
291566
  }
291493
291567
  }
@@ -291758,6 +291832,8 @@ function AppView(props) {
291758
291832
  handleCtrlD,
291759
291833
  feedbackPrefill,
291760
291834
  footerUpdateText,
291835
+ showInspirationalPromptHints,
291836
+ onEscapeCommandCancel,
291761
291837
  handleAgentSelect,
291762
291838
  handleApproveAlways,
291763
291839
  handleApproveCurrent,
@@ -291794,6 +291870,7 @@ function AppView(props) {
291794
291870
  liveItems,
291795
291871
  liveTrajectoryElapsedBaseMs,
291796
291872
  loadingState,
291873
+ markLocalModelsAvailable,
291797
291874
  maybeCarryOverActiveConversationModel,
291798
291875
  modelReasoningPrompt,
291799
291876
  modelSelectorOptions,
@@ -292009,6 +292086,7 @@ function AppView(props) {
292009
292086
  messageQueue: queueDisplay,
292010
292087
  onQueueEdit: handleQueueEdit,
292011
292088
  onEscapeCancel: profileConfirmPending ? handleProfileEscapeCancel : undefined,
292089
+ onEscapeCommandCancel,
292012
292090
  inputDisabled: btwState.status === "complete",
292013
292091
  goalLoopActive: uiGoalLoopActive,
292014
292092
  onGoalLoopExit: handleGoalLoopExit,
@@ -292022,7 +292100,8 @@ function AppView(props) {
292022
292100
  statusLineText: statusLine.text || undefined,
292023
292101
  statusLineRight: statusLine.rightText || undefined,
292024
292102
  statusLinePrompt: statusLine.prompt,
292025
- footerNotification: footerUpdateText
292103
+ footerNotification: footerUpdateText,
292104
+ showInspirationalPromptHints
292026
292105
  }, undefined, false, undefined, this)
292027
292106
  }, undefined, false, undefined, this),
292028
292107
  activeOverlay === "model" && (modelReasoningPrompt ? /* @__PURE__ */ jsx_dev_runtime89.jsxDEV(ModelReasoningSelector, {
@@ -292138,6 +292217,7 @@ function AppView(props) {
292138
292217
  refreshDerived,
292139
292218
  setCommandRunning,
292140
292219
  onCodexConnected: () => {
292220
+ markLocalModelsAvailable();
292141
292221
  setModelSelectorOptions({
292142
292222
  filterProvider: "chatgpt-plus-pro",
292143
292223
  forceRefresh: true
@@ -292183,6 +292263,10 @@ function AppView(props) {
292183
292263
  backendMode
292184
292264
  });
292185
292265
  },
292266
+ onLogin: () => {
292267
+ completeOverlay("resume");
292268
+ openOverlay("login", "/login", "Opening login...", "Login dismissed");
292269
+ },
292186
292270
  onCancel: closeOverlay,
292187
292271
  onCreateNewAgent: (name, backendMode) => {
292188
292272
  const overlayCommand = completeOverlay("resume");
@@ -293910,6 +293994,7 @@ function useConfigurationHandlers(ctx) {
293910
293994
  setConversationOverrideModelSettings,
293911
293995
  setCurrentModelHandle,
293912
293996
  setCurrentModelId,
293997
+ setHasAvailableLocalModels,
293913
293998
  setCurrentPersonalityId,
293914
293999
  setCurrentSystemPromptId,
293915
294000
  setCurrentToolset,
@@ -294053,6 +294138,7 @@ function useConfigurationHandlers(ctx) {
294053
294138
  settingsManager.addRecentModel(modelHandle);
294054
294139
  resetContextHistory(contextTrackerRef.current);
294055
294140
  setCurrentModelHandle(modelHandle);
294141
+ setHasAvailableLocalModels(true);
294056
294142
  const persistedToolsetPreference = settingsManager.getToolsetPreference(agentId);
294057
294143
  const previousToolsetSnapshot = currentToolset;
294058
294144
  const previousToolNamesSnapshot = getToolNames();
@@ -298133,6 +298219,7 @@ async function handleConnectionCommand(msg, trimmed, ctx) {
298133
298219
  buffersRef,
298134
298220
  commandRunner,
298135
298221
  conversationIdRef,
298222
+ markLocalModelsAvailable,
298136
298223
  refreshDerived,
298137
298224
  setCommandRunning,
298138
298225
  setModelSelectorOptions,
@@ -298208,6 +298295,7 @@ async function handleConnectionCommand(msg, trimmed, ctx) {
298208
298295
  refreshDerived,
298209
298296
  setCommandRunning,
298210
298297
  onCodexConnected: () => {
298298
+ markLocalModelsAvailable();
298211
298299
  setModelSelectorOptions({
298212
298300
  filterProvider: "chatgpt-plus-pro",
298213
298301
  forceRefresh: true
@@ -299786,6 +299874,7 @@ function useSubmitHandler(ctx) {
299786
299874
  setHasConversationModelOverride,
299787
299875
  setLines,
299788
299876
  setLlmConfig,
299877
+ markLocalModelsAvailable,
299789
299878
  setModelSelectorOptions,
299790
299879
  setNeedsEagerApprovalCheck,
299791
299880
  setPinDialogLocal,
@@ -300071,6 +300160,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
300071
300160
  refreshDerived,
300072
300161
  openOverlay,
300073
300162
  setCommandRunning,
300163
+ markLocalModelsAvailable,
300074
300164
  setModelSelectorOptions
300075
300165
  });
300076
300166
  if (connectionCommandResult) {
@@ -301773,6 +301863,22 @@ function buildStartupCommandHints(options3) {
301773
301863
  }
301774
301864
  return dedupedHints;
301775
301865
  }
301866
+ function hasConversationContent(lines) {
301867
+ return lines.some((line) => {
301868
+ switch (line.kind) {
301869
+ case "user":
301870
+ case "assistant":
301871
+ case "reasoning":
301872
+ case "tool_call":
301873
+ case "error":
301874
+ case "command":
301875
+ case "bash_command":
301876
+ return true;
301877
+ default:
301878
+ return false;
301879
+ }
301880
+ });
301881
+ }
301776
301882
  function App2({
301777
301883
  agentId: initialAgentId,
301778
301884
  agentState: initialAgentState,
@@ -301797,6 +301903,10 @@ function App2({
301797
301903
  import_react118.useEffect(() => {
301798
301904
  prefetchAvailableModelHandles();
301799
301905
  }, []);
301906
+ const [hasAvailableLocalModels, setHasAvailableLocalModels] = import_react118.useState(startupHasAvailableLocalModels);
301907
+ const markLocalModelsAvailable = import_react118.useCallback(() => {
301908
+ setHasAvailableLocalModels(true);
301909
+ }, []);
301800
301910
  const [agentId, setAgentId] = import_react118.useState(initialAgentId);
301801
301911
  const [agentState, setAgentState] = import_react118.useState(initialAgentState);
301802
301912
  const updateAgentName = import_react118.useCallback((name) => {
@@ -302061,8 +302171,7 @@ function App2({
302061
302171
  const derivedReasoningEffort = deriveReasoningEffort(effectiveModelSettings, llmConfig);
302062
302172
  const startupModelDisplayOverride = getStartupModelDisplayOverride({
302063
302173
  isLocalBackend: isLocalBackendEnabled(),
302064
- startupHasAvailableLocalModels,
302065
- agentProvenance
302174
+ startupHasAvailableLocalModels: hasAvailableLocalModels
302066
302175
  });
302067
302176
  const currentModelDisplay = import_react118.useMemo(() => {
302068
302177
  if (startupModelDisplayOverride)
@@ -303223,7 +303332,6 @@ function App2({
303223
303332
  snapshot: {
303224
303333
  continueSession,
303225
303334
  agentState,
303226
- agentProvenance,
303227
303335
  startupHasAvailableLocalModels,
303228
303336
  terminalWidth: columns
303229
303337
  }
@@ -303274,7 +303382,6 @@ function App2({
303274
303382
  continueSession,
303275
303383
  columns,
303276
303384
  agentState,
303277
- agentProvenance,
303278
303385
  resumedExistingConversation,
303279
303386
  releaseNotes,
303280
303387
  startupHasCloudCredentials,
@@ -304037,6 +304144,7 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304037
304144
  setHasConversationModelOverride,
304038
304145
  setLines,
304039
304146
  setLlmConfig,
304147
+ markLocalModelsAvailable,
304040
304148
  setModelSelectorOptions,
304041
304149
  setNeedsEagerApprovalCheck,
304042
304150
  setPinDialogLocal,
@@ -304157,6 +304265,7 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304157
304265
  setConversationOverrideModelSettings,
304158
304266
  setCurrentModelHandle,
304159
304267
  setCurrentModelId,
304268
+ setHasAvailableLocalModels,
304160
304269
  setCurrentPersonalityId,
304161
304270
  setCurrentSystemPromptId,
304162
304271
  setCurrentToolset,
@@ -304428,7 +304537,6 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304428
304537
  snapshot: {
304429
304538
  continueSession,
304430
304539
  agentState,
304431
- agentProvenance,
304432
304540
  startupHasAvailableLocalModels,
304433
304541
  terminalWidth: columns
304434
304542
  }
@@ -304487,6 +304595,14 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304487
304595
  const trajectoryTokenDisplay = Math.max(liveTrajectoryTokenBase + runTokenDelta, trajectoryTokenDisplayRef.current);
304488
304596
  const inputVisible = !showExitStats;
304489
304597
  const inputEnabled = !showExitStats && pendingApprovals.length === 0 && !anySelectorOpen;
304598
+ const onEscapeCommandCancel = import_react118.useCallback(() => {
304599
+ if (isActiveConnectOperationCancellable()) {
304600
+ cancelActiveConnectOperation();
304601
+ return true;
304602
+ }
304603
+ return false;
304604
+ }, []);
304605
+ const showInspirationalPromptHints = loadingState === "ready" && !hasConversationContent(lines) && !streaming3 && queueDisplay.length === 0 && pendingApprovals.length === 0 && !anySelectorOpen;
304490
304606
  const currentApprovalPreviewCommitted = currentApproval?.toolCallId ? eagerCommittedPreviewsRef.current.has(currentApproval.toolCallId) : false;
304491
304607
  const showApprovalPreview = !currentApprovalShouldCommitPreview && !currentApprovalPreviewCommitted;
304492
304608
  import_react118.useEffect(() => {
@@ -304534,6 +304650,8 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304534
304650
  emittedIdsRef,
304535
304651
  feedbackPrefill,
304536
304652
  footerUpdateText,
304653
+ showInspirationalPromptHints,
304654
+ onEscapeCommandCancel,
304537
304655
  handleAgentSelect,
304538
304656
  handleApproveAlways,
304539
304657
  handleApproveCurrent,
@@ -304570,6 +304688,7 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
304570
304688
  liveItems,
304571
304689
  liveTrajectoryElapsedBaseMs,
304572
304690
  loadingState,
304691
+ markLocalModelsAvailable,
304573
304692
  maybeCarryOverActiveConversationModel,
304574
304693
  modelReasoningPrompt,
304575
304694
  modelSelectorOptions,
@@ -309442,15 +309561,67 @@ async function initTerminalTheme() {
309442
309561
 
309443
309562
  // src/cli/profile-selection.tsx
309444
309563
  init_backend2();
309445
- init_recent_agent_options();
309564
+ await init_build4();
309565
+ var import_react27 = __toESM(require_react(), 1);
309566
+
309567
+ // src/cli/helpers/recent-agent-options.ts
309568
+ init_client2();
309569
+ init_local_agent_listing();
309570
+ init_settings_manager();
309571
+ function sortRecentAgents(agents, currentAgentId) {
309572
+ return agents.toSorted((a2, b3) => {
309573
+ if (currentAgentId) {
309574
+ if (a2.agent.id === currentAgentId)
309575
+ return -1;
309576
+ if (b3.agent.id === currentAgentId)
309577
+ return 1;
309578
+ }
309579
+ const aTime = a2.agent.last_run_completion ? new Date(a2.agent.last_run_completion).getTime() : 0;
309580
+ const bTime = b3.agent.last_run_completion ? new Date(b3.agent.last_run_completion).getTime() : 0;
309581
+ return bTime - aTime;
309582
+ });
309583
+ }
309584
+ function shouldIncludeConstellationRecentAgents(includeConstellation, settings3) {
309585
+ return Boolean(includeConstellation && (settings3.refreshToken || settings3.env?.LETTA_API_KEY));
309586
+ }
309587
+ async function getRecentAgentOptions(options3) {
309588
+ const includeLocal = options3?.includeLocal !== false;
309589
+ const includeConstellation = options3?.includeConstellation !== false;
309590
+ const limit3 = options3?.limit ?? 5;
309591
+ const settings3 = includeConstellation ? await settingsManager.getSettingsWithSecureTokens() : null;
309592
+ const shouldIncludeConstellation = settings3 !== null ? shouldIncludeConstellationRecentAgents(includeConstellation, settings3) : false;
309593
+ const localAgents = includeLocal ? listLocalAgentsFromDisk().map((agent2) => ({ agent: agent2, isLocal: true })) : [];
309594
+ const constellationAgents = shouldIncludeConstellation ? await (async () => {
309595
+ try {
309596
+ const client = await getClient();
309597
+ const result = await client.agents.list({
309598
+ limit: limit3,
309599
+ include: ["agent.blocks"],
309600
+ order: "desc",
309601
+ order_by: "last_run_completion"
309602
+ });
309603
+ return result.items.map((agent2) => ({ agent: agent2, isLocal: false }));
309604
+ } catch {
309605
+ return [];
309606
+ }
309607
+ })() : [];
309608
+ const seen = new Set;
309609
+ const deduped = sortRecentAgents([...localAgents, ...constellationAgents].filter((item) => {
309610
+ if (seen.has(item.agent.id))
309611
+ return false;
309612
+ seen.add(item.agent.id);
309613
+ return true;
309614
+ }), options3?.currentAgentId);
309615
+ return deduped.slice(0, limit3);
309616
+ }
309617
+
309618
+ // src/cli/profile-selection.tsx
309446
309619
  init_settings_manager();
309447
309620
  init_colors();
309448
309621
  await __promiseAll([
309449
- init_build4(),
309450
309622
  init_Text2(),
309451
309623
  init_WelcomeScreen()
309452
309624
  ]);
309453
- var import_react27 = __toESM(require_react(), 1);
309454
309625
  var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
309455
309626
  var MAX_DISPLAY = 3;
309456
309627
  var RECENT_FALLBACK_DISPLAY = 2;
@@ -309658,8 +309829,7 @@ function ProfileSelectionUI({
309658
309829
  /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(WelcomeScreen, {
309659
309830
  loadingState: loading ? "loading_profiles" : "ready",
309660
309831
  continueSession: false,
309661
- agentState: null,
309662
- agentProvenance: null
309832
+ agentState: null
309663
309833
  }, undefined, false, undefined, this),
309664
309834
  /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
309665
309835
  height: 1
@@ -309903,6 +310073,13 @@ function ProfileSelectionInline({
309903
310073
  });
309904
310074
  }
309905
310075
 
310076
+ // src/cli/startup-backend-mode.ts
310077
+ function inferBackendModeFromAgentId(agentId) {
310078
+ if (!agentId)
310079
+ return;
310080
+ return isLocalAgentId2(agentId) ? "local" : "api";
310081
+ }
310082
+
309906
310083
  // src/cli/startup-flag-validation.ts
309907
310084
  function validateFlagConflicts(options3) {
309908
310085
  const { guard, checks: checks4 } = options3;
@@ -315889,6 +316066,10 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
315889
316066
  process.exit(1);
315890
316067
  }
315891
316068
  const specifiedAgentName = values2.name ?? null;
316069
+ const inferredBackendModeFromAgentId = inferBackendModeFromAgentId(specifiedAgentId);
316070
+ if (!explicitBackendMode && inferredBackendModeFromAgentId) {
316071
+ configureBackendMode(inferredBackendModeFromAgentId);
316072
+ }
315892
316073
  const specifiedModel = values2.model ?? undefined;
315893
316074
  const systemPromptPreset = values2.system ?? undefined;
315894
316075
  const systemCustom = values2["system-custom"] ?? undefined;
@@ -315921,10 +316102,10 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
315921
316102
  const isHeadless = values2.prompt || values2.run || !process.stdin.isTTY;
315922
316103
  let apiKey = process.env.LETTA_API_KEY || settings3.env?.LETTA_API_KEY;
315923
316104
  const baseURL = process.env.LETTA_BASE_URL || settings3.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL2;
315924
- if (!explicitBackendMode && settings3.preferredBackendMode === "local" && baseURL === LETTA_CLOUD_API_URL2) {
316105
+ if (!explicitBackendMode && !inferredBackendModeFromAgentId && settings3.preferredBackendMode === "local" && baseURL === LETTA_CLOUD_API_URL2) {
315925
316106
  configureBackendMode("local");
315926
316107
  }
315927
- if (!explicitBackendMode && !isHeadless && baseURL === LETTA_CLOUD_API_URL2 && !settings3.refreshToken && !apiKey) {
316108
+ if (!explicitBackendMode && !inferredBackendModeFromAgentId && !isHeadless && baseURL === LETTA_CLOUD_API_URL2 && !settings3.refreshToken && !apiKey) {
315928
316109
  configureBackendMode("local");
315929
316110
  settingsManager2.updateSettings({ preferredBackendMode: "local" });
315930
316111
  await settingsManager2.flush();
@@ -317079,4 +317260,4 @@ Error during initialization: ${message}`);
317079
317260
  }
317080
317261
  main();
317081
317262
 
317082
- //# debugId=F30CF1173084EE3964756E2164756E21
317263
+ //# debugId=AAE13B069E013B1E64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.26.0",
3
+ "version": "0.26.1",
4
4
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.0",