回调推送消息
This commit is contained in:
parent
2e0936cb6b
commit
8fac71869f
@ -1,6 +1,7 @@
|
|||||||
package com.company.agentfoundation.assistant.api;
|
package com.company.agentfoundation.assistant.api;
|
||||||
|
|
||||||
import com.company.agentfoundation.integration.coze.service.CozeWorkflowService;
|
import com.company.agentfoundation.integration.coze.service.CozeWorkflowService;
|
||||||
|
import com.company.agentfoundation.integration.wecom.client.WecomClient;
|
||||||
import com.company.agentfoundation.semantic.SemanticDispatchResult;
|
import com.company.agentfoundation.semantic.SemanticDispatchResult;
|
||||||
import com.company.agentfoundation.semantic.SemanticDispatchService;
|
import com.company.agentfoundation.semantic.SemanticDispatchService;
|
||||||
import com.company.agentfoundation.semantic.SemanticReplyAttachment;
|
import com.company.agentfoundation.semantic.SemanticReplyAttachment;
|
||||||
@ -35,6 +36,7 @@ public class AssistantApiController {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(AssistantApiController.class);
|
private static final Logger log = LoggerFactory.getLogger(AssistantApiController.class);
|
||||||
|
|
||||||
private final CozeWorkflowService cozeWorkflowService;
|
private final CozeWorkflowService cozeWorkflowService;
|
||||||
|
private final WecomClient wecomClient;
|
||||||
private final SemanticDispatchService semanticDispatchService;
|
private final SemanticDispatchService semanticDispatchService;
|
||||||
private final AssistantFileStore fileStore;
|
private final AssistantFileStore fileStore;
|
||||||
private final Executor assistantTaskExecutor;
|
private final Executor assistantTaskExecutor;
|
||||||
@ -43,11 +45,13 @@ public class AssistantApiController {
|
|||||||
|
|
||||||
public AssistantApiController(
|
public AssistantApiController(
|
||||||
CozeWorkflowService cozeWorkflowService,
|
CozeWorkflowService cozeWorkflowService,
|
||||||
|
WecomClient wecomClient,
|
||||||
SemanticDispatchService semanticDispatchService,
|
SemanticDispatchService semanticDispatchService,
|
||||||
AssistantFileStore fileStore,
|
AssistantFileStore fileStore,
|
||||||
@Qualifier("wecomTaskExecutor") Executor assistantTaskExecutor
|
@Qualifier("wecomTaskExecutor") Executor assistantTaskExecutor
|
||||||
) {
|
) {
|
||||||
this.cozeWorkflowService = cozeWorkflowService;
|
this.cozeWorkflowService = cozeWorkflowService;
|
||||||
|
this.wecomClient = wecomClient;
|
||||||
this.semanticDispatchService = semanticDispatchService;
|
this.semanticDispatchService = semanticDispatchService;
|
||||||
this.fileStore = fileStore;
|
this.fileStore = fileStore;
|
||||||
this.assistantTaskExecutor = assistantTaskExecutor;
|
this.assistantTaskExecutor = assistantTaskExecutor;
|
||||||
@ -57,11 +61,14 @@ public class AssistantApiController {
|
|||||||
value = {"/general/query", "/general/query/", "/general/query/general"},
|
value = {"/general/query", "/general/query/", "/general/query/general"},
|
||||||
consumes = MediaType.APPLICATION_JSON_VALUE,
|
consumes = MediaType.APPLICATION_JSON_VALUE,
|
||||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public AssistantQueryResponse generalQuery(@RequestBody AssistantQueryRequest request) {
|
public AssistantQueryResponse generalQuery(
|
||||||
|
@RequestBody AssistantQueryRequest request,
|
||||||
|
HttpServletRequest httpRequest
|
||||||
|
) {
|
||||||
String query = request == null ? "" : request.normalizedQuery();
|
String query = request == null ? "" : request.normalizedQuery();
|
||||||
if (query.isEmpty()) return AssistantQueryResponse.failure("query不能为空");
|
if (query.isEmpty()) return AssistantQueryResponse.failure("query不能为空");
|
||||||
if (isCustomerCreation(query)) {
|
if (isCustomerCreation(query)) {
|
||||||
return acceptCustomerCreation(query);
|
return acceptCustomerCreation(query, resolveUserId(request, httpRequest));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return AssistantQueryResponse.success(
|
return AssistantQueryResponse.success(
|
||||||
@ -72,7 +79,7 @@ public class AssistantApiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssistantQueryResponse acceptCustomerCreation(String query) {
|
private AssistantQueryResponse acceptCustomerCreation(String query, String userId) {
|
||||||
String requestKey = query.toLowerCase(Locale.ROOT).replaceAll("\\s+", "");
|
String requestKey = query.toLowerCase(Locale.ROOT).replaceAll("\\s+", "");
|
||||||
if (!runningGeneralWrites.add(requestKey)) {
|
if (!runningGeneralWrites.add(requestKey)) {
|
||||||
return AssistantQueryResponse.success(
|
return AssistantQueryResponse.success(
|
||||||
@ -84,9 +91,11 @@ public class AssistantApiController {
|
|||||||
String reply = toRobotPlainText(cozeWorkflowService.chatDefault(query));
|
String reply = toRobotPlainText(cozeWorkflowService.chatDefault(query));
|
||||||
log.info("assistant general async customer creation completed query={} reply={}",
|
log.info("assistant general async customer creation completed query={} reply={}",
|
||||||
query, reply);
|
query, reply);
|
||||||
|
notifyCustomerCreationResult(userId, true, reply);
|
||||||
} catch (RuntimeException exception) {
|
} catch (RuntimeException exception) {
|
||||||
log.error("assistant general async customer creation failed query={} err={}",
|
log.error("assistant general async customer creation failed query={} err={}",
|
||||||
query, exception.getMessage(), exception);
|
query, exception.getMessage(), exception);
|
||||||
|
notifyCustomerCreationResult(userId, false, "客户新增失败,请稍后重试。");
|
||||||
} finally {
|
} finally {
|
||||||
runningGeneralWrites.remove(requestKey);
|
runningGeneralWrites.remove(requestKey);
|
||||||
}
|
}
|
||||||
@ -101,6 +110,23 @@ public class AssistantApiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyCustomerCreationResult(String userId, boolean success, String result) {
|
||||||
|
if (userId == null || userId.isBlank()) {
|
||||||
|
log.warn("assistant general async result cannot be pushed because WeCom UserID is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String safeResult = result == null || result.isBlank()
|
||||||
|
? (success ? "客户新增处理完成。" : "客户新增失败,请稍后重试。")
|
||||||
|
: result;
|
||||||
|
String message = (success ? "✅ 客户新增完成\n" : "❌ 客户新增失败\n") + safeResult;
|
||||||
|
try {
|
||||||
|
wecomClient.sendText("general", userId, message);
|
||||||
|
} catch (RuntimeException exception) {
|
||||||
|
log.error("assistant general async result push failed userId={} err={}",
|
||||||
|
userId, exception.getMessage(), exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isCustomerCreation(String query) {
|
private boolean isCustomerCreation(String query) {
|
||||||
String compact = query == null ? "" : query.replaceAll("\\s+", "");
|
String compact = query == null ? "" : query.replaceAll("\\s+", "");
|
||||||
boolean hasCreationVerb = compact.contains("新增")
|
boolean hasCreationVerb = compact.contains("新增")
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.company.agentfoundation.assistant.api;
|
package com.company.agentfoundation.assistant.api;
|
||||||
|
|
||||||
import com.company.agentfoundation.integration.coze.service.CozeWorkflowService;
|
import com.company.agentfoundation.integration.coze.service.CozeWorkflowService;
|
||||||
|
import com.company.agentfoundation.integration.wecom.client.WecomClient;
|
||||||
import com.company.agentfoundation.semantic.SemanticDispatchResult;
|
import com.company.agentfoundation.semantic.SemanticDispatchResult;
|
||||||
import com.company.agentfoundation.semantic.SemanticDispatchService;
|
import com.company.agentfoundation.semantic.SemanticDispatchService;
|
||||||
import com.company.agentfoundation.semantic.SemanticReplyAttachment;
|
import com.company.agentfoundation.semantic.SemanticReplyAttachment;
|
||||||
@ -44,10 +45,15 @@ class AssistantApiControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void generalApiAcceptsCustomerCreationAsynchronously() throws Exception {
|
void generalApiAcceptsCustomerCreationAsynchronously() throws Exception {
|
||||||
CozeWorkflowService coze = mock(CozeWorkflowService.class);
|
CozeWorkflowService coze = mock(CozeWorkflowService.class);
|
||||||
|
when(coze.chatDefault("新增客户 名称 张三 电话 13632363654"))
|
||||||
|
.thenReturn("企业微信智能表格批量写入成功");
|
||||||
|
WecomClient wecom = mock(WecomClient.class);
|
||||||
CapturingExecutor executor = new CapturingExecutor();
|
CapturingExecutor executor = new CapturingExecutor();
|
||||||
MockMvc mvc = mvc(coze, mock(SemanticDispatchService.class), new AssistantFileStore(), executor);
|
MockMvc mvc = mvc(
|
||||||
|
coze, wecom, mock(SemanticDispatchService.class), new AssistantFileStore(), executor);
|
||||||
|
|
||||||
mvc.perform(post("/api/assistant/general/query")
|
mvc.perform(post("/api/assistant/general/query")
|
||||||
|
.header("X-WeCom-UserId", "YiNianYiQingJing")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content("{\"query\":\"新增客户 名称 张三 电话 13632363654\"}"))
|
.content("{\"query\":\"新增客户 名称 张三 电话 13632363654\"}"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
@ -57,6 +63,10 @@ class AssistantApiControllerTest {
|
|||||||
org.mockito.Mockito.verifyNoInteractions(coze);
|
org.mockito.Mockito.verifyNoInteractions(coze);
|
||||||
executor.runCaptured();
|
executor.runCaptured();
|
||||||
verify(coze).chatDefault("新增客户 名称 张三 电话 13632363654");
|
verify(coze).chatDefault("新增客户 名称 张三 电话 13632363654");
|
||||||
|
verify(wecom).sendText(
|
||||||
|
"general",
|
||||||
|
"YiNianYiQingJing",
|
||||||
|
"✅ 客户新增完成\n企业微信智能表格批量写入成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -204,17 +214,18 @@ class AssistantApiControllerTest {
|
|||||||
SemanticDispatchService semantic,
|
SemanticDispatchService semantic,
|
||||||
AssistantFileStore files
|
AssistantFileStore files
|
||||||
) {
|
) {
|
||||||
return mvc(coze, semantic, files, Runnable::run);
|
return mvc(coze, mock(WecomClient.class), semantic, files, Runnable::run);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MockMvc mvc(
|
private MockMvc mvc(
|
||||||
CozeWorkflowService coze,
|
CozeWorkflowService coze,
|
||||||
|
WecomClient wecom,
|
||||||
SemanticDispatchService semantic,
|
SemanticDispatchService semantic,
|
||||||
AssistantFileStore files,
|
AssistantFileStore files,
|
||||||
Executor executor
|
Executor executor
|
||||||
) {
|
) {
|
||||||
return MockMvcBuilders.standaloneSetup(
|
return MockMvcBuilders.standaloneSetup(
|
||||||
new AssistantApiController(coze, semantic, files, executor))
|
new AssistantApiController(coze, wecom, semantic, files, executor))
|
||||||
.setMessageConverters(
|
.setMessageConverters(
|
||||||
new MappingJackson2HttpMessageConverter(),
|
new MappingJackson2HttpMessageConverter(),
|
||||||
new ByteArrayHttpMessageConverter())
|
new ByteArrayHttpMessageConverter())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user