@vsuryav/agent-sim 0.1.0
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/README.md +25 -0
- package/bin/agent-sim.js +25 -0
- package/package.json +72 -0
- package/src/app-paths.ts +29 -0
- package/src/app-sync.test.ts +75 -0
- package/src/app-sync.ts +110 -0
- package/src/cli.ts +129 -0
- package/src/collector/claude-code.test.ts +102 -0
- package/src/collector/claude-code.ts +133 -0
- package/src/collector/codex-cli.test.ts +116 -0
- package/src/collector/codex-cli.ts +149 -0
- package/src/collector/db.test.ts +59 -0
- package/src/collector/db.ts +125 -0
- package/src/collector/names.test.ts +21 -0
- package/src/collector/names.ts +28 -0
- package/src/collector/personality.test.ts +40 -0
- package/src/collector/personality.ts +46 -0
- package/src/collector/remote-sync.test.ts +31 -0
- package/src/collector/remote-sync.ts +171 -0
- package/src/collector/sync.test.ts +67 -0
- package/src/collector/sync.ts +148 -0
- package/src/collector/types.ts +1 -0
- package/src/engine/bootstrap/state.ts +3 -0
- package/src/engine/buddy/CompanionSprite.tsx +371 -0
- package/src/engine/buddy/companion.ts +133 -0
- package/src/engine/buddy/prompt.ts +36 -0
- package/src/engine/buddy/sprites.ts +514 -0
- package/src/engine/buddy/types.ts +148 -0
- package/src/engine/buddy/useBuddyNotification.tsx +98 -0
- package/src/engine/ink/Ansi.tsx +292 -0
- package/src/engine/ink/bidi.ts +139 -0
- package/src/engine/ink/clearTerminal.ts +74 -0
- package/src/engine/ink/colorize.ts +231 -0
- package/src/engine/ink/components/AlternateScreen.tsx +80 -0
- package/src/engine/ink/components/App.tsx +658 -0
- package/src/engine/ink/components/AppContext.ts +21 -0
- package/src/engine/ink/components/Box.tsx +214 -0
- package/src/engine/ink/components/Button.tsx +192 -0
- package/src/engine/ink/components/ClockContext.tsx +112 -0
- package/src/engine/ink/components/CursorDeclarationContext.ts +32 -0
- package/src/engine/ink/components/ErrorOverview.tsx +109 -0
- package/src/engine/ink/components/Link.tsx +42 -0
- package/src/engine/ink/components/Newline.tsx +39 -0
- package/src/engine/ink/components/NoSelect.tsx +68 -0
- package/src/engine/ink/components/RawAnsi.tsx +57 -0
- package/src/engine/ink/components/ScrollBox.tsx +237 -0
- package/src/engine/ink/components/Spacer.tsx +20 -0
- package/src/engine/ink/components/StdinContext.ts +49 -0
- package/src/engine/ink/components/TerminalFocusContext.tsx +52 -0
- package/src/engine/ink/components/TerminalSizeContext.tsx +7 -0
- package/src/engine/ink/components/Text.tsx +254 -0
- package/src/engine/ink/constants.ts +2 -0
- package/src/engine/ink/dom.ts +484 -0
- package/src/engine/ink/events/click-event.ts +38 -0
- package/src/engine/ink/events/dispatcher.ts +233 -0
- package/src/engine/ink/events/emitter.ts +39 -0
- package/src/engine/ink/events/event-handlers.ts +73 -0
- package/src/engine/ink/events/event.ts +11 -0
- package/src/engine/ink/events/focus-event.ts +21 -0
- package/src/engine/ink/events/input-event.ts +205 -0
- package/src/engine/ink/events/keyboard-event.ts +51 -0
- package/src/engine/ink/events/terminal-event.ts +107 -0
- package/src/engine/ink/events/terminal-focus-event.ts +19 -0
- package/src/engine/ink/focus.ts +181 -0
- package/src/engine/ink/frame.ts +124 -0
- package/src/engine/ink/get-max-width.ts +27 -0
- package/src/engine/ink/global.d.ts +18 -0
- package/src/engine/ink/hit-test.ts +130 -0
- package/src/engine/ink/hooks/use-animation-frame.ts +57 -0
- package/src/engine/ink/hooks/use-app.ts +8 -0
- package/src/engine/ink/hooks/use-declared-cursor.ts +73 -0
- package/src/engine/ink/hooks/use-input.ts +92 -0
- package/src/engine/ink/hooks/use-interval.ts +67 -0
- package/src/engine/ink/hooks/use-search-highlight.ts +53 -0
- package/src/engine/ink/hooks/use-selection.ts +104 -0
- package/src/engine/ink/hooks/use-stdin.ts +8 -0
- package/src/engine/ink/hooks/use-tab-status.ts +72 -0
- package/src/engine/ink/hooks/use-terminal-focus.ts +16 -0
- package/src/engine/ink/hooks/use-terminal-title.ts +31 -0
- package/src/engine/ink/hooks/use-terminal-viewport.ts +96 -0
- package/src/engine/ink/ink.tsx +1723 -0
- package/src/engine/ink/instances.ts +10 -0
- package/src/engine/ink/layout/engine.ts +6 -0
- package/src/engine/ink/layout/geometry.ts +97 -0
- package/src/engine/ink/layout/node.ts +152 -0
- package/src/engine/ink/layout/yoga.ts +308 -0
- package/src/engine/ink/line-width-cache.ts +24 -0
- package/src/engine/ink/log-update.ts +773 -0
- package/src/engine/ink/measure-element.ts +23 -0
- package/src/engine/ink/measure-text.ts +47 -0
- package/src/engine/ink/node-cache.ts +54 -0
- package/src/engine/ink/optimizer.ts +93 -0
- package/src/engine/ink/output.ts +797 -0
- package/src/engine/ink/parse-keypress.ts +801 -0
- package/src/engine/ink/reconciler.ts +512 -0
- package/src/engine/ink/render-border.ts +231 -0
- package/src/engine/ink/render-node-to-output.ts +1462 -0
- package/src/engine/ink/render-to-screen.ts +231 -0
- package/src/engine/ink/renderer.ts +178 -0
- package/src/engine/ink/root.ts +184 -0
- package/src/engine/ink/screen.ts +1486 -0
- package/src/engine/ink/searchHighlight.ts +93 -0
- package/src/engine/ink/selection.ts +917 -0
- package/src/engine/ink/squash-text-nodes.ts +92 -0
- package/src/engine/ink/stringWidth.ts +222 -0
- package/src/engine/ink/styles.ts +771 -0
- package/src/engine/ink/supports-hyperlinks.ts +57 -0
- package/src/engine/ink/tabstops.ts +46 -0
- package/src/engine/ink/terminal-focus-state.ts +47 -0
- package/src/engine/ink/terminal-querier.ts +212 -0
- package/src/engine/ink/terminal.ts +248 -0
- package/src/engine/ink/termio/ansi.ts +75 -0
- package/src/engine/ink/termio/csi.ts +319 -0
- package/src/engine/ink/termio/dec.ts +60 -0
- package/src/engine/ink/termio/esc.ts +67 -0
- package/src/engine/ink/termio/osc.ts +493 -0
- package/src/engine/ink/termio/parser.ts +394 -0
- package/src/engine/ink/termio/sgr.ts +308 -0
- package/src/engine/ink/termio/tokenize.ts +319 -0
- package/src/engine/ink/termio/types.ts +236 -0
- package/src/engine/ink/useTerminalNotification.ts +126 -0
- package/src/engine/ink/warn.ts +9 -0
- package/src/engine/ink/widest-line.ts +19 -0
- package/src/engine/ink/wrap-text.ts +74 -0
- package/src/engine/ink/wrapAnsi.ts +20 -0
- package/src/engine/native-ts/yoga-layout/enums.ts +134 -0
- package/src/engine/native-ts/yoga-layout/index.ts +2578 -0
- package/src/engine/stubs/bootstrap-state.ts +4 -0
- package/src/engine/stubs/debug.ts +6 -0
- package/src/engine/stubs/log.ts +4 -0
- package/src/engine/utils/debug.ts +5 -0
- package/src/engine/utils/earlyInput.ts +4 -0
- package/src/engine/utils/env.ts +15 -0
- package/src/engine/utils/envUtils.ts +4 -0
- package/src/engine/utils/execFileNoThrow.ts +24 -0
- package/src/engine/utils/fullscreen.ts +4 -0
- package/src/engine/utils/intl.ts +9 -0
- package/src/engine/utils/log.ts +3 -0
- package/src/engine/utils/semver.ts +13 -0
- package/src/engine/utils/sliceAnsi.ts +10 -0
- package/src/engine/utils/theme.ts +17 -0
- package/src/game/App.tsx +141 -0
- package/src/game/agents/behavior.ts +249 -0
- package/src/game/agents/speech.ts +57 -0
- package/src/game/canvas.ts +98 -0
- package/src/game/launch.ts +36 -0
- package/src/game/ship/ShipView.tsx +145 -0
- package/src/game/ship/ship-map.ts +172 -0
- package/src/game/ui/AgentBio.tsx +72 -0
- package/src/game/ui/HUD.tsx +63 -0
- package/src/game/ui/StatusBar.tsx +49 -0
- package/src/game/useKeyboard.ts +62 -0
- package/src/main.tsx +22 -0
- package/src/run-interactive.ts +74 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSI (Control Sequence Introducer) Types
|
|
3
|
+
*
|
|
4
|
+
* Enums and types for CSI command parameters.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ESC, ESC_TYPE, SEP } from './ansi.js'
|
|
8
|
+
|
|
9
|
+
export const CSI_PREFIX = ESC + String.fromCharCode(ESC_TYPE.CSI)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* CSI parameter byte ranges
|
|
13
|
+
*/
|
|
14
|
+
export const CSI_RANGE = {
|
|
15
|
+
PARAM_START: 0x30,
|
|
16
|
+
PARAM_END: 0x3f,
|
|
17
|
+
INTERMEDIATE_START: 0x20,
|
|
18
|
+
INTERMEDIATE_END: 0x2f,
|
|
19
|
+
FINAL_START: 0x40,
|
|
20
|
+
FINAL_END: 0x7e,
|
|
21
|
+
} as const
|
|
22
|
+
|
|
23
|
+
/** Check if a byte is a CSI parameter byte */
|
|
24
|
+
export function isCSIParam(byte: number): boolean {
|
|
25
|
+
return byte >= CSI_RANGE.PARAM_START && byte <= CSI_RANGE.PARAM_END
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Check if a byte is a CSI intermediate byte */
|
|
29
|
+
export function isCSIIntermediate(byte: number): boolean {
|
|
30
|
+
return (
|
|
31
|
+
byte >= CSI_RANGE.INTERMEDIATE_START && byte <= CSI_RANGE.INTERMEDIATE_END
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Check if a byte is a CSI final byte (@ through ~) */
|
|
36
|
+
export function isCSIFinal(byte: number): boolean {
|
|
37
|
+
return byte >= CSI_RANGE.FINAL_START && byte <= CSI_RANGE.FINAL_END
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Generate a CSI sequence: ESC [ p1;p2;...;pN final
|
|
42
|
+
* Single arg: treated as raw body
|
|
43
|
+
* Multiple args: last is final byte, rest are params joined by ;
|
|
44
|
+
*/
|
|
45
|
+
export function csi(...args: (string | number)[]): string {
|
|
46
|
+
if (args.length === 0) return CSI_PREFIX
|
|
47
|
+
if (args.length === 1) return `${CSI_PREFIX}${args[0]}`
|
|
48
|
+
const params = args.slice(0, -1)
|
|
49
|
+
const final = args[args.length - 1]
|
|
50
|
+
return `${CSI_PREFIX}${params.join(SEP)}${final}`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* CSI final bytes - the command identifier
|
|
55
|
+
*/
|
|
56
|
+
export const CSI = {
|
|
57
|
+
// Cursor movement
|
|
58
|
+
CUU: 0x41, // A - Cursor Up
|
|
59
|
+
CUD: 0x42, // B - Cursor Down
|
|
60
|
+
CUF: 0x43, // C - Cursor Forward
|
|
61
|
+
CUB: 0x44, // D - Cursor Back
|
|
62
|
+
CNL: 0x45, // E - Cursor Next Line
|
|
63
|
+
CPL: 0x46, // F - Cursor Previous Line
|
|
64
|
+
CHA: 0x47, // G - Cursor Horizontal Absolute
|
|
65
|
+
CUP: 0x48, // H - Cursor Position
|
|
66
|
+
CHT: 0x49, // I - Cursor Horizontal Tab
|
|
67
|
+
VPA: 0x64, // d - Vertical Position Absolute
|
|
68
|
+
HVP: 0x66, // f - Horizontal Vertical Position
|
|
69
|
+
|
|
70
|
+
// Erase
|
|
71
|
+
ED: 0x4a, // J - Erase in Display
|
|
72
|
+
EL: 0x4b, // K - Erase in Line
|
|
73
|
+
ECH: 0x58, // X - Erase Character
|
|
74
|
+
|
|
75
|
+
// Insert/Delete
|
|
76
|
+
IL: 0x4c, // L - Insert Lines
|
|
77
|
+
DL: 0x4d, // M - Delete Lines
|
|
78
|
+
ICH: 0x40, // @ - Insert Characters
|
|
79
|
+
DCH: 0x50, // P - Delete Characters
|
|
80
|
+
|
|
81
|
+
// Scroll
|
|
82
|
+
SU: 0x53, // S - Scroll Up
|
|
83
|
+
SD: 0x54, // T - Scroll Down
|
|
84
|
+
|
|
85
|
+
// Modes
|
|
86
|
+
SM: 0x68, // h - Set Mode
|
|
87
|
+
RM: 0x6c, // l - Reset Mode
|
|
88
|
+
|
|
89
|
+
// SGR
|
|
90
|
+
SGR: 0x6d, // m - Select Graphic Rendition
|
|
91
|
+
|
|
92
|
+
// Other
|
|
93
|
+
DSR: 0x6e, // n - Device Status Report
|
|
94
|
+
DECSCUSR: 0x71, // q - Set Cursor Style (with space intermediate)
|
|
95
|
+
DECSTBM: 0x72, // r - Set Top and Bottom Margins
|
|
96
|
+
SCOSC: 0x73, // s - Save Cursor Position
|
|
97
|
+
SCORC: 0x75, // u - Restore Cursor Position
|
|
98
|
+
CBT: 0x5a, // Z - Cursor Backward Tabulation
|
|
99
|
+
} as const
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Erase in Display regions (ED command parameter)
|
|
103
|
+
*/
|
|
104
|
+
export const ERASE_DISPLAY = ['toEnd', 'toStart', 'all', 'scrollback'] as const
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Erase in Line regions (EL command parameter)
|
|
108
|
+
*/
|
|
109
|
+
export const ERASE_LINE_REGION = ['toEnd', 'toStart', 'all'] as const
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Cursor styles (DECSCUSR)
|
|
113
|
+
*/
|
|
114
|
+
export type CursorStyle = 'block' | 'underline' | 'bar'
|
|
115
|
+
|
|
116
|
+
export const CURSOR_STYLES: Array<{ style: CursorStyle; blinking: boolean }> = [
|
|
117
|
+
{ style: 'block', blinking: true }, // 0 - default
|
|
118
|
+
{ style: 'block', blinking: true }, // 1
|
|
119
|
+
{ style: 'block', blinking: false }, // 2
|
|
120
|
+
{ style: 'underline', blinking: true }, // 3
|
|
121
|
+
{ style: 'underline', blinking: false }, // 4
|
|
122
|
+
{ style: 'bar', blinking: true }, // 5
|
|
123
|
+
{ style: 'bar', blinking: false }, // 6
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
// Cursor movement generators
|
|
127
|
+
|
|
128
|
+
/** Move cursor up n lines (CSI n A) */
|
|
129
|
+
export function cursorUp(n = 1): string {
|
|
130
|
+
return n === 0 ? '' : csi(n, 'A')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Move cursor down n lines (CSI n B) */
|
|
134
|
+
export function cursorDown(n = 1): string {
|
|
135
|
+
return n === 0 ? '' : csi(n, 'B')
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Move cursor forward n columns (CSI n C) */
|
|
139
|
+
export function cursorForward(n = 1): string {
|
|
140
|
+
return n === 0 ? '' : csi(n, 'C')
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Move cursor back n columns (CSI n D) */
|
|
144
|
+
export function cursorBack(n = 1): string {
|
|
145
|
+
return n === 0 ? '' : csi(n, 'D')
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Move cursor to column n (1-indexed) (CSI n G) */
|
|
149
|
+
export function cursorTo(col: number): string {
|
|
150
|
+
return csi(col, 'G')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Move cursor to column 1 (CSI G) */
|
|
154
|
+
export const CURSOR_LEFT = csi('G')
|
|
155
|
+
|
|
156
|
+
/** Move cursor to row, col (1-indexed) (CSI row ; col H) */
|
|
157
|
+
export function cursorPosition(row: number, col: number): string {
|
|
158
|
+
return csi(row, col, 'H')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Move cursor to home position (CSI H) */
|
|
162
|
+
export const CURSOR_HOME = csi('H')
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Move cursor relative to current position
|
|
166
|
+
* Positive x = right, negative x = left
|
|
167
|
+
* Positive y = down, negative y = up
|
|
168
|
+
*/
|
|
169
|
+
export function cursorMove(x: number, y: number): string {
|
|
170
|
+
let result = ''
|
|
171
|
+
// Horizontal first (matches ansi-escapes behavior)
|
|
172
|
+
if (x < 0) {
|
|
173
|
+
result += cursorBack(-x)
|
|
174
|
+
} else if (x > 0) {
|
|
175
|
+
result += cursorForward(x)
|
|
176
|
+
}
|
|
177
|
+
// Then vertical
|
|
178
|
+
if (y < 0) {
|
|
179
|
+
result += cursorUp(-y)
|
|
180
|
+
} else if (y > 0) {
|
|
181
|
+
result += cursorDown(y)
|
|
182
|
+
}
|
|
183
|
+
return result
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Save/restore cursor position
|
|
187
|
+
|
|
188
|
+
/** Save cursor position (CSI s) */
|
|
189
|
+
export const CURSOR_SAVE = csi('s')
|
|
190
|
+
|
|
191
|
+
/** Restore cursor position (CSI u) */
|
|
192
|
+
export const CURSOR_RESTORE = csi('u')
|
|
193
|
+
|
|
194
|
+
// Erase generators
|
|
195
|
+
|
|
196
|
+
/** Erase from cursor to end of line (CSI K) */
|
|
197
|
+
export function eraseToEndOfLine(): string {
|
|
198
|
+
return csi('K')
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Erase from cursor to start of line (CSI 1 K) */
|
|
202
|
+
export function eraseToStartOfLine(): string {
|
|
203
|
+
return csi(1, 'K')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Erase entire line (CSI 2 K) */
|
|
207
|
+
export function eraseLine(): string {
|
|
208
|
+
return csi(2, 'K')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Erase entire line - constant form */
|
|
212
|
+
export const ERASE_LINE = csi(2, 'K')
|
|
213
|
+
|
|
214
|
+
/** Erase from cursor to end of screen (CSI J) */
|
|
215
|
+
export function eraseToEndOfScreen(): string {
|
|
216
|
+
return csi('J')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Erase from cursor to start of screen (CSI 1 J) */
|
|
220
|
+
export function eraseToStartOfScreen(): string {
|
|
221
|
+
return csi(1, 'J')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Erase entire screen (CSI 2 J) */
|
|
225
|
+
export function eraseScreen(): string {
|
|
226
|
+
return csi(2, 'J')
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Erase entire screen - constant form */
|
|
230
|
+
export const ERASE_SCREEN = csi(2, 'J')
|
|
231
|
+
|
|
232
|
+
/** Erase scrollback buffer (CSI 3 J) */
|
|
233
|
+
export const ERASE_SCROLLBACK = csi(3, 'J')
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Erase n lines starting from cursor line, moving cursor up
|
|
237
|
+
* This erases each line and moves up, ending at column 1
|
|
238
|
+
*/
|
|
239
|
+
export function eraseLines(n: number): string {
|
|
240
|
+
if (n <= 0) return ''
|
|
241
|
+
let result = ''
|
|
242
|
+
for (let i = 0; i < n; i++) {
|
|
243
|
+
result += ERASE_LINE
|
|
244
|
+
if (i < n - 1) {
|
|
245
|
+
result += cursorUp(1)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
result += CURSOR_LEFT
|
|
249
|
+
return result
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Scroll
|
|
253
|
+
|
|
254
|
+
/** Scroll up n lines (CSI n S) */
|
|
255
|
+
export function scrollUp(n = 1): string {
|
|
256
|
+
return n === 0 ? '' : csi(n, 'S')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Scroll down n lines (CSI n T) */
|
|
260
|
+
export function scrollDown(n = 1): string {
|
|
261
|
+
return n === 0 ? '' : csi(n, 'T')
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Set scroll region (DECSTBM, CSI top;bottom r). 1-indexed, inclusive. */
|
|
265
|
+
export function setScrollRegion(top: number, bottom: number): string {
|
|
266
|
+
return csi(top, bottom, 'r')
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Reset scroll region to full screen (DECSTBM, CSI r). Homes the cursor. */
|
|
270
|
+
export const RESET_SCROLL_REGION = csi('r')
|
|
271
|
+
|
|
272
|
+
// Bracketed paste markers (input from terminal, not output)
|
|
273
|
+
// These are sent by the terminal to delimit pasted content when
|
|
274
|
+
// bracketed paste mode is enabled (via DEC mode 2004)
|
|
275
|
+
|
|
276
|
+
/** Sent by terminal before pasted content (CSI 200 ~) */
|
|
277
|
+
export const PASTE_START = csi('200~')
|
|
278
|
+
|
|
279
|
+
/** Sent by terminal after pasted content (CSI 201 ~) */
|
|
280
|
+
export const PASTE_END = csi('201~')
|
|
281
|
+
|
|
282
|
+
// Focus event markers (input from terminal, not output)
|
|
283
|
+
// These are sent by the terminal when focus changes while
|
|
284
|
+
// focus events mode is enabled (via DEC mode 1004)
|
|
285
|
+
|
|
286
|
+
/** Sent by terminal when it gains focus (CSI I) */
|
|
287
|
+
export const FOCUS_IN = csi('I')
|
|
288
|
+
|
|
289
|
+
/** Sent by terminal when it loses focus (CSI O) */
|
|
290
|
+
export const FOCUS_OUT = csi('O')
|
|
291
|
+
|
|
292
|
+
// Kitty keyboard protocol (CSI u)
|
|
293
|
+
// Enables enhanced key reporting with modifier information
|
|
294
|
+
// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Enable Kitty keyboard protocol with basic modifier reporting
|
|
298
|
+
* CSI > 1 u - pushes mode with flags=1 (disambiguate escape codes)
|
|
299
|
+
* This makes Shift+Enter send CSI 13;2 u instead of just CR
|
|
300
|
+
*/
|
|
301
|
+
export const ENABLE_KITTY_KEYBOARD = csi('>1u')
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Disable Kitty keyboard protocol
|
|
305
|
+
* CSI < u - pops the keyboard mode stack
|
|
306
|
+
*/
|
|
307
|
+
export const DISABLE_KITTY_KEYBOARD = csi('<u')
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Enable xterm modifyOtherKeys level 2.
|
|
311
|
+
* tmux accepts this (not the kitty stack) to enable extended keys — when
|
|
312
|
+
* extended-keys-format is csi-u, tmux then emits keys in kitty format.
|
|
313
|
+
*/
|
|
314
|
+
export const ENABLE_MODIFY_OTHER_KEYS = csi('>4;2m')
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Disable xterm modifyOtherKeys (reset to default).
|
|
318
|
+
*/
|
|
319
|
+
export const DISABLE_MODIFY_OTHER_KEYS = csi('>4m')
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEC (Digital Equipment Corporation) Private Mode Sequences
|
|
3
|
+
*
|
|
4
|
+
* DEC private modes use CSI ? N h (set) and CSI ? N l (reset) format.
|
|
5
|
+
* These are terminal-specific extensions to the ANSI standard.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { csi } from './csi.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* DEC private mode numbers
|
|
12
|
+
*/
|
|
13
|
+
export const DEC = {
|
|
14
|
+
CURSOR_VISIBLE: 25,
|
|
15
|
+
ALT_SCREEN: 47,
|
|
16
|
+
ALT_SCREEN_CLEAR: 1049,
|
|
17
|
+
MOUSE_NORMAL: 1000,
|
|
18
|
+
MOUSE_BUTTON: 1002,
|
|
19
|
+
MOUSE_ANY: 1003,
|
|
20
|
+
MOUSE_SGR: 1006,
|
|
21
|
+
FOCUS_EVENTS: 1004,
|
|
22
|
+
BRACKETED_PASTE: 2004,
|
|
23
|
+
SYNCHRONIZED_UPDATE: 2026,
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
/** Generate CSI ? N h sequence (set mode) */
|
|
27
|
+
export function decset(mode: number): string {
|
|
28
|
+
return csi(`?${mode}h`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Generate CSI ? N l sequence (reset mode) */
|
|
32
|
+
export function decreset(mode: number): string {
|
|
33
|
+
return csi(`?${mode}l`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Pre-generated sequences for common modes
|
|
37
|
+
export const BSU = decset(DEC.SYNCHRONIZED_UPDATE)
|
|
38
|
+
export const ESU = decreset(DEC.SYNCHRONIZED_UPDATE)
|
|
39
|
+
export const EBP = decset(DEC.BRACKETED_PASTE)
|
|
40
|
+
export const DBP = decreset(DEC.BRACKETED_PASTE)
|
|
41
|
+
export const EFE = decset(DEC.FOCUS_EVENTS)
|
|
42
|
+
export const DFE = decreset(DEC.FOCUS_EVENTS)
|
|
43
|
+
export const SHOW_CURSOR = decset(DEC.CURSOR_VISIBLE)
|
|
44
|
+
export const HIDE_CURSOR = decreset(DEC.CURSOR_VISIBLE)
|
|
45
|
+
export const ENTER_ALT_SCREEN = decset(DEC.ALT_SCREEN_CLEAR)
|
|
46
|
+
export const EXIT_ALT_SCREEN = decreset(DEC.ALT_SCREEN_CLEAR)
|
|
47
|
+
// Mouse tracking: 1000 reports button press/release/wheel, 1002 adds drag
|
|
48
|
+
// events (button-motion), 1003 adds all-motion (no button held — for
|
|
49
|
+
// hover), 1006 uses SGR format (CSI < btn;col;row M/m) instead of legacy
|
|
50
|
+
// X10 bytes. Combined: wheel + click/drag for selection + hover.
|
|
51
|
+
export const ENABLE_MOUSE_TRACKING =
|
|
52
|
+
decset(DEC.MOUSE_NORMAL) +
|
|
53
|
+
decset(DEC.MOUSE_BUTTON) +
|
|
54
|
+
decset(DEC.MOUSE_ANY) +
|
|
55
|
+
decset(DEC.MOUSE_SGR)
|
|
56
|
+
export const DISABLE_MOUSE_TRACKING =
|
|
57
|
+
decreset(DEC.MOUSE_SGR) +
|
|
58
|
+
decreset(DEC.MOUSE_ANY) +
|
|
59
|
+
decreset(DEC.MOUSE_BUTTON) +
|
|
60
|
+
decreset(DEC.MOUSE_NORMAL)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESC Sequence Parser
|
|
3
|
+
*
|
|
4
|
+
* Handles simple escape sequences: ESC + one or two characters
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Action } from './types.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parse a simple ESC sequence
|
|
11
|
+
*
|
|
12
|
+
* @param chars - Characters after ESC (not including ESC itself)
|
|
13
|
+
*/
|
|
14
|
+
export function parseEsc(chars: string): Action | null {
|
|
15
|
+
if (chars.length === 0) return null
|
|
16
|
+
|
|
17
|
+
const first = chars[0]!
|
|
18
|
+
|
|
19
|
+
// Full reset (RIS)
|
|
20
|
+
if (first === 'c') {
|
|
21
|
+
return { type: 'reset' }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Cursor save (DECSC)
|
|
25
|
+
if (first === '7') {
|
|
26
|
+
return { type: 'cursor', action: { type: 'save' } }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Cursor restore (DECRC)
|
|
30
|
+
if (first === '8') {
|
|
31
|
+
return { type: 'cursor', action: { type: 'restore' } }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Index - move cursor down (IND)
|
|
35
|
+
if (first === 'D') {
|
|
36
|
+
return {
|
|
37
|
+
type: 'cursor',
|
|
38
|
+
action: { type: 'move', direction: 'down', count: 1 },
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Reverse index - move cursor up (RI)
|
|
43
|
+
if (first === 'M') {
|
|
44
|
+
return {
|
|
45
|
+
type: 'cursor',
|
|
46
|
+
action: { type: 'move', direction: 'up', count: 1 },
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Next line (NEL)
|
|
51
|
+
if (first === 'E') {
|
|
52
|
+
return { type: 'cursor', action: { type: 'nextLine', count: 1 } }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Horizontal tab set (HTS)
|
|
56
|
+
if (first === 'H') {
|
|
57
|
+
return null // Tab stop, not commonly needed
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Charset selection (ESC ( X, ESC ) X, etc.) - silently ignore
|
|
61
|
+
if ('()'.includes(first) && chars.length >= 2) {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Unknown
|
|
66
|
+
return { type: 'unknown', sequence: `\x1b${chars}` }
|
|
67
|
+
}
|