terminal-bridge-setup 2.9.0 → 2.9.1
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/files/proxy/server.js
CHANGED
|
@@ -537,19 +537,32 @@ function cleanOutput(text, cmd) {
|
|
|
537
537
|
.replace(/\r\n?/g, "\n");
|
|
538
538
|
|
|
539
539
|
// 删除 prompt 行(命令回显行 = prompt + 命令文本,可能粘有 kitty 重绘碎片):
|
|
540
|
-
// - 红帽系:[user@host /cwd]# ——
|
|
541
|
-
//
|
|
542
|
-
//
|
|
540
|
+
// - 红帽系:[user@host /cwd]# —— user/host 段各限长 64(真实 prompt 远短于此)。
|
|
541
|
+
// 不限长时的实测反例(Case A):head -c 600 截断的 JSON 无闭合 ],
|
|
542
|
+
// "data":[ 的 [ 落在前缀窗口内,[^\]]+ 跨过整段 JSON 匹配到 prompt 的 @…]
|
|
543
|
+
// → 647 字符合并行整行被误删。长度约束让这种跨吞匹配失败。
|
|
544
|
+
// - Ubuntu/Debian:user@host:~/path$ —— 同样限长
|
|
543
545
|
// - Arthas:行尾 > 且行短(≤60 字符)
|
|
544
546
|
// 前缀窗口 40 字符:正常 prompt 行 prompt 就在行首;碎片通常几到几十字符。
|
|
545
547
|
out = out.split("\n").filter(line => {
|
|
546
|
-
if (/^.{0,40}\[[^\]\n]
|
|
547
|
-
if (/^.{0,40}[\w.-]
|
|
548
|
+
if (/^.{0,40}\[[^\]\n]{1,64}@[^\]\n]{1,64}\]\s*[#$]/.test(line)) return false;
|
|
549
|
+
if (/^.{0,40}[\w.-]{1,64}@[\w.-]{1,64}:[^\s]{0,128}[$#]/.test(line)) return false;
|
|
548
550
|
// Arthas / 通用 REPL prompt:行尾 > (允许前面有 arthas@xxx 等前缀)
|
|
549
551
|
if (/>\s*$/.test(line) && line.trim().length <= 60) return false;
|
|
550
552
|
return true;
|
|
551
553
|
}).join("\n");
|
|
552
554
|
|
|
555
|
+
// 行尾 prompt 后缀剥离:无尾换行的输出(head -c N 截断)会与后续 prompt
|
|
556
|
+
// 合并成同一物理行。上面的整行过滤(带前缀窗口)会放过这种合并行——内容
|
|
557
|
+
// 保住了,但 prompt 碎片粘在输出尾巴上(如 JSON 尾 + [root@host dir]#),
|
|
558
|
+
// 污染 Agent 的后续解析。这里只剥离行尾的 prompt 形态后缀,内容原样保留。
|
|
559
|
+
out = out.split("\n").map(line => {
|
|
560
|
+
if (line.length <= 100) return line; // 短行已由整行过滤处理,避免误伤
|
|
561
|
+
return line
|
|
562
|
+
.replace(/\[[^\]\n]{1,64}@[^\]\n]{1,64}\]\s*[#$]\s*$/, "") // 红帽系后缀
|
|
563
|
+
.replace(/[\w.-]{1,64}@[\w.-]{1,64}:[^\s]{0,128}[$#]\s*$/, ""); // Ubuntu 后缀
|
|
564
|
+
}).join("\n");
|
|
565
|
+
|
|
553
566
|
// 删除 koko 控制消息:koko 偶尔在终端流里发送 JSON 控制消息
|
|
554
567
|
// (TERMINAL_RESIZE、PING 等),特征是以 {"id": 开头的 JSON 行(可能前面带 # )
|
|
555
568
|
out = out.split("\n").filter(line => {
|
|
@@ -593,26 +606,35 @@ function cleanOutput(text, cmd) {
|
|
|
593
606
|
}
|
|
594
607
|
|
|
595
608
|
// ===================== 输出兜底(问题 1 的安全网)=====================
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
//
|
|
609
|
+
// 两层防御:
|
|
610
|
+
// 1. 清理后为空 + 原始内容 ≥512 字符 → 返回截断原始内容 + warning
|
|
611
|
+
// 2. 清理损失率 >80%(原始 ≥512 字符但清理后 <20%)→ 保留清理结果,
|
|
612
|
+
// 但附加 warning + 原始内容截断——任何未来的 filter 误杀都不再静默
|
|
613
|
+
// (Case A 教训:REDHAT 正则曾跨吞 647 字节合并行,靠这层兜底可暴露)
|
|
599
614
|
const RAW_FALLBACK_THRESHOLD = 512; // 原始内容低于此值视为真无输出
|
|
600
615
|
const RAW_FALLBACK_LIMIT = 4000; // 兜底输出截断长度
|
|
601
616
|
|
|
602
617
|
function finalizeOutput(entry) {
|
|
603
|
-
const
|
|
604
|
-
|
|
618
|
+
const echoCmd = entry.echoCmd != null ? entry.echoCmd : entry.cmd;
|
|
619
|
+
const cleaned = cleanOutput(entry.buffer, echoCmd);
|
|
605
620
|
|
|
606
621
|
const raw = stripAnsi(entry.buffer)
|
|
607
622
|
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, " ")
|
|
608
623
|
.replace(/\r\n?/g, "\n")
|
|
609
624
|
.trim();
|
|
610
|
-
if (raw.length < RAW_FALLBACK_THRESHOLD) return
|
|
625
|
+
if (raw.length < RAW_FALLBACK_THRESHOLD) return cleaned;
|
|
626
|
+
|
|
627
|
+
const truncated = raw.length > RAW_FALLBACK_LIMIT
|
|
628
|
+
? raw.slice(0, RAW_FALLBACK_LIMIT) + "\n...[truncated]"
|
|
629
|
+
: raw;
|
|
611
630
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
631
|
+
if (cleaned.length === 0) {
|
|
632
|
+
return truncated + `\n[warning] output filtered to empty by cleaner; raw ${raw.length} chars shown]`;
|
|
633
|
+
}
|
|
634
|
+
if (cleaned.length < raw.length * 0.2) {
|
|
635
|
+
return cleaned + `\n[warning] cleaner dropped ${(100 - Math.round(cleaned.length / raw.length * 100))}% of output; raw tail:\n${truncated}`;
|
|
636
|
+
}
|
|
637
|
+
return cleaned;
|
|
616
638
|
}
|
|
617
639
|
|
|
618
640
|
// ===================== WebSocket 服务 =====================
|
|
@@ -63,9 +63,12 @@
|
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
- `output`:prompt 锚点出现前的所有 recv 帧拼接,已去 ANSI、`\r\n`→`\n`、
|
|
66
|
-
控制字符(NUL 等)替换为空格、删 prompt
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
控制字符(NUL 等)替换为空格、删 prompt 行和命令回显行(折行感知)、
|
|
67
|
+
剥离行尾 prompt 后缀(无尾换行输出与 prompt 合并形态)、首尾 trim。
|
|
68
|
+
prompt 段识别带长度约束(user/host 各 ≤64 字符),防止截断 JSON 的 `[`
|
|
69
|
+
被当作 prompt 起点跨吞整行(Case A 根因)。
|
|
70
|
+
**双层兜底**:清理后为空或清理损失率 >80%(原始 ≥512 字符)时,附加
|
|
71
|
+
`[warning]` + 截断原始内容——绝不静默丢弃大段输出。
|
|
69
72
|
- `unterminated-quote`:命令含未闭合引号,远端 shell 卡在 PS2 续行(`>` 提示)。
|
|
70
73
|
代理检测到后 ~400ms 快速失败并自动 Ctrl+C 退出续行(终端可继续用),
|
|
71
74
|
`suggest` 会指向 base64 通道。
|
package/package.json
CHANGED