@ryantest/openclaw-qqbot 1.6.7-beta.11 → 1.6.7-beta.13

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.
@@ -694,92 +694,134 @@ function fireHotUpgrade(targetVersion, pkg, useLocal) {
694
694
  // openclaw plugins install/update 启动时会校验整个配置文件,
695
695
  // 如果 channels.qqbot 已存在但 qqbot 插件尚未加载,校验会报 "unknown channel id: qqbot"。
696
696
  //
697
- // 在 TS 端(而非 shell 脚本端)创建临时配置,确保无论脚本版本新旧都能正确绕过校验。
698
- // 通过 OPENCLAW_CONFIG_PATH 环境变量让 openclaw CLI 子进程使用临时配置。
697
+ // 策略(双保险):
698
+ // 1. 直接从真实 openclaw.json 中临时移除 channels.qqbot / plugins.entries.openclaw-qqbot,
699
+ // 暂存到备份文件,脚本完成后恢复。这是最可靠的方式,因为 openclaw CLI 一定读取真实配置。
700
+ // 移除后的配置是合法的,gateway 的 config file watcher 重新加载不会失败。
701
+ // 2. 同时创建临时配置副本并通过 OPENCLAW_CONFIG_PATH 环境变量传递给子进程,
702
+ // 作为额外保险(防止某些 openclaw 版本在 install 过程中多次加载配置)。
699
703
  const homeDir = getHomeDir();
700
704
  const realConfigPath = path.join(homeDir, ".openclaw", "openclaw.json");
705
+ const channelBackupPath = path.join(homeDir, ".openclaw", ".qqbot-upgrade-channel-stash.json");
706
+ let stashedChannelConfig = null;
707
+ let stashedPluginEntry = null;
708
+ let configModified = false;
701
709
  let tempConfigPath = null;
702
710
  const childEnv = { ...process.env };
703
711
  try {
704
712
  if (fs.existsSync(realConfigPath)) {
705
713
  const cfg = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
706
- let needsTemp = false;
707
- // 检查是否存在会导致校验失败的配置项
714
+ let needsModify = false;
708
715
  if (cfg.channels?.qqbot)
709
- needsTemp = true;
710
- if (Array.isArray(cfg.plugins?.allow) && cfg.plugins.allow.includes("openclaw-qqbot"))
711
- needsTemp = true;
716
+ needsModify = true;
712
717
  if (cfg.plugins?.entries?.["openclaw-qqbot"])
713
- needsTemp = true;
714
- if (needsTemp) {
715
- const tmpCfg = JSON.parse(JSON.stringify(cfg)); // deep clone
716
- // 移除 channels.qqbot
717
- if (tmpCfg.channels?.qqbot) {
718
- delete tmpCfg.channels.qqbot;
719
- if (Object.keys(tmpCfg.channels).length === 0)
720
- delete tmpCfg.channels;
718
+ needsModify = true;
719
+ if (needsModify) {
720
+ // 暂存需要移除的配置项
721
+ const stash = {};
722
+ if (cfg.channels?.qqbot) {
723
+ stash.channelsQqbot = cfg.channels.qqbot;
724
+ stashedChannelConfig = cfg.channels.qqbot;
721
725
  }
722
- // 移除 plugins.allow 中的 openclaw-qqbot
723
- if (Array.isArray(tmpCfg.plugins?.allow)) {
724
- tmpCfg.plugins.allow = tmpCfg.plugins.allow.filter((p) => p !== "openclaw-qqbot");
725
- if (tmpCfg.plugins.allow.length === 0)
726
- delete tmpCfg.plugins.allow;
726
+ if (cfg.plugins?.entries?.["openclaw-qqbot"]) {
727
+ stash.pluginsEntry = cfg.plugins.entries["openclaw-qqbot"];
728
+ stashedPluginEntry = cfg.plugins.entries["openclaw-qqbot"];
727
729
  }
728
- // 移除 plugins.entries 中的 openclaw-qqbot
729
- if (tmpCfg.plugins?.entries?.["openclaw-qqbot"]) {
730
- delete tmpCfg.plugins.entries["openclaw-qqbot"];
731
- if (Object.keys(tmpCfg.plugins.entries).length === 0)
732
- delete tmpCfg.plugins.entries;
730
+ // 写入备份文件(防止进程异常退出时丢失暂存数据)
731
+ fs.writeFileSync(channelBackupPath, JSON.stringify(stash, null, 2), "utf8");
732
+ // 从真实配置中移除会导致校验失败的项
733
+ if (cfg.channels?.qqbot) {
734
+ delete cfg.channels.qqbot;
735
+ if (Object.keys(cfg.channels).length === 0)
736
+ delete cfg.channels;
733
737
  }
734
- const tmpDir = path.join(homeDir, ".openclaw", ".qqbot-upgrade-tmp");
735
- fs.mkdirSync(tmpDir, { recursive: true });
736
- tempConfigPath = path.join(tmpDir, "openclaw-tmp.json");
737
- fs.writeFileSync(tempConfigPath, JSON.stringify(tmpCfg, null, 4) + "\n");
738
- childEnv.OPENCLAW_CONFIG_PATH = tempConfigPath;
739
- console.log(`[qqbot] fireHotUpgrade: created temp config (without channels.qqbot) at ${tempConfigPath}`);
738
+ if (cfg.plugins?.entries?.["openclaw-qqbot"]) {
739
+ delete cfg.plugins.entries["openclaw-qqbot"];
740
+ if (Object.keys(cfg.plugins.entries).length === 0)
741
+ delete cfg.plugins.entries;
742
+ }
743
+ fs.writeFileSync(realConfigPath, JSON.stringify(cfg, null, 4) + "\n");
744
+ configModified = true;
745
+ console.log(`[qqbot] fireHotUpgrade: temporarily removed channels.qqbot & plugins.entries from real config (stash=${channelBackupPath})`);
746
+ // 双保险:同时创建临时配置副本并通过 OPENCLAW_CONFIG_PATH 传递
747
+ try {
748
+ const tmpDir = path.join(homeDir, ".openclaw", ".qqbot-upgrade-tmp");
749
+ fs.mkdirSync(tmpDir, { recursive: true });
750
+ tempConfigPath = path.join(tmpDir, "openclaw-tmp.json");
751
+ fs.writeFileSync(tempConfigPath, JSON.stringify(cfg, null, 4) + "\n");
752
+ childEnv.OPENCLAW_CONFIG_PATH = tempConfigPath;
753
+ }
754
+ catch { /* 非关键,忽略 */ }
740
755
  }
741
756
  }
742
757
  }
743
758
  catch (e) {
744
- console.warn(`[qqbot] fireHotUpgrade: failed to create temp config: ${e.message}, proceeding with original`);
745
- tempConfigPath = null;
759
+ console.warn(`[qqbot] fireHotUpgrade: failed to modify config for upgrade: ${e.message}, proceeding with original`);
760
+ configModified = false;
761
+ stashedChannelConfig = null;
762
+ stashedPluginEntry = null;
746
763
  }
747
764
  /**
748
- * 将临时配置中 plugins install/update 写入的记录同步回真实配置,然后清理临时文件。
765
+ * 恢复暂存的 channels.qqbot 和 plugins.entries 到真实配置,
766
+ * 同时合并 openclaw plugins install 写入的 installs/entries 记录。
749
767
  */
750
- function syncTempConfigAndCleanup() {
751
- if (!tempConfigPath)
752
- return;
768
+ function restoreConfigAndCleanup() {
753
769
  try {
754
- if (fs.existsSync(tempConfigPath) && fs.existsSync(realConfigPath)) {
755
- const tmp = JSON.parse(fs.readFileSync(tempConfigPath, "utf8"));
756
- const real = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
757
- let changed = false;
758
- // 同步 plugins.installs
759
- if (tmp.plugins?.installs) {
760
- if (!real.plugins)
761
- real.plugins = {};
762
- real.plugins.installs = { ...(real.plugins.installs || {}), ...tmp.plugins.installs };
763
- changed = true;
770
+ // 从备份文件恢复暂存数据(优先使用文件,防止内存中的数据因异常丢失)
771
+ let stash = {};
772
+ if (fs.existsSync(channelBackupPath)) {
773
+ try {
774
+ stash = JSON.parse(fs.readFileSync(channelBackupPath, "utf8"));
764
775
  }
765
- // 同步 plugins.entries
766
- if (tmp.plugins?.entries) {
767
- if (!real.plugins)
768
- real.plugins = {};
769
- real.plugins.entries = { ...(real.plugins.entries || {}), ...tmp.plugins.entries };
770
- changed = true;
776
+ catch { /* 解析失败,使用内存中的数据 */ }
777
+ }
778
+ const channelCfg = stash.channelsQqbot ?? stashedChannelConfig;
779
+ const entryCfg = stash.pluginsEntry ?? stashedPluginEntry;
780
+ if (configModified && fs.existsSync(realConfigPath)) {
781
+ const cfg = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
782
+ // 恢复 channels.qqbot
783
+ if (channelCfg) {
784
+ if (!cfg.channels)
785
+ cfg.channels = {};
786
+ cfg.channels.qqbot = channelCfg;
787
+ }
788
+ // 恢复 plugins.entries.openclaw-qqbot(仅当 openclaw plugins install 没有写入新 entry 时)
789
+ if (entryCfg) {
790
+ if (!cfg.plugins)
791
+ cfg.plugins = {};
792
+ if (!cfg.plugins.entries)
793
+ cfg.plugins.entries = {};
794
+ if (!cfg.plugins.entries["openclaw-qqbot"]) {
795
+ cfg.plugins.entries["openclaw-qqbot"] = entryCfg;
796
+ }
771
797
  }
772
- if (changed) {
773
- fs.writeFileSync(realConfigPath, JSON.stringify(real, null, 4) + "\n");
774
- console.log("[qqbot] fireHotUpgrade: synced install/entries records from temp config to real config");
798
+ // 如果临时配置中有 plugins install 写入的新记录,也合并过来
799
+ if (tempConfigPath && fs.existsSync(tempConfigPath)) {
800
+ try {
801
+ const tmp = JSON.parse(fs.readFileSync(tempConfigPath, "utf8"));
802
+ if (tmp.plugins?.installs) {
803
+ if (!cfg.plugins)
804
+ cfg.plugins = {};
805
+ cfg.plugins.installs = { ...(cfg.plugins.installs || {}), ...tmp.plugins.installs };
806
+ }
807
+ }
808
+ catch { /* 忽略 */ }
775
809
  }
810
+ fs.writeFileSync(realConfigPath, JSON.stringify(cfg, null, 4) + "\n");
811
+ console.log("[qqbot] fireHotUpgrade: restored channels.qqbot & plugins.entries to real config");
776
812
  }
777
813
  }
778
814
  catch (e) {
779
- console.warn(`[qqbot] fireHotUpgrade: failed to sync temp config: ${e.message}`);
815
+ console.warn(`[qqbot] fireHotUpgrade: failed to restore config: ${e.message}`);
780
816
  }
817
+ // 清理备份和临时文件
818
+ try {
819
+ fs.unlinkSync(channelBackupPath);
820
+ }
821
+ catch { /* ignore */ }
781
822
  try {
782
- fs.unlinkSync(tempConfigPath);
823
+ if (tempConfigPath)
824
+ fs.unlinkSync(tempConfigPath);
783
825
  }
784
826
  catch { /* ignore */ }
785
827
  }
@@ -795,7 +837,7 @@ function fireHotUpgrade(targetVersion, pkg, useLocal) {
795
837
  console.error(`[qqbot] fireHotUpgrade: stdout: ${stdout.slice(0, 2000)}`);
796
838
  if (_stderr)
797
839
  console.error(`[qqbot] fireHotUpgrade: stderr: ${_stderr.slice(0, 2000)}`);
798
- syncTempConfigAndCleanup();
840
+ restoreConfigAndCleanup();
799
841
  cleanupTempScript();
800
842
  _upgrading = false;
801
843
  return;
@@ -806,14 +848,14 @@ function fireHotUpgrade(targetVersion, pkg, useLocal) {
806
848
  const newVersion = versionMatch?.[1];
807
849
  if (newVersion === "unknown") {
808
850
  console.error(`[qqbot] fireHotUpgrade: script output QQBOT_NEW_VERSION=unknown, aborting restart`);
809
- syncTempConfigAndCleanup();
851
+ restoreConfigAndCleanup();
810
852
  cleanupTempScript();
811
853
  _upgrading = false;
812
854
  return;
813
855
  }
814
856
  console.log(`[qqbot] fireHotUpgrade: new version=${newVersion || "(not detected)"}, triggering restart...`);
815
- // 脚本执行成功,同步临时配置记录并清理
816
- syncTempConfigAndCleanup();
857
+ // 脚本执行成功,恢复暂存的配置并清理
858
+ restoreConfigAndCleanup();
817
859
  cleanupTempScript();
818
860
  // 文件替换成功,在 restart 之前把 source 从 path 切换为 npm,
819
861
  // 确保新进程启动时读到的是 npm source,不会被本地源码覆盖。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryantest/openclaw-qqbot",
3
- "version": "1.6.7-beta.11",
3
+ "version": "1.6.7-beta.13",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -796,88 +796,126 @@ function fireHotUpgrade(targetVersion?: string, pkg?: string, useLocal?: boolean
796
796
  // openclaw plugins install/update 启动时会校验整个配置文件,
797
797
  // 如果 channels.qqbot 已存在但 qqbot 插件尚未加载,校验会报 "unknown channel id: qqbot"。
798
798
  //
799
- // 在 TS 端(而非 shell 脚本端)创建临时配置,确保无论脚本版本新旧都能正确绕过校验。
800
- // 通过 OPENCLAW_CONFIG_PATH 环境变量让 openclaw CLI 子进程使用临时配置。
799
+ // 策略(双保险):
800
+ // 1. 直接从真实 openclaw.json 中临时移除 channels.qqbot / plugins.entries.openclaw-qqbot,
801
+ // 暂存到备份文件,脚本完成后恢复。这是最可靠的方式,因为 openclaw CLI 一定读取真实配置。
802
+ // 移除后的配置是合法的,gateway 的 config file watcher 重新加载不会失败。
803
+ // 2. 同时创建临时配置副本并通过 OPENCLAW_CONFIG_PATH 环境变量传递给子进程,
804
+ // 作为额外保险(防止某些 openclaw 版本在 install 过程中多次加载配置)。
801
805
  const homeDir = getHomeDir();
802
806
  const realConfigPath = path.join(homeDir, ".openclaw", "openclaw.json");
807
+ const channelBackupPath = path.join(homeDir, ".openclaw", ".qqbot-upgrade-channel-stash.json");
808
+ let stashedChannelConfig: unknown = null;
809
+ let stashedPluginEntry: unknown = null;
810
+ let configModified = false;
803
811
  let tempConfigPath: string | null = null;
804
812
  const childEnv: NodeJS.ProcessEnv = { ...process.env };
805
813
 
806
814
  try {
807
815
  if (fs.existsSync(realConfigPath)) {
808
816
  const cfg = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
809
- let needsTemp = false;
817
+ let needsModify = false;
810
818
 
811
- // 检查是否存在会导致校验失败的配置项
812
- if (cfg.channels?.qqbot) needsTemp = true;
813
- if (Array.isArray(cfg.plugins?.allow) && cfg.plugins.allow.includes("openclaw-qqbot")) needsTemp = true;
814
- if (cfg.plugins?.entries?.["openclaw-qqbot"]) needsTemp = true;
819
+ if (cfg.channels?.qqbot) needsModify = true;
820
+ if (cfg.plugins?.entries?.["openclaw-qqbot"]) needsModify = true;
815
821
 
816
- if (needsTemp) {
817
- const tmpCfg = JSON.parse(JSON.stringify(cfg)); // deep clone
818
-
819
- // 移除 channels.qqbot
820
- if (tmpCfg.channels?.qqbot) {
821
- delete tmpCfg.channels.qqbot;
822
- if (Object.keys(tmpCfg.channels).length === 0) delete tmpCfg.channels;
822
+ if (needsModify) {
823
+ // 暂存需要移除的配置项
824
+ const stash: Record<string, unknown> = {};
825
+ if (cfg.channels?.qqbot) {
826
+ stash.channelsQqbot = cfg.channels.qqbot;
827
+ stashedChannelConfig = cfg.channels.qqbot;
828
+ }
829
+ if (cfg.plugins?.entries?.["openclaw-qqbot"]) {
830
+ stash.pluginsEntry = cfg.plugins.entries["openclaw-qqbot"];
831
+ stashedPluginEntry = cfg.plugins.entries["openclaw-qqbot"];
823
832
  }
824
- // 移除 plugins.allow 中的 openclaw-qqbot
825
- if (Array.isArray(tmpCfg.plugins?.allow)) {
826
- tmpCfg.plugins.allow = tmpCfg.plugins.allow.filter((p: string) => p !== "openclaw-qqbot");
827
- if (tmpCfg.plugins.allow.length === 0) delete tmpCfg.plugins.allow;
833
+ // 写入备份文件(防止进程异常退出时丢失暂存数据)
834
+ fs.writeFileSync(channelBackupPath, JSON.stringify(stash, null, 2), "utf8");
835
+
836
+ // 从真实配置中移除会导致校验失败的项
837
+ if (cfg.channels?.qqbot) {
838
+ delete cfg.channels.qqbot;
839
+ if (Object.keys(cfg.channels).length === 0) delete cfg.channels;
828
840
  }
829
- // 移除 plugins.entries 中的 openclaw-qqbot
830
- if (tmpCfg.plugins?.entries?.["openclaw-qqbot"]) {
831
- delete tmpCfg.plugins.entries["openclaw-qqbot"];
832
- if (Object.keys(tmpCfg.plugins.entries).length === 0) delete tmpCfg.plugins.entries;
841
+ if (cfg.plugins?.entries?.["openclaw-qqbot"]) {
842
+ delete cfg.plugins.entries["openclaw-qqbot"];
843
+ if (Object.keys(cfg.plugins.entries).length === 0) delete cfg.plugins.entries;
833
844
  }
845
+ fs.writeFileSync(realConfigPath, JSON.stringify(cfg, null, 4) + "\n");
846
+ configModified = true;
847
+ console.log(`[qqbot] fireHotUpgrade: temporarily removed channels.qqbot & plugins.entries from real config (stash=${channelBackupPath})`);
834
848
 
835
- const tmpDir = path.join(homeDir, ".openclaw", ".qqbot-upgrade-tmp");
836
- fs.mkdirSync(tmpDir, { recursive: true });
837
- tempConfigPath = path.join(tmpDir, "openclaw-tmp.json");
838
- fs.writeFileSync(tempConfigPath, JSON.stringify(tmpCfg, null, 4) + "\n");
839
- childEnv.OPENCLAW_CONFIG_PATH = tempConfigPath;
840
- console.log(`[qqbot] fireHotUpgrade: created temp config (without channels.qqbot) at ${tempConfigPath}`);
849
+ // 双保险:同时创建临时配置副本并通过 OPENCLAW_CONFIG_PATH 传递
850
+ try {
851
+ const tmpDir = path.join(homeDir, ".openclaw", ".qqbot-upgrade-tmp");
852
+ fs.mkdirSync(tmpDir, { recursive: true });
853
+ tempConfigPath = path.join(tmpDir, "openclaw-tmp.json");
854
+ fs.writeFileSync(tempConfigPath, JSON.stringify(cfg, null, 4) + "\n");
855
+ childEnv.OPENCLAW_CONFIG_PATH = tempConfigPath;
856
+ } catch { /* 非关键,忽略 */ }
841
857
  }
842
858
  }
843
859
  } catch (e: any) {
844
- console.warn(`[qqbot] fireHotUpgrade: failed to create temp config: ${e.message}, proceeding with original`);
845
- tempConfigPath = null;
860
+ console.warn(`[qqbot] fireHotUpgrade: failed to modify config for upgrade: ${e.message}, proceeding with original`);
861
+ configModified = false;
862
+ stashedChannelConfig = null;
863
+ stashedPluginEntry = null;
846
864
  }
847
865
 
848
866
  /**
849
- * 将临时配置中 plugins install/update 写入的记录同步回真实配置,然后清理临时文件。
867
+ * 恢复暂存的 channels.qqbot 和 plugins.entries 到真实配置,
868
+ * 同时合并 openclaw plugins install 写入的 installs/entries 记录。
850
869
  */
851
- function syncTempConfigAndCleanup(): void {
852
- if (!tempConfigPath) return;
870
+ function restoreConfigAndCleanup(): void {
853
871
  try {
854
- if (fs.existsSync(tempConfigPath) && fs.existsSync(realConfigPath)) {
855
- const tmp = JSON.parse(fs.readFileSync(tempConfigPath, "utf8"));
856
- const real = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
857
- let changed = false;
858
- // 同步 plugins.installs
859
- if (tmp.plugins?.installs) {
860
- if (!real.plugins) real.plugins = {};
861
- real.plugins.installs = { ...(real.plugins.installs || {}), ...tmp.plugins.installs };
862
- changed = true;
872
+ // 从备份文件恢复暂存数据(优先使用文件,防止内存中的数据因异常丢失)
873
+ let stash: Record<string, unknown> = {};
874
+ if (fs.existsSync(channelBackupPath)) {
875
+ try {
876
+ stash = JSON.parse(fs.readFileSync(channelBackupPath, "utf8"));
877
+ } catch { /* 解析失败,使用内存中的数据 */ }
878
+ }
879
+ const channelCfg = stash.channelsQqbot ?? stashedChannelConfig;
880
+ const entryCfg = stash.pluginsEntry ?? stashedPluginEntry;
881
+
882
+ if (configModified && fs.existsSync(realConfigPath)) {
883
+ const cfg = JSON.parse(fs.readFileSync(realConfigPath, "utf8"));
884
+
885
+ // 恢复 channels.qqbot
886
+ if (channelCfg) {
887
+ if (!cfg.channels) cfg.channels = {};
888
+ cfg.channels.qqbot = channelCfg;
863
889
  }
864
- // 同步 plugins.entries
865
- if (tmp.plugins?.entries) {
866
- if (!real.plugins) real.plugins = {};
867
- real.plugins.entries = { ...(real.plugins.entries || {}), ...tmp.plugins.entries };
868
- changed = true;
890
+ // 恢复 plugins.entries.openclaw-qqbot(仅当 openclaw plugins install 没有写入新 entry 时)
891
+ if (entryCfg) {
892
+ if (!cfg.plugins) cfg.plugins = {};
893
+ if (!cfg.plugins.entries) cfg.plugins.entries = {};
894
+ if (!cfg.plugins.entries["openclaw-qqbot"]) {
895
+ cfg.plugins.entries["openclaw-qqbot"] = entryCfg;
896
+ }
869
897
  }
870
- if (changed) {
871
- fs.writeFileSync(realConfigPath, JSON.stringify(real, null, 4) + "\n");
872
- console.log("[qqbot] fireHotUpgrade: synced install/entries records from temp config to real config");
898
+
899
+ // 如果临时配置中有 plugins install 写入的新记录,也合并过来
900
+ if (tempConfigPath && fs.existsSync(tempConfigPath)) {
901
+ try {
902
+ const tmp = JSON.parse(fs.readFileSync(tempConfigPath, "utf8"));
903
+ if (tmp.plugins?.installs) {
904
+ if (!cfg.plugins) cfg.plugins = {};
905
+ cfg.plugins.installs = { ...(cfg.plugins.installs || {}), ...tmp.plugins.installs };
906
+ }
907
+ } catch { /* 忽略 */ }
873
908
  }
909
+
910
+ fs.writeFileSync(realConfigPath, JSON.stringify(cfg, null, 4) + "\n");
911
+ console.log("[qqbot] fireHotUpgrade: restored channels.qqbot & plugins.entries to real config");
874
912
  }
875
913
  } catch (e: any) {
876
- console.warn(`[qqbot] fireHotUpgrade: failed to sync temp config: ${e.message}`);
914
+ console.warn(`[qqbot] fireHotUpgrade: failed to restore config: ${e.message}`);
877
915
  }
878
- try {
879
- fs.unlinkSync(tempConfigPath);
880
- } catch { /* ignore */ }
916
+ // 清理备份和临时文件
917
+ try { fs.unlinkSync(channelBackupPath); } catch { /* ignore */ }
918
+ try { if (tempConfigPath) fs.unlinkSync(tempConfigPath); } catch { /* ignore */ }
881
919
  }
882
920
 
883
921
  // 异步执行升级脚本
@@ -890,7 +928,7 @@ function fireHotUpgrade(targetVersion?: string, pkg?: string, useLocal?: boolean
890
928
  console.error(`[qqbot] fireHotUpgrade: script failed: ${error.message}`);
891
929
  if (stdout) console.error(`[qqbot] fireHotUpgrade: stdout: ${stdout.slice(0, 2000)}`);
892
930
  if (_stderr) console.error(`[qqbot] fireHotUpgrade: stderr: ${_stderr.slice(0, 2000)}`);
893
- syncTempConfigAndCleanup();
931
+ restoreConfigAndCleanup();
894
932
  cleanupTempScript();
895
933
  _upgrading = false;
896
934
  return;
@@ -903,7 +941,7 @@ function fireHotUpgrade(targetVersion?: string, pkg?: string, useLocal?: boolean
903
941
  const newVersion = versionMatch?.[1];
904
942
  if (newVersion === "unknown") {
905
943
  console.error(`[qqbot] fireHotUpgrade: script output QQBOT_NEW_VERSION=unknown, aborting restart`);
906
- syncTempConfigAndCleanup();
944
+ restoreConfigAndCleanup();
907
945
  cleanupTempScript();
908
946
  _upgrading = false;
909
947
  return;
@@ -911,8 +949,8 @@ function fireHotUpgrade(targetVersion?: string, pkg?: string, useLocal?: boolean
911
949
 
912
950
  console.log(`[qqbot] fireHotUpgrade: new version=${newVersion || "(not detected)"}, triggering restart...`);
913
951
 
914
- // 脚本执行成功,同步临时配置记录并清理
915
- syncTempConfigAndCleanup();
952
+ // 脚本执行成功,恢复暂存的配置并清理
953
+ restoreConfigAndCleanup();
916
954
  cleanupTempScript();
917
955
 
918
956
  // 文件替换成功,在 restart 之前把 source 从 path 切换为 npm,