Files
AIclinicalresearch/docs/03-业务模块/AIA-AI智能问答/04-开发计划/04-Protocol_Agent开发计划/03-代码结构设计.md
HaHafeng 2481b786d8 deploy: Complete 0126-27 deployment - database upgrade, services update, code recovery
Major Changes:
- Database: Install pg_bigm/pgvector plugins, create test database
- Python service: v1.0 -> v1.1, add pymupdf4llm/openpyxl/pypandoc
- Node.js backend: v1.3 -> v1.7, fix pino-pretty and ES Module imports
- Frontend: v1.2 -> v1.3, skip TypeScript check for deployment
- Code recovery: Restore empty files from local backup

Technical Fixes:
- Fix pino-pretty error in production (conditional loading)
- Fix ES Module import paths (add .js extensions)
- Fix OSSAdapter TypeScript errors
- Update Prisma Schema (63 models, 16 schemas)
- Update environment variables (DATABASE_URL, EXTRACTION_SERVICE_URL, OSS)
- Remove deprecated variables (REDIS_URL, DIFY_API_URL, DIFY_API_KEY)

Documentation:
- Create 0126 deployment folder with 8 documents
- Update database development standards v2.0
- Update SAE deployment status records

Deployment Status:
- PostgreSQL: ai_clinical_research_test with plugins
- Python: v1.1 @ 172.17.173.84:8000
- Backend: v1.7 @ 172.17.173.89:3001
- Frontend: v1.3 @ 172.17.173.90:80

Tested: All services running successfully on SAE
2026-01-27 08:13:27 +08:00

29 KiB
Raw Blame History

Protocol Agent 代码结构设计

版本v1.0
创建日期2026-01-24


一、目录结构

apps/api/src/
├── modules/
│   │
│   ├── agent-framework/                    # 【新增】通用Agent框架
│   │   ├── core/
│   │   │   ├── BaseAgentOrchestrator.ts   # 抽象基类
│   │   │   ├── QueryAnalyzer.ts           # Query层-意图分析
│   │   │   ├── Planner.ts                 # Planner层-执行规划
│   │   │   ├── Executor.ts                # Executor层-任务执行
│   │   │   ├── ToolInvoker.ts             # 工具调用器
│   │   │   └── ReflexionEngine.ts         # Reflection层-质量反思
│   │   │
│   │   ├── memory/
│   │   │   ├── MemoryManager.ts           # 记忆管理器
│   │   │   └── ContextManager.ts          # 上下文管理器
│   │   │
│   │   ├── config/
│   │   │   ├── ConfigLoader.ts            # 配置加载器
│   │   │   └── StageManager.ts            # 阶段状态机
│   │   │
│   │   ├── prompt/
│   │   │   ├── PromptBuilder.ts           # Prompt构建器
│   │   │   └── PromptTemplates.ts         # Prompt模板常量
│   │   │
│   │   ├── trace/
│   │   │   ├── TraceLogger.ts             # 追踪日志记录
│   │   │   └── TraceAnalyzer.ts           # 追踪分析(调试)
│   │   │
│   │   ├── tools/
│   │   │   ├── ToolRegistry.ts            # 工具注册表
│   │   │   ├── DeepLinkGenerator.ts       # Deep Link生成器
│   │   │   └── BaseToolHandler.ts         # 工具处理基类
│   │   │
│   │   ├── types/
│   │   │   ├── agent.types.ts             # Agent核心类型
│   │   │   ├── query.types.ts             # Query相关类型
│   │   │   ├── plan.types.ts              # Plan相关类型
│   │   │   ├── execution.types.ts         # 执行相关类型
│   │   │   ├── reflexion.types.ts         # 反思相关类型
│   │   │   └── tool.types.ts              # 工具相关类型
│   │   │
│   │   └── index.ts                        # 模块导出
│   │
│   ├── aia/
│   │   ├── agents/
│   │   │   │
│   │   │   ├── protocol/                   # 【新增】Protocol Agent
│   │   │   │   ├── ProtocolOrchestrator.ts       # Protocol编排器
│   │   │   │   ├── ProtocolContextService.ts     # Context服务
│   │   │   │   ├── ProtocolStageConfig.ts        # 阶段配置
│   │   │   │   ├── ProtocolPrompts.ts            # 专用Prompt
│   │   │   │   ├── ProtocolExtractor.ts          # 数据提取器
│   │   │   │   ├── tools/
│   │   │   │   │   ├── SampleCalculatorTool.ts   # 样本量计算工具
│   │   │   │   │   ├── DeepLinkTools.ts          # Deep Link工具
│   │   │   │   │   └── index.ts
│   │   │   │   └── index.ts
│   │   │   │
│   │   │   └── (future agents)/
│   │   │       ├── statistics/              # 未来统计分析Agent
│   │   │       └── data-cleaning/           # 未来数据清洗Agent
│   │   │
│   │   ├── routes/
│   │   │   ├── protocolAgent.routes.ts     # 【新增】Protocol Agent路由
│   │   │   ├── chat.routes.ts              # 现有聊天路由
│   │   │   └── index.ts
│   │   │
│   │   ├── services/
│   │   │   ├── chat.service.ts             # 现有聊天服务
│   │   │   ├── conversation.service.ts     # 现有对话服务
│   │   │   └── protocolAgent.service.ts    # 【新增】Protocol Agent服务
│   │   │
│   │   └── (existing files)
│   │
│   └── (other modules)
│
├── shared/
│   ├── llm/                                # 现有LLM Gateway
│   └── (other shared)
│
└── (other folders)

