@letta-ai/letta-code 0.10.1 → 0.10.2

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
@@ -3233,7 +3233,7 @@ var package_default;
3233
3233
  var init_package = __esm(() => {
3234
3234
  package_default = {
3235
3235
  name: "@letta-ai/letta-code",
3236
- version: "0.10.1",
3236
+ version: "0.10.2",
3237
3237
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3238
3238
  type: "module",
3239
3239
  bin: {
@@ -3285,7 +3285,7 @@ var init_package = __esm(() => {
3285
3285
  typecheck: "tsc --noEmit",
3286
3286
  check: "bun run scripts/check.js",
3287
3287
  dev: "bun --loader:.md=text --loader:.mdx=text --loader:.txt=text run src/index.ts",
3288
- build: "bun run build.js",
3288
+ build: "node scripts/postinstall-patches.js && bun run build.js",
3289
3289
  prepare: "bun run build",
3290
3290
  postinstall: "node scripts/postinstall-patches.js"
3291
3291
  },
@@ -51370,6 +51370,104 @@ var init_headless = __esm(() => {
51370
51370
  init_manager3();
51371
51371
  });
51372
51372
 
51373
+ // src/cli/utils/kittyProtocolDetector.ts
51374
+ var exports_kittyProtocolDetector = {};
51375
+ __export(exports_kittyProtocolDetector, {
51376
+ isKittyProtocolEnabled: () => isKittyProtocolEnabled,
51377
+ detectAndEnableKittyProtocol: () => detectAndEnableKittyProtocol
51378
+ });
51379
+ import * as fs14 from "node:fs";
51380
+ async function detectAndEnableKittyProtocol() {
51381
+ if (detectionComplete) {
51382
+ return;
51383
+ }
51384
+ return new Promise((resolve16) => {
51385
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
51386
+ detectionComplete = true;
51387
+ resolve16();
51388
+ return;
51389
+ }
51390
+ const originalRawMode = process.stdin.isRaw;
51391
+ if (!originalRawMode) {
51392
+ process.stdin.setRawMode(true);
51393
+ }
51394
+ let responseBuffer = "";
51395
+ let progressiveEnhancementReceived = false;
51396
+ let timeoutId;
51397
+ const finish = () => {
51398
+ if (timeoutId !== undefined) {
51399
+ clearTimeout(timeoutId);
51400
+ timeoutId = undefined;
51401
+ }
51402
+ process.stdin.removeListener("data", handleData);
51403
+ if (!originalRawMode) {
51404
+ process.stdin.setRawMode(false);
51405
+ }
51406
+ if (progressiveEnhancementReceived)
51407
+ kittySupported = true;
51408
+ if (process.stdout.isTTY) {
51409
+ if (DEBUG2) {
51410
+ console.error("[kitty] enabling protocol");
51411
+ }
51412
+ enableKittyKeyboardProtocol();
51413
+ process.on("exit", disableKittyKeyboardProtocol);
51414
+ process.on("SIGTERM", disableKittyKeyboardProtocol);
51415
+ process.on("SIGINT", disableKittyKeyboardProtocol);
51416
+ } else if (DEBUG2 && !kittySupported) {
51417
+ console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
51418
+ }
51419
+ detectionComplete = true;
51420
+ resolve16();
51421
+ };
51422
+ const handleData = (data) => {
51423
+ if (timeoutId === undefined) {
51424
+ return;
51425
+ }
51426
+ responseBuffer += data.toString();
51427
+ if (DEBUG2) {
51428
+ console.error("[kitty] rx:", JSON.stringify(data.toString()));
51429
+ }
51430
+ if (responseBuffer.includes("\x1B[?") && responseBuffer.includes("u")) {
51431
+ progressiveEnhancementReceived = true;
51432
+ clearTimeout(timeoutId);
51433
+ timeoutId = setTimeout(finish, 1000);
51434
+ }
51435
+ if (responseBuffer.includes("\x1B[?") && responseBuffer.includes("c")) {
51436
+ if (progressiveEnhancementReceived)
51437
+ kittySupported = true;
51438
+ finish();
51439
+ }
51440
+ };
51441
+ process.stdin.on("data", handleData);
51442
+ if (DEBUG2) {
51443
+ console.error("[kitty] querying support");
51444
+ }
51445
+ fs14.writeSync(process.stdout.fd, "\x1B[?u\x1B[c");
51446
+ timeoutId = setTimeout(finish, 200);
51447
+ });
51448
+ }
51449
+ function isKittyProtocolEnabled() {
51450
+ return kittyEnabled;
51451
+ }
51452
+ function enableKittyKeyboardProtocol() {
51453
+ try {
51454
+ fs14.writeSync(process.stdout.fd, "\x1B[>7u");
51455
+ kittyEnabled = true;
51456
+ } catch {}
51457
+ }
51458
+ function disableKittyKeyboardProtocol() {
51459
+ try {
51460
+ if (kittyEnabled) {
51461
+ fs14.writeSync(process.stdout.fd, "\x1B[<u");
51462
+ kittyEnabled = false;
51463
+ }
51464
+ } catch {}
51465
+ }
51466
+ var detectionComplete = false, kittySupported = false, kittyEnabled = false, DEBUG2;
51467
+ var init_kittyProtocolDetector = __esm(() => {
51468
+ DEBUG2 = process.env.LETTA_DEBUG_KITTY === "1";
51469
+ });
51470
+
51373
51471
  // node_modules/react/index.js
51374
51472
  var require_react2 = __commonJS((exports, module) => {
51375
51473
  var react_development = __toESM(require_react_development(), 1);
@@ -51498,7 +51596,55 @@ var init_available_models = __esm(() => {
51498
51596
  });
51499
51597
 
51500
51598
  // src/settings.ts
51599
+ var exports_settings = {};
51600
+ __export(exports_settings, {
51601
+ updateSettings: () => updateSettings,
51602
+ updateProjectSettings: () => updateProjectSettings,
51603
+ saveSettings: () => saveSettings,
51604
+ saveProjectSettings: () => saveProjectSettings,
51605
+ loadSettings: () => loadSettings,
51606
+ loadProjectSettings: () => loadProjectSettings,
51607
+ getSetting: () => getSetting
51608
+ });
51609
+ import { homedir as homedir6 } from "node:os";
51501
51610
  import { join as join13 } from "node:path";
51611
+ function getSettingsPath() {
51612
+ return join13(homedir6(), ".letta", "settings.json");
51613
+ }
51614
+ async function loadSettings() {
51615
+ const settingsPath = getSettingsPath();
51616
+ try {
51617
+ if (!exists(settingsPath)) {
51618
+ await saveSettings(DEFAULT_SETTINGS3);
51619
+ return DEFAULT_SETTINGS3;
51620
+ }
51621
+ const content = await readFile(settingsPath);
51622
+ const settings = JSON.parse(content);
51623
+ return { ...DEFAULT_SETTINGS3, ...settings };
51624
+ } catch (error) {
51625
+ console.error("Error loading settings, using defaults:", error);
51626
+ return DEFAULT_SETTINGS3;
51627
+ }
51628
+ }
51629
+ async function saveSettings(settings) {
51630
+ const settingsPath = getSettingsPath();
51631
+ try {
51632
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2));
51633
+ } catch (error) {
51634
+ console.error("Error saving settings:", error);
51635
+ throw error;
51636
+ }
51637
+ }
51638
+ async function updateSettings(updates) {
51639
+ const currentSettings = await loadSettings();
51640
+ const newSettings = { ...currentSettings, ...updates };
51641
+ await saveSettings(newSettings);
51642
+ return newSettings;
51643
+ }
51644
+ async function getSetting(key) {
51645
+ const settings = await loadSettings();
51646
+ return settings[key];
51647
+ }
51502
51648
  function getProjectSettingsPath() {
51503
51649
  return join13(process.cwd(), ".letta", "settings.local.json");
51504
51650
  }
@@ -51535,8 +51681,14 @@ async function updateProjectSettings(updates) {
51535
51681
  await saveProjectSettings(newSettings);
51536
51682
  return newSettings;
51537
51683
  }
51684
+ var DEFAULT_SETTINGS3;
51538
51685
  var init_settings = __esm(() => {
51539
51686
  init_fs();
51687
+ DEFAULT_SETTINGS3 = {
51688
+ lastAgent: null,
51689
+ tokenStreaming: false,
51690
+ globalSharedBlockIds: {}
51691
+ };
51540
51692
  });
51541
51693
 
51542
51694
  // src/cli/commands/mcp.ts
@@ -54379,6 +54531,8 @@ function isControlSequence(input, key) {
54379
54531
  return true;
54380
54532
  if (key.shift && key.tab)
54381
54533
  return true;
54534
+ if (key.return && (key.shift || key.meta || key.ctrl))
54535
+ return true;
54382
54536
  if (key.ctrl && (input === "w" || input === "W"))
54383
54537
  return true;
54384
54538
  if (key.ctrl && input && /^[a-z]$/i.test(input) && !["a", "e", "k", "u", "y"].includes(input.toLowerCase()))
@@ -54387,6 +54541,9 @@ function isControlSequence(input, key) {
54387
54541
  return true;
54388
54542
  if (input && typeof input === "string" && input.startsWith("\x1B") && input.length > 1)
54389
54543
  return true;
54544
+ if (key.delete && globalThis.__lettaForwardDeleteTimestamp && Date.now() - globalThis.__lettaForwardDeleteTimestamp < 100) {
54545
+ return true;
54546
+ }
54390
54547
  return false;
54391
54548
  }
54392
54549
  function TextInput({ value: originalValue, placeholder = "", focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit, externalCursorOffset, onCursorOffsetChange }) {
@@ -54736,6 +54893,33 @@ function PasteAwareTextInput({
54736
54893
  }
54737
54894
  }, [value]);
54738
54895
  use_input_default((input, key) => {
54896
+ if (key.return && (key.shift || key.meta || key.ctrl)) {
54897
+ const at = Math.max(0, Math.min(caretOffsetRef.current, displayValueRef.current.length));
54898
+ const newValue = displayValueRef.current.slice(0, at) + `
54899
+ ` + displayValueRef.current.slice(at);
54900
+ setDisplayValue(newValue);
54901
+ setActualValue(newValue);
54902
+ onChangeRef.current(newValue);
54903
+ const nextCaret = at + 1;
54904
+ setNudgeCursorOffset(nextCaret);
54905
+ caretOffsetRef.current = nextCaret;
54906
+ return;
54907
+ }
54908
+ if (key.ctrl && input === "v") {
54909
+ const clip = tryImportClipboardImageMac();
54910
+ if (clip) {
54911
+ const at = Math.max(0, Math.min(caretOffsetRef.current, displayValueRef.current.length));
54912
+ const newDisplay = displayValueRef.current.slice(0, at) + clip + displayValueRef.current.slice(at);
54913
+ displayValueRef.current = newDisplay;
54914
+ setDisplayValue(newDisplay);
54915
+ setActualValue(newDisplay);
54916
+ onChangeRef.current(newDisplay);
54917
+ const nextCaret = at + clip.length;
54918
+ setNudgeCursorOffset(nextCaret);
54919
+ caretOffsetRef.current = nextCaret;
54920
+ }
54921
+ return;
54922
+ }
54739
54923
  const isPasted = key?.isPasted;
54740
54924
  if (isPasted) {
54741
54925
  lastPasteDetectedAtRef.current = Date.now();
@@ -54827,6 +55011,29 @@ function PasteAwareTextInput({
54827
55011
  setNudgeCursorOffset(wordStart);
54828
55012
  caretOffsetRef.current = wordStart;
54829
55013
  };
55014
+ const forwardDeleteAtCursor = (cursorPos) => {
55015
+ if (cursorPos >= displayValueRef.current.length)
55016
+ return;
55017
+ const newDisplay = displayValueRef.current.slice(0, cursorPos) + displayValueRef.current.slice(cursorPos + 1);
55018
+ const resolvedActual = resolvePlaceholders(newDisplay);
55019
+ displayValueRef.current = newDisplay;
55020
+ caretOffsetRef.current = cursorPos;
55021
+ setDisplayValue(newDisplay);
55022
+ setActualValue(resolvedActual);
55023
+ onChangeRef.current(newDisplay);
55024
+ setNudgeCursorOffset(cursorPos);
55025
+ };
55026
+ const insertNewlineAtCursor = () => {
55027
+ const at = Math.max(0, Math.min(caretOffsetRef.current, displayValueRef.current.length));
55028
+ const newValue = displayValueRef.current.slice(0, at) + `
55029
+ ` + displayValueRef.current.slice(at);
55030
+ setDisplayValue(newValue);
55031
+ setActualValue(newValue);
55032
+ onChangeRef.current(newValue);
55033
+ const nextCaret = at + 1;
55034
+ setNudgeCursorOffset(nextCaret);
55035
+ caretOffsetRef.current = nextCaret;
55036
+ };
54830
55037
  const handleRawInput = (payload) => {
54831
55038
  if (!focusRef.current)
54832
55039
  return;
@@ -54838,6 +55045,72 @@ function PasteAwareTextInput({
54838
55045
  }
54839
55046
  if (!sequence)
54840
55047
  return;
55048
+ if (process.env.LETTA_DEBUG_INPUT === "1") {
55049
+ const debugHex = [...sequence].map((c) => `0x${c.charCodeAt(0).toString(16).padStart(2, "0")}`).join(" ");
55050
+ console.error(`[debug:raw-input] len=${sequence.length} hex: ${debugHex}`);
55051
+ }
55052
+ if (sequence === "\x1B\r" || sequence === `\x1B
55053
+ `) {
55054
+ insertNewlineAtCursor();
55055
+ return;
55056
+ }
55057
+ if (sequence === "\\r") {
55058
+ insertNewlineAtCursor();
55059
+ return;
55060
+ }
55061
+ {
55062
+ const prefix = "\x1B[13;";
55063
+ if (sequence.startsWith(prefix) && sequence.endsWith("u")) {
55064
+ const mod = sequence.slice(prefix.length, -1);
55065
+ if (mod.length === 1 && mod >= "2" && mod <= "8") {
55066
+ insertNewlineAtCursor();
55067
+ return;
55068
+ }
55069
+ }
55070
+ }
55071
+ if (sequence === "\x1B[99;5u") {
55072
+ internal_eventEmitter.emit("input", "\x03");
55073
+ return;
55074
+ }
55075
+ if (sequence.startsWith("\x1B[99;5:")) {
55076
+ return;
55077
+ }
55078
+ if (sequence === "\x1B[118;5u") {
55079
+ const clip = tryImportClipboardImageMac();
55080
+ if (clip) {
55081
+ const at = Math.max(0, Math.min(caretOffsetRef.current, displayValueRef.current.length));
55082
+ const newDisplay = displayValueRef.current.slice(0, at) + clip + displayValueRef.current.slice(at);
55083
+ displayValueRef.current = newDisplay;
55084
+ setDisplayValue(newDisplay);
55085
+ setActualValue(newDisplay);
55086
+ onChangeRef.current(newDisplay);
55087
+ const nextCaret = at + clip.length;
55088
+ setNudgeCursorOffset(nextCaret);
55089
+ caretOffsetRef.current = nextCaret;
55090
+ }
55091
+ return;
55092
+ }
55093
+ if (sequence.startsWith("\x1B[118;5:")) {
55094
+ return;
55095
+ }
55096
+ {
55097
+ const arrowMatch = sequence.match(/^\x1b\[1;\d+:[12]([ABCD])$/);
55098
+ if (arrowMatch) {
55099
+ internal_eventEmitter.emit("input", `\x1B[${arrowMatch[1]}`);
55100
+ return;
55101
+ }
55102
+ if (/^\x1b\[1;\d+:3[ABCD]$/.test(sequence)) {
55103
+ return;
55104
+ }
55105
+ }
55106
+ if (sequence === "\x1B[3~" || /^\x1b\[3;\d+:[12]~$/.test(sequence)) {
55107
+ globalThis.__lettaForwardDeleteTimestamp = Date.now();
55108
+ forwardDeleteAtCursor(caretOffsetRef.current);
55109
+ return;
55110
+ }
55111
+ if (/^\x1b\[3;\d+:3~$/.test(sequence)) {
55112
+ return;
55113
+ }
54841
55114
  if (sequence === "\x1B" || sequence === "\x1B\b" || sequence === "\x1B\b" || sequence === "\x17") {
54842
55115
  deletePreviousWord();
54843
55116
  return;
@@ -54919,11 +55192,11 @@ function PasteAwareTextInput({
54919
55192
  caretOffsetRef.current = nextCaret;
54920
55193
  return;
54921
55194
  }
55195
+ displayValueRef.current = newValue;
54922
55196
  setDisplayValue(newValue);
54923
55197
  const resolved = resolvePlaceholders(newValue);
54924
55198
  setActualValue(resolved);
54925
55199
  onChange(newValue);
54926
- caretOffsetRef.current = newValue.length;
54927
55200
  };
54928
55201
  const handleSubmit = () => {
54929
55202
  if (onSubmit) {
@@ -56712,6 +56985,318 @@ var init_FeedbackDialog = __esm(async () => {
56712
56985
  jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
56713
56986
  });
56714
56987
 
56988
+ // src/cli/utils/terminalKeybindingInstaller.ts
56989
+ var exports_terminalKeybindingInstaller = {};
56990
+ __export(exports_terminalKeybindingInstaller, {
56991
+ wezTermDeleteFixExists: () => wezTermDeleteFixExists,
56992
+ removeKeybindingForCurrentTerminal: () => removeKeybindingForCurrentTerminal,
56993
+ removeKeybinding: () => removeKeybinding,
56994
+ keybindingExists: () => keybindingExists,
56995
+ isWezTerm: () => isWezTerm,
56996
+ isVSCodeLikeTerminal: () => isVSCodeLikeTerminal,
56997
+ installWezTermDeleteFix: () => installWezTermDeleteFix,
56998
+ installKeybindingForCurrentTerminal: () => installKeybindingForCurrentTerminal,
56999
+ installKeybinding: () => installKeybinding,
57000
+ getWezTermConfigPath: () => getWezTermConfigPath,
57001
+ getKeybindingsPath: () => getKeybindingsPath,
57002
+ detectTerminalType: () => detectTerminalType
57003
+ });
57004
+ import {
57005
+ copyFileSync,
57006
+ existsSync as existsSync10,
57007
+ mkdirSync as mkdirSync3,
57008
+ readFileSync as readFileSync3,
57009
+ writeFileSync
57010
+ } from "node:fs";
57011
+ import { homedir as homedir7, platform as platform3 } from "node:os";
57012
+ import { dirname as dirname9, join as join14 } from "node:path";
57013
+ function detectTerminalType() {
57014
+ if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
57015
+ return "cursor";
57016
+ }
57017
+ if (process.env.WINDSURF_TRACE_ID || process.env.WINDSURF_CHANNEL) {
57018
+ return "windsurf";
57019
+ }
57020
+ const termProgram = process.env.TERM_PROGRAM?.toLowerCase();
57021
+ if (termProgram === "vscode")
57022
+ return "vscode";
57023
+ if (termProgram === "cursor")
57024
+ return "cursor";
57025
+ if (termProgram === "windsurf")
57026
+ return "windsurf";
57027
+ if (process.env.VSCODE_INJECTION === "1")
57028
+ return "vscode";
57029
+ return null;
57030
+ }
57031
+ function isVSCodeLikeTerminal() {
57032
+ return detectTerminalType() !== null;
57033
+ }
57034
+ function getKeybindingsPath(terminal) {
57035
+ if (!terminal)
57036
+ return null;
57037
+ const appName = {
57038
+ vscode: "Code",
57039
+ cursor: "Cursor",
57040
+ windsurf: "Windsurf"
57041
+ }[terminal];
57042
+ const os3 = platform3();
57043
+ if (os3 === "darwin") {
57044
+ return join14(homedir7(), "Library", "Application Support", appName, "User", "keybindings.json");
57045
+ }
57046
+ if (os3 === "win32") {
57047
+ const appData = process.env.APPDATA;
57048
+ if (!appData)
57049
+ return null;
57050
+ return join14(appData, appName, "User", "keybindings.json");
57051
+ }
57052
+ if (os3 === "linux") {
57053
+ return join14(homedir7(), ".config", appName, "User", "keybindings.json");
57054
+ }
57055
+ return null;
57056
+ }
57057
+ function stripJsonComments(jsonc) {
57058
+ let result = jsonc.replace(/\/\/.*$/gm, "");
57059
+ result = result.replace(/\/\*[\s\S]*?\*\//g, "");
57060
+ result = result.replace(/,(\s*[}\]])/g, "$1");
57061
+ return result;
57062
+ }
57063
+ function parseKeybindings(content) {
57064
+ try {
57065
+ const stripped = stripJsonComments(content);
57066
+ const parsed = JSON.parse(stripped);
57067
+ if (!Array.isArray(parsed))
57068
+ return null;
57069
+ return parsed;
57070
+ } catch {
57071
+ return null;
57072
+ }
57073
+ }
57074
+ function keybindingExists(keybindingsPath) {
57075
+ if (!existsSync10(keybindingsPath))
57076
+ return false;
57077
+ try {
57078
+ const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
57079
+ const keybindings = parseKeybindings(content);
57080
+ if (!keybindings)
57081
+ return false;
57082
+ return keybindings.some((kb) => kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus"));
57083
+ } catch {
57084
+ return false;
57085
+ }
57086
+ }
57087
+ function createBackup(keybindingsPath) {
57088
+ if (!existsSync10(keybindingsPath))
57089
+ return null;
57090
+ const backupPath = `${keybindingsPath}.letta-backup`;
57091
+ try {
57092
+ copyFileSync(keybindingsPath, backupPath);
57093
+ return backupPath;
57094
+ } catch {
57095
+ return null;
57096
+ }
57097
+ }
57098
+ function installKeybinding(keybindingsPath) {
57099
+ try {
57100
+ if (keybindingExists(keybindingsPath)) {
57101
+ return { success: true, alreadyExists: true };
57102
+ }
57103
+ const parentDir = dirname9(keybindingsPath);
57104
+ if (!existsSync10(parentDir)) {
57105
+ mkdirSync3(parentDir, { recursive: true });
57106
+ }
57107
+ let keybindings = [];
57108
+ let backupPath = null;
57109
+ if (existsSync10(keybindingsPath)) {
57110
+ backupPath = createBackup(keybindingsPath);
57111
+ const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
57112
+ const parsed = parseKeybindings(content);
57113
+ if (parsed === null) {
57114
+ return {
57115
+ success: false,
57116
+ error: `Could not parse ${keybindingsPath}. Please fix syntax errors and try again.`
57117
+ };
57118
+ }
57119
+ keybindings = parsed;
57120
+ }
57121
+ keybindings.push(SHIFT_ENTER_KEYBINDING);
57122
+ const newContent = `${JSON.stringify(keybindings, null, 2)}
57123
+ `;
57124
+ writeFileSync(keybindingsPath, newContent, { encoding: "utf-8" });
57125
+ return {
57126
+ success: true,
57127
+ backupPath: backupPath ?? undefined
57128
+ };
57129
+ } catch (error) {
57130
+ const message = error instanceof Error ? error.message : String(error);
57131
+ return {
57132
+ success: false,
57133
+ error: `Failed to install keybinding: ${message}`
57134
+ };
57135
+ }
57136
+ }
57137
+ function removeKeybinding(keybindingsPath) {
57138
+ try {
57139
+ if (!existsSync10(keybindingsPath)) {
57140
+ return { success: true };
57141
+ }
57142
+ const content = readFileSync3(keybindingsPath, { encoding: "utf-8" });
57143
+ const keybindings = parseKeybindings(content);
57144
+ if (!keybindings) {
57145
+ return {
57146
+ success: false,
57147
+ error: `Could not parse ${keybindingsPath}`
57148
+ };
57149
+ }
57150
+ const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
57151
+ const newContent = `${JSON.stringify(filtered, null, 2)}
57152
+ `;
57153
+ writeFileSync(keybindingsPath, newContent, { encoding: "utf-8" });
57154
+ return { success: true };
57155
+ } catch (error) {
57156
+ const message = error instanceof Error ? error.message : String(error);
57157
+ return {
57158
+ success: false,
57159
+ error: `Failed to remove keybinding: ${message}`
57160
+ };
57161
+ }
57162
+ }
57163
+ function installKeybindingForCurrentTerminal() {
57164
+ const terminal = detectTerminalType();
57165
+ if (!terminal) {
57166
+ return {
57167
+ success: false,
57168
+ error: "Not running in a VS Code-like terminal"
57169
+ };
57170
+ }
57171
+ const path17 = getKeybindingsPath(terminal);
57172
+ if (!path17) {
57173
+ return {
57174
+ success: false,
57175
+ error: `Could not determine keybindings.json path for ${terminal}`
57176
+ };
57177
+ }
57178
+ return installKeybinding(path17);
57179
+ }
57180
+ function removeKeybindingForCurrentTerminal() {
57181
+ const terminal = detectTerminalType();
57182
+ if (!terminal) {
57183
+ return {
57184
+ success: false,
57185
+ error: "Not running in a VS Code-like terminal"
57186
+ };
57187
+ }
57188
+ const path17 = getKeybindingsPath(terminal);
57189
+ if (!path17) {
57190
+ return {
57191
+ success: false,
57192
+ error: `Could not determine keybindings.json path for ${terminal}`
57193
+ };
57194
+ }
57195
+ return removeKeybinding(path17);
57196
+ }
57197
+ function isWezTerm() {
57198
+ return process.env.TERM_PROGRAM === "WezTerm";
57199
+ }
57200
+ function getWezTermConfigPath() {
57201
+ if (process.env.WEZTERM_CONFIG_FILE) {
57202
+ return process.env.WEZTERM_CONFIG_FILE;
57203
+ }
57204
+ const xdgConfig = process.env.XDG_CONFIG_HOME;
57205
+ if (xdgConfig) {
57206
+ const xdgPath = join14(xdgConfig, "wezterm", "wezterm.lua");
57207
+ if (existsSync10(xdgPath))
57208
+ return xdgPath;
57209
+ }
57210
+ const configPath = join14(homedir7(), ".config", "wezterm", "wezterm.lua");
57211
+ if (existsSync10(configPath))
57212
+ return configPath;
57213
+ return join14(homedir7(), ".wezterm.lua");
57214
+ }
57215
+ function wezTermDeleteFixExists(configPath) {
57216
+ if (!existsSync10(configPath))
57217
+ return false;
57218
+ try {
57219
+ const content = readFileSync3(configPath, { encoding: "utf-8" });
57220
+ return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
57221
+ } catch {
57222
+ return false;
57223
+ }
57224
+ }
57225
+ function installWezTermDeleteFix() {
57226
+ const configPath = getWezTermConfigPath();
57227
+ try {
57228
+ if (wezTermDeleteFixExists(configPath)) {
57229
+ return { success: true, alreadyExists: true };
57230
+ }
57231
+ let content = "";
57232
+ let backupPath = null;
57233
+ if (existsSync10(configPath)) {
57234
+ backupPath = `${configPath}.letta-backup`;
57235
+ copyFileSync(configPath, backupPath);
57236
+ content = readFileSync3(configPath, { encoding: "utf-8" });
57237
+ }
57238
+ if (content.includes("return {") && !content.includes("local config")) {
57239
+ content = content.replace(/return\s*\{/, "local config = {");
57240
+ if (!content.includes("return config")) {
57241
+ content = `${content.trimEnd()}
57242
+
57243
+ return config
57244
+ `;
57245
+ }
57246
+ }
57247
+ if (!content.trim()) {
57248
+ content = `-- WezTerm configuration
57249
+ local config = {}
57250
+
57251
+ return config
57252
+ `;
57253
+ }
57254
+ if (content.includes("return config")) {
57255
+ content = content.replace("return config", `${WEZTERM_DELETE_FIX}
57256
+ return config`);
57257
+ } else {
57258
+ content = `${content.trimEnd()}
57259
+ ${WEZTERM_DELETE_FIX}
57260
+ `;
57261
+ }
57262
+ const parentDir = dirname9(configPath);
57263
+ if (!existsSync10(parentDir)) {
57264
+ mkdirSync3(parentDir, { recursive: true });
57265
+ }
57266
+ writeFileSync(configPath, content, { encoding: "utf-8" });
57267
+ return {
57268
+ success: true,
57269
+ backupPath: backupPath ?? undefined
57270
+ };
57271
+ } catch (error) {
57272
+ const message = error instanceof Error ? error.message : String(error);
57273
+ return {
57274
+ success: false,
57275
+ error: `Failed to install WezTerm Delete key fix: ${message}`
57276
+ };
57277
+ }
57278
+ }
57279
+ var SHIFT_ENTER_KEYBINDING, WEZTERM_DELETE_FIX = `
57280
+ -- Letta Code: Fix Delete key sending wrong sequence with kitty keyboard protocol
57281
+ -- See: https://github.com/wez/wezterm/issues/3758
57282
+ local wezterm = require 'wezterm'
57283
+ local keys = config.keys or {}
57284
+ table.insert(keys, {
57285
+ key = 'Delete',
57286
+ mods = 'NONE',
57287
+ action = wezterm.action.SendString '\\x1b[3~',
57288
+ })
57289
+ config.keys = keys
57290
+ `;
57291
+ var init_terminalKeybindingInstaller = __esm(() => {
57292
+ SHIFT_ENTER_KEYBINDING = {
57293
+ key: "shift+enter",
57294
+ command: "workbench.action.terminal.sendSequence",
57295
+ args: { text: "\x1B\r" },
57296
+ when: "terminalFocus"
57297
+ };
57298
+ });
57299
+
56715
57300
  // src/cli/commands/registry.ts
56716
57301
  var exports_registry = {};
56717
57302
  __export(exports_registry, {
@@ -56901,6 +57486,51 @@ var init_registry = __esm(() => {
56901
57486
  return "Opening help...";
56902
57487
  }
56903
57488
  },
57489
+ "/terminal": {
57490
+ desc: "Setup terminal shortcuts [--revert]",
57491
+ order: 36,
57492
+ handler: async (args) => {
57493
+ const {
57494
+ detectTerminalType: detectTerminalType2,
57495
+ getKeybindingsPath: getKeybindingsPath2,
57496
+ installKeybinding: installKeybinding2,
57497
+ removeKeybinding: removeKeybinding2
57498
+ } = await Promise.resolve().then(() => (init_terminalKeybindingInstaller(), exports_terminalKeybindingInstaller));
57499
+ const { updateSettings: updateSettings2 } = await Promise.resolve().then(() => (init_settings(), exports_settings));
57500
+ const isRevert = args.includes("--revert") || args.includes("--remove");
57501
+ const terminal = detectTerminalType2();
57502
+ if (!terminal) {
57503
+ return "Not running in a VS Code-like terminal. Shift+Enter keybinding is not needed.";
57504
+ }
57505
+ const terminalName = {
57506
+ vscode: "VS Code",
57507
+ cursor: "Cursor",
57508
+ windsurf: "Windsurf"
57509
+ }[terminal];
57510
+ const keybindingsPath = getKeybindingsPath2(terminal);
57511
+ if (!keybindingsPath) {
57512
+ return `Could not determine keybindings.json path for ${terminalName}`;
57513
+ }
57514
+ if (isRevert) {
57515
+ const result2 = removeKeybinding2(keybindingsPath);
57516
+ if (!result2.success) {
57517
+ return `Failed to remove keybinding: ${result2.error}`;
57518
+ }
57519
+ await updateSettings2({ shiftEnterKeybindingInstalled: false });
57520
+ return `Removed Shift+Enter keybinding from ${terminalName}`;
57521
+ }
57522
+ const result = installKeybinding2(keybindingsPath);
57523
+ if (!result.success) {
57524
+ return `Failed to install keybinding: ${result.error}`;
57525
+ }
57526
+ if (result.alreadyExists) {
57527
+ return `Shift+Enter keybinding already exists in ${terminalName}`;
57528
+ }
57529
+ await updateSettings2({ shiftEnterKeybindingInstalled: true });
57530
+ return `Installed Shift+Enter keybinding for ${terminalName}
57531
+ Location: ${keybindingsPath}`;
57532
+ }
57533
+ },
56904
57534
  "/connect": {
56905
57535
  desc: "Connect an existing Claude account (/connect claude)",
56906
57536
  order: 40,
@@ -56986,9 +57616,9 @@ __export(exports_custom, {
56986
57616
  GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
56987
57617
  COMMANDS_DIR: () => COMMANDS_DIR
56988
57618
  });
56989
- import { existsSync as existsSync10 } from "node:fs";
57619
+ import { existsSync as existsSync11 } from "node:fs";
56990
57620
  import { readdir as readdir7, readFile as readFile8 } from "node:fs/promises";
56991
- import { basename as basename3, dirname as dirname9, join as join14 } from "node:path";
57621
+ import { basename as basename3, dirname as dirname10, join as join15 } from "node:path";
56992
57622
  async function getCustomCommands() {
56993
57623
  if (cachedCommands !== null) {
56994
57624
  return cachedCommands;
@@ -56999,7 +57629,7 @@ async function getCustomCommands() {
56999
57629
  function refreshCustomCommands() {
57000
57630
  cachedCommands = null;
57001
57631
  }
57002
- async function discoverCustomCommands(projectPath = join14(process.cwd(), COMMANDS_DIR)) {
57632
+ async function discoverCustomCommands(projectPath = join15(process.cwd(), COMMANDS_DIR)) {
57003
57633
  const commandsById = new Map;
57004
57634
  const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
57005
57635
  for (const cmd of userCommands) {
@@ -57020,7 +57650,7 @@ async function discoverCustomCommands(projectPath = join14(process.cwd(), COMMAN
57020
57650
  return result;
57021
57651
  }
57022
57652
  async function discoverFromDirectory(dirPath, source) {
57023
- if (!existsSync10(dirPath)) {
57653
+ if (!existsSync11(dirPath)) {
57024
57654
  return [];
57025
57655
  }
57026
57656
  const commands2 = [];
@@ -57031,7 +57661,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source) {
57031
57661
  try {
57032
57662
  const entries = await readdir7(currentPath, { withFileTypes: true });
57033
57663
  for (const entry of entries) {
57034
- const fullPath = join14(currentPath, entry.name);
57664
+ const fullPath = join15(currentPath, entry.name);
57035
57665
  if (entry.isDirectory()) {
57036
57666
  await findCommandFiles(fullPath, rootPath, commands2, source);
57037
57667
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -57049,7 +57679,7 @@ async function parseCommandFile(filePath, rootPath, source) {
57049
57679
  const content = await readFile8(filePath, "utf-8");
57050
57680
  const { frontmatter, body } = parseFrontmatter(content);
57051
57681
  const id = basename3(filePath, ".md");
57052
- const relativePath = dirname9(filePath).slice(rootPath.length);
57682
+ const relativePath = dirname10(filePath).slice(rootPath.length);
57053
57683
  const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
57054
57684
  let description = getStringField(frontmatter, "description");
57055
57685
  if (!description) {
@@ -57116,7 +57746,7 @@ async function findCustomCommand(commandName) {
57116
57746
  }
57117
57747
  var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
57118
57748
  var init_custom = __esm(() => {
57119
- GLOBAL_COMMANDS_DIR = join14(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
57749
+ GLOBAL_COMMANDS_DIR = join15(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
57120
57750
  });
57121
57751
 
57122
57752
  // src/cli/components/HelpDialog.tsx
@@ -57155,6 +57785,8 @@ function HelpDialog({ onClose }) {
57155
57785
  { keys: "Tab", description: "Autocomplete command or file path" },
57156
57786
  { keys: "↓", description: "Navigate down / next command in history" },
57157
57787
  { keys: "↑", description: "Navigate up / previous command in history" },
57788
+ { keys: "Shift+Enter", description: "Insert newline (multi-line input)" },
57789
+ { keys: "Opt+Enter", description: "Insert newline (alternative)" },
57158
57790
  {
57159
57791
  keys: "Ctrl+C",
57160
57792
  description: "Interrupt operation / exit (double press)"
@@ -60354,7 +60986,7 @@ var init_AgentInfoBar = __esm(async () => {
60354
60986
 
60355
60987
  // src/cli/helpers/fileSearch.ts
60356
60988
  import { readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
60357
- import { join as join15, resolve as resolve17 } from "node:path";
60989
+ import { join as join16, resolve as resolve17 } from "node:path";
60358
60990
  function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = []) {
60359
60991
  if (results.length >= maxResults) {
60360
60992
  return results;
@@ -60366,7 +60998,7 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [])
60366
60998
  continue;
60367
60999
  }
60368
61000
  try {
60369
- const fullPath = join15(dir, entry);
61001
+ const fullPath = join16(dir, entry);
60370
61002
  const stats = statSync2(fullPath);
60371
61003
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
60372
61004
  const matches = pattern.length === 0 || relativePath.toLowerCase().includes(pattern.toLowerCase());
@@ -60418,7 +61050,7 @@ async function searchFiles(query, deep = false) {
60418
61050
  const matchingEntries = searchPattern.length === 0 ? entries : entries.filter((entry) => entry.toLowerCase().includes(searchPattern.toLowerCase()));
60419
61051
  for (const entry of matchingEntries.slice(0, 50)) {
60420
61052
  try {
60421
- const fullPath = join15(searchDir, entry);
61053
+ const fullPath = join16(searchDir, entry);
60422
61054
  const stats = statSync2(fullPath);
60423
61055
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
60424
61056
  results.push({
@@ -68297,7 +68929,7 @@ __export(exports_sessionContext, {
68297
68929
  buildSessionContext: () => buildSessionContext
68298
68930
  });
68299
68931
  import { execSync } from "node:child_process";
68300
- import { platform as platform3 } from "node:os";
68932
+ import { platform as platform4 } from "node:os";
68301
68933
  function getLocalTime() {
68302
68934
  const now = new Date;
68303
68935
  return now.toLocaleString(undefined, {
@@ -68311,7 +68943,7 @@ function getLocalTime() {
68311
68943
  });
68312
68944
  }
68313
68945
  function getDeviceType() {
68314
- const p = platform3();
68946
+ const p = platform4();
68315
68947
  switch (p) {
68316
68948
  case "darwin":
68317
68949
  return "macOS";
@@ -68434,7 +69066,7 @@ ${gitInfo.status}
68434
69066
  context3 += `- **Git repository**: No
68435
69067
  `;
68436
69068
  }
68437
- if (platform3() === "win32") {
69069
+ if (platform4() === "win32") {
68438
69070
  context3 += `
68439
69071
  ## Windows Shell Notes
68440
69072
  - The Bash tool uses PowerShell or cmd.exe on Windows
@@ -68466,7 +69098,7 @@ var exports_App = {};
68466
69098
  __export(exports_App, {
68467
69099
  default: () => App2
68468
69100
  });
68469
- import { existsSync as existsSync11, readFileSync as readFileSync3, writeFileSync } from "node:fs";
69101
+ import { existsSync as existsSync12, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
68470
69102
  function uid4(prefix) {
68471
69103
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
68472
69104
  }
@@ -68547,18 +69179,18 @@ NOTE: At any point in time through this workflow you should feel free to ask the
68547
69179
  }
68548
69180
  function planFileExists() {
68549
69181
  const planFilePath = permissionMode2.getPlanFilePath();
68550
- return !!planFilePath && existsSync11(planFilePath);
69182
+ return !!planFilePath && existsSync12(planFilePath);
68551
69183
  }
68552
69184
  function readPlanFile() {
68553
69185
  const planFilePath = permissionMode2.getPlanFilePath();
68554
69186
  if (!planFilePath) {
68555
69187
  return "No plan file path set.";
68556
69188
  }
68557
- if (!existsSync11(planFilePath)) {
69189
+ if (!existsSync12(planFilePath)) {
68558
69190
  return `Plan file not found at ${planFilePath}`;
68559
69191
  }
68560
69192
  try {
68561
- return readFileSync3(planFilePath, "utf-8");
69193
+ return readFileSync4(planFilePath, "utf-8");
68562
69194
  } catch {
68563
69195
  return `Failed to read plan file at ${planFilePath}`;
68564
69196
  }
@@ -70427,7 +71059,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
70427
71059
  const client = await getClient2();
70428
71060
  const fileContent = await client.agents.exportFile(agentId);
70429
71061
  const fileName = `${agentId}.af`;
70430
- writeFileSync(fileName, JSON.stringify(fileContent, null, 2));
71062
+ writeFileSync2(fileName, JSON.stringify(fileContent, null, 2));
70431
71063
  buffersRef.current.byId.set(cmdId2, {
70432
71064
  kind: "command",
70433
71065
  id: cmdId2,
@@ -72282,6 +72914,414 @@ var init_App2 = __esm(async () => {
72282
72914
  jsx_dev_runtime50 = __toESM(require_jsx_dev_runtime(), 1);
72283
72915
  });
72284
72916
 
72917
+ // src/cli/utils/terminalKeybindingInstaller.ts
72918
+ var exports_terminalKeybindingInstaller2 = {};
72919
+ __export(exports_terminalKeybindingInstaller2, {
72920
+ wezTermDeleteFixExists: () => wezTermDeleteFixExists2,
72921
+ removeKeybindingForCurrentTerminal: () => removeKeybindingForCurrentTerminal2,
72922
+ removeKeybinding: () => removeKeybinding2,
72923
+ keybindingExists: () => keybindingExists2,
72924
+ isWezTerm: () => isWezTerm2,
72925
+ isVSCodeLikeTerminal: () => isVSCodeLikeTerminal2,
72926
+ installWezTermDeleteFix: () => installWezTermDeleteFix2,
72927
+ installKeybindingForCurrentTerminal: () => installKeybindingForCurrentTerminal2,
72928
+ installKeybinding: () => installKeybinding2,
72929
+ getWezTermConfigPath: () => getWezTermConfigPath2,
72930
+ getKeybindingsPath: () => getKeybindingsPath2,
72931
+ detectTerminalType: () => detectTerminalType2
72932
+ });
72933
+ import {
72934
+ copyFileSync as copyFileSync2,
72935
+ existsSync as existsSync13,
72936
+ mkdirSync as mkdirSync4,
72937
+ readFileSync as readFileSync5,
72938
+ writeFileSync as writeFileSync3
72939
+ } from "node:fs";
72940
+ import { homedir as homedir8, platform as platform5 } from "node:os";
72941
+ import { dirname as dirname11, join as join17 } from "node:path";
72942
+ function detectTerminalType2() {
72943
+ if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
72944
+ return "cursor";
72945
+ }
72946
+ if (process.env.WINDSURF_TRACE_ID || process.env.WINDSURF_CHANNEL) {
72947
+ return "windsurf";
72948
+ }
72949
+ const termProgram = process.env.TERM_PROGRAM?.toLowerCase();
72950
+ if (termProgram === "vscode")
72951
+ return "vscode";
72952
+ if (termProgram === "cursor")
72953
+ return "cursor";
72954
+ if (termProgram === "windsurf")
72955
+ return "windsurf";
72956
+ if (process.env.VSCODE_INJECTION === "1")
72957
+ return "vscode";
72958
+ return null;
72959
+ }
72960
+ function isVSCodeLikeTerminal2() {
72961
+ return detectTerminalType2() !== null;
72962
+ }
72963
+ function getKeybindingsPath2(terminal) {
72964
+ if (!terminal)
72965
+ return null;
72966
+ const appName = {
72967
+ vscode: "Code",
72968
+ cursor: "Cursor",
72969
+ windsurf: "Windsurf"
72970
+ }[terminal];
72971
+ const os4 = platform5();
72972
+ if (os4 === "darwin") {
72973
+ return join17(homedir8(), "Library", "Application Support", appName, "User", "keybindings.json");
72974
+ }
72975
+ if (os4 === "win32") {
72976
+ const appData = process.env.APPDATA;
72977
+ if (!appData)
72978
+ return null;
72979
+ return join17(appData, appName, "User", "keybindings.json");
72980
+ }
72981
+ if (os4 === "linux") {
72982
+ return join17(homedir8(), ".config", appName, "User", "keybindings.json");
72983
+ }
72984
+ return null;
72985
+ }
72986
+ function stripJsonComments2(jsonc) {
72987
+ let result = jsonc.replace(/\/\/.*$/gm, "");
72988
+ result = result.replace(/\/\*[\s\S]*?\*\//g, "");
72989
+ result = result.replace(/,(\s*[}\]])/g, "$1");
72990
+ return result;
72991
+ }
72992
+ function parseKeybindings2(content) {
72993
+ try {
72994
+ const stripped = stripJsonComments2(content);
72995
+ const parsed = JSON.parse(stripped);
72996
+ if (!Array.isArray(parsed))
72997
+ return null;
72998
+ return parsed;
72999
+ } catch {
73000
+ return null;
73001
+ }
73002
+ }
73003
+ function keybindingExists2(keybindingsPath) {
73004
+ if (!existsSync13(keybindingsPath))
73005
+ return false;
73006
+ try {
73007
+ const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
73008
+ const keybindings = parseKeybindings2(content);
73009
+ if (!keybindings)
73010
+ return false;
73011
+ return keybindings.some((kb) => kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus"));
73012
+ } catch {
73013
+ return false;
73014
+ }
73015
+ }
73016
+ function createBackup2(keybindingsPath) {
73017
+ if (!existsSync13(keybindingsPath))
73018
+ return null;
73019
+ const backupPath = `${keybindingsPath}.letta-backup`;
73020
+ try {
73021
+ copyFileSync2(keybindingsPath, backupPath);
73022
+ return backupPath;
73023
+ } catch {
73024
+ return null;
73025
+ }
73026
+ }
73027
+ function installKeybinding2(keybindingsPath) {
73028
+ try {
73029
+ if (keybindingExists2(keybindingsPath)) {
73030
+ return { success: true, alreadyExists: true };
73031
+ }
73032
+ const parentDir = dirname11(keybindingsPath);
73033
+ if (!existsSync13(parentDir)) {
73034
+ mkdirSync4(parentDir, { recursive: true });
73035
+ }
73036
+ let keybindings = [];
73037
+ let backupPath = null;
73038
+ if (existsSync13(keybindingsPath)) {
73039
+ backupPath = createBackup2(keybindingsPath);
73040
+ const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
73041
+ const parsed = parseKeybindings2(content);
73042
+ if (parsed === null) {
73043
+ return {
73044
+ success: false,
73045
+ error: `Could not parse ${keybindingsPath}. Please fix syntax errors and try again.`
73046
+ };
73047
+ }
73048
+ keybindings = parsed;
73049
+ }
73050
+ keybindings.push(SHIFT_ENTER_KEYBINDING2);
73051
+ const newContent = `${JSON.stringify(keybindings, null, 2)}
73052
+ `;
73053
+ writeFileSync3(keybindingsPath, newContent, { encoding: "utf-8" });
73054
+ return {
73055
+ success: true,
73056
+ backupPath: backupPath ?? undefined
73057
+ };
73058
+ } catch (error) {
73059
+ const message = error instanceof Error ? error.message : String(error);
73060
+ return {
73061
+ success: false,
73062
+ error: `Failed to install keybinding: ${message}`
73063
+ };
73064
+ }
73065
+ }
73066
+ function removeKeybinding2(keybindingsPath) {
73067
+ try {
73068
+ if (!existsSync13(keybindingsPath)) {
73069
+ return { success: true };
73070
+ }
73071
+ const content = readFileSync5(keybindingsPath, { encoding: "utf-8" });
73072
+ const keybindings = parseKeybindings2(content);
73073
+ if (!keybindings) {
73074
+ return {
73075
+ success: false,
73076
+ error: `Could not parse ${keybindingsPath}`
73077
+ };
73078
+ }
73079
+ const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
73080
+ const newContent = `${JSON.stringify(filtered, null, 2)}
73081
+ `;
73082
+ writeFileSync3(keybindingsPath, newContent, { encoding: "utf-8" });
73083
+ return { success: true };
73084
+ } catch (error) {
73085
+ const message = error instanceof Error ? error.message : String(error);
73086
+ return {
73087
+ success: false,
73088
+ error: `Failed to remove keybinding: ${message}`
73089
+ };
73090
+ }
73091
+ }
73092
+ function installKeybindingForCurrentTerminal2() {
73093
+ const terminal = detectTerminalType2();
73094
+ if (!terminal) {
73095
+ return {
73096
+ success: false,
73097
+ error: "Not running in a VS Code-like terminal"
73098
+ };
73099
+ }
73100
+ const path17 = getKeybindingsPath2(terminal);
73101
+ if (!path17) {
73102
+ return {
73103
+ success: false,
73104
+ error: `Could not determine keybindings.json path for ${terminal}`
73105
+ };
73106
+ }
73107
+ return installKeybinding2(path17);
73108
+ }
73109
+ function removeKeybindingForCurrentTerminal2() {
73110
+ const terminal = detectTerminalType2();
73111
+ if (!terminal) {
73112
+ return {
73113
+ success: false,
73114
+ error: "Not running in a VS Code-like terminal"
73115
+ };
73116
+ }
73117
+ const path17 = getKeybindingsPath2(terminal);
73118
+ if (!path17) {
73119
+ return {
73120
+ success: false,
73121
+ error: `Could not determine keybindings.json path for ${terminal}`
73122
+ };
73123
+ }
73124
+ return removeKeybinding2(path17);
73125
+ }
73126
+ function isWezTerm2() {
73127
+ return process.env.TERM_PROGRAM === "WezTerm";
73128
+ }
73129
+ function getWezTermConfigPath2() {
73130
+ if (process.env.WEZTERM_CONFIG_FILE) {
73131
+ return process.env.WEZTERM_CONFIG_FILE;
73132
+ }
73133
+ const xdgConfig = process.env.XDG_CONFIG_HOME;
73134
+ if (xdgConfig) {
73135
+ const xdgPath = join17(xdgConfig, "wezterm", "wezterm.lua");
73136
+ if (existsSync13(xdgPath))
73137
+ return xdgPath;
73138
+ }
73139
+ const configPath = join17(homedir8(), ".config", "wezterm", "wezterm.lua");
73140
+ if (existsSync13(configPath))
73141
+ return configPath;
73142
+ return join17(homedir8(), ".wezterm.lua");
73143
+ }
73144
+ function wezTermDeleteFixExists2(configPath) {
73145
+ if (!existsSync13(configPath))
73146
+ return false;
73147
+ try {
73148
+ const content = readFileSync5(configPath, { encoding: "utf-8" });
73149
+ return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
73150
+ } catch {
73151
+ return false;
73152
+ }
73153
+ }
73154
+ function installWezTermDeleteFix2() {
73155
+ const configPath = getWezTermConfigPath2();
73156
+ try {
73157
+ if (wezTermDeleteFixExists2(configPath)) {
73158
+ return { success: true, alreadyExists: true };
73159
+ }
73160
+ let content = "";
73161
+ let backupPath = null;
73162
+ if (existsSync13(configPath)) {
73163
+ backupPath = `${configPath}.letta-backup`;
73164
+ copyFileSync2(configPath, backupPath);
73165
+ content = readFileSync5(configPath, { encoding: "utf-8" });
73166
+ }
73167
+ if (content.includes("return {") && !content.includes("local config")) {
73168
+ content = content.replace(/return\s*\{/, "local config = {");
73169
+ if (!content.includes("return config")) {
73170
+ content = `${content.trimEnd()}
73171
+
73172
+ return config
73173
+ `;
73174
+ }
73175
+ }
73176
+ if (!content.trim()) {
73177
+ content = `-- WezTerm configuration
73178
+ local config = {}
73179
+
73180
+ return config
73181
+ `;
73182
+ }
73183
+ if (content.includes("return config")) {
73184
+ content = content.replace("return config", `${WEZTERM_DELETE_FIX2}
73185
+ return config`);
73186
+ } else {
73187
+ content = `${content.trimEnd()}
73188
+ ${WEZTERM_DELETE_FIX2}
73189
+ `;
73190
+ }
73191
+ const parentDir = dirname11(configPath);
73192
+ if (!existsSync13(parentDir)) {
73193
+ mkdirSync4(parentDir, { recursive: true });
73194
+ }
73195
+ writeFileSync3(configPath, content, { encoding: "utf-8" });
73196
+ return {
73197
+ success: true,
73198
+ backupPath: backupPath ?? undefined
73199
+ };
73200
+ } catch (error) {
73201
+ const message = error instanceof Error ? error.message : String(error);
73202
+ return {
73203
+ success: false,
73204
+ error: `Failed to install WezTerm Delete key fix: ${message}`
73205
+ };
73206
+ }
73207
+ }
73208
+ var SHIFT_ENTER_KEYBINDING2, WEZTERM_DELETE_FIX2 = `
73209
+ -- Letta Code: Fix Delete key sending wrong sequence with kitty keyboard protocol
73210
+ -- See: https://github.com/wez/wezterm/issues/3758
73211
+ local wezterm = require 'wezterm'
73212
+ local keys = config.keys or {}
73213
+ table.insert(keys, {
73214
+ key = 'Delete',
73215
+ mods = 'NONE',
73216
+ action = wezterm.action.SendString '\\x1b[3~',
73217
+ })
73218
+ config.keys = keys
73219
+ `;
73220
+ var init_terminalKeybindingInstaller2 = __esm(() => {
73221
+ SHIFT_ENTER_KEYBINDING2 = {
73222
+ key: "shift+enter",
73223
+ command: "workbench.action.terminal.sendSequence",
73224
+ args: { text: "\x1B\r" },
73225
+ when: "terminalFocus"
73226
+ };
73227
+ });
73228
+
73229
+ // src/settings.ts
73230
+ var exports_settings2 = {};
73231
+ __export(exports_settings2, {
73232
+ updateSettings: () => updateSettings2,
73233
+ updateProjectSettings: () => updateProjectSettings2,
73234
+ saveSettings: () => saveSettings2,
73235
+ saveProjectSettings: () => saveProjectSettings2,
73236
+ loadSettings: () => loadSettings2,
73237
+ loadProjectSettings: () => loadProjectSettings2,
73238
+ getSetting: () => getSetting2
73239
+ });
73240
+ import { homedir as homedir9 } from "node:os";
73241
+ import { join as join18 } from "node:path";
73242
+ function getSettingsPath2() {
73243
+ return join18(homedir9(), ".letta", "settings.json");
73244
+ }
73245
+ async function loadSettings2() {
73246
+ const settingsPath = getSettingsPath2();
73247
+ try {
73248
+ if (!exists(settingsPath)) {
73249
+ await saveSettings2(DEFAULT_SETTINGS4);
73250
+ return DEFAULT_SETTINGS4;
73251
+ }
73252
+ const content = await readFile(settingsPath);
73253
+ const settings = JSON.parse(content);
73254
+ return { ...DEFAULT_SETTINGS4, ...settings };
73255
+ } catch (error) {
73256
+ console.error("Error loading settings, using defaults:", error);
73257
+ return DEFAULT_SETTINGS4;
73258
+ }
73259
+ }
73260
+ async function saveSettings2(settings) {
73261
+ const settingsPath = getSettingsPath2();
73262
+ try {
73263
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2));
73264
+ } catch (error) {
73265
+ console.error("Error saving settings:", error);
73266
+ throw error;
73267
+ }
73268
+ }
73269
+ async function updateSettings2(updates) {
73270
+ const currentSettings = await loadSettings2();
73271
+ const newSettings = { ...currentSettings, ...updates };
73272
+ await saveSettings2(newSettings);
73273
+ return newSettings;
73274
+ }
73275
+ async function getSetting2(key) {
73276
+ const settings = await loadSettings2();
73277
+ return settings[key];
73278
+ }
73279
+ function getProjectSettingsPath2() {
73280
+ return join18(process.cwd(), ".letta", "settings.local.json");
73281
+ }
73282
+ async function loadProjectSettings2() {
73283
+ const settingsPath = getProjectSettingsPath2();
73284
+ try {
73285
+ if (!exists(settingsPath)) {
73286
+ return null;
73287
+ }
73288
+ const content = await readFile(settingsPath);
73289
+ const settings = JSON.parse(content);
73290
+ return settings;
73291
+ } catch (error) {
73292
+ console.error("Error loading project settings:", error);
73293
+ return null;
73294
+ }
73295
+ }
73296
+ async function saveProjectSettings2(settings) {
73297
+ const settingsPath = getProjectSettingsPath2();
73298
+ const dirPath = join18(process.cwd(), ".letta");
73299
+ try {
73300
+ if (!exists(dirPath)) {
73301
+ await mkdir(dirPath, { recursive: true });
73302
+ }
73303
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2));
73304
+ } catch (error) {
73305
+ console.error("Error saving project settings:", error);
73306
+ throw error;
73307
+ }
73308
+ }
73309
+ async function updateProjectSettings2(updates) {
73310
+ const currentSettings = await loadProjectSettings2() || { lastAgent: null };
73311
+ const newSettings = { ...currentSettings, ...updates };
73312
+ await saveProjectSettings2(newSettings);
73313
+ return newSettings;
73314
+ }
73315
+ var DEFAULT_SETTINGS4;
73316
+ var init_settings2 = __esm(() => {
73317
+ init_fs();
73318
+ DEFAULT_SETTINGS4 = {
73319
+ lastAgent: null,
73320
+ tokenStreaming: false,
73321
+ globalSharedBlockIds: {}
73322
+ };
73323
+ });
73324
+
72285
73325
  // src/tools/toolset.ts
72286
73326
  var exports_toolset2 = {};
72287
73327
  __export(exports_toolset2, {
@@ -72685,7 +73725,7 @@ var exports_create = {};
72685
73725
  __export(exports_create, {
72686
73726
  createAgent: () => createAgent2
72687
73727
  });
72688
- import { join as join16 } from "node:path";
73728
+ import { join as join19 } from "node:path";
72689
73729
  async function createAgent2(name = DEFAULT_AGENT_NAME, model, embeddingModel = "openai/text-embedding-3-small", updateArgs, skillsDirectory, parallelToolCalls = true, enableSleeptime = false, systemPromptId, initBlocks, baseTools) {
72690
73730
  let modelHandle;
72691
73731
  if (model) {
@@ -72737,7 +73777,7 @@ async function createAgent2(name = DEFAULT_AGENT_NAME, model, embeddingModel = "
72737
73777
  }
72738
73778
  }
72739
73779
  const filteredMemoryBlocks = allowedBlockLabels && allowedBlockLabels.size > 0 ? defaultMemoryBlocks.filter((b) => allowedBlockLabels.has(b.label)) : defaultMemoryBlocks;
72740
- const resolvedSkillsDirectory = skillsDirectory || join16(process.cwd(), SKILLS_DIR);
73780
+ const resolvedSkillsDirectory = skillsDirectory || join19(process.cwd(), SKILLS_DIR);
72741
73781
  try {
72742
73782
  const { skills, errors } = await discoverSkills(resolvedSkillsDirectory);
72743
73783
  if (errors.length > 0) {
@@ -74213,12 +75253,12 @@ EXAMPLES
74213
75253
  console.log(usage);
74214
75254
  }
74215
75255
  async function printInfo() {
74216
- const { join: join17 } = await import("path");
75256
+ const { join: join20 } = await import("path");
74217
75257
  const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
74218
75258
  const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
74219
75259
  const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
74220
75260
  const cwd2 = process.cwd();
74221
- const skillsDir = join17(cwd2, SKILLS_DIR3);
75261
+ const skillsDir = join20(cwd2, SKILLS_DIR3);
74222
75262
  const skillsExist = exists3(skillsDir);
74223
75263
  await settingsManager2.loadLocalProjectSettings(cwd2);
74224
75264
  const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
@@ -74444,9 +75484,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
74444
75484
  process.exit(1);
74445
75485
  }
74446
75486
  const { resolve: resolve19 } = await import("path");
74447
- const { existsSync: existsSync12 } = await import("fs");
75487
+ const { existsSync: existsSync14 } = await import("fs");
74448
75488
  const resolvedPath = resolve19(fromAfFile);
74449
- if (!existsSync12(resolvedPath)) {
75489
+ if (!existsSync14(resolvedPath)) {
74450
75490
  console.error(`Error: AgentFile not found: ${resolvedPath}`);
74451
75491
  process.exit(1);
74452
75492
  }
@@ -74549,6 +75589,10 @@ Error: ${message}`);
74549
75589
  await handleHeadlessCommand2(process.argv, specifiedModel, skillsDirectory);
74550
75590
  return;
74551
75591
  }
75592
+ try {
75593
+ const { detectAndEnableKittyProtocol: detectAndEnableKittyProtocol2 } = await Promise.resolve().then(() => (init_kittyProtocolDetector(), exports_kittyProtocolDetector));
75594
+ await detectAndEnableKittyProtocol2();
75595
+ } catch {}
74552
75596
  const React14 = await Promise.resolve().then(() => __toESM(require_react2(), 1));
74553
75597
  const { render: render2 } = await init_build3().then(() => exports_build);
74554
75598
  const { useState: useState35, useEffect: useEffect26 } = React14;
@@ -74566,6 +75610,7 @@ Error: ${message}`);
74566
75610
  skillsDirectory: skillsDirectory2,
74567
75611
  fromAfFile: fromAfFile2
74568
75612
  }) {
75613
+ const [showKeybindingSetup, setShowKeybindingSetup] = useState35(null);
74569
75614
  const [loadingState, setLoadingState] = useState35("selecting");
74570
75615
  const [agentId, setAgentId] = useState35(null);
74571
75616
  const [agentState, setAgentState] = useState35(null);
@@ -74573,6 +75618,63 @@ Error: ${message}`);
74573
75618
  const [isResumingSession, setIsResumingSession] = useState35(false);
74574
75619
  const [agentProvenance, setAgentProvenance] = useState35(null);
74575
75620
  const [selectedGlobalAgentId, setSelectedGlobalAgentId] = useState35(null);
75621
+ useEffect26(() => {
75622
+ async function autoInstallKeybinding() {
75623
+ const {
75624
+ detectTerminalType: detectTerminalType3,
75625
+ getKeybindingsPath: getKeybindingsPath3,
75626
+ keybindingExists: keybindingExists3,
75627
+ installKeybinding: installKeybinding3
75628
+ } = await Promise.resolve().then(() => (init_terminalKeybindingInstaller2(), exports_terminalKeybindingInstaller2));
75629
+ const { loadSettings: loadSettings3, updateSettings: updateSettings3 } = await Promise.resolve().then(() => (init_settings2(), exports_settings2));
75630
+ const terminal = detectTerminalType3();
75631
+ if (!terminal) {
75632
+ setShowKeybindingSetup(false);
75633
+ return;
75634
+ }
75635
+ const settings2 = await loadSettings3();
75636
+ const keybindingsPath = getKeybindingsPath3(terminal);
75637
+ if (!keybindingsPath || settings2.shiftEnterKeybindingInstalled) {
75638
+ setShowKeybindingSetup(false);
75639
+ return;
75640
+ }
75641
+ if (keybindingExists3(keybindingsPath)) {
75642
+ await updateSettings3({ shiftEnterKeybindingInstalled: true });
75643
+ setShowKeybindingSetup(false);
75644
+ return;
75645
+ }
75646
+ const result = installKeybinding3(keybindingsPath);
75647
+ if (result.success) {
75648
+ await updateSettings3({ shiftEnterKeybindingInstalled: true });
75649
+ }
75650
+ setShowKeybindingSetup(false);
75651
+ }
75652
+ async function autoInstallWezTermFix() {
75653
+ const {
75654
+ isWezTerm: isWezTerm3,
75655
+ wezTermDeleteFixExists: wezTermDeleteFixExists3,
75656
+ getWezTermConfigPath: getWezTermConfigPath3,
75657
+ installWezTermDeleteFix: installWezTermDeleteFix3
75658
+ } = await Promise.resolve().then(() => (init_terminalKeybindingInstaller2(), exports_terminalKeybindingInstaller2));
75659
+ const { loadSettings: loadSettings3, updateSettings: updateSettings3 } = await Promise.resolve().then(() => (init_settings2(), exports_settings2));
75660
+ if (!isWezTerm3())
75661
+ return;
75662
+ const settings2 = await loadSettings3();
75663
+ if (settings2.wezTermDeleteFixInstalled)
75664
+ return;
75665
+ const configPath = getWezTermConfigPath3();
75666
+ if (wezTermDeleteFixExists3(configPath)) {
75667
+ await updateSettings3({ wezTermDeleteFixInstalled: true });
75668
+ return;
75669
+ }
75670
+ const result = installWezTermDeleteFix3();
75671
+ if (result.success) {
75672
+ await updateSettings3({ wezTermDeleteFixInstalled: true });
75673
+ }
75674
+ }
75675
+ autoInstallKeybinding();
75676
+ autoInstallWezTermFix();
75677
+ }, []);
74576
75678
  useEffect26(() => {
74577
75679
  async function checkAndStart() {
74578
75680
  await settingsManager2.loadLocalProjectSettings();
@@ -74757,8 +75859,8 @@ Error: ${message}`);
74757
75859
  await initializeLoadedSkillsFlag();
74758
75860
  try {
74759
75861
  const { discoverSkills: discoverSkills3, formatSkillsForMemory: formatSkillsForMemory3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
74760
- const { join: join17 } = await import("path");
74761
- const resolvedSkillsDirectory = skillsDirectory2 || join17(process.cwd(), SKILLS_DIR3);
75862
+ const { join: join20 } = await import("path");
75863
+ const resolvedSkillsDirectory = skillsDirectory2 || join20(process.cwd(), SKILLS_DIR3);
74762
75864
  const { skills, errors } = await discoverSkills3(resolvedSkillsDirectory);
74763
75865
  if (errors.length > 0) {
74764
75866
  console.warn("Errors encountered during skill discovery:");
@@ -74835,6 +75937,9 @@ Error during initialization: ${message}`);
74835
75937
  loadingState,
74836
75938
  selectedGlobalAgentId
74837
75939
  ]);
75940
+ if (showKeybindingSetup === null) {
75941
+ return null;
75942
+ }
74838
75943
  if (loadingState === "selecting") {
74839
75944
  return null;
74840
75945
  }
@@ -74897,4 +76002,4 @@ Error during initialization: ${message}`);
74897
76002
  }
74898
76003
  main();
74899
76004
 
74900
- //# debugId=8134ECE87ABE785364756E2164756E21
76005
+ //# debugId=F52C27FCEB893D3264756E2164756E21