@zaofan/dsh-qqbot 1.10.20 → 1.10.21

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.
@@ -1299,7 +1299,7 @@ window.__ModuleLoader__.load({
1299
1299
  setTimeout(function () {
1300
1300
  try {
1301
1301
  setBusy('')
1302
- save(list)
1302
+ save(list, true)
1303
1303
  } catch (e) {
1304
1304
  setMsg('扫码成功但自动保存失败: ' + (e && e.message ? e.message : e) + ' —— 请手动点保存')
1305
1305
  }
@@ -1671,9 +1671,13 @@ window.__ModuleLoader__.load({
1671
1671
  setInsts(next)
1672
1672
  return next
1673
1673
  }
1674
- function save(listOverride) {
1675
- if (busy) return
1674
+ function save(listOverride, force) { SAVEOVERRIDE
1675
+ if (busy && force !== true) return
1676
1676
  setBusy('save'); setMsg('保存中…')
1677
+ // ⚠️ 2026-10-22 修(卡在「保存中」的根因):保存按钮写的是 onClick: save,React 会把
1678
+ // MouseEvent 当第一个参数传进来;如果直接当列表用,.filter 会抛 TypeError,
1679
+ // busy 永远停在 save ⇒ 界面一直转圈。只接受数组,其余一律回落到当前 insts。
1680
+ if (!Array.isArray(listOverride)) listOverride = null
1677
1681
  var list = (listOverride || insts || []).filter(function (x) { return x.id && (x.appId || x.appSecret || x.hasSecret || !x._new || x._bound) })
1678
1682
  // 空账号(全空且没绑定)不保存; 全新手动号若两凭据都空则提示(hasSecret=已保存的账号不算空)
1679
1683
  var blanks = list.filter(function (x) { return !x.appSecret && !x.hasSecret && !x._bound })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaofan/dsh-qqbot",
3
- "version": "1.10.20",
3
+ "version": "1.10.21",
4
4
  "description": "QQ Bot IM channel plugin for deepseek-harness (dsh)",
5
5
  "type": "module",
6
6
  "main": "./entry.js",
package/settings-host.js CHANGED
@@ -28,65 +28,54 @@ const NS = 'im-qqbot';
28
28
  * 上溯层级在单包合并时已按包根位置修正); 若该位置没有 cordis.patch.yml(link/symlink 安装时
29
29
  * 本文件被从源码目录加载), 则扫描 ~/.dsh/profiles/* 找装着 @zaofan/dsh-qqbot 的 profile。
30
30
  */
31
- function resolveProfileRoot() {
32
- // 2026-10-22(issue #14 建议 1):宿主经 profileContext 直接给了 profile 目录就用它,
33
- // 别再从代码位置/目录扫描去猜(生成式安装下上溯 3 级会落到 .generations/live/<gen>)。
34
- const fromCtx = (globalThis.__dshProfileDir ?? '').trim();
35
- if (fromCtx) { try { return fromCtx; } catch { /* 回落 */ } }
36
- // 2026-10-20 修(GitHub issue #14): 生成式安装(dsh-market / DSH Desktop)下,
37
- // "包根上溯 3 级"得到的是 profiles/.generations/live/<pkg>, 不是 profile 根;
38
- // 且 Desktop 的 DSH_HOME 在 %APPDATA%dsh-desktopharness, 原兜底写死 ~/.dsh 扫不到。
39
- // → 显式环境变量 > 代码位置 > .generations 反推 > 多 home 扫描。
40
- for (const k of ['DSH_PROFILE_DIR', 'DSH_PROFILE_ROOT']) {
41
- const v = (process.env[k] ?? '').trim();
42
- if (v) { try { if (existsSync(join(v, 'cordis.patch.yml'))) return v; } catch { /* 下一个 */ } }
43
- }
44
- const here = dirname(fileURLToPath(import.meta.url));
45
- const byLocation = resolve(here, '..', '..', '..');
46
- try {
47
- if (existsSync(join(byLocation, 'cordis.patch.yml'))) return byLocation;
48
- } catch { /* 继续扫描 */ }
49
- const roots = [];
50
- try {
51
- let cur = here;
52
- for (let n = 0; n < 12; n++) {
53
- cur = dirname(cur);
54
- if (basename(cur) === '.generations') { roots.push(dirname(cur)); break; }
55
- }
56
- } catch { /* ignore */ }
57
- const homeEnv = (process.env.DSH_HOME ?? '').trim();
58
- if (homeEnv) roots.push(join(homeEnv, 'profiles'));
59
- roots.push(join(homedir(), '.dsh', 'profiles'));
60
- for (const base of roots) {
61
- try {
62
- // 2026-10-22 修(GitHub issue #15):原来"第一个有 cordis.patch.yml 的就用"——
63
- // readdirSync 是字母序,desktop-safe-mode 排在 web 前且也有 patch ⇒ 面板把凭据
64
- // 写进了没在运行的 profile(web 才是真跑的那个),表现就是"一直连不上"。
65
- // 改为**两轮扫描:先只认装了本插件的 profile**,都没有才退回 patch 判据。
66
- const names = readdirSync(base);
67
- const dirs = [];
68
- for (const name of names) {
69
- const prof = resolve(base, name);
70
- try { if (statSync(prof).isDirectory()) dirs.push(prof); } catch { /* 跳过 */ }
71
- }
72
- // 第一轮:装了 @zaofan/dsh-qqbot 的 profile(= 真正在跑插件的那个)
73
- for (const prof of dirs) {
74
- try {
75
- if (existsSync(join(prof, 'node_modules', '@zaofan', 'dsh-qqbot'))) return prof;
76
- } catch { /* 下一判据 */ }
77
- try {
78
- const pkg = JSON.parse(readFileSync(join(prof, 'package.json'), 'utf8'));
79
- const blob = JSON.stringify(pkg.dsh?.profile?.bundles ?? []) + JSON.stringify(pkg.dependencies ?? {});
80
- if (blob.includes('@zaofan/dsh-qqbot')) return prof;
81
- } catch { /* 无 package.json */ }
82
- }
83
- // 第二轮:退化为"有 cordis.patch.yml"(老行为,仅当第一轮全落空时)
84
- for (const prof of dirs) {
85
- try { if (existsSync(join(prof, 'cordis.patch.yml'))) return prof; } catch { /* 跳过 */ }
86
- } } catch { /* 该 profiles 根不存在 */ }
87
- }
88
- return byLocation;
89
- }
31
+ function resolveProfileRoot() {
32
+ // 2026-10-20 修(GitHub issue #14): 生成式安装(dsh-market / DSH Desktop)下,
33
+ // "包根上溯 3 级"得到的是 profiles/.generations/live/<pkg>, 不是 profile 根;
34
+ // 且 Desktop 的 DSH_HOME 在 %APPDATA%dsh-desktopharness, 原兜底写死 ~/.dsh 扫不到。
35
+ // → 显式环境变量 > 代码位置 > .generations 反推 > 多 home 扫描。
36
+ for (const k of ['DSH_PROFILE_DIR', 'DSH_PROFILE_ROOT']) {
37
+ const v = (process.env[k] ?? '').trim();
38
+ if (v) { try { if (existsSync(join(v, 'cordis.patch.yml'))) return v; } catch { /* 下一个 */ } }
39
+ }
40
+ const here = dirname(fileURLToPath(import.meta.url));
41
+ const byLocation = resolve(here, '..', '..', '..');
42
+ try {
43
+ if (existsSync(join(byLocation, 'cordis.patch.yml'))) return byLocation;
44
+ } catch { /* 继续扫描 */ }
45
+ const roots = [];
46
+ try {
47
+ let cur = here;
48
+ for (let n = 0; n < 12; n++) {
49
+ cur = dirname(cur);
50
+ if (basename(cur) === '.generations') { roots.push(dirname(cur)); break; }
51
+ }
52
+ } catch { /* ignore */ }
53
+ const homeEnv = (process.env.DSH_HOME ?? '').trim();
54
+ if (homeEnv) roots.push(join(homeEnv, 'profiles'));
55
+ roots.push(join(homedir(), '.dsh', 'profiles'));
56
+ for (const base of roots) {
57
+ try {
58
+ for (const name of readdirSync(base)) {
59
+ const prof = resolve(base, name);
60
+ try {
61
+ if (!statSync(prof).isDirectory()) continue;
62
+ } catch { continue; }
63
+ try {
64
+ if (existsSync(join(prof, 'cordis.patch.yml'))) return prof;
65
+ } catch { /* 走下一判据 */ }
66
+ try {
67
+ if (existsSync(join(prof, 'node_modules', '@zaofan', 'dsh-qqbot'))) return prof;
68
+ } catch { /* 走下一判据 */ }
69
+ try {
70
+ const pkg = JSON.parse(readFileSync(join(prof, 'package.json'), 'utf8'));
71
+ const blob = JSON.stringify(pkg.dsh?.profile?.bundles ?? []) + JSON.stringify(pkg.dependencies ?? {});
72
+ if (blob.includes('@zaofan/dsh-qqbot')) return prof;
73
+ } catch { /* 无 package.json, 跳过 */ }
74
+ }
75
+ } catch { /* 该 profiles 根不存在 */ }
76
+ }
77
+ return byLocation;
78
+ }
90
79
  const PROFILE_ROOT = resolveProfileRoot();
91
80
  /** cordis.patch.yml = 宿主插件装配文件(账号实例声明处; 改它需重启 dsh 生效) */
92
81
  const PATCH_FILE = join(PROFILE_ROOT, 'cordis.patch.yml');