@letta-ai/letta-code 0.10.3 → 0.10.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.10.3",
3
+ "version": "0.10.5",
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": {
@@ -108,7 +108,7 @@ A skill should only contain essential files that directly support its functional
108
108
  - CHANGELOG.md
109
109
  - etc.
110
110
 
111
- The skill should only contain the information needed for an AI agent to do the job at hand. It should not contain auxilary context about the process that went into creating it, setup and testing procedures, user-facing documentation, etc. Creating additional documentation files just adds clutter and confusion.
111
+ The skill should only contain the information needed for an AI agent to do the job at hand. It should not contain auxiliary context about the process that went into creating it, setup and testing procedures, user-facing documentation, etc. Creating additional documentation files just adds clutter and confusion.
112
112
 
113
113
  ### Progressive Disclosure Design Principle
114
114
 
@@ -53,7 +53,56 @@ const useInput = (inputHandler, options = {}) => {
53
53
  return;
54
54
  }
55
55
 
56
- const keypress = parseKeypress(data);
56
+ let keypress = parseKeypress(data);
57
+
58
+ // CSI u fallback: iTerm2 3.5+, Kitty, and other modern terminals send
59
+ // keys in CSI u format: ESC [ keycode ; modifier u
60
+ // or with event type: ESC [ keycode ; modifier : event u
61
+ // parseKeypress doesn't handle this, so we parse it ourselves as a fallback
62
+ if (!keypress.name && typeof data === 'string') {
63
+ // Match CSI u: ESC [ keycode ; modifier u OR ESC [ keycode ; modifier : event u
64
+ const csiUMatch = data.match(/^\x1b\[(\d+)(?:;(\d+))?(?::(\d+))?u$/);
65
+ if (csiUMatch) {
66
+ const keycode = parseInt(csiUMatch[1], 10);
67
+ const modifier = parseInt(csiUMatch[2] || '1', 10) - 1;
68
+ const event = csiUMatch[3] ? parseInt(csiUMatch[3], 10) : 1;
69
+
70
+ // Ignore key release events (event=3)
71
+ if (event === 3) {
72
+ return;
73
+ }
74
+
75
+ // Map keycodes to names
76
+ const csiUKeyMap = {
77
+ 9: 'tab',
78
+ 13: 'return',
79
+ 27: 'escape',
80
+ 127: 'backspace',
81
+ };
82
+
83
+ let name = csiUKeyMap[keycode] || '';
84
+
85
+ // Handle letter keycodes (a-z: 97-122, A-Z: 65-90)
86
+ if (!name && keycode >= 97 && keycode <= 122) {
87
+ name = String.fromCharCode(keycode); // lowercase letter
88
+ } else if (!name && keycode >= 65 && keycode <= 90) {
89
+ name = String.fromCharCode(keycode + 32); // convert to lowercase
90
+ }
91
+
92
+ if (name) {
93
+ keypress = {
94
+ name,
95
+ ctrl: !!(modifier & 4),
96
+ meta: !!(modifier & 10),
97
+ shift: !!(modifier & 1),
98
+ option: false,
99
+ sequence: data,
100
+ raw: data,
101
+ };
102
+ }
103
+ }
104
+ }
105
+
57
106
  const key = {
58
107
  upArrow: keypress.name === 'up',
59
108
  downArrow: keypress.name === 'down',
@@ -72,6 +121,15 @@ const useInput = (inputHandler, options = {}) => {
72
121
  isPasted: false
73
122
  };
74
123
 
124
+ // Debug logging for key parsing (LETTA_DEBUG_KEYS=1)
125
+ if (process.env.LETTA_DEBUG_KEYS === '1') {
126
+ const rawHex = typeof data === 'string'
127
+ ? [...data].map(c => '0x' + c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ')
128
+ : '(non-string)';
129
+ // eslint-disable-next-line no-console
130
+ console.error(`[debug:ink-keypress] raw=${rawHex} name="${keypress.name}" seq="${keypress.sequence}" key={escape:${key.escape},tab:${key.tab},shift:${key.shift},ctrl:${key.ctrl},meta:${key.meta}}`);
131
+ }
132
+
75
133
  let input = keypress.ctrl ? keypress.name : keypress.sequence;
76
134
  const seq = typeof keypress.sequence === 'string' ? keypress.sequence : '';
77
135
  // Filter xterm focus in/out sequences (ESC[I / ESC[O)