From 77473b58175fdfbc654a4acbfb4c28b2ea230ac5 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Jul 2025 21:18:15 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E7=A7=BB=E9=99=A4=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E9=A1=B9=E7=9B=AE=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.py | 3 + src/plugin_system/base/base_plugin.py | 146 ++++++++++---------- src/plugins/built_in/core_actions/plugin.py | 2 +- template/bot_config_template.toml | 1 - 4 files changed, 75 insertions(+), 77 deletions(-) diff --git a/src/main.py b/src/main.py index 768913c4b..e814a86b7 100644 --- a/src/main.py +++ b/src/main.py @@ -42,6 +42,9 @@ willing_manager = get_willing_manager() logger = get_logger("main") +from src.manager.local_store_manager import local_storage +from src.manager.mood_manager import MoodUpdateTask, MoodPrintTask + class MainSystem: def __init__(self): diff --git a/src/plugin_system/base/base_plugin.py b/src/plugin_system/base/base_plugin.py index 5c7edd23b..5afb06d78 100644 --- a/src/plugin_system/base/base_plugin.py +++ b/src/plugin_system/base/base_plugin.py @@ -292,15 +292,15 @@ class BasePlugin(ABC): if "plugin" in self.config_schema and isinstance(self.config_schema["plugin"], dict): config_version_field = self.config_schema["plugin"].get("config_version") if isinstance(config_version_field, ConfigField): - return config_version_field.default - return "1.0.0" + return str(config_version_field.default) + return "" def _get_current_config_version(self, config: Dict[str, Any]) -> str: - """从配置文件中获取当前版本号""" - if "plugin" in config and "config_version" in config["plugin"]: - return str(config["plugin"]["config_version"]) - # 如果没有config_version字段,视为最早的版本 - return "0.0.0" + """从已加载的配置中获取当前版本号""" + # 兼容旧版,尝试从'plugin'或'Plugin'节获取 + if "plugin" in config and isinstance(config.get("plugin"), dict): + return str(config["plugin"].get("config_version", "")) + return "" # 返回空字符串表示未找到 def _backup_config_file(self, config_file_path: str) -> str: """备份配置文件""" @@ -383,6 +383,23 @@ class BasePlugin(ABC): return migrated_config + def _ensure_config_completeness(self, existing_config: Dict[str, Any]) -> Dict[str, Any]: + """确保现有配置的完整性,用schema中的默认值填充缺失的键""" + if not self.config_schema: + return existing_config + + # 创建一个基于schema的完整配置作为参考 + full_config = self._generate_config_from_schema() + migrated_config = self._migrate_config_values(existing_config, full_config) + + # 检查是否有任何值被修改过(即,有缺失的键被填充) + if migrated_config != existing_config: + logger.info(f"{self.log_prefix} 检测到配置文件中缺少部分字段,已使用默认值补全。") + # 注意:这里可以选择是否要自动写回文件,目前只在内存中更新 + # self._save_config_to_file(migrated_config, config_file_path) + + return migrated_config + def _generate_config_from_schema(self) -> Dict[str, Any]: """根据schema生成配置数据结构(不写入文件)""" if not self.config_schema: @@ -474,86 +491,65 @@ class BasePlugin(ABC): logger.error(f"{self.log_prefix} 保存配置文件失败: {e}", exc_info=True) def _load_plugin_config(self): - """加载插件配置文件,支持版本检查和自动迁移""" + """加载插件配置文件,并处理版本迁移""" if not self.config_file_name: - logger.debug(f"{self.log_prefix} 未指定配置文件,跳过加载") + logger.debug(f"{self.log_prefix} 插件未指定配置文件,跳过加载") return - # 优先使用传入的插件目录路径 - if self.plugin_dir: - plugin_dir = self.plugin_dir - else: - # fallback:尝试从类的模块信息获取路径 - try: - plugin_module_path = inspect.getfile(self.__class__) - plugin_dir = os.path.dirname(plugin_module_path) - except (TypeError, OSError): - # 最后的fallback:从模块的__file__属性获取 - module = inspect.getmodule(self.__class__) - if module and hasattr(module, "__file__") and module.__file__: - plugin_dir = os.path.dirname(module.__file__) - else: - logger.warning(f"{self.log_prefix} 无法获取插件目录路径,跳过配置加载") - return + config_dir = os.path.join("config", "plugins", self.plugin_name) + os.makedirs(config_dir, exist_ok=True) + config_file_path = os.path.join(config_dir, self.config_file_name) - config_file_path = os.path.join(plugin_dir, self.config_file_name) - - # 如果配置文件不存在,生成默认配置 + # 1. 配置文件不存在 if not os.path.exists(config_file_path): - logger.info(f"{self.log_prefix} 配置文件 {config_file_path} 不存在,将生成默认配置。") - self._generate_and_save_default_config(config_file_path) - - if not os.path.exists(config_file_path): - logger.warning(f"{self.log_prefix} 配置文件 {config_file_path} 不存在且无法生成。") + logger.info(f"{self.log_prefix} 未找到配置文件,将创建默认配置: {config_file_path}") + self.config = self._generate_config_from_schema() + self._save_config_to_file(self.config, config_file_path) return - file_ext = os.path.splitext(self.config_file_name)[1].lower() - - if file_ext == ".toml": - # 加载现有配置 + # 2. 配置文件存在,加载并检查版本 + try: with open(config_file_path, "r", encoding="utf-8") as f: - existing_config = toml.load(f) or {} + loaded_config = toml.load(f) + except Exception as e: + logger.error(f"{self.log_prefix} 加载配置文件失败: {e},将使用默认配置") + self.config = self._generate_config_from_schema() + return - # 检查配置版本 - current_version = self._get_current_config_version(existing_config) + expected_version = self._get_expected_config_version() + current_version = self._get_current_config_version(loaded_config) - # 如果配置文件没有版本信息,跳过版本检查 - if current_version == "0.0.0": - logger.debug(f"{self.log_prefix} 配置文件无版本信息,跳过版本检查") - self.config = existing_config - else: - expected_version = self._get_expected_config_version() + # 3. 版本匹配,直接加载 + # 如果版本匹配,或者没有可预期的版本(例如插件未定义),则直接加载 + if not expected_version or (current_version and expected_version == current_version): + logger.debug(f"{self.log_prefix} 配置文件版本匹配 (v{current_version}),直接加载") + self.config = self._ensure_config_completeness(loaded_config) + return - if current_version != expected_version: - logger.info( - f"{self.log_prefix} 检测到配置版本需要更新: 当前=v{current_version}, 期望=v{expected_version}" - ) - - # 生成新的默认配置结构 - new_config_structure = self._generate_config_from_schema() - - # 迁移旧配置值到新结构 - migrated_config = self._migrate_config_values(existing_config, new_config_structure) - - # 保存迁移后的配置 - self._save_config_to_file(migrated_config, config_file_path) - - logger.info(f"{self.log_prefix} 配置文件已从 v{current_version} 更新到 v{expected_version}") - - self.config = migrated_config - else: - logger.debug(f"{self.log_prefix} 配置版本匹配 (v{current_version}),直接加载") - self.config = existing_config - - logger.debug(f"{self.log_prefix} 配置已从 {config_file_path} 加载") - - # 从配置中更新 enable_plugin - if "plugin" in self.config and "enabled" in self.config["plugin"]: - self.enable_plugin = self.config["plugin"]["enabled"] - logger.debug(f"{self.log_prefix} 从配置更新插件启用状态: {self.enable_plugin}") + # 4. 版本不匹配或当前版本未知,执行迁移 + if current_version: + logger.info( + f"{self.log_prefix} 配置文件版本不匹配 (v{current_version} -> v{expected_version}),开始迁移..." + ) else: - logger.warning(f"{self.log_prefix} 不支持的配置文件格式: {file_ext},仅支持 .toml") - self.config = {} + # 如果配置文件中没有版本信息,也触发更新 + logger.info(f"{self.log_prefix} 未在配置文件中找到版本信息,将执行更新...") + + # 备份旧文件 + backup_path = self._backup_config_file(config_file_path) + logger.info(f"{self.log_prefix} 已备份旧配置文件到: {backup_path}") + + # 生成新的配置结构 + new_config = self._generate_config_from_schema() + + # 迁移旧的配置值 + migrated_config = self._migrate_config_values(loaded_config, new_config) + + # 保存新的配置文件 + self._save_config_to_file(migrated_config, config_file_path) + logger.info(f"{self.log_prefix} 配置文件更新完成!") + + self.config = migrated_config @abstractmethod def get_plugin_components(self) -> List[tuple[ComponentInfo, Type]]: diff --git a/src/plugins/built_in/core_actions/plugin.py b/src/plugins/built_in/core_actions/plugin.py index c34adbfd2..cb469ae87 100644 --- a/src/plugins/built_in/core_actions/plugin.py +++ b/src/plugins/built_in/core_actions/plugin.py @@ -141,7 +141,7 @@ class CoreActionsPlugin(BasePlugin): config_schema = { "plugin": { "enabled": ConfigField(type=bool, default=True, description="是否启用插件"), - "config_version": ConfigField(type=str, default="0.2.0", description="配置文件版本"), + "config_version": ConfigField(type=str, default="0.3.1", description="配置文件版本"), }, "components": { "enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"), diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 365d6db4f..84bca3718 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -116,7 +116,6 @@ ban_msgs_regex = [ [normal_chat] #普通聊天 #一般回复参数 -replyer_random_probability = 0.5 # 麦麦回答时选择首要模型的概率(与之相对的,次要模型的概率为1 - replyer_random_probability) emoji_chance = 0.2 # 麦麦一般回复时使用表情包的概率,设置为1让麦麦自己决定发不发 thinking_timeout = 120 # 麦麦最长思考时间,超过这个时间的思考会放弃(往往是api反应太慢)