From fbb02b544c1297a9d2f28396f4417452ae7ebd69 Mon Sep 17 00:00:00 2001 From: lrhh123 Date: Mon, 1 Jul 2024 23:33:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E7=9A=84=20BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/backend/constants/index.ts | 22 ++++--- src/main/backend/entities/config.ts | 4 +- src/main/backend/services/dispatchService.ts | 11 ++-- src/main/backend/services/messageService.ts | 51 +++++++++------ src/main/backend/services/pluginService.ts | 18 ++---- src/main/backend/types/index.ts | 2 +- .../common/services/platform/platform.d.ts | 2 +- src/renderer/common/utils/constants/index.ts | 29 ++++++--- .../common/utils/plugins/system/normal.ts | 2 +- .../common/utils/plugins/system/qianniu.ts | 52 --------------- .../common/utils/plugins/system/wechat.ts | 63 ------------------- .../components/Settings/GeneralSettings.tsx | 2 +- 12 files changed, 83 insertions(+), 175 deletions(-) delete mode 100644 src/renderer/common/utils/plugins/system/qianniu.ts delete mode 100644 src/renderer/common/utils/plugins/system/wechat.ts diff --git a/src/main/backend/constants/index.ts b/src/main/backend/constants/index.ts index 81c44af..6ae0d40 100644 --- a/src/main/backend/constants/index.ts +++ b/src/main/backend/constants/index.ts @@ -1,12 +1,12 @@ // 固定会传递的上下文参数 -export const CTX_APP_NAME = 'app_name'; -export const CTX_APP_ID = 'app_id'; -export const CTX_INSTANCE_ID = 'instance_id'; +export const CTX_APP_NAME = 'CTX_APP_NAME'; +export const CTX_APP_ID = 'CTX_APP_ID'; +export const CTX_INSTANCE_ID = 'CTX_INSTANCE_ID'; -export const CTX_USERNAME = 'username'; // 当前操作的用户名 -export const CTX_PLATFORM = 'platform'; // 当前所在平台 -export const CTX_HAS_NEW_MESSAGE = 'has_new_message'; // 是否有新消息 -export const CTX_HAS_GROUP_MESSAGE = 'has_group_message'; // 是否有群消息 +export const CTX_USERNAME = 'CTX_USERNAME'; // 当前操作的用户名 +export const CTX_PLATFORM = 'CTX_PLATFORM'; // 当前所在平台 +export const CTX_HAS_NEW_MESSAGE = 'CTX_HAS_NEW_MESSAGE'; // 是否有新消息 +export const CTX_HAS_GROUP_MESSAGE = 'CTX_HAS_GROUP_MESSAGE'; // 是否有群消息 // 电商平台 export const CTX_CURRENT_GOODS = 'CTX_CURRENT_GOODS'; // 当前商品 @@ -15,6 +15,12 @@ export const CTX_MEMBER_TAG = 'CTX_MEMBER_TAG'; // 会员标签 export const CTX_FAN_TAG = 'CTX_FAN_TAG'; // 粉丝标签 export const CTX_NEW_CUSTOMER_TAG = 'CTX_NEW_CUSTOMER_TAG'; // 新客标签 +export const CTX_ORDER_STATUS = 'CTX_ORDER_STATUS'; // 订单状态 +export const CTX_ORDER_ID = 'CTX_ORDER_ID'; // 订单 ID +export const CTX_ORDER_AMOUNT = 'CTX_ORDER_AMOUNT'; // PDD 平台特有 [订单金额] +export const CTX_GOODS_SPEC = 'CTX_GOODS_SPEC'; // PDD 平台特有 [商品规格] +export const CTX_LOGISTICS_STATUS = 'CTX_LOGISTICS_STATUS'; // 物流状态 + export const PluginDefaultRunCode = ` const cc = require('config_srv'); const rp = require('reply_srv'); @@ -27,5 +33,5 @@ const rp = require('reply_srv'); */ async function main(ctx, messages) { const cfg = await cc.get(ctx); - return await rp.getDefaultReply(cfg, ctx, messages); + return await rp.getReply(cfg, ctx, messages); }`; diff --git a/src/main/backend/entities/config.ts b/src/main/backend/entities/config.ts index 46049af..80910cf 100644 --- a/src/main/backend/entities/config.ts +++ b/src/main/backend/entities/config.ts @@ -86,7 +86,7 @@ export async function checkAndAddFields(sequelize: Sequelize) { .addColumn('n_config', 'truncate_word_count', { type: DataTypes.INTEGER, allowNull: true, - defaultValue: 210, + defaultValue: 4000, }); } @@ -260,7 +260,7 @@ export function initConfig(sequelize: Sequelize) { truncate_word_count: { type: DataTypes.INTEGER, allowNull: true, - defaultValue: 210, + defaultValue: 4000, }, truncate_word_key: { type: DataTypes.STRING, diff --git a/src/main/backend/services/dispatchService.ts b/src/main/backend/services/dispatchService.ts index 2192f6a..1d0ce05 100644 --- a/src/main/backend/services/dispatchService.ts +++ b/src/main/backend/services/dispatchService.ts @@ -97,16 +97,15 @@ export class DispatchService { },使用默认回复`, ); - reply = { - content: cfg.default_reply || 'Failed to execute plugin', - type: 'TEXT', - }; + reply = await this.messageService.getDefaultReply(cfg); } callback(reply); - // 回复后保存消息 - await this.messageController.saveMessages(ctxMap, reply, msgs); + if (reply.type !== 'NO_REPLY') { + // 回复后保存消息 + await this.messageController.saveMessages(ctxMap, reply, msgs); + } }); } diff --git a/src/main/backend/services/messageService.ts b/src/main/backend/services/messageService.ts index 6db8af7..c510a80 100644 --- a/src/main/backend/services/messageService.ts +++ b/src/main/backend/services/messageService.ts @@ -66,11 +66,33 @@ export class MessageService { * @param messages * @returns */ - public async getDefaultReply( + public async getDefaultReply(cfg: Config): Promise { + let reply = { + type: 'TEXT' as MessageType, + content: cfg.default_reply || '当前消息有点多,我稍后再回复你', + }; + + const replyContent = await this.choseRandomReply(reply.content); + reply = { + type: reply.type as MessageType, + content: replyContent, + }; + + return reply; + } + + /** + * 获取回复 + * @param cfg + * @param ctx + * @param messages + * @returns + */ + public async getReply( cfg: Config, ctx: Context, messages: MessageDTO[], - ): Promise<{ type: string; content: string }> { + ): Promise { // 先检查是否存在用户的消息 const lastUserMsg = messages .slice() @@ -78,15 +100,9 @@ export class MessageService { .find((msg) => msg.role === 'OTHER'); let hasDefaultReply = true; + let reply = null; - let reply = { - type: 'TEXT', - content: cfg.default_reply || '当前消息有点多,我稍后再回复你', - }; - - if (!lastUserMsg) { - this.log.warn(`未匹配到用户消息,所以使用默认回复: ${reply.content}`); - } else { + if (lastUserMsg) { if (cfg.has_transfer) { // 检查是否需要转接 const isTransfer = await this.matchTransferKeyword(ctx, lastUserMsg); @@ -94,8 +110,8 @@ export class MessageService { this.log.info('需要转接'); hasDefaultReply = false; return { - type: 'TRANSFER', - content: '', + type: 'TRANSFER' as MessageType, + content: '无', }; } } @@ -143,20 +159,17 @@ export class MessageService { } if (hasDefaultReply) { - const replyContent = await this.choseRandomReply(reply.content); - reply = { - type: reply.type as MessageType, - content: replyContent, - }; + reply = await this.getDefaultReply(cfg); + this.log.warn(`未匹配到用户消息,所以使用默认回复: ${reply.content}`); } if (cfg.has_replace) { - if (reply.type === 'TEXT') { + if (reply && reply.type === 'TEXT') { reply.content = await this.matchReplaceKeyword(ctx, reply.content); } } - return reply; + return reply as ReplyDTO; } public async createTextReply(content: string) { diff --git a/src/main/backend/services/pluginService.ts b/src/main/backend/services/pluginService.ts index 50e66b4..4b8cb72 100644 --- a/src/main/backend/services/pluginService.ts +++ b/src/main/backend/services/pluginService.ts @@ -95,18 +95,12 @@ export class PluginService { throw new Error('Plugin not found'); } - const cfg = await this.configController.get(ctx); - try { const { data } = await this.executePluginCode(plugin.code, ctx, messages); return { ...data }; } catch (error) { - console.error('Plugin execution error:', error); - return { - type: 'TEXT', - content: - cfg.default_reply || 'An error occurred while executing the plugin', - }; + this.log.error(`插件执行失败: ${error}`); + throw error; } } @@ -211,15 +205,15 @@ export class PluginService { return { data: data as ReplyDTO, consoleOutput }; } - this.log.error('未返回有效响应'); - - throw new Error('Plugin function did not return a valid response'); + this.log.error(`未返回有效响应,插件返回数据: ${JSON.stringify(data)}`); + throw new Error('Plugin function did not return a valid response', data); } catch (error: any) { console.error('Plugin execution error:', error); - + this.log.error(`运行插件的日志信息: ${JSON.stringify(consoleOutput)}`); this.log.error( `回复失败: ${error instanceof Error ? error.message : String(error)}`, ); + error.consoleOutput = consoleOutput; throw error; } diff --git a/src/main/backend/types/index.ts b/src/main/backend/types/index.ts index c86b204..16050f0 100644 --- a/src/main/backend/types/index.ts +++ b/src/main/backend/types/index.ts @@ -13,7 +13,7 @@ export enum PlatformTypeEnum { } export type RoleType = 'SELF' | 'OTHER' | 'SYSTEM'; -export type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE'; +export type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE' | 'NO_REPLY'; export type Context = Map; diff --git a/src/renderer/common/services/platform/platform.d.ts b/src/renderer/common/services/platform/platform.d.ts index 253cfe1..c9cdf1a 100644 --- a/src/renderer/common/services/platform/platform.d.ts +++ b/src/renderer/common/services/platform/platform.d.ts @@ -24,7 +24,7 @@ export interface PlatformSettings { } export type RoleType = 'SELF' | 'OTHER' | 'SYSTEM'; -export type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE'; +export type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE' | 'NO_REPLY'; export interface Reply { content: string; diff --git a/src/renderer/common/utils/constants/index.ts b/src/renderer/common/utils/constants/index.ts index d52b8c9..5e89a9b 100644 --- a/src/renderer/common/utils/constants/index.ts +++ b/src/renderer/common/utils/constants/index.ts @@ -16,7 +16,7 @@ export const PluginExtraLib = ` type RoleType = 'SELF' | 'OTHER' | 'SYSTEM'; - type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE'; + type MessageType = 'TEXT' | 'IMAGE' | 'VIDEO' | 'FILE' | 'NO_REPLY'; type Message = { sender: string; // 发送者 @@ -42,7 +42,7 @@ const rp = require('reply_srv'); */ async function main(ctx, messages) { const cfg = await cc.get(ctx); - return await rp.getDefaultReply(cfg, ctx, messages); + return await rp.getReply(cfg, ctx, messages); }`; export const LLMTypeList = [ @@ -168,14 +168,14 @@ export const ModelList = [ ]; // 固定会传递的上下文参数 -export const CTX_APP_NAME = 'app_name'; -export const CTX_APP_ID = 'app_id'; -export const CTX_INSTANCE_ID = 'instance_id'; +export const CTX_APP_NAME = 'CTX_APP_NAME'; +export const CTX_APP_ID = 'CTX_APP_ID'; +export const CTX_INSTANCE_ID = 'CTX_INSTANCE_ID'; -export const CTX_USERNAME = 'username'; // 当前操作的用户名 -export const CTX_PLATFORM = 'platform'; // 当前所在平台 -export const CTX_HAS_NEW_MESSAGE = 'has_new_message'; // 是否有新消息 -export const CTX_HAS_GROUP_MESSAGE = 'has_group_message'; // 是否有群消息 +export const CTX_USERNAME = 'CTX_USERNAME'; // 当前操作的用户名 +export const CTX_PLATFORM = 'CTX_PLATFORM'; // 当前所在平台 +export const CTX_HAS_NEW_MESSAGE = 'CTX_HAS_NEW_MESSAGE'; // 是否有新消息 +export const CTX_HAS_GROUP_MESSAGE = 'CTX_HAS_GROUP_MESSAGE'; // 是否有群消息 // 电商平台 export const CTX_CURRENT_GOODS = 'CTX_CURRENT_GOODS'; // 当前商品 @@ -184,6 +184,12 @@ export const CTX_MEMBER_TAG = 'CTX_MEMBER_TAG'; // 会员标签 export const CTX_FAN_TAG = 'CTX_FAN_TAG'; // 粉丝标签 export const CTX_NEW_CUSTOMER_TAG = 'CTX_NEW_CUSTOMER_TAG'; // 新客标签 +export const CTX_ORDER_STATUS = 'CTX_ORDER_STATUS'; // 订单状态 +export const CTX_ORDER_ID = 'CTX_ORDER_ID'; // 订单 ID +export const CTX_ORDER_AMOUNT = 'CTX_ORDER_AMOUNT'; // PDD 平台特有 [订单金额] +export const CTX_GOODS_SPEC = 'CTX_GOODS_SPEC'; // PDD 平台特有 [商品规格] +export const CTX_LOGISTICS_STATUS = 'CTX_LOGISTICS_STATUS'; // 物流状态 + export const ContextKeys = [ CTX_APP_NAME, CTX_APP_ID, @@ -197,6 +203,11 @@ export const ContextKeys = [ CTX_MEMBER_TAG, CTX_FAN_TAG, CTX_NEW_CUSTOMER_TAG, + CTX_ORDER_STATUS, + CTX_ORDER_ID, + CTX_ORDER_AMOUNT, + CTX_GOODS_SPEC, + CTX_LOGISTICS_STATUS, ]; export const MockCtx = new Map([ diff --git a/src/renderer/common/utils/plugins/system/normal.ts b/src/renderer/common/utils/plugins/system/normal.ts index 15bc2ce..83f4cfe 100644 --- a/src/renderer/common/utils/plugins/system/normal.ts +++ b/src/renderer/common/utils/plugins/system/normal.ts @@ -9,5 +9,5 @@ const rp = require('reply_srv'); */ async function main(ctx, messages) { const cfg = await cc.get(ctx); - return await rp.getDefaultReply(cfg, ctx, messages); + return await rp.getReply(cfg, ctx, messages); }`; diff --git a/src/renderer/common/utils/plugins/system/qianniu.ts b/src/renderer/common/utils/plugins/system/qianniu.ts deleted file mode 100644 index 957d1f2..0000000 --- a/src/renderer/common/utils/plugins/system/qianniu.ts +++ /dev/null @@ -1,52 +0,0 @@ -export const QIANNIU_GOODS_PLUGIN = `const cc = require('config_srv'); -const rp = require('reply_srv'); - -/** - * 插件主函数 - * @param {AppContext} ctx - 上下文信息 - * @param {Message[]} messages - 消息数组 - * @returns {Reply} 插件执行结果 - */ -async function main(ctx, messages) { - const appId = ctx.get('app_id'); - const cfg = cc.get(ctx); - - if (appId === 'win_qianniu') { - // 取得用户最后一条消息 - const lastMessage = messages[messages.length - 1]; - - // 可以取得它的消息内容 - const goodsId = ctx.get('CTX_CURRENT_GOODS_ID'); - const goodsName = ctx.get('CTX_CURRENT_GOODS'); - - // 构建一个消息 - const msg = { - sender: 'SYSTEM', - role: 'OTHER', - content: \`1. 当前客户询问的商品 ID 是: -""" -\${goodsId} -""" - -2. 咨询的商品名称是: -""" -\${goodsName} -""" - -3. 当前客户的问题是: -""" -\${lastMessage.content} -""" -\`, - type: 'TEXT', - }; - - // 替换用户的这条消息 - messages = [msg]; - const reply = await rp.getDefaultReply(cfg, ctx, messages); - return reply; - } - const reply = await rp.getDefaultReply(cfg, ctx, messages); - return reply; -} -`; diff --git a/src/renderer/common/utils/plugins/system/wechat.ts b/src/renderer/common/utils/plugins/system/wechat.ts deleted file mode 100644 index dd896bf..0000000 --- a/src/renderer/common/utils/plugins/system/wechat.ts +++ /dev/null @@ -1,63 +0,0 @@ -export const WECHAT_NEWS_PLUGIN = `const cc = require('config_srv'); -const rp = require('reply_srv'); -const axios = require('axios'); - -/** - * 插件主函数 - * @param {AppContext} ctx - 上下文信息 - * @param {Message[]} messages - 消息数组 - * @returns {Reply} 插件执行结果 - */ -async function main(ctx, messages) { - const appId = ctx.get('app_id'); - const cfg = cc.get(ctx); - - if (appId === 'win_wechat') { - // 取得用户最后一条消息 - const lastMessage = messages[messages.length - 1]; - - // 可以取得它的消息内容 - const hasGroup = ctx.get('CTX_HAS_GROUP_MESSAGE'); - - // 检查当前消息是否携带 @BOT 指令 - const hasBotCommand = lastMessage.content.includes('@BOT'); - - // 如果还携带了 [热榜] 关键词 - const hasNewsKeyword = lastMessage.content.includes('[热榜]'); - - if (hasGroup && hasBotCommand && hasNewsKeyword) { - try { - // 使用 axios 请求新闻数据 - const response = await axios.get('https://api.vvhan.com/api/hotlist/all'); - const newsData = response.data; - - if (newsData.success) { - const newsList = newsData.data; - let replyContent = \`\${new Date().toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' })}\\n\\n\`; - - // 遍历每个平台的新闻 - newsList.forEach(platform => { - replyContent += \`\${platform.name} \${platform.subtitle} 更新于 \${platform.update_time}\\n\`; - platform.data.slice(0, 3).forEach((news, index) => { - replyContent += \`\${index + 1}. \${news.title} 热度: \${news.hot}\\n\`; - }); - replyContent += '\\n'; - }); - - // 发送回复 - return rp.createTextReply(replyContent); - } else { - return rp.createTextReply('无法获取新闻数据,请稍后再试。'); - } - } catch (error) { - console.error('获取新闻数据出错:', error); - return rp.createTextReply('获取新闻数据时出错,请稍后再试。'); - } - } - } - - // 默认回复 - const reply = await rp.getDefaultReply(cfg, ctx, messages); - return reply; -} -`; diff --git a/src/renderer/settings-window/components/Settings/GeneralSettings.tsx b/src/renderer/settings-window/components/Settings/GeneralSettings.tsx index 7a9096d..7b7547c 100644 --- a/src/renderer/settings-window/components/Settings/GeneralSettings.tsx +++ b/src/renderer/settings-window/components/Settings/GeneralSettings.tsx @@ -308,7 +308,7 @@ const GeneralSettings = ({