feat(agent): 补齐会话消息与工作台链路

This commit is contained in:
2026-06-01 04:07:31 +08:00
parent 041ed0b446
commit 5e0212d2a0
29 changed files with 1288 additions and 27 deletions

View File

@@ -0,0 +1,86 @@
package com.bruce.agent.factory;
import com.bruce.agent.dto.request.AgentDefinitionSaveRequest;
import com.bruce.agent.dto.request.AgentSessionCreateDTO;
import com.bruce.agent.dto.request.AgentSessionMessageCreateDTO;
import com.bruce.agent.dto.response.AgentDefinitionResponse;
import com.bruce.agent.entity.AgentDefinition;
import com.bruce.agent.entity.AgentMessage;
import com.bruce.agent.entity.AgentSession;
import com.bruce.agent.vo.AgentSessionDetailVO;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class AgentFactoryTests {
private final AgentDefinitionFactory agentDefinitionFactory = new AgentDefinitionFactory();
private final AgentSessionFactory agentSessionFactory = new AgentSessionFactory();
private final AgentMessageFactory agentMessageFactory = new AgentMessageFactory();
@Test
void agentDefinitionFactoryShouldTrimRequestAndBuildResponse() {
AgentDefinitionSaveRequest request = new AgentDefinitionSaveRequest();
request.setId(1L);
request.setAgentCode(" AGENT_RAG_HELPER ");
request.setAgentName(" 知识问答助手 ");
request.setSystemPrompt(" 你是企业知识助手 ");
request.setStoreId(1001L);
request.setStatus(" ENABLED ");
request.setRemark(" 默认Agent ");
AgentDefinition entity = agentDefinitionFactory.toEntity(request);
assertEquals("AGENT_RAG_HELPER", entity.getAgentCode());
assertEquals("知识问答助手", entity.getAgentName());
assertEquals("你是企业知识助手", entity.getSystemPrompt());
assertEquals("ENABLED", entity.getStatus());
assertEquals("默认Agent", entity.getRemark());
AgentDefinitionResponse response = agentDefinitionFactory.toResponse(entity);
assertEquals(1001L, response.getStoreId());
assertEquals("AGENT_RAG_HELPER", response.getAgentCode());
}
@Test
void agentSessionFactoryShouldBuildSessionEntityAndDetailView() {
AgentSessionCreateDTO request = new AgentSessionCreateDTO();
request.setAgentId(1L);
request.setSessionCode(" session_001 ");
request.setWorkflowRunId(2001L);
request.setTitle(" 产品问答会话 ");
request.setMetadataJson(" {\"source\":\"debug\"} ");
request.setRemark(" 首轮调试 ");
AgentSession entity = agentSessionFactory.toEntity(request);
assertNotNull(entity);
assertEquals("session_001", entity.getSessionCode());
assertEquals("产品问答会话", entity.getTitle());
assertEquals("{\"source\":\"debug\"}", entity.getMetadataJson());
assertEquals("首轮调试", entity.getRemark());
AgentSessionDetailVO detailVO = agentSessionFactory.toDetailVO(entity);
assertEquals(1L, detailVO.getAgentId());
assertEquals("session_001", detailVO.getSessionCode());
}
@Test
void agentMessageFactoryShouldBuildMessageEntityAndPreserveCitationJson() {
AgentSessionMessageCreateDTO request = new AgentSessionMessageCreateDTO();
request.setSessionId(10L);
request.setRole(" assistant ");
request.setContent(" 这里是回答内容 ");
request.setCitationJson(" [{\"chunkId\":1}] ");
request.setTokenCount(256);
request.setRemark(" 回答成功 ");
AgentMessage entity = agentMessageFactory.toEntity(request);
assertEquals(10L, entity.getSessionId());
assertEquals("assistant", entity.getRole());
assertEquals("这里是回答内容", entity.getContent());
assertEquals("[{\"chunkId\":1}]", entity.getCitationJson());
assertEquals(256, entity.getTokenCount());
assertTrue(entity.getRemark().contains("回答成功"));
}
}

View File

