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.
@@ -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
- try {
76
- // Default to the npmmirror mirror unless the user set ELECTRON_MIRROR already.
77
- const env = Object.assign({}, process.env);
78
- if (!env.ELECTRON_MIRROR) env.ELECTRON_MIRROR = 'https://npmmirror.com/mirrors/electron/';
79
- execFileSync(process.execPath, [installJs], { stdio: 'inherit', windowsHide: true, env });
80
- } catch (e) {
81
- console.error(`dsh-oc-desktop: failed to fetch electron binary: ${e && e.message ? e.message : e}`);
82
- console.error('If this is a network issue, set ELECTRON_MIRROR to a mirror and retry.');
83
- process.exit(1);
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
- const showAll = rows.some((r) => r.hasUpdate);
604
+ // 一键更新按钮只看 oc 插件;引擎行有新版仅作"提示",不进入可一键更新(升引擎会清空撤回补丁)
605
+ const showAll = rows.some((r) => r.hasUpdate && !r.isEngine);
605
606
  const cards = rows.map((r) => {
606
- const st = r.error ? '检查失败' : r.hasUpdate ? '可更新' : '已最新';
607
- const stCls = r.error ? 'err' : r.hasUpdate ? 'upd' : 'ok';
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 updates = results.filter((r) => r.hasUpdate);
905
- if (updates.length === 0) return { ok: true, message: '所有组件已是最新,无需更新' };
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
- + (compatToUpdate.length ? `\n随引擎更新的插件:${compatToUpdate.join('、')}。` : '')
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
- const kept = rows.filter((r) => r.compatible === false);
1009
- footer += (footer ? '\n' : '') + '引擎有新版:兼容插件随引擎一起更新'
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.13",
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": ["launcher", "bin", "assets", "scripts"],
26
+ "files": [
27
+ "launcher",
28
+ "bin",
29
+ "assets",
30
+ "scripts"
31
+ ],
27
32
  "license": "MIT"
28
33
  }
@@ -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 ELECTRON_MIRROR_DEFAULT = 'https://npmmirror.com/mirrors/electron/';
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 (mirror) ...');
20
- const env = Object.assign({}, process.env);
21
- if (!env.ELECTRON_MIRROR) env.ELECTRON_MIRROR = ELECTRON_MIRROR_DEFAULT;
22
- const r = spawnSync(process.execPath, [path.join(electronDir, 'install.js')], { stdio: 'inherit', env, windowsHide: true });
23
- if (r.status !== 0 || !fs.existsSync(exe)) {
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);