saeeol 1.4.0 → 1.4.1
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 +1 -1
- package/src/server/routes/instance/httpapi/groups/ltm.ts +93 -0
- package/src/server/routes/instance/httpapi/handlers/ltm.ts +118 -0
- package/src/server/routes/instance/index.ts +96 -1
- package/test/smoke/.tui-input-report.txt +110 -0
- package/test/smoke/.tui-leader-report.txt +70 -0
- package/test/smoke/.tui-scroll-report.txt +66 -0
- package/test/smoke/.tui-slash-report.txt +146 -0
- package/test/smoke/.tui-system-report.txt +62 -0
- package/test/smoke/tui-walkthrough-driver.ts +232 -0
- package/test/smoke/tui-walkthrough-input.test.ts +286 -0
- package/test/smoke/tui-walkthrough-leader.test.ts +175 -0
- package/test/smoke/tui-walkthrough-scroll.test.ts +177 -0
- package/test/smoke/tui-walkthrough-slash.test.ts +302 -0
- package/test/smoke/tui-walkthrough-system.test.ts +210 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
=== slash-help (280 bytes) ===
|
|
2
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
=== slash-status (280 bytes) ===
|
|
6
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
=== slash-themes (280 bytes) ===
|
|
10
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
=== slash-models (280 bytes) ===
|
|
14
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
=== slash-agents (280 bytes) ===
|
|
18
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
=== slash-variants (280 bytes) ===
|
|
22
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
=== slash-sessions (280 bytes) ===
|
|
26
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
=== slash-resume (280 bytes) ===
|
|
30
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
=== slash-continue (280 bytes) ===
|
|
34
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
=== slash-new (280 bytes) ===
|
|
38
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
=== slash-clear (280 bytes) ===
|
|
42
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
=== slash-mcps (280 bytes) ===
|
|
46
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
=== slash-mcp-refresh (280 bytes) ===
|
|
50
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
=== slash-connect (280 bytes) ===
|
|
54
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
=== slash-timeline (280 bytes) ===
|
|
58
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
=== slash-compact (280 bytes) ===
|
|
62
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
=== slash-summarize (280 bytes) ===
|
|
66
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
=== slash-rename (280 bytes) ===
|
|
70
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
=== slash-fork (280 bytes) ===
|
|
74
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
=== slash-editor (280 bytes) ===
|
|
78
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
=== slash-skills (280 bytes) ===
|
|
82
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
=== slash-copy (280 bytes) ===
|
|
86
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
=== slash-export (280 bytes) ===
|
|
90
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
=== slash-timestamps (280 bytes) ===
|
|
94
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
=== slash-toggle-timestamps (280 bytes) ===
|
|
98
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
=== slash-thinking (280 bytes) ===
|
|
102
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
=== slash-toggle-thinking (280 bytes) ===
|
|
106
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
=== slash-pointing (280 bytes) ===
|
|
110
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
=== slash-point (280 bytes) ===
|
|
114
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
=== slash-unpointing (280 bytes) ===
|
|
118
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
=== slash-unpoint (280 bytes) ===
|
|
122
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
=== slash-share (280 bytes) ===
|
|
126
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
=== slash-unshare (280 bytes) ===
|
|
130
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
=== slash-undo (280 bytes) ===
|
|
134
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
=== slash-redo (280 bytes) ===
|
|
138
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
=== slash-logs (280 bytes) ===
|
|
142
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
=== slash-quit (280 bytes) ===
|
|
146
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
=== boot (280 bytes) ===
|
|
2
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
=== home (280 bytes) ===
|
|
6
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
=== slash-restart (280 bytes) ===
|
|
10
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
=== slash-rs (280 bytes) ===
|
|
14
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
=== toggle-notifications (280 bytes) ===
|
|
18
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
=== toggle-animations (280 bytes) ===
|
|
22
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
=== toggle-file-context (280 bytes) ===
|
|
26
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
=== toggle-paste-summary (280 bytes) ===
|
|
30
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
=== toggle-diffwrap (280 bytes) ===
|
|
34
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
=== toggle-session-dir-filter (280 bytes) ===
|
|
38
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
=== debug-overlay (280 bytes) ===
|
|
42
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
=== console-toggle (280 bytes) ===
|
|
46
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
=== slash-org (280 bytes) ===
|
|
50
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
=== slash-orgs (280 bytes) ===
|
|
54
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
=== slash-switch-org (280 bytes) ===
|
|
58
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
=== slash-q-exit (280 bytes) ===
|
|
62
|
+
s service=default e=Export named 'jsx' not found in module 'C:\Users\PC\Desktop\SAEEOL\node_modules\.bun\@opentui+solid@0.2.2+37848aaf691d3d45\node_modules\@opentui\solid\jsx-runtime.d.ts'. exception
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tui-walkthrough-driver.ts — 공유 TUI PTY 드라이버
|
|
3
|
+
*
|
|
4
|
+
* 모든 walkthrough 테스트가 사용하는 공통 유틸리티.
|
|
5
|
+
* bun-pty 기반 TUI 제어 + 에러 감지.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { spawn as PtySpawn, type IPty } from "bun-pty"
|
|
9
|
+
import path from "path"
|
|
10
|
+
|
|
11
|
+
const BIN = path.resolve(import.meta.dir, "../../bin/saeeol.cjs")
|
|
12
|
+
|
|
13
|
+
// ── ANSI 제거 ──
|
|
14
|
+
|
|
15
|
+
export function stripAnsi(s: string): string {
|
|
16
|
+
return s
|
|
17
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "")
|
|
18
|
+
.replace(/\x1b\].*?\x07/g, "")
|
|
19
|
+
.replace(/\x1b\[.*?m/g, "")
|
|
20
|
+
.replace(/[\x00-\x09\x0b\x0c\x0e-\x1f]/g, "")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ── Known issues — 해결되면 배열에서 제거 ──
|
|
24
|
+
|
|
25
|
+
const KNOWN_ISSUES = [
|
|
26
|
+
/export named 'jsx' not found in module.*@opentui\/solid\/jsx-runtime/i,
|
|
27
|
+
/e=Export named 'jsx' not found.*exception/i,
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
export function hasError(plain: string): string[] {
|
|
31
|
+
return plain
|
|
32
|
+
.split("\n")
|
|
33
|
+
.filter((l) => {
|
|
34
|
+
const t = l.trim()
|
|
35
|
+
if (!t) return false
|
|
36
|
+
if (KNOWN_ISSUES.some((re) => re.test(t))) return false
|
|
37
|
+
return (
|
|
38
|
+
/unhandled|TypeError|ReferenceError|SyntaxError|Cannot find module|Error:/i.test(t) ||
|
|
39
|
+
/exception/i.test(t) ||
|
|
40
|
+
/\be=\b.*not found/i.test(t) ||
|
|
41
|
+
/crashed|fatal|panic/i.test(t)
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── PTY 키 시퀀스 ──
|
|
47
|
+
|
|
48
|
+
export const Key = {
|
|
49
|
+
// 제어 문자
|
|
50
|
+
ctrl: (ch: string) => {
|
|
51
|
+
const code = ch.charCodeAt(0) - 96
|
|
52
|
+
return String.fromCharCode(code < 0 ? code + 64 : code)
|
|
53
|
+
},
|
|
54
|
+
esc: "\x1b",
|
|
55
|
+
enter: "\r",
|
|
56
|
+
tab: "\t",
|
|
57
|
+
backspace: "\x7f",
|
|
58
|
+
delete: "\x1b[3~",
|
|
59
|
+
// 화살표
|
|
60
|
+
up: "\x1b[A",
|
|
61
|
+
down: "\x1b[B",
|
|
62
|
+
right: "\x1b[C",
|
|
63
|
+
left: "\x1b[D",
|
|
64
|
+
// 기능키
|
|
65
|
+
f1: "\x1bOP",
|
|
66
|
+
f2: "\x1bOQ",
|
|
67
|
+
f3: "\x1bOR",
|
|
68
|
+
f4: "\x1bOS",
|
|
69
|
+
// 네비게이션
|
|
70
|
+
home: "\x1b[H",
|
|
71
|
+
end: "\x1b[F",
|
|
72
|
+
pageUp: "\x1b[5~",
|
|
73
|
+
pageDown: "\x1b[6~",
|
|
74
|
+
// 수정자 조합
|
|
75
|
+
ctrlUp: "\x1b[1;5A",
|
|
76
|
+
ctrlDown: "\x1b[1;5B",
|
|
77
|
+
ctrlRight: "\x1b[1;5C",
|
|
78
|
+
ctrlLeft: "\x1b[1;5D",
|
|
79
|
+
shiftUp: "\x1b[1;2A",
|
|
80
|
+
shiftDown: "\x1b[1;2B",
|
|
81
|
+
shiftRight: "\x1b[1;2C",
|
|
82
|
+
shiftLeft: "\x1b[1;2D",
|
|
83
|
+
shiftTab: "\x1b[Z",
|
|
84
|
+
altA: "\x1ba",
|
|
85
|
+
altE: "\x1be",
|
|
86
|
+
altF: "\x1bf",
|
|
87
|
+
altB: "\x1bb",
|
|
88
|
+
altD: "\x1bd",
|
|
89
|
+
// ctrl+조합
|
|
90
|
+
ctrlA: "\x01",
|
|
91
|
+
ctrlB: "\x02",
|
|
92
|
+
ctrlC: "\x03",
|
|
93
|
+
ctrlD: "\x04",
|
|
94
|
+
ctrlE: "\x05",
|
|
95
|
+
ctrlF: "\x06",
|
|
96
|
+
ctrlG: "\x07",
|
|
97
|
+
ctrlK: "\x0b",
|
|
98
|
+
ctrlN: "\x0e",
|
|
99
|
+
ctrlP: "\x10",
|
|
100
|
+
ctrlR: "\x12",
|
|
101
|
+
ctrlT: "\x14",
|
|
102
|
+
ctrlU: "\x15",
|
|
103
|
+
ctrlV: "\x16",
|
|
104
|
+
ctrlW: "\x17",
|
|
105
|
+
ctrlX: "\x18", // leader
|
|
106
|
+
ctrlZ: "\x1a",
|
|
107
|
+
// ctrl+shift
|
|
108
|
+
ctrlShiftA: "\x1b[1;6A", // 실제로는 다를 수 있음 — 터미널에 따라 다름
|
|
109
|
+
ctrlShiftD: "\x1b[1;6D",
|
|
110
|
+
ctrlShiftE: "\x1b[1;6E",
|
|
111
|
+
ctrlPageUp: "\x1b[5;5~",
|
|
112
|
+
ctrlPageDown: "\x1b[6;5~",
|
|
113
|
+
shiftF2: "\x1b[1;2Q",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ── TUI 드라이버 ──
|
|
117
|
+
|
|
118
|
+
export class TuiDriver {
|
|
119
|
+
pty: IPty
|
|
120
|
+
output = ""
|
|
121
|
+
snapshots: Array<{ name: string; raw: string; plain: string }> = []
|
|
122
|
+
private exited = false
|
|
123
|
+
|
|
124
|
+
constructor(cwd: string, env?: Record<string, string>) {
|
|
125
|
+
this.pty = PtySpawn("node", [BIN, "tui"], {
|
|
126
|
+
name: "xterm-256color",
|
|
127
|
+
cols: 120,
|
|
128
|
+
rows: 30,
|
|
129
|
+
cwd,
|
|
130
|
+
env: {
|
|
131
|
+
...process.env,
|
|
132
|
+
TERM: "xterm-256color",
|
|
133
|
+
FORCE_COLOR: "1",
|
|
134
|
+
SAEEOL_LLM_PROVIDER: "custom",
|
|
135
|
+
SAEEOL_LLM_BASE_URL: "http://localhost:1",
|
|
136
|
+
SAEEOL_LLM_API_KEY: "test",
|
|
137
|
+
SAEEOL_LLM_MODEL: "test",
|
|
138
|
+
...env,
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
this.pty.onData((data) => {
|
|
142
|
+
this.output += data
|
|
143
|
+
})
|
|
144
|
+
this.pty.onExit(() => {
|
|
145
|
+
this.exited = true
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
write(s: string) {
|
|
150
|
+
this.pty.write(s)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async wait(ms: number) {
|
|
154
|
+
await Bun.sleep(ms)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
snapshot(name: string) {
|
|
158
|
+
const raw = this.output
|
|
159
|
+
const plain = stripAnsi(this.output)
|
|
160
|
+
this.snapshots.push({ name, raw, plain })
|
|
161
|
+
return { raw, plain }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
errors(): string[] {
|
|
165
|
+
return hasError(stripAnsi(this.output))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 마지막 스냅샷 이후 새로 발생한 에러만 */
|
|
169
|
+
newErrors(): string[] {
|
|
170
|
+
const prev = this.snapshots.length >= 2
|
|
171
|
+
? stripAnsi(this.snapshots[this.snapshots.length - 2].raw)
|
|
172
|
+
: ""
|
|
173
|
+
const curr = stripAnsi(this.output)
|
|
174
|
+
if (!prev) return hasError(curr)
|
|
175
|
+
// prev에 없던 에러 라인만
|
|
176
|
+
const prevSet = new Set(prev.split("\n").map((l) => l.trim()))
|
|
177
|
+
return hasError(curr).filter((l) => !prevSet.has(l.trim()))
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async kill() {
|
|
181
|
+
try {
|
|
182
|
+
this.pty.kill()
|
|
183
|
+
} catch {}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
get isExited() {
|
|
187
|
+
return this.exited
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** 특정 텍스트가 화면에 나타날 때까지 대기 */
|
|
191
|
+
async waitFor(text: string, timeoutMs = 10000): Promise<boolean> {
|
|
192
|
+
const start = Date.now()
|
|
193
|
+
while (Date.now() - start < timeoutMs) {
|
|
194
|
+
if (stripAnsi(this.output).includes(text)) return true
|
|
195
|
+
await Bun.sleep(200)
|
|
196
|
+
}
|
|
197
|
+
return false
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** leader 키 (ctrl+x) + 후속 키 */
|
|
201
|
+
async leader(key: string, delay = 100) {
|
|
202
|
+
this.write(Key.ctrlX)
|
|
203
|
+
await this.wait(delay)
|
|
204
|
+
this.write(key)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** 에스케이프로 다이얼로그 닫기 */
|
|
208
|
+
async dismiss(delay = 500) {
|
|
209
|
+
this.write(Key.esc)
|
|
210
|
+
await this.wait(delay)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** 슬래시 명령어 실행 */
|
|
214
|
+
async slash(cmd: string, delay = 500) {
|
|
215
|
+
this.write(`/${cmd}`)
|
|
216
|
+
await this.wait(delay)
|
|
217
|
+
this.write(Key.enter)
|
|
218
|
+
await this.wait(1500)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** 스냅샷 리포트 저장 */
|
|
222
|
+
async saveReport(filename: string) {
|
|
223
|
+
const reportPath = path.join(import.meta.dir, filename)
|
|
224
|
+
const report = this.snapshots
|
|
225
|
+
.map(
|
|
226
|
+
(s) =>
|
|
227
|
+
`=== ${s.name} (${s.raw.length} bytes) ===\n${s.plain.slice(-500)}`,
|
|
228
|
+
)
|
|
229
|
+
.join("\n\n")
|
|
230
|
+
await Bun.write(reportPath, report)
|
|
231
|
+
}
|
|
232
|
+
}
|