@oxecli/oxe 1.0.112 → 1.0.113
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/ui.js +49 -1
- package/package.json +1 -1
package/dist/ui.js
CHANGED
|
@@ -1249,6 +1249,17 @@ export const PROMPT_PLACEHOLDER = "Describe a coding task, or type /help for com
|
|
|
1249
1249
|
const MAX_PROMPT_DISPLAY_LINES = 12;
|
|
1250
1250
|
const MAX_PROMPT_PASTE_CHARS = 400;
|
|
1251
1251
|
const MAX_PROMPT_CHARS = 500;
|
|
1252
|
+
/**
|
|
1253
|
+
* Watchdog for bracketed paste. Some terminals (notably Windows Terminal /
|
|
1254
|
+
* conpty) occasionally drop the paste-END marker, which would leave the field
|
|
1255
|
+
* permanently capturing keystrokes (a "locked" prompt). If a paste-start
|
|
1256
|
+
* arrives but no paste-end AND no further paste data shows up within this
|
|
1257
|
+
* window, we treat the paste as aborted, release capture, and keep whatever
|
|
1258
|
+
* text already arrived so input is never lost. The window resets on every
|
|
1259
|
+
* received paste chunk, so a genuine (continuously-streaming) paste is never
|
|
1260
|
+
* cut short.
|
|
1261
|
+
*/
|
|
1262
|
+
const PASTE_GUARD_MS = 3000;
|
|
1252
1263
|
function shouldCollapsePaste(text) {
|
|
1253
1264
|
return (text.split("\n").length > MAX_PROMPT_DISPLAY_LINES ||
|
|
1254
1265
|
text.length > MAX_PROMPT_PASTE_CHARS);
|
|
@@ -1555,6 +1566,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1555
1566
|
let draft = null;
|
|
1556
1567
|
let bracketedPaste = false;
|
|
1557
1568
|
let bracketedPasteBuffer = "";
|
|
1569
|
+
let pasteGuardTimer = null;
|
|
1558
1570
|
let pasteBurst = false;
|
|
1559
1571
|
let pasteBurstTimer = null;
|
|
1560
1572
|
readline.emitKeypressEvents(process.stdin);
|
|
@@ -1593,6 +1605,10 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1593
1605
|
bracketedPasteBuffer = "";
|
|
1594
1606
|
if (pasteBurstTimer)
|
|
1595
1607
|
clearTimeout(pasteBurstTimer);
|
|
1608
|
+
if (pasteGuardTimer) {
|
|
1609
|
+
clearTimeout(pasteGuardTimer);
|
|
1610
|
+
pasteGuardTimer = null;
|
|
1611
|
+
}
|
|
1596
1612
|
if (isErr) {
|
|
1597
1613
|
clearBox();
|
|
1598
1614
|
dockSetInactive();
|
|
@@ -1898,17 +1914,46 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1898
1914
|
const end = "\x1b[201~";
|
|
1899
1915
|
const sequence = key?.sequence || "";
|
|
1900
1916
|
const value = str || "";
|
|
1917
|
+
// A paste-end marker must close the capture. If it never arrives and no
|
|
1918
|
+
// more paste data follows, the guard below auto-releases the field so it
|
|
1919
|
+
// can't lock. (definitions hoisted below)
|
|
1920
|
+
const armPasteGuard = () => {
|
|
1921
|
+
if (pasteGuardTimer)
|
|
1922
|
+
clearTimeout(pasteGuardTimer);
|
|
1923
|
+
pasteGuardTimer = setTimeout(() => {
|
|
1924
|
+
pasteGuardTimer = null;
|
|
1925
|
+
if (!bracketedPaste)
|
|
1926
|
+
return;
|
|
1927
|
+
// The terminal dropped the paste-end (a Windows/conpty failure). Bail
|
|
1928
|
+
// out of capture mode and insert whatever already arrived so nothing
|
|
1929
|
+
// typed afterward is swallowed.
|
|
1930
|
+
bracketedPaste = false;
|
|
1931
|
+
const leftover = bracketedPasteBuffer;
|
|
1932
|
+
bracketedPasteBuffer = "";
|
|
1933
|
+
if (leftover)
|
|
1934
|
+
insert(leftover, true);
|
|
1935
|
+
repaint();
|
|
1936
|
+
}, PASTE_GUARD_MS);
|
|
1937
|
+
};
|
|
1938
|
+
const disarmPasteGuard = () => {
|
|
1939
|
+
if (pasteGuardTimer) {
|
|
1940
|
+
clearTimeout(pasteGuardTimer);
|
|
1941
|
+
pasteGuardTimer = null;
|
|
1942
|
+
}
|
|
1943
|
+
};
|
|
1901
1944
|
// A new paste-start while already inside a paste means the previous paste
|
|
1902
1945
|
// was aborted (its end marker never arrived). Reset and start over so we
|
|
1903
1946
|
// never swallow subsequent typing.
|
|
1904
1947
|
if ((key?.name === "paste-start" || sequence === start || value === start)) {
|
|
1905
1948
|
bracketedPaste = true;
|
|
1906
1949
|
bracketedPasteBuffer = "";
|
|
1950
|
+
armPasteGuard();
|
|
1907
1951
|
const inline = value === start ? "" : value.startsWith(start) ? value.slice(start.length) : "";
|
|
1908
1952
|
if (inline)
|
|
1909
1953
|
bracketedPasteBuffer = inline;
|
|
1910
1954
|
if (inline.includes(end)) {
|
|
1911
1955
|
const pasted = inline.slice(0, inline.indexOf(end)).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1956
|
+
disarmPasteGuard();
|
|
1912
1957
|
bracketedPaste = false;
|
|
1913
1958
|
bracketedPasteBuffer = "";
|
|
1914
1959
|
if (pasted)
|
|
@@ -1926,6 +1971,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1926
1971
|
if (key?.name === "paste-end" || sequence === end || value === end || endAt >= 0) {
|
|
1927
1972
|
bracketedPasteBuffer += endAt >= 0 ? value.slice(0, endAt) : "";
|
|
1928
1973
|
const pasted = bracketedPasteBuffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1974
|
+
disarmPasteGuard();
|
|
1929
1975
|
bracketedPaste = false;
|
|
1930
1976
|
bracketedPasteBuffer = "";
|
|
1931
1977
|
if (pasted)
|
|
@@ -1934,8 +1980,10 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = [], hin
|
|
|
1934
1980
|
return true;
|
|
1935
1981
|
}
|
|
1936
1982
|
const chunk = value || (sequence && !sequence.startsWith("\x1b[") ? sequence : "");
|
|
1937
|
-
if (chunk)
|
|
1983
|
+
if (chunk) {
|
|
1938
1984
|
bracketedPasteBuffer += chunk;
|
|
1985
|
+
armPasteGuard();
|
|
1986
|
+
}
|
|
1939
1987
|
return true;
|
|
1940
1988
|
};
|
|
1941
1989
|
const markPasteBurst = () => {
|