@xiaoqiong0v0/opencode-ssh-tool 0.4.0 → 0.5.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/README.md +22 -22
- package/dist/base-session.d.ts +128 -0
- package/dist/base-session.d.ts.map +1 -0
- package/dist/base-session.js +414 -0
- package/dist/base-session.js.map +1 -0
- package/dist/constants.d.ts +27 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +28 -3
- package/dist/constants.js.map +1 -1
- package/dist/history.d.ts +14 -5
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +25 -9
- package/dist/history.js.map +1 -1
- package/dist/i18n.d.ts +75 -227
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +65 -211
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83 -31
- package/dist/index.js.map +1 -1
- package/dist/last-match.d.ts +17 -0
- package/dist/last-match.d.ts.map +1 -0
- package/dist/last-match.js +63 -0
- package/dist/last-match.js.map +1 -0
- package/dist/local-session.d.ts +9 -91
- package/dist/local-session.d.ts.map +1 -1
- package/dist/local-session.js +46 -308
- package/dist/local-session.js.map +1 -1
- package/dist/log.d.ts +3 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +5 -0
- package/dist/log.js.map +1 -0
- package/dist/server.d.ts +32 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +417 -349
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +15 -108
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +69 -361
- package/dist/session.js.map +1 -1
- package/dist/shell-adapter.d.ts +20 -0
- package/dist/shell-adapter.d.ts.map +1 -0
- package/dist/shell-adapter.js +70 -0
- package/dist/shell-adapter.js.map +1 -0
- package/dist/ssh-auth.d.ts.map +1 -1
- package/dist/ssh-auth.js +1 -2
- package/dist/ssh-auth.js.map +1 -1
- package/dist/utils.d.ts +25 -24
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +279 -45
- package/dist/utils.js.map +1 -1
- package/dist/web/app.css +43 -0
- package/dist/web/app.js +2 -0
- package/dist/web/fonts/CaskaydiaCoveNerdFontMono-Regular.ttf +0 -0
- package/dist/web/index.html +28 -0
- package/package.json +6 -3
package/dist/utils.d.ts
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* 定位命令回显行在原始流中的结束位置(供流式增量定位使用):
|
|
3
|
+
* 丢弃窗口开头到"命令回显行结束"之前的一切内容(提示符、PS1 填充、光标定位噪音均在内)。
|
|
4
|
+
* 命令回显行 = 命令文本首次出现所在行(命令本身可能含 \033 等转义)。
|
|
5
|
+
* @param raw 原始终端流(含 ANSI)
|
|
6
|
+
* @param command 本次执行的命令文本
|
|
7
|
+
* @returns 命令回显结束后的字节偏移;未命中命令文本返回 0(此时应视作输出尚未开始)
|
|
4
8
|
*/
|
|
5
|
-
export declare function
|
|
9
|
+
export declare function extractOutputStart(raw: string, command: string): number;
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* 剥离"提示符 + 命令回显",只保留程序纯输出:
|
|
12
|
+
* shell 提示符(含背景填充、zle 重绘序列)依赖其自身终端屏幕状态,字节流脱离该状态无法忠实还原,
|
|
13
|
+
* 故丢弃窗口开头到"命令回显行结束"之前的一切内容(提示符、PS1 填充、光标定位噪音均在内)。
|
|
14
|
+
* 命令回显行 = 命令文本首次出现所在行(命令本身可能含 \033 等转义)。
|
|
15
|
+
* 命中后切到"命令文本结束处":zsh 下程序输出可能直接粘连在回显尾(无换行),不能按换行截断。
|
|
16
|
+
* @param raw 原始终端流(含 ANSI)
|
|
17
|
+
* @param command 本次执行的命令文本
|
|
18
|
+
* @returns 纯程序输出原始流(保留程序自身的 ANSI 颜色/进度条,供 web TermScreen 与模型 toModelText)
|
|
12
19
|
*/
|
|
13
|
-
export declare function
|
|
20
|
+
export declare function extractOutput(raw: string, command: string): string;
|
|
14
21
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
22
|
+
* 把原始终端流转为给模型看的干净文本:模拟终端屏幕(处理光标移动/清行/覆盖/退格/SGR/OSC),
|
|
23
|
+
* 输出最终屏幕各行文本,再逐行去尾空白并剔除空行。比纯文本正则更鲁棒地处理 PSReadLine
|
|
24
|
+
* 行内重绘、进度条 \r 覆盖等场景。
|
|
25
|
+
* @param raw 原始终端流(含 ANSI)
|
|
26
|
+
* @returns 纯文本输出(供模型消费 / exec 返回值 / read 命令)
|
|
18
27
|
*/
|
|
19
|
-
export declare function
|
|
28
|
+
export declare function toModelText(raw: string): string;
|
|
20
29
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @param s 原始输出(含 ANSI 或已清洗均可)
|
|
25
|
-
* @returns 合并覆盖后的文本(\r\n 正常换行保留)
|
|
26
|
-
*/
|
|
27
|
-
export declare function collapseCarriage(s: string): string;
|
|
28
|
-
/**
|
|
29
|
-
* 剥离尾部 shell 提示符残留(如 "5cb08b77db01:~$ "、"user@host:~/dir$ "、"root@server:/etc#")
|
|
30
|
-
* @param s 清洗后文本
|
|
31
|
-
* @returns 剥离尾部提示符后的文本
|
|
30
|
+
* 末尾空白清理(原为提示符剥离,现仅做清理,不依赖正则匹配具体提示符形状)
|
|
31
|
+
* @param s 文本
|
|
32
|
+
* @returns 清理后文本
|
|
32
33
|
*/
|
|
33
34
|
export declare function stripPrompt(s: string): string;
|
|
34
35
|
/**
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAavE;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/C;AAgJD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAI1C"}
|
package/dist/utils.js
CHANGED
|
@@ -1,63 +1,297 @@
|
|
|
1
|
-
//
|
|
2
|
-
import {
|
|
1
|
+
// 工具函数:命令回显定位、模型文本清理、ANSI 清洗、CR 覆盖合并、完成标记剥离
|
|
2
|
+
import { stripMarkers } from "./shell-adapter.js";
|
|
3
|
+
import { findLastEndOf } from "./last-match.js";
|
|
4
|
+
/** 正则转义文本 */
|
|
5
|
+
const escRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
+
/** 命令回显匹配的宽松字符间隙(ANSI 序列或普通空白/换行,可插在命令字符之间;容忍终端列宽自动换行) */
|
|
7
|
+
const ECHO_WIDE = "(?:\\x1b\\[[0-9;?]*[a-zA-Z]|\\x1b\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)|\\x1b[^\\x1b]|[ \\t\\r\\n])*";
|
|
3
8
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
9
|
+
* 定位命令回显行在原始流中的结束位置(供流式增量定位使用):
|
|
10
|
+
* 丢弃窗口开头到"命令回显行结束"之前的一切内容(提示符、PS1 填充、光标定位噪音均在内)。
|
|
11
|
+
* 命令回显行 = 命令文本首次出现所在行(命令本身可能含 \033 等转义)。
|
|
12
|
+
* @param raw 原始终端流(含 ANSI)
|
|
13
|
+
* @param command 本次执行的命令文本
|
|
14
|
+
* @returns 命令回显结束后的字节偏移;未命中命令文本返回 0(此时应视作输出尚未开始)
|
|
6
15
|
*/
|
|
7
|
-
export function
|
|
8
|
-
|
|
16
|
+
export function extractOutputStart(raw, command) {
|
|
17
|
+
const cmd = command.trim();
|
|
18
|
+
if (!cmd)
|
|
19
|
+
return 0;
|
|
20
|
+
// 单条宽松正则一次性匹配命令回显(命令文本 + 字符间 ANSI 间隙):
|
|
21
|
+
// 1) 字符间容忍 ANSI 间隙(WIDE)2) 命令字面 \033 回显可能变真实 ESC(二选一)
|
|
22
|
+
const norm = cmd.replace(/\\033/gi, "\x1b");
|
|
23
|
+
const frags = [...norm].map((c) => (c === "\x1b" ? "(?:\\x1b|\\\\033)" : escRe(c)));
|
|
24
|
+
// 要求命令文本(及尾部 ANSI 重置序列)后紧跟行尾(\r?\n 或串尾),避免子 shell 输出内命令字(如 zsh: not found)误匹配
|
|
25
|
+
const TAIL_ANSI = "(?:\\x1b\\[[0-9;?]*[a-zA-Z]|\\x1b\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)|\\x1b[^\\x1b])*";
|
|
26
|
+
const re = new RegExp(frags.join(ECHO_WIDE) + TAIL_ANSI + "(?=\\r?\\n|$)", "g");
|
|
27
|
+
// 取最后一次匹配:备屏退出(如 cmatrix)会重放主屏历史,其中含旧命令回显,
|
|
28
|
+
// 只有最后一次出现的回显之后才是本次命令的真实输出
|
|
29
|
+
return findLastEndOf(re, raw);
|
|
9
30
|
}
|
|
10
31
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
32
|
+
* 剥离"提示符 + 命令回显",只保留程序纯输出:
|
|
33
|
+
* shell 提示符(含背景填充、zle 重绘序列)依赖其自身终端屏幕状态,字节流脱离该状态无法忠实还原,
|
|
34
|
+
* 故丢弃窗口开头到"命令回显行结束"之前的一切内容(提示符、PS1 填充、光标定位噪音均在内)。
|
|
35
|
+
* 命令回显行 = 命令文本首次出现所在行(命令本身可能含 \033 等转义)。
|
|
36
|
+
* 命中后切到"命令文本结束处":zsh 下程序输出可能直接粘连在回显尾(无换行),不能按换行截断。
|
|
37
|
+
* @param raw 原始终端流(含 ANSI)
|
|
38
|
+
* @param command 本次执行的命令文本
|
|
39
|
+
* @returns 纯程序输出原始流(保留程序自身的 ANSI 颜色/进度条,供 web TermScreen 与模型 toModelText)
|
|
16
40
|
*/
|
|
17
|
-
export function
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
41
|
+
export function extractOutput(raw, command) {
|
|
42
|
+
const end = extractOutputStart(raw, command);
|
|
43
|
+
if (end <= 0)
|
|
44
|
+
return raw;
|
|
45
|
+
return raw.slice(end).replace(/^[\r\n]+/, "");
|
|
21
46
|
}
|
|
22
47
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
48
|
+
* 把原始终端流转为给模型看的干净文本:模拟终端屏幕(处理光标移动/清行/覆盖/退格/SGR/OSC),
|
|
49
|
+
* 输出最终屏幕各行文本,再逐行去尾空白并剔除空行。比纯文本正则更鲁棒地处理 PSReadLine
|
|
50
|
+
* 行内重绘、进度条 \r 覆盖等场景。
|
|
51
|
+
* @param raw 原始终端流(含 ANSI)
|
|
52
|
+
* @returns 纯文本输出(供模型消费 / exec 返回值 / read 命令)
|
|
26
53
|
*/
|
|
27
|
-
export function
|
|
28
|
-
|
|
29
|
-
return
|
|
54
|
+
export function toModelText(raw) {
|
|
55
|
+
const screen = simulateScreen(stripMarkers(raw));
|
|
56
|
+
return screen
|
|
57
|
+
.split(/\r?\n/)
|
|
58
|
+
.map((l) => l.replace(/\r/g, "").trimEnd())
|
|
59
|
+
.filter((l) => l !== "")
|
|
60
|
+
.join("\n");
|
|
30
61
|
}
|
|
31
62
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
* @returns 合并覆盖后的文本(\r\n 正常换行保留)
|
|
63
|
+
* 模拟终端屏幕渲染:处理 ANSI 光标/清行/清屏/退格/覆盖,输出最终各行的文本。
|
|
64
|
+
* 不保留颜色/SGR,仅提取各行已写字符的最右列,确保最终屏幕文本与真实终端显示一致。
|
|
65
|
+
* @param s 原始字节流(含 ANSI、\b、\r 等)
|
|
66
|
+
* @returns 按行拼接的纯文本(行间 \n 分隔,行内保留空格)
|
|
37
67
|
*/
|
|
38
|
-
|
|
39
|
-
//
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
function simulateScreen(s) {
|
|
69
|
+
// 网格:每行 { maxCol: 已写最右列, cols: Map<col, char> }
|
|
70
|
+
const rows = [];
|
|
71
|
+
let r = 0; // 当前行
|
|
72
|
+
let c = 0; // 当前列
|
|
73
|
+
let sr = 0; // 保存的光标行(ESC 7 / CSI s)
|
|
74
|
+
let sc = 0; // 保存的光标列
|
|
75
|
+
let altRows = null; // 备屏保存(CSI ?1049h/l)
|
|
76
|
+
const COLS = 240; // 足够宽
|
|
77
|
+
const row = (i) => {
|
|
78
|
+
while (rows.length <= i)
|
|
79
|
+
rows.push({ maxCol: 0, cols: new Map() });
|
|
80
|
+
return rows[i];
|
|
81
|
+
};
|
|
82
|
+
const put = (ch) => {
|
|
83
|
+
const cur = row(r);
|
|
84
|
+
if (c < COLS) {
|
|
85
|
+
cur.cols.set(c, ch);
|
|
86
|
+
if (c >= cur.maxCol)
|
|
87
|
+
cur.maxCol = c + 1;
|
|
88
|
+
}
|
|
89
|
+
c++;
|
|
90
|
+
};
|
|
91
|
+
let i = 0;
|
|
92
|
+
const n = s.length;
|
|
93
|
+
while (i < n) {
|
|
94
|
+
const ch = s[i];
|
|
95
|
+
if (ch === "\x1b") {
|
|
96
|
+
// OSC: ESC ] ... BEL/ESC\ — 整段丢弃
|
|
97
|
+
if (i + 1 < n && s[i + 1] === "]") {
|
|
98
|
+
let j = i + 2;
|
|
99
|
+
while (j < n && s[j] !== "\x07" && !(s[j] === "\x1b" && j + 1 < n && s[j + 1] === "\\"))
|
|
100
|
+
j++;
|
|
101
|
+
if (j >= n)
|
|
102
|
+
break;
|
|
103
|
+
i = s[j] === "\x07" ? j + 1 : j + 2;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// CSI: ESC [ params... final
|
|
107
|
+
if (i + 1 < n && s[i + 1] === "[") {
|
|
108
|
+
let j = i + 2;
|
|
109
|
+
const start = j;
|
|
110
|
+
while (j < n && !/[A-Za-z@]/.test(s[j]))
|
|
111
|
+
j++;
|
|
112
|
+
if (j >= n)
|
|
113
|
+
break;
|
|
114
|
+
const body = s.slice(start, j);
|
|
115
|
+
const final = s[j];
|
|
116
|
+
const p = (d) => { const v = parseInt(d, 10); return Number.isFinite(v) && v > 0 ? v : 1; };
|
|
117
|
+
const va = (d) => { const v = parseInt(d, 10); return Number.isFinite(v) && v >= 0 ? v : 0; };
|
|
118
|
+
if (final === "m") {
|
|
119
|
+
// SGR:忽略颜色
|
|
120
|
+
}
|
|
121
|
+
else if (final === "A") {
|
|
122
|
+
r = Math.max(0, r - p(body));
|
|
123
|
+
}
|
|
124
|
+
else if (final === "B") {
|
|
125
|
+
r += p(body);
|
|
126
|
+
}
|
|
127
|
+
else if (final === "C") {
|
|
128
|
+
c = Math.min(COLS - 1, c + p(body));
|
|
129
|
+
}
|
|
130
|
+
else if (final === "D") {
|
|
131
|
+
c = Math.max(0, c - p(body));
|
|
132
|
+
}
|
|
133
|
+
else if (final === "H" || final === "f") {
|
|
134
|
+
const m = body.split(";");
|
|
135
|
+
r = Math.max(0, (p(m[0]) - 1));
|
|
136
|
+
c = Math.max(0, (p(m[1]) - 1));
|
|
137
|
+
}
|
|
138
|
+
else if (final === "G" || final.charCodeAt(0) === 96) {
|
|
139
|
+
c = Math.max(0, p(body) - 1);
|
|
140
|
+
}
|
|
141
|
+
else if (final === "d") {
|
|
142
|
+
r = Math.max(0, p(body) - 1);
|
|
143
|
+
}
|
|
144
|
+
else if (final === "s") {
|
|
145
|
+
sr = r;
|
|
146
|
+
sc = c;
|
|
147
|
+
}
|
|
148
|
+
else if (final === "u") {
|
|
149
|
+
r = Math.min(sr, rows.length - 1);
|
|
150
|
+
c = sc;
|
|
151
|
+
}
|
|
152
|
+
else if (final === "h" && body.startsWith("?")) {
|
|
153
|
+
// 私有模式 set:?1049h 进入备屏(保存主屏+光标,清屏)
|
|
154
|
+
if (va(body.slice(1)) === 1049) {
|
|
155
|
+
altRows = rows.map((x) => ({ maxCol: x.maxCol, cols: new Map(x.cols) }));
|
|
156
|
+
sr = r;
|
|
157
|
+
sc = c;
|
|
158
|
+
rows.length = 0;
|
|
159
|
+
r = 0;
|
|
160
|
+
c = 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else if (final === "l" && body.startsWith("?")) {
|
|
164
|
+
// 私有模式 reset:?1049l 退出备屏(恢复主屏+光标)
|
|
165
|
+
if (va(body.slice(1)) === 1049 && altRows) {
|
|
166
|
+
rows.length = 0;
|
|
167
|
+
rows.push(...altRows);
|
|
168
|
+
altRows = null;
|
|
169
|
+
r = Math.min(sr, rows.length - 1);
|
|
170
|
+
c = sc;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (final === "K") {
|
|
174
|
+
const mode = va(body);
|
|
175
|
+
const curRow = row(r);
|
|
176
|
+
if (mode === 2) {
|
|
177
|
+
curRow.cols.clear();
|
|
178
|
+
curRow.maxCol = 0;
|
|
179
|
+
}
|
|
180
|
+
else if (mode === 1) {
|
|
181
|
+
for (let ci = 0; ci <= c; ci++) {
|
|
182
|
+
curRow.cols.delete(ci);
|
|
183
|
+
}
|
|
184
|
+
;
|
|
185
|
+
curRow.maxCol = 0;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
for (let ci = c; ci < COLS; ci++) {
|
|
189
|
+
curRow.cols.delete(ci);
|
|
190
|
+
}
|
|
191
|
+
;
|
|
192
|
+
curRow.maxCol = Math.min(curRow.maxCol, c);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (final === "J") {
|
|
196
|
+
const mode = va(body);
|
|
197
|
+
if (mode === 2 || mode === 3) {
|
|
198
|
+
rows.length = 0;
|
|
199
|
+
r = 0;
|
|
200
|
+
c = 0;
|
|
201
|
+
}
|
|
202
|
+
else if (mode === 1) {
|
|
203
|
+
rows.length = 0;
|
|
204
|
+
r = 0;
|
|
205
|
+
c = 0;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
const cur = row(r);
|
|
209
|
+
for (let ci = c; ci < COLS; ci++)
|
|
210
|
+
cur.cols.delete(ci);
|
|
211
|
+
cur.maxCol = Math.min(cur.maxCol, c);
|
|
212
|
+
rows.length = r + 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// 其余 CSI(滚动/插入/删除等)忽略
|
|
216
|
+
i = j + 1;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// ESC 7 保存光标 / ESC 8 恢复光标
|
|
220
|
+
if (s[i + 1] === "7") {
|
|
221
|
+
sr = r;
|
|
222
|
+
sc = c;
|
|
223
|
+
i += 2;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (s[i + 1] === "8") {
|
|
227
|
+
r = Math.min(sr, rows.length - 1);
|
|
228
|
+
c = sc;
|
|
229
|
+
i += 2;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
// 其他 ESC 序列忽略
|
|
233
|
+
i += 2;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (ch === "\r") {
|
|
237
|
+
c = 0;
|
|
238
|
+
i++;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (ch === "\n") {
|
|
242
|
+
r++;
|
|
243
|
+
c = 0;
|
|
244
|
+
i++;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (ch === "\b") {
|
|
248
|
+
if (c > 0)
|
|
249
|
+
c--;
|
|
250
|
+
i++;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (ch === "\t") {
|
|
254
|
+
const next = (Math.floor(c / 8) + 1) * 8;
|
|
255
|
+
if (next >= COLS) {
|
|
256
|
+
r++;
|
|
257
|
+
c = 0;
|
|
258
|
+
}
|
|
259
|
+
else
|
|
260
|
+
c = next;
|
|
261
|
+
i++;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
// 其他控制字符(\x07 BEL 等)跳过
|
|
265
|
+
if (ch.charCodeAt(0) < 32) {
|
|
266
|
+
i++;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
put(ch);
|
|
270
|
+
i++;
|
|
271
|
+
}
|
|
272
|
+
// 构建输出行
|
|
273
|
+
const lines = [];
|
|
274
|
+
for (let ri = 0; ri < rows.length; ri++) {
|
|
275
|
+
const cur = rows[ri];
|
|
276
|
+
if (cur.maxCol === 0) {
|
|
277
|
+
lines.push("");
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
let line = "";
|
|
281
|
+
for (let ci = 0; ci < cur.maxCol; ci++) {
|
|
282
|
+
line += cur.cols.get(ci) ?? " ";
|
|
283
|
+
}
|
|
284
|
+
lines.push(line);
|
|
285
|
+
}
|
|
286
|
+
return lines.join("\n");
|
|
51
287
|
}
|
|
52
288
|
/**
|
|
53
|
-
*
|
|
54
|
-
* @param s
|
|
55
|
-
* @returns
|
|
289
|
+
* 末尾空白清理(原为提示符剥离,现仅做清理,不依赖正则匹配具体提示符形状)
|
|
290
|
+
* @param s 文本
|
|
291
|
+
* @returns 清理后文本
|
|
56
292
|
*/
|
|
57
293
|
export function stripPrompt(s) {
|
|
58
|
-
return s
|
|
59
|
-
.replace(/(?:^|[\r\n])\s*(?:[\w.-]+@)?[\w.-]+:[^\r\n]*[$#%] ?(?=[\r\n]|$)/g, "")
|
|
60
|
-
.trim();
|
|
294
|
+
return s.trimEnd();
|
|
61
295
|
}
|
|
62
296
|
/**
|
|
63
297
|
* 时间戳格式化为 yyyy-MM-dd HH:mm:ss
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,cAAc,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAA;AACzD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,MAAM,aAAa,GAAG,wBAAwB,CAAA;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IACjF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3G,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,4CAA4C;IAC5C,OAAO,CAAC,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAA;AACvF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,kDAAkD;IAClD,MAAM,SAAS,GAAG,qBAAqB,CAAA;IACvC,2CAA2C;IAC3C,OAAO,CAAC;SACL,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAA;QAC9D,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC9B,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,CAAC;SACL,OAAO,CAAC,kEAAkE,EAAE,EAAE,CAAC;SAC/E,IAAI,EAAE,CAAA;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACnD,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAA;AACnI,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,aAAa;AACb,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;AAE7E,0DAA0D;AAC1D,MAAM,SAAS,GAAG,oGAAoG,CAAA;AAEtH;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,OAAe;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAA;IAClB,uCAAuC;IACvC,sDAAsD;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnF,8EAA8E;IAC9E,MAAM,SAAS,GAAG,uFAAuF,CAAA;IACzG,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,SAAS,GAAG,eAAe,EAAE,GAAG,CAAC,CAAA;IAC/E,2CAA2C;IAC3C,2BAA2B;IAC3B,OAAO,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;AAC/B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAe;IACxD,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC5C,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,GAAG,CAAA;IACxB,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;IAChD,OAAO,MAAM;SACV,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;SACvB,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,CAAS;IAC/B,gDAAgD;IAChD,MAAM,IAAI,GAAoD,EAAE,CAAA;IAChE,IAAI,CAAC,GAAG,CAAC,CAAA,CAAG,MAAM;IAClB,IAAI,CAAC,GAAG,CAAC,CAAA,CAAG,MAAM;IAClB,IAAI,EAAE,GAAG,CAAC,CAAA,CAAE,wBAAwB;IACpC,IAAI,EAAE,GAAG,CAAC,CAAA,CAAE,SAAS;IACrB,IAAI,OAAO,GAAuB,IAAI,CAAA,CAAC,qBAAqB;IAC5D,MAAM,IAAI,GAAG,GAAG,CAAA,CAAC,MAAM;IAEvB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE;QACxB,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAA;QAClE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC,CAAA;IACD,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,EAAE;QACzB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;QAClB,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACnB,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM;gBAAE,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;QACzC,CAAC;QACD,CAAC,EAAE,CAAA;IACL,CAAC,CAAA;IAED,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACf,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;YAClB,iCAAiC;YACjC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC;oBAAE,CAAC,EAAE,CAAA;gBAC5F,IAAI,CAAC,IAAI,CAAC;oBAAE,MAAK;gBACjB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;gBACnC,SAAQ;YACV,CAAC;YACD,6BAA6B;YAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACb,MAAM,KAAK,GAAG,CAAC,CAAA;gBACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAE,CAAC,EAAE,CAAA;gBAC5C,IAAI,CAAC,IAAI,CAAC;oBAAE,MAAK;gBACjB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;gBAC9B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC,CAAA;gBAClG,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC,CAAA;gBACpG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAClB,WAAW;gBACb,CAAC;qBAAM,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBAAC,CAAC;qBACrD,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAA;gBAAC,CAAC;qBACnC,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBAAC,CAAC;qBAC1D,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBAAC,CAAC;qBACnD,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;oBACzB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;oBAC9B,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;gBAChC,CAAC;qBACI,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;gBAAC,CAAC;qBACjF,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;gBAAC,CAAC;qBACnD,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,EAAE,GAAG,CAAC,CAAC;oBAAC,EAAE,GAAG,CAAC,CAAA;gBAAC,CAAC;qBACrC,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBAAC,CAAC,GAAG,EAAE,CAAA;gBAAC,CAAC;qBAChE,IAAI,KAAK,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/C,mCAAmC;oBACnC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;wBAC/B,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;wBACxE,EAAE,GAAG,CAAC,CAAC;wBAAC,EAAE,GAAG,CAAC,CAAA;wBACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAA;oBAC/B,CAAC;gBACH,CAAC;qBACI,IAAI,KAAK,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/C,kCAAkC;oBAClC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,EAAE,CAAC;wBAC1C,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;wBACf,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAA;wBACrB,OAAO,GAAG,IAAI,CAAA;wBACd,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;wBAAC,CAAC,GAAG,EAAE,CAAA;oBAC3C,CAAC;gBACH,CAAC;qBACI,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBACvB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;oBACrB,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;oBACrB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;wBAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;wBAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;oBAAC,CAAC;yBACrD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;wBAAC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;4BAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;wBAAC,CAAC;wBAAA,CAAC;wBAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;oBAAC,CAAC;yBACjG,CAAC;wBAAC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC;4BAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;wBAAC,CAAC;wBAAA,CAAC;wBAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;oBAAC,CAAC;gBACnH,CAAC;qBACI,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBACvB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;oBACrB,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;wBAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAA;oBAAC,CAAC;yBAC1D,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;wBAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAC;wBAAC,CAAC,GAAG,CAAC,CAAA;oBAAC,CAAC;yBACjD,CAAC;wBACJ,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;wBAClB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE;4BAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;wBACrD,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;wBACpC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;oBACrB,CAAC;gBACH,CAAC;gBACD,sBAAsB;gBACtB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACT,SAAQ;YACV,CAAC;YACD,0BAA0B;YAC1B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAAC,EAAE,GAAG,CAAC,CAAC;gBAAC,EAAE,GAAG,CAAC,CAAC;gBAAC,CAAC,IAAI,CAAC,CAAC;gBAAC,SAAQ;YAAC,CAAC;YAC1D,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAAC,CAAC,GAAG,EAAE,CAAC;gBAAC,CAAC,IAAI,CAAC,CAAC;gBAAC,SAAQ;YAAC,CAAC;YACrF,cAAc;YACd,CAAC,IAAI,CAAC,CAAA;YACN,SAAQ;QACV,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAAC,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QACzC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC9C,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,CAAC,EAAE,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QAClD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YACxC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBAAC,CAAC,EAAE,CAAC;gBAAC,CAAC,GAAG,CAAC,CAAA;YAAC,CAAC;;gBAC3B,CAAC,GAAG,IAAI,CAAA;YACb,CAAC,EAAE,CAAC;YAAC,SAAQ;QACf,CAAC;QACD,uBAAuB;QACvB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC5C,GAAG,CAAC,EAAE,CAAC,CAAA;QACP,CAAC,EAAE,CAAA;IACL,CAAC;IAED,QAAQ;IACR,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;QACpB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,SAAQ;QAAC,CAAC;QAClD,IAAI,IAAI,GAAG,EAAE,CAAA;QACb,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAA;QACjC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACnD,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAA;AACnI,CAAC"}
|
package/dist/web/app.css
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: "CaskaydiaCove Nerd Font Mono";
|
|
3
|
+
src: url("/web/fonts/CaskaydiaCoveNerdFontMono-Regular.ttf") format("truetype");
|
|
4
|
+
font-display: swap;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
html, body { margin: 0; height: 100%; background: #0d1117; color: #c9d1d9; font-family: system-ui, sans-serif; }
|
|
8
|
+
header { position: sticky; top: 0; display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: #161b22; border-bottom: 1px solid #30363d; }
|
|
9
|
+
header h1 { margin: 0; font-size: 14px; color: #e6edf3; font-weight: 600; }
|
|
10
|
+
select { background: #21262d; color: #c9d1d9; border: 1px solid #30363d; padding: 4px 8px; border-radius: 6px; }
|
|
11
|
+
pre { margin: 0; padding: 16px 16px 52px; font-family: "CaskaydiaCove Nerd Font Mono", "Cascadia Code", "Fira Code", "JetBrains Mono", "Noto Sans Mono", "Hack", Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.5; white-space: pre-wrap; overflow: auto; height: calc(100% - 52px); box-sizing: border-box; color: #c9d1d9; }
|
|
12
|
+
.row { display: flex; align-items: stretch; }
|
|
13
|
+
.row .t { box-sizing: border-box; flex: 0 0 172px; color: #8b949e; padding: 0 10px 0 6px; border-right: 1px solid #30363d; white-space: pre; }
|
|
14
|
+
.row .c { flex: 1; padding-left: 12px; white-space: pre; }
|
|
15
|
+
body:not(.show-time) .row .t { display: none; }
|
|
16
|
+
.row.cmdline { background: #161b22; box-shadow: inset 3px 0 0 #58a6ff; font-weight: 600; }
|
|
17
|
+
.tgl { font-size: 12px; color: #8b949e; display: flex; align-items: center; gap: 4px; white-space: nowrap; }
|
|
18
|
+
#meta { font-size: 12px; color: #8b949e; }
|
|
19
|
+
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
20
|
+
::-webkit-scrollbar-track { background: #161b22; }
|
|
21
|
+
::-webkit-scrollbar-thumb { background: #30363d; border-radius: 5px; border: 2px solid #161b22; }
|
|
22
|
+
::-webkit-scrollbar-thumb:hover { background: #484f58; }
|
|
23
|
+
::-webkit-scrollbar-corner { background: #161b22; }
|
|
24
|
+
* { scrollbar-width: thin; scrollbar-color: #30363d #161b22; }
|
|
25
|
+
.to-bottom-btn {
|
|
26
|
+
position: fixed; right: 24px; bottom: 24px; display: none;
|
|
27
|
+
background: #238636; color: #fff; border: none; border-radius: 20px;
|
|
28
|
+
padding: 8px 16px; font-size: 13px; cursor: pointer; z-index: 10;
|
|
29
|
+
box-shadow: 0 4px 12px rgba(0,0,0,.4);
|
|
30
|
+
}
|
|
31
|
+
.to-bottom-btn:hover { background: #2ea043; }
|
|
32
|
+
.sep hr { border: none; border-top: 1px dashed #30363d; margin: 8px 0; }
|
|
33
|
+
.del-btn { background: none; border: 1px solid #30363d; color: #f85149; border-radius: 4px; cursor: pointer; padding: 2px 8px; font-size: 14px; line-height: 1; display: none; }
|
|
34
|
+
.del-btn:hover { background: #f85149; color: #fff; }
|
|
35
|
+
.del-btn.show { display: inline-block; }
|
|
36
|
+
#cmdbar { position: fixed; bottom: 8px; left: 16px; right: 16px; display: flex; gap: 6px; }
|
|
37
|
+
#cmdInput { flex: 1; box-sizing: border-box; background: #0d1117; color: #c9d1d9; border: 1px solid #30363d; border-radius: 6px; padding: 8px 12px; font-family: "CaskaydiaCove Nerd Font Mono", "Cascadia Code", "Fira Code", "JetBrains Mono", "Noto Sans Mono", "Hack", Consolas, "Courier New", monospace; font-size: 13px; outline: none; resize: none; max-height: 120px; overflow-y: auto; }
|
|
38
|
+
#cmdInput:focus { border-color: #58a6ff; }
|
|
39
|
+
#cmdInput:disabled { opacity: 0.4; }
|
|
40
|
+
#cmdKey { flex: 0 0 auto; width: 72px; text-align: center; background: #21262d; color: #c9d1d9; border: 1px solid #30363d; border-radius: 6px; padding: 8px 6px; font-size: 12px; white-space: nowrap; overflow: hidden; cursor: crosshair; user-select: none; display: flex; align-items: center; justify-content: center; transition: border-color .15s; }
|
|
41
|
+
#cmdKey.capture { border-color: #e67e22; animation: pulse 0.6s ease-in-out infinite alternate; }
|
|
42
|
+
#cmdKey.disabled { opacity: 0.35; cursor: default; }
|
|
43
|
+
@keyframes pulse { from { opacity: 0.6; } to { opacity: 1; } }
|
package/dist/web/app.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";(()=>{var q=Object.defineProperty;var z=(n,e,t)=>e in n?q(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var g=(n,e,t)=>z(n,typeof e!="symbol"?e+"":e,t);function Z(n){let e=n.match(P);if(e&&e.length>0){let t=parseInt(e[e.length-1].replace(/<SSH_DONE:|>/g,""),10);return{text:n.replace(P,""),exitCode:isNaN(t)?void 0:t}}return{text:n}}var B=window.__I18N__,k=window.__PTY_COLS__||120,W=["#010101","#de382b","#39b54a","#ffc005","#006fb8","#762671","#2cb3e9","#c9d1d9"],j=["#666666","#ff7b72","#3fb950","#d29922","#58a6ff","#bc8cff","#39c5cf","#f0f6fc"],M=class{constructor(e){g(this,"cols");g(this,"grid",[]);g(this,"r",0);g(this,"c",0);g(this,"fg",null);g(this,"bg",null);g(this,"bold",!1);g(this,"sr",0);g(this,"sc",0);g(this,"altGrid",null);this.cols=e}_row(e){for(;this.grid.length<=e;){let t=[];for(let i=0;i<this.cols;i++)t.push({ch:" ",fg:null,bg:null,bold:!1});this.grid.push(t)}return this.grid[e]}_put(e){let t=this._row(this.r);t[this.c]={ch:e,fg:this.fg,bg:this.bg,bold:this.bold},this.c++,this.c>=this.cols&&(this.c=0,this.r++)}write(e){let t=0,i=e.length;for(;t<i;){let l=e[t];if(l==="\x1B"){if(t+1<i&&e[t+1]==="]"){let r=t+2;for(;r<i&&e[r]!=="\x07"&&!(e[r]==="\x1B"&&e[r+1]==="\\");)r++;if(r>=i)break;t=e[r]==="\x07"?r+1:r+2;continue}if(t+1<i&&e[t+1]==="["){let r=t+2,o=r;for(;r<i&&!/[A-Za-z@]/.test(e[r]);)r++;if(r>=i)break;this._csi(e.slice(o,r),e[r]),t=r+1;continue}if(e[t+1]==="7"){this.sr=this.r,this.sc=this.c,t+=2;continue}if(e[t+1]==="8"){this.r=Math.min(this.sr,this.grid.length-1),this.c=this.sc,t+=2;continue}t+=2;continue}if(l==="\r"){this.c=0,t++;continue}if(l===`
|
|
2
|
+
`){this.r++,this.c=0,t++;continue}if(l==="\b"){this.c>0&&this.c--,t++;continue}if(l===" "){this.c=(Math.floor(this.c/8)+1)*8,this.c>=this.cols&&(this.c=0,this.r++),t++;continue}if(l.charCodeAt(0)<32){t++;continue}this._put(l),t++}}_csi(e,t){let i=e.replace(/^[?]/,"");if(t==="m"){let o=i?i.split(";").map(s=>parseInt(s,10)):[0];(!i||o.indexOf(0)>=0)&&(this.fg=null,this.bg=null,this.bold=!1);for(let s of o)s===1?this.bold=!0:s===22?this.bold=!1:s>=30&&s<=37?this.fg=W[s-30]:s===39?this.fg=null:s>=90&&s<=97?this.fg=j[s-90]:s>=40&&s<=47?this.bg=W[s-40]:s===49?this.bg=null:s>=100&&s<=107&&(this.bg=j[s-100]);return}let l=o=>{let s=parseInt(o,10);return Number.isFinite(s)&&s>0?s:1},r=o=>{let s=parseInt(o,10);return Number.isFinite(s)&&s>=0?s:0};if(t==="A")this.r=Math.max(0,this.r-l(i));else if(t==="B")this.r+=l(i);else if(t==="C")this.c=Math.min(this.cols-1,this.c+l(i));else if(t==="D")this.c=Math.max(0,this.c-l(i));else if(t==="H"||t==="f"){let o=i.split(";");this.r=l(o[0])-1,this.c=l(o[1])-1}else if(t==="G"||t.charCodeAt(0)===96)this.c=Math.max(0,l(i)-1);else if(t==="d")this.r=Math.max(0,l(i)-1);else if(t==="J"){let o=r(i);if(o===2||o===3){for(let s=0;s<this.grid.length;s++){let c=this._row(s);for(let d=0;d<this.cols;d++)c[d]={ch:" ",fg:null,bg:null,bold:!1}}this.r=0,this.c=0}else if(o===1)for(let s=0;s<=this.r;s++){let c=this._row(s),d=s===this.r?this.c:this.cols;for(let u=0;u<d;u++)c[u]={ch:" ",fg:null,bg:null,bold:!1}}else for(let s=this.r;s<this.grid.length;s++){let c=this._row(s),d=s===this.r?this.c:0;for(let u=d;u<this.cols;u++)c[u]={ch:" ",fg:null,bg:null,bold:!1}}}else if(t==="K"){let o=r(i),s=this._row(this.r);if(o===2)for(let c=0;c<this.cols;c++)s[c]={ch:" ",fg:null,bg:null,bold:!1};else if(o===1)for(let c=0;c<=this.c;c++)s[c]={ch:" ",fg:null,bg:null,bold:!1};else for(let c=this.c;c<this.cols;c++)s[c]={ch:" ",fg:null,bg:null,bold:!1}}else t==="s"?(this.sr=this.r,this.sc=this.c):t==="u"?(this.r=Math.min(this.sr,this.grid.length-1),this.c=this.sc):(t==="h"||t==="l")&&e.startsWith("?")&&r(e.slice(1).split(";")[0])===1049&&(t==="h"?(this.altGrid=this.grid.map(s=>s.slice()),this.sr=this.r,this.sc=this.c,this.grid=[],this.r=0,this.c=0):this.altGrid&&(this.grid=this.altGrid,this.altGrid=null,this.r=Math.min(this.sr,this.grid.length-1),this.c=this.sc))}render(){let e=i=>i.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),t=[];for(let i=0;i<this.grid.length;i++){let l=this.grid[i],r=this.cols;for(;r>0&&l[r-1].ch===" ";)r--;if(r===0)continue;let o="",s=null;for(let c=0;c<r;c++){let d=l[c],u=[];d.bold&&u.push("font-weight:bold"),d.fg&&u.push("color:"+d.fg),d.bg&&u.push("background-color:"+d.bg);let E=u.join(";");E!==s&&(s&&(o+="</span>"),s=E,E&&(o+='<span style="'+E+'">')),o+=e(d.ch)}s&&(o+="</span>"),t.push(o)}return t}},a=null,f=[],y=!0,h=null,b=!1;function Q(){a=new WebSocket("ws://"+window.location.host+"/ws"),a.onopen=()=>{a.send(JSON.stringify({type:"list"})),G()},a.onmessage=n=>{let e;try{e=JSON.parse(n.data)}catch{return}switch(e.type){case"sessions":V(e);break;case"snapshot":$(e);break;case"run":ee(e);break;case"runEnd":break;case"cmdStart":ne(e);break;case"raw":te(e);break}},a.onclose=()=>{let n=document.getElementById("term");n.textContent="WebSocket disconnected"}}function V(n){let e=n.sessions||[],t=document.getElementById("session"),i=e.map(o=>o.sessionID+"|"+o.terminals.length).join(","),l=t.value,r=document.getElementById("terminal").value;f=e,t.innerHTML="";for(let o of f){let s=document.createElement("option");s.value=o.sessionID,s.textContent=R(o)+" ("+o.terminals.length+" "+B.terminals+")",t.appendChild(s)}l&&[...t.options].some(o=>o.value===l)?t.value=l:t.selectedIndex=f.length?0:-1,O(r)}function X(){let n=document.getElementById("session").value,e=document.getElementById("terminal").value,i=f.find(o=>o.sessionID===n)?.terminals.find(o=>(o.name||"default")===e),l=!i||!i.connected,r=document.getElementById("cmdKey");r.classList.toggle("disabled",l),r.title=l?"":B.sendCtrlC||""}function O(n){let e=document.getElementById("session"),t=document.getElementById("terminal"),i=document.getElementById("delTerm"),l=e.value,r=f.find(s=>s.sessionID===l);t.innerHTML="";for(let s of r?r.terminals:[]){let c=document.createElement("option");c.value=s.name||"default",c.textContent=(s.name||"default")+(s.kind==="local"?" ["+B.local+"]":"")+" "+(s.connected?"\u25CF":"\u25CB")+(s.busy?" \u23F3":""),t.appendChild(c)}n&&[...t.options].some(s=>s.value===n)?t.value=n:t.selectedIndex=t.options.length?0:-1;let o=r?.terminals.find(s=>(s.name||"default")===t.value);i.classList.toggle("show",!!(o&&!o.connected)),X(),J(),w="",S="",G()}var w="",S="",x=!1;function G(){let n=document.getElementById("session").value,e=document.getElementById("terminal").value;!n||!e||!a||a.readyState!==WebSocket.OPEN||n===w&&e===S||(w=n,S=e,h=null,x=!1,a.send(JSON.stringify({type:"subscribe",sessionID:n,name:e,raw:b})))}function $(n){let e=document.getElementById("term"),t=document.getElementById("toBottom");if(n.notFound){e.innerHTML='<div class="row"><span class="t"></span><span class="c">'+B.sessionGone+"</span></div>",document.getElementById("meta").textContent="",oe(n.sessionID,n.name);return}let i=n.pairs||[],l=!b&&document.getElementById("showTime").checked;document.body.classList.toggle("show-time",l);let r=i.filter(o=>o.type==="cmd").length;J(r),!(b&&x)&&(h=null,e.innerHTML=se(i,l),y?(e.scrollTop=e.scrollHeight,t.style.display="none"):t.style.display=e.scrollHeight>e.clientHeight?"block":"none")}function J(n){let e=document.getElementById("session").value,t=document.getElementById("terminal").value;if(!e){document.getElementById("meta").textContent="";return}let l=f.find(c=>c.sessionID===e)?.terminals.find(c=>(c.name||"default")===t),r=l?l.host?l.host+(l.port?":"+l.port:""):l.program||"":"",o=r?" ["+r+"]":"",s=n!==void 0?" \xB7 "+n+" "+B.commands:"";document.getElementById("meta").textContent=e+"/"+t+o+s}function ee(n){if(!n.data||b)return;let e=document.getElementById("term"),t=document.getElementById("toBottom"),i=document.getElementById("runBlock");h||(h=new M(k),i=document.createElement("div"),i.id="runBlock",e.appendChild(i)),h.write(K(n.data));let l=h.render().map(r=>'<div class="row"><span class="t"></span><span class="c">'+r+"</span></div>").join("");i.innerHTML=l,y?(e.scrollTop=e.scrollHeight,t.style.display="none"):t.style.display="block"}var I=null;function te(n){if(!b)return;let e=document.getElementById("term"),t=document.getElementById("toBottom");if(x||(x=!0,e.innerHTML="",I=null),n.reset?(I=new M(k),I.write(n.data||"")):n.data&&(I||(I=new M(k)),I.write(n.data)),I){let i=I.render().map(l=>'<div class="row"><span class="c">'+l+"</span></div>").join("");e.innerHTML=i}y?(e.scrollTop=e.scrollHeight,t.style.display="none"):t.style.display=e.scrollHeight>e.clientHeight?"block":"none"}function ne(n){if(b||!n.command)return;let e=document.getElementById("term"),t=document.getElementById("toBottom"),i=document.getElementById("runBlock");i&&i.remove(),h=null;let r=document.getElementById("showTime").checked?Y(Date.now()):"",o=document.createElement("div");o.className="row cmdline",o.innerHTML='<span class="t">'+r+'</span><span class="c">'+F(n.command)+"</span>",e.appendChild(o),y&&(e.scrollTop=e.scrollHeight,t.style.display="none")}function F(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var P=/<SSH_DONE:(-?\d+)>/g;function K(n){return n.replace(P,"")}function se(n,e){let t=[],i=null;for(let l of n){if(l.type==="sep"){t.push('<div class="sep"><hr></div>');continue}if(l.type==="cmd"){i={ts:l.ts,endTs:l.endTs};let r=l.ts?Y(l.ts):"";t.push('<div class="row cmdline"><span class="t">'+r+'</span><span class="c">'+F(l.text)+"</span></div>")}else if(l.type==="run"){h=new M(k),h.write(K(l.text));let r=h.render().map(o=>'<div class="row"><span class="t"></span><span class="c">'+o+"</span></div>").join("");t.push('<div id="runBlock">'+r+"</div>")}else{let r=Z(l.text),o=new M(k);o.write(r.text);let s=o.render(),c=e?ie(i,r.exitCode):"",d=(u,E)=>'<div class="row"><span class="t">'+u+'</span><span class="c">'+E+"</span></div>";s.length===0?t.push(d(c," ")):s.forEach((u,E)=>t.push(d(E===s.length-1?c:"",u))),i=null}}return t.join("")}function ie(n,e){let t=[];if(n&&n.ts&&n.endTs&&t.push("+"+((n.endTs-n.ts)/1e3).toFixed(3)+"s"),e!==void 0){let i=e===0?"#3fb950":"#ff7b72";t.push('<span style="color:'+i+'">'+(e===0?"\u2713":"\u2717 "+e)+"</span>")}return t.join(" ")}function R(n){if(n.title&&n.title.trim())return n.title;let e=n.terminals&&n.terminals[0];return e&&e.host?(e.user?e.user+"@":"")+e.host:n.sessionID.slice(0,8)+"\u2026"}function Y(n){let e=new Date(n),t=i=>String(i).padStart(2,"0");return e.getFullYear()+"-"+t(e.getMonth()+1)+"-"+t(e.getDate())+" "+t(e.getHours())+":"+t(e.getMinutes())+":"+t(e.getSeconds())}function oe(n,e){let t=f.find(o=>o.sessionID===n);t&&(t.terminals=t.terminals.filter(o=>(o.name||"default")!==e),t.terminals.length===0&&(f=f.filter(o=>o.sessionID!==n)));let i=document.getElementById("session"),l=i.value;i.innerHTML="";for(let o of f){let s=document.createElement("option");s.value=o.sessionID,s.textContent=R(o)+" ("+o.terminals.length+" "+B.terminals+")",i.appendChild(s)}l&&[...i.options].some(o=>o.value===l)?i.value=l:i.selectedIndex=f.length?0:-1;let r=document.getElementById("terminal").value;O(r)}function le(n){n&&(y=!0);let e=document.getElementById("terminal").value;O(e)}function re(){let n=document.getElementById("showTime");localStorage.setItem("showTime",n.checked?"1":"0"),document.body.classList.toggle("show-time",n.checked)}function ce(){let n=document.getElementById("debugMode");b=n.checked,localStorage.setItem("debugMode",n.checked?"1":"0"),document.body.classList.toggle("debug",n.checked),w="",S="",G()}function ae(){let n=document.getElementById("session").value,e=document.getElementById("terminal").value;if(!e||!a||a.readyState!==WebSocket.OPEN)return;let t=f.find(r=>r.sessionID===n),i=t?.terminals.find(r=>(r.name||"default")===e);if(!i||i.connected)return;a.send(JSON.stringify({type:"deleteTerminal",sessionID:n,name:e})),t&&(t.terminals=t.terminals.filter(r=>(r.name||"default")!==e),t.terminals.length===0&&(f=f.filter(r=>r.sessionID!==n)));let l=document.getElementById("terminal").value;O(l!==e?l:void 0)}function de(){let n=document.getElementById("term"),e=document.getElementById("toBottom");n.scrollTop=n.scrollHeight,y=!0,e.style.display="none"}var U=document.getElementById("showTime");U.checked=localStorage.getItem("showTime")==="1";document.body.classList.toggle("show-time",U.checked);var ue=document.getElementById("debugMode");b=localStorage.getItem("debugMode")==="1";ue.checked=b;document.body.classList.toggle("debug",b);var C=document.getElementById("term"),me=document.getElementById("toBottom");C.addEventListener("scroll",()=>{C.scrollTop+C.clientHeight>=C.scrollHeight-30?(y=!0,me.style.display="none"):y=!1});var L=[],T=-1,D=-1,_="",m=document.getElementById("cmdInput");m.placeholder=B.cmdPlaceholder||"";m.addEventListener("keydown",n=>{if(n.key==="Tab"){n.preventDefault();let o=m.value.trim();if(!o)return;_!==o&&(D=-1,_=o);let s=L.filter(c=>c.startsWith(_));if(s.length===0)return;D=(D+1)%s.length,m.value=s[D],v();return}if(_="",n.key==="ArrowUp"){n.preventDefault(),T>0&&(T--,m.value=L[T],v());return}if(n.key==="ArrowDown"){n.preventDefault(),T<L.length-1?(T++,m.value=L[T],v()):(T=L.length,m.value="",v());return}if(n.key!=="Enter")return;if(n.shiftKey){v();return}n.preventDefault();let e=document.getElementById("session").value,t=document.getElementById("terminal").value,l=f.find(o=>o.sessionID===e)?.terminals.find(o=>(o.name||"default")===t);if(!l||!l.connected)return;if(l.busy){let o=m.value;if(m.value="",v(),!o||!a||a.readyState!==WebSocket.OPEN)return;(w!==e||S!==t)&&(w=e,S=t,a.send(JSON.stringify({type:"subscribe",sessionID:e,name:t}))),a.send(JSON.stringify({type:"send",sessionID:e,name:t,text:o+"\r"})),y=!0;return}let r=m.value.trim();r&&(m.value="",v(),L.push(r),T=L.length,!(!a||a.readyState!==WebSocket.OPEN)&&((w!==e||S!==t)&&(w=e,S=t,a.send(JSON.stringify({type:"subscribe",sessionID:e,name:t}))),a.send(JSON.stringify({type:"exec",sessionID:e,name:t,command:r})),y=!0))});function v(){m.style.height="auto",m.style.height=Math.min(m.scrollHeight,120)+"px"}m.addEventListener("input",v);var p=document.getElementById("cmdKey"),N=B.sendCtrlC||"Ctrl-C",H=!1;p.textContent=N;function A(n){if(!H)return;H=!1,p.classList.remove("capture"),document.removeEventListener("keyup",A);let e=document.getElementById("session").value,t=document.getElementById("terminal").value;if(!e||!a||a.readyState!==WebSocket.OPEN)return;let i,l;if(n.ctrlKey&&n.key!=="Control"){let r=n.key.toLowerCase().charCodeAt(0)-96;r>=1&&r<=26?(i="\\x"+r.toString(16).padStart(2,"0"),l="Ctrl-"+n.key.toUpperCase()):(i="",l="")}else n.key==="Enter"?(i="\\r",l="\u21B5"):n.key==="Escape"?(i="\\x1b",l="Esc"):n.key==="Tab"?(i="\\t",l="Tab"):n.key==="Backspace"?(i="\\x7f",l="\u232B"):n.key===" "||n.key==="Space"?(i=" ",l="Space"):n.key.length===1?(i=n.key,l=n.key):(i="\\x03",l="Ctrl-C");i&&a.send(JSON.stringify({type:"send",sessionID:e,name:t,text:i})),p.textContent=l||N,setTimeout(()=>{H||(p.textContent=N)},1500)}p.addEventListener("mouseenter",()=>{let n=document.getElementById("session").value,e=document.getElementById("terminal").value;n&&(H=!0,p.classList.add("capture"),p.textContent="...",document.addEventListener("keyup",A))});p.addEventListener("mouseleave",()=>{H&&(H=!1,p.classList.remove("capture"),document.removeEventListener("keyup",A),p.textContent=N)});Object.assign(window,{onSessionChange:le,onShowTimeChange:re,onDebugModeChange:ce,deleteTerminal:ae,scrollToNewest:de});Q();})();
|
|
Binary file
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="{{lang}}">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>{{web_title}}</title>
|
|
6
|
+
<link rel="stylesheet" href="/web/app.css">
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<header>
|
|
10
|
+
<h1>{{web_title}}</h1>
|
|
11
|
+
<select id="session" onchange="onSessionChange(true)"></select>
|
|
12
|
+
<select id="terminal" onchange="onSessionChange(true)"></select>
|
|
13
|
+
<button id="delTerm" class="del-btn" onclick="deleteTerminal()" title="{{web_delete_terminal}}">×</button>
|
|
14
|
+
<label class="tgl"><input type="checkbox" id="showTime" onchange="onShowTimeChange()"> {{web_time}}</label>
|
|
15
|
+
<label class="tgl"><input type="checkbox" id="debugMode" onchange="onDebugModeChange()"> Raw</label>
|
|
16
|
+
<span id="meta"></span>
|
|
17
|
+
</header>
|
|
18
|
+
<pre id="term">{{web_loading}}</pre>
|
|
19
|
+
<button id="toBottom" class="to-bottom-btn" onclick="scrollToNewest()">{{web_new_messages}}</button>
|
|
20
|
+
<div id="cmdbar">
|
|
21
|
+
<span id="cmdKey" title="{{web_send_ctrlc}}">Ctrl-C</span>
|
|
22
|
+
<textarea id="cmdInput" rows="1" placeholder="{{web_cmd_placeholder}}"></textarea>
|
|
23
|
+
</div>
|
|
24
|
+
<script>window.__I18N__ = __I18N_JSON__;</script>
|
|
25
|
+
<script>window.__PTY_COLS__ = __PTY_COLS_VAL__;</script>
|
|
26
|
+
<script src="/web/app.js"></script>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiaoqiong0v0/opencode-ssh-tool",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "长驻交互式 SSH 会话工具插件,远程命令受 opencode 权限管控",
|
|
6
6
|
"files": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
".": "./dist/index.js"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"build": "tsc",
|
|
16
|
+
"build": "tsc && node web/build.mjs",
|
|
17
17
|
"prepublishOnly": "npm run build"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@xiaoqiong0v0/opencode-plugin-logger": "^1.0.4",
|
|
40
40
|
"ssh2": "^1.16.0",
|
|
41
|
-
"string-argv": "^0.3.2"
|
|
41
|
+
"string-argv": "^0.3.2",
|
|
42
|
+
"ws": "^8.21.3"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"@opencode-ai/plugin": "^1.18.4"
|
|
@@ -46,6 +47,8 @@
|
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/node": "^26.1.1",
|
|
48
49
|
"@types/ssh2": "^1.15.4",
|
|
50
|
+
"@types/ws": "^8.18.1",
|
|
51
|
+
"esbuild": "^0.28.2",
|
|
49
52
|
"typescript": "^7.0.2"
|
|
50
53
|
}
|
|
51
54
|
}
|