laohuang 0.8.5 → 0.8.6
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/bin.js +1035 -718
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/main.ts
|
|
4
4
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
|
|
5
|
-
import { dirname as dirname8, join as
|
|
5
|
+
import { dirname as dirname8, join as join14 } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
|
|
8
8
|
// ../../packages/core/agent-runtime/dist/agent.js
|
|
@@ -7862,10 +7862,614 @@ function enterTerminalRawMode(input, console2 = input === process.stdin ? getWin
|
|
|
7862
7862
|
}
|
|
7863
7863
|
}
|
|
7864
7864
|
|
|
7865
|
+
// ../../packages/terminal/tui/dist/tui/terminal-session.js
|
|
7866
|
+
function inputTimeout(kind, env = process.env) {
|
|
7867
|
+
if (kind === "none" || kind === "paste")
|
|
7868
|
+
return null;
|
|
7869
|
+
if (kind === "negotiation")
|
|
7870
|
+
return 150;
|
|
7871
|
+
if (kind === "sequence")
|
|
7872
|
+
return 50;
|
|
7873
|
+
const configured = Number(env.LAOHUANG_ESC_TIMEOUT);
|
|
7874
|
+
if (Number.isFinite(configured) && configured > 0)
|
|
7875
|
+
return configured;
|
|
7876
|
+
return env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT ? 100 : 10;
|
|
7877
|
+
}
|
|
7878
|
+
async function drainTerminalInput(input, maxMs = 1e3, idleMs = 50) {
|
|
7879
|
+
if (!input?.off)
|
|
7880
|
+
return;
|
|
7881
|
+
await new Promise((resolve8) => {
|
|
7882
|
+
let idle;
|
|
7883
|
+
const finish = () => {
|
|
7884
|
+
clearTimeout(idle);
|
|
7885
|
+
clearTimeout(deadline);
|
|
7886
|
+
input.off?.("data", onData);
|
|
7887
|
+
resolve8();
|
|
7888
|
+
};
|
|
7889
|
+
const onData = () => {
|
|
7890
|
+
clearTimeout(idle);
|
|
7891
|
+
idle = setTimeout(finish, idleMs);
|
|
7892
|
+
};
|
|
7893
|
+
const deadline = setTimeout(finish, maxMs);
|
|
7894
|
+
input.on("data", onData);
|
|
7895
|
+
idle = setTimeout(finish, idleMs);
|
|
7896
|
+
});
|
|
7897
|
+
}
|
|
7898
|
+
function refreshTerminalDimensions() {
|
|
7899
|
+
if (process.platform === "win32")
|
|
7900
|
+
return;
|
|
7901
|
+
try {
|
|
7902
|
+
process.kill(process.pid, "SIGWINCH");
|
|
7903
|
+
} catch {
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
function supportsTerminalHyperlinks(env = process.env) {
|
|
7907
|
+
if (env.LAOHUANG_HYPERLINKS !== void 0)
|
|
7908
|
+
return env.LAOHUANG_HYPERLINKS === "1";
|
|
7909
|
+
if (!process.stdout.isTTY || env.TERM === "dumb")
|
|
7910
|
+
return false;
|
|
7911
|
+
return Boolean(env.WT_SESSION || env.KITTY_WINDOW_ID || env.VTE_VERSION || ["iTerm.app", "WezTerm", "vscode", "ghostty"].includes(env.TERM_PROGRAM ?? ""));
|
|
7912
|
+
}
|
|
7913
|
+
|
|
7914
|
+
// ../../node_modules/get-east-asian-width/lookup-data.js
|
|
7915
|
+
var ambiguousMinimalCodePoint = 161;
|
|
7916
|
+
var ambiguousMaximumCodePoint = 1114109;
|
|
7917
|
+
var ambiguousRanges = [161, 161, 164, 164, 167, 168, 170, 170, 173, 174, 176, 180, 182, 186, 188, 191, 198, 198, 208, 208, 215, 216, 222, 225, 230, 230, 232, 234, 236, 237, 240, 240, 242, 243, 247, 250, 252, 252, 254, 254, 257, 257, 273, 273, 275, 275, 283, 283, 294, 295, 299, 299, 305, 307, 312, 312, 319, 322, 324, 324, 328, 331, 333, 333, 338, 339, 358, 359, 363, 363, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 476, 593, 593, 609, 609, 708, 708, 711, 711, 713, 715, 717, 717, 720, 720, 728, 731, 733, 733, 735, 735, 768, 879, 913, 929, 931, 937, 945, 961, 963, 969, 1025, 1025, 1040, 1103, 1105, 1105, 8208, 8208, 8211, 8214, 8216, 8217, 8220, 8221, 8224, 8226, 8228, 8231, 8240, 8240, 8242, 8243, 8245, 8245, 8251, 8251, 8254, 8254, 8308, 8308, 8319, 8319, 8321, 8324, 8364, 8364, 8451, 8451, 8453, 8453, 8457, 8457, 8467, 8467, 8470, 8470, 8481, 8482, 8486, 8486, 8491, 8491, 8531, 8532, 8539, 8542, 8544, 8555, 8560, 8569, 8585, 8585, 8592, 8601, 8632, 8633, 8658, 8658, 8660, 8660, 8679, 8679, 8704, 8704, 8706, 8707, 8711, 8712, 8715, 8715, 8719, 8719, 8721, 8721, 8725, 8725, 8730, 8730, 8733, 8736, 8739, 8739, 8741, 8741, 8743, 8748, 8750, 8750, 8756, 8759, 8764, 8765, 8776, 8776, 8780, 8780, 8786, 8786, 8800, 8801, 8804, 8807, 8810, 8811, 8814, 8815, 8834, 8835, 8838, 8839, 8853, 8853, 8857, 8857, 8869, 8869, 8895, 8895, 8978, 8978, 9312, 9449, 9451, 9547, 9552, 9587, 9600, 9615, 9618, 9621, 9632, 9633, 9635, 9641, 9650, 9651, 9654, 9655, 9660, 9661, 9664, 9665, 9670, 9672, 9675, 9675, 9678, 9681, 9698, 9701, 9711, 9711, 9733, 9734, 9737, 9737, 9742, 9743, 9756, 9756, 9758, 9758, 9792, 9792, 9794, 9794, 9824, 9825, 9827, 9829, 9831, 9834, 9836, 9837, 9839, 9839, 9886, 9887, 9919, 9919, 9926, 9933, 9935, 9939, 9941, 9953, 9955, 9955, 9960, 9961, 9963, 9969, 9972, 9972, 9974, 9977, 9979, 9980, 9982, 9983, 10045, 10045, 10102, 10111, 11094, 11097, 12872, 12879, 57344, 63743, 65024, 65039, 65533, 65533, 127232, 127242, 127248, 127277, 127280, 127337, 127344, 127373, 127375, 127376, 127387, 127404, 917760, 917999, 983040, 1048573, 1048576, 1114109];
|
|
7918
|
+
var fullwidthMinimalCodePoint = 12288;
|
|
7919
|
+
var fullwidthMaximumCodePoint = 65510;
|
|
7920
|
+
var fullwidthRanges = [12288, 12288, 65281, 65376, 65504, 65510];
|
|
7921
|
+
var wideMinimalCodePoint = 4352;
|
|
7922
|
+
var wideMaximumCodePoint = 262141;
|
|
7923
|
+
var wideRanges = [4352, 4447, 8986, 8987, 9001, 9002, 9193, 9196, 9200, 9200, 9203, 9203, 9725, 9726, 9748, 9749, 9776, 9783, 9800, 9811, 9855, 9855, 9866, 9871, 9875, 9875, 9889, 9889, 9898, 9899, 9917, 9918, 9924, 9925, 9934, 9934, 9940, 9940, 9962, 9962, 9970, 9971, 9973, 9973, 9978, 9978, 9981, 9981, 9989, 9989, 9994, 9995, 10024, 10024, 10060, 10060, 10062, 10062, 10067, 10069, 10071, 10071, 10133, 10135, 10160, 10160, 10175, 10175, 11035, 11036, 11088, 11088, 11093, 11093, 11904, 11929, 11931, 12019, 12032, 12245, 12272, 12287, 12289, 12350, 12353, 12438, 12441, 12543, 12549, 12591, 12593, 12686, 12688, 12773, 12783, 12830, 12832, 12871, 12880, 42124, 42128, 42182, 43360, 43388, 44032, 55203, 63744, 64255, 65040, 65049, 65072, 65106, 65108, 65126, 65128, 65131, 94176, 94180, 94192, 94198, 94208, 101589, 101631, 101662, 101760, 101874, 110576, 110579, 110581, 110587, 110589, 110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951, 110960, 111355, 119552, 119638, 119648, 119670, 126980, 126980, 127183, 127183, 127374, 127374, 127377, 127386, 127488, 127490, 127504, 127547, 127552, 127560, 127568, 127569, 127584, 127589, 127744, 127776, 127789, 127797, 127799, 127868, 127870, 127891, 127904, 127946, 127951, 127955, 127968, 127984, 127988, 127988, 127992, 128062, 128064, 128064, 128066, 128252, 128255, 128317, 128331, 128334, 128336, 128359, 128378, 128378, 128405, 128406, 128420, 128420, 128507, 128591, 128640, 128709, 128716, 128716, 128720, 128722, 128725, 128728, 128732, 128735, 128747, 128748, 128756, 128764, 128992, 129003, 129008, 129008, 129292, 129338, 129340, 129349, 129351, 129535, 129648, 129660, 129664, 129674, 129678, 129734, 129736, 129736, 129741, 129756, 129759, 129770, 129775, 129784, 131072, 196605, 196608, 262141];
|
|
7924
|
+
|
|
7925
|
+
// ../../node_modules/get-east-asian-width/utilities.js
|
|
7926
|
+
var isInRange = (ranges, codePoint) => {
|
|
7927
|
+
let low = 0;
|
|
7928
|
+
let high = Math.floor(ranges.length / 2) - 1;
|
|
7929
|
+
while (low <= high) {
|
|
7930
|
+
const mid = Math.floor((low + high) / 2);
|
|
7931
|
+
const i = mid * 2;
|
|
7932
|
+
if (codePoint < ranges[i]) {
|
|
7933
|
+
high = mid - 1;
|
|
7934
|
+
} else if (codePoint > ranges[i + 1]) {
|
|
7935
|
+
low = mid + 1;
|
|
7936
|
+
} else {
|
|
7937
|
+
return true;
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7940
|
+
return false;
|
|
7941
|
+
};
|
|
7942
|
+
|
|
7943
|
+
// ../../node_modules/get-east-asian-width/lookup.js
|
|
7944
|
+
var commonCjkCodePoint = 19968;
|
|
7945
|
+
var [wideFastPathStart, wideFastPathEnd] = /* @__PURE__ */ findWideFastPathRange(wideRanges);
|
|
7946
|
+
function findWideFastPathRange(ranges) {
|
|
7947
|
+
let fastPathStart = ranges[0];
|
|
7948
|
+
let fastPathEnd = ranges[1];
|
|
7949
|
+
for (let index = 0; index < ranges.length; index += 2) {
|
|
7950
|
+
const start = ranges[index];
|
|
7951
|
+
const end = ranges[index + 1];
|
|
7952
|
+
if (commonCjkCodePoint >= start && commonCjkCodePoint <= end) {
|
|
7953
|
+
return [start, end];
|
|
7954
|
+
}
|
|
7955
|
+
if (end - start > fastPathEnd - fastPathStart) {
|
|
7956
|
+
fastPathStart = start;
|
|
7957
|
+
fastPathEnd = end;
|
|
7958
|
+
}
|
|
7959
|
+
}
|
|
7960
|
+
return [fastPathStart, fastPathEnd];
|
|
7961
|
+
}
|
|
7962
|
+
var isAmbiguous = (codePoint) => {
|
|
7963
|
+
if (codePoint < ambiguousMinimalCodePoint || codePoint > ambiguousMaximumCodePoint) {
|
|
7964
|
+
return false;
|
|
7965
|
+
}
|
|
7966
|
+
return isInRange(ambiguousRanges, codePoint);
|
|
7967
|
+
};
|
|
7968
|
+
var isFullWidth = (codePoint) => {
|
|
7969
|
+
if (codePoint < fullwidthMinimalCodePoint || codePoint > fullwidthMaximumCodePoint) {
|
|
7970
|
+
return false;
|
|
7971
|
+
}
|
|
7972
|
+
return isInRange(fullwidthRanges, codePoint);
|
|
7973
|
+
};
|
|
7974
|
+
var isWide = (codePoint) => {
|
|
7975
|
+
if (codePoint >= wideFastPathStart && codePoint <= wideFastPathEnd) {
|
|
7976
|
+
return true;
|
|
7977
|
+
}
|
|
7978
|
+
if (codePoint < wideMinimalCodePoint || codePoint > wideMaximumCodePoint) {
|
|
7979
|
+
return false;
|
|
7980
|
+
}
|
|
7981
|
+
return isInRange(wideRanges, codePoint);
|
|
7982
|
+
};
|
|
7983
|
+
|
|
7984
|
+
// ../../node_modules/get-east-asian-width/index.js
|
|
7985
|
+
function validate(codePoint) {
|
|
7986
|
+
if (!Number.isSafeInteger(codePoint)) {
|
|
7987
|
+
throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7990
|
+
function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
|
|
7991
|
+
validate(codePoint);
|
|
7992
|
+
if (isFullWidth(codePoint) || isWide(codePoint) || ambiguousAsWide && isAmbiguous(codePoint)) {
|
|
7993
|
+
return 2;
|
|
7994
|
+
}
|
|
7995
|
+
return 1;
|
|
7996
|
+
}
|
|
7997
|
+
|
|
7998
|
+
// ../../packages/terminal/tui/dist/tui/terminal-text.js
|
|
7999
|
+
var segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
8000
|
+
var nonPrinting = new RegExp("^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Mark})$", "u");
|
|
8001
|
+
var spacingMark = new RegExp(String.raw`^(?:[\p{Spacing_Mark}--[\u1734\u302E\u302F]]|[\u065F\u0F7F\u102B\u102C\u1031\u1033-\u1035\u1038\u103A-\u103E])$`, "v");
|
|
8002
|
+
var emoji = new RegExp(String.raw`^\p{RGI_Emoji}$`, "v");
|
|
8003
|
+
var TERMINAL_RESET = "\x1B[0m\x1B]8;;\x07";
|
|
8004
|
+
var widthCache = /* @__PURE__ */ new Map();
|
|
8005
|
+
function graphemeClusters(text2) {
|
|
8006
|
+
return Array.from(segmenter.segment(text2), ({ segment }) => segment);
|
|
8007
|
+
}
|
|
8008
|
+
function clusterWidth(cluster) {
|
|
8009
|
+
if (cluster === " ")
|
|
8010
|
+
return 3;
|
|
8011
|
+
if (emoji.test(cluster))
|
|
8012
|
+
return 2;
|
|
8013
|
+
const chars = [...cluster];
|
|
8014
|
+
let width = 0;
|
|
8015
|
+
let foundBase = false;
|
|
8016
|
+
let followsMark = false;
|
|
8017
|
+
for (const char of chars) {
|
|
8018
|
+
const cp = char.codePointAt(0);
|
|
8019
|
+
if (spacingMark.test(char)) {
|
|
8020
|
+
width += 1;
|
|
8021
|
+
followsMark = false;
|
|
8022
|
+
} else if (nonPrinting.test(char)) {
|
|
8023
|
+
if (new RegExp("\\p{Mark}", "u").test(char))
|
|
8024
|
+
followsMark = true;
|
|
8025
|
+
} else if (!foundBase) {
|
|
8026
|
+
if (cp >= 127462 && cp <= 127487)
|
|
8027
|
+
return 2;
|
|
8028
|
+
width += eastAsianWidth(cp);
|
|
8029
|
+
foundBase = true;
|
|
8030
|
+
followsMark = false;
|
|
8031
|
+
} else {
|
|
8032
|
+
if (followsMark || cp >= 65280 && cp <= 65519)
|
|
8033
|
+
width += eastAsianWidth(cp);
|
|
8034
|
+
else if (cp === 3635 || cp === 3763)
|
|
8035
|
+
width += 1;
|
|
8036
|
+
followsMark = false;
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
8039
|
+
return width;
|
|
8040
|
+
}
|
|
8041
|
+
function normalizeDisplayCluster(cluster) {
|
|
8042
|
+
return cluster === " " ? " " : cluster.replace(/[\uD800-\uDFFF]/gu, "\uFFFD").replace(/\u0e33/g, "\u0E4D\u0E32").replace(/\u0eb3/g, "\u0ECD\u0EB2");
|
|
8043
|
+
}
|
|
8044
|
+
function escapeEnd(text2, start) {
|
|
8045
|
+
const marker = text2[start + 1];
|
|
8046
|
+
if (marker === "[") {
|
|
8047
|
+
let end = start + 2;
|
|
8048
|
+
while (end < text2.length) {
|
|
8049
|
+
const cp = text2.charCodeAt(end++);
|
|
8050
|
+
if (cp >= 64 && cp <= 126)
|
|
8051
|
+
break;
|
|
8052
|
+
}
|
|
8053
|
+
return end;
|
|
8054
|
+
}
|
|
8055
|
+
if (marker === "]" || marker === "P" || marker === "_" || marker === "^" || marker === "X") {
|
|
8056
|
+
let end = start + 2;
|
|
8057
|
+
while (end < text2.length) {
|
|
8058
|
+
if (text2[end] === "\x07")
|
|
8059
|
+
return end + 1;
|
|
8060
|
+
if (text2[end] === "\x1B" && text2[end + 1] === "\\")
|
|
8061
|
+
return end + 2;
|
|
8062
|
+
end++;
|
|
8063
|
+
}
|
|
8064
|
+
return end;
|
|
8065
|
+
}
|
|
8066
|
+
return Math.min(text2.length, start + 2);
|
|
8067
|
+
}
|
|
8068
|
+
function stripTerminalControls(text2) {
|
|
8069
|
+
let result = "";
|
|
8070
|
+
for (let index = 0; index < text2.length; ) {
|
|
8071
|
+
if (text2[index] === "\x1B")
|
|
8072
|
+
index = escapeEnd(text2, index);
|
|
8073
|
+
else {
|
|
8074
|
+
const char = text2[index++];
|
|
8075
|
+
if (!/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/u.test(char))
|
|
8076
|
+
result += char;
|
|
8077
|
+
}
|
|
8078
|
+
}
|
|
8079
|
+
return result;
|
|
8080
|
+
}
|
|
8081
|
+
function visibleWidth(text2) {
|
|
8082
|
+
if (/^[\x20-\x7e]*$/u.test(text2))
|
|
8083
|
+
return text2.length;
|
|
8084
|
+
const cached = widthCache.get(text2);
|
|
8085
|
+
if (cached !== void 0)
|
|
8086
|
+
return cached;
|
|
8087
|
+
let width = 0;
|
|
8088
|
+
for (const { segment } of segmenter.segment(stripTerminalControls(text2)))
|
|
8089
|
+
width += clusterWidth(segment);
|
|
8090
|
+
if (text2.length <= 4096) {
|
|
8091
|
+
if (widthCache.size >= 512)
|
|
8092
|
+
widthCache.delete(widthCache.keys().next().value);
|
|
8093
|
+
widthCache.set(text2, width);
|
|
8094
|
+
}
|
|
8095
|
+
return width;
|
|
8096
|
+
}
|
|
8097
|
+
var TerminalStyle = class {
|
|
8098
|
+
codes = /* @__PURE__ */ new Map();
|
|
8099
|
+
link = "";
|
|
8100
|
+
accept(sequence) {
|
|
8101
|
+
if (sequence.startsWith("\x1B]8;")) {
|
|
8102
|
+
const match = /^\x1b\]8;[^;]*;([^\x00-\x1f\x7f]*)(?:\x07|\x1b\\)$/u.exec(sequence);
|
|
8103
|
+
if (match)
|
|
8104
|
+
this.link = match[1] ? `\x1B]8;;${match[1]}\x07` : "";
|
|
8105
|
+
return;
|
|
8106
|
+
}
|
|
8107
|
+
if (!/^\x1b\[[\d;]*m$/u.test(sequence))
|
|
8108
|
+
return;
|
|
8109
|
+
const parts = sequence.slice(2, -1).split(";").map(Number);
|
|
8110
|
+
for (let index = 0; index < parts.length; index++) {
|
|
8111
|
+
const code = parts[index];
|
|
8112
|
+
if (code === 0)
|
|
8113
|
+
this.codes.clear();
|
|
8114
|
+
else if (code === 38 || code === 48) {
|
|
8115
|
+
const count = parts[index + 1] === 5 ? 3 : parts[index + 1] === 2 ? 5 : 1;
|
|
8116
|
+
if (index + count <= parts.length)
|
|
8117
|
+
this.codes.set(code, parts.slice(index, index + count).join(";"));
|
|
8118
|
+
index += count - 1;
|
|
8119
|
+
} else if (code >= 30 && code <= 37 || code >= 90 && code <= 97)
|
|
8120
|
+
this.codes.set(38, String(code));
|
|
8121
|
+
else if (code >= 40 && code <= 47 || code >= 100 && code <= 107)
|
|
8122
|
+
this.codes.set(48, String(code));
|
|
8123
|
+
else if (code === 39)
|
|
8124
|
+
this.codes.delete(38);
|
|
8125
|
+
else if (code === 49)
|
|
8126
|
+
this.codes.delete(48);
|
|
8127
|
+
else if (code === 22) {
|
|
8128
|
+
this.codes.delete(1);
|
|
8129
|
+
this.codes.delete(2);
|
|
8130
|
+
} else if (code >= 23 && code <= 29)
|
|
8131
|
+
this.codes.delete(code - 20);
|
|
8132
|
+
else if (code >= 1 && code <= 9)
|
|
8133
|
+
this.codes.set(code, String(code));
|
|
8134
|
+
}
|
|
8135
|
+
}
|
|
8136
|
+
prefix() {
|
|
8137
|
+
return (this.codes.size ? `\x1B[${[...this.codes.values()].join(";")}m` : "") + this.link;
|
|
8138
|
+
}
|
|
8139
|
+
};
|
|
8140
|
+
function terminalCells(text2) {
|
|
8141
|
+
const style = new TerminalStyle();
|
|
8142
|
+
const runs = [];
|
|
8143
|
+
let clean = "";
|
|
8144
|
+
for (let index = 0; index < text2.length; ) {
|
|
8145
|
+
if (text2[index] === "\x1B") {
|
|
8146
|
+
const end = escapeEnd(text2, index);
|
|
8147
|
+
style.accept(text2.slice(index, end));
|
|
8148
|
+
index = end;
|
|
8149
|
+
} else {
|
|
8150
|
+
const end = text2.indexOf("\x1B", index);
|
|
8151
|
+
runs.push({ start: clean.length, prefix: style.prefix() });
|
|
8152
|
+
clean += stripTerminalControls(text2.slice(index, end < 0 ? text2.length : end));
|
|
8153
|
+
index = end < 0 ? text2.length : end;
|
|
8154
|
+
}
|
|
8155
|
+
}
|
|
8156
|
+
const cells = [];
|
|
8157
|
+
let run = 0;
|
|
8158
|
+
for (const { segment, index } of segmenter.segment(clean)) {
|
|
8159
|
+
while (run + 1 < runs.length && runs[run + 1].start <= index)
|
|
8160
|
+
run++;
|
|
8161
|
+
cells.push({ text: normalizeDisplayCluster(segment), width: clusterWidth(segment), prefix: runs[run]?.prefix ?? "" });
|
|
8162
|
+
}
|
|
8163
|
+
return cells;
|
|
8164
|
+
}
|
|
8165
|
+
function encodeCells(cells) {
|
|
8166
|
+
let prefix = "";
|
|
8167
|
+
let result = "";
|
|
8168
|
+
for (const cell of cells) {
|
|
8169
|
+
if (cell.prefix !== prefix) {
|
|
8170
|
+
if (prefix)
|
|
8171
|
+
result += prefix.includes("\x1B]8;") ? TERMINAL_RESET : "\x1B[0m";
|
|
8172
|
+
result += cell.prefix;
|
|
8173
|
+
prefix = cell.prefix;
|
|
8174
|
+
}
|
|
8175
|
+
result += cell.text;
|
|
8176
|
+
}
|
|
8177
|
+
return result + (prefix ? prefix.includes("\x1B]8;") ? TERMINAL_RESET : "\x1B[0m" : "");
|
|
8178
|
+
}
|
|
8179
|
+
function normalizeTerminalOutput(text2) {
|
|
8180
|
+
if (!/[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\x9f\u0e33\u0eb3\uD800-\uDFFF]/u.test(text2))
|
|
8181
|
+
return text2;
|
|
8182
|
+
return encodeCells(terminalCells(text2));
|
|
8183
|
+
}
|
|
8184
|
+
function truncateToWidth(text2, width) {
|
|
8185
|
+
if (width <= 0)
|
|
8186
|
+
return "";
|
|
8187
|
+
if (/^[\x20-\x7e]*$/u.test(text2))
|
|
8188
|
+
return text2.slice(0, width);
|
|
8189
|
+
const cells = [];
|
|
8190
|
+
let used = 0;
|
|
8191
|
+
for (const cell of terminalCells(text2)) {
|
|
8192
|
+
if (used + cell.width > width)
|
|
8193
|
+
break;
|
|
8194
|
+
cells.push(cell);
|
|
8195
|
+
used += cell.width;
|
|
8196
|
+
}
|
|
8197
|
+
return encodeCells(cells);
|
|
8198
|
+
}
|
|
8199
|
+
function sliceByColumn(text2, start, width) {
|
|
8200
|
+
const cells = [];
|
|
8201
|
+
let column = 0;
|
|
8202
|
+
let used = 0;
|
|
8203
|
+
for (const cell of terminalCells(text2)) {
|
|
8204
|
+
const end = column + cell.width;
|
|
8205
|
+
if (end > start && column < start + width) {
|
|
8206
|
+
const overlap = Math.min(end, start + width) - Math.max(column, start);
|
|
8207
|
+
cells.push(overlap === cell.width ? cell : { ...cell, text: " ".repeat(overlap), width: overlap });
|
|
8208
|
+
used += overlap;
|
|
8209
|
+
}
|
|
8210
|
+
column = end;
|
|
8211
|
+
if (column >= start + width)
|
|
8212
|
+
break;
|
|
8213
|
+
}
|
|
8214
|
+
return encodeCells(cells) + " ".repeat(Math.max(0, width - used));
|
|
8215
|
+
}
|
|
8216
|
+
function previousGraphemeBoundary(text2, offset) {
|
|
8217
|
+
let previous = 0;
|
|
8218
|
+
for (const { index } of segmenter.segment(text2)) {
|
|
8219
|
+
if (index >= offset)
|
|
8220
|
+
break;
|
|
8221
|
+
previous = index;
|
|
8222
|
+
}
|
|
8223
|
+
return previous;
|
|
8224
|
+
}
|
|
8225
|
+
function nextGraphemeBoundary(text2, offset) {
|
|
8226
|
+
for (const { index } of segmenter.segment(text2))
|
|
8227
|
+
if (index > offset)
|
|
8228
|
+
return index;
|
|
8229
|
+
return text2.length;
|
|
8230
|
+
}
|
|
8231
|
+
function projectInput(text2, cursor, width, prompt, mask) {
|
|
8232
|
+
const target = Math.max(1, width);
|
|
8233
|
+
const displayedPrompt = truncateToWidth(stripTerminalControls(prompt), Math.max(0, target - 1));
|
|
8234
|
+
const promptWidth = visibleWidth(displayedPrompt);
|
|
8235
|
+
const contentWidth = Math.max(1, target - promptWidth);
|
|
8236
|
+
const rows = [];
|
|
8237
|
+
let row = "";
|
|
8238
|
+
let column = 0;
|
|
8239
|
+
let cursorRow = 0;
|
|
8240
|
+
let cursorColumn = 0;
|
|
8241
|
+
const placeCursor = () => {
|
|
8242
|
+
cursorRow = rows.length + (column === contentWidth ? 1 : 0);
|
|
8243
|
+
cursorColumn = promptWidth + (column === contentWidth ? 0 : column);
|
|
8244
|
+
};
|
|
8245
|
+
for (const { segment, index } of segmenter.segment(text2)) {
|
|
8246
|
+
if (cursor >= index)
|
|
8247
|
+
placeCursor();
|
|
8248
|
+
if (/^[\r\n]+$/u.test(segment)) {
|
|
8249
|
+
rows.push(row);
|
|
8250
|
+
row = "";
|
|
8251
|
+
column = 0;
|
|
8252
|
+
if (cursor >= index + segment.length)
|
|
8253
|
+
placeCursor();
|
|
8254
|
+
continue;
|
|
8255
|
+
}
|
|
8256
|
+
let display = mask ? "*" : normalizeDisplayCluster(segment.replace(/\x1b/g, "\u241B").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/gu, ""));
|
|
8257
|
+
let cells = mask ? 1 : visibleWidth(display);
|
|
8258
|
+
if (cells > contentWidth) {
|
|
8259
|
+
display = "\uFFFD";
|
|
8260
|
+
cells = 1;
|
|
8261
|
+
}
|
|
8262
|
+
if (column > 0 && column + cells > contentWidth) {
|
|
8263
|
+
rows.push(row);
|
|
8264
|
+
row = "";
|
|
8265
|
+
column = 0;
|
|
8266
|
+
if (cursor >= index)
|
|
8267
|
+
placeCursor();
|
|
8268
|
+
}
|
|
8269
|
+
row += display;
|
|
8270
|
+
column += cells;
|
|
8271
|
+
if (cursor >= index + segment.length)
|
|
8272
|
+
placeCursor();
|
|
8273
|
+
}
|
|
8274
|
+
rows.push(row);
|
|
8275
|
+
if (column === contentWidth)
|
|
8276
|
+
rows.push("");
|
|
8277
|
+
return { rows, prompt: displayedPrompt, promptWidth, cursorRow: Math.min(cursorRow, rows.length - 1), cursorColumn: Math.min(target - 1, cursorColumn) };
|
|
8278
|
+
}
|
|
8279
|
+
|
|
8280
|
+
// ../../packages/terminal/tui/dist/tui/render-model.js
|
|
8281
|
+
function span(text2, style) {
|
|
8282
|
+
return style === void 0 ? { text: text2 } : { text: text2, style };
|
|
8283
|
+
}
|
|
8284
|
+
function line(...spans) {
|
|
8285
|
+
return { spans };
|
|
8286
|
+
}
|
|
8287
|
+
function plainLine(text2) {
|
|
8288
|
+
return line(span(text2));
|
|
8289
|
+
}
|
|
8290
|
+
function lineText(value) {
|
|
8291
|
+
return value.spans.map((item) => item.text).join("");
|
|
8292
|
+
}
|
|
8293
|
+
function styledClusters(spans) {
|
|
8294
|
+
const sources = spans.map((source) => ({ ...source, text: stripTerminalControls(source.text) }));
|
|
8295
|
+
const text2 = sources.map((source) => source.text).join("");
|
|
8296
|
+
let sourceIndex = 0;
|
|
8297
|
+
let sourceEnd = sources[0]?.text.length ?? 0;
|
|
8298
|
+
let offset = 0;
|
|
8299
|
+
const result = [];
|
|
8300
|
+
for (const cluster of graphemeClusters(text2)) {
|
|
8301
|
+
while (sourceIndex + 1 < sources.length && sourceEnd <= offset) {
|
|
8302
|
+
sourceEnd += sources[++sourceIndex].text.length;
|
|
8303
|
+
}
|
|
8304
|
+
result.push(span(normalizeDisplayCluster(cluster), sources[sourceIndex]?.style));
|
|
8305
|
+
offset += cluster.length;
|
|
8306
|
+
}
|
|
8307
|
+
return result;
|
|
8308
|
+
}
|
|
8309
|
+
function wrapStyledSpans(spans, width) {
|
|
8310
|
+
const target = Math.max(1, width);
|
|
8311
|
+
const lines2 = [];
|
|
8312
|
+
let row = [];
|
|
8313
|
+
let used = 0;
|
|
8314
|
+
for (const source of styledClusters(spans)) {
|
|
8315
|
+
if (/^[\r\n]+$/u.test(source.text)) {
|
|
8316
|
+
lines2.push(line(...mergeAdjacent(row)));
|
|
8317
|
+
row = [];
|
|
8318
|
+
used = 0;
|
|
8319
|
+
continue;
|
|
8320
|
+
}
|
|
8321
|
+
const measured = visibleWidth(source.text);
|
|
8322
|
+
const cell = measured > target ? span("\uFFFD", source.style) : source;
|
|
8323
|
+
const cellWidth = measured > target ? 1 : measured;
|
|
8324
|
+
if (used > 0 && used + cellWidth > target) {
|
|
8325
|
+
lines2.push(line(...mergeAdjacent(row)));
|
|
8326
|
+
row = [];
|
|
8327
|
+
used = 0;
|
|
8328
|
+
}
|
|
8329
|
+
row.push(cell);
|
|
8330
|
+
used += cellWidth;
|
|
8331
|
+
}
|
|
8332
|
+
lines2.push(line(...mergeAdjacent(row)));
|
|
8333
|
+
return lines2;
|
|
8334
|
+
}
|
|
8335
|
+
function truncateStyledLine(value, width, ellipsis = "\u2026") {
|
|
8336
|
+
if (width <= 0)
|
|
8337
|
+
return plainLine("");
|
|
8338
|
+
const result = [];
|
|
8339
|
+
let used = 0;
|
|
8340
|
+
let truncated = false;
|
|
8341
|
+
for (const source of styledClusters(value.spans)) {
|
|
8342
|
+
const measured = textWidth(source.text);
|
|
8343
|
+
if (used + measured > width) {
|
|
8344
|
+
truncated = true;
|
|
8345
|
+
break;
|
|
8346
|
+
}
|
|
8347
|
+
result.push(source);
|
|
8348
|
+
used += measured;
|
|
8349
|
+
}
|
|
8350
|
+
if (truncated && ellipsis) {
|
|
8351
|
+
const suffix = truncateStyledLine(plainLine(ellipsis), width, "");
|
|
8352
|
+
const suffixWidth = styledLineWidth(suffix);
|
|
8353
|
+
while (result.length && used + suffixWidth > width)
|
|
8354
|
+
used -= textWidth(result.pop().text);
|
|
8355
|
+
result.push(...suffix.spans.map((part) => span(part.text, result.at(-1)?.style)));
|
|
8356
|
+
}
|
|
8357
|
+
return line(...mergeAdjacent(result));
|
|
8358
|
+
}
|
|
8359
|
+
function textWidth(text2) {
|
|
8360
|
+
let width = 0;
|
|
8361
|
+
for (const cluster of graphemeClusters(text2))
|
|
8362
|
+
width += clusterWidth(cluster);
|
|
8363
|
+
return width;
|
|
8364
|
+
}
|
|
8365
|
+
function padStyledLine(value, width, background) {
|
|
8366
|
+
const padding = width - styledLineWidth(value);
|
|
8367
|
+
if (padding <= 0) {
|
|
8368
|
+
return value;
|
|
8369
|
+
}
|
|
8370
|
+
return line(...value.spans, span(" ".repeat(padding), background === void 0 ? void 0 : { background }));
|
|
8371
|
+
}
|
|
8372
|
+
function styledLineWidth(value) {
|
|
8373
|
+
return textWidth(lineText(value));
|
|
8374
|
+
}
|
|
8375
|
+
function mergeAdjacent(spans) {
|
|
8376
|
+
const merged = [];
|
|
8377
|
+
for (const item of spans) {
|
|
8378
|
+
const previous = merged.at(-1);
|
|
8379
|
+
if (previous !== void 0 && previous.style === item.style) {
|
|
8380
|
+
merged[merged.length - 1] = span(previous.text + item.text, item.style);
|
|
8381
|
+
continue;
|
|
8382
|
+
}
|
|
8383
|
+
merged.push(item);
|
|
8384
|
+
}
|
|
8385
|
+
return merged;
|
|
8386
|
+
}
|
|
8387
|
+
|
|
8388
|
+
// ../../packages/terminal/tui/dist/keybindings/key-id.js
|
|
8389
|
+
function makeKeyInput(id, options = {}) {
|
|
8390
|
+
return {
|
|
8391
|
+
id,
|
|
8392
|
+
text: options.text ?? null,
|
|
8393
|
+
ctrl: options.ctrl ?? false,
|
|
8394
|
+
alt: options.alt ?? false,
|
|
8395
|
+
shift: options.shift ?? false
|
|
8396
|
+
};
|
|
8397
|
+
}
|
|
8398
|
+
|
|
8399
|
+
// ../../packages/terminal/tui/dist/tui/terminal-writer.js
|
|
8400
|
+
var BoundedTerminalWriter = class _BoundedTerminalWriter {
|
|
8401
|
+
static MAX_CHARS = 1024 * 1024;
|
|
8402
|
+
#buffer = "";
|
|
8403
|
+
#write;
|
|
8404
|
+
constructor(write) {
|
|
8405
|
+
this.#write = write;
|
|
8406
|
+
}
|
|
8407
|
+
append(text2) {
|
|
8408
|
+
let offset = 0;
|
|
8409
|
+
while (offset < text2.length) {
|
|
8410
|
+
const capacity = _BoundedTerminalWriter.MAX_CHARS - this.#buffer.length;
|
|
8411
|
+
let end = Math.min(text2.length, offset + capacity);
|
|
8412
|
+
if (end < text2.length && /[\uD800-\uDBFF]/u.test(text2[end - 1] ?? "") && /[\uDC00-\uDFFF]/u.test(text2[end] ?? ""))
|
|
8413
|
+
end--;
|
|
8414
|
+
if (end === offset) {
|
|
8415
|
+
this.flush();
|
|
8416
|
+
continue;
|
|
8417
|
+
}
|
|
8418
|
+
this.#buffer += text2.slice(offset, end);
|
|
8419
|
+
offset = end;
|
|
8420
|
+
if (this.#buffer.length === _BoundedTerminalWriter.MAX_CHARS)
|
|
8421
|
+
this.flush();
|
|
8422
|
+
}
|
|
8423
|
+
}
|
|
8424
|
+
flush() {
|
|
8425
|
+
if (!this.#buffer)
|
|
8426
|
+
return;
|
|
8427
|
+
this.#write(this.#buffer);
|
|
8428
|
+
this.#buffer = "";
|
|
8429
|
+
}
|
|
8430
|
+
};
|
|
8431
|
+
|
|
8432
|
+
// ../../packages/terminal/tui/dist/tui/render-diagnostics.js
|
|
8433
|
+
import { mkdtempSync, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8434
|
+
import { tmpdir } from "node:os";
|
|
8435
|
+
import { join as join8 } from "node:path";
|
|
8436
|
+
var RenderWidthError = class extends Error {
|
|
8437
|
+
expected;
|
|
8438
|
+
actual;
|
|
8439
|
+
renderedLine;
|
|
8440
|
+
source;
|
|
8441
|
+
constructor(expected, actual, renderedLine, source = "unknown component") {
|
|
8442
|
+
super(`rendered line exceeds terminal width: ${actual} > ${expected} (${source})`);
|
|
8443
|
+
this.expected = expected;
|
|
8444
|
+
this.actual = actual;
|
|
8445
|
+
this.renderedLine = renderedLine;
|
|
8446
|
+
this.source = source;
|
|
8447
|
+
}
|
|
8448
|
+
};
|
|
8449
|
+
function recordRenderFailure(error) {
|
|
8450
|
+
if (!(error instanceof RenderWidthError))
|
|
8451
|
+
return error;
|
|
8452
|
+
try {
|
|
8453
|
+
const directory = mkdtempSync(join8(tmpdir(), "laohuang-tui-error-"));
|
|
8454
|
+
const path5 = join8(directory, "render.json");
|
|
8455
|
+
writeFileSync4(path5, JSON.stringify({
|
|
8456
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8457
|
+
source: error.source,
|
|
8458
|
+
expected: error.expected,
|
|
8459
|
+
actual: error.actual,
|
|
8460
|
+
renderedLine: error.renderedLine.slice(0, 4096)
|
|
8461
|
+
}, null, 2), { mode: 384 });
|
|
8462
|
+
error.message += `; diagnostic: ${path5}`;
|
|
8463
|
+
} catch {
|
|
8464
|
+
}
|
|
8465
|
+
return error;
|
|
8466
|
+
}
|
|
8467
|
+
|
|
7865
8468
|
// ../../packages/terminal/tui/dist/tui/screen.js
|
|
7866
8469
|
var MainScreenRenderer = class _MainScreenRenderer {
|
|
7867
8470
|
#terminal;
|
|
7868
8471
|
#previousLines = [];
|
|
8472
|
+
#previousSources = [];
|
|
7869
8473
|
#previousWidth = 0;
|
|
7870
8474
|
#previousHeight = 0;
|
|
7871
8475
|
#previousViewportTop = 0;
|
|
@@ -7873,10 +8477,12 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7873
8477
|
#hardwareCursorRow = 0;
|
|
7874
8478
|
#maxLinesRendered = 0;
|
|
7875
8479
|
#clearOnShrink;
|
|
8480
|
+
#termux;
|
|
7876
8481
|
#closed = false;
|
|
7877
8482
|
constructor(terminal, env = process.env) {
|
|
7878
8483
|
this.#terminal = terminal;
|
|
7879
8484
|
this.#clearOnShrink = env.LAOHUANG_CLEAR_ON_SHRINK === "1";
|
|
8485
|
+
this.#termux = Boolean(env.TERMUX_VERSION);
|
|
7880
8486
|
}
|
|
7881
8487
|
render(frame) {
|
|
7882
8488
|
if (this.#closed) {
|
|
@@ -7885,7 +8491,8 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7885
8491
|
const size = this.#terminal.getSize();
|
|
7886
8492
|
const width = Math.max(1, size.columns);
|
|
7887
8493
|
const height = Math.max(1, size.rows);
|
|
7888
|
-
const
|
|
8494
|
+
const sources = frame.lines;
|
|
8495
|
+
const newLines = sources.map((text2, index) => this.#previousSources[index] === text2 ? this.#previousLines[index] : normalizeTerminalOutput(text2));
|
|
7889
8496
|
const widthChanged = this.#previousWidth !== 0 && this.#previousWidth !== width;
|
|
7890
8497
|
const heightChanged = this.#previousHeight !== 0 && this.#previousHeight !== height;
|
|
7891
8498
|
_MainScreenRenderer.#validateLines(newLines, width, widthChanged || heightChanged ? [] : this.#previousLines);
|
|
@@ -7899,17 +8506,18 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7899
8506
|
return targetScreenRow - currentScreenRow;
|
|
7900
8507
|
};
|
|
7901
8508
|
const fullRender = (clear) => {
|
|
7902
|
-
|
|
8509
|
+
const buffer2 = new BoundedTerminalWriter((text2) => this.#terminal.write(text2));
|
|
8510
|
+
buffer2.append("\x1B[?2026h");
|
|
7903
8511
|
if (clear) {
|
|
7904
|
-
buffer2
|
|
8512
|
+
buffer2.append("\x1B[2J\x1B[H\x1B[3J");
|
|
7905
8513
|
}
|
|
7906
8514
|
newLines.forEach((line2, index) => {
|
|
7907
8515
|
if (index > 0) {
|
|
7908
|
-
buffer2
|
|
8516
|
+
buffer2.append("\r\n");
|
|
7909
8517
|
}
|
|
7910
|
-
buffer2
|
|
8518
|
+
buffer2.append(line2);
|
|
7911
8519
|
});
|
|
7912
|
-
buffer2
|
|
8520
|
+
buffer2.append("\x1B[?2026l");
|
|
7913
8521
|
this.#cursorRow = Math.max(0, newLines.length - 1);
|
|
7914
8522
|
this.#hardwareCursorRow = this.#cursorRow;
|
|
7915
8523
|
if (clear) {
|
|
@@ -7919,16 +8527,17 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7919
8527
|
}
|
|
7920
8528
|
const bufferLength = Math.max(height, newLines.length);
|
|
7921
8529
|
this.#previousViewportTop = Math.max(0, bufferLength - height);
|
|
7922
|
-
buffer2
|
|
8530
|
+
buffer2.append(this.#positionHardwareCursor(frame, width, newLines.length));
|
|
7923
8531
|
this.#commitState(newLines, width, height);
|
|
7924
|
-
this.#
|
|
8532
|
+
this.#previousSources = [...sources];
|
|
8533
|
+
buffer2.flush();
|
|
7925
8534
|
this.#terminal.flush();
|
|
7926
8535
|
};
|
|
7927
8536
|
if (this.#previousLines.length === 0 && !widthChanged && !heightChanged) {
|
|
7928
8537
|
fullRender(false);
|
|
7929
8538
|
return;
|
|
7930
8539
|
}
|
|
7931
|
-
if (widthChanged || heightChanged) {
|
|
8540
|
+
if (widthChanged || heightChanged && !this.#termux) {
|
|
7932
8541
|
fullRender(true);
|
|
7933
8542
|
return;
|
|
7934
8543
|
}
|
|
@@ -7938,11 +8547,12 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7938
8547
|
}
|
|
7939
8548
|
const span2 = _MainScreenRenderer.#changedSpan(this.#previousLines, newLines);
|
|
7940
8549
|
if (span2 === null) {
|
|
7941
|
-
const buffer2 = this.#positionHardwareCursor(frame, width, newLines.length);
|
|
7942
8550
|
this.#previousViewportTop = prevViewportTop;
|
|
8551
|
+
const cursorBuffer = this.#positionHardwareCursor(frame, width, newLines.length);
|
|
8552
|
+
this.#previousSources = [...sources];
|
|
7943
8553
|
this.#previousHeight = height;
|
|
7944
|
-
if (
|
|
7945
|
-
this.#terminal.write(
|
|
8554
|
+
if (cursorBuffer) {
|
|
8555
|
+
this.#terminal.write(cursorBuffer);
|
|
7946
8556
|
}
|
|
7947
8557
|
this.#terminal.flush();
|
|
7948
8558
|
return;
|
|
@@ -7955,7 +8565,8 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7955
8565
|
}
|
|
7956
8566
|
const appendStart = appendedLines && firstChanged === this.#previousLines.length && firstChanged > 0;
|
|
7957
8567
|
if (firstChanged >= newLines.length) {
|
|
7958
|
-
|
|
8568
|
+
const buffer2 = new BoundedTerminalWriter((text2) => this.#terminal.write(text2));
|
|
8569
|
+
buffer2.append("\x1B[?2026h");
|
|
7959
8570
|
const targetRow = Math.max(0, newLines.length - 1);
|
|
7960
8571
|
if (targetRow < prevViewportTop) {
|
|
7961
8572
|
fullRender(true);
|
|
@@ -7963,11 +8574,11 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7963
8574
|
}
|
|
7964
8575
|
const lineDiff2 = computeLineDiff(targetRow);
|
|
7965
8576
|
if (lineDiff2 > 0) {
|
|
7966
|
-
buffer2
|
|
8577
|
+
buffer2.append(`\x1B[${lineDiff2}B`);
|
|
7967
8578
|
} else if (lineDiff2 < 0) {
|
|
7968
|
-
buffer2
|
|
8579
|
+
buffer2.append(`\x1B[${-lineDiff2}A`);
|
|
7969
8580
|
}
|
|
7970
|
-
buffer2
|
|
8581
|
+
buffer2.append("\r");
|
|
7971
8582
|
const extraLines = this.#previousLines.length - newLines.length;
|
|
7972
8583
|
if (extraLines > height) {
|
|
7973
8584
|
fullRender(true);
|
|
@@ -7975,25 +8586,26 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
7975
8586
|
}
|
|
7976
8587
|
const clearStartOffset = newLines.length === 0 ? 0 : 1;
|
|
7977
8588
|
if (extraLines > 0 && clearStartOffset > 0) {
|
|
7978
|
-
buffer2
|
|
8589
|
+
buffer2.append(`\x1B[${clearStartOffset}B`);
|
|
7979
8590
|
}
|
|
7980
8591
|
for (let index = 0; index < extraLines; index += 1) {
|
|
7981
|
-
buffer2
|
|
8592
|
+
buffer2.append("\r\x1B[2K");
|
|
7982
8593
|
if (index < extraLines - 1) {
|
|
7983
|
-
buffer2
|
|
8594
|
+
buffer2.append("\x1B[1B");
|
|
7984
8595
|
}
|
|
7985
8596
|
}
|
|
7986
8597
|
const moveBack = Math.max(0, extraLines - 1 + clearStartOffset);
|
|
7987
8598
|
if (moveBack > 0) {
|
|
7988
|
-
buffer2
|
|
8599
|
+
buffer2.append(`\x1B[${moveBack}A`);
|
|
7989
8600
|
}
|
|
7990
|
-
buffer2
|
|
8601
|
+
buffer2.append("\x1B[?2026l");
|
|
7991
8602
|
this.#cursorRow = targetRow;
|
|
7992
8603
|
this.#hardwareCursorRow = targetRow;
|
|
7993
|
-
buffer2
|
|
8604
|
+
buffer2.append(this.#positionHardwareCursor(frame, width, newLines.length));
|
|
7994
8605
|
this.#previousViewportTop = prevViewportTop;
|
|
7995
8606
|
this.#commitState(newLines, width, height);
|
|
7996
|
-
this.#
|
|
8607
|
+
this.#previousSources = [...sources];
|
|
8608
|
+
buffer2.flush();
|
|
7997
8609
|
this.#terminal.flush();
|
|
7998
8610
|
return;
|
|
7999
8611
|
}
|
|
@@ -8001,56 +8613,58 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
8001
8613
|
fullRender(true);
|
|
8002
8614
|
return;
|
|
8003
8615
|
}
|
|
8004
|
-
|
|
8616
|
+
const buffer = new BoundedTerminalWriter((text2) => this.#terminal.write(text2));
|
|
8617
|
+
buffer.append("\x1B[?2026h");
|
|
8005
8618
|
const prevViewportBottom = prevViewportTop + height - 1;
|
|
8006
8619
|
const moveTargetRow = appendStart ? firstChanged - 1 : firstChanged;
|
|
8007
8620
|
if (moveTargetRow > prevViewportBottom) {
|
|
8008
8621
|
const currentScreenRow = Math.max(0, Math.min(height - 1, hardwareCursorRow - prevViewportTop));
|
|
8009
8622
|
const moveToBottom = height - 1 - currentScreenRow;
|
|
8010
8623
|
if (moveToBottom > 0) {
|
|
8011
|
-
buffer
|
|
8624
|
+
buffer.append(`\x1B[${moveToBottom}B`);
|
|
8012
8625
|
}
|
|
8013
8626
|
const scroll = moveTargetRow - prevViewportBottom;
|
|
8014
|
-
buffer
|
|
8627
|
+
buffer.append("\r\n".repeat(scroll));
|
|
8015
8628
|
viewportTop += scroll;
|
|
8016
8629
|
hardwareCursorRow = moveTargetRow;
|
|
8017
8630
|
}
|
|
8018
8631
|
const lineDiff = computeLineDiff(moveTargetRow);
|
|
8019
8632
|
if (lineDiff > 0) {
|
|
8020
|
-
buffer
|
|
8633
|
+
buffer.append(`\x1B[${lineDiff}B`);
|
|
8021
8634
|
} else if (lineDiff < 0) {
|
|
8022
|
-
buffer
|
|
8635
|
+
buffer.append(`\x1B[${-lineDiff}A`);
|
|
8023
8636
|
}
|
|
8024
|
-
buffer
|
|
8637
|
+
buffer.append(appendStart ? "\r\n" : "\r");
|
|
8025
8638
|
const renderEnd = Math.min(lastChanged, newLines.length - 1);
|
|
8026
8639
|
for (let index = firstChanged; index <= renderEnd; index += 1) {
|
|
8027
8640
|
if (index > firstChanged) {
|
|
8028
|
-
buffer
|
|
8641
|
+
buffer.append("\r\n");
|
|
8029
8642
|
}
|
|
8030
|
-
buffer
|
|
8031
|
-
buffer
|
|
8643
|
+
buffer.append("\x1B[2K");
|
|
8644
|
+
buffer.append(newLines[index]);
|
|
8032
8645
|
}
|
|
8033
8646
|
let finalCursorRow = renderEnd;
|
|
8034
8647
|
if (this.#previousLines.length > newLines.length) {
|
|
8035
8648
|
if (renderEnd < newLines.length - 1) {
|
|
8036
8649
|
const moveDown = newLines.length - 1 - renderEnd;
|
|
8037
|
-
buffer
|
|
8650
|
+
buffer.append(`\x1B[${moveDown}B`);
|
|
8038
8651
|
finalCursorRow = newLines.length - 1;
|
|
8039
8652
|
}
|
|
8040
8653
|
const extraLines = this.#previousLines.length - newLines.length;
|
|
8041
8654
|
for (let index = newLines.length; index < this.#previousLines.length; index += 1) {
|
|
8042
|
-
buffer
|
|
8655
|
+
buffer.append("\r\n\x1B[2K");
|
|
8043
8656
|
}
|
|
8044
|
-
buffer
|
|
8657
|
+
buffer.append(`\x1B[${extraLines}A`);
|
|
8045
8658
|
}
|
|
8046
|
-
buffer
|
|
8659
|
+
buffer.append("\x1B[?2026l");
|
|
8047
8660
|
this.#cursorRow = Math.max(0, newLines.length - 1);
|
|
8048
8661
|
this.#hardwareCursorRow = finalCursorRow;
|
|
8049
8662
|
this.#maxLinesRendered = Math.max(this.#maxLinesRendered, newLines.length);
|
|
8050
8663
|
this.#previousViewportTop = Math.max(prevViewportTop, finalCursorRow - height + 1);
|
|
8051
|
-
buffer
|
|
8664
|
+
buffer.append(this.#positionHardwareCursor(frame, width, newLines.length));
|
|
8052
8665
|
this.#commitState(newLines, width, height);
|
|
8053
|
-
this.#
|
|
8666
|
+
this.#previousSources = [...sources];
|
|
8667
|
+
buffer.flush();
|
|
8054
8668
|
this.#terminal.flush();
|
|
8055
8669
|
}
|
|
8056
8670
|
close() {
|
|
@@ -8059,7 +8673,7 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
8059
8673
|
}
|
|
8060
8674
|
this.#closed = true;
|
|
8061
8675
|
try {
|
|
8062
|
-
this.#terminal.write("\x1B[0 q\x1B[?25h");
|
|
8676
|
+
this.#terminal.write("\x1B[?2026l\x1B[0m\x1B]8;;\x07\x1B[0 q\x1B[?25h");
|
|
8063
8677
|
this.#terminal.flush();
|
|
8064
8678
|
} finally {
|
|
8065
8679
|
this.#terminal.restore();
|
|
@@ -8110,340 +8724,17 @@ var MainScreenRenderer = class _MainScreenRenderer {
|
|
|
8110
8724
|
static #validateLines(lines2, width, previous) {
|
|
8111
8725
|
lines2.forEach((line2, index) => {
|
|
8112
8726
|
if (previous[index] === line2)
|
|
8113
|
-
return;
|
|
8114
|
-
if (/[\r\n]/u.test(line2)) {
|
|
8115
|
-
throw new Error(`rendered line ${index} contains a physical newline`);
|
|
8116
|
-
}
|
|
8117
|
-
const lineWidth = visibleWidth(line2);
|
|
8118
|
-
if (lineWidth > width) {
|
|
8119
|
-
throw new
|
|
8120
|
-
}
|
|
8121
|
-
});
|
|
8122
|
-
}
|
|
8123
|
-
};
|
|
8124
|
-
var WIDTH_CACHE_SIZE = 512;
|
|
8125
|
-
var WIDTH_CACHE_MAX_TEXT_LENGTH = 4096;
|
|
8126
|
-
var widthCache = /* @__PURE__ */ new Map();
|
|
8127
|
-
function visibleWidth(text2) {
|
|
8128
|
-
if (/^[\x20-\x7e]*$/u.test(text2))
|
|
8129
|
-
return text2.length;
|
|
8130
|
-
const cached = widthCache.get(text2);
|
|
8131
|
-
if (cached !== void 0)
|
|
8132
|
-
return cached;
|
|
8133
|
-
const stripped = stripTerminalControls(text2).replace(/\t/g, " ");
|
|
8134
|
-
let width = 0;
|
|
8135
|
-
for (const cluster of graphemeClusters(stripped)) {
|
|
8136
|
-
width += clusterWidth(cluster);
|
|
8137
|
-
}
|
|
8138
|
-
if (text2.length <= WIDTH_CACHE_MAX_TEXT_LENGTH) {
|
|
8139
|
-
if (widthCache.size >= WIDTH_CACHE_SIZE) {
|
|
8140
|
-
const oldest = widthCache.keys().next().value;
|
|
8141
|
-
if (oldest !== void 0)
|
|
8142
|
-
widthCache.delete(oldest);
|
|
8143
|
-
}
|
|
8144
|
-
widthCache.set(text2, width);
|
|
8145
|
-
}
|
|
8146
|
-
return width;
|
|
8147
|
-
}
|
|
8148
|
-
function truncateToWidth(text2, width) {
|
|
8149
|
-
if (width <= 0 || !text2) {
|
|
8150
|
-
return "";
|
|
8151
|
-
}
|
|
8152
|
-
const result = [];
|
|
8153
|
-
const sgrPrefix = [];
|
|
8154
|
-
let used = 0;
|
|
8155
|
-
let index = 0;
|
|
8156
|
-
while (index < text2.length) {
|
|
8157
|
-
if (text2[index] === "\x1B") {
|
|
8158
|
-
const end2 = consumeEscapeSequence(text2, index);
|
|
8159
|
-
const sequence = text2.slice(index, end2);
|
|
8160
|
-
if (isSgrSequence(sequence)) {
|
|
8161
|
-
result.push(sequence);
|
|
8162
|
-
updateSgrPrefix(sgrPrefix, sequence);
|
|
8163
|
-
}
|
|
8164
|
-
index = end2;
|
|
8165
|
-
continue;
|
|
8166
|
-
}
|
|
8167
|
-
const nextEscape = text2.indexOf("\x1B", index);
|
|
8168
|
-
const end = nextEscape === -1 ? text2.length : nextEscape;
|
|
8169
|
-
for (const cluster of graphemeClusters(text2.slice(index, end))) {
|
|
8170
|
-
const [renderedCluster, widthOfCluster] = displayCluster(cluster);
|
|
8171
|
-
if (used + widthOfCluster > width) {
|
|
8172
|
-
if (sgrPrefix.length > 0) {
|
|
8173
|
-
result.push("\x1B[0m");
|
|
8174
|
-
}
|
|
8175
|
-
return result.join("");
|
|
8176
|
-
}
|
|
8177
|
-
result.push(renderedCluster);
|
|
8178
|
-
used += widthOfCluster;
|
|
8179
|
-
}
|
|
8180
|
-
index = end;
|
|
8181
|
-
}
|
|
8182
|
-
if (sgrPrefix.length > 0) {
|
|
8183
|
-
result.push("\x1B[0m");
|
|
8184
|
-
}
|
|
8185
|
-
return result.join("");
|
|
8186
|
-
}
|
|
8187
|
-
function stripTerminalControls(text2) {
|
|
8188
|
-
let result = "";
|
|
8189
|
-
let index = 0;
|
|
8190
|
-
while (index < text2.length) {
|
|
8191
|
-
if (text2[index] !== "\x1B") {
|
|
8192
|
-
result += text2[index];
|
|
8193
|
-
index += 1;
|
|
8194
|
-
continue;
|
|
8195
|
-
}
|
|
8196
|
-
index = consumeEscapeSequence(text2, index);
|
|
8197
|
-
}
|
|
8198
|
-
return result;
|
|
8199
|
-
}
|
|
8200
|
-
function consumeEscapeSequence(text2, start) {
|
|
8201
|
-
if (start + 1 >= text2.length) {
|
|
8202
|
-
return start + 1;
|
|
8203
|
-
}
|
|
8204
|
-
const marker = text2[start + 1];
|
|
8205
|
-
if (marker === "[") {
|
|
8206
|
-
let index = start + 2;
|
|
8207
|
-
while (index < text2.length) {
|
|
8208
|
-
const code = text2.charCodeAt(index);
|
|
8209
|
-
if (code >= 64 && code <= 126) {
|
|
8210
|
-
return index + 1;
|
|
8211
|
-
}
|
|
8212
|
-
index += 1;
|
|
8213
|
-
}
|
|
8214
|
-
return text2.length;
|
|
8215
|
-
}
|
|
8216
|
-
if (marker === "]") {
|
|
8217
|
-
return consumeStringSequence(text2, start + 2, true);
|
|
8218
|
-
}
|
|
8219
|
-
if (marker === "P") {
|
|
8220
|
-
return consumeStringSequence(text2, start + 2, false);
|
|
8221
|
-
}
|
|
8222
|
-
if (marker === "_") {
|
|
8223
|
-
return consumeStringSequence(text2, start + 2, true);
|
|
8224
|
-
}
|
|
8225
|
-
return start + 2;
|
|
8226
|
-
}
|
|
8227
|
-
function consumeStringSequence(text2, start, allowBel) {
|
|
8228
|
-
let index = start;
|
|
8229
|
-
while (index < text2.length) {
|
|
8230
|
-
if (allowBel && text2[index] === "\x07") {
|
|
8231
|
-
return index + 1;
|
|
8232
|
-
}
|
|
8233
|
-
if (text2.slice(index, index + 2) === "\x1B\\") {
|
|
8234
|
-
return index + 2;
|
|
8235
|
-
}
|
|
8236
|
-
index += 1;
|
|
8237
|
-
}
|
|
8238
|
-
return text2.length;
|
|
8239
|
-
}
|
|
8240
|
-
function isSgrSequence(sequence) {
|
|
8241
|
-
return sequence.startsWith("\x1B[") && sequence.endsWith("m");
|
|
8242
|
-
}
|
|
8243
|
-
function updateSgrPrefix(prefix, sequence) {
|
|
8244
|
-
const params = sequence.slice(2, -1).replace(/:/g, ";").split(";").filter((part) => part.length > 0);
|
|
8245
|
-
if (params.length === 0 || params.every((param) => param === "0")) {
|
|
8246
|
-
prefix.length = 0;
|
|
8247
|
-
return;
|
|
8248
|
-
}
|
|
8249
|
-
if (params.includes("0")) {
|
|
8250
|
-
prefix.splice(0, prefix.length, sequence);
|
|
8251
|
-
return;
|
|
8252
|
-
}
|
|
8253
|
-
prefix.push(sequence);
|
|
8254
|
-
}
|
|
8255
|
-
function displayCluster(cluster) {
|
|
8256
|
-
if (cluster === " ") {
|
|
8257
|
-
return [" ", 3];
|
|
8258
|
-
}
|
|
8259
|
-
return [cluster, clusterWidth(cluster)];
|
|
8260
|
-
}
|
|
8261
|
-
var graphemeSegmenter = new Intl.Segmenter("en", {
|
|
8262
|
-
granularity: "grapheme"
|
|
8263
|
-
});
|
|
8264
|
-
function graphemeClusters(text2) {
|
|
8265
|
-
const clusters = [];
|
|
8266
|
-
for (const { segment } of graphemeSegmenter.segment(text2)) {
|
|
8267
|
-
clusters.push(segment);
|
|
8268
|
-
}
|
|
8269
|
-
return clusters;
|
|
8270
|
-
}
|
|
8271
|
-
function isRegionalIndicator(codePoint) {
|
|
8272
|
-
return codePoint >= 127462 && codePoint <= 127487;
|
|
8273
|
-
}
|
|
8274
|
-
function clusterWidth(cluster) {
|
|
8275
|
-
if (!cluster) {
|
|
8276
|
-
return 0;
|
|
8277
|
-
}
|
|
8278
|
-
if (cluster.includes("\u200D") || cluster.includes("\uFE0F") || [...cluster].some((char) => isRegionalIndicator(char.codePointAt(0)))) {
|
|
8279
|
-
return 2;
|
|
8280
|
-
}
|
|
8281
|
-
let width = 0;
|
|
8282
|
-
for (const char of cluster) {
|
|
8283
|
-
width += charCellWidth(char);
|
|
8284
|
-
}
|
|
8285
|
-
return Math.max(0, width);
|
|
8286
|
-
}
|
|
8287
|
-
function charCellWidth(char) {
|
|
8288
|
-
const cp = char.codePointAt(0);
|
|
8289
|
-
if (cp === 8203 || cp >= 8204 && cp <= 8207) {
|
|
8290
|
-
return 0;
|
|
8291
|
-
}
|
|
8292
|
-
if (cp < 32 || cp >= 127 && cp < 160) {
|
|
8293
|
-
return 0;
|
|
8294
|
-
}
|
|
8295
|
-
if (isZeroWidth(cp)) {
|
|
8296
|
-
return 0;
|
|
8297
|
-
}
|
|
8298
|
-
if (isWide(cp)) {
|
|
8299
|
-
return 2;
|
|
8300
|
-
}
|
|
8301
|
-
return 1;
|
|
8302
|
-
}
|
|
8303
|
-
function isZeroWidth(cp) {
|
|
8304
|
-
return cp >= 768 && cp <= 879 || cp >= 1155 && cp <= 1161 || cp >= 1425 && cp <= 1469 || cp === 1471 || cp >= 1473 && cp <= 1474 || cp >= 1476 && cp <= 1477 || cp === 1479 || cp >= 1552 && cp <= 1562 || cp >= 1611 && cp <= 1631 || cp === 1648 || cp >= 1750 && cp <= 1756 || cp >= 3633 && cp <= 3642 || cp >= 3655 && cp <= 3662 || cp >= 6832 && cp <= 6911 || cp >= 7616 && cp <= 7679 || cp === 8205 || cp >= 8400 && cp <= 8447 || cp >= 65024 && cp <= 65039 || cp >= 65056 && cp <= 65071 || cp >= 917760 && cp <= 917999;
|
|
8305
|
-
}
|
|
8306
|
-
function isWide(cp) {
|
|
8307
|
-
return cp >= 4352 && cp <= 4447 || cp >= 8986 && cp <= 8987 || cp >= 9001 && cp <= 9002 || cp >= 9193 && cp <= 9196 || cp === 9200 || cp === 9203 || cp >= 9725 && cp <= 9726 || cp >= 9748 && cp <= 9749 || cp >= 9800 && cp <= 9811 || cp === 9855 || cp === 9875 || cp === 9889 || cp >= 9898 && cp <= 9899 || cp >= 9917 && cp <= 9918 || cp >= 9924 && cp <= 9925 || cp === 9934 || cp === 9940 || cp === 9962 || cp >= 9970 && cp <= 9971 || cp === 9973 || cp >= 9978 && cp <= 9981 || cp === 9989 || cp >= 9994 && cp <= 9995 || cp === 10024 || cp === 10060 || cp === 10062 || cp >= 10067 && cp <= 10069 || cp === 10071 || cp >= 10133 && cp <= 10135 || cp === 10160 || cp === 10175 || cp >= 11035 && cp <= 11036 || cp === 11088 || cp === 11093 || cp >= 11904 && cp <= 12287 || cp >= 12288 && cp <= 12350 || cp >= 12353 && cp <= 13311 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 40960 && cp <= 42191 || cp >= 44032 && cp <= 55203 || cp >= 63744 && cp <= 64255 || cp >= 65040 && cp <= 65049 || cp >= 65072 && cp <= 65135 || cp >= 65280 && cp <= 65376 || cp >= 65504 && cp <= 65510 || cp >= 94176 && cp <= 94180 || cp >= 127744 && cp <= 128591 || cp >= 129280 && cp <= 129535 || cp >= 129648 && cp <= 129791 || cp >= 131072 && cp <= 196605 || cp >= 196608 && cp <= 262141;
|
|
8308
|
-
}
|
|
8309
|
-
|
|
8310
|
-
// ../../packages/terminal/tui/dist/tui/render-model.js
|
|
8311
|
-
function span(text2, style) {
|
|
8312
|
-
return style === void 0 ? { text: text2 } : { text: text2, style };
|
|
8313
|
-
}
|
|
8314
|
-
function line(...spans) {
|
|
8315
|
-
return { spans };
|
|
8316
|
-
}
|
|
8317
|
-
function plainLine(text2) {
|
|
8318
|
-
return line(span(text2));
|
|
8319
|
-
}
|
|
8320
|
-
function lineText(value) {
|
|
8321
|
-
return value.spans.map((item) => item.text).join("");
|
|
8322
|
-
}
|
|
8323
|
-
function wrapStyledSpans(spans, width) {
|
|
8324
|
-
const targetWidth = Math.max(1, width);
|
|
8325
|
-
const lines2 = [];
|
|
8326
|
-
let current = [];
|
|
8327
|
-
let currentWidth = 0;
|
|
8328
|
-
let skipLineFeed = false;
|
|
8329
|
-
const append = (text2, style) => {
|
|
8330
|
-
const previous = current.at(-1);
|
|
8331
|
-
if (previous !== void 0 && previous.style === style) {
|
|
8332
|
-
current[current.length - 1] = span(previous.text + text2, style);
|
|
8333
|
-
return;
|
|
8334
|
-
}
|
|
8335
|
-
current.push(span(text2, style));
|
|
8336
|
-
};
|
|
8337
|
-
const finish = () => {
|
|
8338
|
-
lines2.push(line(...current));
|
|
8339
|
-
current = [];
|
|
8340
|
-
currentWidth = 0;
|
|
8341
|
-
};
|
|
8342
|
-
for (const source of spans) {
|
|
8343
|
-
for (const character of source.text) {
|
|
8344
|
-
if (character === "\r") {
|
|
8345
|
-
finish();
|
|
8346
|
-
skipLineFeed = true;
|
|
8347
|
-
continue;
|
|
8348
|
-
}
|
|
8349
|
-
if (character === "\n") {
|
|
8350
|
-
if (skipLineFeed) {
|
|
8351
|
-
skipLineFeed = false;
|
|
8352
|
-
continue;
|
|
8353
|
-
}
|
|
8354
|
-
finish();
|
|
8355
|
-
continue;
|
|
8356
|
-
}
|
|
8357
|
-
skipLineFeed = false;
|
|
8358
|
-
const characterWidth = charCellWidth(character);
|
|
8359
|
-
if (characterWidth > targetWidth) {
|
|
8360
|
-
throw new Error(`code point exceeds wrap width: ${characterWidth} > ${targetWidth}`);
|
|
8361
|
-
}
|
|
8362
|
-
if (currentWidth > 0 && currentWidth + characterWidth > targetWidth) {
|
|
8363
|
-
finish();
|
|
8364
|
-
}
|
|
8365
|
-
append(character, source.style);
|
|
8366
|
-
currentWidth += characterWidth;
|
|
8367
|
-
}
|
|
8368
|
-
}
|
|
8369
|
-
finish();
|
|
8370
|
-
return lines2;
|
|
8371
|
-
}
|
|
8372
|
-
function truncateStyledLine(value, width, ellipsis = "\u2026") {
|
|
8373
|
-
if (width <= 0) {
|
|
8374
|
-
return plainLine("");
|
|
8375
|
-
}
|
|
8376
|
-
const result = [];
|
|
8377
|
-
let used = 0;
|
|
8378
|
-
let truncated = false;
|
|
8379
|
-
let trailingStyle;
|
|
8380
|
-
for (const source of value.spans) {
|
|
8381
|
-
for (const character of source.text) {
|
|
8382
|
-
const characterWidth = charCellWidth(character);
|
|
8383
|
-
if (used + characterWidth > width) {
|
|
8384
|
-
truncated = true;
|
|
8385
|
-
trailingStyle = source.style;
|
|
8386
|
-
break;
|
|
8387
|
-
}
|
|
8388
|
-
result.push(span(character, source.style));
|
|
8389
|
-
used += characterWidth;
|
|
8390
|
-
trailingStyle = source.style;
|
|
8391
|
-
}
|
|
8392
|
-
if (truncated) {
|
|
8393
|
-
break;
|
|
8394
|
-
}
|
|
8395
|
-
}
|
|
8396
|
-
if (!truncated) {
|
|
8397
|
-
return line(...mergeAdjacent(result));
|
|
8398
|
-
}
|
|
8399
|
-
const ellipsisWidth = ellipsis === "" ? 0 : charCellWidth(ellipsis);
|
|
8400
|
-
while (result.length > 0 && used + ellipsisWidth > width) {
|
|
8401
|
-
const removed = result.pop();
|
|
8402
|
-
used -= charCellWidth(removed.text);
|
|
8403
|
-
trailingStyle = removed.style;
|
|
8404
|
-
}
|
|
8405
|
-
if (ellipsisWidth <= width) {
|
|
8406
|
-
result.push(span(ellipsis, trailingStyle));
|
|
8407
|
-
}
|
|
8408
|
-
return line(...mergeAdjacent(result));
|
|
8409
|
-
}
|
|
8410
|
-
function padStyledLine(value, width, background) {
|
|
8411
|
-
const padding = width - styledLineWidth(value);
|
|
8412
|
-
if (padding <= 0) {
|
|
8413
|
-
return value;
|
|
8414
|
-
}
|
|
8415
|
-
return line(...value.spans, span(" ".repeat(padding), background === void 0 ? void 0 : { background }));
|
|
8416
|
-
}
|
|
8417
|
-
function styledLineWidth(value) {
|
|
8418
|
-
let width = 0;
|
|
8419
|
-
for (const character of lineText(value)) {
|
|
8420
|
-
width += charCellWidth(character);
|
|
8421
|
-
}
|
|
8422
|
-
return width;
|
|
8423
|
-
}
|
|
8424
|
-
function mergeAdjacent(spans) {
|
|
8425
|
-
const merged = [];
|
|
8426
|
-
for (const item of spans) {
|
|
8427
|
-
const previous = merged.at(-1);
|
|
8428
|
-
if (previous !== void 0 && previous.style === item.style) {
|
|
8429
|
-
merged[merged.length - 1] = span(previous.text + item.text, item.style);
|
|
8430
|
-
continue;
|
|
8431
|
-
}
|
|
8432
|
-
merged.push(item);
|
|
8433
|
-
}
|
|
8434
|
-
return merged;
|
|
8435
|
-
}
|
|
8436
|
-
|
|
8437
|
-
// ../../packages/terminal/tui/dist/keybindings/key-id.js
|
|
8438
|
-
function makeKeyInput(id, options = {}) {
|
|
8439
|
-
return {
|
|
8440
|
-
id,
|
|
8441
|
-
text: options.text ?? null,
|
|
8442
|
-
ctrl: options.ctrl ?? false,
|
|
8443
|
-
alt: options.alt ?? false,
|
|
8444
|
-
shift: options.shift ?? false
|
|
8445
|
-
};
|
|
8446
|
-
}
|
|
8727
|
+
return;
|
|
8728
|
+
if (/[\r\n]/u.test(line2)) {
|
|
8729
|
+
throw new Error(`rendered line ${index} contains a physical newline`);
|
|
8730
|
+
}
|
|
8731
|
+
const lineWidth = visibleWidth(line2);
|
|
8732
|
+
if (lineWidth > width) {
|
|
8733
|
+
throw new RenderWidthError(width, lineWidth, line2, `screen row ${index}`);
|
|
8734
|
+
}
|
|
8735
|
+
});
|
|
8736
|
+
}
|
|
8737
|
+
};
|
|
8447
8738
|
|
|
8448
8739
|
// ../../packages/terminal/tui/dist/tui/editor.js
|
|
8449
8740
|
var InputActionKind = {
|
|
@@ -8551,20 +8842,24 @@ var StdinBuffer = class {
|
|
|
8551
8842
|
if (data.length === 0) {
|
|
8552
8843
|
return [];
|
|
8553
8844
|
}
|
|
8554
|
-
|
|
8555
|
-
if (chunk.length === 1 && chunk[0] > 127) {
|
|
8556
|
-
chunk = Buffer.concat([ESCAPE, Buffer.from([chunk[0] - 128])]);
|
|
8557
|
-
}
|
|
8845
|
+
const chunk = Buffer.from(data);
|
|
8558
8846
|
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
8559
8847
|
const events = [];
|
|
8560
8848
|
this.processBuffer(events);
|
|
8561
8849
|
return events;
|
|
8562
8850
|
}
|
|
8851
|
+
pendingKind() {
|
|
8852
|
+
if (this.pasteMode)
|
|
8853
|
+
return "paste";
|
|
8854
|
+
if (this.buffer.length === 0)
|
|
8855
|
+
return "none";
|
|
8856
|
+
return this.buffer.length === 1 && this.buffer[0] === ESC ? "escape" : "sequence";
|
|
8857
|
+
}
|
|
8563
8858
|
flush() {
|
|
8564
8859
|
if (this.pasteMode || this.buffer.length === 0) {
|
|
8565
8860
|
return [];
|
|
8566
8861
|
}
|
|
8567
|
-
const sequence = this.buffer;
|
|
8862
|
+
const sequence = this.buffer.length === 1 && this.buffer[0] > 127 ? Buffer.from([ESC, this.buffer[0] - 128]) : this.buffer;
|
|
8568
8863
|
this.buffer = Buffer.alloc(0);
|
|
8569
8864
|
this.pendingKittyPrintableCodepoint = null;
|
|
8570
8865
|
return [{ kind: BufferedInputKind.Sequence, data: sequence }];
|
|
@@ -8653,6 +8948,9 @@ var TerminalInputFilter = class {
|
|
|
8653
8948
|
this.disableModifyOtherKeys = options.disableModifyOtherKeys ?? (() => {
|
|
8654
8949
|
});
|
|
8655
8950
|
}
|
|
8951
|
+
get negotiationPending() {
|
|
8952
|
+
return this.pendingNegotiationPrefix.length > 0;
|
|
8953
|
+
}
|
|
8656
8954
|
feed(sequence) {
|
|
8657
8955
|
const text2 = Buffer.from(sequence).toString("latin1");
|
|
8658
8956
|
return this.feedText(text2).map((item) => Buffer.from(item, "latin1"));
|
|
@@ -8831,7 +9129,7 @@ var RawInputDecoder = class {
|
|
|
8831
9129
|
this.buffer = Buffer.alloc(0);
|
|
8832
9130
|
return [inputAction(InputActionKind.Dismiss)];
|
|
8833
9131
|
}
|
|
8834
|
-
if (this.buffer.length > 1 && this.buffer[0] === ESC
|
|
9132
|
+
if (this.buffer.length > 1 && this.buffer[0] === ESC) {
|
|
8835
9133
|
this.buffer = Buffer.alloc(0);
|
|
8836
9134
|
}
|
|
8837
9135
|
return this.feed(Buffer.alloc(0));
|
|
@@ -8841,6 +9139,15 @@ var RawInputDecoder = class {
|
|
|
8841
9139
|
return ESCAPE_INCOMPLETE;
|
|
8842
9140
|
}
|
|
8843
9141
|
const second = this.buffer[1];
|
|
9142
|
+
if (second === 93 || second === 80 || second === 95 || second === 94 || second === 88) {
|
|
9143
|
+
for (let index = 2; index < this.buffer.length; index++) {
|
|
9144
|
+
if (this.buffer[index] === 7 || this.buffer[index] === ESC && this.buffer[index + 1] === 92) {
|
|
9145
|
+
this.buffer = this.buffer.subarray(index + (this.buffer[index] === 7 ? 1 : 2));
|
|
9146
|
+
return ESCAPE_CONSUMED;
|
|
9147
|
+
}
|
|
9148
|
+
}
|
|
9149
|
+
return ESCAPE_INCOMPLETE;
|
|
9150
|
+
}
|
|
8844
9151
|
if (second === 10 || second === 13) {
|
|
8845
9152
|
this.buffer = this.buffer.subarray(2);
|
|
8846
9153
|
return {
|
|
@@ -8887,7 +9194,9 @@ var RawInputDecoder = class {
|
|
|
8887
9194
|
this.buffer = this.buffer.subarray(final + 1);
|
|
8888
9195
|
return kind !== void 0 ? { status: "action", action: inputAction(kind) } : ESCAPE_CONSUMED;
|
|
8889
9196
|
}
|
|
8890
|
-
if (second === 79
|
|
9197
|
+
if (second === 79) {
|
|
9198
|
+
if (this.buffer.length < 3)
|
|
9199
|
+
return ESCAPE_INCOMPLETE;
|
|
8891
9200
|
const sequence = this.buffer.subarray(0, 3).toString("latin1");
|
|
8892
9201
|
const kind = ESCAPE_ACTIONS.get(sequence);
|
|
8893
9202
|
this.buffer = this.buffer.subarray(3);
|
|
@@ -9019,7 +9328,7 @@ function completeSequenceStatus(data) {
|
|
|
9019
9328
|
if (second === 93) {
|
|
9020
9329
|
return endsWithEscapeBackslash(data) || data[data.length - 1] === 7 ? "complete" : "incomplete";
|
|
9021
9330
|
}
|
|
9022
|
-
if (second === 80 || second === 95) {
|
|
9331
|
+
if (second === 80 || second === 95 || second === 94 || second === 88) {
|
|
9023
9332
|
return endsWithEscapeBackslash(data) ? "complete" : "incomplete";
|
|
9024
9333
|
}
|
|
9025
9334
|
if (second === 79) {
|
|
@@ -9269,13 +9578,6 @@ function decodeModifyOtherKeysPrintable(sequence) {
|
|
|
9269
9578
|
return null;
|
|
9270
9579
|
}
|
|
9271
9580
|
}
|
|
9272
|
-
function displayWidth(text2) {
|
|
9273
|
-
let width = 0;
|
|
9274
|
-
for (const char of text2) {
|
|
9275
|
-
width += charCellWidth(char);
|
|
9276
|
-
}
|
|
9277
|
-
return width;
|
|
9278
|
-
}
|
|
9279
9581
|
var EditorState = class _EditorState {
|
|
9280
9582
|
/** Window for the Pi-style double-Ctrl+C-to-exit gesture, in milliseconds. */
|
|
9281
9583
|
static DOUBLE_CANCEL_EXIT_MS = 500;
|
|
@@ -9345,36 +9647,7 @@ var EditorState = class _EditorState {
|
|
|
9345
9647
|
};
|
|
9346
9648
|
}
|
|
9347
9649
|
#renderProjection(width, prompt, mask) {
|
|
9348
|
-
|
|
9349
|
-
const promptWidth = Math.max(1, displayWidth(prompt));
|
|
9350
|
-
const contentWidth = Math.max(1, boundedWidth - promptWidth);
|
|
9351
|
-
const displayText = mask ? "*".repeat(this.text.length) : this.text;
|
|
9352
|
-
const sourceLines = displayText.split("\n");
|
|
9353
|
-
const rows = [];
|
|
9354
|
-
for (const source of sourceLines) {
|
|
9355
|
-
rows.push(...wrapLine(source, contentWidth));
|
|
9356
|
-
}
|
|
9357
|
-
const lastLine = sourceLines[sourceLines.length - 1];
|
|
9358
|
-
if (displayText && !displayText.endsWith("\n") && displayWidth(lastLine) % contentWidth === 0) {
|
|
9359
|
-
rows.push("");
|
|
9360
|
-
}
|
|
9361
|
-
const before = displayText.slice(0, this.cursor);
|
|
9362
|
-
const beforeLines = before.split("\n");
|
|
9363
|
-
let priorRows = 0;
|
|
9364
|
-
for (const line2 of beforeLines.slice(0, -1)) {
|
|
9365
|
-
priorRows += wrapLine(line2, contentWidth).length;
|
|
9366
|
-
}
|
|
9367
|
-
const current = beforeLines[beforeLines.length - 1];
|
|
9368
|
-
const [currentRow, currentColumn] = cursorPosition(current, contentWidth);
|
|
9369
|
-
const cursorRow = priorRows + currentRow;
|
|
9370
|
-
const cursorColumn = promptWidth + currentColumn;
|
|
9371
|
-
return {
|
|
9372
|
-
rows,
|
|
9373
|
-
prompt,
|
|
9374
|
-
promptWidth,
|
|
9375
|
-
cursorRow: Math.min(cursorRow, rows.length - 1),
|
|
9376
|
-
cursorColumn: Math.min(cursorColumn, boundedWidth - 1)
|
|
9377
|
-
};
|
|
9650
|
+
return projectInput(this.text, this.cursor, width, prompt, mask);
|
|
9378
9651
|
}
|
|
9379
9652
|
submit() {
|
|
9380
9653
|
const submitted = this.text;
|
|
@@ -9426,16 +9699,18 @@ var EditorState = class _EditorState {
|
|
|
9426
9699
|
this.insert(action.text);
|
|
9427
9700
|
} else if (action.kind === InputActionKind.Backspace && this.cursor > 0) {
|
|
9428
9701
|
this.clearCompletions();
|
|
9429
|
-
|
|
9430
|
-
this.
|
|
9702
|
+
const previous = previousGraphemeBoundary(this.text, this.cursor);
|
|
9703
|
+
const end = nextGraphemeBoundary(this.text, previous);
|
|
9704
|
+
this.text = this.text.slice(0, previous) + this.text.slice(end);
|
|
9705
|
+
this.cursor = previous;
|
|
9431
9706
|
} else if (action.kind === InputActionKind.DeleteToLineStart) {
|
|
9432
9707
|
this.deleteToLineStart();
|
|
9433
9708
|
} else if (action.kind === InputActionKind.CursorLeft) {
|
|
9434
9709
|
this.clearCompletions();
|
|
9435
|
-
this.cursor =
|
|
9710
|
+
this.cursor = previousGraphemeBoundary(this.text, this.cursor);
|
|
9436
9711
|
} else if (action.kind === InputActionKind.CursorRight) {
|
|
9437
9712
|
this.clearCompletions();
|
|
9438
|
-
this.cursor =
|
|
9713
|
+
this.cursor = nextGraphemeBoundary(this.text, this.cursor);
|
|
9439
9714
|
} else if (action.kind === InputActionKind.HistoryUp) {
|
|
9440
9715
|
this.historyUp();
|
|
9441
9716
|
} else if (action.kind === InputActionKind.HistoryDown) {
|
|
@@ -9523,42 +9798,68 @@ var EditorState = class _EditorState {
|
|
|
9523
9798
|
this.selectedCompletion = null;
|
|
9524
9799
|
}
|
|
9525
9800
|
};
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9801
|
+
|
|
9802
|
+
// ../../packages/terminal/tui/dist/tui/terminal-input-decoder.js
|
|
9803
|
+
var TerminalInputDecoder = class {
|
|
9804
|
+
#stdinBuffer = new StdinBuffer();
|
|
9805
|
+
#filter;
|
|
9806
|
+
#decoder = new RawInputDecoder();
|
|
9807
|
+
constructor(hooks, options = {}) {
|
|
9808
|
+
this.#filter = new TerminalInputFilter({
|
|
9809
|
+
...options,
|
|
9810
|
+
enableModifyOtherKeys: () => {
|
|
9811
|
+
hooks.enableModifyOtherKeys();
|
|
9812
|
+
},
|
|
9813
|
+
disableModifyOtherKeys: () => {
|
|
9814
|
+
hooks.disableModifyOtherKeys();
|
|
9815
|
+
}
|
|
9816
|
+
});
|
|
9539
9817
|
}
|
|
9540
|
-
|
|
9541
|
-
|
|
9818
|
+
get kittyProtocolActive() {
|
|
9819
|
+
return this.#filter.kittyProtocolActive;
|
|
9542
9820
|
}
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9821
|
+
set kittyProtocolActive(value) {
|
|
9822
|
+
this.#filter.kittyProtocolActive = value;
|
|
9823
|
+
}
|
|
9824
|
+
pendingKind() {
|
|
9825
|
+
return this.#filter.negotiationPending ? "negotiation" : this.#stdinBuffer.pendingKind();
|
|
9826
|
+
}
|
|
9827
|
+
feed(data) {
|
|
9828
|
+
const actions = [];
|
|
9829
|
+
for (const event of this.#stdinBuffer.feed(data)) {
|
|
9830
|
+
if (event.kind === BufferedInputKind.Paste) {
|
|
9831
|
+
actions.push(inputAction(InputActionKind.Insert, event.data.toString("utf8")));
|
|
9832
|
+
continue;
|
|
9833
|
+
}
|
|
9834
|
+
for (const sequence of this.#filter.feed(event.data)) {
|
|
9835
|
+
actions.push(...this.#decoder.feed(sequence));
|
|
9836
|
+
}
|
|
9553
9837
|
}
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9838
|
+
return actions;
|
|
9839
|
+
}
|
|
9840
|
+
flush() {
|
|
9841
|
+
const actions = [];
|
|
9842
|
+
for (const event of this.#stdinBuffer.flush()) {
|
|
9843
|
+
if (event.kind === BufferedInputKind.Paste) {
|
|
9844
|
+
actions.push(inputAction(InputActionKind.Insert, event.data.toString("utf8")));
|
|
9845
|
+
continue;
|
|
9846
|
+
}
|
|
9847
|
+
for (const sequence of this.#filter.feed(event.data)) {
|
|
9848
|
+
actions.push(...this.#decoder.feed(sequence));
|
|
9849
|
+
}
|
|
9850
|
+
}
|
|
9851
|
+
for (const sequence of this.#filter.flush()) {
|
|
9852
|
+
actions.push(...this.#decoder.feed(sequence));
|
|
9558
9853
|
}
|
|
9854
|
+
actions.push(...this.#decoder.flush());
|
|
9855
|
+
return actions;
|
|
9559
9856
|
}
|
|
9560
|
-
|
|
9561
|
-
|
|
9857
|
+
clear() {
|
|
9858
|
+
this.#stdinBuffer.clear();
|
|
9859
|
+
this.#filter.clear();
|
|
9860
|
+
this.#decoder = new RawInputDecoder();
|
|
9861
|
+
}
|
|
9862
|
+
};
|
|
9562
9863
|
|
|
9563
9864
|
// ../../packages/terminal/tui/dist/keybindings/default-keybindings.js
|
|
9564
9865
|
var DEFAULT_KEYBINDINGS = [
|
|
@@ -10381,12 +10682,12 @@ var TranscriptStore = class {
|
|
|
10381
10682
|
var StyledLineCompiler = class {
|
|
10382
10683
|
#cache = /* @__PURE__ */ new WeakMap();
|
|
10383
10684
|
compile(values, width, theme) {
|
|
10384
|
-
return values.map((value) => {
|
|
10685
|
+
return values.map((value, index) => {
|
|
10385
10686
|
const cached = this.#cache.get(value);
|
|
10386
10687
|
if (cached !== void 0 && cached.width === width && cached.theme === theme) {
|
|
10387
10688
|
return cached.text;
|
|
10388
10689
|
}
|
|
10389
|
-
const text2 = compileStyledLine(truncateStyledLine(value, width, ""), width, theme);
|
|
10690
|
+
const text2 = compileStyledLine(truncateStyledLine(value, width, ""), width, theme, `styled frame row ${index + 1}`);
|
|
10390
10691
|
this.#cache.set(value, { width, theme, text: text2 });
|
|
10391
10692
|
return text2;
|
|
10392
10693
|
});
|
|
@@ -10395,16 +10696,27 @@ var StyledLineCompiler = class {
|
|
|
10395
10696
|
this.#cache = /* @__PURE__ */ new WeakMap();
|
|
10396
10697
|
}
|
|
10397
10698
|
};
|
|
10398
|
-
function compileStyledLine(value, width, theme) {
|
|
10399
|
-
const text2 = value.spans
|
|
10699
|
+
function compileStyledLine(value, width, theme, source = "styled line") {
|
|
10700
|
+
const text2 = compileSpans(value.spans, theme);
|
|
10400
10701
|
const renderedWidth = visibleWidth(text2);
|
|
10401
10702
|
if (renderedWidth > width) {
|
|
10402
|
-
throw new
|
|
10703
|
+
throw new RenderWidthError(width, renderedWidth, text2, source);
|
|
10403
10704
|
}
|
|
10404
10705
|
return text2;
|
|
10405
10706
|
}
|
|
10406
10707
|
function compileStyledLines(values, width, theme) {
|
|
10407
|
-
return values.map((value) => compileStyledLine(value, width, theme));
|
|
10708
|
+
return values.map((value, index) => compileStyledLine(value, width, theme, `styled frame row ${index + 1}`));
|
|
10709
|
+
}
|
|
10710
|
+
function compileSpans(values, theme) {
|
|
10711
|
+
const normalized = [];
|
|
10712
|
+
for (const value of styledClusters(values)) {
|
|
10713
|
+
const previous = normalized.at(-1);
|
|
10714
|
+
if (previous && previous.style === value.style)
|
|
10715
|
+
normalized[normalized.length - 1] = { text: previous.text + value.text, style: value.style };
|
|
10716
|
+
else
|
|
10717
|
+
normalized.push(value);
|
|
10718
|
+
}
|
|
10719
|
+
return normalized.map((value) => compileSpan(value, theme)).join("");
|
|
10408
10720
|
}
|
|
10409
10721
|
function compileSpan(value, theme) {
|
|
10410
10722
|
if (value.style === void 0 || value.text.length === 0) {
|
|
@@ -10429,7 +10741,9 @@ function compileSpan(value, theme) {
|
|
|
10429
10741
|
if (value.style.background !== void 0) {
|
|
10430
10742
|
codes.push(theme.sgr(value.style.background, { background: true }).slice(2, -1));
|
|
10431
10743
|
}
|
|
10432
|
-
|
|
10744
|
+
const text2 = codes.length === 0 ? value.text : `\x1B[${codes.join(";")}m${value.text}\x1B[0m`;
|
|
10745
|
+
const url = value.style.hyperlink;
|
|
10746
|
+
return url && !/[\x00-\x20\x7f]/u.test(url) ? `\x1B]8;;${url}\x07${text2}\x1B]8;;\x07` : text2;
|
|
10433
10747
|
}
|
|
10434
10748
|
|
|
10435
10749
|
// ../../packages/terminal/tui/dist/tui/components/completion-list.js
|
|
@@ -10455,14 +10769,11 @@ var CompletionPopup = class {
|
|
|
10455
10769
|
const description = item.description.replace(/[\r\n]+/gu, " ").trim();
|
|
10456
10770
|
const value = line(span(selected ? "\u203A " : " ", selected ? { foreground: "accent" } : void 0), span(item.value, selected ? { foreground: "accent" } : void 0), ...description ? [span(` ${description}`, { foreground: "muted" })] : []);
|
|
10457
10771
|
const boundedWidth = Math.max(1, width);
|
|
10458
|
-
return
|
|
10772
|
+
return displayWidth(lineText(value)) <= boundedWidth ? value : truncateStyledLine(value, boundedWidth, "");
|
|
10459
10773
|
}
|
|
10460
10774
|
};
|
|
10461
|
-
function
|
|
10462
|
-
|
|
10463
|
-
for (const character of value)
|
|
10464
|
-
width += charCellWidth(character);
|
|
10465
|
-
return width;
|
|
10775
|
+
function displayWidth(value) {
|
|
10776
|
+
return visibleWidth(value);
|
|
10466
10777
|
}
|
|
10467
10778
|
|
|
10468
10779
|
// ../../packages/terminal/tui/dist/tui/components/composer.js
|
|
@@ -10539,10 +10850,10 @@ var StatusLine = class {
|
|
|
10539
10850
|
return { lines: [] };
|
|
10540
10851
|
}
|
|
10541
10852
|
const clippedLeft = truncateStyledLine(left, width, "");
|
|
10542
|
-
const leftWidth =
|
|
10853
|
+
const leftWidth = displayWidth2(lineText(clippedLeft));
|
|
10543
10854
|
const gap = leftWidth > 0 && lineText(right).length > 0 ? 1 : 0;
|
|
10544
10855
|
const clippedRight = truncateStyledLine(right, Math.max(0, width - leftWidth - gap), "");
|
|
10545
|
-
const rightWidth =
|
|
10856
|
+
const rightWidth = displayWidth2(lineText(clippedRight));
|
|
10546
10857
|
const padding = rightWidth > 0 ? Math.max(gap, width - leftWidth - rightWidth) : 0;
|
|
10547
10858
|
return {
|
|
10548
10859
|
lines: [line(...clippedLeft.spans, ...rightWidth > 0 ? [span(" ".repeat(padding)), ...clippedRight.spans] : [])]
|
|
@@ -10597,15 +10908,12 @@ function metadataLine(items) {
|
|
|
10597
10908
|
]));
|
|
10598
10909
|
}
|
|
10599
10910
|
function fits(leftItems, right, width) {
|
|
10600
|
-
const leftWidth =
|
|
10601
|
-
const rightWidth =
|
|
10911
|
+
const leftWidth = displayWidth2(lineText(metadataLine(leftItems)));
|
|
10912
|
+
const rightWidth = displayWidth2(lineText(right));
|
|
10602
10913
|
return leftWidth + rightWidth + (leftWidth > 0 && rightWidth > 0 ? 1 : 0) <= width;
|
|
10603
10914
|
}
|
|
10604
|
-
function
|
|
10605
|
-
|
|
10606
|
-
for (const character of value)
|
|
10607
|
-
width += charCellWidth(character);
|
|
10608
|
-
return width;
|
|
10915
|
+
function displayWidth2(value) {
|
|
10916
|
+
return visibleWidth(value);
|
|
10609
10917
|
}
|
|
10610
10918
|
|
|
10611
10919
|
// ../../packages/terminal/tui/dist/tui/markdown.js
|
|
@@ -10617,7 +10925,7 @@ function renderMarkdownStyledLines(text2, width) {
|
|
|
10617
10925
|
if (!clean.trim()) {
|
|
10618
10926
|
return [];
|
|
10619
10927
|
}
|
|
10620
|
-
const layoutWidth = Math.max(
|
|
10928
|
+
const layoutWidth = Math.max(1, width);
|
|
10621
10929
|
const lines2 = [];
|
|
10622
10930
|
let previous = null;
|
|
10623
10931
|
for (const block of renderBlocks(clean, layoutWidth, Math.max(1, width))) {
|
|
@@ -10641,7 +10949,8 @@ function styleKey(style) {
|
|
|
10641
10949
|
style.italic ? "i" : "",
|
|
10642
10950
|
style.underline ? "u" : "",
|
|
10643
10951
|
style.foreground ?? "",
|
|
10644
|
-
style.background ?? ""
|
|
10952
|
+
style.background ?? "",
|
|
10953
|
+
style.hyperlink ?? ""
|
|
10645
10954
|
].join("|");
|
|
10646
10955
|
}
|
|
10647
10956
|
function renderBlocks(text2, layoutWidth, tableWidth) {
|
|
@@ -10676,6 +10985,10 @@ function renderBlocks(text2, layoutWidth, tableWidth) {
|
|
|
10676
10985
|
index += 1;
|
|
10677
10986
|
break;
|
|
10678
10987
|
}
|
|
10988
|
+
if (index === lines2.length - 1 && body.trim().length > 0 && body.trim().length < 3 && body.trim() === fence[0].repeat(body.trim().length)) {
|
|
10989
|
+
index += 1;
|
|
10990
|
+
break;
|
|
10991
|
+
}
|
|
10679
10992
|
codeLines.push(...body ? wrapSegments([{ style: codeStyle, text: body }], layoutWidth) : [[]]);
|
|
10680
10993
|
index += 1;
|
|
10681
10994
|
}
|
|
@@ -10808,7 +11121,7 @@ function renderListItems(items, prefixFor, layoutWidth) {
|
|
|
10808
11121
|
const marker = { foreground: "accent" };
|
|
10809
11122
|
const lines2 = [];
|
|
10810
11123
|
for (let index = 0; index < items.length; index += 1) {
|
|
10811
|
-
const prefix = prefixFor(index);
|
|
11124
|
+
const prefix = prefixFor(index).slice(0, Math.max(0, layoutWidth - 1));
|
|
10812
11125
|
const wrapped = wrapSegments(items[index], Math.max(1, layoutWidth - prefix.length));
|
|
10813
11126
|
if (wrapped.length === 0) {
|
|
10814
11127
|
lines2.push([{ style: marker, text: prefix }]);
|
|
@@ -10840,13 +11153,7 @@ function splitTableRow(line2) {
|
|
|
10840
11153
|
return rest.split("|").map((cell) => cell.trim());
|
|
10841
11154
|
}
|
|
10842
11155
|
function segmentsWidth(segments) {
|
|
10843
|
-
|
|
10844
|
-
for (const segment of segments) {
|
|
10845
|
-
for (const cluster of graphemeClusters(segment.text)) {
|
|
10846
|
-
width += clusterWidth(cluster);
|
|
10847
|
-
}
|
|
10848
|
-
}
|
|
10849
|
-
return width;
|
|
11156
|
+
return styledClusters(segments).reduce((width, item) => width + graphemeClusters(item.text).reduce((total, cluster) => total + clusterWidth(cluster), 0), 0);
|
|
10850
11157
|
}
|
|
10851
11158
|
function renderTable(header, rows, layoutWidth, rawLines) {
|
|
10852
11159
|
const columnCount = header.length;
|
|
@@ -10863,10 +11170,8 @@ function renderTable(header, rows, layoutWidth, rawLines) {
|
|
|
10863
11170
|
const minWidths = Array(columnCount).fill(1);
|
|
10864
11171
|
for (const row of [headerCells, ...bodyCells]) {
|
|
10865
11172
|
for (let i = 0; i < columnCount; i += 1) {
|
|
10866
|
-
for (const
|
|
10867
|
-
|
|
10868
|
-
minWidths[i] = Math.max(minWidths[i], clusterWidth(cluster));
|
|
10869
|
-
}
|
|
11173
|
+
for (const cluster of styledClusters(row[i])) {
|
|
11174
|
+
minWidths[i] = Math.max(minWidths[i], visibleWidth(cluster.text));
|
|
10870
11175
|
}
|
|
10871
11176
|
}
|
|
10872
11177
|
}
|
|
@@ -10956,10 +11261,12 @@ var INLINE_PATTERNS = [
|
|
|
10956
11261
|
},
|
|
10957
11262
|
{
|
|
10958
11263
|
// Links and images: visible text plus the URL in parentheses, matching
|
|
10959
|
-
//
|
|
10960
|
-
// the link text as plain (unparsed) content.
|
|
11264
|
+
// Keep the destination readable when terminal hyperlinks are unavailable.
|
|
10961
11265
|
pattern: /!?\[([^\]]*)\]\(([^)\s]+)\)/,
|
|
10962
|
-
expand: (base, match) => [
|
|
11266
|
+
expand: (base, match) => supportsTerminalHyperlinks() && !/[\x00-\x20\x7f]/u.test(match[2]) ? [{
|
|
11267
|
+
style: { ...base, underline: true, foreground: "link", hyperlink: match[2] },
|
|
11268
|
+
text: match[1]
|
|
11269
|
+
}] : [
|
|
10963
11270
|
{
|
|
10964
11271
|
style: { ...base, underline: true, foreground: "link" },
|
|
10965
11272
|
text: match[1]
|
|
@@ -11051,15 +11358,14 @@ function mergeSegments(segments) {
|
|
|
11051
11358
|
}
|
|
11052
11359
|
function wrapSegments(segments, width) {
|
|
11053
11360
|
const clusters = [];
|
|
11054
|
-
for (const
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
}
|
|
11361
|
+
for (const item of styledClusters(segments)) {
|
|
11362
|
+
const measured = graphemeClusters(item.text).reduce((total, cluster) => total + clusterWidth(cluster), 0);
|
|
11363
|
+
clusters.push({
|
|
11364
|
+
style: item.style ?? {},
|
|
11365
|
+
text: measured > width ? "\uFFFD" : item.text,
|
|
11366
|
+
width: measured > width ? 1 : measured,
|
|
11367
|
+
space: item.text === " "
|
|
11368
|
+
});
|
|
11063
11369
|
}
|
|
11064
11370
|
const words = [];
|
|
11065
11371
|
let current = [];
|
|
@@ -11141,24 +11447,7 @@ function serializeLine(segments) {
|
|
|
11141
11447
|
return line(...segments.map((segment) => span(segment.text, segment.style)));
|
|
11142
11448
|
}
|
|
11143
11449
|
function truncateMarkdownLine(value, width) {
|
|
11144
|
-
|
|
11145
|
-
let used = 0;
|
|
11146
|
-
for (const source of value.spans) {
|
|
11147
|
-
let text2 = "";
|
|
11148
|
-
for (const character of source.text) {
|
|
11149
|
-
const characterWidth = charCellWidth(character);
|
|
11150
|
-
if (used + characterWidth > width) {
|
|
11151
|
-
if (text2)
|
|
11152
|
-
spans.push(span(text2, source.style));
|
|
11153
|
-
return line(...spans);
|
|
11154
|
-
}
|
|
11155
|
-
text2 += character;
|
|
11156
|
-
used += characterWidth;
|
|
11157
|
-
}
|
|
11158
|
-
if (text2)
|
|
11159
|
-
spans.push(span(text2, source.style));
|
|
11160
|
-
}
|
|
11161
|
-
return line(...spans);
|
|
11450
|
+
return truncateStyledLine(value, width, "");
|
|
11162
11451
|
}
|
|
11163
11452
|
|
|
11164
11453
|
// ../../packages/terminal/tui/dist/tui/components/messages/assistant-message.js
|
|
@@ -11195,9 +11484,10 @@ var Text = class {
|
|
|
11195
11484
|
if (this.#cache?.width === context.width && this.#cache.source === source) {
|
|
11196
11485
|
return this.#cache.result;
|
|
11197
11486
|
}
|
|
11198
|
-
const
|
|
11487
|
+
const paddingX = Math.min(this.#options.paddingX, Math.max(0, Math.floor((context.width - 1) / 2)));
|
|
11488
|
+
const contentWidth = Math.max(1, context.width - paddingX * 2);
|
|
11199
11489
|
const wrapped = wrapStyledSpans(spans, contentWidth);
|
|
11200
|
-
const result = { lines: applyTextPadding(wrapped, context.width, this.#options) };
|
|
11490
|
+
const result = { lines: applyTextPadding(wrapped, context.width, { ...this.#options, paddingX }) };
|
|
11201
11491
|
this.#cache = { width: context.width, source, result };
|
|
11202
11492
|
return result;
|
|
11203
11493
|
}
|
|
@@ -11291,12 +11581,13 @@ var Box = class {
|
|
|
11291
11581
|
}
|
|
11292
11582
|
render(context) {
|
|
11293
11583
|
const width = Math.max(0, context.width);
|
|
11294
|
-
const
|
|
11584
|
+
const paddingX = Math.min(this.#paddingX, Math.max(0, Math.floor((width - 1) / 2)));
|
|
11585
|
+
const child = this.#child.render({ ...context, width: Math.max(1, width - paddingX * 2) });
|
|
11295
11586
|
const blank = () => line(span(" ".repeat(width), backgroundStyle2(this.#background)));
|
|
11296
|
-
const lines2 = child.lines.map((value) => this.#renderLine(value, width));
|
|
11587
|
+
const lines2 = child.lines.map((value) => this.#renderLine(value, width, paddingX));
|
|
11297
11588
|
const cursor = child.cursor === void 0 ? void 0 : {
|
|
11298
11589
|
row: child.cursor.row + this.#paddingY,
|
|
11299
|
-
column: child.cursor.column +
|
|
11590
|
+
column: Math.max(0, Math.min(width - 1, child.cursor.column + paddingX))
|
|
11300
11591
|
};
|
|
11301
11592
|
return {
|
|
11302
11593
|
lines: [
|
|
@@ -11310,8 +11601,8 @@ var Box = class {
|
|
|
11310
11601
|
invalidate() {
|
|
11311
11602
|
this.#child.invalidate();
|
|
11312
11603
|
}
|
|
11313
|
-
#renderLine(value, width) {
|
|
11314
|
-
const left = span(" ".repeat(
|
|
11604
|
+
#renderLine(value, width, paddingX) {
|
|
11605
|
+
const left = span(" ".repeat(paddingX), backgroundStyle2(this.#background));
|
|
11315
11606
|
const content = value.spans.map((item) => span(item.text, this.#background === void 0 ? item.style : { ...item.style, background: this.#background }));
|
|
11316
11607
|
return padStyledLine(truncateStyledLine(line(left, ...content), width, ""), width, this.#background);
|
|
11317
11608
|
}
|
|
@@ -11557,7 +11848,7 @@ var Transcript = class {
|
|
|
11557
11848
|
return this.renderWithMetadata(context);
|
|
11558
11849
|
}
|
|
11559
11850
|
renderWithMetadata(context) {
|
|
11560
|
-
const usableWidth = Math.max(
|
|
11851
|
+
const usableWidth = Math.max(1, context.width);
|
|
11561
11852
|
const lines2 = [];
|
|
11562
11853
|
let activeStart = null;
|
|
11563
11854
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
@@ -11914,17 +12205,12 @@ var SearchInput = class {
|
|
|
11914
12205
|
}
|
|
11915
12206
|
render(context) {
|
|
11916
12207
|
const width = Math.max(1, context.width);
|
|
11917
|
-
const
|
|
11918
|
-
const
|
|
11919
|
-
const lines2 =
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
lines: structuredLines,
|
|
11924
|
-
cursor: {
|
|
11925
|
-
row: Math.min(cursor.row, structuredLines.length - 1),
|
|
11926
|
-
column: Math.min(displayWidth4(PROMPT) + cursor.column, width - 1)
|
|
11927
|
-
}
|
|
12208
|
+
const empty = this.#editor.text.length === 0;
|
|
12209
|
+
const projection = projectInput(empty ? this.#placeholder : this.#editor.text, this.#editor.cursor, width, PROMPT, this.#secret && !empty);
|
|
12210
|
+
const lines2 = projection.rows.map((value, index) => line(span(index === 0 ? projection.prompt : " ".repeat(projection.promptWidth), index === 0 ? { foreground: "accent" } : void 0), span(this.#secret && !empty ? value.replace(/\*/g, "\u2022") : value, empty ? { foreground: "muted" } : void 0)));
|
|
12211
|
+
return {
|
|
12212
|
+
lines: lines2,
|
|
12213
|
+
...this.focused ? { cursor: { row: empty ? 0 : projection.cursorRow, column: empty ? projection.promptWidth : projection.cursorColumn } } : {}
|
|
11928
12214
|
};
|
|
11929
12215
|
}
|
|
11930
12216
|
handleInput(event) {
|
|
@@ -11981,52 +12267,6 @@ function actionFor(event) {
|
|
|
11981
12267
|
return null;
|
|
11982
12268
|
}
|
|
11983
12269
|
}
|
|
11984
|
-
function renderLines(value, width, placeholder) {
|
|
11985
|
-
if (placeholder) {
|
|
11986
|
-
return [value];
|
|
11987
|
-
}
|
|
11988
|
-
const lines2 = [];
|
|
11989
|
-
for (const source of value.split("\n")) {
|
|
11990
|
-
lines2.push(...wrapStyledSpans([span(source)], width).map((item) => item.spans.map((part) => part.text).join("")));
|
|
11991
|
-
}
|
|
11992
|
-
const last = value.split("\n").at(-1) ?? "";
|
|
11993
|
-
if (value && !value.endsWith("\n") && displayWidth4(last) % width === 0) {
|
|
11994
|
-
lines2.push("");
|
|
11995
|
-
}
|
|
11996
|
-
return lines2;
|
|
11997
|
-
}
|
|
11998
|
-
function cursorMetadata(before, width) {
|
|
11999
|
-
const segments = before.split("\n");
|
|
12000
|
-
let row = 0;
|
|
12001
|
-
for (const segment of segments.slice(0, -1)) {
|
|
12002
|
-
row += wrappedRowCount(segment, width);
|
|
12003
|
-
}
|
|
12004
|
-
const current = segments.at(-1) ?? "";
|
|
12005
|
-
let column = 0;
|
|
12006
|
-
for (const character of current) {
|
|
12007
|
-
const characterWidth = Math.max(1, charCellWidth(character));
|
|
12008
|
-
if (column > 0 && column + characterWidth > width) {
|
|
12009
|
-
row += 1;
|
|
12010
|
-
column = 0;
|
|
12011
|
-
}
|
|
12012
|
-
column += characterWidth;
|
|
12013
|
-
if (column === width) {
|
|
12014
|
-
row += 1;
|
|
12015
|
-
column = 0;
|
|
12016
|
-
}
|
|
12017
|
-
}
|
|
12018
|
-
return { row, column };
|
|
12019
|
-
}
|
|
12020
|
-
function wrappedRowCount(value, width) {
|
|
12021
|
-
return wrapStyledSpans([span(value)], width).length;
|
|
12022
|
-
}
|
|
12023
|
-
function displayWidth4(value) {
|
|
12024
|
-
let width = 0;
|
|
12025
|
-
for (const character of value) {
|
|
12026
|
-
width += charCellWidth(character);
|
|
12027
|
-
}
|
|
12028
|
-
return width;
|
|
12029
|
-
}
|
|
12030
12270
|
|
|
12031
12271
|
// ../../packages/terminal/tui/dist/tui/components/primitives/select-list.js
|
|
12032
12272
|
var DEFAULT_PRIMARY_COLUMN_WIDTH = 32;
|
|
@@ -12111,13 +12351,13 @@ var SelectList = class {
|
|
|
12111
12351
|
}
|
|
12112
12352
|
#renderItem(item, selected, width, primaryColumnWidth) {
|
|
12113
12353
|
const prefix = selected ? span("\u2192 ", { foreground: "accent" }) : span(" ");
|
|
12114
|
-
const prefixWidth =
|
|
12354
|
+
const prefixWidth = displayWidth3(prefix.text);
|
|
12115
12355
|
const description = item.description === void 0 ? void 0 : normalizeDescription(item.description);
|
|
12116
12356
|
if (description && width > 40) {
|
|
12117
12357
|
const effectivePrimaryWidth = Math.max(1, Math.min(primaryColumnWidth, width - prefixWidth - 4));
|
|
12118
12358
|
const label = truncateText(displayValue(item), Math.max(1, effectivePrimaryWidth - PRIMARY_COLUMN_GAP));
|
|
12119
|
-
const spacing = " ".repeat(Math.max(1, effectivePrimaryWidth -
|
|
12120
|
-
const remainingWidth = width - prefixWidth -
|
|
12359
|
+
const spacing = " ".repeat(Math.max(1, effectivePrimaryWidth - displayWidth3(label)));
|
|
12360
|
+
const remainingWidth = width - prefixWidth - displayWidth3(label) - displayWidth3(spacing) - 2;
|
|
12121
12361
|
if (remainingWidth > MIN_DESCRIPTION_WIDTH) {
|
|
12122
12362
|
return truncateStyledLine(line(prefix, span(label, selected ? { foreground: "accent" } : void 0), span(spacing), span(truncateText(description, remainingWidth), { foreground: "muted" })), width, "");
|
|
12123
12363
|
}
|
|
@@ -12125,7 +12365,7 @@ var SelectList = class {
|
|
|
12125
12365
|
return truncateStyledLine(line(prefix, span(truncateText(displayValue(item), Math.max(1, width - prefixWidth - 2)), selected ? { foreground: "accent" } : void 0)), width, "");
|
|
12126
12366
|
}
|
|
12127
12367
|
#primaryColumnWidth() {
|
|
12128
|
-
const widest = this.#filteredItems.reduce((value, item) => Math.max(value,
|
|
12368
|
+
const widest = this.#filteredItems.reduce((value, item) => Math.max(value, displayWidth3(displayValue(item)) + PRIMARY_COLUMN_GAP), 0);
|
|
12129
12369
|
return Math.max(1, Math.min(DEFAULT_PRIMARY_COLUMN_WIDTH, Math.max(DEFAULT_PRIMARY_COLUMN_WIDTH, widest)));
|
|
12130
12370
|
}
|
|
12131
12371
|
};
|
|
@@ -12138,12 +12378,8 @@ function normalizeDescription(value) {
|
|
|
12138
12378
|
function truncateText(value, width) {
|
|
12139
12379
|
return lineText(truncateStyledLine(line(span(value)), width, ""));
|
|
12140
12380
|
}
|
|
12141
|
-
function
|
|
12142
|
-
|
|
12143
|
-
for (const character of value) {
|
|
12144
|
-
width += charCellWidth(character);
|
|
12145
|
-
}
|
|
12146
|
-
return width;
|
|
12381
|
+
function displayWidth3(value) {
|
|
12382
|
+
return visibleWidth(value);
|
|
12147
12383
|
}
|
|
12148
12384
|
|
|
12149
12385
|
// ../../packages/terminal/tui/dist/tui/components/primitives/v-stack.js
|
|
@@ -12426,7 +12662,7 @@ var ViewHost = class {
|
|
|
12426
12662
|
openSelection(request) {
|
|
12427
12663
|
return new Promise((resolve8) => {
|
|
12428
12664
|
const component = this.#selectionComponent(request);
|
|
12429
|
-
this.#open({ id: request.id, component, resolve: resolve8 }, "selector");
|
|
12665
|
+
this.#open({ id: request.id, component, resolve: resolve8 }, "selector", request.floating);
|
|
12430
12666
|
});
|
|
12431
12667
|
}
|
|
12432
12668
|
openPrompt(request) {
|
|
@@ -12436,13 +12672,15 @@ var ViewHost = class {
|
|
|
12436
12672
|
onSubmit: (value) => this.#close(request.id, value),
|
|
12437
12673
|
onCancel: () => this.#close(request.id, null)
|
|
12438
12674
|
});
|
|
12439
|
-
this.#open({ id: request.id, component, resolve: resolve8 }, "modal");
|
|
12675
|
+
this.#open({ id: request.id, component, resolve: resolve8 }, "modal", request.floating);
|
|
12440
12676
|
});
|
|
12441
12677
|
}
|
|
12442
12678
|
handleInput(event) {
|
|
12443
12679
|
return this.#topView()?.component.handleInput?.(event) ?? false;
|
|
12444
12680
|
}
|
|
12445
12681
|
render(context) {
|
|
12682
|
+
if (this.#overlays.top()?.placement === "floating")
|
|
12683
|
+
return { lines: [] };
|
|
12446
12684
|
return this.#topView()?.component.render(context) ?? { lines: [] };
|
|
12447
12685
|
}
|
|
12448
12686
|
closeActive(value) {
|
|
@@ -12459,10 +12697,12 @@ var ViewHost = class {
|
|
|
12459
12697
|
activeId() {
|
|
12460
12698
|
return this.#topView()?.id ?? null;
|
|
12461
12699
|
}
|
|
12462
|
-
#open(view, priority) {
|
|
12700
|
+
#open(view, priority, floating) {
|
|
12463
12701
|
this.#close(view.id, null);
|
|
12464
12702
|
this.#views.push(view);
|
|
12465
|
-
if (
|
|
12703
|
+
if (floating !== void 0) {
|
|
12704
|
+
this.#overlays.open({ id: view.id, component: view.component, priority, placement: "floating", options: floating });
|
|
12705
|
+
} else if (priority === "selector") {
|
|
12466
12706
|
this.#overlays.open(createSelectorOverlay(view.id, view.component));
|
|
12467
12707
|
} else {
|
|
12468
12708
|
this.#overlays.open(createModalOverlay(view.id, view.component));
|
|
@@ -12550,7 +12790,61 @@ var PRIORITY_ORDER = {
|
|
|
12550
12790
|
};
|
|
12551
12791
|
var OverlayManager = class {
|
|
12552
12792
|
#entries = [];
|
|
12793
|
+
#hidden = /* @__PURE__ */ new Set();
|
|
12794
|
+
#width = 80;
|
|
12795
|
+
#height = 24;
|
|
12796
|
+
setViewport(width, height) {
|
|
12797
|
+
this.#width = Math.max(1, width);
|
|
12798
|
+
this.#height = Math.max(1, height);
|
|
12799
|
+
this.#syncFocus();
|
|
12800
|
+
}
|
|
12801
|
+
setHidden(id, hidden) {
|
|
12802
|
+
if (hidden)
|
|
12803
|
+
this.#hidden.add(id);
|
|
12804
|
+
else
|
|
12805
|
+
this.#hidden.delete(id);
|
|
12806
|
+
this.#syncFocus();
|
|
12807
|
+
}
|
|
12808
|
+
composite(frame, theme) {
|
|
12809
|
+
const overlays = this.#entries.filter((entry) => entry.placement === "floating" && this.#visible(entry)).sort((left, right) => PRIORITY_ORDER[left.priority] - PRIORITY_ORDER[right.priority]);
|
|
12810
|
+
if (overlays.length === 0)
|
|
12811
|
+
return frame;
|
|
12812
|
+
const lines2 = [...frame.lines];
|
|
12813
|
+
while (lines2.length < this.#height)
|
|
12814
|
+
lines2.push("");
|
|
12815
|
+
const viewport = Math.max(0, lines2.length - this.#height);
|
|
12816
|
+
let cursorRow = frame.cursorRow;
|
|
12817
|
+
let cursorCol = frame.cursorCol;
|
|
12818
|
+
for (const entry of overlays) {
|
|
12819
|
+
const options = entry.options ?? {};
|
|
12820
|
+
const requested = typeof options.width === "string" ? this.#width * Number.parseFloat(options.width) / 100 : options.width ?? Math.min(80, this.#width);
|
|
12821
|
+
const width = Math.max(1, Math.min(this.#width, Number.isFinite(requested) ? Math.floor(requested) : this.#width));
|
|
12822
|
+
const rendered = entry.component.render({ width, theme });
|
|
12823
|
+
const height = Math.max(0, Math.min(this.#height, options.maxHeight ?? this.#height, rendered.lines.length));
|
|
12824
|
+
if (height === 0)
|
|
12825
|
+
continue;
|
|
12826
|
+
const row = Math.max(0, Math.min(this.#height - height, Math.floor(options.row ?? (this.#height - height) / 2)));
|
|
12827
|
+
const column = Math.max(0, Math.min(this.#width - width, Math.floor(options.column ?? (this.#width - width) / 2)));
|
|
12828
|
+
const content = compileStyledLines(rendered.lines.slice(0, height).map((value) => truncateStyledLine(value, width, "")), width, theme);
|
|
12829
|
+
for (let index = 0; index < height; index++) {
|
|
12830
|
+
const target = viewport + row + index;
|
|
12831
|
+
const before = sliceByColumn(lines2[target], 0, column);
|
|
12832
|
+
const after = sliceByColumn(lines2[target], column + width, this.#width - column - width);
|
|
12833
|
+
lines2[target] = before + TERMINAL_RESET + sliceByColumn(content[index], 0, width) + TERMINAL_RESET + after;
|
|
12834
|
+
}
|
|
12835
|
+
if (entry.component.focused) {
|
|
12836
|
+
cursorRow = viewport + row + Math.max(0, Math.min(height - 1, rendered.cursor?.row ?? 0));
|
|
12837
|
+
cursorCol = column + Math.max(0, Math.min(width - 1, rendered.cursor?.column ?? 0));
|
|
12838
|
+
}
|
|
12839
|
+
}
|
|
12840
|
+
return { ...frame, lines: lines2, activeStart: Math.min(frame.activeStart ?? lines2.length, viewport), cursorRow, cursorCol };
|
|
12841
|
+
}
|
|
12553
12842
|
open(entry) {
|
|
12843
|
+
for (const value of [entry.options?.row, entry.options?.column, entry.options?.maxHeight]) {
|
|
12844
|
+
if (value !== void 0 && (!Number.isInteger(value) || value < 0))
|
|
12845
|
+
throw new Error("Overlay coordinates and height must be non-negative integers");
|
|
12846
|
+
}
|
|
12847
|
+
this.#hidden.delete(entry.id);
|
|
12554
12848
|
const previous = this.#entries.filter((item) => item.id === entry.id);
|
|
12555
12849
|
for (const item of previous) {
|
|
12556
12850
|
item.component.focused = false;
|
|
@@ -12560,6 +12854,7 @@ var OverlayManager = class {
|
|
|
12560
12854
|
this.#syncFocus();
|
|
12561
12855
|
}
|
|
12562
12856
|
close(id) {
|
|
12857
|
+
this.#hidden.delete(id);
|
|
12563
12858
|
const closing = this.#entries.filter((entry) => entry.id === id);
|
|
12564
12859
|
for (const entry of closing) {
|
|
12565
12860
|
entry.component.focused = false;
|
|
@@ -12570,6 +12865,8 @@ var OverlayManager = class {
|
|
|
12570
12865
|
top() {
|
|
12571
12866
|
let top = null;
|
|
12572
12867
|
for (const entry of this.#entries) {
|
|
12868
|
+
if (!this.#visible(entry) || entry.options?.nonCapturing)
|
|
12869
|
+
continue;
|
|
12573
12870
|
if (top === null || PRIORITY_ORDER[entry.priority] >= PRIORITY_ORDER[top.priority]) {
|
|
12574
12871
|
top = entry;
|
|
12575
12872
|
}
|
|
@@ -12582,69 +12879,12 @@ var OverlayManager = class {
|
|
|
12582
12879
|
entry.component.focused = entry === top;
|
|
12583
12880
|
}
|
|
12584
12881
|
}
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
// ../../packages/terminal/tui/dist/tui/terminal-input-decoder.js
|
|
12588
|
-
var TerminalInputDecoder = class {
|
|
12589
|
-
#stdinBuffer = new StdinBuffer();
|
|
12590
|
-
#filter;
|
|
12591
|
-
#decoder = new RawInputDecoder();
|
|
12592
|
-
constructor(hooks, options = {}) {
|
|
12593
|
-
this.#filter = new TerminalInputFilter({
|
|
12594
|
-
...options,
|
|
12595
|
-
enableModifyOtherKeys: () => {
|
|
12596
|
-
hooks.enableModifyOtherKeys();
|
|
12597
|
-
},
|
|
12598
|
-
disableModifyOtherKeys: () => {
|
|
12599
|
-
hooks.disableModifyOtherKeys();
|
|
12600
|
-
}
|
|
12601
|
-
});
|
|
12602
|
-
}
|
|
12603
|
-
get kittyProtocolActive() {
|
|
12604
|
-
return this.#filter.kittyProtocolActive;
|
|
12605
|
-
}
|
|
12606
|
-
set kittyProtocolActive(value) {
|
|
12607
|
-
this.#filter.kittyProtocolActive = value;
|
|
12608
|
-
}
|
|
12609
|
-
feed(data) {
|
|
12610
|
-
const actions = [];
|
|
12611
|
-
for (const event of this.#stdinBuffer.feed(data)) {
|
|
12612
|
-
if (event.kind === BufferedInputKind.Paste) {
|
|
12613
|
-
actions.push(inputAction(InputActionKind.Insert, event.data.toString("utf8")));
|
|
12614
|
-
continue;
|
|
12615
|
-
}
|
|
12616
|
-
for (const sequence of this.#filter.feed(event.data)) {
|
|
12617
|
-
actions.push(...this.#decoder.feed(sequence));
|
|
12618
|
-
}
|
|
12619
|
-
}
|
|
12620
|
-
return actions;
|
|
12621
|
-
}
|
|
12622
|
-
flush() {
|
|
12623
|
-
const actions = [];
|
|
12624
|
-
for (const event of this.#stdinBuffer.flush()) {
|
|
12625
|
-
if (event.kind === BufferedInputKind.Paste) {
|
|
12626
|
-
actions.push(inputAction(InputActionKind.Insert, event.data.toString("utf8")));
|
|
12627
|
-
continue;
|
|
12628
|
-
}
|
|
12629
|
-
for (const sequence of this.#filter.feed(event.data)) {
|
|
12630
|
-
actions.push(...this.#decoder.feed(sequence));
|
|
12631
|
-
}
|
|
12632
|
-
}
|
|
12633
|
-
for (const sequence of this.#filter.flush()) {
|
|
12634
|
-
actions.push(...this.#decoder.feed(sequence));
|
|
12635
|
-
}
|
|
12636
|
-
actions.push(...this.#decoder.flush());
|
|
12637
|
-
return actions;
|
|
12638
|
-
}
|
|
12639
|
-
clear() {
|
|
12640
|
-
this.#stdinBuffer.clear();
|
|
12641
|
-
this.#filter.clear();
|
|
12642
|
-
this.#decoder = new RawInputDecoder();
|
|
12882
|
+
#visible(entry) {
|
|
12883
|
+
return !this.#hidden.has(entry.id) && (entry.options?.visible?.(this.#width, this.#height) ?? true);
|
|
12643
12884
|
}
|
|
12644
12885
|
};
|
|
12645
12886
|
|
|
12646
12887
|
// ../../packages/terminal/tui/dist/tui/ui.js
|
|
12647
|
-
var _a;
|
|
12648
12888
|
var WELCOME_TEXT = "Welcome to LaoHuang Code!";
|
|
12649
12889
|
var WELCOME_HELP_TEXT = "Send /help for help information.";
|
|
12650
12890
|
var LocalMessage = class {
|
|
@@ -12757,8 +12997,7 @@ function editorActionForKey(key) {
|
|
|
12757
12997
|
return inputAction(InputActionKind.Eof);
|
|
12758
12998
|
return null;
|
|
12759
12999
|
}
|
|
12760
|
-
var InteractiveTerminalLoop = class {
|
|
12761
|
-
static ESCAPE_TIMEOUT_MS = 50;
|
|
13000
|
+
var InteractiveTerminalLoop = class _InteractiveTerminalLoop {
|
|
12762
13001
|
static WORK_QUEUE_LIMIT = 4096;
|
|
12763
13002
|
#ui;
|
|
12764
13003
|
#driver;
|
|
@@ -12782,6 +13021,8 @@ var InteractiveTerminalLoop = class {
|
|
|
12782
13021
|
#escapeTimer = null;
|
|
12783
13022
|
#wakeupEnabled = false;
|
|
12784
13023
|
#wakeupScheduled = false;
|
|
13024
|
+
#renderTimer = null;
|
|
13025
|
+
#lastRenderAt = 0;
|
|
12785
13026
|
#disposeResize = null;
|
|
12786
13027
|
writeError = null;
|
|
12787
13028
|
constructor(ui, driver, editor, decoderFactory) {
|
|
@@ -12826,7 +13067,7 @@ var InteractiveTerminalLoop = class {
|
|
|
12826
13067
|
if (previous >= 0)
|
|
12827
13068
|
this.#work.splice(previous, 1);
|
|
12828
13069
|
}
|
|
12829
|
-
if (this.#work.length >=
|
|
13070
|
+
if (this.#work.length >= _InteractiveTerminalLoop.WORK_QUEUE_LIMIT - 128 && this.#ui.isHighFrequencyDisplayEvent(event)) {
|
|
12830
13071
|
this.#ui.recordDisplayDrop(event);
|
|
12831
13072
|
return;
|
|
12832
13073
|
}
|
|
@@ -12842,10 +13083,19 @@ var InteractiveTerminalLoop = class {
|
|
|
12842
13083
|
}
|
|
12843
13084
|
/** Synchronously consume queued work; this is also the test hook. */
|
|
12844
13085
|
drain() {
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
13086
|
+
if (this.#renderTimer !== null) {
|
|
13087
|
+
clearTimeout(this.#renderTimer);
|
|
13088
|
+
this.#renderTimer = null;
|
|
13089
|
+
}
|
|
13090
|
+
try {
|
|
13091
|
+
const changed = this.#drainWork();
|
|
13092
|
+
const dropped = this.#ui.flushDisplayDropMarker();
|
|
13093
|
+
if (changed || dropped || this.#needsRender) {
|
|
13094
|
+
this.#render();
|
|
13095
|
+
}
|
|
13096
|
+
} catch (error) {
|
|
13097
|
+
this.writeError = recordRenderFailure(error);
|
|
13098
|
+
this.requestExit();
|
|
12849
13099
|
}
|
|
12850
13100
|
}
|
|
12851
13101
|
requestRender() {
|
|
@@ -12868,6 +13118,10 @@ var InteractiveTerminalLoop = class {
|
|
|
12868
13118
|
focusedComponentId() {
|
|
12869
13119
|
return this.#focus.current();
|
|
12870
13120
|
}
|
|
13121
|
+
setOverlayHidden(id, hidden) {
|
|
13122
|
+
this.#overlays.setHidden(id, hidden);
|
|
13123
|
+
this.requestRender();
|
|
13124
|
+
}
|
|
12871
13125
|
renderActiveView(context) {
|
|
12872
13126
|
return this.#viewHost.render(context);
|
|
12873
13127
|
}
|
|
@@ -12880,6 +13134,10 @@ var InteractiveTerminalLoop = class {
|
|
|
12880
13134
|
return;
|
|
12881
13135
|
}
|
|
12882
13136
|
this.#closed = true;
|
|
13137
|
+
if (this.#renderTimer !== null) {
|
|
13138
|
+
clearTimeout(this.#renderTimer);
|
|
13139
|
+
this.#renderTimer = null;
|
|
13140
|
+
}
|
|
12883
13141
|
this.#running = false;
|
|
12884
13142
|
this.#cancelPendingViews();
|
|
12885
13143
|
this.#viewHost.closeAll();
|
|
@@ -12888,7 +13146,12 @@ var InteractiveTerminalLoop = class {
|
|
|
12888
13146
|
this.#escapeTimer = null;
|
|
12889
13147
|
}
|
|
12890
13148
|
this.#stopResizeWatcher();
|
|
12891
|
-
|
|
13149
|
+
try {
|
|
13150
|
+
this.#stopTerminalModes();
|
|
13151
|
+
} catch (error) {
|
|
13152
|
+
if (this.writeError === null)
|
|
13153
|
+
this.writeError = error;
|
|
13154
|
+
}
|
|
12892
13155
|
try {
|
|
12893
13156
|
this.#renderer.close();
|
|
12894
13157
|
} catch (error) {
|
|
@@ -12903,17 +13166,32 @@ var InteractiveTerminalLoop = class {
|
|
|
12903
13166
|
this.#driver.enterRawMode?.();
|
|
12904
13167
|
this.startTerminalModes();
|
|
12905
13168
|
const onData = (data) => {
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
13169
|
+
try {
|
|
13170
|
+
this.feedInputBytes(data);
|
|
13171
|
+
this.drain();
|
|
13172
|
+
this.#armEscapeTimer();
|
|
13173
|
+
} catch (error) {
|
|
13174
|
+
this.writeError = error;
|
|
13175
|
+
this.requestExit();
|
|
13176
|
+
}
|
|
12909
13177
|
};
|
|
12910
13178
|
const onEnd = () => {
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
13179
|
+
try {
|
|
13180
|
+
this.#applyActions(this.#decoder.flush());
|
|
13181
|
+
this.#applyEof();
|
|
13182
|
+
this.drain();
|
|
13183
|
+
} catch (error) {
|
|
13184
|
+
this.writeError = error;
|
|
13185
|
+
this.requestExit();
|
|
13186
|
+
}
|
|
13187
|
+
};
|
|
13188
|
+
const onError = (error) => {
|
|
13189
|
+
this.writeError = error;
|
|
13190
|
+
this.requestExit();
|
|
12914
13191
|
};
|
|
12915
13192
|
input?.on("data", onData);
|
|
12916
13193
|
input?.on("end", onEnd);
|
|
13194
|
+
input?.addListener?.("error", onError);
|
|
12917
13195
|
this.#wakeupEnabled = true;
|
|
12918
13196
|
try {
|
|
12919
13197
|
input?.resume?.();
|
|
@@ -12926,7 +13204,13 @@ var InteractiveTerminalLoop = class {
|
|
|
12926
13204
|
this.#wakeupEnabled = false;
|
|
12927
13205
|
input?.off?.("data", onData);
|
|
12928
13206
|
input?.off?.("end", onEnd);
|
|
12929
|
-
|
|
13207
|
+
try {
|
|
13208
|
+
this.#stopTerminalModes();
|
|
13209
|
+
await drainTerminalInput(input);
|
|
13210
|
+
} finally {
|
|
13211
|
+
input?.pause?.();
|
|
13212
|
+
input?.removeListener?.("error", onError);
|
|
13213
|
+
}
|
|
12930
13214
|
}
|
|
12931
13215
|
} catch (error) {
|
|
12932
13216
|
this.writeError = error;
|
|
@@ -12998,11 +13282,21 @@ var InteractiveTerminalLoop = class {
|
|
|
12998
13282
|
if (this.#escapeTimer !== null) {
|
|
12999
13283
|
clearTimeout(this.#escapeTimer);
|
|
13000
13284
|
}
|
|
13285
|
+
const timeout = inputTimeout(this.#decoder.pendingKind?.() ?? "sequence");
|
|
13286
|
+
if (timeout === null) {
|
|
13287
|
+
this.#escapeTimer = null;
|
|
13288
|
+
return;
|
|
13289
|
+
}
|
|
13001
13290
|
this.#escapeTimer = setTimeout(() => {
|
|
13002
13291
|
this.#escapeTimer = null;
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13292
|
+
try {
|
|
13293
|
+
this.#applyActions(this.#decoder.flush());
|
|
13294
|
+
this.drain();
|
|
13295
|
+
} catch (error) {
|
|
13296
|
+
this.writeError = error;
|
|
13297
|
+
this.requestExit();
|
|
13298
|
+
}
|
|
13299
|
+
}, timeout);
|
|
13006
13300
|
}
|
|
13007
13301
|
/**
|
|
13008
13302
|
* Production wakeup: while run() is active, queued work is rendered on the
|
|
@@ -13017,11 +13311,26 @@ var InteractiveTerminalLoop = class {
|
|
|
13017
13311
|
this.#wakeupScheduled = true;
|
|
13018
13312
|
setImmediate(() => {
|
|
13019
13313
|
this.#wakeupScheduled = false;
|
|
13020
|
-
this
|
|
13314
|
+
if (this.#closed || this.#renderTimer !== null)
|
|
13315
|
+
return;
|
|
13316
|
+
const delay2 = Math.max(0, 16 - (performance.now() - this.#lastRenderAt));
|
|
13317
|
+
this.#renderTimer = setTimeout(() => {
|
|
13318
|
+
this.#renderTimer = null;
|
|
13319
|
+
if (!this.#closed)
|
|
13320
|
+
this.drain();
|
|
13321
|
+
}, delay2);
|
|
13021
13322
|
});
|
|
13022
13323
|
}
|
|
13023
13324
|
#drainWork() {
|
|
13024
13325
|
let changed = false;
|
|
13326
|
+
let budget = 128;
|
|
13327
|
+
for (let index = this.#work.length - 1; index >= budget; index--) {
|
|
13328
|
+
if (this.#work[index]?.type === "input") {
|
|
13329
|
+
budget = index + 1;
|
|
13330
|
+
break;
|
|
13331
|
+
}
|
|
13332
|
+
}
|
|
13333
|
+
let processed = 0;
|
|
13025
13334
|
let item = this.#work.shift();
|
|
13026
13335
|
while (item !== void 0) {
|
|
13027
13336
|
if (item.type === "input") {
|
|
@@ -13046,19 +13355,27 @@ var InteractiveTerminalLoop = class {
|
|
|
13046
13355
|
this.#ui.applyProjectedEvent(item.event);
|
|
13047
13356
|
changed = true;
|
|
13048
13357
|
}
|
|
13358
|
+
processed++;
|
|
13359
|
+
if (this.#wakeupEnabled && processed >= budget && this.#work.length > 0) {
|
|
13360
|
+
this.#scheduleWakeup();
|
|
13361
|
+
break;
|
|
13362
|
+
}
|
|
13049
13363
|
item = this.#work.shift();
|
|
13050
13364
|
}
|
|
13051
13365
|
return changed;
|
|
13052
13366
|
}
|
|
13053
13367
|
#render() {
|
|
13054
13368
|
this.#needsRender = false;
|
|
13369
|
+
this.#lastRenderAt = performance.now();
|
|
13055
13370
|
try {
|
|
13056
|
-
this.#
|
|
13057
|
-
|
|
13371
|
+
const size = this.#driver.getSize();
|
|
13372
|
+
this.#overlays.setViewport(Math.max(1, size.columns - 1), Math.max(1, size.rows));
|
|
13373
|
+
this.#renderer.render(this.#overlays.composite(this.#ui.buildFrame({
|
|
13374
|
+
width: Math.max(1, size.columns),
|
|
13058
13375
|
editor: this.#editor
|
|
13059
|
-
}));
|
|
13376
|
+
}), this.#ui.theme));
|
|
13060
13377
|
} catch (error) {
|
|
13061
|
-
this.writeError = error;
|
|
13378
|
+
this.writeError = recordRenderFailure(error);
|
|
13062
13379
|
this.requestExit();
|
|
13063
13380
|
}
|
|
13064
13381
|
}
|
|
@@ -13276,7 +13593,6 @@ var InteractiveTerminalLoop = class {
|
|
|
13276
13593
|
this.#work = retained;
|
|
13277
13594
|
}
|
|
13278
13595
|
};
|
|
13279
|
-
_a = InteractiveTerminalLoop;
|
|
13280
13596
|
var FALLBACK_MARKDOWN_WIDTH = 80;
|
|
13281
13597
|
function resolveFallbackMarkdownWidth() {
|
|
13282
13598
|
const columns = process.stdout?.columns;
|
|
@@ -13572,7 +13888,7 @@ var TerminalUI = class {
|
|
|
13572
13888
|
#buildHistoryFrameParts(width) {
|
|
13573
13889
|
const rendered = this.#transcriptView.renderWithMetadata({ width, theme: this.theme });
|
|
13574
13890
|
return {
|
|
13575
|
-
lines: this.#lineCompiler.compile(rendered.lines, Math.max(
|
|
13891
|
+
lines: this.#lineCompiler.compile(rendered.lines, Math.max(1, width), this.theme),
|
|
13576
13892
|
activeStart: rendered.activeStart
|
|
13577
13893
|
};
|
|
13578
13894
|
}
|
|
@@ -13856,6 +14172,7 @@ var StdTerminalDriver = class {
|
|
|
13856
14172
|
return;
|
|
13857
14173
|
}
|
|
13858
14174
|
this.#restoreRawMode ??= enterTerminalRawMode(process.stdin);
|
|
14175
|
+
refreshTerminalDimensions();
|
|
13859
14176
|
}
|
|
13860
14177
|
write(data) {
|
|
13861
14178
|
if (this.#debugLogPath !== null) {
|
|
@@ -14267,7 +14584,7 @@ function resolveBashPath(options = {}) {
|
|
|
14267
14584
|
// ../../packages/shell/bash-local/dist/bash-output.js
|
|
14268
14585
|
import { mkdir as mkdir2, mkdtemp, open, readdir, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
14269
14586
|
import { homedir as homedir3 } from "node:os";
|
|
14270
|
-
import { join as
|
|
14587
|
+
import { join as join9, resolve as resolve3 } from "node:path";
|
|
14271
14588
|
var BASH_OUTPUT_MAX_BYTES = 50 * 1024;
|
|
14272
14589
|
var BASH_OUTPUT_MAX_LINES = 2e3;
|
|
14273
14590
|
var OUTPUT_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
@@ -14317,7 +14634,7 @@ var BashOutput = class {
|
|
|
14317
14634
|
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
14318
14635
|
throw new RangeError("Bash output limits must be positive integers");
|
|
14319
14636
|
}
|
|
14320
|
-
this.#directory = resolve3(options.outputDirectory ??
|
|
14637
|
+
this.#directory = resolve3(options.outputDirectory ?? join9(homedir3(), ".laohuang", "tool-output"));
|
|
14321
14638
|
}
|
|
14322
14639
|
append(stream, text2) {
|
|
14323
14640
|
const next = this.#pending.then(() => this.#append(stream, text2));
|
|
@@ -14354,10 +14671,10 @@ var BashOutput = class {
|
|
|
14354
14671
|
try {
|
|
14355
14672
|
await mkdir2(this.#directory, { recursive: true, mode: 448 });
|
|
14356
14673
|
await this.#removeExpired();
|
|
14357
|
-
this.#archiveDirectory = await mkdtemp(
|
|
14674
|
+
this.#archiveDirectory = await mkdtemp(join9(this.#directory, "bash-"));
|
|
14358
14675
|
const files = {
|
|
14359
|
-
stdout:
|
|
14360
|
-
stderr:
|
|
14676
|
+
stdout: join9(this.#archiveDirectory, "stdout.log"),
|
|
14677
|
+
stderr: join9(this.#archiveDirectory, "stderr.log")
|
|
14361
14678
|
};
|
|
14362
14679
|
for (const stream of ["stdout", "stderr"])
|
|
14363
14680
|
this.#handles[stream] = await open(files[stream], "wx", 384);
|
|
@@ -14396,7 +14713,7 @@ var BashOutput = class {
|
|
|
14396
14713
|
}
|
|
14397
14714
|
if (this.#archiveDirectory !== null) {
|
|
14398
14715
|
try {
|
|
14399
|
-
await writeFile2(
|
|
14716
|
+
await writeFile2(join9(this.#archiveDirectory, "completed"), "", { mode: 384 });
|
|
14400
14717
|
} catch {
|
|
14401
14718
|
}
|
|
14402
14719
|
}
|
|
@@ -14405,9 +14722,9 @@ var BashOutput = class {
|
|
|
14405
14722
|
for (const entry of await readdir(this.#directory, { withFileTypes: true })) {
|
|
14406
14723
|
if (!entry.isDirectory() || !entry.name.startsWith("bash-"))
|
|
14407
14724
|
continue;
|
|
14408
|
-
const directory =
|
|
14725
|
+
const directory = join9(this.#directory, entry.name);
|
|
14409
14726
|
try {
|
|
14410
|
-
if (Date.now() - (await stat(
|
|
14727
|
+
if (Date.now() - (await stat(join9(directory, "completed"))).mtimeMs > OUTPUT_RETENTION_MS) {
|
|
14411
14728
|
await rm(directory, { recursive: true, force: true });
|
|
14412
14729
|
}
|
|
14413
14730
|
} catch {
|
|
@@ -16972,7 +17289,7 @@ var SessionController = class {
|
|
|
16972
17289
|
|
|
16973
17290
|
// src/create-mcp-runtime.ts
|
|
16974
17291
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
16975
|
-
import { dirname as dirname6, join as
|
|
17292
|
+
import { dirname as dirname6, join as join11, resolve as resolve6 } from "node:path";
|
|
16976
17293
|
|
|
16977
17294
|
// ../../packages/core/mcp/dist/config.js
|
|
16978
17295
|
import { resolve as resolve4 } from "node:path";
|
|
@@ -17243,7 +17560,7 @@ import { createHash as createHash6 } from "node:crypto";
|
|
|
17243
17560
|
// ../../packages/core/mcp/dist/output.js
|
|
17244
17561
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
17245
17562
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
17246
|
-
import { join as
|
|
17563
|
+
import { join as join10 } from "node:path";
|
|
17247
17564
|
function bounded(result, limit) {
|
|
17248
17565
|
if (Buffer.byteLength(JSON.stringify(result), "utf8") <= limit)
|
|
17249
17566
|
return result;
|
|
@@ -17304,13 +17621,13 @@ async function adaptMcpResult(result, options) {
|
|
|
17304
17621
|
if (!oversized && media.length === 0)
|
|
17305
17622
|
return preview;
|
|
17306
17623
|
try {
|
|
17307
|
-
const directory =
|
|
17624
|
+
const directory = join10(options.artifactRoot, randomUUID11());
|
|
17308
17625
|
await mkdir3(directory, { recursive: true, mode: 448 });
|
|
17309
|
-
const path5 =
|
|
17626
|
+
const path5 = join10(directory, "result.json");
|
|
17310
17627
|
await writeFile3(path5, JSON.stringify(business), { mode: 384, flag: "wx" });
|
|
17311
17628
|
const attachments = [];
|
|
17312
17629
|
for (const [index, item] of media.entries()) {
|
|
17313
|
-
const path6 =
|
|
17630
|
+
const path6 = join10(directory, `attachment-${index}.bin`);
|
|
17314
17631
|
const decoded = Buffer.from(item.data, "base64");
|
|
17315
17632
|
if (decoded.toString("base64").replace(/=+$/, "") !== item.data.replace(/=+$/, ""))
|
|
17316
17633
|
throw new Error("Invalid base64 attachment");
|
|
@@ -18287,7 +18604,7 @@ var ConnectionManager = class {
|
|
|
18287
18604
|
// src/create-mcp-runtime.ts
|
|
18288
18605
|
async function createMcpRuntime(options) {
|
|
18289
18606
|
const directory = dirname6(resolve6(options.configPath));
|
|
18290
|
-
const paths = [.../* @__PURE__ */ new Set([
|
|
18607
|
+
const paths = [.../* @__PURE__ */ new Set([join11(directory, "mcp.json"), resolve6(options.projectRoot, ".laohuang/mcp.json")])];
|
|
18291
18608
|
const readSources = async (reload) => {
|
|
18292
18609
|
const sources = [];
|
|
18293
18610
|
let invalid2 = false;
|
|
@@ -18317,8 +18634,8 @@ ${url}`, tone: "info" });
|
|
|
18317
18634
|
projectRoot: options.projectRoot,
|
|
18318
18635
|
version: options.version,
|
|
18319
18636
|
env: options.env,
|
|
18320
|
-
credentials: new McpCredentialFileStore(
|
|
18321
|
-
artifactRoot:
|
|
18637
|
+
credentials: new McpCredentialFileStore(join11(directory, "mcp-credentials")),
|
|
18638
|
+
artifactRoot: join11(directory, "mcp-artifacts", randomUUID12()),
|
|
18322
18639
|
onAuthorization: ({ serverId, url }) => showAuthorization(serverId, url),
|
|
18323
18640
|
onLoginState: (active) => {
|
|
18324
18641
|
if (active) process.on("SIGINT", cancel);
|
|
@@ -18902,12 +19219,12 @@ async function runTerminalUi(ui, driver, onSubmit) {
|
|
|
18902
19219
|
// src/update-installation.ts
|
|
18903
19220
|
import { spawn as spawn2 } from "node:child_process";
|
|
18904
19221
|
import { lstat, readFile as readFile3, realpath as realpath2 } from "node:fs/promises";
|
|
18905
|
-
import { basename as basename6, delimiter, dirname as dirname7, isAbsolute, join as
|
|
19222
|
+
import { basename as basename6, delimiter, dirname as dirname7, isAbsolute, join as join13, relative, resolve as resolve7, sep, win32 as win324 } from "node:path";
|
|
18906
19223
|
|
|
18907
19224
|
// src/update.ts
|
|
18908
19225
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
18909
19226
|
import { open as open2, readFile as readFile2, realpath, unlink as unlink3 } from "node:fs/promises";
|
|
18910
|
-
import { join as
|
|
19227
|
+
import { join as join12 } from "node:path";
|
|
18911
19228
|
function compareStableVersions(left, right) {
|
|
18912
19229
|
const parse = (value) => {
|
|
18913
19230
|
if (!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value) || value.includes("\n")) {
|
|
@@ -18933,7 +19250,7 @@ var defaultLockIO = {
|
|
|
18933
19250
|
};
|
|
18934
19251
|
async function installedVersion(installation) {
|
|
18935
19252
|
if (await realpath(installation.packageRoot) !== installation.packageRoot) throw new Error("Installation target changed");
|
|
18936
|
-
const value = JSON.parse(await readFile2(
|
|
19253
|
+
const value = JSON.parse(await readFile2(join12(installation.packageRoot, "package.json"), "utf8"));
|
|
18937
19254
|
if (typeof value !== "object" || value === null || !("name" in value) || value.name !== "laohuang" || !("version" in value) || typeof value.version !== "string") {
|
|
18938
19255
|
throw new Error("Installed laohuang package is missing or invalid");
|
|
18939
19256
|
}
|
|
@@ -19133,9 +19450,9 @@ function createNpmRunner(cliPath, environ, options = {}) {
|
|
|
19133
19450
|
};
|
|
19134
19451
|
}
|
|
19135
19452
|
async function npmCandidates(environ) {
|
|
19136
|
-
const paths = [environ.npm_execpath,
|
|
19453
|
+
const paths = [environ.npm_execpath, join13(dirname7(process.execPath), "node_modules/npm/bin/npm-cli.js"), join13(dirname7(process.execPath), "../lib/node_modules/npm/bin/npm-cli.js")];
|
|
19137
19454
|
for (const directory of (environ.PATH ?? environ.Path ?? "").split(delimiter).filter(Boolean)) {
|
|
19138
|
-
paths.push(
|
|
19455
|
+
paths.push(join13(directory, "npm"), join13(directory, "node_modules/npm/bin/npm-cli.js"));
|
|
19139
19456
|
}
|
|
19140
19457
|
const result = /* @__PURE__ */ new Set();
|
|
19141
19458
|
for (const path5 of paths) {
|
|
@@ -19143,7 +19460,7 @@ async function npmCandidates(environ) {
|
|
|
19143
19460
|
try {
|
|
19144
19461
|
const actual = await realpath2(path5);
|
|
19145
19462
|
if (basename6(actual) !== "npm-cli.js") continue;
|
|
19146
|
-
const manifest = await json(
|
|
19463
|
+
const manifest = await json(join13(dirname7(actual), "../package.json"));
|
|
19147
19464
|
if (manifest.name === "npm") result.add(actual);
|
|
19148
19465
|
} catch {
|
|
19149
19466
|
}
|
|
@@ -19160,8 +19477,8 @@ async function resolveNpmInstallation(entryPath, environ, options = {}) {
|
|
|
19160
19477
|
let packageRoot = dirname7(entry);
|
|
19161
19478
|
let manifest = {};
|
|
19162
19479
|
while (true) {
|
|
19163
|
-
if (await exists(
|
|
19164
|
-
manifest = await json(
|
|
19480
|
+
if (await exists(join13(packageRoot, "package.json"))) {
|
|
19481
|
+
manifest = await json(join13(packageRoot, "package.json"));
|
|
19165
19482
|
break;
|
|
19166
19483
|
}
|
|
19167
19484
|
const parent = dirname7(packageRoot);
|
|
@@ -19190,7 +19507,7 @@ async function resolveNpmInstallation(entryPath, environ, options = {}) {
|
|
|
19190
19507
|
if (checked.code !== 0 || await realpath2(checked.stdout.trim()) !== dirname7(packageRoot)) continue;
|
|
19191
19508
|
globals.push({ packageRoot, installedVersion: manifest.version, npm: {
|
|
19192
19509
|
run: (args, runOptions) => npm.run(args[0] === "view" ? [...args, "--global", "--prefix", prefix] : args, runOptions)
|
|
19193
|
-
}, workingDirectory: prefix, installArgs: ["--global", "--prefix", prefix], lockPath:
|
|
19510
|
+
}, workingDirectory: prefix, installArgs: ["--global", "--prefix", prefix], lockPath: join13(dirname7(packageRoot), ".laohuang-update.lock") });
|
|
19194
19511
|
} catch {
|
|
19195
19512
|
options.signal?.throwIfAborted();
|
|
19196
19513
|
}
|
|
@@ -19202,12 +19519,12 @@ async function resolveNpmInstallation(entryPath, environ, options = {}) {
|
|
|
19202
19519
|
const owners = [];
|
|
19203
19520
|
for (let root = dirname7(dirname7(packageRoot)); ; root = dirname7(root)) {
|
|
19204
19521
|
options.signal?.throwIfAborted();
|
|
19205
|
-
const lockPath =
|
|
19522
|
+
const lockPath = join13(root, "package-lock.json");
|
|
19206
19523
|
if (await exists(lockPath)) {
|
|
19207
19524
|
for (const other of ["pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb", "npm-shrinkwrap.json"]) {
|
|
19208
|
-
if (await exists(
|
|
19525
|
+
if (await exists(join13(root, other))) throw new Error("Ambiguous or unsupported package manager ownership");
|
|
19209
19526
|
}
|
|
19210
|
-
const rootManifest = await json(
|
|
19527
|
+
const rootManifest = await json(join13(root, "package.json"));
|
|
19211
19528
|
if (typeof rootManifest.packageManager === "string" && !rootManifest.packageManager.startsWith("npm@")) throw new Error("Installation belongs to another package manager");
|
|
19212
19529
|
const lock = await json(lockPath);
|
|
19213
19530
|
const packages = object(lock.packages);
|
|
@@ -19239,14 +19556,14 @@ async function resolveNpmInstallation(entryPath, environ, options = {}) {
|
|
|
19239
19556
|
}
|
|
19240
19557
|
const owner = await realpath2(resolve7(root, key));
|
|
19241
19558
|
if (!inside(root, owner)) continue;
|
|
19242
|
-
const declaration = await json(
|
|
19559
|
+
const declaration = await json(join13(owner, "package.json"));
|
|
19243
19560
|
for (const bucket of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
|
19244
19561
|
const range = object(declaration[bucket]).laohuang;
|
|
19245
19562
|
if (typeof range !== "string") continue;
|
|
19246
19563
|
let resolvedPackage;
|
|
19247
19564
|
for (let directory = owner; inside(root, directory); directory = dirname7(directory)) {
|
|
19248
|
-
if (await exists(
|
|
19249
|
-
resolvedPackage = await realpath2(
|
|
19565
|
+
if (await exists(join13(directory, "node_modules/laohuang"))) {
|
|
19566
|
+
resolvedPackage = await realpath2(join13(directory, "node_modules/laohuang"));
|
|
19250
19567
|
break;
|
|
19251
19568
|
}
|
|
19252
19569
|
if (directory === root) break;
|
|
@@ -19263,7 +19580,7 @@ async function resolveNpmInstallation(entryPath, environ, options = {}) {
|
|
|
19263
19580
|
},
|
|
19264
19581
|
workingDirectory: root,
|
|
19265
19582
|
installArgs: ["--global=false", "--prefix", root, "--package-lock=true", "--save=true", "--save-peer=false", "--save-dev=false", "--save-optional=false", "--save-prod=false", bucket === "devDependencies" ? "--save-dev" : bucket === "optionalDependencies" ? "--save-optional" : "--save-prod", ...bucket === "devDependencies" ? ["--include=dev"] : [], .../^[~^]/.test(range) ? ["--save-exact=false", `--save-prefix=${range[0]}`] : ["--save-exact"], ...key ? ["--workspace", key, "--include-workspace-root=false"] : ["--workspaces=false"]],
|
|
19266
|
-
lockPath:
|
|
19583
|
+
lockPath: join13(root, ".laohuang-update.lock")
|
|
19267
19584
|
});
|
|
19268
19585
|
}
|
|
19269
19586
|
}
|
|
@@ -19517,10 +19834,10 @@ async function main(argv, options = {}) {
|
|
|
19517
19834
|
const configPath = options.configPath ?? defaultConfigPath(environ);
|
|
19518
19835
|
const manager = new ConfigManager(configPath);
|
|
19519
19836
|
const credentials = new CredentialStore(
|
|
19520
|
-
options.credentialsPath ??
|
|
19837
|
+
options.credentialsPath ?? join14(dirname8(configPath), "credentials.json")
|
|
19521
19838
|
);
|
|
19522
19839
|
const modelCatalogStore = new ModelCatalogStore(
|
|
19523
|
-
options.modelsPath ??
|
|
19840
|
+
options.modelsPath ?? join14(dirname8(configPath), "models.json")
|
|
19524
19841
|
);
|
|
19525
19842
|
const modelPlatform = await createPiAiPlatform({
|
|
19526
19843
|
credentials,
|
|
@@ -20143,7 +20460,7 @@ async function main(argv, options = {}) {
|
|
|
20143
20460
|
}
|
|
20144
20461
|
}
|
|
20145
20462
|
function defaultSessionsRoot(environ) {
|
|
20146
|
-
return
|
|
20463
|
+
return join14(getHomeDirectory({ env: environ }), ".laohuang", "sessions");
|
|
20147
20464
|
}
|
|
20148
20465
|
function defaultContextPolicy() {
|
|
20149
20466
|
return {
|