@letta-ai/letta-code 0.12.7 → 0.12.8

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 +292 -31
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3237,7 +3237,7 @@ var package_default;
3237
3237
  var init_package = __esm(() => {
3238
3238
  package_default = {
3239
3239
  name: "@letta-ai/letta-code",
3240
- version: "0.12.7",
3240
+ version: "0.12.8",
3241
3241
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3242
3242
  type: "module",
3243
3243
  bin: {
@@ -47793,6 +47793,7 @@ function SetupUI({ onComplete }) {
47793
47793
  refreshToken: tokens.refresh_token,
47794
47794
  tokenExpiresAt: now + tokens.expires_in * 1000
47795
47795
  });
47796
+ await settingsManager.flush();
47796
47797
  setMode("done");
47797
47798
  setTimeout(() => onComplete(), 1000);
47798
47799
  } catch (err) {
@@ -50592,6 +50593,9 @@ ${after}`;
50592
50593
  function clipToolReturn(text, maxLines = 3, maxChars = 300) {
50593
50594
  if (!text)
50594
50595
  return text;
50596
+ if (text.includes("request to call tool denied")) {
50597
+ return text;
50598
+ }
50595
50599
  let clipped = text;
50596
50600
  if (text.length > maxChars) {
50597
50601
  clipped = text.slice(0, maxChars);
@@ -51935,6 +51939,10 @@ var exports_check_approval = {};
51935
51939
  __export(exports_check_approval, {
51936
51940
  getResumeData: () => getResumeData2
51937
51941
  });
51942
+ function isBackfillEnabled2() {
51943
+ const val = process.env.LETTA_BACKFILL;
51944
+ return val !== "0" && val !== "false";
51945
+ }
51938
51946
  async function getResumeData2(client, agent) {
51939
51947
  try {
51940
51948
  const messagesPage = await client.agents.messages.list(agent.id);
@@ -51957,6 +51965,13 @@ async function getResumeData2(client, agent) {
51957
51965
  const inContextLastMessageId = agent.message_ids && agent.message_ids.length > 0 ? agent.message_ids[agent.message_ids.length - 1] : null;
51958
51966
  if (!inContextLastMessageId) {
51959
51967
  debugWarn("check-approval", `No in-context messages (message_ids empty/null) - no pending approvals`);
51968
+ if (!isBackfillEnabled2()) {
51969
+ return {
51970
+ pendingApproval: null,
51971
+ pendingApprovals: [],
51972
+ messageHistory: []
51973
+ };
51974
+ }
51960
51975
  const historyCount2 = Math.min(MESSAGE_HISTORY_LIMIT2, messages.length);
51961
51976
  let messageHistory2 = messages.slice(-historyCount2);
51962
51977
  if (messageHistory2[0]?.message_type === "tool_return_message") {
@@ -52007,6 +52022,9 @@ async function getResumeData2(client, agent) {
52007
52022
  }
52008
52023
  }
52009
52024
  }
52025
+ if (!isBackfillEnabled2()) {
52026
+ return { pendingApproval, pendingApprovals, messageHistory: [] };
52027
+ }
52010
52028
  const historyCount = Math.min(MESSAGE_HISTORY_LIMIT2, messages.length);
52011
52029
  let messageHistory = messages.slice(-historyCount);
52012
52030
  if (messageHistory[0]?.message_type === "tool_return_message") {
@@ -53012,7 +53030,17 @@ async function handleHeadlessCommand(argv, model, skillsDirectory) {
53012
53030
  }
53013
53031
  process.exit(1);
53014
53032
  }
53015
- if (stopReason === "error" && lastRunId && llmApiErrorRetries < LLM_API_ERROR_MAX_RETRIES) {
53033
+ const nonRetriableReasons = [
53034
+ "cancelled",
53035
+ "requires_approval",
53036
+ "max_steps",
53037
+ "max_tokens_exceeded",
53038
+ "context_window_overflow_in_system_prompt",
53039
+ "end_turn",
53040
+ "tool_rule",
53041
+ "no_tool_call"
53042
+ ];
53043
+ if (nonRetriableReasons.includes(stopReason)) {} else if (lastRunId && llmApiErrorRetries < LLM_API_ERROR_MAX_RETRIES) {
53016
53044
  try {
53017
53045
  const run = await client.runs.retrieve(lastRunId);
53018
53046
  const metaError = run.metadata?.error;
@@ -53026,7 +53054,7 @@ async function handleHeadlessCommand(argv, model, skillsDirectory) {
53026
53054
  "api_error",
53027
53055
  "Network error"
53028
53056
  ];
53029
- const isLlmErrorFromDetail = errorType === "internal_error" && llmProviderPatterns.some((pattern) => detail.includes(pattern));
53057
+ const isLlmErrorFromDetail = llmProviderPatterns.some((pattern) => detail.includes(pattern));
53030
53058
  if (errorType === "llm_error" || isLlmErrorFromDetail) {
53031
53059
  const attempt = llmApiErrorRetries + 1;
53032
53060
  const baseDelayMs = 1000;
@@ -57518,7 +57546,10 @@ var init_BlinkDot = __esm(async () => {
57518
57546
  var import_react35, jsx_dev_runtime15, COLLAPSED_LINES = 3, PREFIX_WIDTH = 5, CollapsedOutputDisplay;
57519
57547
  var init_CollapsedOutputDisplay = __esm(async () => {
57520
57548
  init_useTerminalWidth();
57521
- await init_build2();
57549
+ await __promiseAll([
57550
+ init_build2(),
57551
+ init_MarkdownDisplay()
57552
+ ]);
57522
57553
  import_react35 = __toESM(require_react(), 1);
57523
57554
  jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
57524
57555
  CollapsedOutputDisplay = import_react35.memo(({ output }) => {
@@ -57550,9 +57581,8 @@ var init_CollapsedOutputDisplay = __esm(async () => {
57550
57581
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
57551
57582
  flexGrow: 1,
57552
57583
  width: contentWidth,
57553
- children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
57554
- wrap: "wrap",
57555
- children: visibleLines[0]
57584
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(MarkdownDisplay, {
57585
+ text: visibleLines[0] ?? ""
57556
57586
  }, undefined, false, undefined, this)
57557
57587
  }, undefined, false, undefined, this)
57558
57588
  ]
@@ -57570,9 +57600,8 @@ var init_CollapsedOutputDisplay = __esm(async () => {
57570
57600
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
57571
57601
  flexGrow: 1,
57572
57602
  width: contentWidth,
57573
- children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
57574
- wrap: "wrap",
57575
- children: line
57603
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(MarkdownDisplay, {
57604
+ text: line
57576
57605
  }, undefined, false, undefined, this)
57577
57606
  }, undefined, false, undefined, this)
57578
57607
  ]
@@ -59312,14 +59341,14 @@ Location: ${keybindingsPath}`;
59312
59341
  }
59313
59342
  },
59314
59343
  "/connect": {
59315
- desc: "Connect an existing Claude account (/connect claude)",
59344
+ desc: "Connect an existing account (/connect zai <api-key>)",
59316
59345
  order: 40,
59317
59346
  handler: () => {
59318
- return "Initiating OAuth connection...";
59347
+ return "Initiating account connection...";
59319
59348
  }
59320
59349
  },
59321
59350
  "/disconnect": {
59322
- desc: "Disconnect from Claude OAuth",
59351
+ desc: "Disconnect an existing account (/disconnect zai)",
59323
59352
  order: 41,
59324
59353
  handler: () => {
59325
59354
  return "Disconnecting...";
@@ -69041,6 +69070,7 @@ var init_StaticPlanApproval = __esm(async () => {
69041
69070
  onApprove,
69042
69071
  onApproveAndAcceptEdits,
69043
69072
  onKeepPlanning,
69073
+ onCancel,
69044
69074
  isFocused = true
69045
69075
  }) => {
69046
69076
  const [selectedOption, setSelectedOption] = import_react71.useState(0);
@@ -69060,7 +69090,7 @@ var init_StaticPlanApproval = __esm(async () => {
69060
69090
  if (!isFocused)
69061
69091
  return;
69062
69092
  if (key.ctrl && input === "c") {
69063
- onKeepPlanning("User pressed CTRL-C to cancel");
69093
+ onCancel();
69064
69094
  return;
69065
69095
  }
69066
69096
  if (key.upArrow) {
@@ -72182,10 +72212,86 @@ var init_useSyncedState = __esm(() => {
72182
72212
  import_react81 = __toESM(require_react(), 1);
72183
72213
  });
72184
72214
 
72215
+ // src/providers/zai-provider.ts
72216
+ async function getLettaConfig2() {
72217
+ const settings = await settingsManager.getSettingsWithSecureTokens();
72218
+ const baseUrl = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
72219
+ const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY || "";
72220
+ return { baseUrl, apiKey };
72221
+ }
72222
+ async function providersRequest2(method, path20, body) {
72223
+ const { baseUrl, apiKey } = await getLettaConfig2();
72224
+ const url = `${baseUrl}${path20}`;
72225
+ const response = await fetch(url, {
72226
+ method,
72227
+ headers: {
72228
+ "Content-Type": "application/json",
72229
+ Authorization: `Bearer ${apiKey}`,
72230
+ "X-Letta-Source": "letta-code"
72231
+ },
72232
+ ...body && { body: JSON.stringify(body) }
72233
+ });
72234
+ if (!response.ok) {
72235
+ const errorText = await response.text();
72236
+ throw new Error(`Provider API error (${response.status}): ${errorText}`);
72237
+ }
72238
+ const text = await response.text();
72239
+ if (!text) {
72240
+ return {};
72241
+ }
72242
+ return JSON.parse(text);
72243
+ }
72244
+ async function listProviders2() {
72245
+ try {
72246
+ const response = await providersRequest2("GET", "/v1/providers");
72247
+ return response;
72248
+ } catch {
72249
+ return [];
72250
+ }
72251
+ }
72252
+ async function getZaiProvider() {
72253
+ const providers = await listProviders2();
72254
+ return providers.find((p) => p.name === ZAI_PROVIDER_NAME) || null;
72255
+ }
72256
+ async function createZaiProvider(apiKey) {
72257
+ return providersRequest2("POST", "/v1/providers", {
72258
+ name: ZAI_PROVIDER_NAME,
72259
+ provider_type: "zai",
72260
+ api_key: apiKey
72261
+ });
72262
+ }
72263
+ async function updateZaiProvider(providerId, apiKey) {
72264
+ return providersRequest2("PATCH", `/v1/providers/${providerId}`, {
72265
+ api_key: apiKey
72266
+ });
72267
+ }
72268
+ async function createOrUpdateZaiProvider(apiKey) {
72269
+ const existing = await getZaiProvider();
72270
+ if (existing) {
72271
+ return updateZaiProvider(existing.id, apiKey);
72272
+ }
72273
+ return createZaiProvider(apiKey);
72274
+ }
72275
+ async function deleteZaiProvider(providerId) {
72276
+ await providersRequest2("DELETE", `/v1/providers/${providerId}`);
72277
+ }
72278
+ async function removeZaiProvider() {
72279
+ const existing = await getZaiProvider();
72280
+ if (existing) {
72281
+ await deleteZaiProvider(existing.id);
72282
+ }
72283
+ }
72284
+ var ZAI_PROVIDER_NAME = "zai-coding-plan";
72285
+ var init_zai_provider = __esm(async () => {
72286
+ init_oauth();
72287
+ await init_settings_manager();
72288
+ });
72289
+
72185
72290
  // src/cli/commands/connect.ts
72186
72291
  var exports_connect = {};
72187
72292
  __export(exports_connect, {
72188
72293
  handleDisconnect: () => handleDisconnect,
72294
+ handleConnectZai: () => handleConnectZai,
72189
72295
  handleConnect: () => handleConnect
72190
72296
  });
72191
72297
  function uid3(prefix) {
@@ -72223,16 +72329,22 @@ async function handleConnect(ctx, msg) {
72223
72329
  const provider = parts[1]?.toLowerCase();
72224
72330
  const authCode = parts.slice(2).join("");
72225
72331
  if (!provider) {
72226
- addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect claude
72332
+ addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect <provider> [options]
72227
72333
 
72228
- Connect to Claude via OAuth to authenticate without an API key.`, false);
72334
+ Available providers:
72335
+ • claude - Connect via OAuth to authenticate without an API key
72336
+ • zai <api_key> - Connect to Zai with your API key`, false);
72229
72337
  return;
72230
72338
  }
72231
- if (provider !== "claude") {
72339
+ if (provider !== "claude" && provider !== "zai") {
72232
72340
  addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Error: Unknown provider "${provider}"
72233
72341
 
72234
- Currently only 'claude' provider is supported.
72235
- Usage: /connect claude`, false);
72342
+ Available providers: claude, zai
72343
+ Usage: /connect <provider> [options]`, false);
72344
+ return;
72345
+ }
72346
+ if (provider === "zai") {
72347
+ await handleConnectZai(ctx, msg);
72236
72348
  return;
72237
72349
  }
72238
72350
  if (authCode && authCode.length > 0) {
@@ -72352,13 +72464,26 @@ If you have an Anthropic API key, you can use it directly by setting:
72352
72464
  async function handleDisconnect(ctx, msg) {
72353
72465
  const parts = msg.trim().split(/\s+/);
72354
72466
  const provider = parts[1]?.toLowerCase();
72355
- if (provider && provider !== "claude") {
72356
- addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Error: Unknown provider "${provider}"
72467
+ if (!provider) {
72468
+ addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /disconnect <provider>
72357
72469
 
72358
- Currently only 'claude' provider is supported.
72359
- Usage: /disconnect`, false);
72470
+ Available providers: claude, zai`, false);
72471
+ return;
72472
+ }
72473
+ if (provider === "zai") {
72474
+ await handleDisconnectZai(ctx, msg);
72360
72475
  return;
72361
72476
  }
72477
+ if (provider === "claude") {
72478
+ await handleDisconnectClaude(ctx, msg);
72479
+ return;
72480
+ }
72481
+ addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Error: Unknown provider "${provider}"
72482
+
72483
+ Available providers: claude, zai
72484
+ Usage: /disconnect <provider>`, false);
72485
+ }
72486
+ async function handleDisconnectClaude(ctx, msg) {
72362
72487
  if (!settingsManager.hasAnthropicOAuth()) {
72363
72488
  addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Not currently connected to Claude via OAuth.
72364
72489
 
@@ -72383,10 +72508,58 @@ Your local OAuth tokens have been removed.`, true, "finished");
72383
72508
  ctx.setCommandRunning(false);
72384
72509
  }
72385
72510
  }
72511
+ async function handleDisconnectZai(ctx, msg) {
72512
+ const existing = await getZaiProvider();
72513
+ if (!existing) {
72514
+ addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Not currently connected to Zai.
72515
+
72516
+ Use /connect zai <api_key> to connect.`, false);
72517
+ return;
72518
+ }
72519
+ const cmdId = addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, "Disconnecting from Zai...", true, "running");
72520
+ ctx.setCommandRunning(true);
72521
+ try {
72522
+ await removeZaiProvider();
72523
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✓ Disconnected from Zai.
72524
+
72525
+ ` + `Provider '${ZAI_PROVIDER_NAME}' removed from Letta.`, true, "finished");
72526
+ } catch (error) {
72527
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to disconnect from Zai: ${getErrorMessage(error)}`, false, "finished");
72528
+ } finally {
72529
+ ctx.setCommandRunning(false);
72530
+ }
72531
+ }
72532
+ async function handleConnectZai(ctx, msg) {
72533
+ const parts = msg.trim().split(/\s+/);
72534
+ const apiKey = parts.slice(2).join("");
72535
+ if (!apiKey || apiKey.length === 0) {
72536
+ addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, `Usage: /connect zai <api_key>
72537
+
72538
+ Connect to Zai by providing your API key.
72539
+
72540
+ Example: /connect zai <api_key>...`, false);
72541
+ return;
72542
+ }
72543
+ const cmdId = addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, "Creating Zai coding plan provider...", true, "running");
72544
+ ctx.setCommandRunning(true);
72545
+ try {
72546
+ await createOrUpdateZaiProvider(apiKey);
72547
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✓ Successfully connected to Zai!
72548
+
72549
+ ` + `Provider '${ZAI_PROVIDER_NAME}' created in Letta.
72550
+
72551
+ ` + `The models are populated in /model → "All Available Models"`, true, "finished");
72552
+ } catch (error) {
72553
+ updateCommandResult3(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `✗ Failed to create Zai provider: ${getErrorMessage(error)}`, false, "finished");
72554
+ } finally {
72555
+ ctx.setCommandRunning(false);
72556
+ }
72557
+ }
72386
72558
  var init_connect = __esm(async () => {
72387
72559
  init_anthropic_oauth();
72388
72560
  await __promiseAll([
72389
72561
  init_anthropic_provider(),
72562
+ init_zai_provider(),
72390
72563
  init_settings_manager()
72391
72564
  ]);
72392
72565
  });
@@ -72578,7 +72751,19 @@ function sendDesktopNotification() {
72578
72751
  async function isRetriableError(stopReason, lastRunId) {
72579
72752
  if (stopReason === "llm_api_error")
72580
72753
  return true;
72581
- if (stopReason === "error" && lastRunId) {
72754
+ const nonRetriableReasons = [
72755
+ "cancelled",
72756
+ "requires_approval",
72757
+ "max_steps",
72758
+ "max_tokens_exceeded",
72759
+ "context_window_overflow_in_system_prompt",
72760
+ "end_turn",
72761
+ "tool_rule",
72762
+ "no_tool_call"
72763
+ ];
72764
+ if (nonRetriableReasons.includes(stopReason))
72765
+ return false;
72766
+ if (lastRunId) {
72582
72767
  try {
72583
72768
  const client = await getClient2();
72584
72769
  const run = await client.runs.retrieve(lastRunId);
@@ -72595,7 +72780,7 @@ async function isRetriableError(stopReason, lastRunId) {
72595
72780
  "api_error",
72596
72781
  "Network error"
72597
72782
  ];
72598
- if (errorType === "internal_error" && llmProviderPatterns.some((pattern) => detail.includes(pattern))) {
72783
+ if (llmProviderPatterns.some((pattern) => detail.includes(pattern))) {
72599
72784
  return true;
72600
72785
  }
72601
72786
  return false;
@@ -74510,6 +74695,15 @@ ${newState.originalPrompt}`
74510
74695
  const parts = msg.trim().split(/\s+/);
74511
74696
  const provider = parts[1]?.toLowerCase();
74512
74697
  const hasCode = parts.length > 2;
74698
+ if (provider === "zai") {
74699
+ const { handleConnectZai: handleConnectZai2 } = await init_connect().then(() => exports_connect);
74700
+ await handleConnectZai2({
74701
+ buffersRef,
74702
+ refreshDerived,
74703
+ setCommandRunning
74704
+ }, msg);
74705
+ return { submitted: true };
74706
+ }
74513
74707
  if (provider === "claude" && !hasCode) {
74514
74708
  setActiveOverlay("oauth");
74515
74709
  return { submitted: true };
@@ -76551,14 +76745,47 @@ Consider switching to a different system prompt using /system to match.` : null;
76551
76745
  import_react82.useEffect(() => {
76552
76746
  const currentIndex = approvalResults.length;
76553
76747
  const approval = pendingApprovals[currentIndex];
76554
- if (approval?.toolName === "ExitPlanMode" && !planFileExists()) {
76555
- const planFilePath = permissionMode2.getPlanFilePath();
76556
- const plansDir = join20(homedir11(), ".letta", "plans");
76557
- handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
76748
+ if (approval?.toolName === "ExitPlanMode") {
76749
+ if (permissionMode2.getMode() !== "plan") {
76750
+ const statusId = uid4("status");
76751
+ buffersRef.current.byId.set(statusId, {
76752
+ kind: "status",
76753
+ id: statusId,
76754
+ lines: ["⚠️ Plan mode session expired (use /plan to re-enter)"]
76755
+ });
76756
+ buffersRef.current.order.push(statusId);
76757
+ const denialResults = [
76758
+ {
76759
+ type: "approval",
76760
+ tool_call_id: approval.toolCallId,
76761
+ approve: false,
76762
+ reason: "Plan mode session expired (CLI restarted). Use EnterPlanMode to re-enter plan mode, or request the user to re-enter plan mode."
76763
+ }
76764
+ ];
76765
+ setQueuedApprovalResults(denialResults);
76766
+ markIncompleteToolsAsCancelled(buffersRef.current);
76767
+ refreshDerived();
76768
+ setPendingApprovals([]);
76769
+ setApprovalContexts([]);
76770
+ setApprovalResults([]);
76771
+ setAutoHandledResults([]);
76772
+ setAutoDeniedApprovals([]);
76773
+ return;
76774
+ }
76775
+ if (!planFileExists()) {
76776
+ const planFilePath = permissionMode2.getPlanFilePath();
76777
+ const plansDir = join20(homedir11(), ".letta", "plans");
76778
+ handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
76558
76779
  ` + (planFilePath ? `Plan file path: ${planFilePath}
76559
76780
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
76781
+ }
76560
76782
  }
76561
- }, [pendingApprovals, approvalResults.length, handlePlanKeepPlanning]);
76783
+ }, [
76784
+ pendingApprovals,
76785
+ approvalResults.length,
76786
+ handlePlanKeepPlanning,
76787
+ refreshDerived
76788
+ ]);
76562
76789
  const handleQuestionSubmit = import_react82.useCallback(async (answers) => {
76563
76790
  const currentIndex = approvalResults.length;
76564
76791
  const approval = pendingApprovals[currentIndex];
@@ -76588,6 +76815,9 @@ Consider switching to a different system prompt using /system to match.` : null;
76588
76815
  });
76589
76816
  setThinkingMessage(getRandomThinkingVerb());
76590
76817
  refreshDerived();
76818
+ if (approval.toolCallId) {
76819
+ eagerCommittedPreviewsRef.current.add(approval.toolCallId);
76820
+ }
76591
76821
  const decision = {
76592
76822
  type: "approve",
76593
76823
  approval,
@@ -76761,11 +76991,13 @@ Plan file path: ${planFilePath}`;
76761
76991
  });
76762
76992
  buffersRef.current.order.push(statusId);
76763
76993
  refreshDerived();
76994
+ commitEligibleLines(buffersRef.current);
76764
76995
  }
76765
76996
  }, [
76766
76997
  loadingState,
76767
76998
  continueSession,
76768
76999
  messageHistory.length,
77000
+ commitEligibleLines,
76769
77001
  columns,
76770
77002
  agentProvenance,
76771
77003
  agentState,
@@ -76921,6 +77153,7 @@ Plan file path: ${planFilePath}`;
76921
77153
  onApprove: () => handlePlanApprove(false),
76922
77154
  onApproveAndAcceptEdits: () => handlePlanApprove(true),
76923
77155
  onKeepPlanning: handlePlanKeepPlanning,
77156
+ onCancel: handleCancelApprovals,
76924
77157
  isFocused: true
76925
77158
  }, undefined, false, undefined, this) : isFileEditApproval && fileEditInfo ? /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(InlineFileEditApproval, {
76926
77159
  fileEdit: fileEditInfo,
@@ -77000,6 +77233,20 @@ Plan file path: ${planFilePath}`;
77000
77233
  }, ln.id, false, undefined, this);
77001
77234
  })
77002
77235
  }, undefined, false, undefined, this),
77236
+ liveItems.length === 0 && currentApproval && /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(Box_default, {
77237
+ flexDirection: "column",
77238
+ children: /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(InlineGenericApproval, {
77239
+ toolName: currentApproval.toolName,
77240
+ toolArgs: currentApproval.toolArgs,
77241
+ onApprove: () => handleApproveCurrent(),
77242
+ onApproveAlways: (scope) => handleApproveAlways(scope),
77243
+ onDeny: (reason) => handleDenyCurrent(reason),
77244
+ onCancel: handleCancelApprovals,
77245
+ isFocused: true,
77246
+ approveAlwaysText: currentApprovalContext?.approveAlwaysText,
77247
+ allowPersistence: currentApprovalContext?.allowPersistence ?? true
77248
+ }, undefined, false, undefined, this)
77249
+ }, undefined, false, undefined, this),
77003
77250
  /* @__PURE__ */ jsx_dev_runtime59.jsxDEV(SubagentGroupDisplay, {}, undefined, false, undefined, this)
77004
77251
  ]
77005
77252
  }, undefined, true, undefined, this),
