From e0f7f2477c3b57c25044211cb706fec690bfceae Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 2 Oct 2026 04:05:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=9C=A8=20dsh=200.2.0=20=E4=B8=8B=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=B4=A9=E6=8E=89=EF=BC=88ERR=5FMODULE=5FNOT=5FFOUND?= =?UTF-8?q?=EF=BC=89=EF=BC=8C=E4=B8=94=E6=BC=8F=E8=AE=A4=20v4=20=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 升级到 0.2.0-rc.2 后 `verify-mail-sessions-readable.mjs` **一条都验不了**: 1) 依赖不再嵌在 `/node_modules/@deepseek-ai/`,而是平铺到 `/usr/lib/node_modules/@deepseek-ai/` ⇒ import 直接 ERR_MODULE_NOT_FOUND; 2) 会话文件新增 **v4**(`session.v4.jsonl.zstd`),walk 只认 v0+v3 ⇒ 本条线索的 `mail-f8f9a840`(v3+v4 共存、**无 v0**)会被**整目录漏掉**。 ★ 关键点:这两种失败都长得像"会话不可读",但**都不是**。 1 是脚本自己崩了(连候选数都出不来);2 是**漏扫**(少算而不是算错)。 —— "工具报错"与"数据坏"必须分开,否则会把脚本的年龄当成磁盘的病情。 ## 实测(0.2.0-rc.2 修好后) --prefix mail- : 候选 55 可读 55 不可读 0 <- 邮件通道全绿 mail-f8f9a840(.new 线索): 可读,1623 events mail-d042cc4c(老线索) : 可读,56012 events 全盘 /root/.dsh/sessions : 候选 148 可读 119 不可读 29 那 29 个不可读**全部**是既有的独立缺陷 (`subagent/descriptor ... unsupported descriptor version 2`,去重后仅此一种), **没有一个是 mail-*** ⇒ 与邮件通道无关,仍不建议混进同一个 repair。 修法:先探两个候选根再 import(不靠报错"感觉"哪个对), 并把 v4 加进 SESSION_FILES。 --- scripts/verify-mail-sessions-readable.mjs | 26 +++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/scripts/verify-mail-sessions-readable.mjs b/scripts/verify-mail-sessions-readable.mjs index e0265f2..d901191 100644 --- a/scripts/verify-mail-sessions-readable.mjs +++ b/scripts/verify-mail-sessions-readable.mjs @@ -10,15 +10,30 @@ * 用法: * node scripts/verify-mail-sessions-readable.mjs # 验 mail-* * node scripts/verify-mail-sessions-readable.mjs --root --only mail- + * node scripts/verify-mail-sessions-readable.mjs --prefix mail- # 目录名严格前缀 * * 退出码:0 = 全部可读;1 = 存在不可读(打印 id 与逐字错误)。 + * + * ★ 0.2.0 的安装布局变了(2026-09-19/20 实测):依赖**不再嵌在** + * `/node_modules/@deepseek-ai/` 下,而是**平铺**到 + * `/usr/lib/node_modules/@deepseek-ai/`;会话文件多出 + * `session.v3.jsonl.zstd` 与 **v4**(`session.v4.jsonl.zstd`)。 + * ⇒ 下面**先探两个位置**再 import,且 walk 认 v4 —— 否则脚本会以 + * `ERR_MODULE_NOT_FOUND` 直接崩掉,而**那不是会话不可读的证据**。 */ -import { readdirSync, statSync } from "node:fs"; +import { readdirSync, statSync, existsSync } from "node:fs"; import { join } from "node:path"; +import { createRequire } from "node:module"; const dsRoot = process.env.DSH_INSTALL ?? "/usr/lib/node_modules/@deepseek-ai/dsh"; -const NM = join(dsRoot, "node_modules/@deepseek-ai"); +// 0.1.5 是嵌套布局,0.2.0 是平铺布局;两个都试,且不靠报错来"感觉"哪个对。 +const CANDIDATE_ROOTS = [ + join(dsRoot, "node_modules/@deepseek-ai"), + "/usr/lib/node_modules/@deepseek-ai", +]; +const NM = CANDIDATE_ROOTS.find((r) => existsSync(join(r, "dsh-session-persistence-jsonl/lib/index.js"))) ?? CANDIDATE_ROOTS[0]; +const require_ = createRequire(join(NM, "x.js")); const { default: JsonlSessionPersistence } = await import(join(NM, "dsh-session-persistence-jsonl/lib/index.js")); const argv = process.argv.slice(2); @@ -35,7 +50,6 @@ const ONLY = argOf("--only", ""); const PREFIX = argOf("--prefix", ""); const { Context } = await import(join(NM, "cordis/lib/index.js")); - // 桥建实例时注入的最小 ctx:Persistence 继承 cordis Service, // 构造时会用 ctx.reflect.provide(...),所以不能拿普通字面量顶, // 必须给一个真的 Context 实例。 @@ -44,12 +58,16 @@ ctx.logger = { warn() {}, info() {}, error() {}, debug() {} }; const persistence = new JsonlSessionPersistence(ctx, { root: ROOT }); +// 0.2.0 起会话文件可能是 v0 / v3 / **v4**;只认 v0+v3 会漏掉 v4-only 的新会话 +// (本条线索的 `mail-f8f9a840` 就是 v3+v4 共存、且**没有** v0 的那类)。 +const SESSION_FILES = new Set(["session.jsonl.zstd", "session.v3.jsonl.zstd", "session.v4.jsonl.zstd"]); + /** 找出所有 // 目录,返回 {store, id}。 */ function* walk(dir) { for (const name of readdirSync(dir)) { const p = join(dir, name); if (statSync(p).isDirectory()) yield* walk(p); - else if (name === "session.jsonl.zstd" || name === "session.v3.jsonl.zstd") yield p; + else if (SESSION_FILES.has(name)) yield p; } }