@carboncode/cli 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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/DeepSeek-Reasonix-MIT.txt +21 -0
  3. package/README.md +109 -0
  4. package/README.zh-CN.md +91 -0
  5. package/THIRD_PARTY_NOTICES.md +14 -0
  6. package/dashboard/app.css +3233 -0
  7. package/dashboard/dist/app.js +30444 -0
  8. package/dashboard/dist/app.js.map +1 -0
  9. package/dashboard/dist/vendor-hljs.css +10 -0
  10. package/dashboard/dist/vendor-uplot.css +1 -0
  11. package/dashboard/index.html +19 -0
  12. package/data/deepseek-tokenizer.json.gz +0 -0
  13. package/dist/cli/acp-35C4ME6Y.js +711 -0
  14. package/dist/cli/acp-35C4ME6Y.js.map +1 -0
  15. package/dist/cli/chat-A6UJDPGV.js +51 -0
  16. package/dist/cli/chat-A6UJDPGV.js.map +1 -0
  17. package/dist/cli/chunk-2425HK6U.js +54 -0
  18. package/dist/cli/chunk-2425HK6U.js.map +1 -0
  19. package/dist/cli/chunk-25T6CVUP.js +172 -0
  20. package/dist/cli/chunk-25T6CVUP.js.map +1 -0
  21. package/dist/cli/chunk-2UQP6H6T.js +31 -0
  22. package/dist/cli/chunk-2UQP6H6T.js.map +1 -0
  23. package/dist/cli/chunk-3OAR6NVL.js +96 -0
  24. package/dist/cli/chunk-3OAR6NVL.js.map +1 -0
  25. package/dist/cli/chunk-3T6VBZCL.js +54 -0
  26. package/dist/cli/chunk-3T6VBZCL.js.map +1 -0
  27. package/dist/cli/chunk-4IBIPQVB.js +153 -0
  28. package/dist/cli/chunk-4IBIPQVB.js.map +1 -0
  29. package/dist/cli/chunk-4MQ3VURH.js +3106 -0
  30. package/dist/cli/chunk-4MQ3VURH.js.map +1 -0
  31. package/dist/cli/chunk-4TVNJWMA.js +11619 -0
  32. package/dist/cli/chunk-4TVNJWMA.js.map +1 -0
  33. package/dist/cli/chunk-4VR6XF4P.js +341 -0
  34. package/dist/cli/chunk-4VR6XF4P.js.map +1 -0
  35. package/dist/cli/chunk-5QCB62C4.js +25319 -0
  36. package/dist/cli/chunk-5QCB62C4.js.map +1 -0
  37. package/dist/cli/chunk-6OWJV3YW.js +390 -0
  38. package/dist/cli/chunk-6OWJV3YW.js.map +1 -0
  39. package/dist/cli/chunk-7EO27TB3.js +130 -0
  40. package/dist/cli/chunk-7EO27TB3.js.map +1 -0
  41. package/dist/cli/chunk-7L2WTRNU.js +308 -0
  42. package/dist/cli/chunk-7L2WTRNU.js.map +1 -0
  43. package/dist/cli/chunk-BHTZFEYE.js +47 -0
  44. package/dist/cli/chunk-BHTZFEYE.js.map +1 -0
  45. package/dist/cli/chunk-BSGCXZQN.js +343 -0
  46. package/dist/cli/chunk-BSGCXZQN.js.map +1 -0
  47. package/dist/cli/chunk-BSINVTTL.js +464 -0
  48. package/dist/cli/chunk-BSINVTTL.js.map +1 -0
  49. package/dist/cli/chunk-CPKCNHRR.js +323 -0
  50. package/dist/cli/chunk-CPKCNHRR.js.map +1 -0
  51. package/dist/cli/chunk-CXVWUPA3.js +96 -0
  52. package/dist/cli/chunk-CXVWUPA3.js.map +1 -0
  53. package/dist/cli/chunk-D5NFKRGO.js +160 -0
  54. package/dist/cli/chunk-D5NFKRGO.js.map +1 -0
  55. package/dist/cli/chunk-ECHSFYOY.js +109 -0
  56. package/dist/cli/chunk-ECHSFYOY.js.map +1 -0
  57. package/dist/cli/chunk-FEZK652I.js +3644 -0
  58. package/dist/cli/chunk-FEZK652I.js.map +1 -0
  59. package/dist/cli/chunk-GALC45Q2.js +696 -0
  60. package/dist/cli/chunk-GALC45Q2.js.map +1 -0
  61. package/dist/cli/chunk-IAUOP25G.js +2984 -0
  62. package/dist/cli/chunk-IAUOP25G.js.map +1 -0
  63. package/dist/cli/chunk-ILJOIQ5W.js +163 -0
  64. package/dist/cli/chunk-ILJOIQ5W.js.map +1 -0
  65. package/dist/cli/chunk-IX6XI2RG.js +225 -0
  66. package/dist/cli/chunk-IX6XI2RG.js.map +1 -0
  67. package/dist/cli/chunk-J5BYPUB5.js +62795 -0
  68. package/dist/cli/chunk-J5BYPUB5.js.map +1 -0
  69. package/dist/cli/chunk-J5XJHLWM.js +55 -0
  70. package/dist/cli/chunk-J5XJHLWM.js.map +1 -0
  71. package/dist/cli/chunk-JKGYMRX5.js +101 -0
  72. package/dist/cli/chunk-JKGYMRX5.js.map +1 -0
  73. package/dist/cli/chunk-JMBMLOBP.js +26 -0
  74. package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
  75. package/dist/cli/chunk-LN3B5PMX.js +128 -0
  76. package/dist/cli/chunk-LN3B5PMX.js.map +1 -0
  77. package/dist/cli/chunk-M2UFZUX3.js +635 -0
  78. package/dist/cli/chunk-M2UFZUX3.js.map +1 -0
  79. package/dist/cli/chunk-PJS34556.js +809 -0
  80. package/dist/cli/chunk-PJS34556.js.map +1 -0
  81. package/dist/cli/chunk-QJG7OF27.js +655 -0
  82. package/dist/cli/chunk-QJG7OF27.js.map +1 -0
  83. package/dist/cli/chunk-QVC75MR3.js +232 -0
  84. package/dist/cli/chunk-QVC75MR3.js.map +1 -0
  85. package/dist/cli/chunk-S2KIUQKQ.js +378 -0
  86. package/dist/cli/chunk-S2KIUQKQ.js.map +1 -0
  87. package/dist/cli/chunk-S4XVGLRW.js +499 -0
  88. package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
  89. package/dist/cli/chunk-T5TQ4NDT.js +190 -0
  90. package/dist/cli/chunk-T5TQ4NDT.js.map +1 -0
  91. package/dist/cli/chunk-TH756VLN.js +1924 -0
  92. package/dist/cli/chunk-TH756VLN.js.map +1 -0
  93. package/dist/cli/chunk-TUK7OWJA.js +51 -0
  94. package/dist/cli/chunk-TUK7OWJA.js.map +1 -0
  95. package/dist/cli/chunk-U4IJVG32.js +363 -0
  96. package/dist/cli/chunk-U4IJVG32.js.map +1 -0
  97. package/dist/cli/chunk-UI66BH6D.js +624 -0
  98. package/dist/cli/chunk-UI66BH6D.js.map +1 -0
  99. package/dist/cli/chunk-VPMBGAND.js +53 -0
  100. package/dist/cli/chunk-VPMBGAND.js.map +1 -0
  101. package/dist/cli/chunk-WLHH3OSR.js +522 -0
  102. package/dist/cli/chunk-WLHH3OSR.js.map +1 -0
  103. package/dist/cli/chunk-WRN65TRD.js +908 -0
  104. package/dist/cli/chunk-WRN65TRD.js.map +1 -0
  105. package/dist/cli/chunk-X53B3JIX.js +34320 -0
  106. package/dist/cli/chunk-X53B3JIX.js.map +1 -0
  107. package/dist/cli/chunk-XJ5SRLKK.js +50 -0
  108. package/dist/cli/chunk-XJ5SRLKK.js.map +1 -0
  109. package/dist/cli/chunk-YZSXRGFH.js +54 -0
  110. package/dist/cli/chunk-YZSXRGFH.js.map +1 -0
  111. package/dist/cli/code-4TUTAGO5.js +163 -0
  112. package/dist/cli/code-4TUTAGO5.js.map +1 -0
  113. package/dist/cli/commands-KMOZEYCF.js +356 -0
  114. package/dist/cli/commands-KMOZEYCF.js.map +1 -0
  115. package/dist/cli/commit-DTFA56VQ.js +292 -0
  116. package/dist/cli/commit-DTFA56VQ.js.map +1 -0
  117. package/dist/cli/desktop-7N3MHNBD.js +1274 -0
  118. package/dist/cli/desktop-7N3MHNBD.js.map +1 -0
  119. package/dist/cli/devtools-HW3WDT3Q.js +91 -0
  120. package/dist/cli/devtools-HW3WDT3Q.js.map +1 -0
  121. package/dist/cli/diff-E5OWTF4C.js +165 -0
  122. package/dist/cli/diff-E5OWTF4C.js.map +1 -0
  123. package/dist/cli/doctor-IEJQRJMN.js +27 -0
  124. package/dist/cli/doctor-IEJQRJMN.js.map +1 -0
  125. package/dist/cli/events-4625EGXI.js +340 -0
  126. package/dist/cli/events-4625EGXI.js.map +1 -0
  127. package/dist/cli/index.js +3536 -0
  128. package/dist/cli/index.js.map +1 -0
  129. package/dist/cli/mcp-PDI2PDLG.js +277 -0
  130. package/dist/cli/mcp-PDI2PDLG.js.map +1 -0
  131. package/dist/cli/mcp-browse-OSPXOFPZ.js +178 -0
  132. package/dist/cli/mcp-browse-OSPXOFPZ.js.map +1 -0
  133. package/dist/cli/mcp-inspect-QRFVTHMF.js +148 -0
  134. package/dist/cli/mcp-inspect-QRFVTHMF.js.map +1 -0
  135. package/dist/cli/package.json +3 -0
  136. package/dist/cli/prompt-3CDII3UO.js +16 -0
  137. package/dist/cli/prompt-3CDII3UO.js.map +1 -0
  138. package/dist/cli/prune-sessions-KZX4SXKW.js +44 -0
  139. package/dist/cli/prune-sessions-KZX4SXKW.js.map +1 -0
  140. package/dist/cli/replay-HYOSRQIV.js +291 -0
  141. package/dist/cli/replay-HYOSRQIV.js.map +1 -0
  142. package/dist/cli/run-2ZHADOUP.js +220 -0
  143. package/dist/cli/run-2ZHADOUP.js.map +1 -0
  144. package/dist/cli/server-X75PAZG5.js +3572 -0
  145. package/dist/cli/server-X75PAZG5.js.map +1 -0
  146. package/dist/cli/sessions-POOZA5CQ.js +120 -0
  147. package/dist/cli/sessions-POOZA5CQ.js.map +1 -0
  148. package/dist/cli/setup-YLPFI3OH.js +618 -0
  149. package/dist/cli/setup-YLPFI3OH.js.map +1 -0
  150. package/dist/cli/stats-NXJ3TO2D.js +16 -0
  151. package/dist/cli/stats-NXJ3TO2D.js.map +1 -0
  152. package/dist/cli/update-ZUO5MKQ6.js +15 -0
  153. package/dist/cli/update-ZUO5MKQ6.js.map +1 -0
  154. package/dist/cli/version-NXXWE3WN.js +33 -0
  155. package/dist/cli/version-NXXWE3WN.js.map +1 -0
  156. package/dist/index.d.ts +2523 -0
  157. package/dist/index.js +15408 -0
  158. package/dist/index.js.map +1 -0
  159. package/package.json +112 -0