二、核心类型定义

2.1 agent.types.ts - Agent核心类型

// ============================================================
// Agent核心类型定义
// ============================================================

/**
 * Agent配置从数据库加载
 */
export interface AgentConfig {
  id: string;
  agentId: string;
  agentName: string;
  baseSystemPrompt: string;
  toneOfVoice?: string;
  globalKnowledge: string[];
  memoryStrategy: 'full' | 'sliding_window' | 'summary';
  maxHistoryTurns: number;
  defaultModel: string;
  temperature: number;
  maxTokens: number;
  stages: StageConfig[];
  tools: ToolConfig[];
  reflexionRules: ReflexionRuleConfig[];
}

/**
 * 阶段配置
 */
export interface StageConfig {
  id: string;
  stageId: string;
  stageName: string;
  stageOrder: number;
  instruction: string;
  extractionSchema: JSONSchema;
  completionCriteria?: string;
  nextStageId: string | null;
  transitionMode: 'user_confirm' | 'auto' | 'condition';
  transitionCondition?: Record<string, any>;
  availableToolIds: string[];
  actionCards: ActionCardConfig[];
}

/**
 * Action Card配置
 */
export interface ActionCardConfig {
  cardId: string;
  title: string;
  description?: string;
  iconType?: string;
  triggerType: 'stage_enter' | 'condition' | 'manual';
  triggerCondition?: Record<string, any>;
  actionType: 'deep_link' | 'api_call' | 'modal';
  actionPayload: Record<string, any>;
  onCompleteAction?: string;
  resultMapping?: Record<string, string>;
}

/**
 * Agent会话状态
 */
export interface AgentSessionState {
  sessionId: string;
  conversationId: string;
  agentId: string;
  userId: string;
  currentStageId: string;
  stageStatus: 'in_progress' | 'completed' | 'paused';
  lastActiveAt: Date;
}

/**
 * Agent响应
 */
export interface AgentResponse {
  traceId: string;
  message: string;
  thinkingContent?: string;
  actionCards: ActionCardPayload[];
  contextUpdate?: Record<string, any>;
  currentStage: string;
  stageStatus: string;
  suggestions?: string[];
}

2.2 query.types.ts - Query相关类型

