# 10 - 实施计划详解 (Implementation Plan) ## 1. 总体时间线 ``` Week 1 Week 2 Week 2-3 Week 3 Week 4 Week 5 ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Phase 1 │ │ Phase 2 │ │ Phase 3 │ │ Phase 4 │ │ Phase 5+6│ │ Phase 7 │ │ │ │ │ │ │ │ │ │ │ │ │ │ 架构文档 │──→│ 基础设施 │──→│ 专家Agent│──→│ Coordinator│──→│ 集成+前端│──→│ 测试+优化│ │ + 类型 │ │ │ │ │ │ │ │ │ │ │ │ 定义 │ │ Queue │ │ 6个Agent │ │ 核心Loop │ │ Module │ │ 场景测试 │ │ │ │ Context │ │ 6份Prompt│ │ 主Prompt │ │ Gateway │ │ 性能优化 │ │ │ │ Base │ │ │ │ │ │ Frontend │ │ 旧代码清理│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ``` ## 2. Phase 1: 架构文档 + 类型定义 (Week 1) ### 2.1 架构文档(12份) | 序号 | 文件 | 内容 | 状态 | |------|------|------|------| | 00 | `00-overview.md` | 总览 + 架构图 | ✅ 已完成 | | 01 | `01-coordinator-agent.md` | Coordinator 设计 | ✅ 已完成 | | 02 | `02-specialist-agents.md` | 6 个专家 Agent 设计 | 待完成 | | 03 | `03-agent-communication.md` | Agent 间通信协议 | 待完成 | | 04 | `04-streaming-protocol.md` | 流式传输协议 | 待完成 | | 05 | `05-frontend-integration.md` | 前端集成方案 | 待完成 | | 06 | `06-token-cost-management.md` | Token 与成本管理 | 待完成 | | 07 | `07-testing-strategy.md` | 测试策略 | 待完成 | | 08 | `08-context-injection.md` | 动态上下文注入 | ✅ 已完成 | | 09 | `09-tool-execution.md` | 工具并发执行 | ✅ 已完成 | | 10 | `10-implementation-plan.md` | 实施计划(本文档) | ✅ 已完成 | | 11 | `11-prompt-templates.md` | 所有 Prompt 模板 | ✅ 已完成 | ### 2.2 类型定义文件 需要创建以下类型定义文件: ``` packages/services/conversation-service/src/infrastructure/agents/ ├── types/ │ ├── agent.types.ts # Agent 相关类型 │ ├── stream.types.ts # 流式事件类型 │ └── context.types.ts # 上下文注入类型 ``` **agent.types.ts**: ```typescript // 核心 Agent 类型定义 /** Agent 名称枚举 */ export enum AgentName { COORDINATOR = 'coordinator', POLICY_EXPERT = 'policy_expert', ASSESSMENT_EXPERT = 'assessment_expert', STRATEGIST = 'strategist', OBJECTION_HANDLER = 'objection_handler', CASE_ANALYST = 'case_analyst', MEMORY_MANAGER = 'memory_manager', } /** Agent 使用的模型 */ export enum AgentModel { SONNET = 'claude-sonnet-4-20250514', HAIKU = 'claude-haiku-4-20250514', } /** Agent 配置 */ export interface AgentConfig { name: AgentName; model: AgentModel; maxTokens: number; maxTurns: number; // Agent mini-loop 最大轮次 timeoutMs: number; // 超时时间 tools: string[]; // 可用工具名列表 systemPromptFile: string; // Prompt 文件路径 } /** Agent 执行上下文 */ export interface AgentExecutionContext { userId: string; conversationId: string; coordinatorTurn: number; // Coordinator 当前轮次 parentToolUseId: string; // 触发此 Agent 的 tool_use ID } /** Agent Loop 参数 */ export interface AgentLoopParams { messages: Anthropic.MessageParam[]; systemPrompt: string[] | Anthropic.TextBlockParam[]; tools: Anthropic.Tool[]; maxTurns: number; maxBudgetUsd: number; conversationId: string; userId: string; abortSignal?: AbortSignal; } /** 咨询状态(从 consulting_state XML tag 提取) */ export interface ConsultingStateReport { currentStage: string; collectedFields: string[]; nextAction: string; confidenceLevel: 'low' | 'medium' | 'high'; recommendedPrograms?: string[]; } ``` **stream.types.ts**: ```typescript // 流式事件类型 /** 所有可能的 Stream 事件 */ export type StreamEvent = | TextStreamEvent | AgentStartEvent | AgentProgressEvent | AgentCompleteEvent | ToolStartEvent | ToolCompleteEvent | ToolErrorEvent | StateUpdateEvent | UsageEvent | ErrorEvent | EndEvent; export interface TextStreamEvent { type: 'text'; content: string; } export interface AgentStartEvent { type: 'agent_start'; agentName: string; toolUseId: string; } export interface AgentProgressEvent { type: 'agent_progress'; agentName: string; turn: number; maxTurns: number; } export interface AgentCompleteEvent { type: 'agent_complete'; agentName: string; durationMs: number; tokensUsed?: { input: number; output: number }; } export interface StateUpdateEvent { type: 'state_update'; state: ConsultingStateReport; } export interface UsageEvent { type: 'usage'; usage: { inputTokens: number; outputTokens: number }; totalCostUsd: number; } export interface ErrorEvent { type: 'error'; code: string; message: string; } export interface EndEvent { type: 'end'; totalTokens: { input: number; output: number }; totalCostUsd: number; turnsUsed: number; agentsCalled: string[]; } ``` **context.types.ts**: - 详见 [08-context-injection.md](./08-context-injection.md) 第 3 节 **交付标准**: - 所有类型文件通过 `tsc --noEmit` 类型检查 - 每个 interface 有 JSDoc 注释 - 导出为 barrel file (`types/index.ts`) ## 3. Phase 2: 基础设施 (Week 2) ### 3.1 文件结构 ``` packages/services/conversation-service/src/infrastructure/agents/ ├── types/ # Phase 1 产物 │ ├── agent.types.ts │ ├── stream.types.ts │ ├── context.types.ts │ └── index.ts ├── core/ # Phase 2 产物 │ ├── tool-execution-queue.ts # 工具并发执行队列 │ ├── context-injector.service.ts # 上下文注入器 │ ├── base-specialist.service.ts # 专家 Agent 基类 │ ├── agent-executor.ts # Agent 执行器工厂 │ └── token-tracker.ts # Token 追踪器 ``` ### 3.2 tool-execution-queue.ts - 完整实现详见 [09-tool-execution.md](./09-tool-execution.md) 第 4 节 - **关键依赖**: `tool-execution.types.ts` - **单测覆盖**: - 纯并发批次(所有 safe 工具) - 纯串行批次(所有 unsafe 工具) - 混合批次(safe + unsafe 交替) - 单个工具超时 - 批次中一个工具失败 - 空请求 - 结果排序正确性 ```typescript // 单测示例 describe('ToolExecutionQueue', () => { it('should execute concurrent-safe tools in parallel', async () => { const queue = new ToolExecutionQueue(); const executionOrder: string[] = []; queue.registerTool('tool_a', { isConcurrencySafe: true, executor: async () => { executionOrder.push('a_start'); await sleep(100); executionOrder.push('a_end'); return { content: 'a', success: true }; }, // ... }); queue.registerTool('tool_b', { isConcurrencySafe: true, executor: async () => { executionOrder.push('b_start'); await sleep(50); executionOrder.push('b_end'); return { content: 'b', success: true }; }, // ... }); const results = await queue.executeAll([ { toolUseId: '1', toolName: 'tool_a', input: {}, originalIndex: 0 }, { toolUseId: '2', toolName: 'tool_b', input: {}, originalIndex: 1 }, ]); // 两个工具应该几乎同时开始 expect(executionOrder[0]).toBe('a_start'); expect(executionOrder[1]).toBe('b_start'); // b 先完成(50ms vs 100ms) expect(executionOrder[2]).toBe('b_end'); expect(executionOrder[3]).toBe('a_end'); // 结果按 originalIndex 排序 expect(results[0].toolName).toBe('tool_a'); expect(results[1].toolName).toBe('tool_b'); }); }); ``` ### 3.3 context-injector.service.ts - 完整实现详见 [08-context-injection.md](./08-context-injection.md) 第 5 节 - **关键依赖**: `KnowledgeClientService`, `context.types.ts` - **单测覆盖**: - 所有 8 种上下文的独立构建 - 缓存命中/未命中 - Token 预算裁剪 - P0 上下文不被裁剪 - 缓存失效 - auto-compaction 触发条件 ### 3.4 base-specialist.service.ts - 完整实现详见 [09-tool-execution.md](./09-tool-execution.md) 第 6 节 - **关键依赖**: `@anthropic-ai/sdk` - **单测覆盖**: - Mini-loop 正常完成(1轮无工具调用) - Mini-loop 有工具调用(2轮) - 达到 maxTurns 强制终止 - API 错误处理 - Token 追踪回调 ### 3.5 交付标准 - 所有基础设施组件可以独立运行单测 - 不依赖具体的 Specialist Agent 实现 - 使用 mock 的 Claude API 进行测试 ## 4. Phase 3: 专家 Agent (Week 2-3) ### 4.1 文件结构 ``` packages/services/conversation-service/src/infrastructure/agents/ ├── specialists/ │ ├── policy-expert.service.ts # 政策专家 │ ├── assessment-expert.service.ts # 评估专家 │ ├── strategist.service.ts # 策略顾问 │ ├── objection-handler.service.ts # 异议处理 │ ├── case-analyst.service.ts # 案例分析 │ └── memory-manager.service.ts # 记忆管理 ├── prompts/ │ ├── coordinator-system-prompt.ts # Phase 4 │ ├── policy-expert-prompt.ts │ ├── assessment-expert-prompt.ts │ ├── strategist-prompt.ts │ ├── objection-handler-prompt.ts │ ├── case-analyst-prompt.ts │ └── memory-manager-prompt.ts ``` ### 4.2 各 Agent 实现计划 | Agent | 继承 | Model | 工具 | 预估代码量 | 优先级 | |-------|------|-------|------|-----------|--------| | `PolicyExpertService` | `BaseSpecialistService` | Sonnet | `search_knowledge` | ~120 行 | P0 | | `AssessmentExpertService` | `BaseSpecialistService` | Sonnet | `search_knowledge`, `get_user_context` | ~200 行 | P0 | | `MemoryManagerService` | `BaseSpecialistService` | Haiku | `save_user_memory`, `get_user_context` | ~150 行 | P0 | | `StrategistService` | `BaseSpecialistService` | Sonnet | `get_user_context` | ~100 行 | P1 | | `ObjectionHandlerService` | `BaseSpecialistService` | Sonnet | `search_knowledge`, `get_user_context` | ~120 行 | P1 | | `CaseAnalystService` | `BaseSpecialistService` | Haiku | `search_knowledge`, `get_user_context` | ~100 行 | P2 | ### 4.3 开发顺序 建议按以下顺序开发(优先级 + 依赖关系): ``` 1. MemoryManagerService → 最简单,验证 BaseSpecialist + 工具执行 ↓ 2. PolicyExpertService → 最常用,验证 knowledge-service 集成 ↓ 3. AssessmentExpertService → 核心业务,需要 knowledge + 用户上下文 ↓ 4. StrategistService → 辅助 Coordinator 决策 ↓ 5. ObjectionHandlerService → 异议处理,依赖 knowledge ↓ 6. CaseAnalystService → 最后实现,依赖度最低 ``` ### 4.4 每个 Agent 的独立测试策略 ```typescript // 以 PolicyExpertService 为例的独立测试 describe('PolicyExpertService', () => { let service: PolicyExpertService; let mockAnthropicClient: jest.Mocked; let mockKnowledgeClient: jest.Mocked; beforeEach(() => { mockAnthropicClient = createMockAnthropicClient(); mockKnowledgeClient = createMockKnowledgeClient(); service = new PolicyExpertService(mockAnthropicClient, mockKnowledgeClient); }); it('should answer policy questions without tool calls', async () => { // Mock: Claude 直接回答,不调用工具 mockAnthropicClient.messages.create.mockResolvedValue({ content: [{ type: 'text', text: '高才通B类要求...' }], usage: { input_tokens: 500, output_tokens: 200 }, stop_reason: 'end_turn', }); const result = await service.execute({ input: { query: '高才通B类条件是什么' }, maxTurns: 3, }); expect(result.output).toContain('高才通'); expect(result.turnsUsed).toBe(1); }); it('should use search_knowledge tool when needed', async () => { // Mock: Claude 调用 search_knowledge,再用结果生成回答 mockAnthropicClient.messages.create .mockResolvedValueOnce({ content: [ { type: 'tool_use', id: 't1', name: 'search_knowledge', input: { query: 'TTPS B类 条件' } }, ], usage: { input_tokens: 500, output_tokens: 100 }, stop_reason: 'tool_use', }) .mockResolvedValueOnce({ content: [{ type: 'text', text: '根据查询结果,高才通B类...' }], usage: { input_tokens: 800, output_tokens: 300 }, stop_reason: 'end_turn', }); mockKnowledgeClient.retrieveKnowledge.mockResolvedValue({ content: '高才通B类要求全球百强大学学士学位...', sources: [{ articleId: '1', title: '高才通指南', similarity: 0.92 }], }); const result = await service.execute({ input: { query: '高才通B类条件' }, maxTurns: 3, onToolCall: jest.fn(), }); expect(result.output).toContain('根据查询结果'); expect(result.turnsUsed).toBe(2); expect(mockKnowledgeClient.retrieveKnowledge).toHaveBeenCalled(); }); }); ``` ### 4.5 交付标准 - 每个 Agent 有独立的单元测试(mock Claude API + mock 外部服务) - 每个 Agent 的 Prompt 是独立文件,可以独立调整 - 所有 Agent 通过 `BaseSpecialistService.execute()` 统一调用 ## 5. Phase 4: Coordinator (Week 3) ### 5.1 文件结构 ``` packages/services/conversation-service/src/infrastructure/agents/ ├── coordinator/ │ ├── coordinator-agent.service.ts # 主服务 │ ├── agent-loop.ts # 核心递归循环 │ └── state-extractor.ts # 从回复中提取 consulting_state ├── prompts/ │ └── coordinator-system-prompt.ts # 500+ 行 Prompt ``` ### 5.2 coordinator-system-prompt.ts 这是整个系统最重要的文件,详见 [11-prompt-templates.md](./11-prompt-templates.md)。 关键结构: ```typescript export function buildCoordinatorSystemPrompt(config: { expertContact: { wechat: string; phone: string; workingHours: string }; paidServices: { assessmentPrice: number; description: string }; currentDate: string; }): string { return ` # 身份定义 ...(约 30 行) # 你的专家团队 ...(约 80 行) # 六大移民类别 ...(约 200 行) # 对话策略 ...(约 100 行) # 回复规范 ...(约 40 行) # 状态报告格式 ...(约 30 行) # 业务规则 ...(约 20 行) `; } ``` ### 5.3 agent-loop.ts 核心递归循环,详见 [01-coordinator-agent.md](./01-coordinator-agent.md) 第 4 节。 关键特性: - `async function* agentLoop()`: AsyncGenerator 模式 - 递归调用自身(tool_results → 再次调用 Claude) - 集成 ContextInjector - 集成 ToolExecutionQueue - 集成 state extractor - abort 信号支持 ### 5.4 coordinator-agent.service.ts NestJS 服务,封装 agent-loop,对外暴露与旧 `ClaudeAgentServiceV2` 相同的接口: ```typescript @Injectable() export class CoordinatorAgentService { constructor( private contextInjector: ContextInjectorService, private toolExecutionQueue: ToolExecutionQueue, // ... 各 Specialist Agent ) {} async *sendMessage(params: { conversationContext: ConversationContext; userMessage: string; attachments?: FileAttachment[]; userId: string; conversationId: string; deviceInfo?: DeviceInfo; }): AsyncGenerator { // 委托给 agentLoop yield* agentLoop({ messages: this.buildMessages(params), systemPrompt: this.buildSystemPrompt(), tools: this.toolExecutionQueue.getClaudeTools(), maxTurns: 15, maxBudgetUsd: 0.50, conversationId: params.conversationId, userId: params.userId, }); } } ``` ### 5.5 交付标准 - Coordinator 可以独立运行集成测试(使用真实 Claude API) - agent-loop 有完整的单元测试(mock API) - System Prompt 经过人工审查 - 通过 5 个核心对话场景的 E2E 测试 ## 6. Phase 5: 集成 (Week 4 前半) ### 6.1 NestJS Module 集成 **新增 agents.module.ts**: ```typescript // packages/services/conversation-service/src/infrastructure/agents/agents.module.ts @Module({ imports: [KnowledgeModule], // 依赖 KnowledgeClientService providers: [ // Core ToolExecutionQueue, ContextInjectorService, // Specialists PolicyExpertService, AssessmentExpertService, StrategistService, ObjectionHandlerService, CaseAnalystService, MemoryManagerService, // Coordinator CoordinatorAgentService, ], exports: [CoordinatorAgentService], }) export class AgentsModule {} ``` **修改 claude.module.ts**: ```typescript // 在 claude.module.ts 中导入 AgentsModule @Module({ imports: [AgentsModule], // 新增 providers: [ ClaudeAgentServiceV2, // 保留旧服务(过渡期) // ... ], exports: [ ClaudeAgentServiceV2, // 保留旧导出 CoordinatorAgentService, // 新增导出 ], }) export class ClaudeModule {} ``` **修改 conversation.service.ts**: ```typescript // 切换注入(使用 feature flag) @Injectable() export class ConversationService { constructor( @Inject(CONVERSATION_REPOSITORY) private readonly conversationRepo: IConversationRepository, @Inject(MESSAGE_REPOSITORY) private readonly messageRepo: IMessageRepository, // 旧服务(过渡期保留) private readonly claudeAgentService: ClaudeAgentServiceV2, // 新服务 private readonly coordinatorAgentService: CoordinatorAgentService, private readonly configService: ConfigService, ) {} private get useNewArchitecture(): boolean { return this.configService.get('USE_MULTI_AGENT', false); } async *sendMessage(params: SendMessageParams): AsyncGenerator { if (this.useNewArchitecture) { yield* this.sendMessageV3(params); // 新架构 } else { yield* this.sendMessageV2(params); // 旧架构 } } } ``` **更新 conversation.gateway.ts**: ```typescript // 新增 Agent 相关的 WebSocket 事件 // stream_chunk 保持不变 // 新增: // agent_start { agentName, conversationId } // agent_progress { agentName, turn, maxTurns, conversationId } // agent_complete { agentName, durationMs, conversationId } ``` ### 6.2 Feature Flag 策略 ``` 环境变量: USE_MULTI_AGENT=true/false 开发环境: true (直接使用新架构) 测试环境: true (测试新架构) 生产环境: false (等全部测试通过后切换) ``` ### 6.3 共享类型更新 ```typescript // packages/shared/types/src/conversation.ts // 新增 StreamEvent 类型供前端使用 export interface AgentStatusEvent { type: 'agent_start' | 'agent_progress' | 'agent_complete'; agentName: string; conversationId: string; // agent_progress only turn?: number; maxTurns?: number; // agent_complete only durationMs?: number; } ``` ### 6.4 交付标准 - Feature flag 可以在不重启服务的情况下切换 - 旧架构在 `USE_MULTI_AGENT=false` 时完全不受影响 - WebSocket 事件向后兼容(新事件是追加的,不修改已有事件) ## 7. Phase 6: 前端 (Week 4 后半) ### 7.1 前端文件修改 ``` packages/clients/web-client/src/ ├── stores/ │ └── chatStore.ts # 新增 agentStatus 状态 ├── components/ │ ├── chat/ │ │ ├── ChatWindow.tsx # 处理新的 WebSocket 事件 │ │ ├── MessageBubble.tsx # 可能需要微调 │ │ └── AgentStatus.tsx # 新增:Agent 工作状态组件 │ └── shared/ │ └── AgentBadge.tsx # 新增:Agent 名称+状态徽章 ``` ### 7.2 chatStore 更新 ```typescript // chatStore.ts (Zustand) interface AgentStatus { name: string; displayName: string; // 中文显示名 status: 'idle' | 'working' | 'completed'; startedAt?: number; completedAt?: number; durationMs?: number; } interface ChatState { // 已有状态... messages: Message[]; isStreaming: boolean; // 新增:Agent 状态 activeAgents: AgentStatus[]; agentHistory: AgentStatus[]; // 本次对话中所有 Agent 调用记录 } // Agent 名称映射 const AGENT_DISPLAY_NAMES: Record = { policy_expert: '政策专家', assessment_expert: '评估专家', strategist: '策略顾问', objection_handler: '异议处理', case_analyst: '案例分析', memory_manager: '记忆管理', }; ``` ### 7.3 AgentStatus 组件 ```tsx // AgentStatus.tsx // 显示在聊天窗口中,消息气泡和输入框之间 function AgentStatus({ agents }: { agents: AgentStatus[] }) { const workingAgents = agents.filter(a => a.status === 'working'); if (workingAgents.length === 0) return null; return (
{workingAgents.map(agent => (
🔄 {agent.displayName} {formatElapsedTime(Date.now() - (agent.startedAt || 0))}
))} 正在分析中...
); } ``` ### 7.4 ChatWindow 事件处理 ```typescript // ChatWindow.tsx - WebSocket 事件处理更新 socket.on('agent_start', (data: { agentName: string; conversationId: string }) => { chatStore.addActiveAgent({ name: data.agentName, displayName: AGENT_DISPLAY_NAMES[data.agentName] || data.agentName, status: 'working', startedAt: Date.now(), }); }); socket.on('agent_complete', (data: { agentName: string; durationMs: number }) => { chatStore.completeAgent(data.agentName, data.durationMs); }); socket.on('stream_end', () => { chatStore.clearActiveAgents(); // 清除所有工作中的 Agent 状态 }); ``` ### 7.5 交付标准 - Agent 状态在 UI 中实时显示 - Agent 完成后自动消失(带淡出动画) - 在弱网环境下不会出现 Agent 状态 "卡住" 的问题(超时自动清除) - 旧架构模式下不显示 Agent 状态 ## 8. Phase 7: 测试 + 优化 + 清理 (Week 5) ### 8.1 测试场景矩阵 | 场景编号 | 场景描述 | 涉及 Agent | 预期行为 | |----------|---------|-----------|---------| | S01 | 新用户首次咨询 | Coordinator + Memory | 破冰 → 收集信息 → 保存记忆 | | S02 | 询问高才通条件 | Coordinator + Policy | 检索知识库 → 准确回答 | | S03 | 信息收集后评估 | Coordinator + Assessment + Memory | 评估资格 → 推荐方案 | | S04 | 用户表示犹豫 | Coordinator + Objection + Strategist | 识别异议 → 策略回应 | | S05 | 用户要求付费评估 | Coordinator + (Payment tool) | 生成支付链接 | | S06 | 老用户回访 | Coordinator + Memory | 加载历史记忆 → 个性化问候 | | S07 | 并发工具调用 | Coordinator + Policy + Case | 并行执行两个 Agent | | S08 | 超长对话 (30+ 轮) | All | Auto-compaction 触发 | | S09 | API 错误恢复 | Coordinator | 降级到 Haiku / 友好错误 | | S10 | 用户中途取消 | Coordinator | AbortSignal 生效 | ### 8.2 性能优化清单 | 优化项 | 目标 | 方法 | |--------|------|------| | 首次回复延迟 | < 3s | Prompt Caching + 预热 | | 并发 Agent 延迟 | < 5s (3 个 Agent 并行) | ToolExecutionQueue 并行 | | Context Injection 延迟 | < 200ms | 缓存 + 并行获取 | | Auto-compaction 延迟 | < 2s | Haiku 摘要 | | Token 成本 (每对话) | < $0.30 | Haiku for 辅助 Agent + Caching | | 内存使用 | < 100MB per 1000 并发对话 | 对话结束清理缓存 | ### 8.3 旧代码清理计划 **阶段 A: 标记废弃 (Week 5)** ```typescript // 不删除代码,只标记 @deprecated /** @deprecated Use CoordinatorAgentService instead. Will be removed in v4. */ export class ClaudeAgentServiceV2 { ... } /** @deprecated Replaced by Coordinator Prompt. */ export class StrategyEngineService { ... } /** @deprecated Intent classification now handled by LLM. */ export const intentClassifier = { ... }; /** @deprecated Response quality now handled by Prompt. */ export const responseGate = { ... }; ``` **阶段 B: 删除代码 (Week 6+, after 1 week in production)** - 删除 `strategy-engine.service.ts` - 删除 `intent-classifier.ts` - 删除 `response-gate.ts` - 删除 `default-strategy.ts` - 删除 `claude-agent-v2.service.ts` - 移除 feature flag ### 8.4 Rollback 计划 ``` 如果新架构在生产中出现严重问题: 1. 即时回滚 (< 1 分钟): 设置环境变量 USE_MULTI_AGENT=false → 自动切回 ClaudeAgentServiceV2 → 不需要重新部署 2. 部署回滚 (< 5 分钟): git revert 到 Phase 5 之前的 commit → 重新部署 conversation-service 3. 数据恢复: 新架构不修改数据库 schema ConsultingState 格式向后兼容 → 无需数据迁移 ``` ## 9. 组件依赖图 ``` ┌─────────────────┐ │ agents.module │ └────────┬────────┘ │ exports ┌────────────▼────────────┐ │ CoordinatorAgentService │ └────────────┬────────────┘ │ depends on ┌──────────────────┼──────────────────┐ │ │ │ ┌────────▼───────┐ ┌────────▼────────┐ ┌───────▼────────┐ │ ContextInjector │ │ ToolExecution │ │ agentLoop() │ │ Service │ │ Queue │ │ (function) │ └────────┬───────┘ └────────┬────────┘ └───────┬────────┘ │ │ │ ┌────────▼───────┐ ┌────────▼────────┐ │ │ Knowledge │ │ Agent Executors │ │ │ ClientService │ │ (factory) │ │ └────────────────┘ └────────┬────────┘ │ │ │ ┌───────▼───────────────────┘ │ ┌─────────▼─────────┐ │ BaseSpecialist │ │ Service (abstract) │ └─────────┬─────────┘ │ extends ┌───────┬───────┬───┴───┬───────┬───────┐ │ │ │ │ │ │ Policy Assess Strat Object Case Memory Expert Expert gist Handler Analyst Manager ``` ## 10. 风险与缓解 | 风险 | 概率 | 影响 | 缓解措施 | |------|------|------|---------| | Coordinator Prompt 效果不佳 | 高 | 高 | Phase 4 投入大量时间测试 Prompt,准备多个版本 A/B 测试 | | Token 成本超预期 | 中 | 中 | 监控每次对话成本,设置 maxBudgetUsd 硬上限 | | 并发 Agent 导致 Rate Limit | 中 | 中 | 实现指数退避重试,降级到 Haiku | | Context Window 不够用 | 低 | 高 | Auto-compaction + 严格的 token 预算 | | 前端 Agent 状态同步问题 | 中 | 低 | WebSocket 事件超时自动清理 | | 旧代码删除导致回归 | 低 | 高 | Feature flag 过渡期,完善的回滚计划 | ## 11. 交付 Checklist ### Phase 1 Checklist - [ ] 12 份架构文档全部完成 - [ ] `agent.types.ts` 通过类型检查 - [ ] `stream.types.ts` 通过类型检查 - [ ] `context.types.ts` 通过类型检查 - [ ] 所有类型有 JSDoc 注释 ### Phase 2 Checklist - [ ] `ToolExecutionQueue` 通过所有单元测试 - [ ] `ContextInjectorService` 通过所有单元测试 - [ ] `BaseSpecialistService` 通过所有单元测试 - [ ] 所有组件可以独立测试(不依赖 Claude API) ### Phase 3 Checklist - [ ] 6 个 Specialist Agent 全部实现 - [ ] 6 份 Prompt 文件全部编写 - [ ] 每个 Agent 有独立的单元测试 - [ ] 每个 Agent 使用真实 API 的集成测试(可选,按需运行) ### Phase 4 Checklist - [ ] Coordinator System Prompt 完成(500+ 行) - [ ] agent-loop 通过所有单元测试 - [ ] CoordinatorAgentService 通过集成测试 - [ ] 5 个核心场景 E2E 测试通过 ### Phase 5 Checklist - [ ] `agents.module.ts` 编写完成 - [ ] Feature flag 切换工作正常 - [ ] 旧架构在 flag=false 时不受影响 - [ ] WebSocket 事件向后兼容 ### Phase 6 Checklist - [ ] chatStore 更新完成 - [ ] AgentStatus 组件实现 - [ ] ChatWindow 处理新事件 - [ ] 前端无 regression ### Phase 7 Checklist - [ ] 10 个测试场景全部通过 - [ ] 性能指标达标 - [ ] 旧代码标记 @deprecated - [ ] 回滚计划验证通过 - [ ] 文档更新完成