From 8828f8401daab8cdeeae8211c6d3fe4b955e314c Mon Sep 17 00:00:00 2001 From: Tink Date: Wed, 25 Jun 2025 16:32:49 +0800 Subject: [PATCH 01/12] =?UTF-8?q?newsnow=20=E6=8F=92=E4=BB=B6=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=89=8D=E7=AB=AF=E9=85=8D=E7=BD=AE=E6=96=B0=E9=97=BB?= =?UTF-8?q?=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/newsnow_plugin_config.md | 107 ++++++++++++++++++ .../resources/db/changelog/202506251619.sql | 21 ++++ .../db/changelog/db.changelog-master.yaml | 9 +- main/xiaozhi-server/config.yaml | 9 +- .../functions/get_news_from_newsnow.py | 52 ++++++--- 5 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 docs/newsnow_plugin_config.md create mode 100644 main/manager-api/src/main/resources/db/changelog/202506251619.sql diff --git a/docs/newsnow_plugin_config.md b/docs/newsnow_plugin_config.md new file mode 100644 index 00000000..3aff257d --- /dev/null +++ b/docs/newsnow_plugin_config.md @@ -0,0 +1,107 @@ +# get_news_from_newsnow 插件新闻源配置指南 + +## 概述 + +`get_news_from_newsnow` 插件现在支持通过Web管理界面动态配置新闻源,不再需要修改代码。用户可以在智控台中为每个智能体配置不同的新闻源。 + +## 配置方式 + +### 1. 通过Web管理界面配置(推荐) + +1. 登录智控台 +2. 进入"角色配置"页面 +3. 选择要配置的智能体 +4. 点击"编辑功能"按钮 +5. 在右侧参数配置区域找到"newsnow新闻聚合"插件 +6. 在"新闻源配置"字段中输入JSON格式的新闻源配置 + +### 2. 配置文件方式 + +在 `config.yaml` 中配置: + +```yaml +plugins: + get_news_from_newsnow: + url: "https://newsnow.busiyi.world/api/s?id=" + news_sources: + thepaper: "澎湃新闻" + baidu: "百度热搜" + cls-depth: "财联社" + # 可以添加更多新闻源 + sina: "新浪新闻" + sohu: "搜狐新闻" +``` + +## 新闻源配置格式 + +新闻源配置使用JSON格式,格式为: + +```json +{ + "source_id": "显示名称", + "source_id2": "显示名称2" +} +``` + +### 配置示例 + +```json +{ + "thepaper": "澎湃新闻", + "baidu": "百度热搜", + "cls-depth": "财联社", + "sina": "新浪新闻", + "sohu": "搜狐新闻" +} +``` + +## 默认配置 + +如果未配置新闻源,插件将使用以下默认配置: + +```json +{ + "thepaper": "澎湃新闻", + "baidu": "百度热搜", + "cls-depth": "财联社" +} +``` + +## 使用说明 + +1. **配置新闻源**:在Web界面或配置文件中设置新闻源 +2. **调用插件**:用户可以说"播报新闻"或"获取新闻" +3. **指定新闻源**:用户可以说"播报澎湃新闻"或"获取百度热搜" +4. **获取详情**:用户可以说"详细介绍这条新闻" + +## 注意事项 + +1. 新闻源的 `source_id` 必须与API接口支持的ID一致 +2. 配置更改后需要重启服务或重新加载配置 +3. 如果配置的新闻源无效,插件会自动使用默认新闻源 +4. JSON格式必须正确,否则会使用默认配置 + +## 故障排除 + +### 问题:配置的新闻源不生效 + +**解决方案**: +1. 检查JSON格式是否正确 +2. 确认新闻源ID是否有效 +3. 查看日志文件中的错误信息 +4. 重启服务 + +### 问题:无法获取新闻 + +**解决方案**: +1. 检查网络连接 +2. 确认API接口地址是否正确 +3. 查看API接口是否可用 +4. 检查日志文件中的错误信息 + +## 技术实现 + +- 插件会从 `conn.config["plugins"]["get_news_from_newsnow"]["news_sources"]` 读取配置 +- 支持字符串格式的JSON和字典格式的配置 +- 配置验证和错误处理机制 +- 向后兼容,未配置时使用默认值 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/db/changelog/202506251619.sql b/main/manager-api/src/main/resources/db/changelog/202506251619.sql new file mode 100644 index 00000000..a458daea --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202506251619.sql @@ -0,0 +1,21 @@ +-- 更新 get_news_from_newsnow 插件配置,添加新闻源配置字段 +-- 执行时间:2025-06-25 + +-- 更新现有的 get_news_from_newsnow 插件配置 +UPDATE ai_model_provider +SET fields = JSON_ARRAY( + JSON_OBJECT( + 'key', 'url', + 'type', 'string', + 'label', '接口地址', + 'default', 'https://newsnow.busiyi.world/api/s?id=' + ), + JSON_OBJECT( + 'key', 'news_sources', + 'type', 'json', + 'label', '新闻源配置', + 'default', '{"thepaper":"澎湃新闻","baidu":"百度热搜","cls-depth":"财联社"}' + ) +) +WHERE provider_code = 'get_news_from_newsnow' +AND model_type = 'Plugin'; \ No newline at end of file diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index 1d6f94e3..c527398a 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -218,4 +218,11 @@ databaseChangeLog: changes: - sqlFile: encoding: utf8 - path: classpath:db/changelog/202506191643.sql \ No newline at end of file + path: classpath:db/changelog/202506191643.sql + - changeSet: + id: 202506251619 + author: Tink + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202506251619.sql \ No newline at end of file diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index 6dc0b25d..07d21cf8 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -120,7 +120,12 @@ plugins: society_rss_url: "https://www.chinanews.com.cn/rss/society.xml" world_rss_url: "https://www.chinanews.com.cn/rss/world.xml" finance_rss_url: "https://www.chinanews.com.cn/rss/finance.xml" - get_news_from_newsnow: {"url": "https://newsnow.busiyi.world/api/s?id="} + get_news_from_newsnow: + url: "https://newsnow.busiyi.world/api/s?id=" + news_sources: + thepaper: "澎湃新闻" + baidu: "百度热搜" + cls-depth: "财联社" home_assistant: devices: - 客厅,玩具灯,switch.cuco_cn_460494544_cp1_on_p_2_1 @@ -765,4 +770,4 @@ TTS: # 支持声音克隆,可自行上传音频,填入voice参数,voice参数为空时,使用默认声音 access_token: "U4YdYXVfpwWnk2t5Gp822zWPCuORyeJL" voice: "OUeAo1mhq6IBExi" - output_dir: tmp/ \ No newline at end of file + output_dir: tmp/ 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 1b98539d..6fcb7ba6 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 @@ -8,38 +8,61 @@ from markitdown import MarkItDown TAG = __name__ logger = setup_logging() -# 新闻来源字典,包含名称和对应的API ID -NEWS_SOURCES = { +# 默认新闻来源字典,当配置中没有指定时使用 +DEFAULT_NEWS_SOURCES = { "thepaper": "澎湃新闻", "baidu": "百度热搜", "cls-depth": "财联社", } -# 动态生成新闻源描述 -def generate_news_sources_description(): - sources_desc = [] - for source_id, source_name in NEWS_SOURCES.items(): - sources_desc.append(f"{source_name}({source_id})") - return "、".join(sources_desc) +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")): + + # 如果配置中是字符串,尝试解析JSON + news_sources_config = conn.config["plugins"]["get_news_from_newsnow"]["news_sources"] + if isinstance(news_sources_config, str): + try: + return json.loads(news_sources_config) + except json.JSONDecodeError: + logger.bind(tag=TAG).warning("新闻源配置JSON格式错误,使用默认配置") + return DEFAULT_NEWS_SOURCES + elif isinstance(news_sources_config, dict): + return news_sources_config + else: + logger.bind(tag=TAG).warning("新闻源配置格式错误,使用默认配置") + return DEFAULT_NEWS_SOURCES + else: + logger.bind(tag=TAG).debug("未找到新闻源配置,使用默认配置") + return DEFAULT_NEWS_SOURCES + except Exception as e: + logger.bind(tag=TAG).error(f"获取新闻源配置失败: {e},使用默认配置") + return DEFAULT_NEWS_SOURCES +# 静态函数描述,使用默认新闻源生成描述 GET_NEWS_FROM_NEWSNOW_FUNCTION_DESC = { "type": "function", "function": { "name": "get_news_from_newsnow", "description": ( "获取最新新闻,随机选择一条新闻进行播报。" - f"用户可以选择不同的新闻源,如{generate_news_sources_description()}等。" + "用户可以选择不同的新闻源,如澎湃新闻(thepaper)、百度热搜(baidu)、财联社(cls-depth)等。" "如果没有指定,默认从澎湃新闻获取。" "用户可以要求获取详细内容,此时会获取新闻的详细内容。" + "注意:实际可用的新闻源取决于系统配置。" ), "parameters": { "type": "object", "properties": { "source": { "type": "string", - "description": f"新闻源,例如{generate_news_sources_description()}等。可选参数,如果不提供则使用默认新闻源", + "description": "新闻源,例如thepaper、baidu、cls-depth等。可选参数,如果不提供则使用默认新闻源", }, "detail": { "type": "boolean", @@ -115,6 +138,9 @@ def get_news_from_newsnow( ): """获取新闻并随机选择一条进行播报,或获取上一条新闻的详细内容""" try: + # 获取当前配置的新闻源 + news_sources = get_news_sources_from_config(conn) + # 如果detail为True,获取上一条新闻的详细内容 detail = str(detail).lower() == "true" if detail: @@ -132,7 +158,7 @@ def get_news_from_newsnow( url = conn.last_newsnow_link.get("url") title = conn.last_newsnow_link.get("title", "未知标题") source_id = conn.last_newsnow_link.get("source_id", "thepaper") - source_name = NEWS_SOURCES.get(source_id, "未知来源") + source_name = news_sources.get(source_id, "未知来源") if not url or url == "#": return ActionResponse( @@ -167,11 +193,11 @@ def get_news_from_newsnow( # 否则,获取新闻列表并随机选择一条 # 验证新闻源是否有效,如果无效则使用默认源 - if source not in NEWS_SOURCES: + if source not in news_sources: logger.bind(tag=TAG).warning(f"无效的新闻源: {source},使用默认源thepaper") source = "thepaper" - source_name = NEWS_SOURCES.get(source, "澎湃新闻") + source_name = news_sources.get(source, "澎湃新闻") logger.bind(tag=TAG).info(f"获取新闻: 新闻源={source}({source_name})") # 获取新闻列表 From 78dc266eeecdbdf85918700c7fb3fb6b2e9490af Mon Sep 17 00:00:00 2001 From: Tink Date: Wed, 25 Jun 2025 16:49:54 +0800 Subject: [PATCH 02/12] change newsnow plugin doc --- docs/newsnow_plugin_config.md | 37 +++++++---------------------------- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/docs/newsnow_plugin_config.md b/docs/newsnow_plugin_config.md index 3aff257d..88744423 100644 --- a/docs/newsnow_plugin_config.md +++ b/docs/newsnow_plugin_config.md @@ -28,8 +28,9 @@ plugins: baidu: "百度热搜" cls-depth: "财联社" # 可以添加更多新闻源 - sina: "新浪新闻" - sohu: "搜狐新闻" + weibo: "微博头条" + douyin: "抖音热搜" + solidot: "奇客Solidot" ``` ## 新闻源配置格式 @@ -50,8 +51,9 @@ plugins: "thepaper": "澎湃新闻", "baidu": "百度热搜", "cls-depth": "财联社", - "sina": "新浪新闻", - "sohu": "搜狐新闻" + "weibo": "微博头条", + "douyin": "抖音热搜", + "solidot": "奇客Solidot" } ``` @@ -79,29 +81,4 @@ plugins: 1. 新闻源的 `source_id` 必须与API接口支持的ID一致 2. 配置更改后需要重启服务或重新加载配置 3. 如果配置的新闻源无效,插件会自动使用默认新闻源 -4. JSON格式必须正确,否则会使用默认配置 - -## 故障排除 - -### 问题:配置的新闻源不生效 - -**解决方案**: -1. 检查JSON格式是否正确 -2. 确认新闻源ID是否有效 -3. 查看日志文件中的错误信息 -4. 重启服务 - -### 问题:无法获取新闻 - -**解决方案**: -1. 检查网络连接 -2. 确认API接口地址是否正确 -3. 查看API接口是否可用 -4. 检查日志文件中的错误信息 - -## 技术实现 - -- 插件会从 `conn.config["plugins"]["get_news_from_newsnow"]["news_sources"]` 读取配置 -- 支持字符串格式的JSON和字典格式的配置 -- 配置验证和错误处理机制 -- 向后兼容,未配置时使用默认值 \ No newline at end of file +4. JSON格式必须正确,否则会使用默认配置 \ No newline at end of file From 6ec7a1fe09ce6efcd6cfa48cd2f9a46766aa0384 Mon Sep 17 00:00:00 2001 From: Tink Date: Thu, 26 Jun 2025 11:09:17 +0800 Subject: [PATCH 03/12] manual-add-device --- main/manager-web/src/apis/api.js | 2 +- main/manager-web/src/apis/module/device.js | 5 + .../src/components/ManualAddDeviceDialog.vue | 158 ++++++++++++++++++ .../src/views/DeviceManagement.vue | 18 +- 4 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 main/manager-web/src/components/ManualAddDeviceDialog.vue diff --git a/main/manager-web/src/apis/api.js b/main/manager-web/src/apis/api.js index 0a3e8d18..4d1d7d7d 100755 --- a/main/manager-web/src/apis/api.js +++ b/main/manager-web/src/apis/api.js @@ -7,6 +7,7 @@ import model from './module/model.js' import ota from './module/ota.js' import timbre from "./module/timbre.js" import user from './module/user.js' + /** * 接口地址 * 开发时自动读取使用.env.development文件 @@ -22,7 +23,6 @@ export function getServiceUrl() { return DEV_API_SERVICE } - /** request服务封装 */ export default { getServiceUrl, diff --git a/main/manager-web/src/apis/module/device.js b/main/manager-web/src/apis/module/device.js index e6d61353..87f0c7b1 100644 --- a/main/manager-web/src/apis/module/device.js +++ b/main/manager-web/src/apis/module/device.js @@ -1,5 +1,6 @@ import { getServiceUrl } from '../api'; import RequestService from '../httpRequest'; +import request from '../request' export default { // 已绑设备 @@ -68,4 +69,8 @@ export default { }) }).send() }, + // 手动添加设备 + manualAddDevice: (params, callback) => { + return request.post('/device/manual-add', params, callback); + }, } \ No newline at end of file diff --git a/main/manager-web/src/components/ManualAddDeviceDialog.vue b/main/manager-web/src/components/ManualAddDeviceDialog.vue new file mode 100644 index 00000000..b6060ff5 --- /dev/null +++ b/main/manager-web/src/components/ManualAddDeviceDialog.vue @@ -0,0 +1,158 @@ + + + + + \ No newline at end of file diff --git a/main/manager-web/src/views/DeviceManagement.vue b/main/manager-web/src/views/DeviceManagement.vue index 25cd5a68..35238371 100644 --- a/main/manager-web/src/views/DeviceManagement.vue +++ b/main/manager-web/src/views/DeviceManagement.vue @@ -77,7 +77,10 @@ {{ isAllSelected ? '取消全选' : '全选' }} - 新增 + 验证码绑定 + + + 手动添加 解绑 @@ -103,6 +106,8 @@ + @@ -110,13 +115,19 @@