// ============================================================
// Query Analysis 类型定义
// ============================================================

/**
 * 意图类型
 */
export type IntentType = 
  | 'provide_info'         // 提供信息
  | 'ask_question'         // 询问问题
  | 'request_change'       // 请求修改
  | 'confirm_complete'     // 确认完成
  | 'navigate_stage'       // 跳转阶段
  | 'request_tool'         // 请求工具
  | 'chitchat'             // 闲聊
  | 'unclear';             // 不明确

/**
 * 提取的实体
 */
export interface ExtractedEntity {
  type: string;            // 实体类型,如 'population', 'intervention'
  value: string;           // 实体值
  confidence: number;      // 置信度 0-1
  span?: {                 // 在原文中的位置
    start: number;
    end: number;
  };
}

/**
 * Query分析结果
 */
export interface QueryAnalysisResult {
  intent: {
    primary: IntentType;
    confidence: number;
    subIntent?: string;
  };
  entities: ExtractedEntity[];
  resolvedQuery: string;
  sentiment?: 'positive' | 'neutral' | 'confused' | 'frustrated';
  requiresClarification: boolean;
  clarificationQuestion?: string;
}

/**
 * Query分析器配置
 */
export interface QueryAnalyzerConfig {
  enableEntityExtraction: boolean;
  enableSentimentAnalysis: boolean;
  enableContextResolution: boolean;
  confidenceThreshold: number;
}

2.3 plan.types.ts - Plan相关类型

// ============================================================
// Planner 类型定义
// ============================================================

/**
 * 执行策略
 */
export type ExecutionStrategy = 
  | 'guide_and_extract'        // 引导对话并提取数据
  | 'answer_question'          // 回答用户问题
  | 'update_context'           // 更新已有数据
  | 'trigger_tool'             // 触发工具调用
  | 'transition_stage'         // 执行阶段流转
  | 'request_clarification'    // 请求澄清
  | 'handle_chitchat';         // 处理闲聊

/**
 * 执行任务
 */
export interface ExecutionTask {
  taskId: string;
  taskType: 'llm_generate' | 'tool_call' | 'data_extract' | 'context_update';
  priority: number;
  params: Record<string, any>;
  dependsOn?: string[];        // 依赖的其他任务ID
}

/**
 * 执行计划
 */
export interface ExecutionPlan {
  strategy: ExecutionStrategy;
  tasks: ExecutionTask[];
  toolsNeeded: string[];
  promptOverrides?: {
    systemPrompt?: string;
    userPromptPrefix?: string;
  };
  shouldExtract: boolean;
  shouldReflect: boolean;
  metadata: {
    planReason: string;
    estimatedTokens?: number;
  };
}

/**
 * 阶段流转结果
 */
export interface StageTransitionResult {
  success: boolean;
  previousStage: string;
  nextStage?: string;
  issues?: string[];
  suggestions?: string[];
  summary?: string;
}

2.4 execution.types.ts - 执行相关类型

// ============================================================
// Executor 类型定义
// ============================================================

/**
 * LLM响应
 */
export interface LLMResponse {
  content: string;
  thinkingContent?: string;
  finishReason: 'stop' | 'length' | 'tool_calls';
  usage: {
    promptTokens: number;
    completionTokens: number;
    totalTokens: number;
  };
  model: string;
}

/**
 * 提取的数据
 */
export interface ExtractedData {
  hasNewData: boolean;
  data: Record<string, any>;
  confidence: number;
  sourceMessageId: string;
  extractionMethod: 'inline' | 'post_process';
}

/**
 * 工具调用结果
 */
export interface ToolCallResult {
  toolId: string;
  success: boolean;
  result?: any;
  error?: string;
  durationMs: number;
}

/**
 * 执行结果
 */
export interface ExecutionResult {
  response: LLMResponse;
  extracted?: ExtractedData;
  toolResults?: ToolCallResult[];
  actionCards: ActionCardPayload[];
}

