@moonquake2004/dsh-doctor 0.4.14 → 0.4.15
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/dsh-doctor.mjs +40 -4
- package/package.json +1 -1
package/dsh-doctor.mjs
CHANGED
|
@@ -54,11 +54,11 @@
|
|
|
54
54
|
* 退出码:0 = 全部通过;1 = 发现可修复问题(内置 + catalog severity=error);warn 级失败不改退出码。
|
|
55
55
|
*/
|
|
56
56
|
import { execFileSync, spawnSync } from 'node:child_process';
|
|
57
|
-
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
57
|
+
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
58
58
|
import { createRequire } from 'node:module';
|
|
59
59
|
import net from 'node:net';
|
|
60
60
|
import { basename, delimiter as PATH_DELIM, dirname, join, relative, resolve } from 'node:path';
|
|
61
|
-
import { homedir } from 'node:os';
|
|
61
|
+
import { homedir, tmpdir } from 'node:os';
|
|
62
62
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
63
63
|
|
|
64
64
|
const HOME = process.env.DSH_HOME || join(homedir(), '.dsh');
|
|
@@ -1162,8 +1162,44 @@ function checkSession(targetPath) {
|
|
|
1162
1162
|
`日志首行不是会话头(type=${header && header.type ? JSON.stringify(header.type) : '缺失/无法解析'})——#6651:此类损坏会让 \`dsh web\` **整体启动失败**(corrupt Zstandard session log: first frame is not exactly …),会话列表一并损坏`,
|
|
1163
1163
|
'优先从备份恢复该日志;无备份时把整个会话目录**移出** sessions/(隔离,勿删)后重启 dsh,再用本工具复查');
|
|
1164
1164
|
} else {
|
|
1165
|
-
|
|
1166
|
-
|
|
1165
|
+
// 更精确的判据:harness 要求的是「**第一个 zstd 帧恰好只含一行**(即头行)」,
|
|
1166
|
+
// 见 dsh-session-persistence-jsonl:1891/2185 —— 首帧里若多裹了事件,同样抛
|
|
1167
|
+
// corrupt Zstandard session log。只查"首行是不是头"会漏掉帧边界错位这一类。
|
|
1168
|
+
let frameNote = '';
|
|
1169
|
+
let frameBad = false;
|
|
1170
|
+
if (target.endsWith('.zstd')) {
|
|
1171
|
+
try {
|
|
1172
|
+
const raw = readFileSync(target);
|
|
1173
|
+
const magic = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
|
|
1174
|
+
const offs = [];
|
|
1175
|
+
for (let i = 0; i <= raw.length - 4; i++) {
|
|
1176
|
+
if (raw[i] === magic[0] && raw[i + 1] === magic[1] && raw[i + 2] === magic[2] && raw[i + 3] === magic[3]) offs.push(i);
|
|
1177
|
+
}
|
|
1178
|
+
if (offs.length >= 2) {
|
|
1179
|
+
const tmp = join(tmpdir(), `dsh-doctor-firstframe-${process.pid}.zst`);
|
|
1180
|
+
writeFileSync(tmp, raw.subarray(0, offs[1]));
|
|
1181
|
+
let first = '';
|
|
1182
|
+
try { first = execFileSync('zstd', ['-dc', tmp], { maxBuffer: 16 * 1024 * 1024 }).toString('utf8'); }
|
|
1183
|
+
finally { try { unlinkSync(tmp); } catch { /* 清理失败不致命 */ } }
|
|
1184
|
+
const frameLines = first.split('\n').filter((l) => l.trim());
|
|
1185
|
+
if (frameLines.length !== 1) {
|
|
1186
|
+
frameBad = true;
|
|
1187
|
+
frameNote = `首帧含 ${frameLines.length} 行(应为 1 行头)——帧边界错位同样会让 harness 抛 corrupt Zstandard session log`;
|
|
1188
|
+
}
|
|
1189
|
+
} else {
|
|
1190
|
+
frameBad = true;
|
|
1191
|
+
frameNote = '仅 1 个 zstd 帧(首帧裹住了全部行)——harness 要求首帧恰好一行,与 #1043 同族';
|
|
1192
|
+
}
|
|
1193
|
+
} catch { frameNote = '(首帧边界无法确认,未据此判定)'; }
|
|
1194
|
+
}
|
|
1195
|
+
if (frameBad) {
|
|
1196
|
+
report('session', 'S13', false,
|
|
1197
|
+
`会话头存在但**首帧边界不合规**:${frameNote}`,
|
|
1198
|
+
'优先从备份恢复;无备份时把整个会话目录移出 sessions/(隔离,勿删)后重启 dsh,再用本工具复查');
|
|
1199
|
+
} else {
|
|
1200
|
+
report('session', 'S13', true,
|
|
1201
|
+
`会话头完整(type=session, version=${header.version ?? '?'}, id=${String(header.id ?? '').slice(0, 12)})${frameNote}`);
|
|
1202
|
+
}
|
|
1167
1203
|
}
|
|
1168
1204
|
}
|
|
1169
1205
|
const calls = new Map(); const results2 = new Set(); let maxSeq = -1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moonquake2004/dsh-doctor",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.15",
|
|
4
4
|
"description": "Offline diagnostic for DeepSeek Harness — 28 built-in + 5 catalog checks across env/profile/session (Layer A checks-as-data), self-update (Layer B), and a semi-automatic LLM observer (Layer C, --observe); Doctor panel in web UI settings.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|