diff --git a/main/xiaozhi-server/app.py b/main/xiaozhi-server/app.py index ab085464..701d11fb 100644 --- a/main/xiaozhi-server/app.py +++ b/main/xiaozhi-server/app.py @@ -47,6 +47,13 @@ async def main(): check_ffmpeg_installed() config = load_config() + # 初始化插件描述(需要在load_config之后、服务启动之前) + try: + from plugins_func.functions.get_news_from_newsnow import init_news_description + init_news_description(config) + except Exception: + pass + # auth_key优先级:配置文件server.auth_key > manager-api.secret > 自动生成 # auth_key用于jwt认证,比如视觉分析接口的jwt认证、ota接口的token生成与websocket认证 # 获取配置文件中的auth_key diff --git a/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py b/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py index e32ea3a0..372ea48d 100644 --- a/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py +++ b/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py @@ -51,33 +51,36 @@ CHANNEL_MAP = { "虫部落": "chongbuluo-latest", } - # 默认新闻来源字典,当配置中没有指定时使用 DEFAULT_NEWS_SOURCES = "澎湃新闻;百度热搜;财联社" +def _get_newsnow_config(conn): + """从连接配置中获取newsnow插件配置,优先用conn.common_config,兜底用conn.config""" + # 优先从公共配置获取(保留本地config.yaml的配置) + common_plugins = getattr(conn, "common_config", {}).get("plugins", {}) + common_newsnow = common_plugins.get("get_news_from_newsnow", {}) + common_sources = common_newsnow.get("news_sources", "") + if isinstance(common_sources, str) and common_sources.strip(): + return common_sources + + # 兜底从连接配置获取 + plugins = conn.config.get("plugins", {}) + newsnow = plugins.get("get_news_from_newsnow", {}) + sources = newsnow.get("news_sources", "") + if isinstance(sources, str) and sources.strip(): + return sources + + return "" def get_news_sources_from_config(conn): """从配置中获取新闻源字符串""" try: - # 尝试从插件配置中获取新闻源 - if ( - conn.config.get("plugins") - and conn.config["plugins"].get("get_news_from_newsnow") - and conn.config["plugins"]["get_news_from_newsnow"].get("news_sources") - ): - # 获取配置的新闻源字符串 - news_sources_config = conn.config["plugins"]["get_news_from_newsnow"][ - "news_sources" - ] - - if isinstance(news_sources_config, str) and news_sources_config.strip(): - logger.bind(tag=TAG).debug(f"使用配置的新闻源: {news_sources_config}") - return news_sources_config - else: - logger.bind(tag=TAG).warning("新闻源配置为空或格式错误,使用默认配置") - else: - logger.bind(tag=TAG).debug("未找到新闻源配置,使用默认配置") + result = _get_newsnow_config(conn) + if result: + logger.bind(tag=TAG).debug(f"使用配置的新闻源: {result}") + return result + logger.bind(tag=TAG).debug("未找到新闻源配置,使用默认配置") return DEFAULT_NEWS_SOURCES except Exception as e: @@ -85,9 +88,26 @@ def get_news_sources_from_config(conn): return DEFAULT_NEWS_SOURCES -# 从CHANNEL_MAP获取所有可用的新闻源名称 -available_sources = list(CHANNEL_MAP.keys()) -example_sources_str = "、".join(available_sources) +# 从默认配置获取可用的新闻源名称(运行时由get_news_sources_from_config动态获取) +example_sources_str = DEFAULT_NEWS_SOURCES.replace(";","、") + +def init_news_description(config: dict): + """项目启动时调用一次,根据配置更新工具描述中的新闻源示例""" + from types import SimpleNamespace + from plugins_func.register import all_function_registry + + # 复用get_news_sources_from_config,用SimpleNamespace模拟conn + conn_wrapper = SimpleNamespace(config=config) + news_sources = get_news_sources_from_config(conn_wrapper) + + sources_str = news_sources.replace(";","、") + + func_item = all_function_registry.get("get_news_from_newsnow") + if func_item: + func_item.description["function"]["parameters"]["properties"]["source"][ + "description" + ] = f"新闻源的标准中文名称,例如{sources_str}等。可选参数,如果不提供则使用默认新闻源" + logger.bind(tag=TAG).info(f"新闻工具描述已初始化,可用新闻源: {sources_str}") GET_NEWS_FROM_NEWSNOW_FUNCTION_DESC = { "type": "function", @@ -99,7 +119,7 @@ GET_NEWS_FROM_NEWSNOW_FUNCTION_DESC = { "properties": { "source": { "type": "string", - "description": "新闻源名称,如'澎湃新闻'、'百度热搜'、'IT之家'等。可选参数", + "description": f"新闻源的标准中文名称,例如{example_sources_str}等。可选参数,如果不提供则使用默认新闻源", }, "detail": { "type": "boolean",