/**
 * Action Card载荷返回给前端
 */
export interface ActionCardPayload {
  cardId: string;
  title: string;
  description?: string;
  iconType?: string;
  actionType: 'deep_link' | 'api_call' | 'modal';
  actionUrl?: string;
  actionParams?: Record<string, any>;
  priority: number;
}

2.5 reflexion.types.ts - 反思相关类型

// ============================================================
// Reflexion 类型定义
// ============================================================

/**
 * 反思规则配置
 */
export interface ReflexionRuleConfig {
  ruleId: string;
  ruleName: string;
  triggerStageId?: string;
  triggerTiming: 'on_extract' | 'on_complete' | 'on_transition';
  ruleType: 'prompt_based' | 'rule_based' | 'hybrid';
  promptTemplate?: string;
  ruleLogic?: RuleLogic;
  severity: 'error' | 'warning' | 'info';
  failureAction: 'block' | 'warn' | 'log';
  priority: number;
}

/**
 * 规则逻辑rule_based类型
 */
export interface RuleLogic {
  field: string;
  condition: 'required' | 'min_length' | 'max_length' | 'pattern' | 'custom';
  value?: any;
  customValidator?: string;  // 自定义验证函数名
}

/**
 * 反思检查项
 */
export interface ReflexionCheck {
  ruleId: string;
  ruleName: string;
  passed: boolean;
  severity: 'error' | 'warning' | 'info';
  message?: string;
  suggestion?: string;
}

/**
 * 反思结果
 */
export interface ReflexionResult {
  passed: boolean;
  checks: ReflexionCheck[];
  issues: string[];
  suggestions: string[];
  blockTransition: boolean;
}

2.6 tool.types.ts - 工具相关类型

// ============================================================
// Tool 类型定义
// ============================================================

/**
 * 工具类型
 */
export type ToolType = 'internal' | 'external' | 'deep_link' | 'rag';

/**
 * 工具配置
 */
export interface ToolConfig {
  toolId: string;
  toolName: string;
  toolDescription: string;
  toolType: ToolType;
  functionSchema?: FunctionSchema;
  handlerType: 'code' | 'api' | 'deep_link';
  handlerConfig: Record<string, any>;
  requiresAuth: boolean;
  timeout: number;
}

/**
 * Function Schema (OpenAI格式)
 */
export interface FunctionSchema {
  name: string;
  description: string;
  parameters: {
    type: 'object';
    properties: Record<string, JSONSchemaProperty>;
    required?: string[];
  };
}

/**
 * JSON Schema属性
 */
export interface JSONSchemaProperty {
  type: 'string' | 'number' | 'boolean' | 'array' | 'object';
  description?: string;
  enum?: string[];
  items?: JSONSchemaProperty;
  properties?: Record<string, JSONSchemaProperty>;
}

/**
 * 工具处理器接口
 */
export interface IToolHandler {
  toolId: string;
  execute(params: Record<string, any>, context: ToolContext): Promise<any>;
  validate?(params: Record<string, any>): boolean;
}

/**
 * 工具执行上下文
 */
export interface ToolContext {
  conversationId: string;
  userId: string;
  agentId: string;
  currentStage: string;
  protocolContext?: Record<string, any>;
}

三、核心类实现

3.1 BaseAgentOrchestrator.ts

/**
 * Agent编排器基类
 * 所有Agent都继承此类实现标准的Query→Plan→Execute→Reflect流程
 */
export abstract class BaseAgentOrchestrator<TContext> {
  
  protected config: AgentConfig;
  protected queryAnalyzer: QueryAnalyzer;
  protected planner: Planner;
  protected executor: Executor;
  protected reflexionEngine: ReflexionEngine;
  protected memoryManager: MemoryManager;
  protected configLoader: ConfigLoader;
  protected traceLogger: TraceLogger;
  
