@letta-ai/letta-code 0.14.13 → 0.14.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -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.14.13",
3125
+ version: "0.14.15",
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: {
@@ -3355,20 +3355,46 @@ async function mkdir(path2, options) {
3355
3355
  var init_fs = () => {};
3356
3356
 
3357
3357
  // src/utils/secrets.ts
3358
- async function setApiKey(apiKey) {
3359
- if (secretsAvailable) {
3360
- try {
3361
- await secrets.set({
3362
- service: SERVICE_NAME,
3363
- name: API_KEY_NAME,
3364
- value: apiKey
3365
- });
3366
- return;
3367
- } catch (error) {
3368
- console.warn(`Failed to store API key in secrets, using fallback: ${error}`);
3358
+ function getErrorMessage(error) {
3359
+ return error instanceof Error ? error.message : String(error);
3360
+ }
3361
+ function isDuplicateKeychainItemError(error) {
3362
+ const message = getErrorMessage(error);
3363
+ return message.includes("already exists in the keychain") || message.includes("code: -25299");
3364
+ }
3365
+ async function setSecretValue(name, value) {
3366
+ if (!secretsAvailable) {
3367
+ throw new Error("Secrets API unavailable");
3368
+ }
3369
+ try {
3370
+ await secrets.set({
3371
+ service: SERVICE_NAME,
3372
+ name,
3373
+ value
3374
+ });
3375
+ return;
3376
+ } catch (error) {
3377
+ if (!isDuplicateKeychainItemError(error)) {
3378
+ throw error;
3369
3379
  }
3370
3380
  }
3371
- throw new Error("Secrets API unavailable");
3381
+ try {
3382
+ await secrets.delete({
3383
+ service: SERVICE_NAME,
3384
+ name
3385
+ });
3386
+ } catch {}
3387
+ await secrets.set({
3388
+ service: SERVICE_NAME,
3389
+ name,
3390
+ value
3391
+ });
3392
+ }
3393
+ async function setApiKey(apiKey) {
3394
+ if (!secretsAvailable) {
3395
+ throw new Error("Secrets API unavailable");
3396
+ }
3397
+ await setSecretValue(API_KEY_NAME, apiKey);
3372
3398
  }
3373
3399
  async function getApiKey() {
3374
3400
  if (secretsAvailable) {
@@ -3384,19 +3410,10 @@ async function getApiKey() {
3384
3410
  return null;
3385
3411
  }
3386
3412
  async function setRefreshToken(refreshToken) {
3387
- if (secretsAvailable) {
3388
- try {
3389
- await secrets.set({
3390
- service: SERVICE_NAME,
3391
- name: REFRESH_TOKEN_NAME,
3392
- value: refreshToken
3393
- });
3394
- return;
3395
- } catch (error) {
3396
- console.warn(`Failed to store refresh token in secrets, using fallback: ${error}`);
3397
- }
3413
+ if (!secretsAvailable) {
3414
+ throw new Error("Secrets API unavailable");
3398
3415
  }
3399
- throw new Error("Secrets API unavailable");
3416
+ await setSecretValue(REFRESH_TOKEN_NAME, refreshToken);
3400
3417
  }
3401
3418
  async function getRefreshToken() {
3402
3419
  if (secretsAvailable) {
@@ -3497,6 +3514,9 @@ __export(exports_settings_manager, {
3497
3514
  });
3498
3515
  import { homedir } from "node:os";
3499
3516
  import { join } from "node:path";
3517
+ function isSubagentProcess() {
3518
+ return process.env.LETTA_CODE_AGENT_ROLE === "subagent";
3519
+ }
3500
3520
  function normalizeBaseUrl(baseUrl) {
3501
3521
  let normalized = baseUrl.replace(/^https?:\/\//, "");
3502
3522
  normalized = normalized.replace(/\/$/, "");
@@ -3529,14 +3549,18 @@ class SettingsManager {
3529
3549
  }
3530
3550
  this.initialized = true;
3531
3551
  await this.checkSecretsSupport();
3532
- await this.migrateTokensToSecrets();
3552
+ if (!isSubagentProcess()) {
3553
+ await this.migrateTokensToSecrets();
3554
+ }
3533
3555
  this.migrateToAgentsArray();
3534
3556
  } catch (error) {
3535
3557
  console.error("Error loading settings, using defaults:", error);
3536
3558
  this.settings = { ...DEFAULT_SETTINGS };
3537
3559
  this.initialized = true;
3538
3560
  await this.checkSecretsSupport();
3539
- await this.migrateTokensToSecrets();
3561
+ if (!isSubagentProcess()) {
3562
+ await this.migrateTokensToSecrets();
3563
+ }
3540
3564
  this.migrateToAgentsArray();
3541
3565
  }
3542
3566
  }
@@ -5625,7 +5649,6 @@ Your memory consists of memory blocks and external memory:
5625
5649
  - Memory Blocks: Stored as memory blocks, each containing a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and remain constantly available in-context.
5626
5650
  - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
5627
5651
 
5628
- Memory management tools allow you to edit existing memory blocks and query for external memories.
5629
5652
  Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
5630
5653
  They are the foundation which makes you *you*.
5631
5654
 
@@ -5704,7 +5727,7 @@ Some blocks are read-only in the API (e.g., certain system-managed blocks). For
5704
5727
  var init_system_prompt_memfs = () => {};
5705
5728
 
5706
5729
  // src/utils/error.ts
5707
- function getErrorMessage(error) {
5730
+ function getErrorMessage2(error) {
5708
5731
  return error instanceof Error ? error.message : String(error);
5709
5732
  }
5710
5733
 
@@ -6919,7 +6942,7 @@ function getBuiltinSubagents() {
6919
6942
  const config = parseSubagentContent(source);
6920
6943
  builtins[config.name] = config;
6921
6944
  } catch (error) {
6922
- console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage(error)}`);
6945
+ console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage2(error)}`);
6923
6946
  }
6924
6947
  }
6925
6948
  cache.builtins = builtins;
@@ -6954,14 +6977,14 @@ async function discoverSubagentsFromDir(agentsDir, seenNames, subagents, errors)
6954
6977
  } catch (error) {
6955
6978
  errors.push({
6956
6979
  path: filePath,
6957
- message: getErrorMessage(error)
6980
+ message: getErrorMessage2(error)
6958
6981
  });
6959
6982
  }
6960
6983
  }
6961
6984
  } catch (error) {
6962
6985
  errors.push({
6963
6986
  path: agentsDir,
6964
- message: `Failed to read agents directory: ${getErrorMessage(error)}`
6987
+ message: `Failed to read agents directory: ${getErrorMessage2(error)}`
6965
6988
  });
6966
6989
  }
6967
6990
  }
@@ -29211,6 +29234,12 @@ var create = (stream, { showCursor = false } = {}) => {
29211
29234
  let previousLineCount = 0;
29212
29235
  let previousOutput = "";
29213
29236
  let hasHiddenCursor = false;
29237
+ const renderWithClearedLineEnds = (output) => {
29238
+ const lines = output.split(`
29239
+ `);
29240
+ return lines.map((line) => line + exports_base.eraseEndLine).join(`
29241
+ `);
29242
+ };
29214
29243
  const render = (str) => {
29215
29244
  if (!showCursor && !hasHiddenCursor) {
29216
29245
  cli_cursor_default.hide();
@@ -29221,10 +29250,17 @@ var create = (stream, { showCursor = false } = {}) => {
29221
29250
  if (output === previousOutput) {
29222
29251
  return;
29223
29252
  }
29224
- previousOutput = output;
29225
- stream.write(exports_base.eraseLines(previousLineCount) + output);
29226
- previousLineCount = output.split(`
29253
+ const nextLineCount = output.split(`
29227
29254
  `).length;
29255
+ if (previousLineCount > 1) {
29256
+ stream.write(exports_base.cursorUp(previousLineCount - 1));
29257
+ }
29258
+ stream.write(renderWithClearedLineEnds(output));
29259
+ if (nextLineCount < previousLineCount) {
29260
+ stream.write(exports_base.eraseDown);
29261
+ }
29262
+ previousOutput = output;
29263
+ previousLineCount = nextLineCount;
29228
29264
  };
29229
29265
  render.clear = () => {
29230
29266
  stream.write(exports_base.eraseLines(previousLineCount));
@@ -31079,7 +31115,7 @@ var init_colors = __esm(() => {
31079
31115
  inline: "green"
31080
31116
  },
31081
31117
  link: {
31082
- text: "cyan",
31118
+ text: brandColors.primaryAccentLight,
31083
31119
  url: brandColors.primaryAccent
31084
31120
  },
31085
31121
  heading: {
@@ -33136,7 +33172,8 @@ var init_models2 = __esm(() => {
33136
33172
  isFeatured: true,
33137
33173
  free: true,
33138
33174
  updateArgs: {
33139
- context_window: 180000
33175
+ context_window: 160000,
33176
+ max_output_tokens: 64000
33140
33177
  }
33141
33178
  },
33142
33179
  {
@@ -33145,7 +33182,8 @@ var init_models2 = __esm(() => {
33145
33182
  label: "Minimax M2",
33146
33183
  description: "Minimax's latest model",
33147
33184
  updateArgs: {
33148
- context_window: 196000
33185
+ context_window: 160000,
33186
+ max_output_tokens: 64000
33149
33187
  }
33150
33188
  },
33151
33189
  {
@@ -54693,7 +54731,7 @@ function parseResultFromStdout(stdout, agentId) {
54693
54731
  agentId: agentId || "",
54694
54732
  report: "",
54695
54733
  success: false,
54696
- error: `Failed to parse subagent output: ${getErrorMessage(parseError)}`
54734
+ error: `Failed to parse subagent output: ${getErrorMessage2(parseError)}`
54697
54735
  };
54698
54736
  }
54699
54737
  }
@@ -54832,12 +54870,14 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
54832
54870
  return executeSubagent(type, config, primaryModel, userPrompt, baseURL, subagentId, true, signal, undefined, undefined, maxTurns);
54833
54871
  }
54834
54872
  }
54873
+ const propagatedError = state.finalError?.trim();
54874
+ const fallbackError = stderr || `Subagent exited with code ${exitCode}`;
54835
54875
  return {
54836
54876
  agentId: state.agentId || "",
54837
54877
  conversationId: state.conversationId || undefined,
54838
54878
  report: "",
54839
54879
  success: false,
54840
- error: stderr || `Subagent exited with code ${exitCode}`
54880
+ error: propagatedError || fallbackError
54841
54881
  };
54842
54882
  }
54843
54883
  if (state.finalResult !== null) {
@@ -54867,7 +54907,7 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
54867
54907
  agentId: "",
54868
54908
  report: "",
54869
54909
  success: false,
54870
- error: getErrorMessage(error)
54910
+ error: getErrorMessage2(error)
54871
54911
  };
54872
54912
  }
54873
54913
  }
@@ -55029,6 +55069,34 @@ function extractTaskNotificationsForDisplay(message) {
55029
55069
  }
55030
55070
 
55031
55071
  // src/tools/impl/Task.ts
55072
+ function buildTaskResultHeader(subagentType, result) {
55073
+ return [
55074
+ `subagent_type=${subagentType}`,
55075
+ result.agentId ? `agent_id=${result.agentId}` : undefined,
55076
+ result.conversationId ? `conversation_id=${result.conversationId}` : undefined
55077
+ ].filter(Boolean).join(" ");
55078
+ }
55079
+ function writeTaskTranscriptStart(outputFile, description, subagentType) {
55080
+ appendToOutputFile(outputFile, `[Task started: ${description}]
55081
+ [subagent_type: ${subagentType}]
55082
+
55083
+ `);
55084
+ }
55085
+ function writeTaskTranscriptResult(outputFile, result, header) {
55086
+ if (result.success) {
55087
+ appendToOutputFile(outputFile, `${header}
55088
+
55089
+ ${result.report}
55090
+
55091
+ [Task completed]
55092
+ `);
55093
+ return;
55094
+ }
55095
+ appendToOutputFile(outputFile, `[error] ${result.error || "Subagent execution failed"}
55096
+
55097
+ [Task failed]
55098
+ `);
55099
+ }
55032
55100
  async function task(args) {
55033
55101
  const { command = "run", model, toolCallId, signal } = args;
55034
55102
  if (command === "refresh") {
@@ -55067,7 +55135,7 @@ async function task(args) {
55067
55135
  registerSubagent(subagentId, subagent_type, description, toolCallId, isBackground);
55068
55136
  if (isBackground) {
55069
55137
  const taskId = getNextTaskId();
55070
- const outputFile = createBackgroundOutputFile(taskId);
55138
+ const outputFile2 = createBackgroundOutputFile(taskId);
55071
55139
  const abortController = new AbortController;
55072
55140
  const bgTask = {
55073
55141
  description,
@@ -55076,37 +55144,21 @@ async function task(args) {
55076
55144
  status: "running",
55077
55145
  output: [],
55078
55146
  startTime: new Date,
55079
- outputFile,
55147
+ outputFile: outputFile2,
55080
55148
  abortController
55081
55149
  };
55082
55150
  backgroundTasks.set(taskId, bgTask);
55083
- appendToOutputFile(outputFile, `[Task started: ${description}]
55084
- [subagent_type: ${subagent_type}]
55085
-
55086
- `);
55151
+ writeTaskTranscriptStart(outputFile2, description, subagent_type);
55087
55152
  spawnSubagent(subagent_type, prompt, model, subagentId, abortController.signal, args.agent_id, args.conversation_id, args.max_turns).then((result) => {
55088
55153
  bgTask.status = result.success ? "completed" : "failed";
55089
55154
  if (result.error) {
55090
55155
  bgTask.error = result.error;
55091
55156
  }
55092
- const header = [
55093
- `subagent_type=${subagent_type}`,
55094
- result.agentId ? `agent_id=${result.agentId}` : undefined,
55095
- result.conversationId ? `conversation_id=${result.conversationId}` : undefined
55096
- ].filter(Boolean).join(" ");
55157
+ const header = buildTaskResultHeader(subagent_type, result);
55158
+ writeTaskTranscriptResult(outputFile2, result, header);
55097
55159
  if (result.success) {
55098
- appendToOutputFile(outputFile, `${header}
55099
-
55100
- ${result.report}
55101
- `);
55102
55160
  bgTask.output.push(result.report || "");
55103
- } else {
55104
- appendToOutputFile(outputFile, `[error] ${result.error || "Subagent execution failed"}
55105
- `);
55106
55161
  }
55107
- appendToOutputFile(outputFile, `
55108
- [Task ${result.success ? "completed" : "failed"}]
55109
- `);
55110
55162
  completeSubagent(subagentId, {
55111
55163
  success: result.success,
55112
55164
  error: result.error,
@@ -55125,7 +55177,7 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
55125
55177
  status: result.success ? "completed" : "failed",
55126
55178
  summary: `Agent "${description}" ${result.success ? "completed" : "failed"}`,
55127
55179
  result: truncatedResult,
55128
- outputFile,
55180
+ outputFile: outputFile2,
55129
55181
  usage: {
55130
55182
  totalTokens: result.totalTokens,
55131
55183
  toolUses,
@@ -55138,7 +55190,7 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
55138
55190
  const errorMessage = error instanceof Error ? error.message : String(error);
55139
55191
  bgTask.status = "failed";
55140
55192
  bgTask.error = errorMessage;
55141
- appendToOutputFile(outputFile, `[error] ${errorMessage}
55193
+ appendToOutputFile(outputFile2, `[error] ${errorMessage}
55142
55194
  `);
55143
55195
  completeSubagent(subagentId, { success: false, error: errorMessage });
55144
55196
  const subagentSnapshot = getSnapshot2();
@@ -55149,7 +55201,7 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
55149
55201
  status: "failed",
55150
55202
  summary: `Agent "${description}" failed`,
55151
55203
  result: errorMessage,
55152
- outputFile,
55204
+ outputFile: outputFile2,
55153
55205
  usage: {
55154
55206
  toolUses,
55155
55207
  durationMs
@@ -55159,8 +55211,11 @@ ${result.report || ""}` : result.error || "Subagent execution failed";
55159
55211
  runSubagentStopHooks(subagent_type, subagentId, false, errorMessage, args.agent_id, args.conversation_id).catch(() => {});
55160
55212
  });
55161
55213
  return `Task running in background with ID: ${taskId}
55162
- Output file: ${outputFile}`;
55214
+ Output file: ${outputFile2}`;
55163
55215
  }
55216
+ const foregroundTaskId = getNextTaskId();
55217
+ const outputFile = createBackgroundOutputFile(foregroundTaskId);
55218
+ writeTaskTranscriptStart(outputFile, description, subagent_type);
55164
55219
  try {
55165
55220
  const result = await spawnSubagent(subagent_type, prompt, model, subagentId, signal, args.agent_id, args.conversation_id, args.max_turns);
55166
55221
  completeSubagent(subagentId, {
@@ -55170,24 +55225,34 @@ Output file: ${outputFile}`;
55170
55225
  });
55171
55226
  runSubagentStopHooks(subagent_type, subagentId, result.success, result.error, result.agentId, result.conversationId).catch(() => {});
55172
55227
  if (!result.success) {
55173
- return `Error: ${result.error || "Subagent execution failed"}`;
55228
+ const errorMessage = result.error || "Subagent execution failed";
55229
+ const failedResult = {
55230
+ ...result,
55231
+ error: errorMessage
55232
+ };
55233
+ writeTaskTranscriptResult(outputFile, failedResult, "");
55234
+ return `Error: ${errorMessage}
55235
+ Output file: ${outputFile}`;
55174
55236
  }
55175
- const header = [
55176
- `subagent_type=${subagent_type}`,
55177
- result.agentId ? `agent_id=${result.agentId}` : undefined,
55178
- result.conversationId ? `conversation_id=${result.conversationId}` : undefined
55179
- ].filter(Boolean).join(" ");
55237
+ const header = buildTaskResultHeader(subagent_type, result);
55180
55238
  const fullOutput = `${header}
55181
55239
 
55182
55240
  ${result.report}`;
55241
+ writeTaskTranscriptResult(outputFile, result, header);
55183
55242
  const userCwd = process.env.USER_CWD || process.cwd();
55184
55243
  const { content: truncatedOutput } = truncateByChars(fullOutput, LIMITS.TASK_OUTPUT_CHARS, "Task", { workingDirectory: userCwd, toolName: "Task" });
55185
- return truncatedOutput;
55244
+ return `${truncatedOutput}
55245
+ Output file: ${outputFile}`;
55186
55246
  } catch (error) {
55187
55247
  const errorMessage = error instanceof Error ? error.message : String(error);
55188
55248
  completeSubagent(subagentId, { success: false, error: errorMessage });
55189
55249
  runSubagentStopHooks(subagent_type, subagentId, false, errorMessage, args.agent_id, args.conversation_id).catch(() => {});
55190
- return `Error: ${errorMessage}`;
55250
+ appendToOutputFile(outputFile, `[error] ${errorMessage}
55251
+
55252
+ [Task failed]
55253
+ `);
55254
+ return `Error: ${errorMessage}
55255
+ Output file: ${outputFile}`;
55191
55256
  }
55192
55257
  }
55193
55258
  var VALID_DEPLOY_TYPES;
@@ -58567,6 +58632,7 @@ var exports_analyzer = {};
58567
58632
  __export(exports_analyzer, {
58568
58633
  analyzeApprovalContext: () => analyzeApprovalContext
58569
58634
  });
58635
+ import { homedir as homedir11 } from "node:os";
58570
58636
  import { dirname as dirname8, resolve as resolve15 } from "node:path";
58571
58637
  function analyzeApprovalContext(toolName, toolArgs, workingDirectory) {
58572
58638
  const resolveFilePath = () => {
@@ -58667,7 +58733,85 @@ function containsDangerousCommand(command) {
58667
58733
  }
58668
58734
  return false;
58669
58735
  }
58670
- function analyzeBashApproval(command, _workingDir) {
58736
+ function escapeRegex(text) {
58737
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58738
+ }
58739
+ function normalizePathSeparators(path18) {
58740
+ return path18.replace(/\\/g, "/");
58741
+ }
58742
+ function parseAbsoluteCommandPaths(command) {
58743
+ const normalized = command.replace(/\\"/g, '"').replace(/\\'/g, "'");
58744
+ const candidates = [];
58745
+ const quotedRegex = /["']((?:[A-Za-z]:)?\/[^"']+)["']/g;
58746
+ let quotedMatch = quotedRegex.exec(normalized);
58747
+ while (quotedMatch) {
58748
+ if (quotedMatch[1]) {
58749
+ candidates.push(normalizePathSeparators(quotedMatch[1]));
58750
+ }
58751
+ quotedMatch = quotedRegex.exec(normalized);
58752
+ }
58753
+ const tokens = normalized.split(/\s+/);
58754
+ for (const token of tokens) {
58755
+ const cleaned = token.replace(/^["'`([{]+/, "").replace(/["'`),;|\]}]+$/g, "");
58756
+ if (/^(?:[A-Za-z]:)?\//.test(cleaned)) {
58757
+ candidates.push(normalizePathSeparators(cleaned));
58758
+ }
58759
+ }
58760
+ return Array.from(new Set(candidates));
58761
+ }
58762
+ function detectSkillScript(command, workingDir) {
58763
+ const pathCandidates = parseAbsoluteCommandPaths(command);
58764
+ if (pathCandidates.length === 0) {
58765
+ return null;
58766
+ }
58767
+ const normalizedWorkingDir = normalizePathSeparators(workingDir).replace(/\/$/, "");
58768
+ const normalizedHomeDir = normalizePathSeparators(homedir11()).replace(/\/$/, "");
58769
+ const detect = (source, regex2) => {
58770
+ for (const candidate of pathCandidates) {
58771
+ const match3 = candidate.match(regex2);
58772
+ if (!match3?.[1]) {
58773
+ continue;
58774
+ }
58775
+ const skillName = match3[1];
58776
+ const skillRootPath = match3[0].replace(/\/scripts\/$/, "");
58777
+ return { source, skillName, skillRootPath };
58778
+ }
58779
+ return null;
58780
+ };
58781
+ const projectRegex = new RegExp(`^${escapeRegex(normalizedWorkingDir)}/\\.skills/(.+?)/scripts/`);
58782
+ const projectSkill = detect("project", projectRegex);
58783
+ if (projectSkill) {
58784
+ return projectSkill;
58785
+ }
58786
+ const agentRegex = new RegExp(`^${escapeRegex(normalizedHomeDir)}/\\.letta/agents/[^/]+/skills/(.+?)/scripts/`);
58787
+ const agentSkill = detect("agent-scoped", agentRegex);
58788
+ if (agentSkill) {
58789
+ return agentSkill;
58790
+ }
58791
+ const globalRegex = new RegExp(`^${escapeRegex(normalizedHomeDir)}/\\.letta/skills/(.+?)/scripts/`);
58792
+ const globalSkill = detect("global", globalRegex);
58793
+ if (globalSkill) {
58794
+ return globalSkill;
58795
+ }
58796
+ const bundledSkill = detect("bundled", /\/skills\/builtin\/([^/]+)\/scripts\//);
58797
+ if (bundledSkill) {
58798
+ return bundledSkill;
58799
+ }
58800
+ return null;
58801
+ }
58802
+ function buildSkillScriptRule(command, skillRootPath) {
58803
+ const normalizedCommand = normalizePathSeparators(command).trim();
58804
+ const rootIndex = normalizedCommand.indexOf(skillRootPath);
58805
+ if (rootIndex === -1) {
58806
+ return `Bash(${normalizedCommand})`;
58807
+ }
58808
+ const rulePrefix = normalizedCommand.slice(0, rootIndex + skillRootPath.length);
58809
+ return `Bash(${rulePrefix}:*)`;
58810
+ }
58811
+ function getSkillApprovalText(source, skillName) {
58812
+ return `Yes, and don't ask again for scripts in ${source} skill '${skillName}'`;
58813
+ }
58814
+ function analyzeBashApproval(command, workingDir) {
58671
58815
  const parts = command.trim().split(/\s+/);
58672
58816
  const baseCommand = parts[0] || "";
58673
58817
  const firstArg = parts[1] || "";
@@ -58691,6 +58835,18 @@ function analyzeBashApproval(command, _workingDir) {
58691
58835
  safetyLevel: "dangerous"
58692
58836
  };
58693
58837
  }
58838
+ const skillScript = detectSkillScript(command, workingDir);
58839
+ if (skillScript) {
58840
+ const { source, skillName, skillRootPath } = skillScript;
58841
+ return {
58842
+ recommendedRule: buildSkillScriptRule(command, skillRootPath),
58843
+ ruleDescription: `scripts in ${source} skill '${skillName}'`,
58844
+ approveAlwaysText: getSkillApprovalText(source, skillName),
58845
+ defaultScope: "project",
58846
+ allowPersistence: true,
58847
+ safetyLevel: "moderate"
58848
+ };
58849
+ }
58694
58850
  if (baseCommand === "git") {
58695
58851
  const gitSubcommand = firstArg;
58696
58852
  const safeGitCommands = ["status", "diff", "log", "show", "branch"];
@@ -60957,7 +61113,7 @@ function getBuiltinSubagents2() {
60957
61113
  const config = parseSubagentContent2(source);
60958
61114
  builtins[config.name] = config;
60959
61115
  } catch (error) {
60960
- console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage(error)}`);
61116
+ console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage2(error)}`);
60961
61117
  }
60962
61118
  }
60963
61119
  cache5.builtins = builtins;
@@ -60992,14 +61148,14 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
60992
61148
  } catch (error) {
60993
61149
  errors.push({
60994
61150
  path: filePath,
60995
- message: getErrorMessage(error)
61151
+ message: getErrorMessage2(error)
60996
61152
  });
60997
61153
  }
60998
61154
  }
60999
61155
  } catch (error) {
61000
61156
  errors.push({
61001
61157
  path: agentsDir,
61002
- message: `Failed to read agents directory: ${getErrorMessage(error)}`
61158
+ message: `Failed to read agents directory: ${getErrorMessage2(error)}`
61003
61159
  });
61004
61160
  }
61005
61161
  }
@@ -63840,6 +63996,49 @@ var init_errorContext = __esm(() => {
63840
63996
  });
63841
63997
 
63842
63998
  // src/cli/helpers/errorFormatter.ts
63999
+ function extractReasonList(value) {
64000
+ if (!Array.isArray(value))
64001
+ return [];
64002
+ return value.filter((reason) => typeof reason === "string").map((reason) => reason.toLowerCase());
64003
+ }
64004
+ function getErrorReasons(e) {
64005
+ const reasons = new Set;
64006
+ const errorBody = e.error;
64007
+ if (errorBody && typeof errorBody === "object") {
64008
+ const body = errorBody;
64009
+ for (const reason of extractReasonList(body.reasons)) {
64010
+ reasons.add(reason);
64011
+ }
64012
+ if (body.error && typeof body.error === "object") {
64013
+ const nested = body.error;
64014
+ for (const reason of extractReasonList(nested.reasons)) {
64015
+ reasons.add(reason);
64016
+ }
64017
+ }
64018
+ }
64019
+ const message = e.message?.toLowerCase() ?? "";
64020
+ for (const knownReason of [
64021
+ "not-enough-credits",
64022
+ "model-unknown",
64023
+ "byok-not-available-on-free-tier",
64024
+ "free-usage-exceeded",
64025
+ "premium-usage-exceeded",
64026
+ "standard-usage-exceeded",
64027
+ "basic-usage-exceeded",
64028
+ "context-window-size-not-supported",
64029
+ "agents-limit-exceeded",
64030
+ "exceeded-quota"
64031
+ ]) {
64032
+ if (message.includes(knownReason)) {
64033
+ reasons.add(knownReason);
64034
+ }
64035
+ }
64036
+ return Array.from(reasons);
64037
+ }
64038
+ function hasErrorReason(e, reason, reasons) {
64039
+ const allReasons = reasons ?? getErrorReasons(e);
64040
+ return allReasons.includes(reason.toLowerCase());
64041
+ }
63843
64042
  function getRateLimitResetMs(e) {
63844
64043
  if (e.status !== 429)
63845
64044
  return;
@@ -63893,52 +64092,26 @@ function getResourceLimitMessage(e) {
63893
64092
  }
63894
64093
  return;
63895
64094
  }
63896
- function isAgentLimitError(e) {
64095
+ function isAgentLimitError(e, reasons) {
63897
64096
  if (e.status !== 429)
63898
64097
  return false;
63899
- const errorBody = e.error;
63900
- if (errorBody && typeof errorBody === "object") {
63901
- if ("reasons" in errorBody && Array.isArray(errorBody.reasons)) {
63902
- if (errorBody.reasons.includes("agents-limit-exceeded")) {
63903
- return true;
63904
- }
63905
- }
63906
- }
63907
- return false;
64098
+ return hasErrorReason(e, "agents-limit-exceeded", reasons);
63908
64099
  }
63909
- function isCreditExhaustedError(e) {
64100
+ function isCreditExhaustedError(e, reasons) {
63910
64101
  if (e.status !== 402)
63911
64102
  return false;
63912
- const errorBody = e.error;
63913
- if (errorBody && typeof errorBody === "object") {
63914
- if ("reasons" in errorBody && Array.isArray(errorBody.reasons)) {
63915
- if (errorBody.reasons.includes("not-enough-credits")) {
63916
- return true;
63917
- }
63918
- }
63919
- if ("error" in errorBody && typeof errorBody.error === "object") {
63920
- const nested = errorBody.error;
63921
- if ("reasons" in nested && Array.isArray(nested.reasons)) {
63922
- if (nested.reasons.includes("not-enough-credits")) {
63923
- return true;
63924
- }
63925
- }
63926
- }
63927
- }
63928
- if (e.message?.includes("not-enough-credits")) {
63929
- return true;
63930
- }
63931
- return false;
64103
+ return hasErrorReason(e, "not-enough-credits", reasons);
63932
64104
  }
63933
64105
  function formatErrorDetails(e, agentId, conversationId) {
63934
64106
  let runId;
63935
64107
  if (e instanceof APIError2) {
64108
+ const reasons = getErrorReasons(e);
63936
64109
  const rateLimitResetMs = getRateLimitResetMs(e);
63937
64110
  if (rateLimitResetMs !== undefined) {
63938
64111
  const resetInfo = rateLimitResetMs > 0 ? formatResetTime(rateLimitResetMs) : "Try again later";
63939
64112
  return `You've hit your usage limit. ${resetInfo}. View usage: ${LETTA_USAGE_URL}`;
63940
64113
  }
63941
- if (isAgentLimitError(e)) {
64114
+ if (isAgentLimitError(e, reasons)) {
63942
64115
  const { billingTier } = getErrorContext();
63943
64116
  if (billingTier?.toLowerCase() === "free") {
63944
64117
  return `You've reached the agent limit (3) for the Free Plan. Delete agents at: ${LETTA_AGENTS_URL}
@@ -63947,6 +64120,12 @@ Or upgrade to Pro for unlimited agents at: ${LETTA_USAGE_URL}`;
63947
64120
  return `You've reached your agent limit. Delete agents at: ${LETTA_AGENTS_URL}
63948
64121
  Or check your plan at: ${LETTA_USAGE_URL}`;
63949
64122
  }
64123
+ if (hasErrorReason(e, "model-unknown", reasons)) {
64124
+ return `The selected model is not currently available for this account or provider. Run /model and press R to refresh available models, then choose an available model or connect a provider with /connect.`;
64125
+ }
64126
+ if (hasErrorReason(e, "context-window-size-not-supported", reasons)) {
64127
+ return `The selected context window is not supported for this model. Switch models with /model or pick a model with a larger context window.`;
64128
+ }
63950
64129
  const resourceLimitMsg = getResourceLimitMessage(e);
63951
64130
  if (resourceLimitMsg) {
63952
64131
  const match3 = resourceLimitMsg.match(/limit for (\w+)/);
@@ -63955,13 +64134,19 @@ Or check your plan at: ${LETTA_USAGE_URL}`;
63955
64134
  Upgrade at: ${LETTA_USAGE_URL}
63956
64135
  Delete ${resourceType} at: ${LETTA_AGENTS_URL}`;
63957
64136
  }
63958
- if (isCreditExhaustedError(e)) {
63959
- const { billingTier, modelDisplayName } = getErrorContext();
63960
- if (billingTier?.toLowerCase() === "free") {
63961
- const modelInfo = modelDisplayName ? ` (${modelDisplayName})` : "";
63962
- return `Selected hosted model${modelInfo} not available on Free plan. Switch to a free model with /model (glm-4.7 or minimax-m2.1), upgrade your account at ${LETTA_USAGE_URL}, or connect your own API keys with /connect.`;
63963
- }
63964
- return `Your account is out of credits. Redeem additional credits or configure auto-recharge on your account page: ${LETTA_USAGE_URL}`;
64137
+ if (isCreditExhaustedError(e, reasons)) {
64138
+ return `Your account is out of credits for hosted inference. Add credits, enable auto-recharge, or upgrade at ${LETTA_USAGE_URL}. You can also connect your own provider keys with /connect.`;
64139
+ }
64140
+ if (hasErrorReason(e, "premium-usage-exceeded", reasons) || hasErrorReason(e, "standard-usage-exceeded", reasons) || hasErrorReason(e, "basic-usage-exceeded", reasons)) {
64141
+ return `You've reached your hosted model usage limit. View your plan and usage at ${LETTA_USAGE_URL}, or connect your own provider keys with /connect.`;
64142
+ }
64143
+ if (hasErrorReason(e, "byok-not-available-on-free-tier", reasons)) {
64144
+ const { modelDisplayName } = getErrorContext();
64145
+ const modelInfo = modelDisplayName ? ` (${modelDisplayName})` : "";
64146
+ return `Selected BYOK model${modelInfo} is not available on the Free plan. Switch to a free hosted model with /model (glm-4.7 or minimax-m2.1), or upgrade at ${LETTA_USAGE_URL}.`;
64147
+ }
64148
+ if (hasErrorReason(e, "free-usage-exceeded", reasons)) {
64149
+ return `You've reached the Free plan hosted model usage limit. Switch to free hosted models with /model (glm-4.7 or minimax-m2.1), upgrade at ${LETTA_USAGE_URL}, or connect your own provider keys with /connect.`;
63965
64150
  }
63966
64151
  if (e.error && typeof e.error === "object" && "error" in e.error) {
63967
64152
  const errorData = e.error.error;
@@ -66696,10 +66881,10 @@ __export(exports_settings, {
66696
66881
  loadProjectSettings: () => loadProjectSettings,
66697
66882
  getSetting: () => getSetting
66698
66883
  });
66699
- import { homedir as homedir12 } from "node:os";
66884
+ import { homedir as homedir13 } from "node:os";
66700
66885
  import { join as join20 } from "node:path";
66701
66886
  function getSettingsPath() {
66702
- return join20(homedir12(), ".letta", "settings.json");
66887
+ return join20(homedir13(), ".letta", "settings.json");
66703
66888
  }
66704
66889
  async function loadSettings() {
66705
66890
  const settingsPath = getSettingsPath();
@@ -72693,8 +72878,9 @@ function AnimationProvider({
72693
72878
  children,
72694
72879
  shouldAnimate
72695
72880
  }) {
72881
+ const contextValue = import_react45.useMemo(() => ({ shouldAnimate }), [shouldAnimate]);
72696
72882
  return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(AnimationContext.Provider, {
72697
- value: { shouldAnimate },
72883
+ value: contextValue,
72698
72884
  children
72699
72885
  }, undefined, false, undefined, this);
72700
72886
  }
@@ -72750,11 +72936,18 @@ var init_CollapsedOutputDisplay = __esm(async () => {
72750
72936
  jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
72751
72937
  CollapsedOutputDisplay = import_react47.memo(({
72752
72938
  output,
72753
- maxLines = DEFAULT_COLLAPSED_LINES
72939
+ maxLines = DEFAULT_COLLAPSED_LINES,
72940
+ maxChars
72754
72941
  }) => {
72755
72942
  const columns = useTerminalWidth();
72756
72943
  const contentWidth = Math.max(0, columns - PREFIX_WIDTH);
72757
- const lines = output.split(`
72944
+ let displayOutput = output;
72945
+ let clippedByChars = false;
72946
+ if (typeof maxChars === "number" && maxChars > 0 && output.length > maxChars) {
72947
+ displayOutput = `${output.slice(0, maxChars)}…`;
72948
+ clippedByChars = true;
72949
+ }
72950
+ const lines = displayOutput.split(`
72758
72951
  `);
72759
72952
  if (lines.length > 0 && lines[lines.length - 1] === "") {
72760
72953
  lines.pop();
@@ -72829,6 +73022,26 @@ var init_CollapsedOutputDisplay = __esm(async () => {
72829
73022
  }, undefined, true, undefined, this)
72830
73023
  }, undefined, false, undefined, this)
72831
73024
  ]
73025
+ }, undefined, true, undefined, this),
73026
+ clippedByChars && /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
73027
+ flexDirection: "row",
73028
+ children: [
73029
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
73030
+ width: PREFIX_WIDTH,
73031
+ flexShrink: 0,
73032
+ children: /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text2, {
73033
+ children: " "
73034
+ }, undefined, false, undefined, this)
73035
+ }, undefined, false, undefined, this),
73036
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
73037
+ flexGrow: 1,
73038
+ width: contentWidth,
73039
+ children: /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text2, {
73040
+ dimColor: true,
73041
+ children: "… output clipped"
73042
+ }, undefined, false, undefined, this)
73043
+ }, undefined, false, undefined, this)
73044
+ ]
72832
73045
  }, undefined, true, undefined, this)
72833
73046
  ]
72834
73047
  }, undefined, true, undefined, this);
@@ -74872,7 +75085,7 @@ import {
74872
75085
  readFileSync as readFileSync6,
74873
75086
  writeFileSync as writeFileSync5
74874
75087
  } from "node:fs";
74875
- import { homedir as homedir13, platform as platform3 } from "node:os";
75088
+ import { homedir as homedir14, platform as platform3 } from "node:os";
74876
75089
  import { dirname as dirname12, join as join22 } from "node:path";
74877
75090
  function detectTerminalType() {
74878
75091
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
@@ -74905,7 +75118,7 @@ function getKeybindingsPath(terminal) {
74905
75118
  }[terminal];
74906
75119
  const os5 = platform3();
74907
75120
  if (os5 === "darwin") {
74908
- return join22(homedir13(), "Library", "Application Support", appName, "User", "keybindings.json");
75121
+ return join22(homedir14(), "Library", "Application Support", appName, "User", "keybindings.json");
74909
75122
  }
74910
75123
  if (os5 === "win32") {
74911
75124
  const appData = process.env.APPDATA;
@@ -74914,7 +75127,7 @@ function getKeybindingsPath(terminal) {
74914
75127
  return join22(appData, appName, "User", "keybindings.json");
74915
75128
  }
74916
75129
  if (os5 === "linux") {
74917
- return join22(homedir13(), ".config", appName, "User", "keybindings.json");
75130
+ return join22(homedir14(), ".config", appName, "User", "keybindings.json");
74918
75131
  }
74919
75132
  return null;
74920
75133
  }
@@ -75071,10 +75284,10 @@ function getWezTermConfigPath() {
75071
75284
  if (existsSync13(xdgPath))
75072
75285
  return xdgPath;
75073
75286
  }
75074
- const configPath = join22(homedir13(), ".config", "wezterm", "wezterm.lua");
75287
+ const configPath = join22(homedir14(), ".config", "wezterm", "wezterm.lua");
75075
75288
  if (existsSync13(configPath))
75076
75289
  return configPath;
75077
- return join22(homedir13(), ".wezterm.lua");
75290
+ return join22(homedir14(), ".wezterm.lua");
75078
75291
  }
75079
75292
  function wezTermDeleteFixExists(configPath) {
75080
75293
  if (!existsSync13(configPath))
@@ -80701,7 +80914,8 @@ var init_ShimmerText = __esm(async () => {
80701
80914
  color = colors.status.processing,
80702
80915
  boldPrefix,
80703
80916
  message,
80704
- shimmerOffset
80917
+ shimmerOffset,
80918
+ wrap
80705
80919
  }) {
80706
80920
  const fullText = `${boldPrefix ? `${boldPrefix} ` : ""}${message}…`;
80707
80921
  const prefixLength = boldPrefix ? boldPrefix.length + 1 : 0;
@@ -80716,6 +80930,7 @@ var init_ShimmerText = __esm(async () => {
80716
80930
  return isInPrefix ? source_default.bold(styledChar) : styledChar;
80717
80931
  }).join("");
80718
80932
  return /* @__PURE__ */ jsx_dev_runtime44.jsxDEV(Text2, {
80933
+ wrap,
80719
80934
  children: shimmerText
80720
80935
  }, undefined, false, undefined, this);
80721
80936
  });
@@ -80724,6 +80939,15 @@ var init_ShimmerText = __esm(async () => {
80724
80939
  // src/cli/components/InputRich.tsx
80725
80940
  import { EventEmitter as EventEmitter5 } from "node:events";
80726
80941
  import { stdin } from "node:process";
80942
+ function truncateEnd(value, maxChars) {
80943
+ if (maxChars <= 0)
80944
+ return "";
80945
+ if (value.length <= maxChars)
80946
+ return value;
80947
+ if (maxChars <= 3)
80948
+ return value.slice(0, maxChars);
80949
+ return `${value.slice(0, maxChars - 3)}...`;
80950
+ }
80727
80951
  function getVisualLines(text, lineWidth) {
80728
80952
  const lines = [];
80729
80953
  let lineStart = 0;
@@ -80789,7 +81013,9 @@ function Input({
80789
81013
  onPasteError,
80790
81014
  restoredInput,
80791
81015
  onRestoredInputConsumed,
80792
- networkPhase = null
81016
+ networkPhase = null,
81017
+ terminalWidth,
81018
+ shouldAnimate = true
80793
81019
  }) {
80794
81020
  const [value, setValue] = import_react68.useState("");
80795
81021
  const [escapePressed, setEscapePressed] = import_react68.useState(false);
@@ -80801,7 +81027,7 @@ function Input({
80801
81027
  const [isAutocompleteActive, setIsAutocompleteActive] = import_react68.useState(false);
80802
81028
  const [cursorPos, setCursorPos] = import_react68.useState(undefined);
80803
81029
  const [currentCursorPosition, setCurrentCursorPosition] = import_react68.useState(0);
80804
- const columns = useTerminalWidth();
81030
+ const columns = terminalWidth;
80805
81031
  const contentWidth = Math.max(0, columns - 2);
80806
81032
  const interactionEnabled = visible && inputEnabled;
80807
81033
  const reserveInputSpace = !collapseInputWhenDisabled;
@@ -80810,6 +81036,38 @@ function Input({
80810
81036
  return Math.max(1, getVisualLines(value, contentWidth).length);
80811
81037
  }, [value, contentWidth]);
80812
81038
  const inputChromeHeight = inputRowLines + 3;
81039
+ const computedFooterRightColumnWidth = import_react68.useMemo(() => Math.max(28, Math.min(72, Math.floor(columns * 0.45))), [columns]);
81040
+ const [footerRightColumnWidth, setFooterRightColumnWidth] = import_react68.useState(computedFooterRightColumnWidth);
81041
+ const debugFlicker = process.env.LETTA_DEBUG_FLICKER === "1";
81042
+ import_react68.useEffect(() => {
81043
+ if (!streaming) {
81044
+ setFooterRightColumnWidth(computedFooterRightColumnWidth);
81045
+ return;
81046
+ }
81047
+ if (computedFooterRightColumnWidth >= footerRightColumnWidth) {
81048
+ const growthDelta = computedFooterRightColumnWidth - footerRightColumnWidth;
81049
+ if (debugFlicker && growthDelta >= FOOTER_WIDTH_STREAMING_DELTA) {
81050
+ console.error(`[debug:flicker:footer-width] defer growth ${footerRightColumnWidth} -> ${computedFooterRightColumnWidth} (delta=${growthDelta})`);
81051
+ }
81052
+ return;
81053
+ }
81054
+ const shrinkDelta = footerRightColumnWidth - computedFooterRightColumnWidth;
81055
+ if (shrinkDelta < FOOTER_WIDTH_STREAMING_DELTA) {
81056
+ if (debugFlicker && shrinkDelta > 0) {
81057
+ console.error(`[debug:flicker:footer-width] ignore minor shrink ${footerRightColumnWidth} -> ${computedFooterRightColumnWidth} (delta=${shrinkDelta})`);
81058
+ }
81059
+ return;
81060
+ }
81061
+ if (debugFlicker) {
81062
+ console.error(`[debug:flicker:footer-width] shrink ${footerRightColumnWidth} -> ${computedFooterRightColumnWidth} (delta=${shrinkDelta})`);
81063
+ }
81064
+ setFooterRightColumnWidth(computedFooterRightColumnWidth);
81065
+ }, [
81066
+ streaming,
81067
+ computedFooterRightColumnWidth,
81068
+ footerRightColumnWidth,
81069
+ debugFlicker
81070
+ ]);
80813
81071
  const [history, setHistory] = import_react68.useState([]);
80814
81072
  const [historyIndex, setHistoryIndex] = import_react68.useState(-1);
80815
81073
  const [temporaryInput, setTemporaryInput] = import_react68.useState("");
@@ -80825,18 +81083,18 @@ function Input({
80825
81083
  onRestoredInputConsumed?.();
80826
81084
  }
80827
81085
  }, [restoredInput, value, onRestoredInputConsumed]);
80828
- const handleBangAtEmpty = () => {
81086
+ const handleBangAtEmpty = import_react68.useCallback(() => {
80829
81087
  if (isBashMode)
80830
81088
  return false;
80831
81089
  setIsBashMode(true);
80832
81090
  return true;
80833
- };
80834
- const handleBackspaceAtEmpty = () => {
81091
+ }, [isBashMode]);
81092
+ const handleBackspaceAtEmpty = import_react68.useCallback(() => {
80835
81093
  if (!isBashMode)
80836
81094
  return false;
80837
81095
  setIsBashMode(false);
80838
81096
  return true;
80839
- };
81097
+ }, [isBashMode]);
80840
81098
  import_react68.useEffect(() => {
80841
81099
  if (cursorPos !== undefined) {
80842
81100
  const timer = setTimeout(() => setCursorPos(undefined), 0);
@@ -80857,9 +81115,6 @@ function Input({
80857
81115
  setCurrentMode(externalMode);
80858
81116
  }
80859
81117
  }, [externalMode]);
80860
- const [shimmerOffset, setShimmerOffset] = import_react68.useState(-3);
80861
- const [elapsedMs, setElapsedMs] = import_react68.useState(0);
80862
- const streamStartRef = import_react68.useRef(null);
80863
81118
  import_react68.useEffect(() => {
80864
81119
  if (!interactionEnabled) {
80865
81120
  setIsAutocompleteActive(false);
@@ -81078,35 +81333,7 @@ function Input({
81078
81333
  clearTimeout(ctrlCTimerRef.current);
81079
81334
  };
81080
81335
  }, []);
81081
- import_react68.useEffect(() => {
81082
- if (!streaming || !visible)
81083
- return;
81084
- const id = setInterval(() => {
81085
- setShimmerOffset((prev) => {
81086
- const prefixLen = agentName ? agentName.length + 1 : 0;
81087
- const len = prefixLen + thinkingMessage.length;
81088
- const next = prev + 1;
81089
- return next > len + 3 ? -3 : next;
81090
- });
81091
- }, 120);
81092
- return () => clearInterval(id);
81093
- }, [streaming, thinkingMessage, visible, agentName]);
81094
- import_react68.useEffect(() => {
81095
- if (streaming && visible) {
81096
- if (streamStartRef.current === null) {
81097
- streamStartRef.current = performance.now();
81098
- }
81099
- const id = setInterval(() => {
81100
- if (streamStartRef.current !== null) {
81101
- setElapsedMs(performance.now() - streamStartRef.current);
81102
- }
81103
- }, 1000);
81104
- return () => clearInterval(id);
81105
- }
81106
- streamStartRef.current = null;
81107
- setElapsedMs(0);
81108
- }, [streaming, visible]);
81109
- const handleSubmit = async () => {
81336
+ const handleSubmit = import_react68.useCallback(async () => {
81110
81337
  if (isAutocompleteActive) {
81111
81338
  return;
81112
81339
  }
@@ -81116,9 +81343,11 @@ function Input({
81116
81343
  return;
81117
81344
  if (bashRunning)
81118
81345
  return;
81119
- if (previousValue.trim() !== history[history.length - 1]) {
81120
- setHistory([...history, previousValue]);
81121
- }
81346
+ setHistory((prev) => {
81347
+ if (previousValue.trim() === prev[prev.length - 1])
81348
+ return prev;
81349
+ return [...prev, previousValue];
81350
+ });
81122
81351
  setHistoryIndex(-1);
81123
81352
  setTemporaryInput("");
81124
81353
  setValue("");
@@ -81127,8 +81356,12 @@ function Input({
81127
81356
  }
81128
81357
  return;
81129
81358
  }
81130
- if (previousValue.trim() && previousValue !== history[history.length - 1]) {
81131
- setHistory([...history, previousValue]);
81359
+ if (previousValue.trim()) {
81360
+ setHistory((prev) => {
81361
+ if (previousValue === prev[prev.length - 1])
81362
+ return prev;
81363
+ return [...prev, previousValue];
81364
+ });
81132
81365
  }
81133
81366
  setHistoryIndex(-1);
81134
81367
  setTemporaryInput("");
@@ -81137,8 +81370,15 @@ function Input({
81137
81370
  if (!result.submitted) {
81138
81371
  setValue(previousValue);
81139
81372
  }
81140
- };
81141
- const handleFileSelect = (selectedPath) => {
81373
+ }, [
81374
+ isAutocompleteActive,
81375
+ value,
81376
+ isBashMode,
81377
+ bashRunning,
81378
+ onBashSubmit,
81379
+ onSubmit
81380
+ ]);
81381
+ const handleFileSelect = import_react68.useCallback((selectedPath) => {
81142
81382
  const atIndex = value.lastIndexOf("@");
81143
81383
  if (atIndex === -1)
81144
81384
  return;
@@ -81157,21 +81397,25 @@ function Input({
81157
81397
  }
81158
81398
  setValue(newValue);
81159
81399
  setCursorPos(newCursorPos);
81160
- };
81161
- const handleCommandSelect = async (selectedCommand) => {
81400
+ }, [value]);
81401
+ const handleCommandSelect = import_react68.useCallback(async (selectedCommand) => {
81162
81402
  const commandToSubmit = selectedCommand.trim();
81163
- if (commandToSubmit && commandToSubmit !== history[history.length - 1]) {
81164
- setHistory([...history, commandToSubmit]);
81403
+ if (commandToSubmit) {
81404
+ setHistory((prev) => {
81405
+ if (commandToSubmit === prev[prev.length - 1])
81406
+ return prev;
81407
+ return [...prev, commandToSubmit];
81408
+ });
81165
81409
  }
81166
81410
  setHistoryIndex(-1);
81167
81411
  setTemporaryInput("");
81168
81412
  setValue("");
81169
81413
  await onSubmit(commandToSubmit);
81170
- };
81171
- const handleCommandAutocomplete = (selectedCommand) => {
81414
+ }, [onSubmit]);
81415
+ const handleCommandAutocomplete = import_react68.useCallback((selectedCommand) => {
81172
81416
  setValue(selectedCommand);
81173
81417
  setCursorPos(selectedCommand.length);
81174
- };
81418
+ }, []);
81175
81419
  const modeInfo = import_react68.useMemo(() => {
81176
81420
  if (ralphPending) {
81177
81421
  if (ralphPendingYolo) {
@@ -81213,164 +81457,145 @@ function Input({
81213
81457
  return null;
81214
81458
  }
81215
81459
  }, [ralphPending, ralphPendingYolo, ralphActive, currentMode]);
81216
- const estimatedTokens = charsToTokens(tokenCount);
81217
- const totalElapsedMs = elapsedBaseMs + elapsedMs;
81218
- const shouldShowTokenCount = streaming && estimatedTokens > TOKEN_DISPLAY_THRESHOLD;
81219
- const shouldShowElapsed = streaming && totalElapsedMs > ELAPSED_DISPLAY_THRESHOLD_MS;
81220
- const elapsedLabel = formatElapsedLabel(totalElapsedMs);
81221
- const networkArrow = import_react68.useMemo(() => {
81222
- if (!networkPhase)
81223
- return "";
81224
- if (networkPhase === "upload")
81225
- return "↑";
81226
- if (networkPhase === "download")
81227
- return "↑";
81228
- return "↑̸";
81229
- }, [networkPhase]);
81230
- const showErrorArrow = networkArrow === "↑̸";
81231
- const statusHintText = import_react68.useMemo(() => {
81232
- const hintColor = source_default.hex(colors.subagent.hint);
81233
- const hintBold = hintColor.bold;
81234
- const parts = [];
81235
- if (shouldShowElapsed) {
81236
- parts.push(elapsedLabel);
81237
- }
81238
- if (shouldShowTokenCount) {
81239
- parts.push(`${formatCompact(estimatedTokens)}${networkArrow ? ` ${networkArrow}` : ""}`);
81240
- } else if (showErrorArrow) {
81241
- parts.push(networkArrow);
81242
- }
81243
- const suffix = `${parts.length > 0 ? ` · ${parts.join(" · ")}` : ""})`;
81244
- if (interruptRequested) {
81245
- return hintColor(` (interrupting${suffix}`);
81246
- }
81247
- return hintColor(" (") + hintBold("esc") + hintColor(` to interrupt${suffix}`);
81460
+ const horizontalLine = import_react68.useMemo(() => "─".repeat(columns), [columns]);
81461
+ const lowerPane = import_react68.useMemo(() => {
81462
+ return /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(jsx_dev_runtime45.Fragment, {
81463
+ children: [
81464
+ messageQueue && messageQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(QueuedMessages, {
81465
+ messages: messageQueue
81466
+ }, undefined, false, undefined, this),
81467
+ interactionEnabled ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81468
+ flexDirection: "column",
81469
+ children: [
81470
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81471
+ dimColor: !isBashMode,
81472
+ color: isBashMode ? colors.bash.border : undefined,
81473
+ children: horizontalLine
81474
+ }, undefined, false, undefined, this),
81475
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81476
+ flexDirection: "row",
81477
+ children: [
81478
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81479
+ width: 2,
81480
+ flexShrink: 0,
81481
+ children: [
81482
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81483
+ color: isBashMode ? colors.bash.prompt : colors.input.prompt,
81484
+ children: isBashMode ? "!" : ">"
81485
+ }, undefined, false, undefined, this),
81486
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81487
+ children: " "
81488
+ }, undefined, false, undefined, this)
81489
+ ]
81490
+ }, undefined, true, undefined, this),
81491
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81492
+ flexGrow: 1,
81493
+ width: contentWidth,
81494
+ children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(PasteAwareTextInput, {
81495
+ value,
81496
+ onChange: setValue,
81497
+ onSubmit: handleSubmit,
81498
+ cursorPosition: cursorPos,
81499
+ onCursorMove: setCurrentCursorPosition,
81500
+ focus: interactionEnabled && !onEscapeCancel,
81501
+ onBangAtEmpty: handleBangAtEmpty,
81502
+ onBackspaceAtEmpty: handleBackspaceAtEmpty,
81503
+ onPasteError
81504
+ }, undefined, false, undefined, this)
81505
+ }, undefined, false, undefined, this)
81506
+ ]
81507
+ }, undefined, true, undefined, this),
81508
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81509
+ dimColor: !isBashMode,
81510
+ color: isBashMode ? colors.bash.border : undefined,
81511
+ children: horizontalLine
81512
+ }, undefined, false, undefined, this),
81513
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(InputAssist, {
81514
+ currentInput: value,
81515
+ cursorPosition: currentCursorPosition,
81516
+ onFileSelect: handleFileSelect,
81517
+ onCommandSelect: handleCommandSelect,
81518
+ onCommandAutocomplete: handleCommandAutocomplete,
81519
+ onAutocompleteActiveChange: setIsAutocompleteActive,
81520
+ agentId,
81521
+ agentName,
81522
+ serverUrl,
81523
+ workingDirectory: process.cwd(),
81524
+ conversationId
81525
+ }, undefined, false, undefined, this),
81526
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(InputFooter, {
81527
+ ctrlCPressed,
81528
+ escapePressed,
81529
+ isBashMode,
81530
+ modeName: modeInfo?.name ?? null,
81531
+ modeColor: modeInfo?.color ?? null,
81532
+ showExitHint: ralphActive || ralphPending,
81533
+ agentName,
81534
+ currentModel,
81535
+ isOpenAICodexProvider: currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
81536
+ isByokProvider: currentModelProvider?.startsWith("lc-") || currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
81537
+ hideFooter,
81538
+ rightColumnWidth: footerRightColumnWidth
81539
+ }, undefined, false, undefined, this)
81540
+ ]
81541
+ }, undefined, true, undefined, this) : reserveInputSpace ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81542
+ height: inputChromeHeight
81543
+ }, undefined, false, undefined, this) : null
81544
+ ]
81545
+ }, undefined, true, undefined, this);
81248
81546
  }, [
81249
- shouldShowElapsed,
81250
- elapsedLabel,
81251
- shouldShowTokenCount,
81252
- estimatedTokens,
81253
- interruptRequested,
81254
- networkArrow,
81255
- showErrorArrow
81547
+ messageQueue,
81548
+ interactionEnabled,
81549
+ isBashMode,
81550
+ horizontalLine,
81551
+ contentWidth,
81552
+ value,
81553
+ handleSubmit,
81554
+ cursorPos,
81555
+ onEscapeCancel,
81556
+ handleBangAtEmpty,
81557
+ handleBackspaceAtEmpty,
81558
+ onPasteError,
81559
+ currentCursorPosition,
81560
+ handleFileSelect,
81561
+ handleCommandSelect,
81562
+ handleCommandAutocomplete,
81563
+ agentId,
81564
+ agentName,
81565
+ serverUrl,
81566
+ conversationId,
81567
+ ctrlCPressed,
81568
+ escapePressed,
81569
+ modeInfo?.name,
81570
+ modeInfo?.color,
81571
+ ralphActive,
81572
+ ralphPending,
81573
+ currentModel,
81574
+ currentModelProvider,
81575
+ hideFooter,
81576
+ footerRightColumnWidth,
81577
+ reserveInputSpace,
81578
+ inputChromeHeight
81256
81579
  ]);
81257
- const horizontalLine = import_react68.useMemo(() => "─".repeat(columns), [columns]);
81258
81580
  if (!visible) {
81259
81581
  return null;
81260
81582
  }
81261
81583
  return /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81262
81584
  flexDirection: "column",
81263
81585
  children: [
81264
- streaming && /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81265
- flexDirection: "row",
81266
- marginBottom: 1,
81267
- children: [
81268
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81269
- width: 2,
81270
- flexShrink: 0,
81271
- children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81272
- color: colors.status.processing,
81273
- children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Spinner2, {
81274
- type: "layer"
81275
- }, undefined, false, undefined, this)
81276
- }, undefined, false, undefined, this)
81277
- }, undefined, false, undefined, this),
81278
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81279
- flexGrow: 1,
81280
- flexDirection: "row",
81281
- children: [
81282
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(ShimmerText, {
81283
- boldPrefix: agentName || undefined,
81284
- message: thinkingMessage,
81285
- shimmerOffset
81286
- }, undefined, false, undefined, this),
81287
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81288
- children: statusHintText
81289
- }, undefined, false, undefined, this)
81290
- ]
81291
- }, undefined, true, undefined, this)
81292
- ]
81293
- }, undefined, true, undefined, this),
81294
- messageQueue && messageQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(QueuedMessages, {
81295
- messages: messageQueue
81586
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(StreamingStatus, {
81587
+ streaming,
81588
+ visible,
81589
+ tokenCount,
81590
+ elapsedBaseMs,
81591
+ thinkingMessage,
81592
+ agentName,
81593
+ interruptRequested,
81594
+ networkPhase,
81595
+ terminalWidth: columns,
81596
+ shouldAnimate
81296
81597
  }, undefined, false, undefined, this),
81297
- interactionEnabled ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81298
- flexDirection: "column",
81299
- children: [
81300
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81301
- dimColor: !isBashMode,
81302
- color: isBashMode ? colors.bash.border : undefined,
81303
- children: horizontalLine
81304
- }, undefined, false, undefined, this),
81305
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81306
- flexDirection: "row",
81307
- children: [
81308
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81309
- width: 2,
81310
- flexShrink: 0,
81311
- children: [
81312
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81313
- color: isBashMode ? colors.bash.prompt : colors.input.prompt,
81314
- children: isBashMode ? "!" : ">"
81315
- }, undefined, false, undefined, this),
81316
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81317
- children: " "
81318
- }, undefined, false, undefined, this)
81319
- ]
81320
- }, undefined, true, undefined, this),
81321
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81322
- flexGrow: 1,
81323
- width: contentWidth,
81324
- children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(PasteAwareTextInput, {
81325
- value,
81326
- onChange: setValue,
81327
- onSubmit: handleSubmit,
81328
- cursorPosition: cursorPos,
81329
- onCursorMove: setCurrentCursorPosition,
81330
- focus: interactionEnabled && !onEscapeCancel,
81331
- onBangAtEmpty: handleBangAtEmpty,
81332
- onBackspaceAtEmpty: handleBackspaceAtEmpty,
81333
- onPasteError
81334
- }, undefined, false, undefined, this)
81335
- }, undefined, false, undefined, this)
81336
- ]
81337
- }, undefined, true, undefined, this),
81338
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81339
- dimColor: !isBashMode,
81340
- color: isBashMode ? colors.bash.border : undefined,
81341
- children: horizontalLine
81342
- }, undefined, false, undefined, this),
81343
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(InputAssist, {
81344
- currentInput: value,
81345
- cursorPosition: currentCursorPosition,
81346
- onFileSelect: handleFileSelect,
81347
- onCommandSelect: handleCommandSelect,
81348
- onCommandAutocomplete: handleCommandAutocomplete,
81349
- onAutocompleteActiveChange: setIsAutocompleteActive,
81350
- agentId,
81351
- agentName,
81352
- serverUrl,
81353
- workingDirectory: process.cwd(),
81354
- conversationId
81355
- }, undefined, false, undefined, this),
81356
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(InputFooter, {
81357
- ctrlCPressed,
81358
- escapePressed,
81359
- isBashMode,
81360
- modeName: modeInfo?.name ?? null,
81361
- modeColor: modeInfo?.color ?? null,
81362
- showExitHint: ralphActive || ralphPending,
81363
- agentName,
81364
- currentModel,
81365
- isOpenAICodexProvider: currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
81366
- isByokProvider: currentModelProvider?.startsWith("lc-") || currentModelProvider === OPENAI_CODEX_PROVIDER_NAME,
81367
- isAutocompleteActive,
81368
- hideFooter
81369
- }, undefined, false, undefined, this)
81370
- ]
81371
- }, undefined, true, undefined, this) : reserveInputSpace ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81372
- height: inputChromeHeight
81373
- }, undefined, false, undefined, this) : null
81598
+ lowerPane
81374
81599
  ]
81375
81600
  }, undefined, true, undefined, this);
81376
81601
  }
@@ -81393,14 +81618,13 @@ function formatElapsedLabel(ms) {
81393
81618
  }
81394
81619
  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
81395
81620
  }
81396
- var import_react68, jsx_dev_runtime45, Spinner2, ESC_CLEAR_WINDOW_MS = 2500, InputFooter;
81621
+ var import_react68, jsx_dev_runtime45, Spinner2, ESC_CLEAR_WINDOW_MS = 2500, FOOTER_WIDTH_STREAMING_DELTA = 2, InputFooter, StreamingStatus;
81397
81622
  var init_InputRich = __esm(async () => {
81398
81623
  init_source();
81399
81624
  init_oauth();
81400
81625
  init_constants();
81401
81626
  init_mode();
81402
81627
  init_mode2();
81403
- init_useTerminalWidth();
81404
81628
  init_colors();
81405
81629
  await __promiseAll([
81406
81630
  init_build2(),
@@ -81427,78 +81651,249 @@ var init_InputRich = __esm(async () => {
81427
81651
  currentModel,
81428
81652
  isOpenAICodexProvider,
81429
81653
  isByokProvider,
81430
- isAutocompleteActive,
81431
- hideFooter
81654
+ hideFooter,
81655
+ rightColumnWidth
81656
+ }) {
81657
+ const hideFooterContent = hideFooter;
81658
+ const maxAgentChars = Math.max(10, Math.floor(rightColumnWidth * 0.45));
81659
+ const displayAgentName = truncateEnd(agentName || "Unnamed", maxAgentChars);
81660
+ const byokExtraChars = isByokProvider ? 2 : 0;
81661
+ const reservedChars = displayAgentName.length + byokExtraChars + 4;
81662
+ const maxModelChars = Math.max(8, rightColumnWidth - reservedChars);
81663
+ const displayModel = truncateEnd(currentModel ?? "unknown", maxModelChars);
81664
+ const rightTextLength = displayAgentName.length + displayModel.length + byokExtraChars + 3;
81665
+ const rightPrefixSpaces = Math.max(0, rightColumnWidth - rightTextLength);
81666
+ const rightLabel = import_react68.useMemo(() => {
81667
+ const parts = [];
81668
+ parts.push(" ".repeat(rightPrefixSpaces));
81669
+ parts.push(source_default.hex(colors.footer.agentName)(displayAgentName));
81670
+ parts.push(source_default.dim(" ["));
81671
+ parts.push(source_default.dim(displayModel));
81672
+ if (isByokProvider) {
81673
+ parts.push(source_default.dim(" "));
81674
+ parts.push(isOpenAICodexProvider ? source_default.hex("#74AA9C")("▲") : source_default.yellow("▲"));
81675
+ }
81676
+ parts.push(source_default.dim("]"));
81677
+ return parts.join("");
81678
+ }, [
81679
+ rightPrefixSpaces,
81680
+ displayAgentName,
81681
+ displayModel,
81682
+ isByokProvider,
81683
+ isOpenAICodexProvider
81684
+ ]);
81685
+ return /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81686
+ flexDirection: "row",
81687
+ marginBottom: 1,
81688
+ children: [
81689
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81690
+ flexGrow: 1,
81691
+ paddingRight: 1,
81692
+ children: hideFooterContent ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81693
+ children: " "
81694
+ }, undefined, false, undefined, this) : ctrlCPressed ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81695
+ dimColor: true,
81696
+ children: "Press CTRL-C again to exit"
81697
+ }, undefined, false, undefined, this) : escapePressed ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81698
+ dimColor: true,
81699
+ children: "Press Esc again to clear"
81700
+ }, undefined, false, undefined, this) : isBashMode ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81701
+ children: [
81702
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81703
+ color: colors.bash.prompt,
81704
+ children: "⏵⏵ bash mode"
81705
+ }, undefined, false, undefined, this),
81706
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81707
+ color: colors.bash.prompt,
81708
+ dimColor: true,
81709
+ children: [
81710
+ " ",
81711
+ "(backspace to exit)"
81712
+ ]
81713
+ }, undefined, true, undefined, this)
81714
+ ]
81715
+ }, undefined, true, undefined, this) : modeName && modeColor ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81716
+ children: [
81717
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81718
+ color: modeColor,
81719
+ children: [
81720
+ "⏵⏵ ",
81721
+ modeName
81722
+ ]
81723
+ }, undefined, true, undefined, this),
81724
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81725
+ color: modeColor,
81726
+ dimColor: true,
81727
+ children: [
81728
+ " ",
81729
+ "(shift+tab to ",
81730
+ showExitHint ? "exit" : "cycle",
81731
+ ")"
81732
+ ]
81733
+ }, undefined, true, undefined, this)
81734
+ ]
81735
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81736
+ dimColor: true,
81737
+ children: "Press / for commands"
81738
+ }, undefined, false, undefined, this)
81739
+ }, undefined, false, undefined, this),
81740
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81741
+ width: rightColumnWidth,
81742
+ flexShrink: 0,
81743
+ children: hideFooterContent ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81744
+ children: " ".repeat(rightColumnWidth)
81745
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81746
+ children: rightLabel
81747
+ }, undefined, false, undefined, this)
81748
+ }, undefined, false, undefined, this)
81749
+ ]
81750
+ }, undefined, true, undefined, this);
81751
+ });
81752
+ StreamingStatus = import_react68.memo(function StreamingStatus2({
81753
+ streaming,
81754
+ visible,
81755
+ tokenCount,
81756
+ elapsedBaseMs,
81757
+ thinkingMessage,
81758
+ agentName,
81759
+ interruptRequested,
81760
+ networkPhase,
81761
+ terminalWidth,
81762
+ shouldAnimate
81432
81763
  }) {
81433
- if (hideFooter || isAutocompleteActive) {
81764
+ const [shimmerOffset, setShimmerOffset] = import_react68.useState(-3);
81765
+ const [elapsedMs, setElapsedMs] = import_react68.useState(0);
81766
+ const streamStartRef = import_react68.useRef(null);
81767
+ import_react68.useEffect(() => {
81768
+ if (!streaming || !visible || !shouldAnimate)
81769
+ return;
81770
+ const id = setInterval(() => {
81771
+ setShimmerOffset((prev) => {
81772
+ const prefixLen = agentName ? agentName.length + 1 : 0;
81773
+ const len = prefixLen + thinkingMessage.length;
81774
+ const next = prev + 1;
81775
+ return next > len + 3 ? -3 : next;
81776
+ });
81777
+ }, 120);
81778
+ return () => clearInterval(id);
81779
+ }, [streaming, thinkingMessage, visible, agentName, shouldAnimate]);
81780
+ import_react68.useEffect(() => {
81781
+ if (!shouldAnimate) {
81782
+ setShimmerOffset(-3);
81783
+ }
81784
+ }, [shouldAnimate]);
81785
+ import_react68.useEffect(() => {
81786
+ if (streaming && visible) {
81787
+ if (streamStartRef.current === null) {
81788
+ streamStartRef.current = performance.now();
81789
+ }
81790
+ const id = setInterval(() => {
81791
+ if (streamStartRef.current !== null) {
81792
+ setElapsedMs(performance.now() - streamStartRef.current);
81793
+ }
81794
+ }, 1000);
81795
+ return () => clearInterval(id);
81796
+ }
81797
+ streamStartRef.current = null;
81798
+ setElapsedMs(0);
81799
+ }, [streaming, visible]);
81800
+ const estimatedTokens = charsToTokens(tokenCount);
81801
+ const totalElapsedMs = elapsedBaseMs + elapsedMs;
81802
+ const shouldShowTokenCount = streaming && estimatedTokens > TOKEN_DISPLAY_THRESHOLD;
81803
+ const shouldShowElapsed = streaming && totalElapsedMs > ELAPSED_DISPLAY_THRESHOLD_MS;
81804
+ const elapsedLabel = formatElapsedLabel(totalElapsedMs);
81805
+ const networkArrow = import_react68.useMemo(() => {
81806
+ if (!networkPhase)
81807
+ return "";
81808
+ if (networkPhase === "upload")
81809
+ return "↑";
81810
+ if (networkPhase === "download")
81811
+ return "↑";
81812
+ return "↑̸";
81813
+ }, [networkPhase]);
81814
+ const showErrorArrow = networkArrow === "↑̸";
81815
+ const statusContentWidth = Math.max(0, terminalWidth - 2);
81816
+ const minMessageWidth = 12;
81817
+ const statusHintParts = import_react68.useMemo(() => {
81818
+ const parts = [];
81819
+ if (shouldShowElapsed) {
81820
+ parts.push(elapsedLabel);
81821
+ }
81822
+ if (shouldShowTokenCount) {
81823
+ parts.push(`${formatCompact(estimatedTokens)}${networkArrow ? ` ${networkArrow}` : ""}`);
81824
+ } else if (showErrorArrow) {
81825
+ parts.push(networkArrow);
81826
+ }
81827
+ return parts;
81828
+ }, [
81829
+ shouldShowElapsed,
81830
+ elapsedLabel,
81831
+ shouldShowTokenCount,
81832
+ estimatedTokens,
81833
+ networkArrow,
81834
+ showErrorArrow
81835
+ ]);
81836
+ const statusHintSuffix = statusHintParts.length ? ` · ${statusHintParts.join(" · ")}` : "";
81837
+ const statusHintPlain = interruptRequested ? ` (interrupting${statusHintSuffix})` : ` (esc to interrupt${statusHintSuffix})`;
81838
+ const statusHintWidth = Array.from(statusHintPlain).length;
81839
+ const maxHintWidth = Math.max(0, statusContentWidth - minMessageWidth);
81840
+ const hintColumnWidth = Math.max(0, Math.min(statusHintWidth, maxHintWidth));
81841
+ const maxMessageWidth = Math.max(0, statusContentWidth - hintColumnWidth);
81842
+ const statusLabel = `${agentName ? `${agentName} ` : ""}${thinkingMessage}…`;
81843
+ const statusLabelWidth = Array.from(statusLabel).length;
81844
+ const messageColumnWidth = Math.max(0, Math.min(maxMessageWidth, Math.max(minMessageWidth, statusLabelWidth)));
81845
+ const statusHintText = import_react68.useMemo(() => {
81846
+ const hintColor = source_default.hex(colors.subagent.hint);
81847
+ const hintBold = hintColor.bold;
81848
+ const suffix = `${statusHintSuffix})`;
81849
+ if (interruptRequested) {
81850
+ return hintColor(` (interrupting${suffix}`);
81851
+ }
81852
+ return hintColor(" (") + hintBold("esc") + hintColor(` to interrupt${suffix}`);
81853
+ }, [interruptRequested, statusHintSuffix]);
81854
+ if (!streaming || !visible) {
81434
81855
  return null;
81435
81856
  }
81436
81857
  return /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81437
- justifyContent: "space-between",
81858
+ flexDirection: "row",
81438
81859
  marginBottom: 1,
81439
81860
  children: [
81440
- ctrlCPressed ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81441
- dimColor: true,
81442
- children: "Press CTRL-C again to exit"
81443
- }, undefined, false, undefined, this) : escapePressed ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81444
- dimColor: true,
81445
- children: "Press Esc again to clear"
81446
- }, undefined, false, undefined, this) : isBashMode ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81447
- children: [
81448
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81449
- color: colors.bash.prompt,
81450
- children: "⏵⏵ bash mode"
81451
- }, undefined, false, undefined, this),
81452
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81453
- color: colors.bash.prompt,
81454
- dimColor: true,
81455
- children: [
81456
- " ",
81457
- "(backspace to exit)"
81458
- ]
81459
- }, undefined, true, undefined, this)
81460
- ]
81461
- }, undefined, true, undefined, this) : modeName && modeColor ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81462
- children: [
81463
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81464
- color: modeColor,
81465
- children: [
81466
- "⏵⏵ ",
81467
- modeName
81468
- ]
81469
- }, undefined, true, undefined, this),
81470
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81471
- color: modeColor,
81472
- dimColor: true,
81473
- children: [
81474
- " ",
81475
- "(shift+tab to ",
81476
- showExitHint ? "exit" : "cycle",
81477
- ")"
81478
- ]
81479
- }, undefined, true, undefined, this)
81480
- ]
81481
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81482
- dimColor: true,
81483
- children: "Press / for commands"
81861
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81862
+ width: 2,
81863
+ flexShrink: 0,
81864
+ children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81865
+ color: colors.status.processing,
81866
+ children: shouldAnimate ? /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Spinner2, {
81867
+ type: "layer"
81868
+ }, undefined, false, undefined, this) : "●"
81869
+ }, undefined, false, undefined, this)
81484
81870
  }, undefined, false, undefined, this),
81485
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81871
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81872
+ width: statusContentWidth,
81873
+ flexShrink: 0,
81874
+ flexDirection: "row",
81486
81875
  children: [
81487
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81488
- color: colors.footer.agentName,
81489
- children: agentName || "Unnamed"
81876
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81877
+ width: messageColumnWidth,
81878
+ flexShrink: 0,
81879
+ children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(ShimmerText, {
81880
+ boldPrefix: agentName || undefined,
81881
+ message: thinkingMessage,
81882
+ shimmerOffset: shouldAnimate ? shimmerOffset : -3,
81883
+ wrap: "truncate-end"
81884
+ }, undefined, false, undefined, this)
81490
81885
  }, undefined, false, undefined, this),
81491
- /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81492
- dimColor: true,
81493
- children: [
81494
- ` [${currentModel ?? "unknown"}`,
81495
- isByokProvider && /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81496
- color: isOpenAICodexProvider ? "#74AA9C" : "yellow",
81497
- children: " ▲"
81498
- }, undefined, false, undefined, this),
81499
- "]"
81500
- ]
81501
- }, undefined, true, undefined, this)
81886
+ hintColumnWidth > 0 && /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81887
+ width: hintColumnWidth,
81888
+ flexShrink: 0,
81889
+ children: /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
81890
+ wrap: "truncate-end",
81891
+ children: statusHintText
81892
+ }, undefined, false, undefined, this)
81893
+ }, undefined, false, undefined, this),
81894
+ /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
81895
+ flexGrow: 1
81896
+ }, undefined, false, undefined, this)
81502
81897
  ]
81503
81898
  }, undefined, true, undefined, this)
81504
81899
  ]
@@ -84616,22 +85011,22 @@ function ModelSelector({
84616
85011
  };
84617
85012
  const getCategoryDescription = (cat) => {
84618
85013
  if (cat === "server-recommended") {
84619
- return "Recommended models on the server";
85014
+ return "Recommended models currently available for this account";
84620
85015
  }
84621
85016
  if (cat === "server-all") {
84622
- return "All models on the server";
85017
+ return "All models currently available for this account";
84623
85018
  }
84624
85019
  if (cat === "supported") {
84625
- return isFreeTier ? "Upgrade your account to access more models" : "Recommended models on the Letta API";
85020
+ return isFreeTier ? "Upgrade your account to access more models" : "Recommended Letta API models currently available for this account";
84626
85021
  }
84627
85022
  if (cat === "byok")
84628
- return "Recommended models via your API keys (use /connect to add more)";
85023
+ return "Recommended models via your connected API keys (use /connect to add more)";
84629
85024
  if (cat === "byok-all")
84630
- return "All models via your API keys (use /connect to add more)";
85025
+ return "All models via your connected API keys (use /connect to add more)";
84631
85026
  if (cat === "all") {
84632
- return isFreeTier ? "Upgrade your account to access more models" : "All models on the Letta API";
85027
+ return isFreeTier ? "Upgrade your account to access more models" : "All Letta API models currently available for this account";
84633
85028
  }
84634
- return "All models on the Letta API";
85029
+ return "All Letta API models currently available for this account";
84635
85030
  };
84636
85031
  const renderTabBar = () => /* @__PURE__ */ jsx_dev_runtime51.jsxDEV(Box_default, {
84637
85032
  flexDirection: "row",
@@ -84791,7 +85186,7 @@ function ModelSelector({
84791
85186
  currentList.length,
84792
85187
  " models",
84793
85188
  isCached ? " · cached" : "",
84794
- " · R to refresh"
85189
+ " · R to refresh availability"
84795
85190
  ]
84796
85191
  }, undefined, true, undefined, this),
84797
85192
  /* @__PURE__ */ jsx_dev_runtime51.jsxDEV(Text2, {
@@ -85407,11 +85802,11 @@ var init_byok_providers = __esm(async () => {
85407
85802
 
85408
85803
  // src/utils/aws-credentials.ts
85409
85804
  import { readFile as readFile12 } from "node:fs/promises";
85410
- import { homedir as homedir14 } from "node:os";
85805
+ import { homedir as homedir15 } from "node:os";
85411
85806
  import { join as join26 } from "node:path";
85412
85807
  async function parseAwsCredentials() {
85413
- const credentialsPath = join26(homedir14(), ".aws", "credentials");
85414
- const configPath = join26(homedir14(), ".aws", "config");
85808
+ const credentialsPath = join26(homedir15(), ".aws", "credentials");
85809
+ const configPath = join26(homedir15(), ".aws", "config");
85415
85810
  const profiles = new Map;
85416
85811
  try {
85417
85812
  const content = await readFile12(credentialsPath, "utf-8");
@@ -89129,7 +89524,8 @@ var init_ToolCallMessageRich = __esm(async () => {
89129
89524
  streaming: line.streaming
89130
89525
  }, undefined, false, undefined, this),
89131
89526
  isShellTool2(rawName) && line.phase === "finished" && line.resultText && line.resultOk !== false && /* @__PURE__ */ jsx_dev_runtime65.jsxDEV(CollapsedOutputDisplay, {
89132
- output: line.resultText
89527
+ output: line.resultText,
89528
+ maxChars: 300
89133
89529
  }, undefined, false, undefined, this),
89134
89530
  (() => {
89135
89531
  const showDefaultResult = !isShellTool2(rawName) || line.phase === "finished" && line.resultOk === false || line.phase !== "running" && line.phase !== "finished";
@@ -90390,7 +90786,7 @@ __export(exports_shellAliases, {
90390
90786
  clearAliasCache: () => clearAliasCache
90391
90787
  });
90392
90788
  import { existsSync as existsSync16, readFileSync as readFileSync8 } from "node:fs";
90393
- import { homedir as homedir15 } from "node:os";
90789
+ import { homedir as homedir16 } from "node:os";
90394
90790
  import { join as join27 } from "node:path";
90395
90791
  function parseAliasesFromFile(filePath) {
90396
90792
  const aliases = new Map;
@@ -90460,7 +90856,7 @@ function loadAliases(forceReload = false) {
90460
90856
  if (aliasCache && !forceReload) {
90461
90857
  return aliasCache;
90462
90858
  }
90463
- const home = homedir15();
90859
+ const home = homedir16();
90464
90860
  const allAliases = new Map;
90465
90861
  for (const file of ALIAS_FILES) {
90466
90862
  const filePath = join27(home, file);
@@ -91081,21 +91477,6 @@ Use /disconnect codex to remove the current connection first.`, false);
91081
91477
  ctx.setCommandRunning(true);
91082
91478
  const cmdId = addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, "Checking account eligibility...", true, "running");
91083
91479
  try {
91084
- const eligibility = await checkOpenAICodexEligibility();
91085
- if (!eligibility.eligible) {
91086
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ ChatGPT OAuth requires a Pro or Enterprise plan
91087
-
91088
- ` + `This feature is only available for Letta Pro or Enterprise customers.
91089
- ` + `Current plan: ${eligibility.billing_tier}
91090
-
91091
- ` + `To upgrade your plan, visit:
91092
-
91093
- ` + ` https://app.letta.com/settings/organization/usage
91094
-
91095
- ` + `If you have an OpenAI API key, you can use it directly by setting:
91096
- ` + ` export OPENAI_API_KEY=your-key`, false, "finished");
91097
- return;
91098
- }
91099
91480
  updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Starting OAuth flow...
91100
91481
  A browser window will open for authorization.`, true, "running");
91101
91482
  const { authorizationUrl, state, codeVerifier, redirectUri } = await startOpenAIOAuth(OPENAI_OAUTH_CONFIG.defaultPort);
@@ -91148,21 +91529,8 @@ Your ChatGPT Plus/Pro subscription is now linked.`, true, "finished");
91148
91529
  }
91149
91530
  } catch (error) {
91150
91531
  settingsManager.clearOAuthState();
91151
- const errorMessage = getErrorMessage(error);
91152
- let displayMessage;
91153
- if (errorMessage === "PLAN_UPGRADE_REQUIRED") {
91154
- displayMessage = `✗ ChatGPT OAuth requires a Pro or Enterprise plan
91155
-
91156
- ` + `This feature is only available for Letta Pro or Enterprise customers.
91157
- To upgrade your plan, visit:
91158
-
91159
- https://app.letta.com/settings/organization/usage
91160
-
91161
- If you have an OpenAI API key, you can use it directly by setting:
91162
- export OPENAI_API_KEY=your-key`;
91163
- } else {
91164
- displayMessage = `✗ Failed to connect: ${errorMessage}`;
91165
- }
91532
+ const errorMessage = getErrorMessage2(error);
91533
+ const displayMessage = `✗ Failed to connect: ${errorMessage}`;
91166
91534
  updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, displayMessage, false, "finished");
91167
91535
  } finally {
91168
91536
  ctx.setCommandRunning(false);
@@ -91184,7 +91552,7 @@ Use /connect minimax <api_key> to connect.`, false);
91184
91552
 
91185
91553
  ` + `Provider '${MINIMAX_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91186
91554
  } catch (error) {
91187
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from MiniMax: ${getErrorMessage(error)}`, false, "finished");
91555
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from MiniMax: ${getErrorMessage2(error)}`, false, "finished");
91188
91556
  } finally {
91189
91557
  ctx.setCommandRunning(false);
91190
91558
  }
@@ -91205,7 +91573,7 @@ Use /connect and select "AWS Bedrock" to connect.`, false);
91205
91573
 
91206
91574
  ` + `Provider '${BEDROCK_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91207
91575
  } catch (error) {
91208
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Bedrock: ${getErrorMessage(error)}`, false, "finished");
91576
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Bedrock: ${getErrorMessage2(error)}`, false, "finished");
91209
91577
  } finally {
91210
91578
  ctx.setCommandRunning(false);
91211
91579
  }
@@ -91231,7 +91599,7 @@ Example: /connect minimax <api_key>...`, false);
91231
91599
 
91232
91600
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91233
91601
  } catch (error) {
91234
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create MiniMax provider: ${getErrorMessage(error)}`, false, "finished");
91602
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create MiniMax provider: ${getErrorMessage2(error)}`, false, "finished");
91235
91603
  } finally {
91236
91604
  ctx.setCommandRunning(false);
91237
91605
  }
@@ -91298,7 +91666,7 @@ Use /connect codex to authenticate.`, false);
91298
91666
 
91299
91667
  ` + `Provider '${OPENAI_CODEX_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91300
91668
  } catch (error) {
91301
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from ChatGPT: ${getErrorMessage(error)}`, false, "finished");
91669
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from ChatGPT: ${getErrorMessage2(error)}`, false, "finished");
91302
91670
  } finally {
91303
91671
  ctx.setCommandRunning(false);
91304
91672
  }
@@ -91326,7 +91694,7 @@ The '${CLAUDE_PROVIDER_NAME}' provider does not exist in your Letta account.`, f
91326
91694
 
91327
91695
  Note: /connect claude has been replaced with /connect codex for OpenAI ChatGPT Plus/Pro.`, true, "finished");
91328
91696
  } catch (error) {
91329
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Claude: ${getErrorMessage(error)}`, false, "finished");
91697
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Claude: ${getErrorMessage2(error)}`, false, "finished");
91330
91698
  } finally {
91331
91699
  ctx.setCommandRunning(false);
91332
91700
  }
@@ -91347,7 +91715,7 @@ Use /connect zai <api_key> to connect.`, false);
91347
91715
 
91348
91716
  ` + `Provider '${ZAI_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91349
91717
  } catch (error) {
91350
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage(error)}`, false, "finished");
91718
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage2(error)}`, false, "finished");
91351
91719
  } finally {
91352
91720
  ctx.setCommandRunning(false);
91353
91721
  }
@@ -91373,7 +91741,7 @@ Example: /connect zai <api_key>...`, false);
91373
91741
 
91374
91742
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91375
91743
  } catch (error) {
91376
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage(error)}`, false, "finished");
91744
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage2(error)}`, false, "finished");
91377
91745
  } finally {
91378
91746
  ctx.setCommandRunning(false);
91379
91747
  }
@@ -91401,7 +91769,7 @@ Example: /connect openrouter sk-or-v1-...`, false);
91401
91769
 
91402
91770
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91403
91771
  } catch (error) {
91404
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create OpenRouter provider: ${getErrorMessage(error)}`, false, "finished");
91772
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create OpenRouter provider: ${getErrorMessage2(error)}`, false, "finished");
91405
91773
  } finally {
91406
91774
  ctx.setCommandRunning(false);
91407
91775
  }
@@ -91422,7 +91790,7 @@ Use /connect openrouter <api_key> to connect.`, false);
91422
91790
 
91423
91791
  ` + `Provider '${OPENROUTER_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91424
91792
  } catch (error) {
91425
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from OpenRouter: ${getErrorMessage(error)}`, false, "finished");
91793
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from OpenRouter: ${getErrorMessage2(error)}`, false, "finished");
91426
91794
  } finally {
91427
91795
  ctx.setCommandRunning(false);
91428
91796
  }
@@ -91471,7 +91839,7 @@ async function packageSkills(agentId, skillsDir) {
91471
91839
  console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
91472
91840
  continue;
91473
91841
  }
91474
- const sourceUrl = await findSkillSourceUrl(entry.name);
91842
+ const sourceUrl = skillsDir ? null : await findSkillSourceUrl(entry.name);
91475
91843
  const skill2 = { name: entry.name };
91476
91844
  if (sourceUrl) {
91477
91845
  skill2.source_url = sourceUrl;
@@ -91547,7 +91915,7 @@ __export(exports_App, {
91547
91915
  default: () => App2
91548
91916
  });
91549
91917
  import { existsSync as existsSync17, readFileSync as readFileSync9, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
91550
- import { homedir as homedir16, tmpdir as tmpdir3 } from "node:os";
91918
+ import { homedir as homedir17, tmpdir as tmpdir3 } from "node:os";
91551
91919
  import { join as join28 } from "node:path";
91552
91920
  function getErrorHintForStopReason(stopReason, currentModelId) {
91553
91921
  if (currentModelId === "opus" && stopReason === "llm_api_error" && getModelInfo("bedrock-opus")) {
@@ -92204,18 +92572,93 @@ function App2({
92204
92572
  setCommandRunning(false);
92205
92573
  }
92206
92574
  }, [setCommandRunning]);
92207
- const columns = useTerminalWidth();
92575
+ const rawColumns = useTerminalWidth();
92208
92576
  const terminalRows = useTerminalRows();
92209
- const prevColumnsRef = import_react91.useRef(columns);
92210
- const lastClearedColumnsRef = import_react91.useRef(columns);
92577
+ const [stableColumns, setStableColumns] = import_react91.useState(rawColumns);
92578
+ const stableColumnsTimeoutRef = import_react91.useRef(null);
92579
+ const prevColumnsRef = import_react91.useRef(rawColumns);
92580
+ const lastClearedColumnsRef = import_react91.useRef(rawColumns);
92211
92581
  const pendingResizeRef = import_react91.useRef(false);
92212
92582
  const pendingResizeColumnsRef = import_react91.useRef(null);
92213
92583
  const [staticRenderEpoch, setStaticRenderEpoch] = import_react91.useState(0);
92214
92584
  const resizeClearTimeout = import_react91.useRef(null);
92585
+ const lastClearAtRef = import_react91.useRef(0);
92215
92586
  const isInitialResizeRef = import_react91.useRef(true);
92587
+ const columns = stableColumns;
92588
+ const debugFlicker = process.env.LETTA_DEBUG_FLICKER === "1";
92589
+ import_react91.useEffect(() => {
92590
+ if (rawColumns === stableColumns) {
92591
+ if (stableColumnsTimeoutRef.current) {
92592
+ clearTimeout(stableColumnsTimeoutRef.current);
92593
+ stableColumnsTimeoutRef.current = null;
92594
+ }
92595
+ return;
92596
+ }
92597
+ const delta = Math.abs(rawColumns - stableColumns);
92598
+ if (delta >= MIN_RESIZE_DELTA) {
92599
+ if (stableColumnsTimeoutRef.current) {
92600
+ clearTimeout(stableColumnsTimeoutRef.current);
92601
+ stableColumnsTimeoutRef.current = null;
92602
+ }
92603
+ setStableColumns(rawColumns);
92604
+ return;
92605
+ }
92606
+ if (stableColumnsTimeoutRef.current) {
92607
+ clearTimeout(stableColumnsTimeoutRef.current);
92608
+ }
92609
+ stableColumnsTimeoutRef.current = setTimeout(() => {
92610
+ stableColumnsTimeoutRef.current = null;
92611
+ setStableColumns(rawColumns);
92612
+ }, STABLE_WIDTH_SETTLE_MS);
92613
+ }, [rawColumns, stableColumns]);
92614
+ const clearAndRemount = import_react91.useCallback((targetColumns) => {
92615
+ if (debugFlicker) {
92616
+ console.error(`[debug:flicker:clear-remount] target=${targetColumns} previousCleared=${lastClearedColumnsRef.current} raw=${prevColumnsRef.current}`);
92617
+ }
92618
+ if (typeof process !== "undefined" && process.stdout && "write" in process.stdout && process.stdout.isTTY) {
92619
+ process.stdout.write(CLEAR_SCREEN_AND_HOME);
92620
+ }
92621
+ setStaticRenderEpoch((epoch) => epoch + 1);
92622
+ lastClearedColumnsRef.current = targetColumns;
92623
+ lastClearAtRef.current = Date.now();
92624
+ }, [debugFlicker]);
92625
+ const scheduleResizeClear = import_react91.useCallback((targetColumns) => {
92626
+ if (targetColumns === lastClearedColumnsRef.current) {
92627
+ return;
92628
+ }
92629
+ if (resizeClearTimeout.current) {
92630
+ clearTimeout(resizeClearTimeout.current);
92631
+ resizeClearTimeout.current = null;
92632
+ }
92633
+ const elapsedSinceClear = Date.now() - lastClearAtRef.current;
92634
+ const rateLimitDelay = elapsedSinceClear >= MIN_CLEAR_INTERVAL_MS ? 0 : MIN_CLEAR_INTERVAL_MS - elapsedSinceClear;
92635
+ const delay = Math.max(RESIZE_SETTLE_MS, rateLimitDelay);
92636
+ if (debugFlicker) {
92637
+ console.error(`[debug:flicker:resize-schedule] target=${targetColumns} delay=${delay}ms elapsedSinceClear=${elapsedSinceClear}ms`);
92638
+ }
92639
+ resizeClearTimeout.current = setTimeout(() => {
92640
+ resizeClearTimeout.current = null;
92641
+ if (prevColumnsRef.current !== targetColumns) {
92642
+ if (debugFlicker) {
92643
+ console.error(`[debug:flicker:resize-skip] stale target=${targetColumns} currentRaw=${prevColumnsRef.current}`);
92644
+ }
92645
+ return;
92646
+ }
92647
+ if (targetColumns === lastClearedColumnsRef.current) {
92648
+ if (debugFlicker) {
92649
+ console.error(`[debug:flicker:resize-skip] already-cleared target=${targetColumns}`);
92650
+ }
92651
+ return;
92652
+ }
92653
+ if (debugFlicker) {
92654
+ console.error(`[debug:flicker:resize-fire] clear target=${targetColumns}`);
92655
+ }
92656
+ clearAndRemount(targetColumns);
92657
+ }, delay);
92658
+ }, [clearAndRemount, debugFlicker]);
92216
92659
  import_react91.useEffect(() => {
92217
92660
  const prev = prevColumnsRef.current;
92218
- if (columns === prev)
92661
+ if (rawColumns === prev)
92219
92662
  return;
92220
92663
  if (resizeClearTimeout.current) {
92221
92664
  clearTimeout(resizeClearTimeout.current);
@@ -92223,52 +92666,38 @@ function App2({
92223
92666
  }
92224
92667
  if (isInitialResizeRef.current) {
92225
92668
  isInitialResizeRef.current = false;
92226
- prevColumnsRef.current = columns;
92227
- lastClearedColumnsRef.current = columns;
92669
+ prevColumnsRef.current = rawColumns;
92670
+ lastClearedColumnsRef.current = rawColumns;
92228
92671
  return;
92229
92672
  }
92230
- const delta = Math.abs(columns - prev);
92673
+ const delta = Math.abs(rawColumns - prev);
92231
92674
  const isMinorJitter = delta > 0 && delta < MIN_RESIZE_DELTA;
92675
+ if (isMinorJitter) {
92676
+ prevColumnsRef.current = rawColumns;
92677
+ return;
92678
+ }
92232
92679
  if (streaming) {
92233
- if (isMinorJitter) {
92234
- prevColumnsRef.current = columns;
92235
- return;
92236
- }
92237
92680
  pendingResizeRef.current = true;
92238
- pendingResizeColumnsRef.current = columns;
92239
- prevColumnsRef.current = columns;
92681
+ pendingResizeColumnsRef.current = rawColumns;
92682
+ prevColumnsRef.current = rawColumns;
92240
92683
  return;
92241
92684
  }
92242
- if (columns === lastClearedColumnsRef.current) {
92685
+ if (rawColumns === lastClearedColumnsRef.current) {
92243
92686
  pendingResizeRef.current = false;
92244
92687
  pendingResizeColumnsRef.current = null;
92245
- prevColumnsRef.current = columns;
92688
+ prevColumnsRef.current = rawColumns;
92246
92689
  return;
92247
92690
  }
92248
- const scheduledColumns = columns;
92249
- resizeClearTimeout.current = setTimeout(() => {
92250
- resizeClearTimeout.current = null;
92251
- if (typeof process !== "undefined" && process.stdout && "write" in process.stdout && process.stdout.isTTY) {
92252
- process.stdout.write(CLEAR_SCREEN_AND_HOME);
92253
- }
92254
- setStaticRenderEpoch((epoch) => epoch + 1);
92255
- lastClearedColumnsRef.current = scheduledColumns;
92256
- }, 150);
92257
- prevColumnsRef.current = columns;
92258
- return () => {
92259
- if (resizeClearTimeout.current) {
92260
- clearTimeout(resizeClearTimeout.current);
92261
- resizeClearTimeout.current = null;
92262
- }
92263
- };
92264
- }, [columns, streaming]);
92691
+ scheduleResizeClear(rawColumns);
92692
+ prevColumnsRef.current = rawColumns;
92693
+ }, [rawColumns, streaming, scheduleResizeClear]);
92265
92694
  import_react91.useEffect(() => {
92266
92695
  if (streaming) {
92267
92696
  if (resizeClearTimeout.current) {
92268
92697
  clearTimeout(resizeClearTimeout.current);
92269
92698
  resizeClearTimeout.current = null;
92270
92699
  pendingResizeRef.current = true;
92271
- pendingResizeColumnsRef.current = columns;
92700
+ pendingResizeColumnsRef.current = rawColumns;
92272
92701
  }
92273
92702
  return;
92274
92703
  }
@@ -92281,12 +92710,20 @@ function App2({
92281
92710
  return;
92282
92711
  if (pendingColumns === lastClearedColumnsRef.current)
92283
92712
  return;
92284
- if (typeof process !== "undefined" && process.stdout && "write" in process.stdout && process.stdout.isTTY) {
92285
- process.stdout.write(CLEAR_SCREEN_AND_HOME);
92286
- }
92287
- setStaticRenderEpoch((epoch) => epoch + 1);
92288
- lastClearedColumnsRef.current = pendingColumns;
92289
- }, [columns, streaming]);
92713
+ scheduleResizeClear(pendingColumns);
92714
+ }, [rawColumns, streaming, scheduleResizeClear]);
92715
+ import_react91.useEffect(() => {
92716
+ return () => {
92717
+ if (resizeClearTimeout.current) {
92718
+ clearTimeout(resizeClearTimeout.current);
92719
+ resizeClearTimeout.current = null;
92720
+ }
92721
+ if (stableColumnsTimeoutRef.current) {
92722
+ clearTimeout(stableColumnsTimeoutRef.current);
92723
+ stableColumnsTimeoutRef.current = null;
92724
+ }
92725
+ };
92726
+ }, []);
92290
92727
  const deferredToolCallCommitsRef = import_react91.useRef(new Map);
92291
92728
  const [deferredCommitAt, setDeferredCommitAt] = import_react91.useState(null);
92292
92729
  const resetDeferredToolCallCommits = import_react91.useCallback(() => {
@@ -96828,8 +97265,9 @@ ${SYSTEM_REMINDER_CLOSE}
96828
97265
  };
96829
97266
  }
96830
97267
  if (!selectedModel) {
96831
- const cmd = overlayCommand ?? commandRunner.start("/model", `Model not found: ${modelId}`);
96832
- cmd.fail(`Model not found: ${modelId}`);
97268
+ const output = `Model not found: ${modelId}. Run /model and press R to refresh available models.`;
97269
+ const cmd = overlayCommand ?? commandRunner.start("/model", output);
97270
+ cmd.fail(output);
96833
97271
  return;
96834
97272
  }
96835
97273
  const model = selectedModel;
@@ -96878,8 +97316,11 @@ Consider switching to a different system prompt using /system to match.` : null;
96878
97316
  });
96879
97317
  } catch (error) {
96880
97318
  const errorDetails = formatErrorDetails(error, agentId);
96881
- const cmd = overlayCommand ?? commandRunner.start("/model", "Failed to switch model.");
96882
- cmd.fail(`Failed to switch model: ${errorDetails}`);
97319
+ const modelLabel = selectedModel?.label ?? modelId;
97320
+ const guidance = "Run /model and press R to refresh available models. If the model is still unavailable, choose another model or connect a provider with /connect.";
97321
+ const cmd = overlayCommand ?? commandRunner.start("/model", `Failed to switch model to ${modelLabel}.`);
97322
+ cmd.fail(`Failed to switch model to ${modelLabel}: ${errorDetails}
97323
+ ${guidance}`);
96883
97324
  }
