@letta-ai/letta-code 0.14.12 → 0.14.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/letta.js +294 -71
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3122,7 +3122,7 @@ var package_default;
3122
3122
  var init_package = __esm(() => {
3123
3123
  package_default = {
3124
3124
  name: "@letta-ai/letta-code",
3125
- version: "0.14.12",
3125
+ version: "0.14.14",
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
  }
@@ -5704,7 +5728,7 @@ Some blocks are read-only in the API (e.g., certain system-managed blocks). For
5704
5728
  var init_system_prompt_memfs = () => {};
5705
5729
 
5706
5730
  // src/utils/error.ts
5707
- function getErrorMessage(error) {
5731
+ function getErrorMessage2(error) {
5708
5732
  return error instanceof Error ? error.message : String(error);
5709
5733
  }
5710
5734
 
@@ -6919,7 +6943,7 @@ function getBuiltinSubagents() {
6919
6943
  const config = parseSubagentContent(source);
6920
6944
  builtins[config.name] = config;
6921
6945
  } catch (error) {
6922
- console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage(error)}`);
6946
+ console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage2(error)}`);
6923
6947
  }
6924
6948
  }
6925
6949
  cache.builtins = builtins;
@@ -6954,14 +6978,14 @@ async function discoverSubagentsFromDir(agentsDir, seenNames, subagents, errors)
6954
6978
  } catch (error) {
6955
6979
  errors.push({
6956
6980
  path: filePath,
6957
- message: getErrorMessage(error)
6981
+ message: getErrorMessage2(error)
6958
6982
  });
6959
6983
  }
6960
6984
  }
6961
6985
  } catch (error) {
6962
6986
  errors.push({
6963
6987
  path: agentsDir,
6964
- message: `Failed to read agents directory: ${getErrorMessage(error)}`
6988
+ message: `Failed to read agents directory: ${getErrorMessage2(error)}`
6965
6989
  });
6966
6990
  }
6967
6991
  }
@@ -32655,6 +32679,30 @@ var init_models2 = __esm(() => {
32655
32679
  max_output_tokens: 64000
32656
32680
  }
32657
32681
  },