  constructor(dependencies: AgentDependencies) {
    // 注入依赖
  }
  
  /**
   * 子类必须实现的抽象方法
   */
  abstract getAgentId(): string;
  abstract getContextSchema(): TContext;
  abstract getContext(conversationId: string): Promise<TContext>;
  abstract updateContext(conversationId: string, data: Partial<TContext>): Promise<void>;
  
  /**
   * 主处理入口
   */
  async handleMessage(
    conversationId: string,
    userMessage: string,
    messageId: string
  ): Promise<AgentResponse> {
    
    const traceId = this.traceLogger.startTrace(conversationId);
    
    try {
      // Step 1: 加载配置和上下文
      const config = await this.configLoader.getAgentConfig(this.getAgentId());
      const context = await this.getContext(conversationId);
      const session = await this.getSession(conversationId);
      const stageConfig = this.getStageConfig(config, session.currentStageId);
      
      // Step 2: Query Analysis
      const queryResult = await this.queryAnalyzer.analyze(
        userMessage, 
        context, 
        session
      );
      this.traceLogger.logStep(traceId, 'query_analysis', { input: userMessage, output: queryResult });
      
      // Step 3: Planning
      const plan = await this.planner.createPlan(
        queryResult, 
        stageConfig, 
        context
      );
      this.traceLogger.logStep(traceId, 'planning', { input: queryResult, output: plan });
      
      // Step 4: Execution
      const execResult = await this.executor.execute(
        plan,
        config,
        stageConfig,
        context,
        conversationId
      );
      this.traceLogger.logStep(traceId, 'execution', { input: plan, output: execResult });
      
      // Step 5: Data Extraction
      if (plan.shouldExtract && execResult.extracted?.hasNewData) {
        await this.updateContext(conversationId, execResult.extracted.data);
      }
      
      // Step 6: Reflection (可选)
      let reflexionResult: ReflexionResult | undefined;
      if (plan.shouldReflect) {
        reflexionResult = await this.reflexionEngine.reflect(
          execResult,
          context,
          stageConfig
        );
        this.traceLogger.logStep(traceId, 'reflexion', { output: reflexionResult });
      }
      
      // Step 7: 构建响应
      const response = this.buildResponse(
        execResult,
        reflexionResult,
        session,
        stageConfig
      );
      
      this.traceLogger.endTrace(traceId, 'success');
      return response;
      
    } catch (error) {
      this.traceLogger.endTrace(traceId, 'error', error);
      throw error;
    }
  }
  
  /**
   * 处理阶段完成
   */
  async handleStageComplete(conversationId: string): Promise<StageTransitionResult> {
    // ... 阶段流转逻辑
  }
  
  /**
   * 处理Action Card回调
   */
  async handleActionCallback(
    conversationId: string,
    cardId: string,
    result: any
  ): Promise<void> {
    // ... Action回调处理
  }
  
  // ... 其他protected方法
}

3.2 ProtocolOrchestrator.ts

/**
 * Protocol Agent 编排器
 * 继承BaseAgentOrchestrator实现研究方案特定逻辑
 */
export class ProtocolOrchestrator extends BaseAgentOrchestrator<ProtocolContext> {
  
  private contextService: ProtocolContextService;
  private protocolExtractor: ProtocolExtractor;
  
  constructor(dependencies: ProtocolAgentDependencies) {
    super(dependencies);
    this.contextService = dependencies.contextService;
    this.protocolExtractor = dependencies.protocolExtractor;
  }
  
  getAgentId(): string {
    return 'protocol_agent';
  }
  
  getContextSchema(): ProtocolContext {
    return ProtocolContextSchema;
  }
  
  async getContext(conversationId: string): Promise<ProtocolContext> {
    return this.contextService.getOrCreate(conversationId);
  }
  
  async updateContext(conversationId: string, data: Partial<ProtocolContext>): Promise<void> {
    await this.contextService.update(conversationId, data);
  }
  
