@moonquake2004/dsh-doctor 0.4.9 → 0.4.13
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 +34 -4
- package/package.json +1 -1
package/dsh-doctor.mjs
CHANGED
|
@@ -212,6 +212,15 @@ function readableSessionEventTypes() {
|
|
|
212
212
|
|
|
213
213
|
const READABLE = readableSessionEventTypes();
|
|
214
214
|
|
|
215
|
+
/**
|
|
216
|
+
* 是否存在值得诊断的 DSH 环境(真实用户机器有 sessions/ 或 settings.yaml;干净容器/仓库检出没有)。
|
|
217
|
+
* 以传入的 home 为准:探针应当判断"它被告知的那个环境",而不是进程全局的 HOME ——
|
|
218
|
+
* 这样单测可以显式构造两种环境,fixture 也不会被真实 HOME 的状态污染。
|
|
219
|
+
*/
|
|
220
|
+
function hasDshEnvironment(home = HOME) {
|
|
221
|
+
return existsSync(join(home, 'sessions')) || existsSync(join(home, 'settings.yaml'));
|
|
222
|
+
}
|
|
223
|
+
|
|
215
224
|
function report(section, id, ok, detail, fix, src) {
|
|
216
225
|
results.push({ section, id, ok, detail, fix, src: src ?? 'builtin' });
|
|
217
226
|
}
|
|
@@ -274,6 +283,14 @@ function checkEnv() {
|
|
|
274
283
|
for (const d of readdirSync(pnpmStore)) if (d.startsWith('node-pty@')) ptyDirs.push(join(pnpmStore, d, 'node_modules', 'node-pty'));
|
|
275
284
|
}
|
|
276
285
|
const plat = `${process.platform}-${process.arch}`;
|
|
286
|
+
// 无对象可查时 skip 而非 fail(2026-09 修正):E4 的判据是"**已安装的** dsh 里 node-pty 是否完整",
|
|
287
|
+
// 但此前在**没有任何 node_modules 的合成 HOME**(测试 fixture、全新环境)里也会报"未找到 node-pty" ——
|
|
288
|
+
// 那不是"缺失",而是"这里根本没有安装树可查"。据此报 fail 会让 fixture 全红、也会让 CI 在
|
|
289
|
+
// 干净容器里得到无意义的 exit 2。与项目一贯纪律一致:不适用 ⇒ skip 且带 reason。
|
|
290
|
+
// "有安装树可查" = PATH 里找到了 dsh 的 node_modules,**或**本 HOME 的 profile 里有 node_modules。
|
|
291
|
+
// 二者皆无(合成 HOME、干净容器)→ 这里没有"已安装的 dsh"可言,报 fail 是无意义的。
|
|
292
|
+
const fromPath = ptyDirs.length > 0 && existsSync(ptyDirs[0]);
|
|
293
|
+
const hasInstall = fromPath || existsSync(profileNM);
|
|
277
294
|
const ptyFound = ptyDirs.filter((d) => existsSync(d));
|
|
278
295
|
let ptyBinary = null;
|
|
279
296
|
for (const d of ptyFound) {
|
|
@@ -282,7 +299,8 @@ function checkEnv() {
|
|
|
282
299
|
}
|
|
283
300
|
if (ptyBinary) break;
|
|
284
301
|
}
|
|
285
|
-
if (
|
|
302
|
+
if (!hasInstall) reportSkip('env', 'E4', '未发现 DSH 安装树(无 profiles/node_modules 可查),跳过 node-pty 完整性检测');
|
|
303
|
+
else if (ptyFound.length === 0) report('env', 'E4', false, '未找到 node-pty(dsh web 终端依赖它,#1219)', '重新安装 @deepseek-ai/dsh,确保 node-pty 装全');
|
|
286
304
|
else if (ptyBinary) report('env', 'E4', true, `node-pty 原生模块在位(${plat})`, undefined);
|
|
287
305
|
else report('env', 'E4', false, `node-pty 存在但缺 ${plat} 原生二进制(#1219: dsh web 启动失败)`, '重装 node-pty(npm rebuild node-pty)或从源码构建');
|
|
288
306
|
|
|
@@ -1638,8 +1656,14 @@ export function runCatalogCheck(check, ctx) {
|
|
|
1638
1656
|
switch (probe.type) {
|
|
1639
1657
|
case 'command-exists': {
|
|
1640
1658
|
const found = findCommand(probe.cmd);
|
|
1641
|
-
|
|
1642
|
-
|
|
1659
|
+
if (found) return { ok: true, detail: check.detailOk ?? `${probe.cmd} 在 PATH: ${found}` };
|
|
1660
|
+
// 无 DSH 环境可言时 skip(2026-09):在干净容器/仓库检出里跑本工具时,dsh 当然不在 PATH ——
|
|
1661
|
+
// 那不是"用户环境有问题",而是"这里没有被诊断的 DSH 环境"。据此报 error 会让 CI 与 fixture
|
|
1662
|
+
// 得到无意义的失败(CI 三次红都源于同类检查:E4 → E1-pnpm → E7)。
|
|
1663
|
+
if (!hasDshEnvironment(ctx?.home ?? HOME)) {
|
|
1664
|
+
return { skipped: true, detail: `未发现 DSH 环境(无 sessions/ 与 settings.yaml),跳过 ${probe.cmd} 的 PATH 检查` };
|
|
1665
|
+
}
|
|
1666
|
+
return { ok: false, detail: check.detailFail ?? `${probe.cmd} 不在 PATH` };
|
|
1643
1667
|
}
|
|
1644
1668
|
case 'path-exists':
|
|
1645
1669
|
case 'path-is-dir':
|
|
@@ -2012,7 +2036,13 @@ async function run() {
|
|
|
2012
2036
|
console.log(JSON.stringify(out, null, 2));
|
|
2013
2037
|
process.exit(exitCode);
|
|
2014
2038
|
} else if (jsonOut) {
|
|
2015
|
-
|
|
2039
|
+
// 每条检查带上 status(pass/warn/fail/skip,与 --envelope 同一词汇表)。
|
|
2040
|
+
// 2026-09:此前 --json 只给 ok 布尔,消费者(含我们自己的测试助手)无法区分
|
|
2041
|
+
// "warn 级失败"(如 CI 上无 pnpm → E1-pnpm warn,不翻退出码)与"error 级失败",
|
|
2042
|
+
// 于是把 warn 当成误报。状态本就不该由消费者自行推导。
|
|
2043
|
+
const statusOf = (r) => (r.skip ? 'skip' : (!r.ok ? (((r.section === 'security') ? r.severity !== 'critical' : catalogSeverity.get(r.id) === 'warn') ? 'warn' : 'fail') : 'pass'));
|
|
2044
|
+
const checksWithStatus = results.map((r) => ({ ...r, status: statusOf(r) }));
|
|
2045
|
+
console.log(JSON.stringify({ ok: bad.length === 0 && secExit === 0, checks: checksWithStatus, catalog: catalogMeta, update: updateInfo, ...(securityMeta.enabled ? { security: securityMeta } : {}) }, null, 2));
|
|
2016
2046
|
} else {
|
|
2017
2047
|
const sectionOrder = { env: 0, profile: 1, session: 2, catalog: 3 };
|
|
2018
2048
|
const ordered = [...results].sort((a, b) => (sectionOrder[a.section] ?? 9) - (sectionOrder[b.section] ?? 9));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moonquake2004/dsh-doctor",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
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": [
|