@@ -0,0 +1,624 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+ import {
4
+ useColor
5
+ } from "./chunk-D5NFKRGO.js";
6
+ import {
7
+ Box_default,
8
+ Text,
9
+ require_react,
10
+ use_input_default
11
+ } from "./chunk-X53B3JIX.js";
12
+ import {
13
+ __toESM
14
+ } from "./chunk-TUK7OWJA.js";
15
+
16
+ // src/cli/ui/keystroke-context.tsx
17
+ var import_react = __toESM(require_react(), 1);
18
+
19
+ // src/cli/ui/stdin-reader.ts
20
+ import { stdin } from "process";
21
+ var ESC_TIMEOUT_MS = 250;
22
+ var PASTE_START = "\x1B[200~";
23
+ var PASTE_END = "\x1B[201~";
24
+ var PASTE_START_BARE = "[200~";
25
+ var PASTE_END_BARE = "[201~";
26
+ var CSI_TAIL_MAP = [
27
+ { tail: "A", ev: { input: "", upArrow: true } },
28
+ { tail: "B", ev: { input: "", downArrow: true } },
29
+ { tail: "C", ev: { input: "", rightArrow: true } },
30
+ { tail: "D", ev: { input: "", leftArrow: true } },
31
+ { tail: "H", ev: { input: "", home: true } },
32
+ { tail: "F", ev: { input: "", end: true } },
33
+ { tail: "1~", ev: { input: "", home: true } },
34
+ { tail: "4~", ev: { input: "", end: true } },
35
+ { tail: "5~", ev: { input: "", pageUp: true } },
36
+ { tail: "6~", ev: { input: "", pageDown: true } },
37
+ { tail: "3~", ev: { input: "", delete: true } },
38
+ { tail: "Z", ev: { input: "", shift: true, tab: true } },
39
+ // Some Windows hosts (PowerShell 7.x conhost path) emit the
40
+ // modifier-encoded back-tab `\x1b[1;2Z` instead of bare `\x1b[Z`.
41
+ // Issue #373 — without this entry Shift+Tab is silently dropped.
42
+ { tail: "1;2Z", ev: { input: "", shift: true, tab: true } },
43
+ // modifyOtherKeys (xterm CSI > 4 ; 2 m) sequences for Enter / Tab
44
+ // with modifiers. Only fired when App.tsx has enabled the mode at
45
+ // startup; otherwise Shift+Enter stays indistinguishable from Enter.
46
+ // Modifier encoding: 2=shift, 3=alt, 4=alt+shift, 5=ctrl,
47
+ // 6=ctrl+shift, 7=ctrl+alt, 8=ctrl+alt+shift. Keycodes: 9=Tab, 13=Enter.
48
+ { tail: "27;2;9~", ev: { input: "", tab: true, shift: true } },
49
+ { tail: "27;2;13~", ev: { input: "", return: true, shift: true } },
50
+ { tail: "27;5;13~", ev: { input: "", return: true, ctrl: true } },
51
+ { tail: "27;6;13~", ev: { input: "", return: true, ctrl: true, shift: true } },
52
+ // Kitty keyboard protocol — same idea, different envelope:
53
+ // `\x1b[<keycode>;<mod>u`. Some terminals (kitty, recent Windows
54
+ // Terminal previews) prefer this shape. Harmless to map here too.
55
+ { tail: "9;2u", ev: { input: "", tab: true, shift: true } },
56
+ { tail: "13;2u", ev: { input: "", return: true, shift: true } },
57
+ { tail: "13;5u", ev: { input: "", return: true, ctrl: true } },
58
+ { tail: "13;6u", ev: { input: "", return: true, ctrl: true, shift: true } }
59
+ ];
60
+ var SS3_MAP = {
61
+ A: { input: "", upArrow: true },
62
+ B: { input: "", downArrow: true },
63
+ C: { input: "", rightArrow: true },
64
+ D: { input: "", leftArrow: true },
65
+ H: { input: "", home: true },
66
+ F: { input: "", end: true }
67
+ };
68
+ function tryEscapelessCsi(chunk, i) {
69
+ if (chunk[i] !== "[") return null;
70
+ for (const entry of CSI_TAIL_MAP) {
71
+ const candidate = `[${entry.tail}`;
72
+ if (chunk.slice(i, i + candidate.length) === candidate) {
73
+ return { advance: candidate.length, ev: entry.ev };
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+ var SGR_MOUSE_ESCAPELESS_RE = /^\[<\d+;\d+;\d+[Mm]/;
79
+ function decodeSgrMouseBody(body) {
80
+ const m = /^<(\d+);(\d+);(\d+)([Mm])$/.exec(body);
81
+ if (!m) return null;
82
+ const btn = Number.parseInt(m[1], 10);
83
+ const col = Number.parseInt(m[2], 10);
84
+ const row = Number.parseInt(m[3], 10);
85
+ if (!Number.isFinite(btn) || !Number.isFinite(col) || !Number.isFinite(row)) return null;
86
+ const tail = m[4];
87
+ if (tail === "m") return { input: "", mouseRelease: true, mouseRow: row, mouseCol: col };
88
+ if (btn === 64) return { input: "", mouseScrollUp: true, mouseRow: row, mouseCol: col };
89
+ if (btn === 65) return { input: "", mouseScrollDown: true, mouseRow: row, mouseCol: col };
90
+ if (btn === 0) return { input: "", mouseClick: true, mouseRow: row, mouseCol: col };
91
+ if (btn === 32) return { input: "", mouseDrag: true, mouseRow: row, mouseCol: col };
92
+ return null;
93
+ }
94
+ function tryEscapelessSgrMouse(chunk, i) {
95
+ if (chunk[i] !== "[") return null;
96
+ const m = SGR_MOUSE_ESCAPELESS_RE.exec(chunk.slice(i));
97
+ if (!m) return null;
98
+ const body = m[0].slice(1);
99
+ return { advance: m[0].length, ev: decodeSgrMouseBody(body) };
100
+ }
101
+ function isCsiFinal(ch) {
102
+ const code = ch.charCodeAt(0);
103
+ return code >= 64 && code <= 126;
104
+ }
105
+ function lookupCsi(tail) {
106
+ for (const entry of CSI_TAIL_MAP) {
107
+ if (entry.tail === tail) return entry.ev;
108
+ }
109
+ return null;
110
+ }
111
+ function decodeModifiedKey(cp, mod) {
112
+ if (mod < 1 || mod > 8) return null;
113
+ const bits = mod - 1;
114
+ const shift = (bits & 1) !== 0;
115
+ const alt = (bits & 2) !== 0;
116
+ const ctrl = (bits & 4) !== 0;
117
+ if (cp >= 32 && cp <= 126 && !ctrl && !alt) {
118
+ const ev = { input: String.fromCharCode(cp) };
119
+ if (shift) ev.shift = true;
120
+ return ev;
121
+ }
122
+ if (cp >= 32 && cp <= 126 && alt && !ctrl) {
123
+ const ev = { input: String.fromCharCode(cp), meta: true };
124
+ if (shift) ev.shift = true;
125
+ return ev;
126
+ }
127
+ if (cp >= 65 && cp <= 122 && ctrl && !alt) {
128
+ const ev = { input: String.fromCharCode(cp).toLowerCase(), ctrl: true };
129
+ if (shift) ev.shift = true;
130
+ return ev;
131
+ }
132
+ return null;
133
+ }
134
+ function tryDecodeGenericCsi(seq) {
135
+ let m = /^27;(\d+);(\d+)~$/.exec(seq);
136
+ if (m) return decodeModifiedKey(Number.parseInt(m[2], 10), Number.parseInt(m[1], 10));
137
+ m = /^(\d+);(\d+)u$/.exec(seq);
138
+ if (m) return decodeModifiedKey(Number.parseInt(m[1], 10), Number.parseInt(m[2], 10));
139
+ m = /^(\d+)u$/.exec(seq);
140
+ if (m) return decodeModifiedKey(Number.parseInt(m[1], 10), 1);
141
+ return null;
142
+ }
143
+ var PASTE_INVISIBLE_RE = /[\u200B\u200E\u200F\u202A-\u202E\u2060\u2066-\u2069\u00AD\uFEFF]/g;
144
+ function sanitizePasteText(s) {
145
+ return s.replace(PASTE_INVISIBLE_RE, "").replace(/\r\n?/g, "\n");
146
+ }
147
+ function looksLikeUnbracketedPaste(chunk) {
148
+ if (chunk.length < 2) return false;
149
+ if (chunk.includes(PASTE_START) || chunk.includes(PASTE_START_BARE)) return false;
150
+ if (chunk.includes(PASTE_END) || chunk.includes(PASTE_END_BARE)) return false;
151
+ if (chunk.includes("\x1B")) return false;
152
+ const norm = chunk.replace(/\r\n/g, "\n");
153
+ if (norm === "\r" || norm === "\n") return false;
154
+ let breaks = 0;
155
+ let firstBreakIdx = -1;
156
+ for (let i = 0; i < norm.length; i++) {
157
+ const c = norm[i];
158
+ if (c === "\r" || c === "\n") {
159
+ if (firstBreakIdx < 0) firstBreakIdx = i;
160
+ breaks++;
161
+ }
162
+ }
163
+ if (breaks >= 2) return true;
164
+ if (breaks === 1) return firstBreakIdx > 0 && firstBreakIdx < norm.length - 1;
165
+ return false;
166
+ }
167
+ var StdinReader = class {
168
+ subscribers = /* @__PURE__ */ new Set();
169
+ state = "idle";
170
+ /** Buffer for partial sequences across chunks. */
171
+ csiBuf = "";
172
+ /** Buffer for paste content. */
173
+ pasteBuf = "";
174
+ escTimer = null;
175
+ // Deferred-dispatch handle paired with `escTimer`. The timer
176
+ // queues an Immediate that runs in the event loop's CHECK phase —
177
+ // i.e. AFTER the POLL phase where stdin 'data' events fire — so
178
+ // a multi-byte sequence whose chunks queued up while the loop was
179
+ // blocked (heavy render, etc.) gets a chance to be processed
180
+ // BEFORE we emit a bogus standalone-Esc. Fixes the "I didn't press
181
+ // Esc but it aborted the turn" class of bug: previously the timer's
182
+ // setTimeout callback ran in the timers phase ahead of poll, so a
183
+ // split sequence like `\x1b` + `[A` would dispatch escape+upArrow
184
+ // even though the user only pressed Up.
185
+ escImmediate = null;
186
+ started = false;
187
+ /** The actual `data` listener — kept as a field so `stop()` can detach it. */
188
+ listener = null;
189
+ start() {
190
+ if (this.started) return;
191
+ try {
192
+ stdin.setRawMode(true);
193
+ } catch {
194
+ return;
195
+ }
196
+ stdin.setEncoding("utf8");
197
+ stdin.resume();
198
+ this.listener = (chunk) => this.handleChunk(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
199
+ stdin.on("data", this.listener);
200
+ this.started = true;
201
+ }
202
+ stop() {
203
+ if (!this.started) return;
204
+ if (this.listener) {
205
+ stdin.off("data", this.listener);
206
+ this.listener = null;
207
+ }
208
+ try {
209
+ stdin.setRawMode(false);
210
+ } catch {
211
+ }
212
+ stdin.pause();
213
+ this.cancelEscTimer();
214
+ this.state = "idle";
215
+ this.csiBuf = "";
216
+ this.pasteBuf = "";
217
+ this.started = false;
218
+ }
219
+ subscribe(fn) {
220
+ this.subscribers.add(fn);
221
+ return () => {
222
+ this.subscribers.delete(fn);
223
+ };
224
+ }
225
+ /** Test seam — drives the parser without a real TTY. */
226
+ feed(chunk) {
227
+ this.handleChunk(chunk);
228
+ }
229
+ dispatch(ev) {
230
+ for (const sub of this.subscribers) sub(ev);
231
+ }
232
+ cancelEscTimer() {
233
+ if (this.escTimer) {
234
+ clearTimeout(this.escTimer);
235
+ this.escTimer = null;
236
+ }
237
+ if (this.escImmediate) {
238
+ clearImmediate(this.escImmediate);
239
+ this.escImmediate = null;
240
+ }
241
+ }
242
+ scheduleEscTimer() {
243
+ this.cancelEscTimer();
244
+ this.escTimer = setTimeout(() => {
245
+ this.escTimer = null;
246
+ this.escImmediate = setImmediate(() => {
247
+ this.escImmediate = null;
248
+ if (this.state === "esc") {
249
+ this.state = "idle";
250
+ this.dispatch({ input: "", escape: true });
251
+ }
252
+ });
253
+ }, ESC_TIMEOUT_MS);
254
+ }
255
+ handleChunk(rawChunk) {
256
+ this.cancelEscTimer();
257
+ const chunk = this.state === "idle" && looksLikeUnbracketedPaste(rawChunk) ? PASTE_START + rawChunk + PASTE_END : rawChunk;
258
+ let i = 0;
259
+ while (i < chunk.length) {
260
+ if (this.state === "paste") {
261
+ const endA = chunk.indexOf(PASTE_END, i);
262
+ const endB = chunk.indexOf(PASTE_END_BARE, i);
263
+ let endIdx = -1;
264
+ let endLen = 0;
265
+ if (endA !== -1 && (endB === -1 || endA <= endB)) {
266
+ endIdx = endA;
267
+ endLen = PASTE_END.length;
268
+ } else if (endB !== -1) {
269
+ endIdx = endB;
270
+ endLen = PASTE_END_BARE.length;
271
+ }
272
+ if (endIdx === -1) {
273
+ this.pasteBuf += chunk.slice(i);
274
+ i = chunk.length;
275
+ break;
276
+ }
277
+ this.pasteBuf += chunk.slice(i, endIdx);
278
+ this.dispatch({ input: sanitizePasteText(this.pasteBuf), paste: true });
279
+ this.pasteBuf = "";
280
+ this.state = "idle";
281
+ i = endIdx + endLen;
282
+ continue;
283
+ }
284
+ if (this.state === "csi") {
285
+ const ch2 = chunk[i];
286
+ this.csiBuf += ch2;
287
+ if (isCsiFinal(ch2)) {
288
+ this.dispatchCsi(this.csiBuf);
289
+ this.csiBuf = "";
290
+ if (this.state === "csi") this.state = "idle";
291
+ }
292
+ i++;
293
+ continue;
294
+ }
295
+ if (this.state === "ss3") {
296
+ const ev = SS3_MAP[chunk[i]];
297
+ if (ev) this.dispatch(ev);
298
+ this.state = "idle";
299
+ i++;
300
+ continue;
301
+ }
302
+ if (this.state === "esc") {
303
+ const ch2 = chunk[i];
304
+ if (ch2 === "[") {
305
+ this.state = "csi";
306
+ this.csiBuf = "";
307
+ i++;
308
+ continue;
309
+ }
310
+ if (ch2 === "O") {
311
+ this.state = "ss3";
312
+ i++;
313
+ continue;
314
+ }
315
+ if (ch2 === "\r" || ch2 === "\n") {
316
+ this.dispatch({ input: "", return: true, meta: true });
317
+ this.state = "idle";
318
+ i++;
319
+ continue;
320
+ }
321
+ this.dispatch({ input: ch2, meta: true });
322
+ this.state = "idle";
323
+ i++;
324
+ continue;
325
+ }
326
+ const ch = chunk[i];
327
+ if (ch === "\x1B") {
328
+ this.state = "esc";
329
+ i++;
330
+ continue;
331
+ }
332
+ if (chunk.slice(i, i + PASTE_START_BARE.length) === PASTE_START_BARE) {
333
+ this.state = "paste";
334
+ this.pasteBuf = "";
335
+ i += PASTE_START_BARE.length;
336
+ continue;
337
+ }
338
+ const escapeless = tryEscapelessCsi(chunk, i);
339
+ if (escapeless) {
340
+ this.dispatch(escapeless.ev);
341
+ i += escapeless.advance;
342
+ continue;
343
+ }
344
+ const mouseEscapeless = tryEscapelessSgrMouse(chunk, i);
345
+ if (mouseEscapeless) {
346
+ if (mouseEscapeless.ev) this.dispatch(mouseEscapeless.ev);
347
+ i += mouseEscapeless.advance;
348
+ continue;
349
+ }
350
+ if (ch === "\r") {
351
+ this.dispatch({ input: "", return: true });
352
+ i++;
353
+ continue;
354
+ }
355
+ if (ch === "\n") {
356
+ this.dispatch({ input: "j", ctrl: true });
357
+ i++;
358
+ continue;
359
+ }
360
+ if (ch === " ") {
361
+ this.dispatch({ input: "", tab: true });
362
+ i++;
363
+ continue;
364
+ }
365
+ if (ch === "\x7F" || ch === "\b") {
366
+ this.dispatch({ input: "", backspace: true });
367
+ i++;
368
+ continue;
369
+ }
370
+ if (ch === "") {
371
+ this.dispatch({ input: "c", ctrl: true });
372
+ i++;
373
+ continue;
374
+ }
375
+ const code = ch.charCodeAt(0);
376
+ if (code >= 1 && code <= 26) {
377
+ const letter = String.fromCharCode(96 + code);
378
+ this.dispatch({ input: letter, ctrl: true });
379
+ i++;
380
+ continue;
381
+ }
382
+ let end = i + 1;
383
+ while (end < chunk.length) {
384
+ const c = chunk[end];
385
+ if (c === "\x1B" || c === "\r" || c === "\n" || c === " ") break;
386
+ if (c === "\x7F" || c === "\b" || c === "") break;
387
+ const cc = c.charCodeAt(0);
388
+ if (cc >= 1 && cc <= 26) break;
389
+ if (c === "[" && (tryEscapelessCsi(chunk, end) || tryEscapelessSgrMouse(chunk, end))) break;
390
+ if (chunk.slice(end, end + PASTE_START_BARE.length) === PASTE_START_BARE) break;
391
+ end++;
392
+ }
393
+ this.dispatch({ input: chunk.slice(i, end) });
394
+ i = end;
395
+ }
396
+ if (this.state === "esc") {
397
+ this.scheduleEscTimer();
398
+ }
399
+ }
400
+ dispatchCsi(seq) {
401
+ if (seq === "200~") {
402
+ this.state = "paste";
403
+ this.pasteBuf = "";
404
+ return;
405
+ }
406
+ if (seq === "201~") {
407
+ return;
408
+ }
409
+ if (seq.length > 1 && seq.charCodeAt(0) === 60) {
410
+ const ev2 = decodeSgrMouseBody(seq);
411
+ if (ev2) this.dispatch(ev2);
412
+ return;
413
+ }
414
+ const ev = lookupCsi(seq);
415
+ if (ev) {
416
+ this.dispatch(ev);
417
+ return;
418
+ }
419
+ const generic = tryDecodeGenericCsi(seq);
420
+ if (generic) {
421
+ this.dispatch(generic);
422
+ return;
423
+ }
424
+ }
425
+ };
426
+ var singleton = null;
427
+ function getStdinReader() {
428
+ if (!singleton) singleton = new StdinReader();
429
+ return singleton;
430
+ }
431
+
432
+ // src/cli/ui/keystroke-context.tsx
433
+ var KeystrokeContext = (0, import_react.createContext)(null);
434
+ function KeystrokeProvider({
435
+ children,
436
+ reader: providedReader
437
+ }) {
438
+ const handlersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
439
+ const busRef = (0, import_react.useRef)(null);
440
+ if (busRef.current === null) {
441
+ busRef.current = {
442
+ subscribe(handler) {
443
+ handlersRef.current.add(handler);
444
+ return () => {
445
+ handlersRef.current.delete(handler);
446
+ };
447
+ }
448
+ };
449
+ }
450
+ (0, import_react.useEffect)(() => {
451
+ const reader = providedReader ?? getStdinReader();
452
+ reader.start();
453
+ const unsubscribe = reader.subscribe((ev) => {
454
+ for (const fn of [...handlersRef.current]) fn(ev);
455
+ });
456
+ return () => {
457
+ unsubscribe();
458
+ };
459
+ }, [providedReader]);
460
+ return /* @__PURE__ */ import_react.default.createElement(KeystrokeContext.Provider, { value: busRef.current }, children);
461
+ }
462
+ function useKeystroke(handler, isActive = true) {
463
+ const bus = (0, import_react.useContext)(KeystrokeContext);
464
+ const handlerRef = (0, import_react.useRef)(handler);
465
+ handlerRef.current = handler;
466
+ (0, import_react.useEffect)(() => {
467
+ if (!bus || !isActive) return void 0;
468
+ return bus.subscribe((ev) => handlerRef.current(ev));
469
+ }, [bus, isActive]);
470
+ use_input_default(
471
+ (input, key) => {
472
+ if (bus) return;
473
+ handlerRef.current({
474
+ input,
475
+ upArrow: key.upArrow,
476
+ downArrow: key.downArrow,
477
+ leftArrow: key.leftArrow,
478
+ rightArrow: key.rightArrow,
479
+ return: key.return,
480
+ escape: key.escape,
481
+ backspace: key.backspace,
482
+ delete: key.delete,
483
+ tab: key.tab,
484
+ shift: key.shift,
485
+ ctrl: key.ctrl,
486
+ meta: key.meta,
487
+ pageUp: key.pageUp,
488
+ pageDown: key.pageDown
489
+ });
490
+ },
491
+ { isActive: !bus && isActive }
492
+ );
493
+ }
494
+
495
+ // src/cli/ui/Select.tsx
496
+ var import_react2 = __toESM(require_react(), 1);
497
+ function SingleSelect({
498
+ items,
499
+ initialValue,
500
+ onSubmit,
501
+ onTab,
502
+ onCancel,
503
+ footer,
504
+ inlineHints = false,
505
+ ignoreKey
506
+ }) {
507
+ const color = useColor();
508
+ const initialIndex = Math.max(
509
+ 0,
510
+ items.findIndex((i) => i.value === initialValue && !i.disabled)
511
+ );
512
+ const [index, setIndex] = (0, import_react2.useState)(initialIndex === -1 ? 0 : initialIndex);
513
+ useKeystroke((ev) => {
514
+ if (ev.paste || ignoreKey?.(ev)) return;
515
+ if (ev.upArrow) {
516
+ setIndex((i) => findNextEnabled(items, i, -1));
517
+ } else if (ev.downArrow) {
518
+ setIndex((i) => findNextEnabled(items, i, 1));
519
+ } else if (ev.return) {
520
+ const chosen = items[index];
521
+ if (chosen && !chosen.disabled) onSubmit(chosen.value);
522
+ } else if (ev.tab) {
523
+ const chosen = items[index];
524
+ if (chosen && !chosen.disabled) onTab?.(chosen.value);
525
+ } else if (ev.escape && onCancel) {
526
+ onCancel();
527
+ }
528
+ });
529
+ return /* @__PURE__ */ import_react2.default.createElement(Box_default, { flexDirection: "column" }, items.map((item, i) => /* @__PURE__ */ import_react2.default.createElement(
530
+ SelectRow,
531
+ {
532
+ key: item.value,
533
+ item,
534
+ active: i === index,
535
+ marker: i === index ? "\u25B8" : " ",
536
+ color,
537
+ inlineHint: inlineHints
538
+ }
539
+ )), footer ? /* @__PURE__ */ import_react2.default.createElement(Box_default, { marginTop: 1 }, /* @__PURE__ */ import_react2.default.createElement(Text, { dimColor: true }, footer)) : null);
540
+ }
541
+ function MultiSelect({
542
+ items,
543
+ initialSelected = [],
544
+ onSubmit,
545
+ onCancel,
546
+ footer,
547
+ inlineHints = false,
548
+ ignoreKey
549
+ }) {
550
+ const color = useColor();
551
+ const [index, setIndex] = (0, import_react2.useState)(() => {
552
+ const first = items.findIndex((i) => !i.disabled);
553
+ return first === -1 ? 0 : first;
554
+ });
555
+ const [selected, setSelected] = (0, import_react2.useState)(new Set(initialSelected));
556
+ useKeystroke((ev) => {
557
+ if (ev.paste || ignoreKey?.(ev)) return;
558
+ if (ev.upArrow) {
559
+ setIndex((i) => findNextEnabled(items, i, -1));
560
+ } else if (ev.downArrow) {
561
+ setIndex((i) => findNextEnabled(items, i, 1));
562
+ } else if (ev.input === " ") {
563
+ const item = items[index];
564
+ if (!item || item.disabled) return;
565
+ setSelected((prev) => {
566
+ const next = new Set(prev);
567
+ if (next.has(item.value)) next.delete(item.value);
568
+ else next.add(item.value);
569
+ return next;
570
+ });
571
+ } else if (ev.return) {
572
+ const ordered = items.filter((i) => selected.has(i.value)).map((i) => i.value);
573
+ onSubmit(ordered);
574
+ } else if (ev.escape && onCancel) {
575
+ onCancel();
576
+ }
577
+ });
578
+ return /* @__PURE__ */ import_react2.default.createElement(Box_default, { flexDirection: "column" }, items.map((item, i) => {
579
+ const checked = selected.has(item.value);
580
+ const marker = checked ? "[x]" : "[ ]";
581
+ return /* @__PURE__ */ import_react2.default.createElement(
582
+ SelectRow,
583
+ {
584
+ key: item.value,
585
+ item,
586
+ active: i === index,
587
+ marker: `${i === index ? "\u25B8" : " "} ${marker}`,
588
+ color,
589
+ inlineHint: inlineHints
590
+ }
591
+ );
592
+ }), footer ? /* @__PURE__ */ import_react2.default.createElement(Box_default, { marginTop: 1 }, /* @__PURE__ */ import_react2.default.createElement(Text, { dimColor: true }, footer)) : null);
593
+ }
594
+ function SelectRow({
595
+ item,
596
+ active,
597
+ marker,
598
+ color,
599
+ inlineHint = false
600
+ }) {
601
+ const rowColor = item.disabled ? color.info : active ? color.primary : void 0;
602
+ const labelText = `${marker} ${item.label}`;
603
+ if (inlineHint) {
604
+ return /* @__PURE__ */ import_react2.default.createElement(Box_default, { flexDirection: "row", flexWrap: "nowrap", minHeight: 1 }, /* @__PURE__ */ import_react2.default.createElement(Text, { color: rowColor, bold: active, dimColor: item.disabled, wrap: "truncate" }, labelText), item.hint ? /* @__PURE__ */ import_react2.default.createElement(Text, { dimColor: true, wrap: "truncate" }, ` ${item.hint}`) : null);
605
+ }
606
+ return /* @__PURE__ */ import_react2.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react2.default.createElement(Box_default, null, /* @__PURE__ */ import_react2.default.createElement(Text, { color: rowColor, bold: active, dimColor: item.disabled }, labelText)), item.hint ? /* @__PURE__ */ import_react2.default.createElement(Box_default, { paddingLeft: marker.length + 1 }, /* @__PURE__ */ import_react2.default.createElement(Text, { dimColor: true }, item.hint)) : null);
607
+ }
608
+ function findNextEnabled(items, from, step) {
609
+ if (items.length === 0) return 0;
610
+ let i = from;
611
+ for (let tries = 0; tries < items.length; tries++) {
612
+ i = (i + step + items.length) % items.length;
613
+ if (!items[i]?.disabled) return i;
614
+ }
615
+ return from;
616
+ }
617
+
618
+ export {
619
+ KeystrokeProvider,
620
+ useKeystroke,
621
+ SingleSelect,
622
+ MultiSelect
623
+ };
624
+ //# sourceMappingURL=chunk-UI66BH6D.js.map