@ouro.bot/cli 0.1.0-alpha.262 → 0.1.0-alpha.263
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/changelog.json +6 -0
- package/dist/senses/cli/input-keys.js +6 -0
- package/dist/senses/cli/ouro-tui.js +40 -43
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.263",
|
|
6
|
+
"changes": [
|
|
7
|
+
"fix(tui): arrow keys char-by-char (Ink 3.2 key.meta bug), Option+Arrow word-jump via CSI sequences."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.262",
|
|
6
12
|
"changes": [
|
|
@@ -119,6 +119,12 @@ function classifyEscapeSequence(inputChar) {
|
|
|
119
119
|
// End: \x1b[F or \x1b[4~
|
|
120
120
|
if (seq === "F" || seq === "4~")
|
|
121
121
|
return "end";
|
|
122
|
+
// Option+Left: \x1b[1;3D (CSI modified arrow with Alt modifier)
|
|
123
|
+
if (seq === "1;3D")
|
|
124
|
+
return "word-left";
|
|
125
|
+
// Option+Right: \x1b[1;3C
|
|
126
|
+
if (seq === "1;3C")
|
|
127
|
+
return "word-right";
|
|
122
128
|
// PageUp: \x1b[5~, PageDown: \x1b[6~
|
|
123
129
|
if (seq === "5~" || seq === "6~")
|
|
124
130
|
return "ignore";
|
|
@@ -324,39 +324,20 @@ function InputArea({ onSubmit, onCtrlC, history, queuedInputs, onPopQueue, agent
|
|
|
324
324
|
historyIdx.current = -1;
|
|
325
325
|
return;
|
|
326
326
|
}
|
|
327
|
-
// Left/right arrow: move cursor
|
|
327
|
+
// Left/right arrow: move cursor (char by char, token-aware)
|
|
328
|
+
// NOTE: Ink 3.2 bug — key.meta is ALWAYS true for arrow keys because all
|
|
329
|
+
// arrows start with \x1b and Ink sets meta=true for any ESC-prefixed input.
|
|
330
|
+
// Word-jump is handled via Meta+B/F (emacs bindings) instead.
|
|
328
331
|
if (key.leftArrow) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const match = before.match(/(?:^|\s)\S+\s*$/);
|
|
333
|
-
const newPos = match ? cursorRef.current - match[0].length + (match[0].startsWith(" ") ? 1 : 0) : 0;
|
|
334
|
-
cursorRef.current = Math.max(0, newPos);
|
|
335
|
-
setCursorPos(cursorRef.current);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
// Token-aware: hop over image ref chips
|
|
339
|
-
const chipStart = (0, image_ref_navigation_1.imageRefEndingAt)(inputRef.current, cursorRef.current);
|
|
340
|
-
cursorRef.current = chipStart !== undefined ? chipStart : Math.max(0, cursorRef.current - 1);
|
|
341
|
-
setCursorPos(cursorRef.current);
|
|
342
|
-
}
|
|
332
|
+
const chipStart = (0, image_ref_navigation_1.imageRefEndingAt)(inputRef.current, cursorRef.current);
|
|
333
|
+
cursorRef.current = chipStart !== undefined ? chipStart : Math.max(0, cursorRef.current - 1);
|
|
334
|
+
setCursorPos(cursorRef.current);
|
|
343
335
|
return;
|
|
344
336
|
}
|
|
345
337
|
if (key.rightArrow) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const match = after.match(/^\s*\S+/);
|
|
350
|
-
const newPos = match ? cursorRef.current + match[0].length : inputRef.current.length;
|
|
351
|
-
cursorRef.current = Math.min(inputRef.current.length, newPos);
|
|
352
|
-
setCursorPos(cursorRef.current);
|
|
353
|
-
}
|
|
354
|
-
else {
|
|
355
|
-
// Token-aware: hop over image ref chips
|
|
356
|
-
const chipEnd = (0, image_ref_navigation_1.imageRefStartingAt)(inputRef.current, cursorRef.current);
|
|
357
|
-
cursorRef.current = chipEnd !== undefined ? chipEnd : Math.min(inputRef.current.length, cursorRef.current + 1);
|
|
358
|
-
setCursorPos(cursorRef.current);
|
|
359
|
-
}
|
|
338
|
+
const chipEnd = (0, image_ref_navigation_1.imageRefStartingAt)(inputRef.current, cursorRef.current);
|
|
339
|
+
cursorRef.current = chipEnd !== undefined ? chipEnd : Math.min(inputRef.current.length, cursorRef.current + 1);
|
|
340
|
+
setCursorPos(cursorRef.current);
|
|
360
341
|
return;
|
|
361
342
|
}
|
|
362
343
|
// Up/Down: queue pop takes priority over history
|
|
@@ -542,22 +523,38 @@ function InputArea({ onSubmit, onCtrlC, history, queuedInputs, onPopQueue, agent
|
|
|
542
523
|
// ─── Non-kill/non-yank keystroke resets ────────────────────────
|
|
543
524
|
killRing.resetAccumulation();
|
|
544
525
|
killRing.resetYankState();
|
|
526
|
+
// Detect raw escape sequences — Ink 3.2 strips \x1b prefix and sets key.meta,
|
|
527
|
+
// so we re-prepend it for classification when meta is set and inputChar starts with [
|
|
528
|
+
const escInput = key.meta && inputChar.startsWith("[") ? "\x1b" + inputChar : inputChar;
|
|
529
|
+
const escClass = (0, input_keys_1.classifyEscapeSequence)(escInput);
|
|
530
|
+
if (escClass === "home") {
|
|
531
|
+
cursorRef.current = (0, input_keys_1.handleHome)(inputRef.current, cursorRef.current);
|
|
532
|
+
setCursorPos(cursorRef.current);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (escClass === "end") {
|
|
536
|
+
cursorRef.current = (0, input_keys_1.handleEnd)(inputRef.current, cursorRef.current);
|
|
537
|
+
setCursorPos(cursorRef.current);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (escClass === "word-left") {
|
|
541
|
+
const before = inputRef.current.slice(0, cursorRef.current);
|
|
542
|
+
const match = before.match(/(?:^|\s)\S+\s*$/);
|
|
543
|
+
cursorRef.current = match ? Math.max(0, cursorRef.current - match[0].length + (match[0].startsWith(" ") ? 1 : 0)) : 0;
|
|
544
|
+
setCursorPos(cursorRef.current);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
if (escClass === "word-right") {
|
|
548
|
+
const after = inputRef.current.slice(cursorRef.current);
|
|
549
|
+
const match = after.match(/^\s*\S+/);
|
|
550
|
+
cursorRef.current = match ? Math.min(inputRef.current.length, cursorRef.current + match[0].length) : inputRef.current.length;
|
|
551
|
+
setCursorPos(cursorRef.current);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (escClass === "ignore")
|
|
555
|
+
return;
|
|
545
556
|
// Regular character: insert at cursor position
|
|
546
557
|
if (!key.ctrl && !key.meta && inputChar) {
|
|
547
|
-
// Detect raw escape sequences before inserting text
|
|
548
|
-
const escClass = (0, input_keys_1.classifyEscapeSequence)(inputChar);
|
|
549
|
-
if (escClass === "home") {
|
|
550
|
-
cursorRef.current = (0, input_keys_1.handleHome)(inputRef.current, cursorRef.current);
|
|
551
|
-
setCursorPos(cursorRef.current);
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
if (escClass === "end") {
|
|
555
|
-
cursorRef.current = (0, input_keys_1.handleEnd)(inputRef.current, cursorRef.current);
|
|
556
|
-
setCursorPos(cursorRef.current);
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
if (escClass === "ignore")
|
|
560
|
-
return; // PageUp/PageDown/mouse wheel fallback
|
|
561
558
|
const before = inputRef.current.slice(0, cursorRef.current);
|
|
562
559
|
const after = inputRef.current.slice(cursorRef.current);
|
|
563
560
|
updateInput(before + inputChar + after, cursorRef.current + 1);
|