32682
+ {
32683
+ id: "gpt-5.3-codex-plus-pro-medium",
32684
+ handle: "chatgpt-plus-pro/gpt-5.3-codex",
32685
+ label: "GPT-5.3 Codex",
32686
+ description: "GPT-5.3 Codex (med reasoning) via ChatGPT Plus/Pro",
32687
+ updateArgs: {
32688
+ reasoning_effort: "medium",
32689
+ verbosity: "medium",
32690
+ context_window: 272000,
32691
+ max_output_tokens: 128000
32692
+ }
32693
+ },
32694
+ {
32695
+ id: "gpt-5.3-codex-plus-pro-high",
32696
+ handle: "chatgpt-plus-pro/gpt-5.3-codex",
32697
+ label: "GPT-5.3 Codex",
32698
+ description: "GPT-5.3 Codex (high reasoning) via ChatGPT Plus/Pro",
32699
+ updateArgs: {
32700
+ reasoning_effort: "high",
32701
+ verbosity: "medium",
32702
+ context_window: 272000,
32703
+ max_output_tokens: 128000
32704
+ }
32705
+ },
32658
32706
  {
32659
32707
  id: "gpt-5.2-codex-plus-pro-medium",
32660
32708
  handle: "chatgpt-plus-pro/gpt-5.2-codex",
@@ -33239,6 +33287,7 @@ __export(exports_model, {
33239
33287
  models: () => models,
33240
33288
  getModelUpdateArgs: () => getModelUpdateArgs,
33241
33289
  getModelShortName: () => getModelShortName,
33290
+ getModelInfoForLlmConfig: () => getModelInfoForLlmConfig,
33242
33291
  getModelInfo: () => getModelInfo,
33243
33292
  getModelDisplayName: () => getModelDisplayName,
33244
33293
  getDefaultModelForTier: () => getDefaultModelForTier,
@@ -33288,6 +33337,25 @@ function getModelInfo(modelIdentifier) {
33288
33337
  return byHandle;
33289
33338
  return null;
33290
33339
  }
33340
+ function getModelInfoForLlmConfig(modelHandle, llmConfig) {
33341
+ const direct = getModelInfo(modelHandle);
33342
+ const candidates = models.filter((m) => m.handle === modelHandle);
33343
+ if (candidates.length === 0) {
33344
+ return direct;
33345
+ }
33346
+ const effort = llmConfig?.reasoning_effort ?? null;
33347
+ if (effort) {
33348
+ const match = candidates.find((m) => m.updateArgs?.reasoning_effort === effort);
33349
+ if (match)
33350
+ return match;
33351
+ }
33352
+ if (llmConfig?.enable_reasoner === false) {
33353
+ const match = candidates.find((m) => m.updateArgs?.enable_reasoner === false);
33354
+ if (match)
33355
+ return match;
33356
+ }
33357
+ return direct ?? candidates[0] ?? null;
33358
+ }
33291
33359
  function getModelUpdateArgs(modelIdentifier) {
33292
33360
  if (!modelIdentifier)
33293
33361
  return;
@@ -38182,6 +38250,14 @@ function setGlobalPlanFilePath2(value) {
38182
38250
  const global2 = globalThis;
38183
38251
  global2[PLAN_FILE_KEY2] = value;
38184
38252
  }
38253
+ function getGlobalModeBeforePlan2() {
38254
+ const global2 = globalThis;
38255
+ return global2[MODE_BEFORE_PLAN_KEY2] ?? null;
38256
+ }
38257
+ function setGlobalModeBeforePlan2(value) {
38258
+ const global2 = globalThis;
38259
+ global2[MODE_BEFORE_PLAN_KEY2] = value;
38260
+ }
38185
38261
 
38186
38262
  class PermissionModeManager2 {
38187
38263
  get currentMode() {
@@ -38191,10 +38267,20 @@ class PermissionModeManager2 {
38191
38267
  setGlobalMode2(value);
38192
38268
  }
38193
38269
  setMode(mode) {
38270
+ const prevMode = this.currentMode;
38271
+ if (mode === "plan" && prevMode !== "plan") {
38272
+ setGlobalModeBeforePlan2(prevMode);
38273
+ }
38194
38274
  this.currentMode = mode;
38195
38275
  if (mode !== "plan") {
38196
38276
  setGlobalPlanFilePath2(null);
38197
38277
  }
38278
+ if (prevMode === "plan" && mode !== "plan") {
38279
+ setGlobalModeBeforePlan2(null);
38280
+ }
38281
+ }
38282
+ getModeBeforePlan() {
38283
+ return getGlobalModeBeforePlan2();
38198
38284
  }
38199
38285
  getMode() {
38200
38286
  return this.currentMode;
@@ -38320,13 +38406,16 @@ class PermissionModeManager2 {
38320
38406
  }
38321
38407
  reset() {
38322
38408
  this.currentMode = "default";
38409
+ setGlobalPlanFilePath2(null);
38410
+ setGlobalModeBeforePlan2(null);
38323
38411
  }
38324
38412
  }
38325
- var MODE_KEY2, PLAN_FILE_KEY2, permissionMode2;
38413
+ var MODE_KEY2, PLAN_FILE_KEY2, MODE_BEFORE_PLAN_KEY2, permissionMode2;
38326
38414
  var init_mode = __esm(() => {
38327
38415
  init_readOnlyShell();
38328
38416
  MODE_KEY2 = Symbol.for("@letta/permissionMode");
38329
38417
  PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
38418
+ MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
38330
38419
  permissionMode2 = new PermissionModeManager2;
38331
38420
  });
38332
38421
 
@@ -54628,7 +54717,7 @@ function parseResultFromStdout(stdout, agentId) {
54628
54717
  agentId: agentId || "",
54629
54718
  report: "",
54630
54719
  success: false,
54631
- error: `Failed to parse subagent output: ${getErrorMessage(parseError)}`
54720
+ error: `Failed to parse subagent output: ${getErrorMessage2(parseError)}`
54632
54721
  };
54633
54722
  }
54634
54723
  }
@@ -54802,7 +54891,7 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
54802
54891
  agentId: "",
54803
54892
  report: "",
54804
54893
  success: false,
54805
- error: getErrorMessage(error)
54894
+ error: getErrorMessage2(error)
54806
54895
  };
54807
54896
  }
54808
54897
  }
@@ -60892,7 +60981,7 @@ function getBuiltinSubagents2() {
60892
60981
  const config = parseSubagentContent2(source);
60893
60982
  builtins[config.name] = config;
60894
60983
  } catch (error) {
60895
- console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage(error)}`);
60984
+ console.warn(`[subagent] Failed to parse built-in subagent: ${getErrorMessage2(error)}`);
60896
60985
  }
60897
60986
  }
60898
60987
  cache5.builtins = builtins;
@@ -60927,14 +61016,14 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
60927
61016
  } catch (error) {
60928
61017
  errors.push({
60929
61018
  path: filePath,
60930
- message: getErrorMessage(error)
61019
+ message: getErrorMessage2(error)
60931
61020
  });
60932
61021
  }
60933
61022
  }
60934
61023
  } catch (error) {
60935
61024
  errors.push({
60936
61025
  path: agentsDir,
60937
- message: `Failed to read agents directory: ${getErrorMessage(error)}`
61026
+ message: `Failed to read agents directory: ${getErrorMessage2(error)}`
60938
61027
  });
60939
61028
  }
60940
61029
  }
@@ -65980,10 +66069,13 @@ async function runBidirectionalMode(agent, conversationId, _client, _outputForma
65980
66069
  request: canUseToolRequest
65981
66070
  };
65982
66071
  console.log(JSON.stringify(controlRequest));
65983
- while (true) {
66072
+ const deferredLines = [];
66073
+ let result = null;
66074
+ while (result === null) {
65984
66075
  const line = await getNextLine();
65985
66076
  if (line === null) {
65986
- return { decision: "deny", reason: "stdin closed" };
66077
+ result = { decision: "deny", reason: "stdin closed" };
66078
+ break;
65987
66079
  }
65988
66080
  if (!line.trim())
65989
66081
  continue;
@@ -65992,20 +66084,31 @@ async function runBidirectionalMode(agent, conversationId, _client, _outputForma
65992
66084
  if (msg.type === "control_response" && msg.response?.request_id === requestId) {
65993
66085
  const response = msg.response?.response;
65994
66086
  if (!response) {
65995
- return { decision: "deny", reason: "Invalid response format" };
66087
+ result = { decision: "deny", reason: "Invalid response format" };
66088
+ break;
65996
66089
  }
65997
66090
  if (response.behavior === "allow") {
65998
- return { decision: "allow", updatedInput: response.updatedInput };
66091
+ result = {
66092
+ decision: "allow",
66093
+ updatedInput: response.updatedInput
66094
+ };
65999
66095
  } else {
66000
- return {
66096
+ result = {
66001
66097
  decision: "deny",
66002
66098
  reason: response.message
66003
66099
  };
66004
66100
  }
66101
+ break;
66005
66102
  }
66006
- lineQueue.unshift(line);
66007
- } catch {}
66103
+ deferredLines.push(line);
66104
+ } catch {
66105
+ deferredLines.push(line);
66106
+ }
66107
+ }
66108
+ if (deferredLines.length > 0) {
66109
+ lineQueue.unshift(...deferredLines);
66008
66110
  }
66111
+ return result;
66009
66112
  }
66010
66113
  while (true) {
66011
66114
  const line = await getNextLine();
@@ -86483,6 +86586,25 @@ function getTreeChars(isLast) {
86483
86586
  continueChar: isLast ? " " : "│ "
86484
86587
  };
86485
86588
  }
86589
+ function getSubagentModelDisplay(model) {
86590
+ if (!model)
86591
+ return null;
86592
+ const normalized = resolveModel(model) ?? model;
86593
+ const slashIndex = normalized.indexOf("/");
86594
+ const provider = slashIndex >= 0 ? normalized.slice(0, slashIndex) : normalized;
86595
+ const isOpenAICodexProvider = provider === OPENAI_CODEX_PROVIDER_NAME;
86596
+ const isByokProvider = provider.startsWith("lc-") || isOpenAICodexProvider;
86597
+ const label = getModelShortName(normalized) ?? normalized.split("/").pop() ?? normalized;
86598
+ return {
86599
+ label,
86600
+ isByokProvider,
86601
+ isOpenAICodexProvider
86602
+ };
86603
+ }
86604
+ var init_subagentDisplay = __esm(async () => {
86605
+ init_model();
86606
+ await init_openai_codex_provider();
86607
+ });
86486
86608
 
86487
86609
  // src/cli/components/SubagentGroupDisplay.tsx
86488
86610
  function formatToolArgs(argsStr) {
@@ -86510,6 +86632,7 @@ var init_SubagentGroupDisplay = __esm(async () => {
86510
86632
  init_colors();
86511
86633
  await __promiseAll([
86512
86634
  init_build2(),
86635
+ init_subagentDisplay(),
86513
86636
  init_BlinkDot(),
86514
86637
  init_Text2()
86515
86638
  ]);
@@ -86523,6 +86646,7 @@ var init_SubagentGroupDisplay = __esm(async () => {
86523
86646
  const isRunning = agent.status === "pending" || agent.status === "running";
86524
86647
  const shouldDim = isRunning && !agent.isBackground;
86525
86648
  const stats = formatStats(agent.toolCalls.length, agent.totalTokens, isRunning);
86649
+ const modelDisplay = getSubagentModelDisplay(agent.model);
86526
86650
  const lastTool = agent.toolCalls[agent.toolCalls.length - 1];
86527
86651
  if (condensed) {
86528
86652
  const isComplete = agent.status === "completed" || agent.status === "error";
@@ -86550,8 +86674,19 @@ var init_SubagentGroupDisplay = __esm(async () => {
86550
86674
  dimColor: true,
86551
86675
  children: [
86552
86676
  " · ",
86553
- agent.type.toLowerCase(),
86554
- agent.model ? ` · ${agent.model}` : ""
86677
+ agent.type.toLowerCase()
86678
+ ]
86679
+ }, undefined, true, undefined, this),
86680
+ modelDisplay && /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(jsx_dev_runtime58.Fragment, {
86681
+ children: [
86682
+ /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(Text2, {
86683
+ dimColor: true,
86684
+ children: ` · ${modelDisplay.label}`
86685
+ }, undefined, false, undefined, this),
86686
+ modelDisplay.isByokProvider && /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(Text2, {
86687
+ color: modelDisplay.isOpenAICodexProvider ? "#74AA9C" : "yellow",
86688
+ children: " ▲"
86689
+ }, undefined, false, undefined, this)
86555
86690
  ]
86556
86691
  }, undefined, true, undefined, this)
86557
86692
  ]
@@ -86613,8 +86748,24 @@ var init_SubagentGroupDisplay = __esm(async () => {
86613
86748
  dimColor: true,
86614
86749
  children: [
86615
86750
  " · ",
86616
- agent.type.toLowerCase(),
86617
- agent.model ? ` · ${agent.model}` : "",
86751
+ agent.type.toLowerCase()
86752
+ ]
86753
+ }, undefined, true, undefined, this),
86754
+ modelDisplay && /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(jsx_dev_runtime58.Fragment, {
86755
+ children: [
86756
+ /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(Text2, {
86757
+ dimColor: true,
86758
+ children: ` · ${modelDisplay.label}`
86759
+ }, undefined, false, undefined, this),
86760
+ modelDisplay.isByokProvider && /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(Text2, {
86761
+ color: modelDisplay.isOpenAICodexProvider ? "#74AA9C" : "yellow",
86762
+ children: " ▲"
86763
+ }, undefined, false, undefined, this)
86764
+ ]
86765
+ }, undefined, true, undefined, this),
86766
+ /* @__PURE__ */ jsx_dev_runtime58.jsxDEV(Text2, {
86767
+ dimColor: true,
86768
+ children: [
86618
86769
  " · ",
86619
86770
  stats
86620
86771
  ]
@@ -86849,6 +87000,7 @@ var init_SubagentGroupStatic = __esm(async () => {
86849
87000
  init_colors();
86850
87001
  await __promiseAll([
86851
87002
  init_build2(),
87003
+ init_subagentDisplay(),
86852
87004
  init_Text2()
86853
87005
  ]);
86854
87006
  import_react82 = __toESM(require_react(), 1);
@@ -86861,6 +87013,7 @@ var init_SubagentGroupStatic = __esm(async () => {
86861
87013
  const isRunning = agent.status === "running";
86862
87014
  const shouldDim = isRunning && !agent.isBackground;
86863
87015
  const stats = formatStats(agent.toolCount, agent.totalTokens, isRunning);
87016
+ const modelDisplay = getSubagentModelDisplay(agent.model);
86864
87017
  return /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Box_default, {
86865
87018
  flexDirection: "column",
86866
87019
  children: [
@@ -86885,8 +87038,24 @@ var init_SubagentGroupStatic = __esm(async () => {
86885
87038
  dimColor: true,
86886
87039
  children: [
86887
87040
  " · ",
86888
- agent.type.toLowerCase(),
86889
- agent.model ? ` · ${agent.model}` : "",
87041
+ agent.type.toLowerCase()
87042
+ ]
87043
+ }, undefined, true, undefined, this),
87044
+ modelDisplay && /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(jsx_dev_runtime59.Fragment, {
87045
+ children: [
87046
+ /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Text2, {
87047
+ dimColor: true,
87048
+ children: ` · ${modelDisplay.label}`
87049
+ }, undefined, false, undefined, this),
87050
+ modelDisplay.isByokProvider && /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Text2, {
87051
+ color: modelDisplay.isOpenAICodexProvider ? "#74AA9C" : "yellow",
87052
+ children: " ▲"
87053
+ }, undefined, false, undefined, this)
87054
+ ]
87055
+ }, undefined, true, undefined, this),
87056
+ /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Text2, {
87057
+ dimColor: true,
87058
+ children: [
86890
87059
  " · ",
86891
87060
  stats
86892
87061
  ]
@@ -91003,7 +91172,7 @@ Your ChatGPT Plus/Pro subscription is now linked.`, true, "finished");
91003
91172
  }