@@ -78158,6 +78405,10 @@ import { parseArgs as parseArgs2 } from "util";
78158
78405
 
78159
78406
  // src/agent/check-approval.ts
78160
78407
  var MESSAGE_HISTORY_LIMIT = 15;
78408
+ function isBackfillEnabled() {
78409
+ const val = process.env.LETTA_BACKFILL;
78410
+ return val !== "0" && val !== "false";
78411
+ }
78161
78412
  async function getResumeData(client, agent) {
78162
78413
  try {
78163
78414
  const messagesPage = await client.agents.messages.list(agent.id);
@@ -78180,6 +78431,13 @@ async function getResumeData(client, agent) {
78180
78431
  const inContextLastMessageId = agent.message_ids && agent.message_ids.length > 0 ? agent.message_ids[agent.message_ids.length - 1] : null;
78181
78432
  if (!inContextLastMessageId) {
78182
78433
  debugWarn("check-approval", `No in-context messages (message_ids empty/null) - no pending approvals`);
78434
+ if (!isBackfillEnabled()) {
78435
+ return {
78436
+ pendingApproval: null,
78437
+ pendingApprovals: [],
78438
+ messageHistory: []
78439
+ };
78440
+ }
78183
78441
  const historyCount2 = Math.min(MESSAGE_HISTORY_LIMIT, messages.length);
78184
78442
  let messageHistory2 = messages.slice(-historyCount2);
78185
78443
  if (messageHistory2[0]?.message_type === "tool_return_message") {
@@ -78230,6 +78488,9 @@ async function getResumeData(client, agent) {
78230
78488
  }
78231
78489
  }
78232
78490
  }
78491
+ if (!isBackfillEnabled()) {
78492
+ return { pendingApproval, pendingApprovals, messageHistory: [] };
78493
+ }
78233
78494
  const historyCount = Math.min(MESSAGE_HISTORY_LIMIT, messages.length);
78234
78495
  let messageHistory = messages.slice(-historyCount);
78235
78496
  if (messageHistory[0]?.message_type === "tool_return_message") {
@@ -80638,4 +80899,4 @@ Error during initialization: ${message}`);
80638
80899
  }
80639
80900
  main();
80640
80901
 
80641
- //# debugId=8F40442B5CEE87AA64756E2164756E21
80902
+ //# debugId=C1C8E8CD6D145E1A64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.12.7",
3
+ "version": "0.12.8",
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": {