dsh-oc-desktop 0.3.13 → 0.3.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/bin/dsh-desktop.cjs +23 -14
- package/launcher/main.js +24 -49
- package/package.json +8 -3
- package/scripts/postinstall.js +18 -6
package/bin/dsh-desktop.cjs
CHANGED
|
@@ -60,32 +60,41 @@ function main() {
|
|
|
60
60
|
// re-downloaded. Probe ProductName first (fast); inject when it is not 'DSH Desktop'.
|
|
61
61
|
const injectScript = path.join(__dirname, '..', 'scripts', 'set-exe-icon.ps1');
|
|
62
62
|
|
|
63
|
+
// Ordered candidate mirrors; npmmirror can lag a new electron release and 404, so
|
|
64
|
+
// fall back to the official GitHub source. A user-set ELECTRON_MIRROR is tried first.
|
|
65
|
+
function electronMirrors(env) {
|
|
66
|
+
const out = [];
|
|
67
|
+
const push = (m) => { if (m && out.indexOf(m) < 0) out.push(m); };
|
|
68
|
+
push(env && env.ELECTRON_MIRROR);
|
|
69
|
+
push('https://npmmirror.com/mirrors/electron/');
|
|
70
|
+
push('https://github.com/electron/electron/releases/download/');
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
// Ensure the electron binary exists before booting. `npm install -g` can skip
|
|
64
75
|
// electron's postinstall when the npm package cache is warm, leaving dist/ empty;
|
|
65
76
|
// re-running install.js fetches the binary from the local electron cache or network.
|
|
66
77
|
function ensureElectron(electron) {
|
|
67
78
|
if (fs.existsSync(electron)) return; // binary already present
|
|
68
|
-
console.log('dsh-oc-desktop: electron binary missing, running electron/install.js ...');
|
|
69
79
|
const pkgDir = path.resolve(path.dirname(electron), '..');
|
|
70
80
|
const installJs = path.join(pkgDir, 'install.js');
|
|
71
81
|
if (!fs.existsSync(installJs)) {
|
|
72
82
|
console.error(`dsh-oc-desktop: ${installJs} missing, reinstall the package.`);
|
|
73
83
|
process.exit(1);
|
|
74
84
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
if (!fs.existsSync(electron)) {
|
|
86
|
-
console.error('dsh-oc-desktop: electron binary still missing after install.js; reinstall the package.');
|
|
87
|
-
process.exit(1);
|
|
85
|
+
const mirrors = electronMirrors(process.env);
|
|
86
|
+
let lastErr = null;
|
|
87
|
+
for (const mirror of mirrors) {
|
|
88
|
+
console.log(`dsh-oc-desktop: electron binary missing, trying mirror ${mirror}`);
|
|
89
|
+
const env = Object.assign({}, process.env, { ELECTRON_MIRROR: mirror });
|
|
90
|
+
try {
|
|
91
|
+
execFileSync(process.execPath, [installJs], { stdio: 'inherit', windowsHide: true, env });
|
|
92
|
+
if (fs.existsSync(electron)) return;
|
|
93
|
+
} catch (e) { lastErr = e; }
|
|
88
94
|
}
|
|
95
|
+
console.error(`dsh-oc-desktop: failed to fetch electron binary: ${(lastErr && lastErr.message) ? lastErr.message : 'unknown'}`);
|
|
96
|
+
console.error('Check network / ELECTRON_MIRROR, then retry.');
|
|
97
|
+
process.exit(1);
|
|
89
98
|
}
|
|
90
99
|
|
|
91
100
|
function ensureInjected(electron) {
|
package/launcher/main.js
CHANGED
|
@@ -601,20 +601,25 @@ const OC_DISPLAY = {
|
|
|
601
601
|
};
|
|
602
602
|
function updateHtml(title, rows, footer) {
|
|
603
603
|
const esc = escapeHtml;
|
|
604
|
-
|
|
604
|
+
// 一键更新按钮只看 oc 插件;引擎行有新版仅作"提示",不进入可一键更新(升引擎会清空撤回补丁)
|
|
605
|
+
const showAll = rows.some((r) => r.hasUpdate && !r.isEngine);
|
|
605
606
|
const cards = rows.map((r) => {
|
|
606
|
-
const
|
|
607
|
-
const
|
|
607
|
+
const engUpd = r.isEngine && r.hasUpdate && !r.error; // 引擎有新版:仅提示
|
|
608
|
+
const st = r.error ? '检查失败' : engUpd ? '引擎·提示' : r.hasUpdate ? '可更新' : '已最新';
|
|
609
|
+
const stCls = r.error ? 'err' : engUpd ? 'warn' : r.hasUpdate ? 'upd' : 'ok';
|
|
608
610
|
const compat = r.compatible == null ? '' : r.compatible
|
|
609
611
|
? `<span class="compat ok" title="该插件声明的依赖范围兼容最新引擎">兼容新引擎</span>`
|
|
610
612
|
: `<span class="compat err" title="该插件声明的依赖范围不满足最新引擎,将保留当前版本">不兼容·保留</span>`;
|
|
611
613
|
const desc = r.description ? `<div class="desc" title="${esc(r.description)}">${esc(r.description)}</div>` : '';
|
|
612
614
|
const ver = r.error
|
|
613
615
|
? ''
|
|
614
|
-
: `<div class="ver"><span class="lbl">当前</span> <b>${esc(r.current)}</b> <span class="arrow ${r.hasUpdate ? 'upd' : ''}">→</span> <span class="lbl">最新</span> <b>${esc(r.latest)}</b></div>`;
|
|
616
|
+
: `<div class="ver"><span class="lbl">当前</span> <b>${esc(r.current)}</b> <span class="arrow ${(r.hasUpdate && !engUpd) ? 'upd' : ''}">→</span> <span class="lbl">最新</span> <b>${esc(r.latest)}</b></div>`;
|
|
617
|
+
const engNote = engUpd
|
|
618
|
+
? `<div class="eng-note">⚠️ 需作者发布适配补丁后才可升级;当前不可自动升级(升级会清空撤回补丁,撤回功能将失效)。</div>`
|
|
619
|
+
: '';
|
|
615
620
|
return `<div class="card">
|
|
616
621
|
<div class="top"><span class="pkg">${esc(r.display || r.name)}</span><span class="nm">${esc(r.name)}</span>${compat}<span class="st ${stCls}">${st}</span></div>
|
|
617
|
-
${desc}${ver}
|
|
622
|
+
${desc}${ver}${engNote}
|
|
618
623
|
</div>`;
|
|
619
624
|
}).join('');
|
|
620
625
|
const foot = footer ? `<div class="footnote">${esc(footer)}</div>` : '';
|
|
@@ -635,7 +640,9 @@ function updateHtml(title, rows, footer) {
|
|
|
635
640
|
.st{margin-left:auto;flex-shrink:0;font-size:11px;padding:2px 10px;border-radius:10px}
|
|
636
641
|
.ok{color:#34d399;background:#12251d}
|
|
637
642
|
.upd{color:#fbbf24;background:#2a2013}
|
|
643
|
+
.warn{color:#fbbf24;background:#2a2013}
|
|
638
644
|
.err{color:#f87171;background:#2a1414}
|
|
645
|
+
.eng-note{color:#fbbf24;font-size:11px;margin-top:4px;line-height:1.5}
|
|
639
646
|
.compat{flex-shrink:0;font-size:11px;padding:2px 8px;border-radius:10px}
|
|
640
647
|
.compat.ok{color:#34d399;border:1px solid #1d3a2e}
|
|
641
648
|
.compat.err{color:#f87171;border:1px solid #3a2020}
|
|
@@ -898,50 +905,19 @@ async function executeUpdate(action) {
|
|
|
898
905
|
log('info', `update action: ${JSON.stringify(action)}`);
|
|
899
906
|
if (!action || action.kind !== 'all') return { ok: false, message: '已取消单独更新,仅支持一键更新' };
|
|
900
907
|
const registry = (settings.updateRegistry || 'https://registry.npmjs.org').replace(/\/+$/, '');
|
|
901
|
-
const engineBin = path.join(dataHome, 'profiles', 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js');
|
|
902
908
|
try {
|
|
909
|
+
// 一键更新永远 = npx dsh-oc install:升级全部 oc 插件 + 把引擎钉回补丁兼容版(0.1.1-rc.2)。
|
|
910
|
+
// 引擎本身不随一键自动升最新(升引擎会清空撤回补丁),只能由作者发布新 dsh-oc
|
|
911
|
+
// (改 REQUIRED_ENGINE + 重做撤回补丁)后,用户再跑 dsh-oc install 才能更新引擎。
|
|
903
912
|
const results = await checkNpmUpdates(collectInstalled(), registry);
|
|
904
|
-
const
|
|
905
|
-
if (
|
|
913
|
+
const ocUpd = results.some((r) => r.name !== '@deepseek-ai/dsh' && r.hasUpdate);
|
|
914
|
+
if (!ocUpd) return { ok: true, message: '所有 oc 组件已是最新,无需更新' };
|
|
915
|
+
await runCommand('npx', ['--yes', 'dsh-oc', 'install']);
|
|
906
916
|
const engineUpd = results.find((r) => r.name === '@deepseek-ai/dsh' && r.hasUpdate);
|
|
907
|
-
if (!engineUpd) {
|
|
908
|
-
// 引擎无更新:聚合器一键更新全部 oc 组件
|
|
909
|
-
await runCommand('npx', ['--yes', 'dsh-oc', 'install']);
|
|
910
|
-
return { ok: true, message: '全部 oc 组件已更新到最新。重启应用后生效。' };
|
|
911
|
-
}
|
|
912
|
-
// 引擎有新版:检测各插件兼容性,兼容且有更新的随引擎一起更新,不兼容保留
|
|
913
|
-
const engineInfo = await npmPackageInfo('@deepseek-ai/dsh', registry);
|
|
914
|
-
const compatToUpdate = [];
|
|
915
|
-
const kept = [];
|
|
916
|
-
for (const r of results) {
|
|
917
|
-
if (r.name === '@deepseek-ai/dsh' || r.error) continue;
|
|
918
|
-
const ok = await checkEngineCompat(r.peerDependencies, engineInfo.dependencies, async (pkg) => npmPackageVersions(pkg, registry));
|
|
919
|
-
if (ok) { if (r.hasUpdate) compatToUpdate.push(r.name); }
|
|
920
|
-
else kept.push(r.name);
|
|
921
|
-
}
|
|
922
|
-
// 备份旧引擎
|
|
923
|
-
const dshDir = path.join(dataHome, 'profiles', 'node_modules', '@deepseek-ai', 'dsh');
|
|
924
|
-
if (!fs.existsSync(dshDir)) return { ok: false, message: '共享数据根内未找到 dsh 引擎' };
|
|
925
|
-
const backup = path.join(dataHome, 'profiles', 'node_modules', '@deepseek-ai', `.dsh-backup-${Date.now()}`);
|
|
926
|
-
fs.cpSync(dshDir, backup, { recursive: true });
|
|
927
|
-
log('info', `engine update: backup to ${backup}`);
|
|
928
|
-
// 更新兼容插件(引擎删除前,用当前引擎 CLI)
|
|
929
|
-
for (const name of compatToUpdate) {
|
|
930
|
-
try { await runCommand(process.execPath, [engineBin, 'plugin', '--profile', 'web', 'add', name]); log('info', `plugin updated: ${name}`); }
|
|
931
|
-
catch (e) { log('warn', `plugin ${name} update skipped: ${e.message}`); }
|
|
932
|
-
}
|
|
933
|
-
// 停引擎 + 删 dsh + 重启壳(autoBootstrap 重装最新引擎)
|
|
934
|
-
killHarness();
|
|
935
|
-
killWebEngine();
|
|
936
|
-
fs.rmSync(dshDir, { recursive: true, force: true });
|
|
937
|
-
app.relaunch();
|
|
938
|
-
app.exit(0);
|
|
939
917
|
return {
|
|
940
918
|
ok: true,
|
|
941
|
-
message: '
|
|
942
|
-
+ (
|
|
943
|
-
+ (kept.length ? `\n因不兼容保留当前版本:${kept.join('、')}。` : '')
|
|
944
|
-
+ '\n如更新后异常,可在托盘「回滚引擎更新」恢复。',
|
|
919
|
+
message: '全部 oc 组件已更新到最新,重启应用后生效。'
|
|
920
|
+
+ (engineUpd ? '\n注:引擎有新版(需作者发布适配补丁后才可升级);当前保持补丁兼容版,未自动升级。' : ''),
|
|
945
921
|
};
|
|
946
922
|
} catch (e) {
|
|
947
923
|
const msg = e && e.message ? e.message : String(e);
|
|
@@ -994,7 +970,8 @@ async function runCheckUpdates() {
|
|
|
994
970
|
compatible = await checkEngineCompat(r.peerDependencies, engineDeps, async (pkg) => npmPackageVersions(pkg, registry));
|
|
995
971
|
}
|
|
996
972
|
rows.push({ name: r.name, display: OC_DISPLAY[r.name] || r.name, current: r.current,
|
|
997
|
-
latest: r.latest, hasUpdate: r.hasUpdate, error: r.error, description: r.description, compatible
|
|
973
|
+
latest: r.latest, hasUpdate: r.hasUpdate, error: r.error, description: r.description, compatible,
|
|
974
|
+
isEngine: r.name === '@deepseek-ai/dsh' });
|
|
998
975
|
}
|
|
999
976
|
let footer = '';
|
|
1000
977
|
if (updates.length === 0) {
|
|
@@ -1005,10 +982,8 @@ async function runCheckUpdates() {
|
|
|
1005
982
|
const engineUpd = updates.some((u) => u.name === '@deepseek-ai/dsh');
|
|
1006
983
|
if (ocUpd) footer += '一键更新将升级全部 oc 组件';
|
|
1007
984
|
if (engineUpd) {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
+ (kept.length ? `;不兼容插件保留(${kept.map((k) => k.display).join('、')})` : '');
|
|
1011
|
-
footer += '\n引擎更新后若异常,可在托盘「回滚引擎更新」恢复';
|
|
985
|
+
footer += (footer ? '\n' : '') + '⚠️ 引擎有新版(' + (engineResult ? `${engineResult.current} → ${engineResult.latest}` : '') + '):需等作者发布适配补丁后才可升级;'
|
|
986
|
+
+ '一键更新不会自动升级引擎(升级会清空撤回补丁,撤回功能将失效)。';
|
|
1012
987
|
}
|
|
1013
988
|
log('info', 'check update: ' + updates.map((u) => `${u.name} ${u.current}→${u.latest}`).join(', '));
|
|
1014
989
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-oc-desktop",
|
|
3
3
|
"productName": "DeepSeek Harness Desktop",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.15",
|
|
5
5
|
"description": "DeepSeek Harness 桌面端插件(Electron 启动器):自绘标题栏/托盘/通知/快捷键/崩溃自愈",
|
|
6
6
|
"main": "launcher/main.js",
|
|
7
7
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/FeiJi-9527/dsh"
|
|
12
|
+
"url": "git+https://github.com/FeiJi-9527/dsh.git"
|
|
13
13
|
},
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"electron": "^43.4.0"
|
|
25
25
|
},
|
|
26
|
-
"files": [
|
|
26
|
+
"files": [
|
|
27
|
+
"launcher",
|
|
28
|
+
"bin",
|
|
29
|
+
"assets",
|
|
30
|
+
"scripts"
|
|
31
|
+
],
|
|
27
32
|
"license": "MIT"
|
|
28
33
|
}
|
package/scripts/postinstall.js
CHANGED
|
@@ -9,18 +9,30 @@ const fs = require('node:fs');
|
|
|
9
9
|
const path = require('node:path');
|
|
10
10
|
const { spawnSync } = require('node:child_process');
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const ELECTRON_MIRRORS = [
|
|
13
|
+
'https://npmmirror.com/mirrors/electron/',
|
|
14
|
+
'https://github.com/electron/electron/releases/download/',
|
|
15
|
+
];
|
|
13
16
|
|
|
14
17
|
const electronDir = path.join(__dirname, '..', 'node_modules', 'electron');
|
|
15
18
|
if (!fs.existsSync(path.join(electronDir, 'install.js'))) process.exit(0);
|
|
16
19
|
const exe = path.join(electronDir, 'dist', process.platform === 'win32' ? 'electron.exe' : 'electron');
|
|
17
20
|
if (fs.existsSync(exe)) process.exit(0);
|
|
18
21
|
|
|
19
|
-
console.log('dsh-oc-desktop: electron binary missing, downloading
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
22
|
+
console.log('dsh-oc-desktop: electron binary missing, downloading ...');
|
|
23
|
+
// Try a user-set ELECTRON_MIRROR first, then npmmirror, then the official GitHub source
|
|
24
|
+
// (npmmirror can lag a new electron release and 404). Never fail the install.
|
|
25
|
+
const mirrors = [];
|
|
26
|
+
const push = (m) => { if (m && mirrors.indexOf(m) < 0) mirrors.push(m); };
|
|
27
|
+
push(process.env.ELECTRON_MIRROR);
|
|
28
|
+
for (const m of ELECTRON_MIRRORS) push(m);
|
|
29
|
+
for (const mirror of mirrors) {
|
|
30
|
+
if (fs.existsSync(exe)) break;
|
|
31
|
+
const env = Object.assign({}, process.env, { ELECTRON_MIRROR: mirror });
|
|
32
|
+
const r = spawnSync(process.execPath, [path.join(electronDir, 'install.js')], { stdio: 'inherit', env, windowsHide: true });
|
|
33
|
+
if (r.status === 0 && fs.existsSync(exe)) break;
|
|
34
|
+
}
|
|
35
|
+
if (!fs.existsSync(exe)) {
|
|
24
36
|
console.warn('dsh-oc-desktop: electron binary fetch failed; it will self-heal on first launch.');
|
|
25
37
|
}
|
|
26
38
|
process.exit(0);
|