91004
91173
  } catch (error) {
91005
91174
  settingsManager.clearOAuthState();
91006
- const errorMessage = getErrorMessage(error);
91175
+ const errorMessage = getErrorMessage2(error);
91007
91176
  let displayMessage;
91008
91177
  if (errorMessage === "PLAN_UPGRADE_REQUIRED") {
91009
91178
  displayMessage = `✗ ChatGPT OAuth requires a Pro or Enterprise plan
@@ -91039,7 +91208,7 @@ Use /connect minimax <api_key> to connect.`, false);
91039
91208
 
91040
91209
  ` + `Provider '${MINIMAX_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91041
91210
  } catch (error) {
91042
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from MiniMax: ${getErrorMessage(error)}`, false, "finished");
91211
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from MiniMax: ${getErrorMessage2(error)}`, false, "finished");
91043
91212
  } finally {
91044
91213
  ctx.setCommandRunning(false);
91045
91214
  }
@@ -91060,7 +91229,7 @@ Use /connect and select "AWS Bedrock" to connect.`, false);
91060
91229
 
91061
91230
  ` + `Provider '${BEDROCK_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91062
91231
  } catch (error) {
91063
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Bedrock: ${getErrorMessage(error)}`, false, "finished");
91232
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Bedrock: ${getErrorMessage2(error)}`, false, "finished");
91064
91233
  } finally {
91065
91234
  ctx.setCommandRunning(false);
91066
91235
  }
@@ -91086,7 +91255,7 @@ Example: /connect minimax <api_key>...`, false);
91086
91255
 
