@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.
- package/LICENSE +21 -0
- package/LICENSES/DeepSeek-Reasonix-MIT.txt +21 -0
- package/README.md +109 -0
- package/README.zh-CN.md +91 -0
- package/THIRD_PARTY_NOTICES.md +14 -0
- package/dashboard/app.css +3233 -0
- package/dashboard/dist/app.js +30444 -0
- package/dashboard/dist/app.js.map +1 -0
- package/dashboard/dist/vendor-hljs.css +10 -0
- package/dashboard/dist/vendor-uplot.css +1 -0
- package/dashboard/index.html +19 -0
- package/data/deepseek-tokenizer.json.gz +0 -0
- package/dist/cli/acp-35C4ME6Y.js +711 -0
- package/dist/cli/acp-35C4ME6Y.js.map +1 -0
- package/dist/cli/chat-A6UJDPGV.js +51 -0
- package/dist/cli/chat-A6UJDPGV.js.map +1 -0
- package/dist/cli/chunk-2425HK6U.js +54 -0
- package/dist/cli/chunk-2425HK6U.js.map +1 -0
- package/dist/cli/chunk-25T6CVUP.js +172 -0
- package/dist/cli/chunk-25T6CVUP.js.map +1 -0
- package/dist/cli/chunk-2UQP6H6T.js +31 -0
- package/dist/cli/chunk-2UQP6H6T.js.map +1 -0
- package/dist/cli/chunk-3OAR6NVL.js +96 -0
- package/dist/cli/chunk-3OAR6NVL.js.map +1 -0
- package/dist/cli/chunk-3T6VBZCL.js +54 -0
- package/dist/cli/chunk-3T6VBZCL.js.map +1 -0
- package/dist/cli/chunk-4IBIPQVB.js +153 -0
- package/dist/cli/chunk-4IBIPQVB.js.map +1 -0
- package/dist/cli/chunk-4MQ3VURH.js +3106 -0
- package/dist/cli/chunk-4MQ3VURH.js.map +1 -0
- package/dist/cli/chunk-4TVNJWMA.js +11619 -0
- package/dist/cli/chunk-4TVNJWMA.js.map +1 -0
- package/dist/cli/chunk-4VR6XF4P.js +341 -0
- package/dist/cli/chunk-4VR6XF4P.js.map +1 -0
- package/dist/cli/chunk-5QCB62C4.js +25319 -0
- package/dist/cli/chunk-5QCB62C4.js.map +1 -0
- package/dist/cli/chunk-6OWJV3YW.js +390 -0
- package/dist/cli/chunk-6OWJV3YW.js.map +1 -0
- package/dist/cli/chunk-7EO27TB3.js +130 -0
- package/dist/cli/chunk-7EO27TB3.js.map +1 -0
- package/dist/cli/chunk-7L2WTRNU.js +308 -0
- package/dist/cli/chunk-7L2WTRNU.js.map +1 -0
- package/dist/cli/chunk-BHTZFEYE.js +47 -0
- package/dist/cli/chunk-BHTZFEYE.js.map +1 -0
- package/dist/cli/chunk-BSGCXZQN.js +343 -0
- package/dist/cli/chunk-BSGCXZQN.js.map +1 -0
- package/dist/cli/chunk-BSINVTTL.js +464 -0
- package/dist/cli/chunk-BSINVTTL.js.map +1 -0
- package/dist/cli/chunk-CPKCNHRR.js +323 -0
- package/dist/cli/chunk-CPKCNHRR.js.map +1 -0
- package/dist/cli/chunk-CXVWUPA3.js +96 -0
- package/dist/cli/chunk-CXVWUPA3.js.map +1 -0
- package/dist/cli/chunk-D5NFKRGO.js +160 -0
- package/dist/cli/chunk-D5NFKRGO.js.map +1 -0
- package/dist/cli/chunk-ECHSFYOY.js +109 -0
- package/dist/cli/chunk-ECHSFYOY.js.map +1 -0
- package/dist/cli/chunk-FEZK652I.js +3644 -0
- package/dist/cli/chunk-FEZK652I.js.map +1 -0
- package/dist/cli/chunk-GALC45Q2.js +696 -0
- package/dist/cli/chunk-GALC45Q2.js.map +1 -0
- package/dist/cli/chunk-IAUOP25G.js +2984 -0
- package/dist/cli/chunk-IAUOP25G.js.map +1 -0
- package/dist/cli/chunk-ILJOIQ5W.js +163 -0
- package/dist/cli/chunk-ILJOIQ5W.js.map +1 -0
- package/dist/cli/chunk-IX6XI2RG.js +225 -0
- package/dist/cli/chunk-IX6XI2RG.js.map +1 -0
- package/dist/cli/chunk-J5BYPUB5.js +62795 -0
- package/dist/cli/chunk-J5BYPUB5.js.map +1 -0
- package/dist/cli/chunk-J5XJHLWM.js +55 -0
- package/dist/cli/chunk-J5XJHLWM.js.map +1 -0
- package/dist/cli/chunk-JKGYMRX5.js +101 -0
- package/dist/cli/chunk-JKGYMRX5.js.map +1 -0
- package/dist/cli/chunk-JMBMLOBP.js +26 -0
- package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
- package/dist/cli/chunk-LN3B5PMX.js +128 -0
- package/dist/cli/chunk-LN3B5PMX.js.map +1 -0
- package/dist/cli/chunk-M2UFZUX3.js +635 -0
- package/dist/cli/chunk-M2UFZUX3.js.map +1 -0
- package/dist/cli/chunk-PJS34556.js +809 -0
- package/dist/cli/chunk-PJS34556.js.map +1 -0
- package/dist/cli/chunk-QJG7OF27.js +655 -0
- package/dist/cli/chunk-QJG7OF27.js.map +1 -0
- package/dist/cli/chunk-QVC75MR3.js +232 -0
- package/dist/cli/chunk-QVC75MR3.js.map +1 -0
- package/dist/cli/chunk-S2KIUQKQ.js +378 -0
- package/dist/cli/chunk-S2KIUQKQ.js.map +1 -0
- package/dist/cli/chunk-S4XVGLRW.js +499 -0
- package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
- package/dist/cli/chunk-T5TQ4NDT.js +190 -0
- package/dist/cli/chunk-T5TQ4NDT.js.map +1 -0
- package/dist/cli/chunk-TH756VLN.js +1924 -0
- package/dist/cli/chunk-TH756VLN.js.map +1 -0
- package/dist/cli/chunk-TUK7OWJA.js +51 -0
- package/dist/cli/chunk-TUK7OWJA.js.map +1 -0
- package/dist/cli/chunk-U4IJVG32.js +363 -0
- package/dist/cli/chunk-U4IJVG32.js.map +1 -0
- package/dist/cli/chunk-UI66BH6D.js +624 -0
- package/dist/cli/chunk-UI66BH6D.js.map +1 -0
- package/dist/cli/chunk-VPMBGAND.js +53 -0
- package/dist/cli/chunk-VPMBGAND.js.map +1 -0
- package/dist/cli/chunk-WLHH3OSR.js +522 -0
- package/dist/cli/chunk-WLHH3OSR.js.map +1 -0
- package/dist/cli/chunk-WRN65TRD.js +908 -0
- package/dist/cli/chunk-WRN65TRD.js.map +1 -0
- package/dist/cli/chunk-X53B3JIX.js +34320 -0
- package/dist/cli/chunk-X53B3JIX.js.map +1 -0
- package/dist/cli/chunk-XJ5SRLKK.js +50 -0
- package/dist/cli/chunk-XJ5SRLKK.js.map +1 -0
- package/dist/cli/chunk-YZSXRGFH.js +54 -0
- package/dist/cli/chunk-YZSXRGFH.js.map +1 -0
- package/dist/cli/code-4TUTAGO5.js +163 -0
- package/dist/cli/code-4TUTAGO5.js.map +1 -0
- package/dist/cli/commands-KMOZEYCF.js +356 -0
- package/dist/cli/commands-KMOZEYCF.js.map +1 -0
- package/dist/cli/commit-DTFA56VQ.js +292 -0
- package/dist/cli/commit-DTFA56VQ.js.map +1 -0
- package/dist/cli/desktop-7N3MHNBD.js +1274 -0
- package/dist/cli/desktop-7N3MHNBD.js.map +1 -0
- package/dist/cli/devtools-HW3WDT3Q.js +91 -0
- package/dist/cli/devtools-HW3WDT3Q.js.map +1 -0
- package/dist/cli/diff-E5OWTF4C.js +165 -0
- package/dist/cli/diff-E5OWTF4C.js.map +1 -0
- package/dist/cli/doctor-IEJQRJMN.js +27 -0
- package/dist/cli/doctor-IEJQRJMN.js.map +1 -0
- package/dist/cli/events-4625EGXI.js +340 -0
- package/dist/cli/events-4625EGXI.js.map +1 -0
- package/dist/cli/index.js +3536 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-PDI2PDLG.js +277 -0
- package/dist/cli/mcp-PDI2PDLG.js.map +1 -0
- package/dist/cli/mcp-browse-OSPXOFPZ.js +178 -0
- package/dist/cli/mcp-browse-OSPXOFPZ.js.map +1 -0
- package/dist/cli/mcp-inspect-QRFVTHMF.js +148 -0
- package/dist/cli/mcp-inspect-QRFVTHMF.js.map +1 -0
- package/dist/cli/package.json +3 -0
- package/dist/cli/prompt-3CDII3UO.js +16 -0
- package/dist/cli/prompt-3CDII3UO.js.map +1 -0
- package/dist/cli/prune-sessions-KZX4SXKW.js +44 -0
- package/dist/cli/prune-sessions-KZX4SXKW.js.map +1 -0
- package/dist/cli/replay-HYOSRQIV.js +291 -0
- package/dist/cli/replay-HYOSRQIV.js.map +1 -0
- package/dist/cli/run-2ZHADOUP.js +220 -0
- package/dist/cli/run-2ZHADOUP.js.map +1 -0
- package/dist/cli/server-X75PAZG5.js +3572 -0
- package/dist/cli/server-X75PAZG5.js.map +1 -0
- package/dist/cli/sessions-POOZA5CQ.js +120 -0
- package/dist/cli/sessions-POOZA5CQ.js.map +1 -0
- package/dist/cli/setup-YLPFI3OH.js +618 -0
- package/dist/cli/setup-YLPFI3OH.js.map +1 -0
- package/dist/cli/stats-NXJ3TO2D.js +16 -0
- package/dist/cli/stats-NXJ3TO2D.js.map +1 -0
- package/dist/cli/update-ZUO5MKQ6.js +15 -0
- package/dist/cli/update-ZUO5MKQ6.js.map +1 -0
- package/dist/cli/version-NXXWE3WN.js +33 -0
- package/dist/cli/version-NXXWE3WN.js.map +1 -0
- package/dist/index.d.ts +2523 -0
- package/dist/index.js +15408 -0
- package/dist/index.js.map +1 -0
- 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
|