From 1e61d35d5ca28ab5590729635ab7deb7929be19d Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Fri, 31 Jul 2026 17:59:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assistant/api/AssistantApiController.java | 21 ++++++++++++++++--- .../api/AssistantApiControllerTest.java | 18 ++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/company/agentfoundation/assistant/api/AssistantApiController.java b/src/main/java/com/company/agentfoundation/assistant/api/AssistantApiController.java index 0bd8379..4ef6a72 100644 --- a/src/main/java/com/company/agentfoundation/assistant/api/AssistantApiController.java +++ b/src/main/java/com/company/agentfoundation/assistant/api/AssistantApiController.java @@ -55,7 +55,8 @@ public class AssistantApiController { String query = request == null ? "" : request.normalizedQuery(); if (query.isEmpty()) return AssistantQueryResponse.failure("query不能为空"); try { - return AssistantQueryResponse.success(cozeWorkflowService.chatDefault(query), List.of()); + return AssistantQueryResponse.success( + toRobotPlainText(cozeWorkflowService.chatDefault(query)), List.of()); } catch (RuntimeException exception) { log.error("assistant general api failed err={}", exception.getMessage(), exception); return AssistantQueryResponse.failure("扣子问答调用失败,请稍后重试。"); @@ -133,8 +134,9 @@ public class AssistantApiController { String reply, List attachments ) { - if (attachments.isEmpty()) return reply == null ? "" : reply; - StringBuilder content = new StringBuilder(reply == null ? "" : reply); + String robotReply = toRobotPlainText(reply); + if (attachments.isEmpty()) return robotReply; + StringBuilder content = new StringBuilder(robotReply); content.append("\n\n附件:"); for (AssistantQueryResponse.Attachment attachment : attachments) { content.append("\n- [").append(attachment.name()).append("](") @@ -143,6 +145,19 @@ public class AssistantApiController { return content.toString(); } + /** + * API plugins render responses as plain text, so application-message font tags must not leak + * into the robot conversation. + */ + private String toRobotPlainText(String value) { + if (value == null || value.isBlank()) return ""; + return value + .replaceAll("(?i)]*>", "") + .replace("\r\n", "\n") + .replace('\r', '\n') + .trim(); + } + private String resolveUserId( AssistantQueryRequest request, HttpServletRequest httpRequest diff --git a/src/test/java/com/company/agentfoundation/assistant/api/AssistantApiControllerTest.java b/src/test/java/com/company/agentfoundation/assistant/api/AssistantApiControllerTest.java index 8130d96..adfbc23 100644 --- a/src/test/java/com/company/agentfoundation/assistant/api/AssistantApiControllerTest.java +++ b/src/test/java/com/company/agentfoundation/assistant/api/AssistantApiControllerTest.java @@ -162,6 +162,24 @@ class AssistantApiControllerTest { .andExpect(jsonPath("$.content").value(org.hamcrest.Matchers.containsString("UserID"))); } + @Test + void sportsVenueApiRemovesUnsupportedWecomFontTags() throws Exception { + SemanticDispatchService semantic = mock(SemanticDispatchService.class); + when(semantic.dispatchWithAttachments("tester", "daily report")) + .thenReturn(new SemanticDispatchResult( + "new: 35\n" + + "warning: low rate", + List.of())); + MockMvc mvc = mvc(mock(CozeWorkflowService.class), semantic, new AssistantFileStore()); + + mvc.perform(post("/api/assistant/sports-venue/query") + .header("X-WeCom-UserId", "tester") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"query\":\"daily report\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.content").value("new: 35\nwarning: low rate")); + } + private MockMvc mvc( CozeWorkflowService coze, SemanticDispatchService semantic,