91087
91256
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91088
91257
  } catch (error) {
91089
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create MiniMax provider: ${getErrorMessage(error)}`, false, "finished");
91258
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create MiniMax provider: ${getErrorMessage2(error)}`, false, "finished");
91090
91259
  } finally {
91091
91260
  ctx.setCommandRunning(false);
91092
91261
  }
@@ -91153,7 +91322,7 @@ Use /connect codex to authenticate.`, false);
91153
91322
 
91154
91323
  ` + `Provider '${OPENAI_CODEX_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91155
91324
  } catch (error) {
91156
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from ChatGPT: ${getErrorMessage(error)}`, false, "finished");
91325
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from ChatGPT: ${getErrorMessage2(error)}`, false, "finished");
91157
91326
  } finally {
91158
91327
  ctx.setCommandRunning(false);
91159
91328
  }
@@ -91181,7 +91350,7 @@ The '${CLAUDE_PROVIDER_NAME}' provider does not exist in your Letta account.`, f
91181
91350
 
91182
91351
  Note: /connect claude has been replaced with /connect codex for OpenAI ChatGPT Plus/Pro.`, true, "finished");
91183
91352
  } catch (error) {
91184
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Claude: ${getErrorMessage(error)}`, false, "finished");
91353
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Claude: ${getErrorMessage2(error)}`, false, "finished");
91185
91354
  } finally {
91186
91355
  ctx.setCommandRunning(false);
91187
91356
  }
@@ -91202,7 +91371,7 @@ Use /connect zai <api_key> to connect.`, false);
91202
91371
 
