From 80ac48595aecaf469fb7f6f9e2abe2d26c693295 Mon Sep 17 00:00:00 2001 From: kawayiYokami <289104862@qq.com> Date: Wed, 17 Sep 2025 23:49:44 +0800 Subject: [PATCH 1/3] Fix: hot reload state synchronization issue in ProviderManager --- astrbot/core/provider/manager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/astrbot/core/provider/manager.py b/astrbot/core/provider/manager.py index 3b50e4976..7d79291ab 100644 --- a/astrbot/core/provider/manager.py +++ b/astrbot/core/provider/manager.py @@ -389,6 +389,10 @@ async def reload(self, provider_config: dict): if provider_config["enable"]: await self.load_provider(provider_config) + # 重新获取最新的配置 + latest_config = self.acm.get_conf("default") + self.providers_config = latest_config["provider"] + # 和配置文件保持同步 config_ids = [provider["id"] for provider in self.providers_config] logger.debug(f"providers in user's config: {config_ids}") From 198367a63da09bfad0ff754ddecdec32de4060e8 Mon Sep 17 00:00:00 2001 From: kawayiYokami <289104862@qq.com> Date: Thu, 18 Sep 2025 00:00:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E5=95=86=E4=B9=8B=E5=90=8E=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/provider/manager.py | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/astrbot/core/provider/manager.py b/astrbot/core/provider/manager.py index 7d79291ab..61064c3d9 100644 --- a/astrbot/core/provider/manager.py +++ b/astrbot/core/provider/manager.py @@ -400,29 +400,50 @@ async def reload(self, provider_config: dict): if key not in config_ids: await self.terminate_provider(key) - if len(self.provider_insts) == 0: + # 确保当前 Provider 实例仍然有效 + if ( + self.curr_provider_inst + and self.curr_provider_inst.meta().id not in self.inst_map + ): self.curr_provider_inst = None - elif self.curr_provider_inst is None and len(self.provider_insts) > 0: + # 自动选择第一个可用的 Provider + if self.curr_provider_inst is None and len(self.provider_insts) > 0: self.curr_provider_inst = self.provider_insts[0] logger.info( f"自动选择 {self.curr_provider_inst.meta().id} 作为当前提供商适配器。" ) + elif len(self.provider_insts) == 0: + self.curr_provider_inst = None - if len(self.stt_provider_insts) == 0: + # 确保当前 STT Provider 实例仍然有效 + if ( + self.curr_stt_provider_inst + and self.curr_stt_provider_inst.meta().id not in self.inst_map + ): self.curr_stt_provider_inst = None - elif self.curr_stt_provider_inst is None and len(self.stt_provider_insts) > 0: + # 自动选择第一个可用的 STT Provider + if self.curr_stt_provider_inst is None and len(self.stt_provider_insts) > 0: self.curr_stt_provider_inst = self.stt_provider_insts[0] logger.info( f"自动选择 {self.curr_stt_provider_inst.meta().id} 作为当前语音转文本提供商适配器。" ) + elif len(self.stt_provider_insts) == 0: + self.curr_stt_provider_inst = None - if len(self.tts_provider_insts) == 0: + # 确保当前 TTS Provider 实例仍然有效 + if ( + self.curr_tts_provider_inst + and self.curr_tts_provider_inst.meta().id not in self.inst_map + ): self.curr_tts_provider_inst = None - elif self.curr_tts_provider_inst is None and len(self.tts_provider_insts) > 0: + # 自动选择第一个可用的 TTS Provider + if self.curr_tts_provider_inst is None and len(self.tts_provider_insts) > 0: self.curr_tts_provider_inst = self.tts_provider_insts[0] logger.info( f"自动选择 {self.curr_tts_provider_inst.meta().id} 作为当前文本转语音提供商适配器。" ) + elif len(self.tts_provider_insts) == 0: + self.curr_tts_provider_inst = None def get_insts(self): return self.provider_insts From bce634b3cac24cc7fd4ebb323b3b1679d80a76cd Mon Sep 17 00:00:00 2001 From: kawayiYokami <289104862@qq.com> Date: Thu, 18 Sep 2025 00:17:28 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E7=AE=80=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/provider/manager.py | 80 +++++++++++++------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/astrbot/core/provider/manager.py b/astrbot/core/provider/manager.py index 61064c3d9..c16daa2e0 100644 --- a/astrbot/core/provider/manager.py +++ b/astrbot/core/provider/manager.py @@ -384,14 +384,36 @@ async def load_provider(self, provider_config: dict): f"实例化 {provider_config['type']}({provider_config['id']}) 提供商适配器失败:{e}" ) + def _sync_current_provider(self, inst_list, curr_attr_name, provider_name): + """同步当前提供商实例,确保其有效性并在必要时自动选择第一个可用实例""" + curr = getattr(self, curr_attr_name) + # 如果当前实例无效(不在inst_map中),则置为None + if curr and curr.meta().id not in self.inst_map: + curr = None + # 如果当前没有实例但列表中有实例,则自动选择第一个 + if curr is None: + if inst_list: + curr = inst_list[0] + logger.info( + f"自动选择 {curr.meta().id} 作为当前{provider_name}提供商适配器。" + ) + else: + curr = None + setattr(self, curr_attr_name, curr) + async def reload(self, provider_config: dict): await self.terminate_provider(provider_config["id"]) if provider_config["enable"]: await self.load_provider(provider_config) - # 重新获取最新的配置 - latest_config = self.acm.get_conf("default") - self.providers_config = latest_config["provider"] + # 重新获取最新的配置,增加错误处理 + try: + latest_config = self.acm.get_conf("default") + self.providers_config = latest_config.get("provider", []) + except Exception as e: + logger.error(f"获取最新配置时出错: {e}") + # 使用空列表作为后备方案 + self.providers_config = [] # 和配置文件保持同步 config_ids = [provider["id"] for provider in self.providers_config] @@ -400,50 +422,14 @@ async def reload(self, provider_config: dict): if key not in config_ids: await self.terminate_provider(key) - # 确保当前 Provider 实例仍然有效 - if ( - self.curr_provider_inst - and self.curr_provider_inst.meta().id not in self.inst_map - ): - self.curr_provider_inst = None - # 自动选择第一个可用的 Provider - if self.curr_provider_inst is None and len(self.provider_insts) > 0: - self.curr_provider_inst = self.provider_insts[0] - logger.info( - f"自动选择 {self.curr_provider_inst.meta().id} 作为当前提供商适配器。" - ) - elif len(self.provider_insts) == 0: - self.curr_provider_inst = None - - # 确保当前 STT Provider 实例仍然有效 - if ( - self.curr_stt_provider_inst - and self.curr_stt_provider_inst.meta().id not in self.inst_map - ): - self.curr_stt_provider_inst = None - # 自动选择第一个可用的 STT Provider - if self.curr_stt_provider_inst is None and len(self.stt_provider_insts) > 0: - self.curr_stt_provider_inst = self.stt_provider_insts[0] - logger.info( - f"自动选择 {self.curr_stt_provider_inst.meta().id} 作为当前语音转文本提供商适配器。" - ) - elif len(self.stt_provider_insts) == 0: - self.curr_stt_provider_inst = None - - # 确保当前 TTS Provider 实例仍然有效 - if ( - self.curr_tts_provider_inst - and self.curr_tts_provider_inst.meta().id not in self.inst_map - ): - self.curr_tts_provider_inst = None - # 自动选择第一个可用的 TTS Provider - if self.curr_tts_provider_inst is None and len(self.tts_provider_insts) > 0: - self.curr_tts_provider_inst = self.tts_provider_insts[0] - logger.info( - f"自动选择 {self.curr_tts_provider_inst.meta().id} 作为当前文本转语音提供商适配器。" - ) - elif len(self.tts_provider_insts) == 0: - self.curr_tts_provider_inst = None + # 使用辅助函数同步各个提供商实例 + self._sync_current_provider(self.provider_insts, "curr_provider_inst", "提供商") + self._sync_current_provider( + self.stt_provider_insts, "curr_stt_provider_inst", "语音转文本" + ) + self._sync_current_provider( + self.tts_provider_insts, "curr_tts_provider_inst", "文本转语音" + ) def get_insts(self): return self.provider_insts