dsh-maoying 0.1.4 → 0.1.5
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/index.mjs +116 -18
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -197,42 +197,117 @@ export function hostRejectsInlineDelegation(version) {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
/** 宿主包版本:从 <home>/node_modules require('@deepseek-ai/dsh/package.json')。 */
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
let dir = path.dirname(path.resolve(process.argv?.[1] ?? ''))
|
|
208
|
-
for (let i = 0; i < 8 && dir && dir !== path.dirname(dir); i++, dir = path.dirname(dir)) {
|
|
209
|
-
const pkgPath = path.join(dir, 'package.json')
|
|
210
|
-
if (!existsSync(pkgPath)) continue
|
|
200
|
+
/** 从 start 向上最多 8 层找最近的 @deepseek-ai/dsh package.json,命中记轨迹 */
|
|
201
|
+
function anchorVersion(start, probe, trace) {
|
|
202
|
+
let dir = path.dirname(path.resolve(start))
|
|
203
|
+
for (let i = 0; i < 8 && dir && dir !== path.dirname(dir); i++, dir = path.dirname(dir)) {
|
|
204
|
+
const pkgPath = path.join(dir, 'package.json')
|
|
205
|
+
if (!existsSync(pkgPath)) continue
|
|
206
|
+
try {
|
|
211
207
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
212
208
|
if (pkg?.name === '@deepseek-ai/dsh' && typeof pkg.version === 'string' && pkg.version !== '') {
|
|
209
|
+
trace.push({ probe, hit: pkg.version, via: pkgPath })
|
|
213
210
|
return pkg.version
|
|
214
211
|
}
|
|
212
|
+
} catch { /* 单个坏 package.json 跳过继续走 */ }
|
|
213
|
+
}
|
|
214
|
+
trace.push({ probe, hit: null })
|
|
215
|
+
return null
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 宿主版本探测(带轨迹)。五级优先,前四级都锚定「当前进程的真实宿主」,
|
|
220
|
+
* home 全局那份(老 CLI 残留,版本可能差几个大版本)只做最后兜底:
|
|
221
|
+
* ① argv[1]——CLI 下就是 @deepseek-ai/dsh 包内入口;
|
|
222
|
+
* ② 全 argv 扫描——Electron 主进程常见 argv 里带 app 入口或 .asar 路径;
|
|
223
|
+
* ③ app.asar 锚定——桌面应用 execPath 反推 Resources/app.asar/dsh(Electron
|
|
224
|
+
* 主进程 fs 可透读 asar);
|
|
225
|
+
* ④ Electron app.getVersion()——桌面应用版本即其内置 dsh 版本;
|
|
226
|
+
* ⑤ home 全局安装兜底。
|
|
227
|
+
* 轨迹经 trace 数组透出(host-debug 路由用),方便现场诊断每级看到了什么。
|
|
228
|
+
*/
|
|
229
|
+
function collectHostVersion(dshHome, trace) {
|
|
230
|
+
// ① argv[1]
|
|
231
|
+
const argv1 = process.argv?.[1]
|
|
232
|
+
if (typeof argv1 === 'string' && argv1 !== '') {
|
|
233
|
+
const hit = anchorVersion(argv1, 'argv[1]', trace)
|
|
234
|
+
if (hit) return hit
|
|
235
|
+
} else {
|
|
236
|
+
trace.push({ probe: 'argv[1]', hit: null, note: 'argv[1] 缺席' })
|
|
237
|
+
}
|
|
238
|
+
// ② 全 argv 扫描
|
|
239
|
+
let scanned = 0
|
|
240
|
+
for (const arg of process.argv ?? []) {
|
|
241
|
+
if (typeof arg !== 'string' || arg === argv1 || arg.startsWith('-')) continue
|
|
242
|
+
if (!/\.asar($|\/)|\.(mjs|cjs|js)$/.test(arg)) continue
|
|
243
|
+
scanned++
|
|
244
|
+
const hit = anchorVersion(arg, 'argv-scan', trace)
|
|
245
|
+
if (hit) return hit
|
|
246
|
+
}
|
|
247
|
+
if (scanned === 0) trace.push({ probe: 'argv-scan', hit: null, note: '无可锚定的 argv 项' })
|
|
248
|
+
// ③ app.asar 锚定(仅 Electron 进程内有意义;纯 Node 的 fs 读不了 asar)
|
|
249
|
+
if (process.versions?.electron) {
|
|
250
|
+
const execDir = path.dirname(process.execPath)
|
|
251
|
+
const candidates = [
|
|
252
|
+
path.resolve(execDir, '..', 'Resources', 'app.asar', 'dsh', 'package.json'),
|
|
253
|
+
path.resolve(execDir, 'resources', 'app.asar', 'dsh', 'package.json'),
|
|
254
|
+
path.resolve(execDir, '..', 'Resources', 'app.asar', 'package.json'),
|
|
255
|
+
path.resolve(execDir, 'resources', 'app.asar', 'package.json'),
|
|
256
|
+
]
|
|
257
|
+
let probed = false
|
|
258
|
+
for (const pkgPath of candidates) {
|
|
259
|
+
try {
|
|
260
|
+
if (!existsSync(pkgPath)) continue
|
|
261
|
+
probed = true
|
|
262
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
263
|
+
if (pkg?.name === '@deepseek-ai/dsh' && typeof pkg.version === 'string' && pkg.version !== '') {
|
|
264
|
+
trace.push({ probe: 'asar', hit: pkg.version, via: pkgPath })
|
|
265
|
+
return pkg.version
|
|
266
|
+
}
|
|
267
|
+
} catch { /* 单个候选坏掉换下一个 */ }
|
|
215
268
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
269
|
+
if (!probed) trace.push({ probe: 'asar', hit: null, note: 'execPath 反推的 asar 路径均不可读' })
|
|
270
|
+
} else {
|
|
271
|
+
trace.push({ probe: 'asar', hit: null, note: '非 Electron 进程' })
|
|
272
|
+
}
|
|
273
|
+
// ④ Electron app.getVersion()。纯 Node 下 require('electron') 得到路径字符串
|
|
274
|
+
// 或直接找不到,类型守卫天然挡掉。
|
|
219
275
|
try {
|
|
220
276
|
const electron = createRequire(import.meta.url)('electron')
|
|
221
277
|
if (electron && typeof electron === 'object' && typeof electron.app?.getVersion === 'function') {
|
|
222
278
|
const v = electron.app.getVersion()
|
|
223
|
-
|
|
279
|
+
const hit = typeof v === 'string' && v !== '' ? v : null
|
|
280
|
+
trace.push({ probe: 'electron-api', hit })
|
|
281
|
+
if (hit) return hit
|
|
282
|
+
} else {
|
|
283
|
+
trace.push({ probe: 'electron-api', hit: null, note: 'require 结果非 API 对象' })
|
|
224
284
|
}
|
|
225
|
-
} catch {
|
|
226
|
-
|
|
285
|
+
} catch {
|
|
286
|
+
trace.push({ probe: 'electron-api', hit: null, note: 'require 失败' })
|
|
287
|
+
}
|
|
288
|
+
// ⑤ home 全局兜底
|
|
227
289
|
try {
|
|
228
290
|
const req = createRequire(path.join(dshHome, 'node_modules', 'package.json'))
|
|
229
291
|
const pkg = req('@deepseek-ai/dsh/package.json')
|
|
230
|
-
|
|
292
|
+
const hit = typeof pkg?.version === 'string' && pkg.version !== '' ? pkg.version : null
|
|
293
|
+
trace.push({ probe: 'home-global', hit, note: hit ? '兜底命中——home 全局版本可能陈旧' : null })
|
|
294
|
+
return hit
|
|
231
295
|
} catch {
|
|
296
|
+
trace.push({ probe: 'home-global', hit: null })
|
|
232
297
|
return null
|
|
233
298
|
}
|
|
234
299
|
}
|
|
235
300
|
|
|
301
|
+
export function readHostVersion(dshHome) {
|
|
302
|
+
return collectHostVersion(dshHome, [])
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** host-debug 路由用:版本 + 每级探针轨迹 */
|
|
306
|
+
export function readHostVersionDebug(dshHome) {
|
|
307
|
+
const trace = []
|
|
308
|
+
return { version: collectHostVersion(dshHome, trace), trace }
|
|
309
|
+
}
|
|
310
|
+
|
|
236
311
|
// ── 预设源解析 ──────────────────────────────────────────────────────────────
|
|
237
312
|
|
|
238
313
|
/**
|
|
@@ -666,6 +741,29 @@ export async function registerCreatorRoutes(ctx) {
|
|
|
666
741
|
return
|
|
667
742
|
}
|
|
668
743
|
|
|
744
|
+
if (route === 'host-debug' && req.method === 'GET') {
|
|
745
|
+
// 现场诊断:宿主版本五级探针轨迹 + 形状判定。与 client.css 同级信任
|
|
746
|
+
// 围栏(loopback + 可信 Host 才放行),只暴露版本与路径类信息。
|
|
747
|
+
const home = resolveDshHome()
|
|
748
|
+
const dbg = readHostVersionDebug(home)
|
|
749
|
+
let shape = null
|
|
750
|
+
try { shape = composeManagedRows(home, ctx.logger).shape } catch { /* 诊断信息尽力而为 */ }
|
|
751
|
+
json(res, 200, {
|
|
752
|
+
ok: true,
|
|
753
|
+
hostVersion: dbg.version,
|
|
754
|
+
trace: dbg.trace,
|
|
755
|
+
shape,
|
|
756
|
+
runtime: {
|
|
757
|
+
argv: process.argv,
|
|
758
|
+
execPath: process.execPath,
|
|
759
|
+
cwd: process.cwd(),
|
|
760
|
+
electron: process.versions?.electron ?? null,
|
|
761
|
+
node: process.version,
|
|
762
|
+
},
|
|
763
|
+
})
|
|
764
|
+
return
|
|
765
|
+
}
|
|
766
|
+
|
|
669
767
|
if (route === 'workspaces' && req.method === 'GET') {
|
|
670
768
|
// 工作区清单:宿主注册表逐根探测 novel/project.yml,面板顶部
|
|
671
769
|
// 工作区选择器取数(hasNovel 的排前由客户端做,这里保序即可)。
|