91203
91372
  ` + `Provider '${ZAI_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91204
91373
  } catch (error) {
91205
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage(error)}`, false, "finished");
91374
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage2(error)}`, false, "finished");
91206
91375
  } finally {
91207
91376
  ctx.setCommandRunning(false);
91208
91377
  }
@@ -91228,7 +91397,7 @@ Example: /connect zai <api_key>...`, false);
91228
91397
 
91229
91398
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91230
91399
  } catch (error) {
91231
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage(error)}`, false, "finished");
91400
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage2(error)}`, false, "finished");
91232
91401
  } finally {
91233
91402
  ctx.setCommandRunning(false);
91234
91403
  }
@@ -91256,7 +91425,7 @@ Example: /connect openrouter sk-or-v1-...`, false);
91256
91425
 
91257
91426
  ` + `The models are populated in /model → "All Available Models"`, true, "finished");
91258
91427
  } catch (error) {
91259
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create OpenRouter provider: ${getErrorMessage(error)}`, false, "finished");
91428
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create OpenRouter provider: ${getErrorMessage2(error)}`, false, "finished");
91260
91429
  } finally {
91261
91430
  ctx.setCommandRunning(false);
91262
91431
  }
@@ -91277,7 +91446,7 @@ Use /connect openrouter <api_key> to connect.`, false);
91277
91446
 
