@xiaoqiong0v0/opencode-ssh-tool 0.6.8 → 0.6.11

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/log.js CHANGED
@@ -1,5 +1,238 @@
1
- // 共享日志模块:全局单例 logger,避免各文件重复创建
1
+ // 共享日志模块:全局单例 logger + 降噪辅助(debug 门控 / 短窗去重 / 跨进程去重)
2
+ // 级别与开关口径(@xiaoqiong0v0/opencode-plugin-logger 1.0.6):
3
+ // - 级别只是标签:底层以 `log(level, msg)` 原样落盘 `[level]`,**无内置门槛/过滤**——只要全局 enabled=true,
4
+ // 任何级别(含 "DEBUG")都会写入;因此"debug 是否落盘"完全由本模块门控决定,而非底层级别。
5
+ // - 全局开关:`~/.config/opencode/plugin-logger.jsonc` 的 `enabled`(默认 false)。关闭时底层所有方法都是空函数,
6
+ // 本模块另以 LOG_ENABLED 同步判定,让各辅助函数**先判后做**(关闭时直接 return:不拼串 / 不建去重 Map / 不读写文件 / 不裁剪)。
7
+ // - debug 级:由环境变量 SSH_TOOL_DEBUG=1 门控(默认关);开启且全局 enabled 时经 `log("DEBUG", …)` 原生级别落盘。
8
+ // 会话/终端标识约定(便于 `grep ses_xxx` 捞出一个会话的全部状态行):
9
+ // - 处于会话/终端上下文的行必须带 `<主会话ID>/<终端名>`(如 ses_abc/default);命令坐标用 `seq=<命令序号>`;
10
+ // server 侧由 `sid:name` 键转成同一写法(server.ts keyTag),本地/SSH 传输层沿用既有的 `(session x, term y)` 写法。
11
+ // - 进程级事件(插件加载、agent 连上/断开服务、独立服务启停与替换、锁清理)本身没有单一会话归属,
12
+ // 只带 wsUrl / pid / port;若该事件牵涉具体终端(如断开受影响的终端、重连发现的运行中终端),
13
+ // 把受影响的 `<主会话ID>/<终端名>` 列表打进同一行。独立服务是另一进程,只能看到 key=`sid:name`,
14
+ // 拿不到 opencode 会话之外的上下文(其日志可按 sid 过滤,但无法按插件进程过滤)。
2
15
  import createLogger from "@xiaoqiong0v0/opencode-plugin-logger";
16
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
+ import { homedir } from "node:os";
18
+ import { join } from "node:path";
19
+ import { stripAnsi } from "./ansi.js";
20
+ import { CACHE_DIR } from "./constants.js";
3
21
  const log = createLogger("opencode-ssh-tool");