96884
97325
  }, [
96885
97326
  agentId,
@@ -97046,9 +97487,9 @@ Consider switching to a different system prompt using /system to match.` : null;
97046
97487
  commandRunner.start
97047
97488
  ]);
97048
97489
  const handleFeedbackSubmit = import_react91.useCallback(async (message) => {
97490
+ const overlayCommand = consumeOverlayCommand("feedback");
97049
97491
  closeOverlay();
97050
97492
  await withCommandLock(async () => {
97051
- const overlayCommand = consumeOverlayCommand("feedback");
97052
97493
  const cmd = overlayCommand ?? commandRunner.start("/feedback", "Sending feedback...");
97053
97494
  try {
97054
97495
  const resolvedMessage = resolvePlaceholders(message);
@@ -97255,7 +97696,7 @@ Consider switching to a different system prompt using /system to match.` : null;
97255
97696
  }
97256
97697
  if (!planFileExists()) {
97257
97698
  const planFilePath = permissionMode2.getPlanFilePath();
97258
- const plansDir = join28(homedir16(), ".letta", "plans");
97699
+ const plansDir = join28(homedir17(), ".letta", "plans");
97259
97700
  handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
97260
97701
  ` + (planFilePath ? `Plan file path: ${planFilePath}
97261
97702
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
@@ -97411,7 +97852,7 @@ Plan file path: ${planFilePath}`;
97411
97852
  deferredCommitAt
97412
97853
  ]);
97413
97854
  const { agents: subagents } = import_react91.useSyncExternalStore(subscribe2, getSnapshot2);
97414
- const shouldAnimate = import_react91.useMemo(() => {
97855
+ const estimatedLiveHeight = import_react91.useMemo(() => {
97415
97856
  const countLines4 = (text) => {
97416
97857
  if (!text)
97417
97858
  return 0;
@@ -97435,8 +97876,23 @@ Plan file path: ${planFilePath}`;
97435
97876
  const subagentsHeight = subagents.length * LINES_PER_SUBAGENT;
97436
97877
  const FIXED_BUFFER = 20;
97437
97878
  const estimatedHeight = liveItemsHeight + subagentsHeight + FIXED_BUFFER;
97438
- return estimatedHeight < terminalRows;
97439
- }, [liveItems, terminalRows, subagents.length]);
97879
+ return estimatedHeight;
97880
+ }, [liveItems, subagents.length]);
97881
+ const [shouldAnimate, setShouldAnimate] = import_react91.useState(() => estimatedLiveHeight < terminalRows);
97882
+ import_react91.useEffect(() => {
97883
+ if (terminalRows <= 0) {
97884
+ setShouldAnimate(false);
97885
+ return;
97886
+ }
97887
+ const disableThreshold = terminalRows;
97888
+ const resumeThreshold = Math.max(0, terminalRows - ANIMATION_RESUME_HYSTERESIS_ROWS);
97889
+ setShouldAnimate((prev) => {
97890
+ if (prev) {
97891
+ return estimatedLiveHeight < disableThreshold;
97892
+ }
97893
+ return estimatedLiveHeight < resumeThreshold;
97894
+ });
97895
+ }, [estimatedLiveHeight, terminalRows]);
97440
97896
  import_react91.useEffect(() => {
97441
97897
  if (loadingState === "ready" && !welcomeCommittedRef.current && messageHistory.length === 0) {
97442
97898
  if (!continueSession && !agentProvenance) {
@@ -97789,7 +98245,9 @@ Plan file path: ${planFilePath}`;
97789
98245
  onPasteError: handlePasteError,
97790
98246
  restoredInput,
97791
98247
  onRestoredInputConsumed: () => setRestoredInput(null),
97792
- networkPhase
98248
+ networkPhase,
98249
+ terminalWidth: columns,
98250
+ shouldAnimate
97793
98251
  }, undefined, false, undefined, this)
97794
98252
  }, undefined, false, undefined, this),
97795
98253
  activeOverlay === "model" && /* @__PURE__ */ jsx_dev_runtime69.jsxDEV(ModelSelector, {
@@ -98295,7 +98753,7 @@ Open /mcp to attach or detach tools for this server.`, true);
98295
98753
  ]
98296
98754
  }, resumeKey, true, undefined, this);
