diff --git a/docs/newsnow_plugin_config.md b/docs/newsnow_plugin_config.md new file mode 100644 index 00000000..8be887c2 --- /dev/null +++ b/docs/newsnow_plugin_config.md @@ -0,0 +1,105 @@ +# get_news_from_newsnow 插件新闻源配置指南 + +## 概述 + +`get_news_from_newsnow` 插件现在支持通过Web管理界面动态配置新闻源,不再需要修改代码。用户可以在智控台中为每个智能体配置不同的新闻源。 + +## 配置方式 + +### 1. 通过Web管理界面配置(推荐) + +1. 登录智控台 +2. 进入"角色配置"页面 +3. 选择要配置的智能体 +4. 点击"编辑功能"按钮 +5. 在右侧参数配置区域找到"newsnow新闻聚合"插件 +6. 在"新闻源配置"字段中输入分号分隔的中文名称 + +### 2. 配置文件方式 + +在 `config.yaml` 中配置: + +```yaml +plugins: + get_news_from_newsnow: + url: "https://newsnow.busiyi.world/api/s?id=" + news_sources: "澎湃新闻;百度热搜;财联社;微博;抖音" +``` + +## 新闻源配置格式 + +新闻源配置使用分号分隔的中文名称,格式为: + +``` +中文名称1;中文名称2;中文名称3 +``` + +### 配置示例 + +``` +澎湃新闻;百度热搜;财联社;微博;抖音;知乎;36氪 +``` + +## 支持的新闻源 + +插件支持以下新闻源的中文名称: + +- 澎湃新闻 +- 百度热搜 +- 财联社 +- 微博 +- 抖音 +- 知乎 +- 36氪 +- 华尔街见闻 +- IT之家 +- 今日头条 +- 虎扑 +- 哔哩哔哩 +- 快手 +- 雪球 +- 格隆汇 +- 法布财经 +- 金十数据 +- 牛客 +- 少数派 +- 稀土掘金 +- 凤凰网 +- 虫部落 +- 联合早报 +- 酷安 +- 远景论坛 +- 参考消息 +- 卫星通讯社 +- 百度贴吧 +- 靠谱新闻 +- 以及更多... + +## 默认配置 + +如果未配置新闻源,插件将使用以下默认配置: + +``` +澎湃新闻;百度热搜;财联社 +``` + +## 使用说明 + +1. **配置新闻源**:在Web界面或配置文件中设置新闻源的中文名称,用分号分隔 +2. **调用插件**:用户可以说"播报新闻"或"获取新闻" +3. **指定新闻源**:用户可以说"播报澎湃新闻"或"获取百度热搜" +4. **获取详情**:用户可以说"详细介绍这条新闻" + +## 工作原理 + +1. 插件接受中文名称作为参数(如"澎湃新闻") +2. 根据配置的新闻源列表,将中文名称转换为对应的英文ID(如"thepaper") +3. 使用英文ID调用API获取新闻数据 +4. 返回新闻内容给用户 + +## 注意事项 + +1. 配置的中文名称必须与 CHANNEL_MAP 中定义的名称完全一致 +2. 配置更改后需要重启服务或重新加载配置 +3. 如果配置的新闻源无效,插件会自动使用默认新闻源 +4. 多个新闻源之间使用英文分号(;)分隔,不要使用中文分号(;) \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java index 087c1b9d..36b59993 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/biz/impl/AgentChatHistoryBizServiceImpl.java @@ -19,6 +19,8 @@ import xiaozhi.modules.agent.service.AgentChatAudioService; import xiaozhi.modules.agent.service.AgentChatHistoryService; import xiaozhi.modules.agent.service.AgentService; import xiaozhi.modules.agent.service.biz.AgentChatHistoryBizService; +import xiaozhi.modules.device.entity.DeviceEntity; +import xiaozhi.modules.device.service.DeviceService; /** * {@link AgentChatHistoryBizService} impl @@ -35,6 +37,7 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic private final AgentChatHistoryService agentChatHistoryService; private final AgentChatAudioService agentChatAudioService; private final RedisUtils redisUtils; + private final DeviceService deviceService; /** * 处理聊天记录上报,包括文件上传和相关信息记录 @@ -68,6 +71,15 @@ public class AgentChatHistoryBizServiceImpl implements AgentChatHistoryBizServic // 更新设备最后对话时间 redisUtils.set(RedisKeys.getAgentDeviceLastConnectedAtById(agentId), new Date()); + + // 更新设备最后连接时间 + DeviceEntity device = deviceService.getDeviceByMacAddress(macAddress); + if (device != null) { + deviceService.updateDeviceConnectionInfo(agentId, device.getId(), null); + } else { + log.warn("聊天记录上报时,未找到mac地址为 {} 的设备", macAddress); + } + return Boolean.TRUE; } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java index 34192dd8..294dbbe2 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java @@ -72,6 +72,8 @@ public class ConfigServiceImpl implements ConfigService { null, null, null, + null, + null, agent.getVadModelId(), agent.getAsrModelId(), null, @@ -108,9 +110,13 @@ public class ConfigServiceImpl implements ConfigService { } // 获取音色信息 String voice = null; + String referenceAudio = null; + String referenceText = null; TimbreDetailsVO timbre = timbreService.get(agent.getTtsVoiceId()); if (timbre != null) { voice = timbre.getTtsVoice(); + referenceAudio = timbre.getReferenceAudio(); + referenceText = timbre.getReferenceText(); } // 构建返回数据 Map result = new HashMap<>(); @@ -163,6 +169,8 @@ public class ConfigServiceImpl implements ConfigService { agent.getSystemPrompt(), agent.getSummaryMemory(), voice, + referenceAudio, + referenceText, agent.getVadModelId(), agent.getAsrModelId(), agent.getLlmModelId(), @@ -179,7 +187,7 @@ public class ConfigServiceImpl implements ConfigService { /** * 构建配置信息 * - * @param paramsList 系统参数列表 + * @param config 系统参数列表 * @return 配置信息 */ private Object buildConfig(Map config) { @@ -250,21 +258,25 @@ public class ConfigServiceImpl implements ConfigService { /** * 构建模块配置 * - * @param prompt 提示词 - * @param voice 音色 - * @param vadModelId VAD模型ID - * @param asrModelId ASR模型ID - * @param llmModelId LLM模型ID - * @param ttsModelId TTS模型ID - * @param memModelId 记忆模型ID - * @param intentModelId 意图模型ID - * @param result 结果Map + * @param prompt 提示词 + * @param voice 音色 + * @param referenceAudio 参考音频路径 + * @param referenceText 参考文本 + * @param vadModelId VAD模型ID + * @param asrModelId ASR模型ID + * @param llmModelId LLM模型ID + * @param ttsModelId TTS模型ID + * @param memModelId 记忆模型ID + * @param intentModelId 意图模型ID + * @param result 结果Map */ private void buildModuleConfig( String assistantName, String prompt, String summaryMemory, String voice, + String referenceAudio, + String referenceText, String vadModelId, String asrModelId, String llmModelId, @@ -290,8 +302,10 @@ public class ConfigServiceImpl implements ConfigService { if (model.getConfigJson() != null) { typeConfig.put(model.getId(), model.getConfigJson()); // 如果是TTS类型,添加private_voice属性 - if ("TTS".equals(modelTypes[i]) && voice != null) { - ((Map) model.getConfigJson()).put("private_voice", voice); + if ("TTS".equals(modelTypes[i])){ + if (voice != null) ((Map) model.getConfigJson()).put("private_voice", voice); + if (referenceAudio != null) ((Map) model.getConfigJson()).put("ref_audio", referenceAudio); + if (referenceText != null) ((Map) model.getConfigJson()).put("ref_text", referenceText); } // 如果是Intent类型,且type=intent_llm,则给他添加附加模型 if ("Intent".equals(modelTypes[i])) { diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java index eaf3636f..b0320e3c 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java @@ -25,6 +25,7 @@ import xiaozhi.common.utils.Result; import xiaozhi.modules.device.dto.DeviceRegisterDTO; import xiaozhi.modules.device.dto.DeviceUnBindDTO; import xiaozhi.modules.device.dto.DeviceUpdateDTO; +import xiaozhi.modules.device.dto.DeviceManualAddDTO; import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.service.DeviceService; import xiaozhi.modules.security.user.SecurityUser; @@ -99,4 +100,13 @@ public class DeviceController { deviceService.updateById(entity); return new Result(); } + + @PostMapping("/manual-add") + @Operation(summary = "手动添加设备") + @RequiresPermissions("sys:role:normal") + public Result manualAddDevice(@RequestBody @Valid DeviceManualAddDTO dto) { + UserDetail user = SecurityUser.getUser(); + deviceService.manualAddDevice(user.getId(), dto); + return new Result<>(); + } } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/dto/DeviceManualAddDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/device/dto/DeviceManualAddDTO.java new file mode 100644 index 00000000..369726b0 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/dto/DeviceManualAddDTO.java @@ -0,0 +1,11 @@ +package xiaozhi.modules.device.dto; + +import lombok.Data; + +@Data +public class DeviceManualAddDTO { + private String agentId; + private String board; // 设备型号 + private String appVersion; // 固件版本 + private String macAddress; // Mac地址 +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java index fb91ff89..3392c96f 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java @@ -8,6 +8,7 @@ import xiaozhi.common.service.BaseService; import xiaozhi.modules.device.dto.DevicePageUserDTO; import xiaozhi.modules.device.dto.DeviceReportReqDTO; import xiaozhi.modules.device.dto.DeviceReportRespDTO; +import xiaozhi.modules.device.dto.DeviceManualAddDTO; import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.vo.UserShowDeviceListVO; @@ -87,5 +88,14 @@ public interface DeviceService extends BaseService { */ Date getLatestLastConnectionTime(String agentId); + /** + * 手动添加设备 + */ + void manualAddDevice(Long userId, DeviceManualAddDTO dto); + + /** + * 更新设备连接信息 + */ + void updateDeviceConnectionInfo(String agentId, String deviceId, String appVersion); } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java index ee31c41f..3cff111d 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java @@ -44,6 +44,7 @@ import xiaozhi.modules.device.vo.UserShowDeviceListVO; import xiaozhi.modules.security.user.SecurityUser; import xiaozhi.modules.sys.service.SysParamsService; import xiaozhi.modules.sys.service.SysUserUtilService; +import xiaozhi.modules.device.dto.DeviceManualAddDTO; @Slf4j @Service @@ -410,4 +411,30 @@ public class DeviceServiceImpl extends BaseServiceImpl } return 0; } + + @Override + public void manualAddDevice(Long userId, DeviceManualAddDTO dto) { + // 检查mac是否已存在 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("mac_address", dto.getMacAddress()); + DeviceEntity exist = baseDao.selectOne(wrapper); + if (exist != null) { + throw new RenException("该Mac地址已存在"); + } + Date now = new Date(); + DeviceEntity entity = new DeviceEntity(); + entity.setId(dto.getMacAddress()); + entity.setUserId(userId); + entity.setAgentId(dto.getAgentId()); + entity.setBoard(dto.getBoard()); + entity.setAppVersion(dto.getAppVersion()); + entity.setMacAddress(dto.getMacAddress()); + entity.setCreateDate(now); + entity.setUpdateDate(now); + entity.setLastConnectedAt(now); + entity.setCreator(userId); + entity.setUpdater(userId); + entity.setAutoUpdate(1); + baseDao.insert(entity); + } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java index 030e2b4a..202c4eaf 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java @@ -26,6 +26,12 @@ public class TimbreDataDTO { @Schema(description = "备注") private String remark; + @Schema(description = "参考音频路径") + private String referenceAudio; + + @Schema(description = "參考文本") + private String referenceText; + @Schema(description = "排序") @Min(value = 0, message = "{sort.number}") private long sort; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java index 3d6e5ba1..508c3f32 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java @@ -34,6 +34,12 @@ public class TimbreEntity { @Schema(description = "备注") private String remark; + @Schema(description = "参考音频路径") + private String referenceAudio; + + @Schema(description = "參考文本") + private String referenceText; + @Schema(description = "排序") private long sort; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java index 3f0ace40..2cae1a53 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java @@ -25,6 +25,12 @@ public class TimbreDetailsVO implements Serializable { @Schema(description = "备注") private String remark; + @Schema(description = "参考音频路径") + private String referenceAudio; + + @Schema(description = "參考文本") + private String referenceText; + @Schema(description = "排序") private long sort; diff --git a/main/manager-api/src/main/resources/db/changelog/202506091720.sql b/main/manager-api/src/main/resources/db/changelog/202506091720.sql new file mode 100644 index 00000000..97b457ee --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202506091720.sql @@ -0,0 +1,3 @@ +ALTER TABLE `ai_tts_voice` +ADD COLUMN `reference_audio` VARCHAR(500) DEFAULT NULL COMMENT '参考音频路径' AFTER `remark`, +ADD COLUMN `reference_text` VARCHAR(500) DEFAULT NULL COMMENT '参考文本' AFTER `reference_audio`; diff --git a/main/manager-api/src/main/resources/db/changelog/202506251620.sql b/main/manager-api/src/main/resources/db/changelog/202506251620.sql new file mode 100644 index 00000000..9af9acd7 --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202506251620.sql @@ -0,0 +1,18 @@ +-- 更新现有的 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', 'string', + 'label', '新闻源配置', + 'default', '澎湃新闻;百度热搜;财联社' + ) +) +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 b60094ef..32ba9f30 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 @@ -205,6 +205,13 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202506080955.sql + - changeSet: + id: 202506091720 + author: shane0411 + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202506091720.sql - changeSet: id: 202506161101 author: hrz @@ -219,6 +226,13 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202506191643.sql + - changeSet: + id: 202506251620 + author: Tink + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202506251620.sql - changeSet: id: 202506261637 author: hrz 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..233c764b 100644 --- a/main/manager-web/src/apis/module/device.js +++ b/main/manager-web/src/apis/module/device.js @@ -68,4 +68,21 @@ export default { }) }).send() }, + // 手动添加设备 + manualAddDevice(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/device/manual-add`) + .method('POST') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('手动添加设备失败:', err); + RequestService.reAjaxFun(() => { + this.manualAddDevice(params, callback); + }); + }).send(); + }, } \ No newline at end of file diff --git a/main/manager-web/src/apis/module/timbre.js b/main/manager-web/src/apis/module/timbre.js index 7aa6a711..3a149b1d 100644 --- a/main/manager-web/src/apis/module/timbre.js +++ b/main/manager-web/src/apis/module/timbre.js @@ -34,6 +34,8 @@ export default { languages: params.languageType, name: params.voiceName, remark: params.remark, + referenceAudio: params.referenceAudio, + referenceText: params.referenceText, sort: params.sort, ttsModelId: params.ttsModelId, ttsVoice: params.voiceCode, @@ -75,6 +77,8 @@ export default { languages: params.languageType, name: params.voiceName, remark: params.remark, + referenceAudio: params.referenceAudio, + referenceText: params.referenceText, ttsModelId: params.ttsModelId, ttsVoice: params.voiceCode, voiceDemo: params.voiceDemo || '' 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/components/TtsModel.vue b/main/manager-web/src/components/TtsModel.vue index 87356523..84d2c883 100644 --- a/main/manager-web/src/components/TtsModel.vue +++ b/main/manager-web/src/components/TtsModel.vue @@ -1,79 +1,66 @@ \ 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 @@