@zhongqian97-code/ecode 0.5.60 → 0.5.61
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/dist/altScreen-I6W4LBRE.js +46 -0
- package/dist/index.js +4 -16
- package/dist/{ui-3HB6NDEE.js → ui-DFEOOA36.js} +161 -93
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const _ew=process.emitWarning.bind(process);process.emitWarning=function(w,...a){if((w?.message??w)?.includes?.('punycode'))return;_ew(w,...a);};
|
|
3
|
+
|
|
4
|
+
// src/ui/altScreen.ts
|
|
5
|
+
import { writeSync as fsWriteSync } from "fs";
|
|
6
|
+
var ENTER_ALT_SCREEN_SEQ = "\x1B[?1049h\x1B[H";
|
|
7
|
+
var EXIT_ALT_SCREEN_SEQ = "\x1B[?1049l";
|
|
8
|
+
var DISABLE_TERMINAL_MODES_SEQ = "\x1B[?1004l\x1B[?1002l\x1B[?1006l";
|
|
9
|
+
function installCrashCleanup(opts = {}) {
|
|
10
|
+
const writeSync = opts.writeSync ?? ((s) => {
|
|
11
|
+
try {
|
|
12
|
+
fsWriteSync(1, s);
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const signals = opts.signals ?? ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
17
|
+
let cleaned = false;
|
|
18
|
+
const cleanup = () => {
|
|
19
|
+
if (cleaned) return;
|
|
20
|
+
cleaned = true;
|
|
21
|
+
writeSync(DISABLE_TERMINAL_MODES_SEQ);
|
|
22
|
+
writeSync(EXIT_ALT_SCREEN_SEQ);
|
|
23
|
+
};
|
|
24
|
+
const onExit = () => {
|
|
25
|
+
cleanup();
|
|
26
|
+
};
|
|
27
|
+
process.on("exit", onExit);
|
|
28
|
+
const sigHandlers = signals.map((sig) => {
|
|
29
|
+
const h = () => {
|
|
30
|
+
cleanup();
|
|
31
|
+
process.exit(0);
|
|
32
|
+
};
|
|
33
|
+
process.on(sig, h);
|
|
34
|
+
return [sig, h];
|
|
35
|
+
});
|
|
36
|
+
return () => {
|
|
37
|
+
process.off("exit", onExit);
|
|
38
|
+
for (const [sig, h] of sigHandlers) process.off(sig, h);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
DISABLE_TERMINAL_MODES_SEQ,
|
|
43
|
+
ENTER_ALT_SCREEN_SEQ,
|
|
44
|
+
EXIT_ALT_SCREEN_SEQ,
|
|
45
|
+
installCrashCleanup
|
|
46
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -903,21 +903,9 @@ Press Ctrl+C to stop.
|
|
|
903
903
|
process.exit(0);
|
|
904
904
|
}
|
|
905
905
|
if (process.stdout.isTTY) {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
process.on("SIGINT", () => {
|
|
910
|
-
exitAltScreen();
|
|
911
|
-
process.exit(0);
|
|
912
|
-
});
|
|
913
|
-
process.on("SIGTERM", () => {
|
|
914
|
-
exitAltScreen();
|
|
915
|
-
process.exit(0);
|
|
916
|
-
});
|
|
917
|
-
process.on("SIGHUP", () => {
|
|
918
|
-
exitAltScreen();
|
|
919
|
-
process.exit(0);
|
|
920
|
-
});
|
|
906
|
+
const { ENTER_ALT_SCREEN_SEQ, installCrashCleanup } = await import("./altScreen-I6W4LBRE.js");
|
|
907
|
+
process.stdout.write(ENTER_ALT_SCREEN_SEQ);
|
|
908
|
+
installCrashCleanup();
|
|
921
909
|
}
|
|
922
910
|
const [nodeMaj] = process.versions.node.split(".").map(Number);
|
|
923
911
|
if (nodeMaj < 20) {
|
|
@@ -928,7 +916,7 @@ Node.js 16/18 \u8BF7\u4F7F\u7528 --web \u6216 --pipe \u6A21\u5F0F\u3002
|
|
|
928
916
|
);
|
|
929
917
|
process.exit(1);
|
|
930
918
|
}
|
|
931
|
-
const { App, React, render, createStdinFilter } = await import("./ui-
|
|
919
|
+
const { App, React, render, createStdinFilter } = await import("./ui-DFEOOA36.js");
|
|
932
920
|
const stdinFilter = process.stdin.isTTY ? createStdinFilter(process.stdin) : process.stdin;
|
|
933
921
|
render(
|
|
934
922
|
React.createElement(App, { config: finalConfig, version: VERSION, autoMode, registry, trustedSkillDirs, initialMessages, stdinFilter }),
|
|
@@ -47,7 +47,7 @@ import { render } from "ink";
|
|
|
47
47
|
|
|
48
48
|
// src/ui/App.tsx
|
|
49
49
|
import { useState as useState3, useCallback, useRef as useRef2, useEffect as useEffect3, useMemo } from "react";
|
|
50
|
-
import { Box as Box6, Text as Text6, useInput as useInput2, useStdout } from "ink";
|
|
50
|
+
import { Box as Box6, Text as Text6, useInput as useInput2, useStdout, measureElement } from "ink";
|
|
51
51
|
|
|
52
52
|
// src/skills/executor.ts
|
|
53
53
|
import { exec } from "child_process";
|
|
@@ -296,6 +296,7 @@ function messageToLines(msg, expandTools, terminalWidth) {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
// src/ui/mouseSelection.ts
|
|
299
|
+
import stringWidth2 from "string-width";
|
|
299
300
|
function initialSelectionState() {
|
|
300
301
|
return { anchor: null, focus: null, dragging: false };
|
|
301
302
|
}
|
|
@@ -328,6 +329,21 @@ function isCellSelected(row, col, state) {
|
|
|
328
329
|
if (row === end.row) return col <= end.col;
|
|
329
330
|
return true;
|
|
330
331
|
}
|
|
332
|
+
function colToStringIndex(line, col, roundUp) {
|
|
333
|
+
if (col <= 0) return 0;
|
|
334
|
+
let w = 0;
|
|
335
|
+
let idx = 0;
|
|
336
|
+
for (const ch of line) {
|
|
337
|
+
const cw = stringWidth2(ch);
|
|
338
|
+
if (w >= col) return idx;
|
|
339
|
+
if (w + cw > col) {
|
|
340
|
+
return roundUp ? idx + ch.length : idx;
|
|
341
|
+
}
|
|
342
|
+
w += cw;
|
|
343
|
+
idx += ch.length;
|
|
344
|
+
}
|
|
345
|
+
return idx;
|
|
346
|
+
}
|
|
331
347
|
function extractSelectedText(lines, state) {
|
|
332
348
|
const norm = normalizeSelection(state);
|
|
333
349
|
if (!norm) return "";
|
|
@@ -335,9 +351,11 @@ function extractSelectedText(lines, state) {
|
|
|
335
351
|
const parts = [];
|
|
336
352
|
for (let r = start.row; r <= end.row; r++) {
|
|
337
353
|
const line = lines[r] ?? "";
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
|
|
354
|
+
const colStartVis = r === start.row ? start.col : 0;
|
|
355
|
+
const colEndVis = r === end.row ? end.col + 1 : Number.POSITIVE_INFINITY;
|
|
356
|
+
const idxStart = colToStringIndex(line, colStartVis, false);
|
|
357
|
+
const idxEnd = colToStringIndex(line, colEndVis, true);
|
|
358
|
+
parts.push(line.slice(idxStart, idxEnd));
|
|
341
359
|
}
|
|
342
360
|
return parts.join("\n");
|
|
343
361
|
}
|
|
@@ -405,7 +423,20 @@ import { useState as useState2, useEffect as useEffect2, useRef, forwardRef, use
|
|
|
405
423
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
406
424
|
|
|
407
425
|
// src/ui/inputClick.ts
|
|
426
|
+
import stringWidth3 from "string-width";
|
|
408
427
|
var INPUT_PREFIX_WIDTH = 2;
|
|
428
|
+
function colToStringIndex2(line, col) {
|
|
429
|
+
if (col <= 0) return 0;
|
|
430
|
+
let w = 0;
|
|
431
|
+
let idx = 0;
|
|
432
|
+
for (const ch of line) {
|
|
433
|
+
const cw = stringWidth3(ch);
|
|
434
|
+
if (w + cw > col) break;
|
|
435
|
+
w += cw;
|
|
436
|
+
idx += ch.length;
|
|
437
|
+
}
|
|
438
|
+
return idx;
|
|
439
|
+
}
|
|
409
440
|
function clickToCursor(value, localRow, localCol) {
|
|
410
441
|
if (value.length === 0) return 0;
|
|
411
442
|
const lines = value.split("\n");
|
|
@@ -416,7 +447,7 @@ function clickToCursor(value, localRow, localCol) {
|
|
|
416
447
|
pos += lines[i].length + 1;
|
|
417
448
|
}
|
|
418
449
|
const lineCol = Math.max(0, localCol - INPUT_PREFIX_WIDTH);
|
|
419
|
-
pos +=
|
|
450
|
+
pos += colToStringIndex2(lines[localRow], lineCol);
|
|
420
451
|
return pos;
|
|
421
452
|
}
|
|
422
453
|
|
|
@@ -962,7 +993,7 @@ function computeVisibleWindow(totalLines, scrollOffset, historyMaxHeight) {
|
|
|
962
993
|
}
|
|
963
994
|
function mouseRowToLineIndex(opts) {
|
|
964
995
|
if (opts.visibleCount <= 0) return null;
|
|
965
|
-
const bottomRows = STATUS_BAR_ROWS + opts.skillAcRows + opts.fileAcRows + opts.selectedItemsRows + opts.inputRows;
|
|
996
|
+
const bottomRows = opts.bottomChromeRows ?? STATUS_BAR_ROWS + (opts.skillAcRows ?? 0) + (opts.fileAcRows ?? 0) + (opts.selectedItemsRows ?? 0) + (opts.inputRows ?? 1);
|
|
966
997
|
const innerBoxHeight = opts.terminalRows - bottomRows;
|
|
967
998
|
const chTopRow = innerBoxHeight - opts.visibleCount;
|
|
968
999
|
const chBottomRow = innerBoxHeight - 1;
|
|
@@ -2542,6 +2573,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2542
2573
|
const inputHistoryRef = useRef2([]);
|
|
2543
2574
|
inputHistoryRef.current = inputHistory;
|
|
2544
2575
|
const historyIndexRef = useRef2(-1);
|
|
2576
|
+
const historyDraftRef = useRef2("");
|
|
2545
2577
|
const isNavigatingHistoryRef = useRef2(false);
|
|
2546
2578
|
const totalLines = useMemo(() => {
|
|
2547
2579
|
const visible = messages.filter((m) => m.role !== "system");
|
|
@@ -2558,10 +2590,8 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2558
2590
|
historyMaxHeightRef.current = historyMaxHeight;
|
|
2559
2591
|
const selectionStateRef = useRef2(selectionState);
|
|
2560
2592
|
selectionStateRef.current = selectionState;
|
|
2593
|
+
const bottomChromeRef = useRef2(null);
|
|
2561
2594
|
const inputRowsRef = useRef2(1);
|
|
2562
|
-
const skillAcRowsRef = useRef2(0);
|
|
2563
|
-
const fileAcRowsRef = useRef2(0);
|
|
2564
|
-
const selectedItemsRowsRef = useRef2(0);
|
|
2565
2595
|
const terminalRowsRef = useRef2((stdout == null ? void 0 : stdout.rows) ?? 24);
|
|
2566
2596
|
terminalRowsRef.current = (stdout == null ? void 0 : stdout.rows) ?? 24;
|
|
2567
2597
|
const pendingConfirmRef = useRef2(null);
|
|
@@ -2626,13 +2656,24 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2626
2656
|
automationManagerRef.current.stop();
|
|
2627
2657
|
};
|
|
2628
2658
|
}, []);
|
|
2659
|
+
const enableModesSeq = "\x1B[?1002h\x1B[?1006h\x1B[?1004h";
|
|
2629
2660
|
useEffect3(() => {
|
|
2630
2661
|
if (!stdout) return;
|
|
2631
|
-
stdout.write(
|
|
2662
|
+
stdout.write(enableModesSeq);
|
|
2632
2663
|
return () => {
|
|
2633
|
-
stdout.write("\x1B[?1002l\x1B[?1006l");
|
|
2664
|
+
stdout.write("\x1B[?1004l\x1B[?1002l\x1B[?1006l");
|
|
2634
2665
|
};
|
|
2635
2666
|
}, [stdout]);
|
|
2667
|
+
useEffect3(() => {
|
|
2668
|
+
if (!stdinFilter || !stdout) return;
|
|
2669
|
+
const onResumed = () => {
|
|
2670
|
+
stdout.write(enableModesSeq);
|
|
2671
|
+
};
|
|
2672
|
+
stdinFilter.on("resumed", onResumed);
|
|
2673
|
+
return () => {
|
|
2674
|
+
stdinFilter.off("resumed", onResumed);
|
|
2675
|
+
};
|
|
2676
|
+
}, [stdinFilter, stdout]);
|
|
2636
2677
|
useEffect3(() => {
|
|
2637
2678
|
if (!stdinFilter) return;
|
|
2638
2679
|
const onMouse = (e) => {
|
|
@@ -2672,13 +2713,16 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2672
2713
|
scrollOffsetRef.current,
|
|
2673
2714
|
historyMaxHeightRef.current
|
|
2674
2715
|
);
|
|
2716
|
+
let bottomRows;
|
|
2717
|
+
if (bottomChromeRef.current) {
|
|
2718
|
+
const m = measureElement(bottomChromeRef.current);
|
|
2719
|
+
if (m && m.height > 0) bottomRows = m.height;
|
|
2720
|
+
}
|
|
2675
2721
|
const lineIdx = mouseRowToLineIndex({
|
|
2676
2722
|
mouseRow: e.row,
|
|
2677
2723
|
terminalRows: tRows,
|
|
2724
|
+
bottomChromeRows: bottomRows,
|
|
2678
2725
|
inputRows: inRows,
|
|
2679
|
-
skillAcRows: skillAcRowsRef.current,
|
|
2680
|
-
fileAcRows: fileAcRowsRef.current,
|
|
2681
|
-
selectedItemsRows: selectedItemsRowsRef.current,
|
|
2682
2726
|
visibleCount: window.visibleCount,
|
|
2683
2727
|
hasScrollIndicator: window.hasScrollIndicator
|
|
2684
2728
|
});
|
|
@@ -2721,7 +2765,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2721
2765
|
};
|
|
2722
2766
|
}, [fileAcState.query]);
|
|
2723
2767
|
useInput2((input, key) => {
|
|
2724
|
-
var _a, _b, _c
|
|
2768
|
+
var _a, _b, _c;
|
|
2725
2769
|
if (key.escape && status === "thinking" && abortControllerRef.current) {
|
|
2726
2770
|
abortControllerRef.current.abort();
|
|
2727
2771
|
return;
|
|
@@ -2796,52 +2840,47 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
2796
2840
|
return;
|
|
2797
2841
|
}
|
|
2798
2842
|
const currentInput = ((_c = inputRef.current) == null ? void 0 : _c.getValue()) ?? "";
|
|
2799
|
-
|
|
2843
|
+
const inHistory = historyIndexRef.current >= 0;
|
|
2844
|
+
const canEnterHistory = currentInput === "" || inHistory;
|
|
2845
|
+
const navUp = () => {
|
|
2846
|
+
var _a2;
|
|
2800
2847
|
const history = inputHistoryRef.current;
|
|
2801
2848
|
const newIndex = Math.min(historyIndexRef.current + 1, history.length - 1);
|
|
2802
|
-
if (newIndex
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2849
|
+
if (newIndex < 0 || newIndex >= history.length) return;
|
|
2850
|
+
if (historyIndexRef.current === -1) historyDraftRef.current = currentInput;
|
|
2851
|
+
historyIndexRef.current = newIndex;
|
|
2852
|
+
isNavigatingHistoryRef.current = true;
|
|
2853
|
+
(_a2 = inputRef.current) == null ? void 0 : _a2.fill(history[newIndex]);
|
|
2854
|
+
};
|
|
2855
|
+
const navDown = () => {
|
|
2856
|
+
var _a2, _b2;
|
|
2810
2857
|
const history = inputHistoryRef.current;
|
|
2811
2858
|
if (historyIndexRef.current > 0) {
|
|
2812
2859
|
const newIndex = historyIndexRef.current - 1;
|
|
2813
2860
|
historyIndexRef.current = newIndex;
|
|
2814
2861
|
isNavigatingHistoryRef.current = true;
|
|
2815
|
-
(
|
|
2862
|
+
(_a2 = inputRef.current) == null ? void 0 : _a2.fill(history[newIndex]);
|
|
2816
2863
|
} else if (historyIndexRef.current === 0) {
|
|
2817
2864
|
historyIndexRef.current = -1;
|
|
2818
2865
|
isNavigatingHistoryRef.current = true;
|
|
2819
|
-
(
|
|
2866
|
+
(_b2 = inputRef.current) == null ? void 0 : _b2.fill(historyDraftRef.current);
|
|
2867
|
+
historyDraftRef.current = "";
|
|
2820
2868
|
}
|
|
2869
|
+
};
|
|
2870
|
+
if (canEnterHistory && key.upArrow) {
|
|
2871
|
+
navUp();
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
if (canEnterHistory && key.downArrow) {
|
|
2875
|
+
navDown();
|
|
2821
2876
|
return;
|
|
2822
2877
|
}
|
|
2823
2878
|
if (key.ctrl && input === "p") {
|
|
2824
|
-
|
|
2825
|
-
const newIndex = Math.min(historyIndexRef.current + 1, history.length - 1);
|
|
2826
|
-
if (newIndex >= 0 && newIndex < history.length) {
|
|
2827
|
-
historyIndexRef.current = newIndex;
|
|
2828
|
-
isNavigatingHistoryRef.current = true;
|
|
2829
|
-
(_g = inputRef.current) == null ? void 0 : _g.fill(history[newIndex]);
|
|
2830
|
-
}
|
|
2879
|
+
navUp();
|
|
2831
2880
|
return;
|
|
2832
2881
|
}
|
|
2833
2882
|
if (key.ctrl && input === "n") {
|
|
2834
|
-
|
|
2835
|
-
if (historyIndexRef.current > 0) {
|
|
2836
|
-
const newIndex = historyIndexRef.current - 1;
|
|
2837
|
-
historyIndexRef.current = newIndex;
|
|
2838
|
-
isNavigatingHistoryRef.current = true;
|
|
2839
|
-
(_h = inputRef.current) == null ? void 0 : _h.fill(history[newIndex]);
|
|
2840
|
-
} else if (historyIndexRef.current === 0) {
|
|
2841
|
-
historyIndexRef.current = -1;
|
|
2842
|
-
isNavigatingHistoryRef.current = true;
|
|
2843
|
-
(_i = inputRef.current) == null ? void 0 : _i.fill("");
|
|
2844
|
-
}
|
|
2883
|
+
navDown();
|
|
2845
2884
|
return;
|
|
2846
2885
|
}
|
|
2847
2886
|
});
|
|
@@ -3186,9 +3225,6 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
3186
3225
|
const skillSuggestions = registry ? computeSuggestions(registry.list(), acState) : [];
|
|
3187
3226
|
const acOpen = isOpen(acState, skillSuggestions);
|
|
3188
3227
|
const facOpen = isOpen2(fileAcState, fileSuggestions);
|
|
3189
|
-
skillAcRowsRef.current = acOpen ? skillSuggestions.length + 2 : 0;
|
|
3190
|
-
fileAcRowsRef.current = facOpen ? fileSuggestions.length + 2 : 0;
|
|
3191
|
-
selectedItemsRowsRef.current = selectedItems.length > 0 ? 1 : 0;
|
|
3192
3228
|
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: "100%", children: [
|
|
3193
3229
|
/* @__PURE__ */ jsx6(Box6, { flexGrow: 1, flexDirection: "column", justifyContent: "flex-end", children: /* @__PURE__ */ jsx6(
|
|
3194
3230
|
ConversationHistory,
|
|
@@ -3201,46 +3237,48 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
|
|
|
3201
3237
|
selection: selectionState
|
|
3202
3238
|
}
|
|
3203
3239
|
) }),
|
|
3204
|
-
/* @__PURE__ */
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3240
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", ref: bottomChromeRef, children: [
|
|
3241
|
+
/* @__PURE__ */ jsx6(
|
|
3242
|
+
StatusBar,
|
|
3243
|
+
{
|
|
3244
|
+
status,
|
|
3245
|
+
toolName,
|
|
3246
|
+
confirmPrompt,
|
|
3247
|
+
version,
|
|
3248
|
+
tokenUsage
|
|
3249
|
+
}
|
|
3250
|
+
),
|
|
3251
|
+
/* @__PURE__ */ jsx6(
|
|
3252
|
+
SkillAutocomplete,
|
|
3253
|
+
{
|
|
3254
|
+
suggestions: skillSuggestions,
|
|
3255
|
+
selectedIndex: acState.selectedIndex,
|
|
3256
|
+
isOpen: acOpen
|
|
3257
|
+
}
|
|
3258
|
+
),
|
|
3259
|
+
/* @__PURE__ */ jsx6(
|
|
3260
|
+
FileAutocomplete,
|
|
3261
|
+
{
|
|
3262
|
+
suggestions: fileSuggestions,
|
|
3263
|
+
selectedIndex: fileAcState.selectedIndex,
|
|
3264
|
+
isOpen: facOpen
|
|
3265
|
+
}
|
|
3266
|
+
),
|
|
3267
|
+
selectedItems.length > 0 && /* @__PURE__ */ jsx6(Box6, { paddingLeft: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "cyan", dimColor: true, children: [
|
|
3268
|
+
"Selected: ",
|
|
3269
|
+
selectedItems.map((i) => i.label).join(", ")
|
|
3270
|
+
] }) }),
|
|
3271
|
+
/* @__PURE__ */ jsx6(
|
|
3272
|
+
Input_default,
|
|
3273
|
+
{
|
|
3274
|
+
ref: inputRef,
|
|
3275
|
+
isActive: isInputActive,
|
|
3276
|
+
onSubmit: handleSubmit,
|
|
3277
|
+
onChange: handleInputTextChange,
|
|
3278
|
+
placeholder: status === "awaiting_confirm" ? "y / n" : void 0
|
|
3279
|
+
}
|
|
3280
|
+
)
|
|
3281
|
+
] })
|
|
3244
3282
|
] });
|
|
3245
3283
|
}
|
|
3246
3284
|
|
|
@@ -3306,6 +3344,7 @@ function tokenizeStdin(input, pendingIn) {
|
|
|
3306
3344
|
let i = 0;
|
|
3307
3345
|
let keyboardOut = "";
|
|
3308
3346
|
const events = [];
|
|
3347
|
+
const focusEvents = [];
|
|
3309
3348
|
while (i < data.length) {
|
|
3310
3349
|
const ch = data[i];
|
|
3311
3350
|
if (ch !== "\x1B") {
|
|
@@ -3327,13 +3366,18 @@ function tokenizeStdin(input, pendingIn) {
|
|
|
3327
3366
|
i += mLen;
|
|
3328
3367
|
continue;
|
|
3329
3368
|
}
|
|
3369
|
+
if (tail.length >= 3 && tail[1] === "[" && (tail[2] === "I" || tail[2] === "O")) {
|
|
3370
|
+
focusEvents.push({ kind: "focus", focused: tail[2] === "I" });
|
|
3371
|
+
i += 3;
|
|
3372
|
+
continue;
|
|
3373
|
+
}
|
|
3330
3374
|
if (isMousePartial(tail) && tail.length < MAX_MOUSE_SEQ) {
|
|
3331
|
-
return { keyboard: keyboardOut, pending: tail, events };
|
|
3375
|
+
return { keyboard: keyboardOut, pending: tail, events, focusEvents };
|
|
3332
3376
|
}
|
|
3333
3377
|
keyboardOut += ch;
|
|
3334
3378
|
i++;
|
|
3335
3379
|
}
|
|
3336
|
-
return { keyboard: keyboardOut, pending: "", events };
|
|
3380
|
+
return { keyboard: keyboardOut, pending: "", events, focusEvents };
|
|
3337
3381
|
}
|
|
3338
3382
|
|
|
3339
3383
|
// src/ui/stdinFilter.ts
|
|
@@ -3341,12 +3385,22 @@ var StdinFilterImpl = class extends Transform {
|
|
|
3341
3385
|
isTTY;
|
|
3342
3386
|
source;
|
|
3343
3387
|
pending = "";
|
|
3344
|
-
|
|
3388
|
+
// 焦点状态——cc-haha 把 focus 作 signal 而非 mode switch(§5.4)。
|
|
3389
|
+
// CSI I/O 切换;任何字节到达时若为 false 由 failsafe 强制回 true。
|
|
3390
|
+
focused = true;
|
|
3391
|
+
// resume 检测:最近一次活动时间戳;间隔 > resumeIdleMs 算 SSH 重连 / tmux detach 回来。
|
|
3392
|
+
lastByteAt = 0;
|
|
3393
|
+
resumeIdleMs;
|
|
3394
|
+
constructor(source, opts = {}) {
|
|
3345
3395
|
super();
|
|
3346
3396
|
this.source = source;
|
|
3347
3397
|
this.isTTY = source.isTTY ?? false;
|
|
3398
|
+
this.resumeIdleMs = opts.resumeIdleMs ?? 5e3;
|
|
3348
3399
|
source.pipe(this);
|
|
3349
3400
|
}
|
|
3401
|
+
isFocused() {
|
|
3402
|
+
return this.focused;
|
|
3403
|
+
}
|
|
3350
3404
|
setRawMode(mode) {
|
|
3351
3405
|
var _a, _b;
|
|
3352
3406
|
(_b = (_a = this.source).setRawMode) == null ? void 0 : _b.call(_a, mode);
|
|
@@ -3361,9 +3415,23 @@ var StdinFilterImpl = class extends Transform {
|
|
|
3361
3415
|
}
|
|
3362
3416
|
_transform(chunk, _encoding, callback) {
|
|
3363
3417
|
const s = typeof chunk === "string" ? chunk : chunk.toString("binary");
|
|
3364
|
-
const
|
|
3418
|
+
const now = Date.now();
|
|
3419
|
+
if (this.lastByteAt > 0 && now - this.lastByteAt >= this.resumeIdleMs) {
|
|
3420
|
+
this.emit("resumed");
|
|
3421
|
+
}
|
|
3422
|
+
this.lastByteAt = now;
|
|
3423
|
+
const { keyboard, pending, events, focusEvents } = tokenizeStdin(s, this.pending);
|
|
3365
3424
|
this.pending = pending;
|
|
3425
|
+
for (const ev of focusEvents) {
|
|
3426
|
+
this.focused = ev.focused;
|
|
3427
|
+
this.emit("focus", ev);
|
|
3428
|
+
}
|
|
3366
3429
|
for (const ev of events) this.emit("mouse", ev);
|
|
3430
|
+
const hadNonFocusActivity = events.length > 0 || keyboard.length > 0;
|
|
3431
|
+
if (hadNonFocusActivity && !this.focused) {
|
|
3432
|
+
this.focused = true;
|
|
3433
|
+
this.emit("focus", { kind: "focus", focused: true });
|
|
3434
|
+
}
|
|
3367
3435
|
if (keyboard.length > 0) {
|
|
3368
3436
|
callback(null, Buffer.from(keyboard, "binary"));
|
|
3369
3437
|
} else {
|
|
@@ -3371,8 +3439,8 @@ var StdinFilterImpl = class extends Transform {
|
|
|
3371
3439
|
}
|
|
3372
3440
|
}
|
|
3373
3441
|
};
|
|
3374
|
-
function createStdinFilter(source) {
|
|
3375
|
-
return new StdinFilterImpl(source);
|
|
3442
|
+
function createStdinFilter(source, opts) {
|
|
3443
|
+
return new StdinFilterImpl(source, opts);
|
|
3376
3444
|
}
|
|
3377
3445
|
export {
|
|
3378
3446
|
App,
|