91278
91447
  ` + `Provider '${OPENROUTER_PROVIDER_NAME}' removed from Letta.`, true, "finished");
91279
91448
  } catch (error) {
91280
- updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from OpenRouter: ${getErrorMessage(error)}`, false, "finished");
91449
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from OpenRouter: ${getErrorMessage2(error)}`, false, "finished");
91281
91450
  } finally {
91282
91451
  ctx.setCommandRunning(false);
91283
91452
  }
@@ -92639,7 +92808,8 @@ function App2({
92639
92808
  const lastRunCompletion = agent.last_run_completion;
92640
92809
  setAgentLastRunAt(lastRunCompletion ?? null);
92641
92810
  const agentModelHandle = agent.llm_config.model_endpoint_type && agent.llm_config.model ? `${agent.llm_config.model_endpoint_type}/${agent.llm_config.model}` : agent.llm_config.model;
92642
- const modelInfo = getModelInfo(agentModelHandle || "");
92811
+ const { getModelInfoForLlmConfig: getModelInfoForLlmConfig2 } = await Promise.resolve().then(() => (init_model(), exports_model));
92812
+ const modelInfo = getModelInfoForLlmConfig2(agentModelHandle || "", agent.llm_config);
92643
92813
  if (modelInfo) {
92644
92814
  setCurrentModelId(modelInfo.id);
92645
92815
  } else {
@@ -93167,13 +93337,17 @@ ${newState.originalPrompt}`
93167
93337
  const agent = await client.agents.retrieve(agentIdRef.current);
93168
93338
  const currentModel = llmConfigRef.current?.model;
93169
93339
  const currentEndpoint = llmConfigRef.current?.model_endpoint_type;
93340
+ const currentEffort = llmConfigRef.current?.reasoning_effort;
93341
+ const currentEnableReasoner = llmConfigRef.current?.enable_reasoner;
93170
93342
  const agentModel = agent.llm_config.model;
93171
93343
  const agentEndpoint = agent.llm_config.model_endpoint_type;
