dsh-db-tool 0.1.8 → 1.2.0
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 +6 -4
- package/dist/adapters/index.js +1 -1
- package/dist/adapters/mongodb/index.js +51 -16
- package/docs/dsh-db-tool /351/224/231/350/257/257/350/256/260/345/275/225.txt" +66 -0
- package/docs/dsh/346/217/222/344/273/266/345/256/211/350/243/205/351/227/256/351/242/230/350/256/260/345/275/225-20260928.md +309 -0
- package/docs/dsh/346/217/222/344/273/266/351/227/256/351/242/230/350/247/243/345/206/263/346/226/271/346/241/210-20260928.md +166 -0
- package/docs/install.md +1 -0
- package/docs//344/270/212/346/270/270issue/350/215/211/347/250/277-20260928.md +133 -0
- package/package.json +8 -3
- package/patches/dsh-app-boot-route-scoped-hotfix.patch +15 -1
- package/scripts/build-mongodb.mjs +62 -0
- package/scripts/hotfix-core.d.mts +5 -0
- package/scripts/hotfix-core.mjs +99 -25
- package/vendor/mongodb-driver.cjs +28132 -0
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ dsh plugin --profile web add "dsh-db-tool@github:mengqi1436/dsh-db-tool"
|
|
|
36
36
|
dsh plugin --profile web add "link:E:\path\to\dsh-db-tool"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
GaussDB 官方驱动未发布 npm,需先构建 vendor:`npm run build:gaussdb`(PowerShell)或 `bash scripts/build-gaussdb.sh`;运行要求 Node ≥ 22.12(产物依赖 p-limit@7 纯 ESM)。oracledb 安装脚本需 `npm approve-scripts oracledb
|
|
39
|
+
GaussDB 官方驱动未发布 npm,需先构建 vendor:`npm run build:gaussdb`(PowerShell)或 `bash scripts/build-gaussdb.sh`;运行要求 Node ≥ 22.12(产物依赖 p-limit@7 纯 ESM)。oracledb 安装脚本需 `npm approve-scripts oracledb`。mongodb 驱动已 bundle 进发布包(`vendor/mongodb-driver.cjs`,esbuild 构建,`npm run build:mongodb` 可重建),依赖树中不含 mongodb/punycode,详见 [docs/install.md](docs/install.md)。
|
|
40
40
|
|
|
41
41
|
## 安全模型
|
|
42
42
|
|
|
@@ -52,7 +52,7 @@ GaussDB 官方驱动未发布 npm,需先构建 vendor:`npm run build:gaussdb
|
|
|
52
52
|
|
|
53
53
|
症状:DSH 启动后插件加载报 `failed to import`,伴随 `TypeError: Cannot read properties of null (reading 'Symbol(Symbol.iterator)')`,栈指向 `dsh-app-boot` 的 `routeScoped`。
|
|
54
54
|
|
|
55
|
-
根因:上游 `@deepseek-ai/dsh-app-boot` 对 `createRequire(parent).resolve.paths(name)` 直接做 `for..of`,而 Node 对 core-module 同名包(`punycode` 等)返回 `null`,hoisted profile 下凡依赖树含此类 npm
|
|
55
|
+
根因:上游 `@deepseek-ai/dsh-app-boot` 对 `createRequire(parent).resolve.paths(name)` 直接做 `for..of`,而 Node 对 core-module 同名包(`punycode` 等)返回 `null`,hoisted profile 下凡依赖树含此类 npm 包的插件都会炸。`0.1.7-rc.2` 中共两处同型缺陷:`routeScoped()` 与 `nativePackageDir()`,本补丁一并修复(两处分别独立判定,已打过旧版单处补丁的机器只会补上缺的那处)。
|
|
56
56
|
|
|
57
57
|
一键修复(幂等,应用前自动备份为 `index.js.bak-hotfix`;`--revert` 可还原):
|
|
58
58
|
|
|
@@ -63,6 +63,8 @@ npm run patch:dsh:sh # macOS / Linux
|
|
|
63
63
|
|
|
64
64
|
脚本自动探测 DSH 安装根(`--dsh-root` 可显式指定);补丁文件见 `patches/dsh-app-boot-route-scoped-hotfix.patch`,仅对 `0.1.7-rc.2` 声明兼容,其他版本会警告(`--force` 覆盖)。上游 issue:<https://github.com/mengqi1436/dsh-db-tool/issues>(占位,待上游仓库开放后替换)。
|
|
65
65
|
|
|
66
|
+
**本插件的免补丁路径(0.1.9+)**:该 bug 的触发条件是依赖树中出现 core-module 同名包,mongodb 链(`mongodb-connection-string-url → whatwg-url → tr46 → punycode`)正是元凶。0.1.9 起 mongodb 驱动经 esbuild bundle 为 `vendor/mongodb-driver.cjs` 随包发布,生产依赖树不再含 mongodb 与 punycode——在**未修复宿主**(含桌面版 app.asar,无法打补丁)上也能正常安装加载。守卫测试 `tests/guard/deps-core-collision.spec.ts` 断言依赖树永不回退(dependencies 白名单 + lockfile 生产树 core 同名包零交集)。`patch:dsh` 仍保留,用于修复**其他**含同类依赖的插件或宿主自身报错。
|
|
67
|
+
|
|
66
68
|
## 测试
|
|
67
69
|
|
|
68
70
|
```bash
|
|
@@ -79,8 +81,8 @@ npx stryker run # 变异测试(范围 lib/guard + lib/manager + lib/store,
|
|
|
79
81
|
lib/ host 插件(store / adapters×8 / guard / manager / http / index)
|
|
80
82
|
client/ 侧边栏单文件产物(client.js,即源码)
|
|
81
83
|
skills/ db-admin skill
|
|
82
|
-
scripts/ GaussDB vendor 构建、DSH dsh-app-boot 热修复(patch:dsh)
|
|
84
|
+
scripts/ GaussDB vendor 构建、mongodb 驱动 bundle(build:mongodb)、DSH dsh-app-boot 热修复(patch:dsh)
|
|
83
85
|
docs/ 安装、HTTP 契约(api-contract.md)、skill 说明
|
|
84
86
|
tests/ vitest(离线 mock + DBT_TEST_* 门控真机)
|
|
85
|
-
vendor/ gaussdb-
|
|
87
|
+
vendor/ gaussdb 构建源/产物与 mongodb-driver.cjs bundle(gitignore,发布经 files 白名单收录 bundle)
|
|
86
88
|
```
|
package/dist/adapters/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const INSTALL_HINTS = {
|
|
|
15
15
|
gaussdb: 'npm run build:gaussdb(构建 vendor/gaussdb-pg)',
|
|
16
16
|
sqlite: 'npm install better-sqlite3',
|
|
17
17
|
redis: 'npm install redis',
|
|
18
|
-
mongodb: 'npm
|
|
18
|
+
mongodb: 'npm run build:mongodb(构建 vendor/mongodb-driver.cjs;发布包已内置产物,仅在缺失时需要)',
|
|
19
19
|
oracle: 'npm install oracledb',
|
|
20
20
|
dmdb: 'npm install dmdb',
|
|
21
21
|
};
|
|
@@ -10,8 +10,36 @@
|
|
|
10
10
|
* - execute() 写白名单;updateMany/deleteMany 空 filter 直接拒绝(适配器级防线)。
|
|
11
11
|
* - 错误判定用 instanceof MongoServerError(官方建议不解析 message)。
|
|
12
12
|
* - 只读账号由用户配置官方内置角色 read / readWrite(见文档)。
|
|
13
|
+
* - 驱动不进依赖树:mongodb 经 esbuild bundle 成 vendor/mongodb-driver.cjs(见
|
|
14
|
+
* scripts/build-mongodb.mjs),运行时经 createRequire 相对加载(不经宿主
|
|
15
|
+
* dsh-app-boot 的模块解析器,规避其 resolve.paths 未防护的 for..of bug,
|
|
16
|
+
* 该 bug 会因依赖树中的 punycode 等核心模块同名包直接炸掉插件加载)。
|
|
17
|
+
* bson 保持 dependencies(bundle 的 external),保证 BSON 类实例与外部一致。
|
|
13
18
|
*/
|
|
14
|
-
import {
|
|
19
|
+
import { createRequire } from 'node:module';
|
|
20
|
+
let vendorCache;
|
|
21
|
+
/** 容错加载 vendor bundle:缺失时返回 undefined(调用方降级处理),成功后缓存。
|
|
22
|
+
* 失败不缓存 → vendor 构建完成后无需重启即可恢复。 */
|
|
23
|
+
function vendorOrNull() {
|
|
24
|
+
if (vendorCache === undefined) {
|
|
25
|
+
try {
|
|
26
|
+
// 相对路径从本模块出发:dist/adapters/mongodb/ 或 lib/adapters/mongodb/ 均指向包根 vendor/
|
|
27
|
+
vendorCache = createRequire(import.meta.url)('../../../vendor/mongodb-driver.cjs');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return vendorCache;
|
|
34
|
+
}
|
|
35
|
+
/** 严格加载 vendor bundle:缺失时抛带修复指引的错误 */
|
|
36
|
+
function vendor() {
|
|
37
|
+
const m = vendorOrNull();
|
|
38
|
+
if (m === undefined) {
|
|
39
|
+
throw new Error('mongodb 驱动不可用:缺少 vendor/mongodb-driver.cjs。请在插件目录运行 npm run build:mongodb 构建后重试');
|
|
40
|
+
}
|
|
41
|
+
return m;
|
|
42
|
+
}
|
|
15
43
|
/** 危险操作:服务层拦截器用于确认流程。deleteMany/updateMany 仅空 filter 时危险(适配器已拦截);createIndex 在大集合上可能阻塞。createIndexes/dropIndexes 为单数形式别名,renameCollection 影响集合可见性。 */
|
|
16
44
|
export const DANGEROUS_OPS = new Set([
|
|
17
45
|
'dropDatabase', 'dropCollection', 'renameCollection', 'deleteMany', 'updateMany',
|
|
@@ -33,7 +61,9 @@ const CELL_TRUNC = 1000;
|
|
|
33
61
|
function trunc(s, max = CELL_TRUNC) {
|
|
34
62
|
return s.length > max ? `${s.slice(0, max)}…[截断,共${s.length}字符]` : s;
|
|
35
63
|
}
|
|
36
|
-
/** NormalizedCell 规范化:ObjectId/Decimal128/Long/Timestamp → toString();Binary → hex 截断;Date → ISO;嵌套对象/数组 → JSON 截断 1000
|
|
64
|
+
/** NormalizedCell 规范化:ObjectId/Decimal128/Long/Timestamp → toString();Binary → hex 截断;Date → ISO;嵌套对象/数组 → JSON 截断 1000。
|
|
65
|
+
* BSON 类型判别依赖 vendor bundle 的类(external bson,与外部 require('bson') 同实例);
|
|
66
|
+
* vendor 缺失时降级为普通对象处理,不阻断非 BSON 值的规范化。 */
|
|
37
67
|
export function normalizeMongoCell(v) {
|
|
38
68
|
if (v === null || v === undefined)
|
|
39
69
|
return null;
|
|
@@ -45,10 +75,11 @@ export function normalizeMongoCell(v) {
|
|
|
45
75
|
return v ? 'true' : 'false';
|
|
46
76
|
if (v instanceof Date)
|
|
47
77
|
return v.toISOString();
|
|
48
|
-
|
|
78
|
+
const M = vendorOrNull();
|
|
79
|
+
if (M && (v instanceof M.ObjectId || v instanceof M.Decimal128 || v instanceof M.Long || v instanceof M.Timestamp)) {
|
|
49
80
|
return trunc(v.toString());
|
|
50
81
|
}
|
|
51
|
-
if (v instanceof Binary)
|
|
82
|
+
if (M && v instanceof M.Binary)
|
|
52
83
|
return trunc(Buffer.from(v.buffer ?? []).toString('hex') || String(v));
|
|
53
84
|
if (typeof v === 'object') {
|
|
54
85
|
try {
|
|
@@ -120,7 +151,7 @@ export async function createMongoAdapter(conn, opts) {
|
|
|
120
151
|
}
|
|
121
152
|
else {
|
|
122
153
|
const uri = conn.url ?? buildUri(conn.fields, conn.ssl);
|
|
123
|
-
client = new MongoClient(uri, {
|
|
154
|
+
client = new (vendor().MongoClient)(uri, {
|
|
124
155
|
maxPoolSize: 10,
|
|
125
156
|
readPreference: 'primary',
|
|
126
157
|
w: 'majority',
|
|
@@ -138,7 +169,8 @@ export async function createMongoAdapter(conn, opts) {
|
|
|
138
169
|
: defaultDbName(conn.fields);
|
|
139
170
|
const db = client.db(dbName);
|
|
140
171
|
function wrap(e) {
|
|
141
|
-
|
|
172
|
+
const M = vendorOrNull();
|
|
173
|
+
if (M && e instanceof M.MongoServerError) {
|
|
142
174
|
return new Error(`MongoDB 服务端错误:${e.message}${e.codeName ? `(${e.codeName})` : ''}`);
|
|
143
175
|
}
|
|
144
176
|
return new Error(`MongoDB 错误:${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -471,16 +503,19 @@ function objectToResult(obj) {
|
|
|
471
503
|
function inferBsonType(v) {
|
|
472
504
|
if (v === null)
|
|
473
505
|
return 'null';
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
506
|
+
const M = vendorOrNull();
|
|
507
|
+
if (M) {
|
|
508
|
+
if (v instanceof M.ObjectId)
|
|
509
|
+
return 'ObjectId';
|
|
510
|
+
if (v instanceof M.Decimal128)
|
|
511
|
+
return 'Decimal128';
|
|
512
|
+
if (v instanceof M.Long)
|
|
513
|
+
return 'Long';
|
|
514
|
+
if (v instanceof M.Timestamp)
|
|
515
|
+
return 'Timestamp';
|
|
516
|
+
if (v instanceof M.Binary)
|
|
517
|
+
return 'Binary';
|
|
518
|
+
}
|
|
484
519
|
if (v instanceof Date)
|
|
485
520
|
return 'date';
|
|
486
521
|
if (Array.isArray(v))
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
DSH 插件 dsh-db-tool 加载错误记录
|
|
2
|
+
=====================================
|
|
3
|
+
记录时间:2026-09-28
|
|
4
|
+
当前状态:已从 desktop profile 卸载;卸载后该错误归零,其余 12 个第三方插件全部正常。
|
|
5
|
+
|
|
6
|
+
一、错误原文
|
|
7
|
+
-------------------------------------
|
|
8
|
+
dsh: error: [/197] createRequire.resolve.paths is not a function or its return value is not iterable
|
|
9
|
+
|
|
10
|
+
对应条目:/197 id=db-tool name=dsh-db-tool status=error
|
|
11
|
+
|
|
12
|
+
出现场景:DSH 0.1.7-rc.2 桌面版,desktop profile 的插件组合检查
|
|
13
|
+
(等价 `dsh --profile desktop --dump-config-schema` 的官方加载路径)。
|
|
14
|
+
同一检查中,其余 12 个第三方插件均无错误。
|
|
15
|
+
|
|
16
|
+
二、根因(DSH 0.1.7-rc.2 自带代码的 bug)
|
|
17
|
+
-------------------------------------
|
|
18
|
+
1) DSH 自带 @deepseek-ai/dsh-app-boot 的 lib/index.js 里有 6 处
|
|
19
|
+
`createRequire(parent).resolve.paths(name)` 调用,其中 5 处未做空值防护。
|
|
20
|
+
2) Node 对「内置模块同名包」调用该 API 会返回 null
|
|
21
|
+
(本机实测:resolve.paths('punycode') 返回 null;普通包返回数组)。
|
|
22
|
+
对 null 做 for..of 即抛 TypeError —— 这就是上面的错误消息。
|
|
23
|
+
3) dsh-db-tool 的依赖链包含 npm 包 punycode:
|
|
24
|
+
dsh-db-tool → mongodb → mongodb-connection-string-url → whatwg-url → tr46 → punycode
|
|
25
|
+
因此该插件的加载路径必然触发这个 bug。
|
|
26
|
+
|
|
27
|
+
三、本机复现证据
|
|
28
|
+
-------------------------------------
|
|
29
|
+
运行环境:Electron Node(DeepSeek Harness.exe 加 --expose-internals),可直接访问 asar 内模块。
|
|
30
|
+
|
|
31
|
+
复现结果(最小用例):
|
|
32
|
+
createRequire('.../node_modules/dsh-db-tool/dist/index.js').resolve.paths('punycode') => null
|
|
33
|
+
createRequire('.../node_modules/tr46/index.js').resolve.paths('punycode') => null
|
|
34
|
+
createRequire('.../node_modules/dsh-db-tool/dist/index.js').resolve.paths('ssh2') => array[11]
|
|
35
|
+
|
|
36
|
+
DSH 官方检查的诊断输出:
|
|
37
|
+
卸载前:F:\DSH\_recon\dump-schema-err.txt (含 /197 db-tool 错误)
|
|
38
|
+
卸载后:F:\DSH\_recon\dump-schema-err-2.txt (该错误消失,只剩 DSH 内置 agent-preset 的 4 条既有诊断)
|
|
39
|
+
|
|
40
|
+
四、插件作者已知该问题(包内自带 hotfix)
|
|
41
|
+
-------------------------------------
|
|
42
|
+
dsh-db-tool 包内提供:
|
|
43
|
+
scripts/hotfix-core.mjs
|
|
44
|
+
patches/dsh-app-boot-route-scoped-hotfix.patch
|
|
45
|
+
目标:@deepseek-ai/dsh-app-boot 0.1.7-rc.2 中未防护的那行 for..of。
|
|
46
|
+
修法:resolve.paths 返回 null 时回退到标准 node_modules 搜索链。
|
|
47
|
+
|
|
48
|
+
限制(本机为何没能直接用):
|
|
49
|
+
该脚本按「文件系统安装的 DSH」定位目标(找 DSH_HOME、PATH 上的 dsh、全局 npm 目录),
|
|
50
|
+
而桌面版把 dsh-app-boot 打包在 F:\DSH\resources\app.asar 内,脚本找不到文件,无法应用。
|
|
51
|
+
|
|
52
|
+
五、可选修复路径(供向 DSH/插件作者反馈)
|
|
53
|
+
-------------------------------------
|
|
54
|
+
1) 等 DSH 上游修复(推荐):该 bug 属于 0.1.7-rc.2 自带代码,任意「依赖树含 core-module 同名包」的插件都会触发。
|
|
55
|
+
2) 重打包 app.asar 应用该 hotfix:需先关闭 DSH 应用,修改应用安装文件,版本更新时会被覆盖,有风险。
|
|
56
|
+
3) 插件侧规避:依赖树中避免引入 core-module 同名包(例如替换 punycode 的实现)。
|
|
57
|
+
|
|
58
|
+
六、本次卸载记录
|
|
59
|
+
-------------------------------------
|
|
60
|
+
卸载方式:DSH plugin-manager operations(pnpm remove + 从 dsh.profile.bundles 移除,等价插件页卸载)。
|
|
61
|
+
结果核对:依赖 13 → 12;bundles 17 → 16;传递依赖 mongodb / punycode 等已一并清理。
|
|
62
|
+
其余 12 个插件的运行时依赖健康检查全部通过(ssh2 纯 JS 可用、better-sqlite3/oracledb 可用、rtk 0.50.0 可用)。
|
|
63
|
+
|
|
64
|
+
相关产物:
|
|
65
|
+
报告目录:F:\DSH\_recon\(install-results.json、各 recon 报告、dump 诊断、验证脚本)
|
|
66
|
+
安装前备份:F:\DSH\_backup\profile-20260928-162128\
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# dsh 插件安装/更新问题记录
|
|
2
|
+
|
|
3
|
+
- **记录时间**:2026-09-28
|
|
4
|
+
- **任务范围**:按 `G:\CLI\DSH插件包.txt` 的 12 个插件清单,对 dsh web profile 执行安装/更新
|
|
5
|
+
- **目标 profile**:`C:\Users\Sjc\.dsh\profiles\web`
|
|
6
|
+
- **环境**:Windows 11 + Git Bash;Node v24.19.0;dsh 起始版本 0.1.7-rc.1(任务中途升级至 0.1.7-rc.2);pnpm 双版本共存(`G:\Env\nodejs\pnpm` 12.3.4 / `C:\Users\Sjc\AppData\Roaming\npm\pnpm` 12.6.0);内网 registry `http://10.192.2.173:8081/repository/group-npm/`
|
|
7
|
+
|
|
8
|
+
## 一、最终结果
|
|
9
|
+
|
|
10
|
+
| 项目 | 结果 |
|
|
11
|
+
|---|---|
|
|
12
|
+
| 版本达标 | **11/11**(清单第 12 个 `dsh-zh-thinking` 确认从未发布,跳过) |
|
|
13
|
+
| 服务状态 | dsh web 正常运行(PID 83020,监听 127.0.0.1:3080),11 个插件全部激活 |
|
|
14
|
+
| 附带修复 | ① 依赖残缺态恢复;② 3 条被覆写丢失的 MCP 配置恢复 + 拆块加固;③ dsh-db-tool 加载修复 |
|
|
15
|
+
| 遗留 | MongoDB 连接功能不可用(需上游修复宿主缺陷);`dsh-zh-thinking` 来源待确认 |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 二、问题清单(按严重度)
|
|
20
|
+
|
|
21
|
+
| # | 问题 | 严重度 | 状态 |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| 1 | dsh-db-tool 插件加载失败(宿主 loader 缺陷) | 高 | 已修复(插件侧绕过)+ 上游待修 |
|
|
24
|
+
| 2 | MCP 配置被 mcp-manager 覆写丢失 3 条 | 高 | 已恢复 + 已加固 |
|
|
25
|
+
| 3 | `ERR_PNPM_UNUSED_PATCH` 阻断所有升级操作 | 高 | 已解决 |
|
|
26
|
+
| 4 | pnpm 崩溃 exit 3221226505 遗留依赖残缺态 | 中 | 已恢复(崩溃本身不可复现) |
|
|
27
|
+
| 5 | dsh-zh-thinking 不存在于任何 registry | 中 | 待确认 |
|
|
28
|
+
| 6 | better-sqlite3 构建失败(nodejs.org 被拦) | 中 | 已解决 |
|
|
29
|
+
| 7 | skill-explorer 宿主版本门槛不满足 | 中 | 已豁免(rc.2 后自然满足) |
|
|
30
|
+
| 8 | 诊断探针插件被 dsh 拒绝加载 | 低 | 已知规避 |
|
|
31
|
+
| 9 | mcp-intellij 未拉起 | 低 | 外部依赖(IDEA 未运行) |
|
|
32
|
+
| 10 | Git Bash 的 http_proxy 拦截本机 curl | 低 | 已知规避 |
|
|
33
|
+
| 11 | 清单记载的 rtk 路径错误 | 低 | 已澄清 |
|
|
34
|
+
| 12 | cordis.patch.yml 注释过期 | 低 | 已标注 |
|
|
35
|
+
| 13 | cpu-features 原生构建失败(既有问题) | 低 | 不阻塞 |
|
|
36
|
+
| 14 | GitHub 直装包 specifier 为浮动引用 | 低 | 已知风险 |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 三、问题详情
|
|
41
|
+
|
|
42
|
+
### 问题 1:dsh-db-tool 插件加载失败【高】
|
|
43
|
+
|
|
44
|
+
**现象**
|
|
45
|
+
|
|
46
|
+
插件安装成功、版本正确(0.1.8),但启动日志始终出现:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
dsh: warning: 1 entry did not activate
|
|
50
|
+
db-tool (dsh-db-tool): failed to import
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
宿主 0.1.7-rc.1 与升级后的 0.1.7-rc.2 均复现;纯 Node 环境下导入该插件完全正常。
|
|
54
|
+
|
|
55
|
+
**根因(四层因果)**
|
|
56
|
+
|
|
57
|
+
1. **宿主缺陷**:dsh 为实现 profile 感知解析,用 `node-addon-require-builtin` 深入 Node 内部模块并改写 CJS 的 `Module._resolveFilename`。每个请求都会经过 `dsh-app-boot/lib/index.js:1422`:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
for (const searchPath of createRequire(parent).resolve.paths(name)) {
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
该行**无空值保护**(对比同类调用 `profile.ts:596` 有 `?? []`),在特定请求上抛:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
TypeError: createRequire.resolve.paths is not a function or its return value is not iterable
|
|
67
|
+
at ResolutionRouter.routeScoped (.../dsh-app-boot/lib/index.js:1422:58)
|
|
68
|
+
at ResolutionRouter.routePath (...:1554)
|
|
69
|
+
at Module.wrappedFilename [as _resolveFilename] (...:1771)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
2. **为何是 mongodb 触发**:dsh 的 `selfReferenceName()` 只在包声明了 `exports` 字段时才短路解析。`mongodb@7.6.0` 是**无 exports 的老式布局**(132 个 js 文件),内部请求全部经过缺陷循环;而 `bson@7.3.3` 有 exports,不触发。纯 Node 下穷举 mongodb(132 文件 × 8 种子路径请求)的 `resolve.paths` 调用:**零异常**,证明包本身无问题。
|
|
73
|
+
|
|
74
|
+
3. **为何是 db-tool 撞上**:其加载链 `dist/index.js → manager.js → guard/index.js:10 静态导入 ../adapters/mongodb/index.js → 顶层 import 'mongodb'`。即**加载插件必然加载 mongodb**——而 db-tool 的适配器本设计为惰性加载(`adapters/index.js` 中 8 个驱动全是 `() => import(...)`),是 guard 为取两个常量做的静态导入破坏了惰性。
|
|
75
|
+
|
|
76
|
+
4. **为何看不到线索**:dsh 启动审计把加载异常吞掉,只打印 `failed to import`(源头 `app-boot` 的 `inactiveEntries`)。
|
|
77
|
+
|
|
78
|
+
**定位方法**:影子入口二分法——在同一 profile 挂 7 个探针入口(分别导入 db-tool 的各子模块),一次实验即锁定:不碰 mongodb 的 `store`/`adapters` 成功,`guard`/`manager`/`http`/`script` 全部失败。
|
|
79
|
+
|
|
80
|
+
**修复(插件侧绕过,三处最小改动)**
|
|
81
|
+
|
|
82
|
+
1. 新增 `dist/adapters/mongodb/ops.js`:把 `DANGEROUS_OPS`、`READ_OPS` 两个纯数据集合拆出;
|
|
83
|
+
2. `dist/guard/index.js` 改为从 `ops.js` 导入这两个常量;
|
|
84
|
+
3. `dist/adapters/mongodb/index.js` 改为从 `ops.js` 转发导出(对外接口不变)。
|
|
85
|
+
|
|
86
|
+
**固化**:pnpm patch 官方机制 —— `patches/dsh-db-tool@0.1.8.patch`(3454 字节)+ `pnpm-workspace.yaml` 的 `patchedDependencies`,重装后自动应用。
|
|
87
|
+
|
|
88
|
+
**验证**:纯 Node 导入成功且不再加载 mongodb → 实例启动 11/11 激活 → 生产服务重启后 `GET /dsh-db-tool/api/connections` 返回 **200**(修复前 404,响应体 `{"ok":true,"data":[]}`)。
|
|
89
|
+
|
|
90
|
+
**遗留**:真正建立 MongoDB 连接时仍会加载 mongodb 包、仍会踩中同一缺陷,**MongoDB 连接功能暂不可用**(其余 6 种数据库正常)。彻底修复需上游给 1422 行加空值保护(建议反馈上游)。
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### 问题 2:MCP 配置被 mcp-manager 覆写丢失【高】
|
|
95
|
+
|
|
96
|
+
**现象**
|
|
97
|
+
|
|
98
|
+
`cordis.patch.yml` 在 2026-09-28 08:51(dsh web 运行期间)被从约 82 行改写为 49 行:原本 4 条 MCP 挂载只剩 `mcp-cbmem` 一条,`mcp-intellij`(IDEA)、`mcp-laya`、`mcp-mcphub` 三条丢失;且 `mcp-cbmem` 的 `serverName` 被从 `cbmem` 改成 `cbm`。
|
|
99
|
+
|
|
100
|
+
**根因(读 `@xxxyz/dsh-mcp-manager@2.2.7/lib/index.js` 确认)**
|
|
101
|
+
|
|
102
|
+
- 该插件按"块"而非"条目"处理:`insertBlockRange()`(678-691 行)一旦在某 `- insert:` 块内匹配到目标 id,返回范围就是**从 `- insert:` 到下一个顶层 `- ` 的整块**;
|
|
103
|
+
- `removeEntryAll()`(713-721 行)把整块并入删除集;UI 的"编辑"(1074-1079 行)与"删除"(1160-1163 行)都会先删整块再(或不)追加;
|
|
104
|
+
- 因此**同块内的无标记条目会被连带删除**——4 条 MCP 同处一个 insert 块,误操作一次即全丢;
|
|
105
|
+
- 给手工条目补 `# dsh-mcp-manager:server:<id>` 标记也**不能免疫**(`markerRanges()` 657-677 行同样按整块计算)。
|
|
106
|
+
|
|
107
|
+
这与历史记录中的同类事故(`G:\CLI\github-项目安装核查报告.md` 第 507-509 行)完全吻合。
|
|
108
|
+
|
|
109
|
+
**处置**
|
|
110
|
+
|
|
111
|
+
1. 恢复:按历史原文补回丢失的 3 条(`mcp-intellij` / `mcp-laya` / `mcp-mcphub`),`dsh --profile web --dump-config` 验证 4 条全部加载;
|
|
112
|
+
2. **加固**:把 4 条 MCP 拆成 **4 个独立 `- insert:` 块**,把"误删一条导致全部丢失"降级为"只丢一条";
|
|
113
|
+
3. 备份:`.backup-20260928/cordis.patch.yml.before-mcp-restore`(恢复前)、`cordis.patch.yml.before-split`(拆块前)。
|
|
114
|
+
|
|
115
|
+
**遗留与建议**
|
|
116
|
+
|
|
117
|
+
- ⚠️ **不要在 dsh-mcp-manager 的 UI 里"编辑/删除"任何 MCP 条目**(新增/启用/禁用/重启是安全的);
|
|
118
|
+
- `mcp-cbmem` 的 serverName 仍为 `cbm`(工具前缀 `mcp__cbm__*`,原基线 `cbmem`);恢复时未改回以避免二次风险,如需修回只能手工改文件 + 重启。
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 问题 3:`ERR_PNPM_UNUSED_PATCH` 阻断升级【高】
|
|
123
|
+
|
|
124
|
+
**现象**:`pnpm add billion-context@0.1.163` 稳定失败:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Error: ERR_PNPM_UNUSED_PATCH
|
|
128
|
+
× adding a new package
|
|
129
|
+
╰─▶ The following patches were not used: billion-context@0.1.147
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**根因**:`pnpm-workspace.yaml` 的 `patchedDependencies` 声明了 `billion-context@0.1.147: patches/billion-context@0.1.147.patch`。一旦执行升级命令、0.1.147 退出依赖树,该 patch 立即"未被使用",pnpm 直接拒绝整个操作。**这不是崩溃、不是网络问题,而是版本的确定性阻塞**——换任何 pnpm 版本都会失败。
|
|
133
|
+
|
|
134
|
+
**处置**:为 0.1.163 重新生成 patch(新版 dist 是压缩格式,旧 patch 上下文无法落位,必须重新生成)→ 复制 patch 文件 → 修改 `pnpm-workspace.yaml` 的 `patchedDependencies` 指向 0.1.163 → **紧接**执行升级 add(切换与升级之间不插入其他 pnpm 命令,最小化不一致窗口)。
|
|
135
|
+
|
|
136
|
+
**说明**:该 patch 修复的不是安装问题,而是 billion-context 的隧道 DNS 校验:本机内网 DNS 不解析外网域名,导致其内置 deepseek 路由被 403 拒绝。补丁让 DNS 解析失败时对回环客户端放行(非回环仍拒绝,SSRF 防护不变)。
|
|
137
|
+
|
|
138
|
+
**验证**:patch 文件 sha256 与 lock 记录一致;`node_modules/billion-context/dist/index.js` 中 `ctx.clientLoopback` 出现 3 次(原 2 + 补丁 1);`catch{` 后紧跟补丁注释与 `if(ctx.clientLoopback)return{ok:true}`。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 问题 4:pnpm 崩溃 exit 3221226505 遗留依赖残缺态【中】
|
|
143
|
+
|
|
144
|
+
**现象**:2026-09-28 08:12 一次 `pnpm add "billion-context@0.1.163"` 以 Windows 崩溃码 **3221226505(0xC0000409,fail-fast)** 退出,日志 76 字节无输出;其后 node_modules 残缺,任何 `dsh plugin` 命令都在 reconcile 阶段报 `cannot resolve profile bundle` 并异常退出。
|
|
145
|
+
|
|
146
|
+
**诊断实验**:临时目录 × {pnpm 12.3.4, 12.6.0} × {小包, billion-context} × {共享 store, 干净 store} 全矩阵 —— **全部 exit 0,崩溃不可复现**;同期生产日志(08:41)显示同一命令已变为稳定的 `exit 1`(即 ERR_PNPM_UNUSED_PATCH),说明崩溃是一次偶发的 Windows fail-fast,非确定性缺陷。
|
|
147
|
+
|
|
148
|
+
**规避**:所有 dsh/pnpm 命令统一用 PATH 前置强制走 pnpm 12.6.0:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
PATH="/c/Users/Sjc/AppData/Roaming/npm:$PATH" dsh plugin --profile web <args>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
(dsh 从 PATH 解析 pnpm,`operations.js:271` 有 `options.command ?? 'pnpm'`;已验证前置生效。)
|
|
155
|
+
|
|
156
|
+
**遗留**:崩溃根因未定位(无输出、不可复现),升级 pnpm 属合理规避但无直接证据证明根治。
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### 问题 5:dsh-zh-thinking 不存在于任何 registry【中】
|
|
161
|
+
|
|
162
|
+
**现象**:清单记载 `dsh-zh-thinking@0.1.1` 且给出 npm 链接,但三方核实全部 404:
|
|
163
|
+
|
|
164
|
+
| 来源 | 结果 |
|
|
165
|
+
|---|---|
|
|
166
|
+
| 内网 Nexus(group-npm) | 404 |
|
|
167
|
+
| 公网 registry.npmjs.org | 404(`{"error":"Not found"}`) |
|
|
168
|
+
| npmjs 网页 | 本机 TLS 不可达(环境问题,非包问题) |
|
|
169
|
+
|
|
170
|
+
**结论**:该包从未发布或已下架/改名。**待你确认来源**。另有相似包 `@hytime/dsh-thinking-effort@0.3.5`(用途不同),如需请告知。
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### 问题 6:better-sqlite3 构建失败【中】
|
|
175
|
+
|
|
176
|
+
**现象**:安装 `dsh-db-tool@0.1.8` 时其依赖 `better-sqlite3@^13.0.3` 的 `node-gyp rebuild` 失败 —— 需要从 `https://nodejs.org` 下载 node headers,本机网络返回 SSL `wrong version number`(被代理/防火墙拦截)。经测试 CCProxy(`http://10.192.2.117:8085`)**只放行 github.com,不放行 nodejs.org**(HTTP 000)。
|
|
177
|
+
|
|
178
|
+
**处置(方案 2 成功,仅 16 秒)**:使用本机已有的 node headers 强制源码编译:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npm_config_nodedir=C:/nodedir npm_config_build_from_source=true \
|
|
182
|
+
PATH="/c/Users/Sjc/AppData/Roaming/npm:$PATH" dsh plugin --profile web add -E dsh-db-tool@0.1.8
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`C:\nodedir` 内已有完整 headers 与 node.lib;node-gyp 找到 VS2022 与 Python 3.13.15,编译通过。
|
|
186
|
+
|
|
187
|
+
**验证**:`require('better-sqlite3')` 加载成功、SQL 往返 `{"x":42}` 通过。注:该版本 binding.gyp 为 `type:'none'`(prebuildify 设计),运行时加载包内 `prebuilds/win32-x64.node`,无 build/Release 产物属正常。
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### 问题 7:skill-explorer 宿主版本门槛不满足【中】
|
|
192
|
+
|
|
193
|
+
**现象**:`@linxin666/dsh-client-ui-skill-explorer@0.4.3` 声明 `dsh.engines.dsh = ">=0.1.7-rc.2"`,而当时宿主为 0.1.7-rc.1,被兼容性预检拒绝。
|
|
194
|
+
|
|
195
|
+
**处置**:按 dsh 官方机制授予精确版本豁免:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
dsh plugin --profile web allow-version '@linxin666/dsh-client-ui-skill-explorer@0.4.3' \
|
|
199
|
+
--dsh-version 0.1.7-rc.1 --accept-risk
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
记录持久化在 `compatibility.json`:`{"@linxin666/dsh-client-ui-skill-explorer@0.4.3": ["0.1.7-rc.1"]}`。功能实测正常。
|
|
203
|
+
|
|
204
|
+
**后续**:宿主升级到 rc.2 后门槛自然满足、**不再需要豁免**;旧豁免记录保留无副作用(未撤销以避免无谓变更)。
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### 问题 8:诊断探针插件被 dsh 拒绝加载【低】
|
|
209
|
+
|
|
210
|
+
**现象**:凡是在插件顶层或 `apply()` 内**包装 `Module._resolveFilename` 或 `Module.prototype.require`** 的探针插件,自身都会 `failed to import`;甚至顶层 `import Module from 'node:module'` 也可能触发。普通探针(只做动态 import、读文件)正常。
|
|
211
|
+
|
|
212
|
+
**解释**:dsh 对模块加载链有自我保护/一致性校验,包装会破坏其内部假设。
|
|
213
|
+
|
|
214
|
+
**规避**:诊断时改用"影子入口二分法"(只做静态导入、不包装加载器)或"层外探针 + 延迟执行"。
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### 问题 9:mcp-intellij 未拉起【低】
|
|
219
|
+
|
|
220
|
+
**现象**:服务启动期 IDEA MCP 反复 11 轮 `io.ktor.client.plugins.sse.SSEClientException: Connection refused`,之后放弃;`curl 127.0.0.1:64342` 返回 000。
|
|
221
|
+
|
|
222
|
+
**原因**:IDE 未运行(其 MCP Server 未监听 64342),非配置问题(stdio 拉起命令被反复执行、Java 进程反复启停可证)。**启动 IDEA 后即可用。**
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### 问题 10:Git Bash 的 http_proxy 拦截本机 curl【低】
|
|
227
|
+
|
|
228
|
+
**现象**:在本机探测 `http://127.0.0.1:3080` 等地址时,Git Bash 环境的小写 `http_proxy=http://10.192.2.117:8085` 会拦截请求,返回统一 403,导致误判"端口无监听"。
|
|
229
|
+
|
|
230
|
+
**规避**:本机探测一律加 `--noproxy '*'`:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
curl -s --noproxy '*' -o /dev/null -w "%{http_code}" http://127.0.0.1:3080/
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### 问题 11:清单记载的 rtk 路径错误【低】
|
|
239
|
+
|
|
240
|
+
清单写 `~/.local/bin/rtk.exe`,实际路径为 `G:\CLI\Rtk\rtk.exe`(PATH 可用)。`dsh-pwsh-rtk-rewrite` 按 `RTK_BIN || 'rtk'` 解析,**功能不受影响**,仅文档偏差。
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### 问题 12:cordis.patch.yml 注释过期【低】
|
|
245
|
+
|
|
246
|
+
文件第 30-37 行的 billion-context 注释仍称补丁文件为 `billion-context@0.1.147.patch`,而实际引用的已是 0.1.163。旧 patch 文件已保留(未删除)但不再被引用。建议后续手工更新注释。
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
### 问题 13:cpu-features 原生构建失败【低】
|
|
251
|
+
|
|
252
|
+
`dsh-pwsh-rtk-rewrite` 与 `dsh-db-tool` 两次安装中均出现 `cpu-features`(`ssh2` 的可选依赖)原生构建失败(同问题 6 的 nodejs.org 拦截),但 pnpm 容忍、主操作成功。**既有问题,非本次引入,不阻塞。**
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### 问题 14:GitHub 直装包 specifier 为浮动引用【低】
|
|
257
|
+
|
|
258
|
+
`dsh-ssh-tunnel` 的依赖 specifier 为 `github:thirsty5034/dsh-ssh-tunnel#main`(跟随 main)。当前 lockfile 已锁死 commit `c88da56b...`(与远端 main 一致),但**非 frozen 安装可能漂移**。`dsh-restart-fab` 则锁定 commit `99cd34aa...`(与远端最新一致,无漂移风险)。
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 四、避坑与操作建议
|
|
263
|
+
|
|
264
|
+
1. **改插件版本前,先对齐 patch 声明**:`pnpm-workspace.yaml` 的 `patchedDependencies` 必须与实际依赖树匹配,否则一律 `ERR_PNPM_UNUSED_PATCH`。
|
|
265
|
+
2. **不要用 dsh-mcp-manager 的 UI 编辑/删除 MCP 条目**(会把整块删掉);手工编辑 `cordis.patch.yml` 更安全(现已拆成 4 块进一步降低影响面)。
|
|
266
|
+
3. **安装/升级前先停 dsh web**(Windows 文件占用会导致 EPERM/EBUSY);升级后必须重启服务才生效。
|
|
267
|
+
4. **统一用 pnpm 12.6.0**:`PATH="/c/Users/Sjc/AppData/Roaming/npm:$PATH" dsh plugin ...`(规避 12.3.4 的偶发 fail-fast)。
|
|
268
|
+
5. **构建原生模块时用本地 headers**:`npm_config_nodedir=C:/nodedir npm_config_build_from_source=true`(本机到 nodejs.org 被拦)。
|
|
269
|
+
6. **本机 HTTP 探测加 `--noproxy '*'`**(Git Bash 的 http_proxy 会拦截回环请求)。
|
|
270
|
+
7. **改配置前先备份**:本次全程滚动快照在 `.dsh\profiles\web\.backup-20260928\`。
|
|
271
|
+
8. 兼容性被拒时用官方豁免(`dsh plugin --profile web allow-version <pkg>@<ver> --dsh-version <ver> --accept-risk`),并记录豁免清单。
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 五、关键路径索引
|
|
276
|
+
|
|
277
|
+
| 用途 | 路径 |
|
|
278
|
+
|---|---|
|
|
279
|
+
| 改造前基线快照 | `C:\Users\Sjc\.dsh\profiles\web\.backup-20260928\snapshot-0\` |
|
|
280
|
+
| 最终快照(含修复) | `…\.backup-20260928\snapshot-final2\` |
|
|
281
|
+
| db-tool 修复说明 | `…\.backup-20260928\db-tool-修复说明.md` |
|
|
282
|
+
| MCP 恢复前备份 | `…\.backup-20260928\cordis.patch.yml.before-mcp-restore` |
|
|
283
|
+
| MCP 拆块前备份 | `…\.backup-20260928\cordis.patch.yml.before-split` |
|
|
284
|
+
| billion-context patch | `…\patches\billion-context@0.1.163.patch` |
|
|
285
|
+
| db-tool patch | `…\patches\dsh-db-tool@0.1.8.patch` |
|
|
286
|
+
| 宿主缺陷代码位置 | `…\@deepseek-ai\dsh\node_modules\@deepseek-ai\dsh-app-boot\lib\index.js:1422` |
|
|
287
|
+
|
|
288
|
+
**回滚方式**:用目标快照覆盖 `package.json` / `pnpm-workspace.yaml` / `pnpm-lock.yaml` / `cordis.patch.yml`(+ `patches/`),再执行 `dsh plugin --profile web install`。
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 六、待办与上游反馈建议
|
|
293
|
+
|
|
294
|
+
> 解决方案详见 [dsh插件问题解决方案-20260928.md](./dsh插件问题解决方案-20260928.md)。
|
|
295
|
+
|
|
296
|
+
**待你决策**
|
|
297
|
+
|
|
298
|
+
1. `dsh-zh-thinking` 的来源(清单给了 npm 链接但三方 404);
|
|
299
|
+
2. MongoDB 连接功能是否接受"暂不可用"(等上游修复),或要求我尝试给宿主 app-boot 打补丁(改动全局 npm 包,dsh 升级会被覆盖)。
|
|
300
|
+
|
|
301
|
+
**建议反馈上游(deepseek-harness)**
|
|
302
|
+
|
|
303
|
+
1. `dsh-app-boot` 的 `routeScoped` 中 `createRequire(parent).resolve.paths(name)` 缺空值保护(对比 `profile.ts:596` 有 `?? []`),建议统一加固;同一模式在 rc.2 中仍有 5 处无保护;
|
|
304
|
+
2. `selfReferenceName()` 对无 `exports` 字段的老式包会走完整路由路径,建议增加降级处理;
|
|
305
|
+
3. 启动审计对插件加载异常只输出 `failed to import`,建议附带原始错误与堆栈(可加调试开关)。
|
|
306
|
+
|
|
307
|
+
**建议反馈 `@xxxyz/dsh-mcp-manager`**
|
|
308
|
+
|
|
309
|
+
`insertBlockRange` / `removeEntryAll` 的"整块删除"语义会把同块内非目标条目一并删除,建议改为按条目粒度定位(配合缩进解析),或在文档中明确警示。
|