98297
98755
  }
98298
- var import_react91, jsx_dev_runtime69, CLEAR_SCREEN_AND_HOME = "\x1B[2J\x1B[H", MIN_RESIZE_DELTA = 2, TOOL_CALL_COMMIT_DEFER_MS = 50, 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;
98756
+ var import_react91, jsx_dev_runtime69, 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;
98299
98757
  var init_App2 = __esm(async () => {
98300
98758
  init_error();
98301
98759
  init_check_approval();
@@ -98442,7 +98900,7 @@ import {
98442
98900
  readFileSync as readFileSync10,
98443
98901
  writeFileSync as writeFileSync7
98444
98902
  } from "node:fs";
98445
- import { homedir as homedir17, platform as platform5 } from "node:os";
98903
+ import { homedir as homedir18, platform as platform5 } from "node:os";
98446
98904
  import { dirname as dirname14, join as join29 } from "node:path";
98447
98905
  function detectTerminalType2() {
98448
98906
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
@@ -98475,7 +98933,7 @@ function getKeybindingsPath2(terminal) {
98475
98933
  }[terminal];
98476
98934
  const os6 = platform5();
98477
98935
  if (os6 === "darwin") {
98478
- return join29(homedir17(), "Library", "Application Support", appName, "User", "keybindings.json");
98936
+ return join29(homedir18(), "Library", "Application Support", appName, "User", "keybindings.json");
98479
98937
  }
98480
98938
  if (os6 === "win32") {
98481
98939
  const appData = process.env.APPDATA;
@@ -98484,7 +98942,7 @@ function getKeybindingsPath2(terminal) {
98484
98942
  return join29(appData, appName, "User", "keybindings.json");
98485
98943
  }
98486
98944
  if (os6 === "linux") {
98487
- return join29(homedir17(), ".config", appName, "User", "keybindings.json");
98945
+ return join29(homedir18(), ".config", appName, "User", "keybindings.json");
98488
98946
  }
98489
98947
  return null;
98490
98948
  }
@@ -98641,10 +99099,10 @@ function getWezTermConfigPath2() {
98641
99099
  if (existsSync18(xdgPath))
98642
99100
  return xdgPath;
98643
99101
  }
98644
- const configPath = join29(homedir17(), ".config", "wezterm", "wezterm.lua");
99102
+ const configPath = join29(homedir18(), ".config", "wezterm", "wezterm.lua");
98645
99103
  if (existsSync18(configPath))
98646
99104
  return configPath;
98647
- return join29(homedir17(), ".wezterm.lua");
99105
+ return join29(homedir18(), ".wezterm.lua");
98648
99106
  }
98649
99107
  function wezTermDeleteFixExists2(configPath) {
98650
99108
  if (!existsSync18(configPath))
@@ -98742,10 +99200,10 @@ __export(exports_settings2, {
98742
99200
  loadProjectSettings: () => loadProjectSettings2,
98743
99201
  getSetting: () => getSetting2
98744
99202
  });
98745
- import { homedir as homedir18 } from "node:os";
99203
+ import { homedir as homedir19 } from "node:os";
98746
99204
  import { join as join30 } from "node:path";
98747
99205
  function getSettingsPath2() {
98748
- return join30(homedir18(), ".letta", "settings.json");
99206
+ return join30(homedir19(), ".letta", "settings.json");
98749
99207
  }
98750
99208
  async function loadSettings2() {
98751
99209
  const settingsPath = getSettingsPath2();
@@ -102181,6 +102639,9 @@ var DEFAULT_LOCAL_PROJECT_SETTINGS2 = {
102181
102639
  lastAgent: null
102182
102640
  };
102183
102641
  var DEFAULT_LETTA_API_URL2 = "https://api.letta.com";
102642
+ function isSubagentProcess2() {
102643
+ return process.env.LETTA_CODE_AGENT_ROLE === "subagent";
102644
+ }
102184
102645
  function normalizeBaseUrl2(baseUrl) {
102185
102646
  let normalized = baseUrl.replace(/^https?:\/\//, "");
102186
102647
  normalized = normalized.replace(/\/$/, "");
@@ -102213,14 +102674,18 @@ class SettingsManager2 {
102213
102674
  }
102214
102675
  this.initialized = true;
102215
102676
  await this.checkSecretsSupport();
102216
- await this.migrateTokensToSecrets();
102677
+ if (!isSubagentProcess2()) {
102678
+ await this.migrateTokensToSecrets();
102679
+ }
102217
102680
  this.migrateToAgentsArray();
102218
102681
  } catch (error) {
102219
102682
  console.error("Error loading settings, using defaults:", error);
102220
102683
  this.settings = { ...DEFAULT_SETTINGS2 };
102221
102684
  this.initialized = true;
102222
102685
  await this.checkSecretsSupport();
102223
- await this.migrateTokensToSecrets();
102686
+ if (!isSubagentProcess2()) {
102687
+ await this.migrateTokensToSecrets();
102688
+ }
102224
102689
  this.migrateToAgentsArray();
102225
102690
  }
102226
102691
  }
@@ -103750,7 +104215,8 @@ Auto-update failed due to filesystem issue (ENOTEMPTY).`);
103750
104215
  sleeptime: { type: "boolean" },
103751
104216
  "from-af": { type: "string" },
103752
104217
  memfs: { type: "boolean" },
103753
- "no-memfs": { type: "boolean" }
104218
+ "no-memfs": { type: "boolean" },
104219
+ "max-turns": { type: "string" }
103754
104220
  },
103755
104221
  strict: true,
103756
104222
  allowPositionals: true
@@ -104777,4 +105243,4 @@ Error during initialization: ${message}`);
104777
105243
  }
104778
105244
  main();
104779
105245
 
104780
- //# debugId=F77B95C148F3937C64756E2164756E21
105246
+ //# debugId=F0DE08B3E2B6D4FD64756E2164756E21