93172
- if (currentModel !== agentModel || currentEndpoint !== agentEndpoint) {
93344
+ const agentEffort = agent.llm_config.reasoning_effort;
93345
+ const agentEnableReasoner = agent.llm_config?.enable_reasoner;
93346
+ if (currentModel !== agentModel || currentEndpoint !== agentEndpoint || currentEffort !== agentEffort || currentEnableReasoner !== agentEnableReasoner) {
93173
93347
  setLlmConfig(agent.llm_config);
93174
- const { getModelInfo: getModelInfo2 } = await Promise.resolve().then(() => (init_model(), exports_model));
93348
+ const { getModelInfoForLlmConfig: getModelInfoForLlmConfig2 } = await Promise.resolve().then(() => (init_model(), exports_model));
93175
93349
  const agentModelHandle = agent.llm_config.model_endpoint_type && agent.llm_config.model ? `${agent.llm_config.model_endpoint_type}/${agent.llm_config.model}` : agent.llm_config.model;
93176
- const modelInfo = getModelInfo2(agentModelHandle || "");
93350
+ const modelInfo = getModelInfoForLlmConfig2(agentModelHandle || "", agent.llm_config);
93177
93351
  if (modelInfo) {
93178
93352
  setCurrentModelId(modelInfo.id);
93179
93353
  } else {
@@ -97011,9 +97185,9 @@ Consider switching to a different system prompt using /system to match.` : null;
97011
97185
  const isLast = currentIndex + 1 >= pendingApprovals.length;
97012
97186
  const planFilePath = permissionMode2.getPlanFilePath();
97013
97187
  lastPlanFilePathRef.current = planFilePath;
97014
- const newMode = acceptEdits ? "acceptEdits" : "default";
97015
- permissionMode2.setMode(newMode);
97016
- setUiPermissionMode(newMode);
97188
+ const restoreMode = acceptEdits ? "acceptEdits" : permissionMode2.getModeBeforePlan() ?? "default";
97189
+ permissionMode2.setMode(restoreMode);
97190
+ setUiPermissionMode(restoreMode);
97017
97191
  try {
97018
97192
  const parsedArgs = safeJsonParseOr(approval.toolArgs, {});
97019
97193
  const toolResult = await executeTool("ExitPlanMode", parsedArgs);
@@ -98736,6 +98910,7 @@ __export(exports_model2, {
98736
98910
  models: () => models2,
98737
98911
  getModelUpdateArgs: () => getModelUpdateArgs2,
98738
98912
  getModelShortName: () => getModelShortName2,
98913
+ getModelInfoForLlmConfig: () => getModelInfoForLlmConfig2,
98739
98914
  getModelInfo: () => getModelInfo2,
98740
98915
  getModelDisplayName: () => getModelDisplayName2,
98741
98916
  getDefaultModelForTier: () => getDefaultModelForTier2,
@@ -98785,6 +98960,25 @@ function getModelInfo2(modelIdentifier) {
98785
98960
  return byHandle;
98786
98961
  return null;
98787
98962
  }
98963
+ function getModelInfoForLlmConfig2(modelHandle, llmConfig) {
98964
+ const direct = getModelInfo2(modelHandle);
98965
+ const candidates = models2.filter((m) => m.handle === modelHandle);
98966
+ if (candidates.length === 0) {
98967
+ return direct;
98968
+ }
98969
+ const effort = llmConfig?.reasoning_effort ?? null;
98970
+ if (effort) {
98971
+ const match3 = candidates.find((m) => m.updateArgs?.reasoning_effort === effort);
98972
+ if (match3)
98973
+ return match3;
98974
+ }
98975
+ if (llmConfig?.enable_reasoner === false) {
98976
+ const match3 = candidates.find((m) => m.updateArgs?.enable_reasoner === false);
98977
+ if (match3)
98978
+ return match3;
98979
+ }
98980
+ return direct ?? candidates[0] ?? null;
98981
+ }
98788
98982
  function getModelUpdateArgs2(modelIdentifier) {
98789
98983
  if (!modelIdentifier)
98790
98984
  return;
@@ -101807,6 +102001,7 @@ import { homedir as homedir5 } from "node:os";
101807
102001
  import { join as join5 } from "node:path";
101808
102002
  var MODE_KEY = Symbol.for("@letta/permissionMode");
101809
102003
  var PLAN_FILE_KEY = Symbol.for("@letta/planFilePath");
102004
+ var MODE_BEFORE_PLAN_KEY = Symbol.for("@letta/permissionModeBeforePlan");
101810
102005
  function getGlobalMode() {
101811
102006
  const global2 = globalThis;
101812
102007
  if (!global2[MODE_KEY]) {
@@ -101826,6 +102021,14 @@ function setGlobalPlanFilePath(value) {
101826
102021
  const global2 = globalThis;
101827
102022
  global2[PLAN_FILE_KEY] = value;
101828
102023
  }
102024
+ function getGlobalModeBeforePlan() {
102025
+ const global2 = globalThis;
102026
+ return global2[MODE_BEFORE_PLAN_KEY] ?? null;
102027
+ }
102028
+ function setGlobalModeBeforePlan(value) {
102029
+ const global2 = globalThis;
102030
+ global2[MODE_BEFORE_PLAN_KEY] = value;
102031
+ }
101829
102032
 
101830
102033
  class PermissionModeManager {
101831
102034
  get currentMode() {
@@ -101835,10 +102038,20 @@ class PermissionModeManager {
101835
102038
  setGlobalMode(value);
101836
102039
  }
101837
102040
  setMode(mode) {
102041
+ const prevMode = this.currentMode;
102042
+ if (mode === "plan" && prevMode !== "plan") {
102043
+ setGlobalModeBeforePlan(prevMode);
102044
+ }
101838
102045
  this.currentMode = mode;
101839
102046
  if (mode !== "plan") {
101840
102047
  setGlobalPlanFilePath(null);
101841
102048
  }
102049
+ if (prevMode === "plan" && mode !== "plan") {
102050
+ setGlobalModeBeforePlan(null);
102051
+ }
102052
+ }
102053
+ getModeBeforePlan() {
102054
+ return getGlobalModeBeforePlan();
101842
102055
  }
101843
102056
  getMode() {
101844
102057
  return this.currentMode;
@@ -101964,6 +102177,8 @@ class PermissionModeManager {
101964
102177
  }
101965
102178
  reset() {
101966
102179
  this.currentMode = "default";
102180
+ setGlobalPlanFilePath(null);
102181
+ setGlobalModeBeforePlan(null);
101967
102182
  }
101968
102183
  }
101969
102184
  var permissionMode = new PermissionModeManager;
@@ -101990,6 +102205,9 @@ var DEFAULT_LOCAL_PROJECT_SETTINGS2 = {
101990
102205
  lastAgent: null
101991
102206
  };
101992
102207
  var DEFAULT_LETTA_API_URL2 = "https://api.letta.com";
102208
+ function isSubagentProcess2() {
102209
+ return process.env.LETTA_CODE_AGENT_ROLE === "subagent";
102210
+ }
101993
102211
  function normalizeBaseUrl2(baseUrl) {
101994
102212
  let normalized = baseUrl.replace(/^https?:\/\//, "");
101995
102213
  normalized = normalized.replace(/\/$/, "");
@@ -102022,14 +102240,18 @@ class SettingsManager2 {
102022
102240
  }
102023
102241
  this.initialized = true;
102024
102242
  await this.checkSecretsSupport();
102025
- await this.migrateTokensToSecrets();
102243
+ if (!isSubagentProcess2()) {
102244
+ await this.migrateTokensToSecrets();
102245
+ }
102026
102246
  this.migrateToAgentsArray();
102027
102247
  } catch (error) {
102028
102248
  console.error("Error loading settings, using defaults:", error);
102029
102249
  this.settings = { ...DEFAULT_SETTINGS2 };
102030
102250
  this.initialized = true;
102031
102251
  await this.checkSecretsSupport();
102032
- await this.migrateTokensToSecrets();
102252
+ if (!isSubagentProcess2()) {
102253
+ await this.migrateTokensToSecrets();
102254
+ }
102033
102255
  this.migrateToAgentsArray();
102034
102256
  }
102035
102257
  }
@@ -103559,7 +103781,8 @@ Auto-update failed due to filesystem issue (ENOTEMPTY).`);
103559
103781
  sleeptime: { type: "boolean" },
103560
103782
  "from-af": { type: "string" },
103561
103783
  memfs: { type: "boolean" },
103562
- "no-memfs": { type: "boolean" }
103784
+ "no-memfs": { type: "boolean" },
103785
+ "max-turns": { type: "string" }
103563
103786
  },
103564
103787
  strict: true,
103565
103788
  allowPositionals: true
@@ -104586,4 +104809,4 @@ Error during initialization: ${message}`);
104586
104809
  }
104587
104810
  main();
104588
104811
 
104589
- //# debugId=82E2B767C7ECFCC264756E2164756E21
104812
+ //# debugId=8B604F61633624E964756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.14.12",
3
+ "version": "0.14.14",
4
4
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {