agent-foundation/src/main/java/com/company/agentfoundation/agent/AgentOrchestratorService.java
2026-06-12 09:56:34 +08:00

137 lines
5.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.company.agentfoundation.agent;
import com.company.agentfoundation.domain.ChatRequest;
import com.company.agentfoundation.domain.ChatResponse;
import com.company.agentfoundation.directory.EmployeeAccountMapping;
import com.company.agentfoundation.directory.EmployeeDirectoryResponse;
import com.company.agentfoundation.directory.EmployeeDirectoryService;
import com.company.agentfoundation.security.AgentContext;
import com.company.agentfoundation.service.ChatService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AgentOrchestratorService {
private static final Logger log = LoggerFactory.getLogger(AgentOrchestratorService.class);
private final IntentRecognitionService intentRecognitionService;
private final OperationReportService operationReportService;
private final ChatService chatService;
private final EmployeeDirectoryService employeeDirectoryService;
public AgentOrchestratorService(
IntentRecognitionService intentRecognitionService,
OperationReportService operationReportService,
ChatService chatService,
EmployeeDirectoryService employeeDirectoryService
) {
this.intentRecognitionService = intentRecognitionService;
this.operationReportService = operationReportService;
this.chatService = chatService;
this.employeeDirectoryService = employeeDirectoryService;
}
public String handleMessage(String agentId, String fromUser, String userText) {
AgentIntent intent = intentRecognitionService.recognize(agentId, userText);
log.info("agent orchestrator route fromUser={} intent={} group={}", fromUser, intent.code(), intent.mcpGroup());
if (intent != AgentIntent.GENERAL_CHAT) {
return appendDirectoryInfo(
toWecomText(operationReportService.handle(intent, AgentRequestContext.of(agentId, fromUser, userText))),
fromUser
);
}
ChatRequest request = new ChatRequest(
null,
List.of(
new ChatRequest.Message("system", "You are an enterprise CRM assistant. Reply concisely in Chinese."),
new ChatRequest.Message("user", userText)
),
0.3
);
ChatResponse response = chatService.chat(new AgentContext(agentId), request);
return appendDirectoryInfo(response.content(), fromUser);
}
private String toWecomText(AgentCapabilityResponse response) {
return """
\u3010%s\u3011
%s
\u80fd\u529b\u5206\u7ec4\uff1a%s
\u80fd\u529b\u7f16\u7801\uff1a%s
\u6570\u636e\u6e90\uff1a%s
\u72b6\u6001\uff1a%s
""".formatted(
response.title(),
response.message(),
response.mcpGroup(),
response.intentCode(),
String.join("\u3001", response.dataSources()),
response.status()
).trim();
}
private String appendDirectoryInfo(String reply, String wecomUserId) {
String text = reply == null || reply.isBlank() ? "" : reply.trim();
return text + "\n\n" + buildDirectoryInfo(wecomUserId);
}
private String buildDirectoryInfo(String wecomUserId) {
if (wecomUserId == null || wecomUserId.isBlank()) {
return "【身份信息】\n企业微信账号:未获取\n学邦账号:未匹配\n部门:未匹配\n身份:未匹配";
}
try {
return employeeDirectoryService.findByWecomUserId(wecomUserId)
.map(this::formatDirectoryInfo)
.orElse("""
【身份信息】
企业微信账号:%s
学邦账号:未匹配
部门:未匹配
身份:未匹配
""".formatted(wecomUserId).trim());
} catch (Exception e) {
log.warn("employee directory lookup failed wecomUserId={} err={}", wecomUserId, e.getMessage());
return """
【身份信息】
企业微信账号:%s
学邦账号:查询失败
部门:查询失败
身份:查询失败
""".formatted(wecomUserId).trim();
}
}
private String formatDirectoryInfo(EmployeeDirectoryResponse response) {
EmployeeAccountMapping account = response.account();
String department = firstNotBlank(account.xuebangPrimaryOrg(), account.wecomDepartmentPath(), "未匹配");
String xuebangAccount = firstNotBlank(account.xuebangAccount(), "未匹配");
String roleName = firstNotBlank(account.primaryRoleName(), "未匹配");
String roleCode = firstNotBlank(account.primaryRoleCode(), "未匹配");
String scopeType = firstNotBlank(account.dataScopeType(), "未匹配");
String roleLevel = account.roleLevel() == null ? "未匹配" : account.roleLevel().toString();
return """
【身份信息】
企业微信账号:%s
学邦账号:%s
部门:%s
身份:%s(%s,级别%s,范围%s)
""".formatted(account.wecomUserId(), xuebangAccount, department, roleName, roleCode, roleLevel, scopeType).trim();
}
private String firstNotBlank(String... values) {
for (String value : values) {
if (value != null && !value.isBlank()) {
return value;
}
}
return "";
}
}