feat(ssa): Implement dual-channel architecture Phase 1-3 (QPER + LLM Agent pipeline)
Completed: - Phase 1: DB schema (execution_mode + ssa_agent_executions), ModeToggle component, Session PATCH API - Phase 2: AgentPlannerService + AgentCoderService (streaming) + CodeRunnerService + R Docker /execute-code endpoint - Phase 3: AgentCodePanel (3-step confirmation UI), SSE event handling (7 agent events), streaming code display - Three-step confirmation pipeline: plan -> user confirm -> stream code -> user confirm -> execute R code -> results - R Docker sandbox /execute-code endpoint with 120s timeout + block_helpers preloaded - E2E dual-channel test script (8 tests) - Updated R engine architecture doc (v1.5) and SSA module status doc (v4.0) Technical details: - AgentCoderService uses LLM streaming (chatStream) for real-time code generation feedback - ReviewerAgent temporarily disabled, prioritizing Plan -> Code -> Execute flow - CodeRunnerService wraps user code with auto data loading (df variable injection) - Frontend handles agent_planning, agent_plan_ready, code_generating, code_generated, code_executing, code_result events - ask_user mechanism used for plan and code confirmation steps Files: 24 files (4 new services, 2 new components, 1 migration, 1 E2E test, 16 modified) Made-with: Cursor
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
import { FastifyInstance, FastifyRequest } from 'fastify';
|
||||
import { logger } from '../../../common/logging/index.js';
|
||||
import { prisma } from '../../../config/database.js';
|
||||
import { conversationService } from '../services/ConversationService.js';
|
||||
import { intentRouterService } from '../services/IntentRouterService.js';
|
||||
import { chatHandlerService } from '../services/ChatHandlerService.js';
|
||||
@@ -114,6 +115,41 @@ export default async function chatRoutes(app: FastifyInstance) {
|
||||
}
|
||||
// ── H1 结束 ──
|
||||
|
||||
// 3. 读取 session 的执行模式
|
||||
const session = await (prisma.ssaSession as any).findUnique({
|
||||
where: { id: sessionId },
|
||||
select: { executionMode: true },
|
||||
});
|
||||
const executionMode = (session?.executionMode as string) || 'qper';
|
||||
|
||||
// ── Agent 通道分流 ──
|
||||
if (executionMode === 'agent') {
|
||||
const placeholderMsgId = await conversationService.createAssistantPlaceholder(
|
||||
conversationId, 'chat',
|
||||
);
|
||||
|
||||
const metaEvent = JSON.stringify({
|
||||
type: 'intent_classified',
|
||||
intent: 'analyze',
|
||||
confidence: 1,
|
||||
source: 'agent_mode',
|
||||
guardTriggered: false,
|
||||
});
|
||||
writer.write(`data: ${metaEvent}\n\n`);
|
||||
|
||||
const result = await chatHandlerService.handleAgentMode(
|
||||
sessionId, conversationId, content.trim(), writer, placeholderMsgId,
|
||||
);
|
||||
|
||||
logger.info('[SSA:Chat] Agent mode request completed', {
|
||||
sessionId, success: result.success,
|
||||
});
|
||||
|
||||
writer.end();
|
||||
return;
|
||||
}
|
||||
// ── QPER 通道(现有逻辑) ──
|
||||
|
||||
// 3. 意图分类
|
||||
const intentResult = await intentRouterService.classify(content.trim(), sessionId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user