diff --git a/server/service/app/conversation.go b/server/service/app/conversation.go index cd27694..68f8c5f 100644 --- a/server/service/app/conversation.go +++ b/server/service/app/conversation.go @@ -90,11 +90,20 @@ func (s *ConversationService) CreateConversation(userID uint, req *request.Creat // 如果角色有开场白,创建开场白消息 if character.FirstMes != "" { + // 应用输出阶段正则脚本处理开场白 + processedFirstMes := character.FirstMes + var regexService RegexScriptService + outputScripts, err := regexService.GetScriptsForPlacement(userID, 1, &character.ID, nil) + if err == nil && len(outputScripts) > 0 { + processedFirstMes = regexService.ExecuteScripts(outputScripts, processedFirstMes, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("开场白应用正则脚本: 原始长度=%d, 处理后长度=%d", len(character.FirstMes), len(processedFirstMes))) + } + firstMessage := app.Message{ ConversationID: conversation.ID, Role: "assistant", - Content: character.FirstMes, - TokenCount: len(character.FirstMes) / 4, + Content: processedFirstMes, + TokenCount: len(processedFirstMes) / 4, } err = global.GVA_DB.Create(&firstMessage).Error if err != nil { @@ -316,12 +325,27 @@ func (s *ConversationService) SendMessage(userID, conversationID uint, req *requ return nil, errors.New("角色卡不存在") } + // 应用输入阶段的正则脚本 (Placement 0) + processedContent := req.Content + var regexService RegexScriptService + global.GVA_LOG.Info(fmt.Sprintf("查询输入阶段正则脚本: userID=%d, placement=0, charID=%d", userID, conversation.CharacterID)) + inputScripts, err := regexService.GetScriptsForPlacement(userID, 0, &conversation.CharacterID, nil) + if err != nil { + global.GVA_LOG.Error(fmt.Sprintf("查询输入阶段正则脚本失败: %v", err)) + } else { + global.GVA_LOG.Info(fmt.Sprintf("找到 %d 个输入阶段正则脚本", len(inputScripts))) + if len(inputScripts) > 0 { + processedContent = regexService.ExecuteScripts(inputScripts, processedContent, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("应用了 %d 个输入阶段正则脚本,原文: %s, 处理后: %s", len(inputScripts), req.Content, processedContent)) + } + } + // 保存用户消息 userMessage := app.Message{ ConversationID: conversationID, Role: "user", - Content: req.Content, - TokenCount: len(req.Content) / 4, // 简单估算 + Content: processedContent, + TokenCount: len(processedContent) / 4, // 简单估算 } err = global.GVA_DB.Create(&userMessage).Error @@ -372,13 +396,23 @@ func (s *ConversationService) SendMessage(userID, conversationID uint, req *requ return nil, err } + // 应用显示阶段的正则脚本 (Placement 3) + displayContent := assistantMessage.Content + displayScripts, err := regexService.GetScriptsForPlacement(userID, 3, &conversation.CharacterID, nil) + if err == nil && len(displayScripts) > 0 { + displayContent = regexService.ExecuteScripts(displayScripts, displayContent, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("应用了 %d 个显示阶段正则脚本", len(displayScripts))) + } + resp := response.ToMessageResponse(&assistantMessage) + resp.Content = displayContent // 使用处理后的显示内容 return &resp, nil } // callAIService 调用 AI 服务 func (s *ConversationService) callAIService(conversation app.Conversation, character app.AICharacter, messages []app.Message) (string, error) { // 获取 AI 配置 + var aiConfig app.AIConfig var err error @@ -521,6 +555,21 @@ func (s *ConversationService) callAIService(conversation app.Conversation, chara } global.GVA_LOG.Info(fmt.Sprintf("========== AI返回的完整内容 ==========\n%s\n==========================================", aiResponse)) + // 应用输出阶段的正则脚本 (Placement 1) + var regexService RegexScriptService + global.GVA_LOG.Info(fmt.Sprintf("查询输出阶段正则脚本: userID=%d, placement=1, charID=%d", conversation.UserID, conversation.CharacterID)) + outputScripts, err := regexService.GetScriptsForPlacement(conversation.UserID, 1, &conversation.CharacterID, nil) + if err != nil { + global.GVA_LOG.Error(fmt.Sprintf("查询输出阶段正则脚本失败: %v", err)) + } else { + global.GVA_LOG.Info(fmt.Sprintf("找到 %d 个输出阶段正则脚本", len(outputScripts))) + if len(outputScripts) > 0 { + originalResponse := aiResponse + aiResponse = regexService.ExecuteScripts(outputScripts, aiResponse, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("应用了 %d 个输出阶段正则脚本,原文: %s, 处理后: %s", len(outputScripts), originalResponse, aiResponse)) + } + } + return aiResponse, nil } @@ -648,12 +697,27 @@ func (s *ConversationService) SendMessageStream(userID, conversationID uint, req return errors.New("角色卡不存在") } + // 应用输入阶段的正则脚本 (Placement 0) + processedContent := req.Content + var regexService RegexScriptService + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 查询输入阶段正则脚本: userID=%d, placement=0, charID=%d", userID, conversation.CharacterID)) + inputScripts, err := regexService.GetScriptsForPlacement(userID, 0, &conversation.CharacterID, nil) + if err != nil { + global.GVA_LOG.Error(fmt.Sprintf("[流式传输] 查询输入阶段正则脚本失败: %v", err)) + } else { + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 找到 %d 个输入阶段正则脚本", len(inputScripts))) + if len(inputScripts) > 0 { + processedContent = regexService.ExecuteScripts(inputScripts, processedContent, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 应用了 %d 个输入阶段正则脚本", len(inputScripts))) + } + } + // 保存用户消息 userMessage := app.Message{ ConversationID: conversationID, Role: "user", - Content: req.Content, - TokenCount: len(req.Content) / 4, + Content: processedContent, + TokenCount: len(processedContent) / 4, } err = global.GVA_DB.Create(&userMessage).Error @@ -768,6 +832,19 @@ func (s *ConversationService) SendMessageStream(userID, conversationID uint, req // 打印AI返回的完整内容 global.GVA_LOG.Info(fmt.Sprintf("========== [流式传输] AI返回的完整内容 ==========\n%s\n==========================================", fullContent)) + // 应用输出阶段的正则脚本 (Placement 1) + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 查询输出阶段正则脚本: userID=%d, placement=1, charID=%d", userID, conversation.CharacterID)) + outputScripts, err := regexService.GetScriptsForPlacement(userID, 1, &conversation.CharacterID, nil) + if err != nil { + global.GVA_LOG.Error(fmt.Sprintf("[流式传输] 查询输出阶段正则脚本失败: %v", err)) + } else { + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 找到 %d 个输出阶段正则脚本", len(outputScripts))) + if len(outputScripts) > 0 { + fullContent = regexService.ExecuteScripts(outputScripts, fullContent, "", character.Name) + global.GVA_LOG.Info(fmt.Sprintf("[流式传输] 应用了 %d 个输出阶段正则脚本", len(outputScripts))) + } + } + // 保存 AI 回复 assistantMessage := app.Message{ ConversationID: conversationID, diff --git a/server/service/app/regex_script.go b/server/service/app/regex_script.go index 58faf1f..ffc91e7 100644 --- a/server/service/app/regex_script.go +++ b/server/service/app/regex_script.go @@ -254,14 +254,16 @@ func (s *RegexScriptService) GetScriptsForPlacement(userID uint, placement int, db := global.GVA_DB.Where("user_id = ? AND placement = ? AND disabled = ?", userID, placement, false) // 作用域过滤:全局(0) 或 角色(1) 或 预设(2) - scopeCondition := "scope = 0" // 全局 - if charID != nil { - scopeCondition += " OR (scope = 1 AND owner_char_id = " + string(rune(*charID)) + ")" + // 使用参数化查询避免 SQL 注入 + if charID != nil && presetID != nil { + db = db.Where("scope = 0 OR (scope = 1 AND owner_char_id = ?) OR (scope = 2 AND owner_preset_id = ?)", *charID, *presetID) + } else if charID != nil { + db = db.Where("scope = 0 OR (scope = 1 AND owner_char_id = ?)", *charID) + } else if presetID != nil { + db = db.Where("scope = 0 OR (scope = 2 AND owner_preset_id = ?)", *presetID) + } else { + db = db.Where("scope = 0") } - if presetID != nil { - scopeCondition += " OR (scope = 2 AND owner_preset_id = " + string(rune(*presetID)) + ")" - } - db = db.Where(scopeCondition) if err := db.Order("\"order\" ASC").Find(&scripts).Error; err != nil { return nil, err diff --git a/web-app/src/api/regex.ts b/web-app/src/api/regex.ts index bfa7afa..9059a85 100644 --- a/web-app/src/api/regex.ts +++ b/web-app/src/api/regex.ts @@ -107,7 +107,7 @@ export const regexScriptApi = { }, // 测试正则脚本 - testRegexScript: (id: number, testString: string): Promise<{ data: { result: string } }> => { + testRegexScript: (id: number, testString: string): Promise<{ data: { original: string; result: string; success: boolean; error?: string } }> => { return apiClient.post(`/app/regex/${id}/test`, { testString }) }, }