  /**
   * 重写Protocol特定的提取逻辑
   */
  protected async extractData(
    llmResponse: LLMResponse,
    stageConfig: StageConfig
  ): Promise<ExtractedData> {
    return this.protocolExtractor.extract(llmResponse, stageConfig);
  }
  
  /**
   * 重写Protocol特定的阶段完成检查
   */
  protected async validateStageCompletion(
    context: ProtocolContext,
    stageConfig: StageConfig
  ): Promise<ReflexionResult> {
    // Protocol特定的验证逻辑
    const stageData = context[stageConfig.stageId as keyof ProtocolContext];
    
    // 检查必填字段
    // 检查数据完整性
    // 调用Reflexion引擎
    
    return this.reflexionEngine.reflectOnStageComplete(stageData, stageConfig);
  }
}

3.3 PromptBuilder.ts

/**
 * Prompt构建器
 * 负责构建各阶段的System Prompt
 */
export class PromptBuilder {
  
  /**
   * 构建系统Prompt
   */
  buildSystemPrompt(params: {
    basePrompt: string;
    stageConfig: StageConfig;
    context: Record<string, any>;
    toneOfVoice?: string;
  }): string {
    
    const { basePrompt, stageConfig, context, toneOfVoice } = params;
    
    return `
# 角色设定
${basePrompt}

${toneOfVoice ? `# 语气风格\n${toneOfVoice}\n` : ''}

# 当前阶段: ${stageConfig.stageName}
${stageConfig.instruction}

# 已收集的研究方案信息
<protocol_context>
${this.formatContext(context)}
</protocol_context>

# 数据提取要求
在回复的最后如果用户提供了新的信息请以XML格式输出提取到的结构化数据
<extracted_data>
${JSON.stringify(stageConfig.extractionSchema.example || {}, null, 2)}
</extracted_data>

# 注意事项
- 如果用户信息不完整,温和地追问补充
- 如果用户表述有歧义,先确认再记录
- 保持专业但不失亲和力的语气
- 不要编造或假设用户未提供的信息
`.trim();
  }
  
  /**
   * 构建意图识别Prompt
   */
  buildQueryAnalysisPrompt(params: {
    userMessage: string;
    currentStage: string;
    contextSummary: string;
  }): string {
    return `
分析用户消息的意图。

当前阶段: ${params.currentStage}
上下文摘要: ${params.contextSummary}

用户消息: "${params.userMessage}"

请分析并以JSON格式返回:
{
  "intent": {
    "primary": "provide_info|ask_question|request_change|confirm_complete|navigate_stage|request_tool|chitchat|unclear",
    "confidence": 0.0-1.0,
    "subIntent": "可选的子意图"
  },
  "entities": [
    {"type": "entity_type", "value": "entity_value", "confidence": 0.0-1.0}
  ],
  "requiresClarification": true|false,
  "clarificationQuestion": "如需澄清,提供问题"
}
`.trim();
  }
  
  /**
   * 构建Reflexion检查Prompt
   */
  buildReflexionPrompt(params: {
    stageData: Record<string, any>;
    stageConfig: StageConfig;
    rule: ReflexionRuleConfig;
  }): string {
    if (params.rule.promptTemplate) {
      return this.interpolateTemplate(params.rule.promptTemplate, {
        stageData: params.stageData,
        stageName: params.stageConfig.stageName
      });
    }
    
    return `
检查${params.stageConfig.stageName}阶段的数据质量。

当前数据:
${JSON.stringify(params.stageData, null, 2)}

完成标准:
${params.stageConfig.completionCriteria || '无特定标准'}

请检查并以JSON格式返回:
{
  "passed": true|false,
  "issues": ["问题1", "问题2"],
  "suggestions": ["建议1", "建议2"]
}
`.trim();
  }
  
  private formatContext(context: Record<string, any>): string {
    // 格式化上下文,过滤空值,美化输出
    const filtered = Object.entries(context)
      .filter(([_, v]) => v != null && Object.keys(v).length > 0)
      .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
    
    return JSON.stringify(filtered, null, 2);
  }
  
  private interpolateTemplate(template: string, vars: Record<string, any>): string {
    return template.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (_, path) => {
      const value = path.split('.').reduce((obj: any, key: string) => obj?.[key], vars);
      return typeof value === 'object' ? JSON.stringify(value) : String(value ?? '');
    });
  }
}

四、API设计

4.1 路由定义

// protocolAgent.routes.ts

export async function protocolAgentRoutes(fastify: FastifyInstance) {
  
  // 发送消息核心对话API
  fastify.post('/api/aia/protocol-agent/chat', {
    schema: {
      body: {
        type: 'object',
        required: ['conversationId', 'message'],
        properties: {
          conversationId: { type: 'string' },
          message: { type: 'string' },
          attachments: { type: 'array', items: { type: 'string' } }
        }
      }
    },
    handler: protocolAgentController.chat
  });
  
  // 确认阶段完成
  fastify.post('/api/aia/protocol-agent/stage/complete', {
    schema: {
      body: {
        type: 'object',
        required: ['conversationId'],
        properties: {
          conversationId: { type: 'string' }
        }
      }
    },
    handler: protocolAgentController.completeStage
  });
  
  // 获取当前Context
  fastify.get('/api/aia/protocol-agent/context/:conversationId', {
    handler: protocolAgentController.getContext
  });
  
  // 更新ContextState Panel编辑
  fastify.patch('/api/aia/protocol-agent/context/:conversationId', {
    schema: {
      body: {
        type: 'object',
        required: ['field', 'value'],
        properties: {
          field: { type: 'string' },
          value: { type: 'object' }
        }
      }
    },
    handler: protocolAgentController.updateContext
  });
  
  // Action Card回调
  fastify.post('/api/aia/protocol-agent/action-callback', {
    schema: {
      body: {
        type: 'object',
        required: ['conversationId', 'cardId', 'result'],
        properties: {
          conversationId: { type: 'string' },
          cardId: { type: 'string' },
          result: { type: 'object' }
        }
      }
    },
    handler: protocolAgentController.handleActionCallback
  });
  
  // 获取追踪日志(调试用)
  fastify.get('/api/aia/protocol-agent/trace/:traceId', {
    handler: protocolAgentController.getTrace
  });
}

4.2 响应格式

// Chat响应
interface ChatResponse {
  traceId: string;
  message: string;
  thinkingContent?: string;
  actionCards: ActionCardPayload[];
  contextUpdate: {
    field: string;
    data: any;
    confidence: number;
  } | null;
  currentStage: string;
  stageStatus: 'in_progress' | 'completed';
  stageProgress: {
    current: number;
    total: number;
    completedStages: string[];
  };
}

// Stage Complete响应
interface StageCompleteResponse {
  success: boolean;
  issues?: string[];
  suggestions?: string[];
  previousStage: string;
  nextStage?: string;
  summary?: string;
  nextStageActionCards?: ActionCardPayload[];
}

// Context响应
interface ContextResponse {
  id: string;
  conversationId: string;
  currentStage: string;
  overallProgress: number;
  completedStages: string[];
  scientificQuestion: any;
  pico: any;
  studyDesign: any;
  sampleSize: any;
  endpoints: any;
  updatedAt: string;
}

五、前端组件设计

5.1 组件结构

apps/web/src/modules/aia/
├── components/
│   ├── ProtocolAgent/
│   │   ├── ProtocolAgentPage.tsx        # 主页面
│   │   ├── ProtocolChat.tsx             # 聊天区域
│   │   ├── StatePanel/
│   │   │   ├── StatePanel.tsx           # 状态面板容器
│   │   │   ├── StageProgress.tsx        # 阶段进度
│   │   │   ├── ContextDisplay.tsx       # Context展示
│   │   │   └── ContextEditor.tsx        # Context编辑
│   │   ├── ActionCard/
│   │   │   ├── ActionCardList.tsx       # Action Card列表
│   │   │   ├── ActionCard.tsx           # 单个Card
│   │   │   └── DeepLinkModal.tsx        # Deep Link弹窗
│   │   └── index.ts
│   └── (existing components)
│
├── hooks/
│   ├── useProtocolAgent.ts              # Protocol Agent Hook
│   ├── useProtocolContext.ts            # Context管理Hook
│   └── useActionCard.ts                 # Action Card Hook
│
├── stores/
│   └── protocolAgentStore.ts            # Zustand Store
│
└── services/
    └── protocolAgentApi.ts              # API调用

5.2 核心Hook

// useProtocolAgent.ts

export function useProtocolAgent(conversationId: string) {
  const [context, setContext] = useState<ProtocolContext | null>(null);
  const [currentStage, setCurrentStage] = useState<string>('scientific_question');
  const [actionCards, setActionCards] = useState<ActionCardPayload[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  
  // 发送消息
  const sendMessage = async (message: string) => {
    setIsLoading(true);
    try {
      const response = await protocolAgentApi.chat(conversationId, message);
      
      // 更新状态
      if (response.contextUpdate) {
        setContext(prev => ({
          ...prev,
          [response.contextUpdate.field]: response.contextUpdate.data
        }));
      }
      setCurrentStage(response.currentStage);
      setActionCards(response.actionCards);
      
      return response;
    } finally {
      setIsLoading(false);
    }
  };
  
  // 确认阶段完成
  const completeStage = async () => {
    const result = await protocolAgentApi.completeStage(conversationId);
    if (result.success && result.nextStage) {
      setCurrentStage(result.nextStage);
      setActionCards(result.nextStageActionCards || []);
    }
    return result;
  };
  
  // 更新Context
  const updateContext = async (field: string, value: any) => {
    await protocolAgentApi.updateContext(conversationId, field, value);
    setContext(prev => ({ ...prev, [field]: value }));
  };
  
  // 处理Action Card点击
  const handleActionCard = async (card: ActionCardPayload) => {
    if (card.actionType === 'deep_link') {
      // 打开Deep Link
      window.open(card.actionUrl, '_blank');
    } else if (card.actionType === 'modal') {
      // 打开弹窗
    }
  };
  
  return {
    context,
    currentStage,
    actionCards,
    isLoading,
    sendMessage,
    completeStage,
    updateContext,
    handleActionCard
  };
}

六、依赖注入设计

// 依赖注入容器配置

export function createProtocolAgentDependencies(
  prisma: PrismaClient,
  llmGateway: LLMGateway
): ProtocolAgentDependencies {
  
  // 基础服务
  const traceLogger = new TraceLogger(prisma);
  const configLoader = new ConfigLoader(prisma);
  const memoryManager = new MemoryManager(prisma);
  const promptBuilder = new PromptBuilder();
  
  // Query层
  const queryAnalyzer = new QueryAnalyzer(llmGateway, promptBuilder);
  
  // Planner层
  const stageManager = new StageManager(configLoader);
  const planner = new Planner(stageManager);
  
  // Executor层
  const toolRegistry = new ToolRegistry();
  const executor = new Executor(llmGateway, toolRegistry, promptBuilder);
  
  // Reflexion层
  const reflexionEngine = new ReflexionEngine(llmGateway, promptBuilder);
  
  // Protocol专用
  const contextService = new ProtocolContextService(prisma);
  const protocolExtractor = new ProtocolExtractor();
  
  return {
    traceLogger,
    configLoader,
    memoryManager,
    queryAnalyzer,
    planner,
    executor,
    reflexionEngine,
    contextService,
    protocolExtractor
  };
}