@yuaone/cli 0.9.7 → 0.9.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.
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useMouseScroll — enables mouse wheel scrolling in the TUI.
|
|
3
3
|
*
|
|
4
|
-
* Problem:
|
|
5
|
-
*
|
|
6
|
-
* text in InputBox.
|
|
4
|
+
* Problem: Enabling mouse tracking causes escape sequences to leak into
|
|
5
|
+
* Ink's readline → garbage text + broken backspace in InputBox.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* Root cause of leakage: ESC byte (\x1b) can arrive in a SEPARATE data
|
|
8
|
+
* event from the rest of the sequence ([<0;56;28M). The original code
|
|
9
|
+
* checked `str.includes("\x1b[<")` — true only when ESC + rest arrive
|
|
10
|
+
* together. When split, the second chunk has no ESC and bypasses the
|
|
11
|
+
* strip, landing directly in InputBox as literal text.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Fix: partial-sequence buffer. Any trailing incomplete escape at the
|
|
14
|
+
* end of a data chunk is held in `partialBuf` and prepended to the
|
|
15
|
+
* next chunk, reassembling split sequences before pattern matching.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Protocols:
|
|
18
|
+
* X10 (1000h): \x1b[M <btn> <col> <row> — 6 bytes total
|
|
19
|
+
* SGR (1006h): \x1b[<btn;col;rowM/m — variable length
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Scroll codes:
|
|
22
|
+
* X10 scroll-up = btn byte 96 (64+32), scroll-down = 97
|
|
23
|
+
* SGR scroll-up = btn field 64, scroll-down = 65
|
|
23
24
|
*/
|
|
24
25
|
export declare function useMouseScroll(onScrollUp: () => void, onScrollDown: () => void): void;
|
|
25
26
|
//# sourceMappingURL=useMouseScroll.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMouseScroll.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useMouseScroll.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useMouseScroll.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useMouseScroll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAqBH,wBAAgB,cAAc,CAC5B,UAAU,EAAI,MAAM,IAAI,EACxB,YAAY,EAAE,MAAM,IAAI,GACvB,IAAI,CA0FN"}
|
|
@@ -1,112 +1,116 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useMouseScroll — enables mouse wheel scrolling in the TUI.
|
|
3
3
|
*
|
|
4
|
-
* Problem:
|
|
5
|
-
*
|
|
6
|
-
* text in InputBox.
|
|
4
|
+
* Problem: Enabling mouse tracking causes escape sequences to leak into
|
|
5
|
+
* Ink's readline → garbage text + broken backspace in InputBox.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* Root cause of leakage: ESC byte (\x1b) can arrive in a SEPARATE data
|
|
8
|
+
* event from the rest of the sequence ([<0;56;28M). The original code
|
|
9
|
+
* checked `str.includes("\x1b[<")` — true only when ESC + rest arrive
|
|
10
|
+
* together. When split, the second chunk has no ESC and bypasses the
|
|
11
|
+
* strip, landing directly in InputBox as literal text.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Fix: partial-sequence buffer. Any trailing incomplete escape at the
|
|
14
|
+
* end of a data chunk is held in `partialBuf` and prepended to the
|
|
15
|
+
* next chunk, reassembling split sequences before pattern matching.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Protocols:
|
|
18
|
+
* X10 (1000h): \x1b[M <btn> <col> <row> — 6 bytes total
|
|
19
|
+
* SGR (1006h): \x1b[<btn;col;rowM/m — variable length
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Scroll codes:
|
|
22
|
+
* X10 scroll-up = btn byte 96 (64+32), scroll-down = 97
|
|
23
|
+
* SGR scroll-up = btn field 64, scroll-down = 65
|
|
23
24
|
*/
|
|
24
25
|
import { useEffect, useRef } from "react";
|
|
25
|
-
const MOUSE_ENABLE = "\x1b[?1000h\x1b[?1006h";
|
|
26
|
-
const MOUSE_DISABLE = "\x1b[?1006l\x1b[?1000l";
|
|
27
|
-
// X10
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
//
|
|
31
|
-
const X10_MOUSE_PATTERN = /\x1b\[M[\s\S]{3}/g;
|
|
32
|
-
// SGR: matches \x1b[<button;col;rowM or \x1b[<button;col;rowm
|
|
33
|
-
const SGR_MOUSE_PATTERN = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
34
|
-
// SGR scroll button codes (no offset applied — raw values)
|
|
26
|
+
const MOUSE_ENABLE = "\x1b[?1000h\x1b[?1006h";
|
|
27
|
+
const MOUSE_DISABLE = "\x1b[?1006l\x1b[?1000l";
|
|
28
|
+
// X10 scroll button values (raw byte after 32-offset encoding)
|
|
29
|
+
const X10_SCROLL_UP = 96;
|
|
30
|
+
const X10_SCROLL_DOWN = 97;
|
|
31
|
+
// SGR scroll button values (no offset — raw field)
|
|
35
32
|
const SGR_SCROLL_UP = 64;
|
|
36
33
|
const SGR_SCROLL_DOWN = 65;
|
|
34
|
+
// Matches a trailing INCOMPLETE escape sequence that might continue in the next chunk.
|
|
35
|
+
// Complete sequences are NOT matched (they'll be handled by the strip regexes below).
|
|
36
|
+
const TRAILING_PARTIAL = /\x1b(?:\[(?:<[\d;]*)?)?$/;
|
|
37
37
|
export function useMouseScroll(onScrollUp, onScrollDown) {
|
|
38
|
-
// Keep callback refs stable so the effect only runs once
|
|
39
38
|
const upRef = useRef(onScrollUp);
|
|
40
39
|
const downRef = useRef(onScrollDown);
|
|
41
40
|
upRef.current = onScrollUp;
|
|
42
41
|
downRef.current = onScrollDown;
|
|
43
42
|
useEffect(() => {
|
|
44
|
-
|
|
45
|
-
if (process.stdin._yuanMousePatched) {
|
|
43
|
+
if (process.stdin._yuanMousePatched)
|
|
46
44
|
return;
|
|
47
|
-
}
|
|
48
45
|
process.stdin._yuanMousePatched = true;
|
|
49
46
|
process.stdout.write(MOUSE_ENABLE);
|
|
47
|
+
let partialBuf = ""; // holds incomplete escape sequence tail from last chunk
|
|
50
48
|
const originalEmit = process.stdin.emit.bind(process.stdin);
|
|
51
49
|
process.stdin.emit = function (event, ...args) {
|
|
52
50
|
if (event === "data") {
|
|
53
51
|
const raw = args[0];
|
|
54
|
-
const
|
|
55
|
-
? raw.toString("
|
|
52
|
+
const chunk = raw instanceof Buffer
|
|
53
|
+
? raw.toString("latin1")
|
|
56
54
|
: typeof raw === "string"
|
|
57
55
|
? raw
|
|
58
56
|
: "";
|
|
57
|
+
// Reassemble split sequences: prepend buffered partial from last chunk
|
|
58
|
+
let str = partialBuf + chunk;
|
|
59
|
+
partialBuf = "";
|
|
60
|
+
// Buffer any new trailing partial (incomplete escape sequence at end of str)
|
|
61
|
+
const trailMatch = TRAILING_PARTIAL.exec(str);
|
|
62
|
+
if (trailMatch) {
|
|
63
|
+
partialBuf = trailMatch[0];
|
|
64
|
+
str = str.slice(0, trailMatch.index);
|
|
65
|
+
}
|
|
66
|
+
if (str.length === 0)
|
|
67
|
+
return true; // only had a partial — wait for more
|
|
59
68
|
let ups = 0;
|
|
60
69
|
let downs = 0;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Fire scroll callbacks
|
|
88
|
-
for (let i = 0; i < ups; i++)
|
|
89
|
-
upRef.current();
|
|
90
|
-
for (let i = 0; i < downs; i++)
|
|
91
|
-
downRef.current();
|
|
92
|
-
// Swallow event entirely if nothing left after stripping
|
|
93
|
-
if (stripped.length === 0)
|
|
94
|
-
return true;
|
|
95
|
-
// Pass stripped data onward to Ink's readline
|
|
96
|
-
const newData = raw instanceof Buffer
|
|
97
|
-
? Buffer.from(stripped, "binary")
|
|
98
|
-
: stripped;
|
|
99
|
-
return originalEmit(event, newData);
|
|
70
|
+
// Strip ALL SGR mouse events: \x1b[<btn;col;rowM/m (clicks + scroll)
|
|
71
|
+
let stripped = str.replace(/\x1b\[<(\d+);\d+;\d+[Mm]/g, (_, btnStr) => {
|
|
72
|
+
const btn = parseInt(btnStr, 10);
|
|
73
|
+
if (btn === SGR_SCROLL_UP)
|
|
74
|
+
ups++;
|
|
75
|
+
else if (btn === SGR_SCROLL_DOWN)
|
|
76
|
+
downs++;
|
|
77
|
+
return "";
|
|
78
|
+
});
|
|
79
|
+
// Strip ALL X10 mouse events: \x1b[M + 3 bytes (clicks + scroll)
|
|
80
|
+
stripped = stripped.replace(/\x1b\[M[\s\S]{3}/g, (match) => {
|
|
81
|
+
const btn = match.charCodeAt(3);
|
|
82
|
+
if (btn === X10_SCROLL_UP)
|
|
83
|
+
ups++;
|
|
84
|
+
else if (btn === X10_SCROLL_DOWN)
|
|
85
|
+
downs++;
|
|
86
|
+
return "";
|
|
87
|
+
});
|
|
88
|
+
// Fire scroll callbacks
|
|
89
|
+
for (let i = 0; i < ups; i++)
|
|
90
|
+
upRef.current();
|
|
91
|
+
for (let i = 0; i < downs; i++)
|
|
92
|
+
downRef.current();
|
|
93
|
+
// If nothing changed and no partial buffered, pass through as-is
|
|
94
|
+
if (stripped === str) {
|
|
95
|
+
return originalEmit(event, ...args);
|
|
100
96
|
}
|
|
97
|
+
// Swallow entirely if nothing left
|
|
98
|
+
if (stripped.length === 0)
|
|
99
|
+
return true;
|
|
100
|
+
// Forward cleaned data
|
|
101
|
+
const newData = raw instanceof Buffer
|
|
102
|
+
? Buffer.from(stripped, "latin1")
|
|
103
|
+
: stripped;
|
|
104
|
+
return originalEmit(event, newData);
|
|
101
105
|
}
|
|
102
|
-
// All other events pass through unchanged
|
|
103
106
|
return originalEmit(event, ...args);
|
|
104
107
|
};
|
|
105
108
|
return () => {
|
|
106
109
|
process.stdout.write(MOUSE_DISABLE);
|
|
107
110
|
process.stdin.emit = originalEmit;
|
|
108
111
|
delete process.stdin._yuanMousePatched;
|
|
112
|
+
partialBuf = "";
|
|
109
113
|
};
|
|
110
|
-
}, []);
|
|
114
|
+
}, []);
|
|
111
115
|
}
|
|
112
116
|
//# sourceMappingURL=useMouseScroll.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMouseScroll.js","sourceRoot":"","sources":["../../../src/tui/hooks/useMouseScroll.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useMouseScroll.js","sourceRoot":"","sources":["../../../src/tui/hooks/useMouseScroll.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuaone/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"description": "YUAN — Autonomous Coding Agent CLI",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"type": "module",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"string-width": "7.2.0",
|
|
49
49
|
"strip-ansi": "7.1.0",
|
|
50
50
|
"wrap-ansi": "9.0.0",
|
|
51
|
-
"@yuaone/
|
|
52
|
-
"@yuaone/
|
|
51
|
+
"@yuaone/tools": "0.9.0",
|
|
52
|
+
"@yuaone/core": "0.9.6"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^22.19.15",
|