@@ -0,0 +1,119 @@
package com.bruce.agent.session;
import com.bruce.agent.dto.request.AgentSessionCreateDTO;
import com.bruce.agent.dto.request.AgentSessionMessageCreateDTO;
import com.bruce.agent.entity.AgentDefinition;
import com.bruce.agent.entity.AgentMessage;
import com.bruce.agent.entity.AgentSession;
import com.bruce.agent.service.IAgentDefinitionService;
import com.bruce.agent.service.impl.AgentMessageServiceImpl;
import com.bruce.agent.service.impl.AgentSessionServiceImpl;
import com.bruce.common.enums.EnableStatusEnum;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class AgentSessionServiceTests {
@Mock
private IAgentDefinitionService agentDefinitionService;
@Spy
@InjectMocks
private AgentSessionServiceImpl agentSessionService;
@Spy
@InjectMocks
private AgentMessageServiceImpl agentMessageService;
@Test
void createSessionShouldRejectDisabledAgent() {
AgentDefinition agent = new AgentDefinition();
agent.setId(1L);
agent.setStatus("DISABLED");
when(agentDefinitionService.getById(1L)).thenReturn(agent);
AgentSessionCreateDTO request = new AgentSessionCreateDTO();
request.setAgentId(1L);
request.setSessionCode("session_001");
assertThrows(IllegalArgumentException.class, () -> agentSessionService.createSession(request));
}
@Test
void createSessionShouldPersistActiveSession() {
AgentDefinition agent = new AgentDefinition();
agent.setId(1L);
agent.setStatus(EnableStatusEnum.ENABLED.name());
when(agentDefinitionService.getById(1L)).thenReturn(agent);
doAnswer(invocation -> true).when(agentSessionService).save(any(AgentSession.class));
AgentSessionCreateDTO request = new AgentSessionCreateDTO();
request.setAgentId(1L);
request.setSessionCode("session_001");
request.setTitle("产品问答");
request.setMetadataJson("{\"source\":\"debug\"}");
boolean result = agentSessionService.createSession(request);
assertTrue(result);
ArgumentCaptor<AgentSession> captor = ArgumentCaptor.forClass(AgentSession.class);
verify(agentSessionService).save(captor.capture());
assertEquals("session_001", captor.getValue().getSessionCode());
assertEquals("ACTIVE", captor.getValue().getStatus());
}
@Test
void appendMessageShouldRejectClosedSession() {
AgentSession session = new AgentSession();
session.setId(10L);
session.setStatus("CLOSED");
doReturn(session).when(agentMessageService).loadSession(10L);
AgentSessionMessageCreateDTO request = new AgentSessionMessageCreateDTO();
request.setSessionId(10L);
request.setRole("user");
request.setContent("你好");
request.setCitationJson("[]");
assertThrows(IllegalArgumentException.class, () -> agentMessageService.appendMessage(request));
}
@Test
void appendMessageShouldPersistCitationJson() {
AgentSession session = new AgentSession();
session.setId(10L);
session.setStatus("ACTIVE");
doReturn(session).when(agentMessageService).loadSession(10L);
doAnswer(invocation -> true).when(agentMessageService).save(any(AgentMessage.class));
AgentSessionMessageCreateDTO request = new AgentSessionMessageCreateDTO();
request.setSessionId(10L);
request.setRole("assistant");
request.setContent("这里是回答");
request.setCitationJson("[{\"chunkId\":1}]");
request.setTokenCount(128);
boolean result = agentMessageService.appendMessage(request);
assertTrue(result);
ArgumentCaptor<AgentMessage> captor = ArgumentCaptor.forClass(AgentMessage.class);
verify(agentMessageService).save(captor.capture());
assertEquals("[{\"chunkId\":1}]", captor.getValue().getCitationJson());
assertEquals(128, captor.getValue().getTokenCount());
}
}

View File

@@ -0,0 +1,81 @@
package com.bruce.agent.workspace;
import com.bruce.agent.entity.AgentDefinition;
import com.bruce.agent.service.IAgentDefinitionService;
import com.bruce.agent.service.IAgentMessageService;
import com.bruce.agent.service.IAgentSessionService;
import com.bruce.agent.service.impl.AgentWorkspaceServiceImpl;
import com.bruce.agent.vo.AgentMessageVO;
import com.bruce.agent.vo.AgentSessionDetailVO;
import com.bruce.agent.vo.AgentWorkspaceVO;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class AgentWorkspaceServiceTests {
@Mock
private IAgentDefinitionService agentDefinitionService;
@Mock
private IAgentSessionService agentSessionService;
@Mock
private IAgentMessageService agentMessageService;
@InjectMocks
private AgentWorkspaceServiceImpl agentWorkspaceService;
@Test
void getWorkspaceShouldAggregateAgentSessionAndMessages() {
AgentDefinition agent = new AgentDefinition();
agent.setId(1L);
agent.setAgentCode("AGENT_RAG_HELPER");
agent.setAgentName("知识问答助手");
agent.setStoreId(1001L);
agent.setStatus("ENABLED");
AgentSessionDetailVO session = new AgentSessionDetailVO();
session.setId(10L);
session.setAgentId(1L);
session.setSessionCode("session_001");
session.setStatus("ACTIVE");
session.setTitle("产品问答");
session.setWorkflowRunId(2001L);
AgentMessageVO userMessage = new AgentMessageVO();
userMessage.setRole("user");
userMessage.setContent("产品支持哪些模型?");
AgentMessageVO assistantMessage = new AgentMessageVO();
assistantMessage.setRole("assistant");
assistantMessage.setContent("当前支持 OpenAI Compatible 协议模型。");
assistantMessage.setCitationJson("[{\"chunkId\":1}]");
assistantMessage.setTokenCount(256);
assistantMessage.setRequestId("req-001");
when(agentDefinitionService.getById(1L)).thenReturn(agent);
when(agentSessionService.listByAgentId(1L)).thenReturn(List.of(session));
when(agentMessageService.listBySessionId(10L)).thenReturn(List.of(userMessage, assistantMessage));
AgentWorkspaceVO workspace = agentWorkspaceService.getWorkspace(1L, 10L);
assertNotNull(workspace);
assertEquals("AGENT_RAG_HELPER", workspace.getAgentCode());
assertEquals("知识问答助手", workspace.getAgentName());
assertEquals(10L, workspace.getSessionId());
assertEquals("session_001", workspace.getSessionCode());
assertEquals(2, workspace.getMessages().size());
assertEquals(1, workspace.getCitationCount());
assertEquals(256, workspace.getTotalTokens());
assertEquals("req-001", workspace.getLatestRequestId());
}
}