Files
SuperBizAgent-java/src/test/java/com/superbiz/agent/config/HarnessChatConfigurationTest.java
T
zhuyongxin 7ae9707a3b feat(harness,rag): dual LLM audit fields, run conclusion, and hybrid quality
Persist provider reasoning and assistant text separately on agent_reasoning_audit
(DeepSeekAssistantMessage path), extract diagnosis_run.conclusion, enrich RAG
tool audit (step_id/query/qualityScore), gate empty mysql tools, drop devtools,
and align MVP docs after live E2E verification.
2026-07-28 19:43:13 +08:00

110 lines
5.9 KiB
Java

package com.superbiz.agent.config;
import com.superbiz.agent.harness.core.DiagnosisHarnessCore;
import com.superbiz.agent.harness.audit.ToolInvocationAuditSink;
import com.superbiz.agent.harness.audit.DiagnosisTraceRecorder;
import com.superbiz.agent.harness.application.persistence.ChatRunStore;
import com.superbiz.agent.harness.tool.contract.MysqlToolRequest;
import com.superbiz.agent.harness.tool.mysql.MysqlSqlValidator;
import com.superbiz.agent.harness.tool.mysql.MysqlSecurityException;
import com.superbiz.agent.tool.LookupKnowledgeTool;
import com.superbiz.agent.service.KnowledgeContextPacker;
import com.superbiz.agent.service.KnowledgeDocumentRetriever;
import com.superbiz.agent.service.KnowledgeEvidencePostProcessor;
import com.superbiz.agent.service.KnowledgeQueryTransformer;
import com.superbiz.agent.service.LookupResultAssembler;
import com.superbiz.agent.repository.AgentStepRepository;
import com.superbiz.agent.repository.AgentReasoningAuditRepository;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.data.redis.core.RedisTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
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.Mockito.mock;
class HarnessChatConfigurationTest {
@Test
void diagnosisNoGainThresholdDefaultsAndValidates() {
ChatHarnessProperties properties = new ChatHarnessProperties();
assertEquals(2, properties.getStopAfterConsecutiveNoGain());
assertEquals(2, properties.getStopAfterConsecutiveProgressProtocolViolations());
properties.setStopAfterConsecutiveNoGain(0);
assertThrows(IllegalArgumentException.class, properties::validate);
properties.setStopAfterConsecutiveNoGain(2);
properties.setStopAfterConsecutiveProgressProtocolViolations(0);
assertThrows(IllegalArgumentException.class, properties::validate);
}
@Test
void defaultsArePositiveAndExecutorsAreBounded() {
ChatHarnessProperties properties = new ChatHarnessProperties();
properties.validate();
HarnessChatConfiguration configuration = new HarnessChatConfiguration();
ThreadPoolExecutor worker = configuration.chatWorkerExecutor(properties);
ThreadPoolExecutor model = configuration.harnessModelExecutor(properties);
try {
assertTrue(worker.getQueue().remainingCapacity() > 0);
assertTrue(model.getQueue().remainingCapacity() > 0);
assertEquals(properties.getWorkerMaxPoolSize(), worker.getMaximumPoolSize());
assertEquals(properties.getModelMaxPoolSize(), model.getMaximumPoolSize());
} finally {
worker.shutdownNow();
model.shutdownNow();
}
}
@Test
void emptyMysqlConfigurationFailsClosedWithoutApplicationDatasource() {
MysqlToolProperties properties = new MysqlToolProperties();
HarnessChatConfiguration configuration = new HarnessChatConfiguration();
assertTrue(configuration.harnessMysqlDataSources(properties).isEmpty());
Map<String, com.superbiz.agent.harness.tool.mysql.MysqlDataSourceDefinition> definitions =
configuration.harnessMysqlDefinitions(properties);
MysqlSqlValidator validator = configuration.mysqlSqlValidator(definitions);
assertThrows(MysqlSecurityException.class, () -> validator.validate(
new MysqlToolRequest("application", "SELECT id FROM users", java.util.List.of())));
}
@Test
void harnessConfigurationBuildsOneApplicationGraphWithControlledDependencies() {
new ApplicationContextRunner()
.withUserConfiguration(HarnessChatConfiguration.class)
.withBean(ObjectMapper.class, ObjectMapper::new)
.withBean(ChatModel.class, () -> mock(ChatModel.class))
.withBean(RedisTemplate.class, () -> mock(RedisTemplate.class))
.withBean(LookupKnowledgeTool.class, () -> mock(LookupKnowledgeTool.class))
.withBean(KnowledgeQueryTransformer.class, () -> mock(KnowledgeQueryTransformer.class))
.withBean(KnowledgeDocumentRetriever.class, () -> mock(KnowledgeDocumentRetriever.class))
.withBean(KnowledgeEvidencePostProcessor.class, () -> mock(KnowledgeEvidencePostProcessor.class))
.withBean(KnowledgeContextPacker.class, () -> mock(KnowledgeContextPacker.class))
.withBean(LookupResultAssembler.class, () -> mock(LookupResultAssembler.class))
.withBean(ToolInvocationAuditSink.class, ToolInvocationAuditSink::noop)
.withBean(DiagnosisTraceRecorder.class, DiagnosisTraceRecorder::noop)
.withBean(com.superbiz.agent.harness.audit.AgentStepAuditTracker.class,
com.superbiz.agent.harness.audit.AgentStepAuditTracker::new)
.withBean(AgentStepRepository.class, () -> mock(AgentStepRepository.class))
.withBean(AgentReasoningAuditRepository.class,
() -> mock(AgentReasoningAuditRepository.class))
.withBean(ChatRunStore.class, () -> mock(ChatRunStore.class))
.withBean(MysqlToolProperties.class, MysqlToolProperties::new)
.run(context -> {
assertTrue(context.isRunning());
assertEquals(1, context.getBeansOfType(
com.superbiz.agent.harness.application.ChatApplicationUseCase.class).size());
assertTrue(context.containsBean("harnessModelExecutor"));
assertTrue(context.containsBean("chatWorkerExecutor"));
});
}
}