22
+ /** 插件日志配置文件路径(与 opencode-plugin-logger 包内一致:~/.config/opencode/plugin-logger.jsonc) */
23
+ const LOGGER_CONFIG_PATH = join(homedir(), ".config", "opencode", "plugin-logger.jsonc");
24
+ /**
25
+ * 判断插件日志是否全局启用:底层 logger 在 `enabled=false` 时会把 info/warn/… 全替换为空函数,
26
+ * 但它**没有查询启用状态的 API**(返回对象只暴露方法),故这里按其同款口径自行解析配置:
27
+ * 读取 `~/.config/opencode/plugin-logger.jsonc` 的 `enabled`(默认 false,与包内 defaults 一致)。
28
+ * 配置路径与 JSONC 处理与包内 resolveCfg 保持一致(兼容注释);任何读取/解析异常都降级为 false。
29
+ * @returns 是否启用(true=会产生日志输出)
30
+ */
31
+ function resolveLogEnabled() {
32
+ try {
33
+ const raw = readFileSync(LOGGER_CONFIG_PATH, "utf8")
34
+ .replace(/\/\/.*$/gm, "")
35
+ .replace(/\/\*[\s\S]*?\*\//g, "");
36
+ return JSON.parse(raw).enabled === true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * 全局日志开关(启动时解析一次):logger 关闭时 info/warn/… 均为空函数,
44
+ * 本模块各辅助函数据此**先判后做**——关闭时直接 return,不再维护去重窗口 Map、不再做字符串拼装/裁剪/文件读写。
45
+ */
46
+ const LOG_ENABLED = resolveLogEnabled();
47
+ /**
48
+ * debug 日志开关:默认关闭。底层 1.0.6 的 `log("DEBUG", …)` 只是级别标签、**无默认门槛**(全局 enabled=true 即落盘),
49
+ * 故 debug 是否输出完全由本开关门控:周期性/心跳类细节(ssh2 协议 trace、探针 tick、轮询无变化等)
50
+ * 默认不落盘,置 SSH_TOOL_DEBUG=1 后才记录。
51
+ */
52
+ const DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.SSH_TOOL_DEBUG ?? "");
53
+ /**
54
+ * 当前是否会真正产出 debug 级日志("日志全局启用" 且 "SSH_TOOL_DEBUG 打开")。
55
+ * 供调用方在**拼装日志字符串之前**短路(例如 ssh2 协议 trace 回调的注册),避免关闭时做无谓的字符串拼装。
56
+ * @returns 是否启用 debug 级日志
57
+ */
58
+ export function isDebugEnabled() {
59
+ return LOG_ENABLED && DEBUG_ENABLED;
60
+ }
61
+ /**
62
+ * 记录 debug 级细节(周期性/心跳类噪声):
63
+ * 默认不输出,置环境变量 SSH_TOOL_DEBUG=1 后才写日志,避免刷屏又不丢取证能力。
64
+ * 全局日志关闭时直接 return(不做任何拼装)。1.0.6 起用底层**原生级别** `log("DEBUG", …)` 落盘
65
+ * (`[DEBUG]` 标签由底层按级别输出),不再有 "info + `[DEBUG]` 前缀" 的写法;
66
+ * 调用方一律用 debug()/ssh2Trace(),不要自己写 log.info(...)(那样会绕过门控、无条件落盘)。
67
+ * @param msg 日志内容(按本模块约定,带会话上下文的行须含 `<主会话ID>/<终端名>`)
68
+ */
69
+ export function debug(msg) {
70
+ if (!isDebugEnabled())
71
+ return;
72
+ log.log("DEBUG", msg);
73
+ }
74
+ /** 随收发数据量增长的 ssh2 协议行(一次大输出/大文件传输会产生成千上万条)——一律不记 */
75
+ const SSH2_VOLUME_RE = /(CHANNEL_DATA|CHANNEL_EXTENDED_DATA|CHANNEL_WINDOW_ADJUST)/;
76
+ /**
77
+ * ssh2 协议 trace 落盘(debug 级):只记**有界**的连接/握手/认证类事件,
78
+ * `CHANNEL_DATA` / `CHANNEL_EXTENDED_DATA` / `CHANNEL_WINDOW_ADJUST` 这些**跟着输出/字节流增长**的协议行一律丢弃
79
+ * (避免"每收到/发出一个数据包就记一行"式刷屏)。
80
+ * @param tag 会话/终端标识(`<主会话ID>/<终端名>`)
81
+ * @param msg ssh2 协议 trace 原文
82
+ */
83
+ export function ssh2Trace(tag, msg) {
84
+ if (!isDebugEnabled())
85
+ return;
86
+ if (SSH2_VOLUME_RE.test(msg))
87
+ return;
88
+ log.log("DEBUG", `[ssh2] ${tag} ${msg}`);
89
+ }
90
+ /**
91
+ * 取字符串最后 n 行(默认 3):供"需要体现命令输出/缓冲内容"的日志做**有界摘要**,
92
+ * 避免多行内容(如多行命令回显)把一条日志撑成多行、随内容增长。
93
+ * 行数 ≤ n 时原样返回;全局日志关闭时直接返回原串(不做切分/裁剪)。
94
+ * @param s 原始字符串
95
+ * @param n 保留的最后行数(默认 3)
96
+ * @returns 至多 n 行的字符串
97
+ */
98
+ export function tailLines(s, n = 3) {
99
+ if (!LOG_ENABLED)
100
+ return s;
101
+ const lines = s.split(/\r?\n/);
102
+ return lines.length <= n ? s : lines.slice(-n).join("\n");
103
+ }
104
+ /**
105
+ * 取命令输出供 `[run] 结束` 等日志附加的**有界尾部摘要**:
106
+ * 输出是含 ANSI 的原始流(`_extractOutput` 产物,非渲染文本),先剥净 ANSI;再按终端渲染口径归一化每行
107
+ * (行内 CR 覆盖只保留最后一次回车后的可见内容,避免进度条式行内刷新撑爆单行)、去行尾空白、剔除空行
108
+ * (与模型可见文本 toModelText 口径一致:协议框定/回显产生的空行不算"输出行")。
109
+ * 仅当归一化后**行数 > n**(默认 3)时返回**末 n 行**,并把换行转义为 `\n` 字面量(保证整段摘要是单行、
110
+ * 不随输出增长);行数 ≤ n 时返回空串(短输出正文里已见,不重复附)。只取末尾有界行数,绝不打整段输出/字节流。
111
+ * 全局日志关闭时直接返回空串(不做剥 ANSI / 切分 / 裁剪)。
112
+ * @param s 命令输出(可能含 ANSI 的原始流)
113
+ * @param n 保留的最后行数(默认 3)
114
+ * @returns 空串,或转义换行后的末 n 行
115
+ */
116
+ export function tailSummary(s, n = 3) {
117
+ if (!LOG_ENABLED)
118
+ return "";
119
+ const lines = stripAnsi(s)
120
+ .split(/\r?\n/)
121
+ .map(normalizeOutputLine)
122
+ .filter((l) => l !== "");
123
+ if (lines.length <= n)
124
+ return "";
125
+ return lines.slice(-n).join("\\n");
126
+ }
127
+ /**
128
+ * 单行日志化归一:CR 覆盖只保留最后一次回车之后的可见内容(行尾孤立 CR 无覆盖内容时回退为去 CR),再去行尾空白。
129
+ * @param line 原始单行(已剥 ANSI,可能含行内 CR)
130
+ * @returns 归一化后的可见单行
131
+ */
132
+ function normalizeOutputLine(line) {
133
+ const i = line.lastIndexOf("\r");
134
+ const visible = i >= 0 ? line.slice(i + 1) : line;
135
+ return (visible !== "" ? visible : line.replace(/\r/g, "")).trimEnd();
136
+ }
137
+ /** 进程内去重窗口(毫秒):同 key 重复消息在此窗口内只记一次 */
138
+ const DEDUP_WINDOW_MS = 3000;
139
+ /** 各 key 的进程内去重状态:count=窗口内被抑制的次数,timer=窗口结束回补定时器 */
140
+ const dedupState = new Map();
141
+ /**
142
+ * 进程内短窗去重记录:同 key 首次立即输出;窗口内重复只计数不输出;
143
+ * 窗口结束时若有重复,补一条"<msg>(N 秒内重复 M 次)",既不刷屏也不丢信息量。
144
+ * @param key 去重键(相同 key 的同义消息合并)
145
+ * @param msg 日志内容(首次与回补都用它)
146
+ * @param windowMs 去重窗口(默认 3000ms)
147
+ */
148
+ export function infoDedup(key, msg, windowMs = DEDUP_WINDOW_MS) {
149
+ if (!LOG_ENABLED)
150
+ return;
151
+ const st = dedupState.get(key);
152
+ if (st) {
153
+ st.count += 1;
154
+ return;
155
+ }
156
+ log.info(msg);
157
+ const timer = setTimeout(() => {
158
+ const cur = dedupState.get(key);
159
+ if (!cur)
160
+ return;
161
+ dedupState.delete(key);
162
+ if (cur.count > 0)
163
+ log.info(`${msg}(${Math.round(windowMs / 1000)}s 内重复 ${cur.count} 次)`);
164
+ }, windowMs);
165
+ if (typeof timer.unref === "function")
166
+ timer.unref();
167
+ dedupState.set(key, { count: 0, timer });
168
+ }
169
+ /** 跨进程去重标记目录(放在插件缓存根下,多进程共享,供批量实例加载场景合并重复行) */
170
+ const SHARED_DEDUP_DIR = join(homedir(), CACHE_DIR, ".log-dedup");
171
+ /** 把去重键规整为安全文件名(非字母数字替换为下划线) */
172
+ function dedupSafeName(key) {
173
+ return key.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 100);
174
+ }
175
+ /** 已排定"窗口结束回补汇总"定时器的跨进程 key(避免同进程重复排定) */
176
+ const sharedTimerKeys = new Set();
177
+ /**
178
+ * 跨进程短窗去重:多个 opencode 插件实例(各自独立进程)写同一日志文件时,
179
+ * 用共享目录下的标记文件记录上次输出时刻与合并计数,窗口内的重复只记一次;
180
+ * 创建窗口的进程在窗口结束时读计数补一条"N 秒内重复 M 次",避免每个实例刷一整套。
181
+ * 任何文件读写失败都静默降级为直接输出(不阻断日志,不影响插件行为)。
182
+ * @param key 去重键(跨进程一致)
183
+ * @param msg 日志内容
184
+ * @param windowMs 去重窗口(默认 5000ms)
185
+ */
186
+ export function infoDedupShared(key, msg, windowMs = 5000) {
187
+ if (!LOG_ENABLED)
188
+ return;
189
+ try {
190
+ const file = join(SHARED_DEDUP_DIR, dedupSafeName(key));
191
+ const now = Date.now();
192
+ let prev = null;
193
+ try {
194
+ prev = JSON.parse(readFileSync(file, "utf8"));
195
+ }
196
+ catch {
197
+ prev = null;
198
+ }
199
+ if (prev && now - prev.ts < windowMs) {
200
+ // 窗口内:仅累加计数,抑制输出
201
+ prev.count += 1;
202
+ writeFileSync(file, JSON.stringify(prev), "utf8");
203
+ return;
204
+ }
205
+ mkdirSync(SHARED_DEDUP_DIR, { recursive: true });
206
+ writeFileSync(file, JSON.stringify({ ts: now, count: 0 }), "utf8");
207
+ // 上一窗口有合并的重复:先补一条汇总,再输出本次
208
+ if (prev && prev.count > 0) {
209
+ log.info(`${msg}(上次窗口内重复 ${prev.count} 次)`);
210
+ }
211
+ log.info(msg);
212
+ // 窗口结束回补本窗口合并计数(本进程仍存活时;置 0 避免与下次懒汇总重复)
213
+ if (!sharedTimerKeys.has(key)) {
214
+ sharedTimerKeys.add(key);
215
+ const timer = setTimeout(() => {
216
+ sharedTimerKeys.delete(key);
217
+ try {
218
+ const cur = JSON.parse(readFileSync(file, "utf8"));
219
+ if (cur && cur.count > 0) {
220
+ log.info(`${msg}(${Math.round(windowMs / 1000)}s 内重复 ${cur.count} 次)`);
221
+ cur.count = 0;
222
+ writeFileSync(file, JSON.stringify(cur), "utf8");
223
+ }
224
+ }
225
+ catch {
226
+ /* 标记文件已不在,忽略 */
227
+ }
228
+ }, windowMs);
229
+ if (typeof timer.unref === "function")
230
+ timer.unref();
231
+ }
232
+ }
233
+ catch {
234
+ log.info(msg);
235
+ }
236
+ }
4
237
  export default log;
5
238
  //# sourceMappingURL=log.js.map
package/dist/log.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,YAAY,MAAM,sCAAsC,CAAA;AAE/D,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAA;AAE7C,eAAe,GAAG,CAAA"}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,uDAAuD;AACvD,iFAAiF;AACjF,yDAAyD;AACzD,wFAAwF;AACxF,sFAAsF;AACtF,sFAAsF;AACtF,6CAA6C;AAC7C,2EAA2E;AAC3E,6FAA6F;AAC7F,uDAAuD;AACvD,4DAA4D;AAC5D,iEAAiE;AACjE,oDAAoD;AACpD,OAAO,YAAY,MAAM,sCAAsC,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAA;AAE7C,uFAAuF;AACvF,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAAA;AAExF;;;;;;GAMG;AACH,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,kBAAkB,EAAE,MAAM,CAAC;aACjD,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;aACxB,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAA;QACnC,OAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC,OAAO,KAAK,IAAI,CAAA;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAA;AAEvC;;;;GAIG;AACH,MAAM,aAAa,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAA;AAE9E;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,IAAI,aAAa,CAAA;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,IAAI,CAAC,cAAc,EAAE;QAAE,OAAM;IAC7B,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;AACvB,CAAC;AAED,oDAAoD;AACpD,MAAM,cAAc,GAAG,4DAA4D,CAAA;AAEnF;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,IAAI,CAAC,cAAc,EAAE;QAAE,OAAM;IAC7B,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAM;IACpC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAC,GAAG,CAAC;IACxC,IAAI,CAAC,WAAW;QAAE,OAAO,CAAC,CAAA;IAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAC,GAAG,CAAC;IAC1C,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC;SACvB,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,mBAAmB,CAAC;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA;IAC1B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IAChC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACpC,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACjD,OAAO,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;AACvE,CAAC;AAED,sCAAsC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAA;AAC5B,qDAAqD;AACrD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmE,CAAA;AAE7F;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW,EAAE,QAAQ,GAAG,eAAe;IAC5E,IAAI,CAAC,WAAW;QAAE,OAAM;IACxB,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,IAAI,CAAC,CAAA;QACb,OAAM;IACR,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACb,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACtB,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,KAAK,KAAK,CAAC,CAAA;IAC3F,CAAC,EAAE,QAAQ,CAAC,CAAA;IACZ,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;QAAE,KAAK,CAAC,KAAK,EAAE,CAAA;IACpD,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED,+CAA+C;AAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC,CAAA;AAEjE,gCAAgC;AAChC,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC3D,CAAC;AAED,0CAA0C;AAC1C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAA;AAEzC;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,GAAW,EAAE,QAAQ,GAAG,IAAI;IACvE,IAAI,CAAC,WAAW;QAAE,OAAM;IACxB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAA;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,IAAI,GAAyC,IAAI,CAAA;QACrD,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkC,CAAA;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,IAAI,CAAA;QACb,CAAC;QACD,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC;YACrC,iBAAiB;YACjB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;YACf,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QACD,SAAS,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAChD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;QAClE,0BAA0B;QAC1B,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,YAAY,IAAI,CAAC,KAAK,KAAK,CAAC,CAAA;QAC7C,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACb,wCAAwC;QACxC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACxB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBAC3B,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkC,CAAA;oBACnF,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;wBACzB,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,KAAK,KAAK,CAAC,CAAA;wBACtE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAA;wBACb,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;oBAClD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,gBAAgB;gBAClB,CAAC;YACH,CAAC,EAAE,QAAQ,CAAC,CAAA;YACZ,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;gBAAE,KAAK,CAAC,KAAK,EAAE,CAAA;QACtD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,CAAC;AACH,CAAC;AAED,eAAe,GAAG,CAAA"}
@@ -27,7 +27,7 @@ async function main() {
27
27
  const handle = await startServer(port, getSessions, dir, lang, streamTickMs);
28
28
  // 写服务信息文件(供其他进程探测复用;proto 标识代码/协议版本,版本不符会触发重启)
29
29
  writeFileSync(join(dir, INFO_FILE), JSON.stringify({ port: handle.port, host: "127.0.0.1", pid: process.pid, startedAt: Date.now(), proto: SERVER_PROTO_VERSION }), "utf8");
30
- log.info(`独立服务启动 ${handle.url} (pid ${process.pid})`);
30
+ log.info(`独立服务启动 ${handle.url} (pid ${process.pid}, proto ${SERVER_PROTO_VERSION}),内存流缓冲 streamBuf 初始为空(新进程不复用旧内存,旧进程追踪中的命令状态需 agent 重连后重新上报)`);
31
31
  // 空闲自动关闭:无任何 connected 会话持续 idleShutdownMs 后退出(0=不关闭)
32
32
  if (idleShutdownMs > 0) {
33
33
  let idleSince = Date.now();
@@ -1 +1 @@
1
- {"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../src/server-entry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../src/server-entry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../src/server-manager.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAIrC,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,CAAA;IACZ,WAAW;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,MAAM,EAAE,OAAO,CAAA;CAChB;AAgMD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,OAAO,EAAE,EAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAW,GAChB,OAAO,CAAC,YAAY,CAAC,CAQvB"}
1
+ {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../src/server-manager.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAIrC,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,CAAA;IACZ,WAAW;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,MAAM,EAAE,OAAO,CAAA;CAChB;AA8ND;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,OAAO,EAAE,EAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAW,GAChB,OAAO,CAAC,YAAY,CAAC,CAQvB"}
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url";
7
7
  import { spawn } from "node:child_process";
8
8
  import { createServer } from "node:net";
9
9
  import { SERVER_PROTO_VERSION } from "./constants.js";
10
- import log from "./log.js";
10
+ import log, { infoDedupShared } from "./log.js";
11
11
  const LOCK_DIR = "server.lock";
12
12
  const INFO_FILE = "server.json";
13
13
  /** 锁目录内的属主信息文件名(pid + 创建时间,用于判定陈旧锁) */
@@ -42,6 +42,27 @@ async function probe(port) {
42
42
  return false;
43
43
  }
44
44
  }
45
+ /**
46
+ * 读取端口上服务 /health 自证的身份(其自身进程 pid),用于终止前校验归属。
47
+ * 取不到 / 超时 / 响应非 2xx / 响应体异常 / 无 pid 字段均返回 null,表示"身份未知"。
48
+ * @param port 待探测端口
49
+ * @returns 服务自报 pid;无法确认时返回 null
50
+ */
51
+ async function probeServerPid(port) {
52
+ try {
53
+ const ctrl = new AbortController();
54
+ const timer = setTimeout(() => ctrl.abort(), PROBE_TIMEOUT);
55
+ const r = await fetch(`http://127.0.0.1:${port}/health`, { signal: ctrl.signal });
56
+ clearTimeout(timer);
57
+ if (!r.ok)
58
+ return null;
59
+ const body = (await r.json());
60
+ return typeof body?.pid === "number" ? body.pid : null;
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
45
66
  /**
46
67
  * 预检端口在本机 127.0.0.1 能否绑定(快速失败):
47
68
  * 固定端口落在系统保留区间时立即得到 EACCES,无需 spawn 子进程后干等启动超时。
@@ -157,29 +178,37 @@ function acquireLock(dir) {
157
178
  return create();
158
179
  }
159
180
  /**
160
- * 杀掉可能仍在运行的旧服务进程并等待端口释放:
181
+ * 杀掉可能仍在运行的旧服务进程并等待端口释放(跨平台,不依赖 lsof/wmic):
161
182
  * detached 子进程不随插件进程退出,升级后旧进程可能仍占住端口,
162
183
  * 必须显式 kill 后再 spawn,否则新进程 bind 失败。
184
+ * 杀之前先向 info.port 取 /health 自证身份:仅当响应 pid 与 info.pid 一致才发 SIGTERM,
185
+ * 防止 server.json 残留的 pid 已被系统回收给无关进程时误杀。
186
+ * /health 取不到、超时、响应异常、pid 缺失或不匹配 → 一律不杀(宁可留僵尸元数据,也不误杀),
187
+ * 残留元数据(server.json / 陈旧锁)交由既有清理路径处理,随后继续启动新服务。
163
188
  * @param info 服务信息(含 pid/port)
164
- * @returns 端口是否已释放
165
189
  */
166
190
  async function killStale(info) {
167
191
  if (!info)
168
- return true;
192
+ return;
193
+ const selfPid = await probeServerPid(info.port);
194
+ if (selfPid === null || selfPid !== info.pid) {
195
+ log.info(`跳过终止 pid=${info.pid}:其不在我们的端口 ${info.port} 上服务 / pid 归属不符(端口自报 pid=${selfPid ?? "未知"}),仅清理残留元数据`);
196
+ return;
197
+ }
169
198
  try {
170
199
  process.kill(info.pid, "SIGTERM");
200
+ log.info(`终止旧独立服务 pid=${info.pid}(端口 ${info.port},等待端口释放)`);
171
201
  }
172
202
  catch {
173
203
  // 进程可能已退出或无权 kill,交由端口探测判断
174
204
  }
175
205
  const deadline = Date.now() + KILL_WAIT_MAX;
176
206
  while (Date.now() < deadline) {
177
- const alive = await probe(info.port);
178
- if (!alive)
179
- return true;
207
+ if (!(await probe(info.port)))
208
+ return;
180
209
  await new Promise((r) => setTimeout(r, 200));
181
210
  }
182
- return false;
211
+ log.warn(`旧独立服务 pid=${info.pid} 未在 ${KILL_WAIT_MAX}ms 内释放端口 ${info.port},继续尝试启动新服务`);
183
212
  }
184
213
  /** 失败结果:url 为空串,调用方据此判定服务不可用(命令执行不受影响) */
185
214
  function failedResult() {
@@ -219,14 +248,18 @@ export function ensureServer(port, getSessions, dir, lang = "en") {
219
248
  */
220
249
  async function ensureServerOnce(port, _getSessions, dir, lang = "en") {
221
250
  mkdirSync(dir, { recursive: true });
251
+ /** 本次被终止/判定为陈旧的旧服务 pid(用于日志对齐"旧 pid → 新 pid"的替换关系) */
252
+ let replacedPid = null;
222
253
  // 1. 探测既有服务(固定端口场景可复用;旧版本实例不复用,杀旧后新启)
223
254
  if (port > 0) {
224
255
  const info = readInfo(dir);
225
256
  if (isCurrentVersion(info) && info.port === port && (await probe(port))) {
257
+ infoDedupShared(`reuse-service:${port}`, `复用现有独立服务 pid=${info.pid} port=${port}(proto ${info.proto})`, 10000);
226
258
  return { server: null, url: `http://127.0.0.1:${port}`, port, reused: true };
227
259
  }
228
260
  if (info && info.port === port && (await probe(port)) && !isCurrentVersion(info)) {
229
261
  log.info(`检测到旧版服务 pid=${info.pid}(proto ${info.proto ?? "?"}),重启独立服务`);
262
+ replacedPid = info.pid;
230
263
  await killStale(info);
231
264
  }
232
265
  }
@@ -240,9 +273,11 @@ async function ensureServerOnce(port, _getSessions, dir, lang = "en") {
240
273
  await new Promise((r) => setTimeout(r, 200));
241
274
  const info = readInfo(dir);
242
275
  if (info && isCurrentVersion(info) && (await probe(info.port))) {
276
+ infoDedupShared(`reuse-service:${info.port}`, `复用现有独立服务 pid=${info.pid} port=${info.port}(锁竞争等待后探测到)`, 10000);
243
277
  return { server: null, url: `http://127.0.0.1:${info.port}`, port: info.port, reused: true };
244
278
  }
245
279
  if (info && !isCurrentVersion(info) && (await probe(info.port))) {
280
+ replacedPid = info.pid;
246
281
  await killStale(info);
247
282
  }
248
283
  acquired = acquireLock(dir);
@@ -253,8 +288,10 @@ async function ensureServerOnce(port, _getSessions, dir, lang = "en") {
253
288
  try {
254
289
  // 3. 拿锁成功:先清残留旧进程(可能 pid 已退出或锁内刚杀掉),再启动新版
255
290
  const leftover = readInfo(dir);
256
- if (leftover && !isCurrentVersion(leftover))
291
+ if (leftover && !isCurrentVersion(leftover)) {
292
+ replacedPid = leftover.pid;
257
293
  await killStale(leftover);
294
+ }
258
295
  // 固定端口:spawn 前预检可绑定,绑定被拒(如 Windows 保留区间 EACCES)立即失败,不回退不重试
259
296
  if (port > 0) {
260
297
  const code = await probeBindable(port);
@@ -273,6 +310,12 @@ async function ensureServerOnce(port, _getSessions, dir, lang = "en") {
273
310
  }
274
311
  const info = readInfo(dir);
275
312
  if (info && isCurrentVersion(info) && (await probe(info.port))) {
313
+ if (replacedPid !== null) {
314
+ log.info(`独立服务已替换 ${replacedPid} -> ${info.pid}(port ${info.port})`);
315
+ }
316
+ else {
317
+ log.info(`独立服务已启动 pid=${info.pid} port=${info.port}(本进程启动,非复用)`);
318
+ }
276
319
  return { server: null, url: `http://127.0.0.1:${info.port}`, port: info.port, reused: false };
277
320
  }
278
321
  await new Promise((r) => setTimeout(r, 200));
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../src/server-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../src/server-manager.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,MAAM,EAAwB,MAAM,WAAW,CAAA;AAO3E,OAAO,EAAoB,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAIvD,MAAM,WAAW,WAAW;IAC1B,UAAU,IAAI;QAAE,QAAQ,IAAI,OAAO,EAAE,CAAA;KAAE,CAAA;IACvC,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAaD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IACnC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAuCD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,YAAY,EAAE,EAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAW,EACjB,aAAa,SAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA+cvB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,MAAM,EAAwB,MAAM,WAAW,CAAA;AAO3E,OAAO,EAAoB,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAIvD,MAAM,WAAW,WAAW;IAC1B,UAAU,IAAI;QAAE,QAAQ,IAAI,OAAO,EAAE,CAAA;KAAE,CAAA;IACvC,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAaD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IACnC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAkDD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,YAAY,EAAE,EAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAW,EACjB,aAAa,SAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAmfvB"}
package/dist/server.js CHANGED
@@ -9,7 +9,7 @@ import { WebSocketServer, WebSocket } from "ws";
9
9
  import { listAllSessions, removeSessionState } from "./session-store.js";
10
10
  import { tr } from "./i18n.js";
11
11
  import { PTY_COLS, PTY_ROWS } from "./constants.js";
12
- import log from "./log.js";
12
+ import log, { infoDedup } from "./log.js";
13
13
  const PAGE_KEYS = [
14
14
  "web_title",
15
15
  "web_loading",
@@ -33,6 +33,16 @@ const JS_I18N_KEYS = {
33
33
  };
34
34
  const STATUS_PUSH_MS = 2000;
35
35
  const sessionKey = (sid, name) => `${sid}:${name}`;
36
+ /**
37
+ * 会话键(`sid:name`)转日志显示形式(`sid/name`):与终端侧 `[busy]`/`[run]` 行同一写法,
38
+ * 保证所有带会话上下文的日志都能用同一个 `<主会话ID>/<终端名>` 口径 grep。
39
+ * @param sKey 会话键(sid:name)
40
+ * @returns 显示用标签(ses_xxx/default);无分隔符时原样返回
41
+ */
42
+ const keyTag = (sKey) => {
43
+ const i = sKey.indexOf(":");
44
+ return i < 0 ? sKey : `${sKey.slice(0, i)}/${sKey.slice(i + 1)}`;
45
+ };
36
46
  export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs = 100) {
37
47
  let actualPort = port;
38
48
  const webDir = join(dirname(fileURLToPath(import.meta.url)), "web");
@@ -44,12 +54,28 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
44
54
  const cmdCount = new Map();
45
55
  /** 排队序列保持 busy 的 key(agent 报 more=true 加入,最后一条 done 移除) */
46
56
  const seqHold = new Set();
57
+ /** server 侧各终端最近一次的对外 busy 状态(仅用于日志:翻转时记一行) */
58
+ const busyState = new Map();
59
+ /**
60
+ * 记录 server 侧 busy 翻转(仅在值变化时输出一行,带 session/终端/原因):
61
+ * 与终端侧 [busy] 行互补,便于对齐"server 认为忙/闲"的时间线。
62
+ * @param sKey 会话键(sid:name)
63
+ * @param next 目标 busy 值
64
+ * @param reason 翻转原因(cmdStart / cmdDone / exec / 无 agent 强制 done / 状态文件回退 等)
65
+ */
66
+ const logBusy = (sKey, next, reason) => {
67
+ if (busyState.get(sKey) === next)
68
+ return;
69
+ busyState.set(sKey, next);
70
+ log.info(`[busy] server ${keyTag(sKey)} busy=${next} reason=${reason}`);
71
+ };
47
72
  const server = createServer((req, res) => {
48
73
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
49
74
  const path = url.pathname;
50
75
  if (path === "/health") {
76
+ // 自证身份:返回本服务进程 pid,供 ensureServer 在终止旧进程前校验归属(防 pid 复用误杀)
51
77
  res.writeHead(200, { "Content-Type": "application/json" });
52
- res.end(JSON.stringify({ ok: true }));
78
+ res.end(JSON.stringify({ ok: true, pid: process.pid }));
53
79
  return;
54
80
  }
55
81
  if (path === "/") {
@@ -121,16 +147,15 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
121
147
  const seen = new Set();
122
148
  const liveKey = new Set(agentBySession.keys());
123
149
  const liveBusy = new Map();
124
- const now = Date.now();
125
- // 兜底:streamBuf 中 agent 连接已消失的 key 强制清 busy(agent 崩溃/退出防卡死)。
126
- // 注意不能用"无 out 超时"判定——交互命令(sudo/read 等输入)等待期间无输出,
127
- // 但 agent 仍在,命令未完成,busy 必须保持 true(完成由 agent 生命周期钩子兜底,仅断连时 watch 补发 done,无超时强杀)
150
+ // 兜底:streamBuf 中 agent 连接已消失的 key —— **不假报完成**。
151
+ // agent 掉线 ≠ 命令完成:此处不 finalizeCommand、不发 diff done、不改 done 标志,
152
+ // 保持"未完成(busy 不变)"并仅把"agent 离线、命令状态未知"显式落盘(短窗去重防每 2s 刷屏);
153
+ // agent 重连会补播 cmdStart 恢复状态。注意不能用"无 out 超时"判定——交互命令(sudo/read 等输入)
154
+ // 等待期间无输出,但 agent 仍在、命令未完成,busy 必须保持 true。
155
+ // 命令真实结束只认 agent 上报的当前 seq 完成标记(cmdDone),会话拆除路径另算。
128
156
  for (const [key, b] of streamBuf) {
129
157
  if (b && !b.done && !agentBySession.has(key)) {
130
- b.done = true;
131
- b.ts = now;
132
- b.endTs = now;
133
- finalizeCommand(key);
158
+ infoDedup(`agent-offline:${key}`, `[fallback] ${keyTag(key)} 无 agent 连接:命令状态未知(保持未完成,不判完成/不发 diff done)command=${JSON.stringify((b.command ?? "").slice(0, 120))} ts=${b.ts}`);
134
159
  }
135
160
  if (!agentBySession.has(key))
136
161
  seqHold.delete(key); // agent 已消失:清排队序列 busy 保持
@@ -144,6 +169,9 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
144
169
  const busy = liveBusy.get(lk);
145
170
  if (busy !== undefined)
146
171
  s.busy = busy;
172
+ // 盲点显式化:拿不到 agent/实时流状态时,busy 回退取状态文件(可能是命令执行前写的旧值,未必可靠)
173
+ else
174
+ logBusy(lk, !!s.busy, "状态文件回退(无 agent 状态)");
147
175
  seen.add(sessionKey(s.sessionID, s.name));
148
176
  }
149
177
  const bySession = new Map();
@@ -264,6 +292,11 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
264
292
  agents.get(ws).add(k);
265
293
  agentBySession.set(k, ws);
266
294
  }
295
+ {
296
+ // 记录 agent 上报的会话列表(批量实例注册同一列表时按内容去重),便于对齐 server 侧视角
297
+ const keys = [...(agents.get(ws) ?? [])];
298
+ infoDedup(`agent-register:${keys.slice().sort().join(",")}`, `agent 注册 ${keys.length} 个会话: ${keys.length ? keys.map(keyTag).join(", ") : "无"}`);
299
+ }
267
300
  return;
268
301
  }
269
302
  if (t === "cmdStart") {
@@ -274,6 +307,7 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
274
307
  return;
275
308
  const k = sessionKey(sid, name);
276
309
  seqHold.delete(k); // 新命令开始:本条正在运行,busy 由 streamBuf 反映
310
+ logBusy(k, true, "cmdStart");
277
311
  const existing = streamBuf.get(k);
278
312
  streamBuf.set(k, {
279
313
  data: existing && existing.done ? "" : existing?.data ?? "",
@@ -355,6 +389,7 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
355
389
  else {
356
390
  streamBuf.set(k, { data: "", done: true, ts: Date.now(), endTs: typeof msg.endTs === "number" ? msg.endTs : Date.now(), command: "" });
357
391
  }
392
+ logBusy(k, msg.more === true, msg.more === true ? "cmdDone(more 保持 busy)" : "cmdDone");
358
393
  finalizeCommand(k);
359
394
  pushSessions();
360
395
  return;
@@ -485,6 +520,7 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
485
520
  const k = sessionKey(sid, name);
486
521
  const existing = streamBuf.get(k);
487
522
  streamBuf.set(k, { data: existing && existing.done ? "" : existing?.data ?? "", done: false, ts: Date.now(), command });
523
+ logBusy(k, true, "exec");
488
524
  pushSessions();
489
525
  send(agent, { type: "run-exec", reqId: `${sid}:${name}:${Date.now()}`, sessionID: sid, name, command });
490
526
  return;
@@ -518,6 +554,7 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
518
554
  catch { /* 目录不存在忽略 */ }
519
555
  streamBuf.delete(sessionKey(sid, name));
520
556
  rawBuf.delete(sessionKey(sid, name));
557
+ busyState.delete(sessionKey(sid, name));
521
558
  log.info(`Web 页删除终端 ${sid}/${name}`);
522
559
  pushSessions();
523
560
  return;
@@ -526,9 +563,12 @@ export function startServer(port, _getSessions, dir, lang = "en", _streamTickMs
526
563
  ws.on("close", () => {
527
564
  const reg = agents.get(ws);
528
565
  if (reg) {
566
+ // 盲点显式化:agent 断开时记录受影响的终端列表(仅 agent 连接,web 订阅者不在此列)
567
+ const keys = [...reg];
529
568
  for (const k of reg)
530
569
  agentBySession.delete(k);
531
570
  agents.delete(ws);
571
+ infoDedup(`agent-disconnect:${keys.slice().sort().join(",")}`, `agent 断开(受影响终端: ${keys.length ? keys.map(keyTag).join(", ") : "无"})`);
532
572
  }
533
573
  });
534
574
  });