fischer-agentkit/docs/plans/2026-06-30-002-refactor-sys...

28 KiB
Raw Permalink Blame History

title date type depth origin deepened
refactor: 系统性技术债清理 2026-06-30 refactor deep 综合评审报告(双 agent 评审 2026-06-30 2026-06-30

refactor: 系统性技术债清理

Summary

针对综合评审识别的 5 项系统性技术债制定分阶段重构 planReActEngine 流式/非流式 ~800 行重复、TeamOrchestrator 2080 行上帝类、except Exception 345+ 处滥用(聚焦 core//experts/ 关键路径)、Any 类型残留bitable/ 33 处等)、前端 chat.ts 2025 行巨型文件。通过 characterization-first 重构策略,在测试保障下消除架构契约脱节、恢复类型契约、拆分上帝类。

Problem Frame

综合评审3.78/5发现项目在安全性4.5和文档4.5表现优秀但代码质量3.0和生产就绪度3.5存在系统性技术债。P0/P1 项Dockerfile、jieba、OTel、验收降级标注、skill_routing Any已修复但以下 5 项属于大规模重构,需独立 plan 排期:

  1. ReActEngine 契约脱节execute() ~130 行与 execute_stream() ~800 行约 80% 逻辑重复,_execute_loop 已存在但 execute_stream 未复用,文档注释自认"Same logic as execute()"。stream 版有 _drain_phase_violations 而 execute 版无——行为漂移。
  2. TeamOrchestrator 上帝类:单文件 2080 行、37 个方法、8 项职责(任务分解/阶段执行/辩论/验收/分歧检测/回滚/综合/干预),_execute_execution_phase 单方法 ~290 行。
  3. except Exception 关键路径降级:全项目 345+ 处/100 文件,其中 core/ + experts/ 关键路径react.py 23、rewoo.py 21、base.py 12、orchestrator.py 20 等)存在验收 LLM 失败静默降级为"自动通过",无声绕过质量门。已加 [DEGRADED] 标注,但需结构性整改。
  4. Any 类型残留bitable/33 处/8 文件service.py 6、db.py 6、repository.py 5、formula/functions.py 7、formula/parser.py 4、recalc_worker.py 2、ingestion/database.py 2、ingestion/excel.py 1、pipeline_state.py9 处、tools/computer_use_session.py8 处)等,违反 AGENTS.md "禁止 any 类型"。
  5. 前端 chat.ts 巨型文件2025 行、20+ 内部函数,handleWsMessage 单函数处理 10+ 事件类型vitest 仅 3 个测试。

Requirements

  • R1ReActEngine executeexecute_stream 共用同一循环骨架,消除 80% 重复代码行为等价golden trajectory 验证)
  • R2TeamOrchestrator 按职责拆分为 ≤7 个模块,主类 ≤600 行,单方法 ≤100 行
  • R3:关键路径(core/experts/)的 except Exception 禁止静默降级为"自动通过",必须返回 passed=Falsedegraded=True 结构化标记
  • R4bitable/、pipeline_state.py、tools/computer_use_session.py 的 Any 替换为具体类型或 object
  • R5:前端 chat.ts 拆分为 chatSocket/chatStream/chatStore 三个模块,每个 ≤500 行vitest 覆盖 handleWsMessage discriminated union
  • R6所有重构在现有测试5989 单测)基础上不引入回归,关键路径补充 characterization/golden 测试

Scope Boundaries

In Scope

  • ReActEngine _execute_loop 事件回调驱动重构
  • TeamOrchestrator 按职责拆分为协作模块
  • except Exceptioncore/experts/ 目录的关键路径整改
  • Any 在 bitable/、pipeline_state.py、tools/computer_use_session.py 的治理
  • 前端 chat.ts 拆分 + 关键路径 vitest 补充

Out of Scope

  • 功能变更或新功能开发
  • except Exceptionserver/routes/portal.py 19 处、chat.py 16 处的全量整改——deferred to follow-up
  • Any 在其他模块llm/、memory/ 等的残留——deferred to follow-up
  • ReActEngine 流式路径的 _drain_phase_violations 行为对齐到 execute——属 R1 行为等价验证范围,但修复本身 deferred
  • 前端 a11y 全量补齐(已修 AssistantText其余 deferred
  • OTel exporter 实际启用(已加配置注释,启用 deferred

Deferred to Follow-Up Work

  • server/routes/except Exception 整治portal.py 19、chat.py 16——独立 PR
  • llm/memory/client/Any 残留治理——独立 PR
  • bitable/ 内部 Any 残留repository.py 5、recalc_worker.py 2、ingestion/database.py 2、ingestion/excel.py 1共 10 处)——独立 PR
  • 前端 a11y 全量扫描与补齐——独立前端专项
  • OTel exporter 启用 + Grafana dashboard 模板——独立运维任务

Key Technical Decisions

KTD1: ReActEngine 重构采用 async generator 统一骨架

决策:将 _execute_loop 改为 async generator始终 yield ReActEventexecute 收集所有事件并从最终事件提取 ReActResultexecute_stream 直接 async for 透传事件。

理由_execute_loop 已是独立方法529-1174execute_stream 未复用。async generator 是 Python 原生模式,无需 callback/queue 桥接,最简洁。ReActEvent 已存在line 130event_type: str 字符串字段,无 EventType 枚举),在 event_type 字段新增 'final_result' 字符串值、在 data dict 中携带 ReActResult 即可——无需新建枚举类型。

替代方案:事件回调(event_sink: Callable | None)——需 queue 桥接 async generator 与 coroutine复杂度高违反 ponytail。

KTD2: TeamOrchestrator 拆分为 Mixin 而非独立类

决策:采用 mixin 模式拆分 TeamOrchestrator——PhaseExecutorMixinDebateRunnerMixinReviewGateMixinDivergenceDetectorMixinRollbackHandlerMixinSynthesizerMixinInterventionHandlerMixin,主类组合这些 mixin。

理由37 个方法大量访问 self._expertsself._workspaceself._broadcast_event 等共享状态拆分为独立类需注入大量依赖或改用组合模式改动面大、回归风险高。Mixin 保持 self 访问,改动最小,符合 ponytail"最小代码"原则。

替代方案:组合模式(独立类 + 依赖注入——更解耦但改动面大deferred to follow-up。

KTD3: except Exception 整改采用"分级降级"策略

决策:关键路径(验收/质量门)的 except Exception 改为捕获具体异常(LLMGatewayErrorasyncio.TimeoutError 等),降级路径返回 passed=True, degraded=True 结构化标记(而非字符串前缀),让调用方可编程判断。

理由:已加 [DEGRADED] 字符串前缀,但字符串匹配脆弱。结构化 degraded 字段让 _execute_execution_phase 可在广播事件中体现降级状态,运维可监控。

KTD4: Any 治理采用 object + TYPE_CHECKING Protocol 模式

决策:对无法直接导入具体类型(循环依赖)的 Any,替换为 object + 在 TYPE_CHECKING 块中定义 Protocol 描述期望接口对可直接导入的类型bitable/ 内部模型),替换为具体 Pydantic 模型。

理由object 是最严格的"任意类型",禁止属性访问,强制使用 getattr 或 cast。Protocol 在类型检查时提供接口契约,运行时零开销。

KTD5: 前端 chat.ts 按职责层拆分

决策:拆分为 chatSocket.tsWebSocket 连接/心跳/重连)、chatStream.ts(流式步骤聚合/事件分发)、chatStore.ts(会话/消息状态/computedhandleWsMessage 的事件分发逻辑提取到 chatStream.tsdispatchWsEvent 函数。

理由:现有 20+ 函数可清晰按职责分组,拆分后每个文件 ≤500 行,可独立测试。

KTD6: Characterization-first 执行姿态

决策U1ReActEngine和 U2TeamOrchestrator在重构前先补充 characterization/golden 测试,锁定现有行为,再执行重构。

理由:核心引擎重构高风险,现有测试虽多但 mock 密度高(评审报告),流式路径缺乏 golden trajectory 快照。先锁行为再重构是安全底线。

High-Level Technical Design

ReActEngine 事件回调驱动重构U1

flowchart TD
    A[execute 入口] --> B[_execute_loop async generator]
    C[execute_stream 入口] --> B
    B --> D{每个步骤}
    D --> E[yield ReActEvent]
    E --> F[Think: LLM 调用]
    F --> G[Act: 工具执行]
    G --> H[Observe: 结果回灌]
    H --> I{停止条件?}
    I -->|否| D
    I -->|是| J[yield 'final_result' event]
    A --> K[收集所有 events\n提取 ReActResult]
    C --> L[async for 透传 events]

TeamOrchestrator Mixin 拆分U2

graph TB
    subgraph TeamOrchestrator[主类 ≤600 行]
        EX[execute / _run_pipeline / resume]
        DC[_decompose_task / _parse_phases]
        UT[共享状态: _experts / _workspace / _broadcast_event]
    end

    subgraph Mixins
        PE[PhaseExecutorMixin\n阶段执行 + 隔离 agent]
        DR[DebateRunnerMixin\n辩论 5 阶段]
        RG[ReviewGateMixin\n验收 + risk_flags]
        DD[DivergenceDetectorMixin\n分歧检测 + 插入辩论]
        RH[RollbackHandlerMixin\n依赖失败 + 回滚]
        SY[SynthesizerMixin\n综合 + 单 agent 回退]
        IH[InterventionHandlerMixin\n用户干预]
    end

    TeamOrchestrator -.组合.-> Mixins

Implementation Units

U1. ReActEngine 事件回调驱动重构

Goal: 将 _execute_loop 改为 async generatorexecuteexecute_stream 共用同一骨架,消除 80% 重复代码。

Requirements: R1, R6

Dependencies: 无(首个单元)

Files:

  • src/agentkit/core/react.py — 重构 _execute_loopexecuteexecute_streamReActEvent 扩展 'final_result' 事件值
  • tests/unit/test_react_engine.py — 补充 golden trajectory 测试
  • tests/unit/test_react_token_streaming.py — 验证流式行为等价

Approach:

  1. 扩展 ReActEventline 130event_type: str 字符串字段)增加 'final_result' 字符串值,在 data dict 中携带 ReActResult(不新建 EventType 枚举)
  2. _execute_loop529-1174改为 async generator在每个关键节点think/act/observe/phase_violation/compressyield ReActEvent,结束时 yield ReActEvent(event_type='final_result', data={'result': final_result})
  3. execute396-527改为 [e async for e in self._execute_loop(...)],从最后一个 event 提取 ReActResult 返回
  4. execute_stream1176-1989改为 async for event in self._execute_loop(...): yield event,删除 ~800 行重复逻辑
  5. 合并 _drain_phase_violations 差异:确认 stream 版有而 execute 版无的行为,在 _execute_loop 中统一处理

Execution note: Characterization-first。重构前先在 test_react_engine.py 补充 golden trajectory 测试(固定输入 → 期望事件序列快照),锁定现有行为。重构后验证快照不变。

Patterns to follow: 项目已有的 async generator 安全规则(return; yield 守卫,见 .trae/rules/project_rules.md

Test scenarios:

  • Happy path: 单步工具调用 → 期望事件序列 [thinking, tool_call, tool_result, final_result]execute 返回 ReActResult.status="success"
  • Happy path 流式等价: 同一输入分别调用 execute 和 execute_stream验证 execute 返回的 ReActResult 与 execute_stream 最后的 'final_result' event 内容一致
  • 多步循环: 3 步工具调用后 LLM 不返回 tool_calls → 停止,事件序列长度正确
  • Edge case: 空工具列表: 无工具时 LLM 直接返回文本 → 单个 final_result 事件
  • Edge case: max_steps 达到: 循环达到 max_steps → final_result.status="timeout"
  • Error path: 工具执行失败: 工具抛异常 → tool_result event 包含错误,循环继续
  • Error path: LLM 调用失败: LLM gateway 抛异常 → final_result.status="empty_fallback" 或错误状态
  • Phase violation: phase 不允许的工具调用 → phase_violation event循环继续
  • CancellationToken: 中途取消 → final_result.status="cancelled"
  • 压缩触发: 上下文超阈值 → compress event循环继续
  • Golden trajectory: 固定 mock LLM 响应序列 → 完整事件序列快照比对(重构前后一致)

Verification: executeexecute_stream 对同一输入产生等价结果;现有 5 个 react 测试文件全部通过(tests/unit/test_react_engine.pytests/unit/test_react_token_streaming.pytests/unit/test_react_phase_enforcement.pytests/unit/test_react_skill_mcp_integration.pytests/unit/test_react_compression.py);新增 golden trajectory 测试通过;_execute_loop 是唯一的循环实现。


U2. TeamOrchestrator Mixin 拆分

Goal: 将 2080 行上帝类按职责拆分为 7 个 mixin主类 ≤600 行,单方法 ≤100 行。

Requirements: R2, R6

Dependencies: U1ReActEngine 重构完成后,减少 TeamOrchestrator 测试耦合)

Files:

  • src/agentkit/experts/orchestrator.py — 主类瘦身,组合 mixin
  • src/agentkit/experts/_phase_executor.py — 新建PhaseExecutorMixin
  • src/agentkit/experts/_debate_runner.py — 新建DebateRunnerMixin
  • src/agentkit/experts/_review_gate.py — 新建ReviewGateMixin
  • src/agentkit/experts/_divergence_detector.py — 新建DivergenceDetectorMixin
  • src/agentkit/experts/_rollback_handler.py — 新建RollbackHandlerMixin
  • src/agentkit/experts/_synthesizer.py — 新建SynthesizerMixin
  • src/agentkit/experts/_intervention_handler.py — 新建InterventionHandlerMixin
  • tests/unit/experts/test_team_orchestrator.py — 验证拆分后行为等价

Approach:

  1. 按职责将 37 个方法分组到 7 个 mixin见 HTD 图):
    • PhaseExecutorMixin_execute_phase, _execute_execution_phase, _get_isolated_agent, _cleanup_isolated_agent, _build_dependency_context, _read_dependency_output, _offload_result, _notify_collaborators
    • DebateRunnerMixin_execute_debate_phase, _generate_debate_*4 个), _format_debate_history
    • ReviewGateMixin_review_phase_output, _parse_risk_flags
    • DivergenceDetectorMixin_detect_divergence, _insert_debate_phase, _check_divergence_and_insert_debates, _maybe_add_plan_review_debate
    • RollbackHandlerMixin_mark_dependents_failed, _run_phase_rollback
    • SynthesizerMixin_synthesize_results, _fallback_to_single_agent
    • InterventionHandlerMixin_consume_team_interventions, _has_stop_command, _process_interventions
  2. 主类保留:execute, _run_pipeline, resume, _decompose_task, _parse_phases, _get_model, _get_llm_gateway, _broadcast_event + 共享状态字段
  3. 每个 mixin 文件顶部注明 # TYPE_CHECKING: 由 TeamOrchestrator 组合,访问 self 共享状态
  4. _execute_execution_phase~290 行)拆分为 _prepare_phase_context_run_agent_steps_finalize_phase 三个子方法

Execution note: Characterization-first。拆分前先运行现有 test_team_orchestrator.py 确认绿色,拆分后验证不变。如现有测试覆盖不足,补充关键路径测试(阶段执行/辩论/回滚/综合)。

Patterns to follow: Python mixin 模式,TYPE_CHECKING 块声明共享状态 Protocol

Test scenarios:

  • Happy path 拆分等价: 现有 test_team_orchestrator.py 全部通过(拆分前后行为不变)
  • 阶段执行: 单阶段计划 → COMPLETED 状态,广播事件序列正确
  • 多阶段并行: 3 阶段计划2 个同层并行) → 阶段并行执行,依赖正确
  • 辩论阶段: debate 类型阶段 → 辩论 5 步执行opening/argument/summary/verdict
  • 验收降级: LLM gateway 不可用 → passed=True, degraded=TrueU3 联动)
  • 回滚: 阶段失败 → 依赖阶段标记 FAILED回滚执行
  • 分歧检测: 多轮交互超阈值 → 插入辩论阶段
  • 用户干预: stop 命令 → 计划暂停
  • 综合: 所有阶段完成 → Lead 综合,广播 team_synthesis
  • 单 agent 回退: 所有阶段失败 → 回退到单 agent 模式

Verification: 主类 ≤600 行;每个 mixin 文件 ≤400 行;现有 test_team_orchestrator.py 全部通过;ruff check 通过。


U3. except Exception 关键路径治理

Goal: core/experts/ 目录的 except Exception 整改为捕获具体异常 + 结构化降级标记。

Requirements: R3, R6

Dependencies: U2TeamOrchestrator 拆分后,验收逻辑在 ReviewGateMixin 中)

Files:

  • src/agentkit/experts/_review_gate.py — 验收降级改结构化 degraded 字段(联动 U2
  • src/agentkit/core/react.py_execute_loop 内的 except Exception 分类
  • src/agentkit/core/base.pyexecute()except Exception 分类
  • src/agentkit/orchestrator/pipeline_engine.py — 关键路径 except Exception 分类
  • tests/unit/experts/test_team_orchestrator.py — 验收降级测试
  • tests/unit/test_react_engine.py — 错误路径测试

Approach:

  1. 验收路径(_review_phase_outputexcept Exception 改为 except (LLMGatewayError, asyncio.TimeoutError, ConnectionError),降级返回 (True, ReviewResult(degraded=True, reason="...")) 而非字符串前缀
  2. 定义 ReviewResult dataclasspassed: bool, degraded: bool = False, feedback: str = "",替换裸 tuple 返回
  3. 广播层联动AE3_review_phase_output 在广播 review_result 事件时payload 必须包含 degraded: bool 字段(从 ReviewResult.degraded 取值),让前端/运维可编程判断降级状态——而非依赖 [DEGRADED] 字符串前缀匹配
  4. core/react.py _execute_loop 内:except Exception 按 LLM 错误/工具错误/超时分类,保留"日志 + 继续"但记录结构化错误码
  5. core/base.py execute()except Exception 改为 except (AgentError, asyncio.TimeoutError, CancelledError),其余 re-raise
  6. 非 LLM 不可用类的降级(如工具执行失败)保持现有"日志 + 继续"行为,但用 logger.warning 替代 logger.error 避免告警疲劳
  7. 调用方迁移:搜索 _review_phase_output 的所有调用点(_execute_execution_phase 等),将解构 passed, feedback = ... 改为 review = ...; passed, feedback, degraded = review.passed, review.feedback, review.degraded,确保 degraded 字段向后兼容(默认 False

Patterns to follow: 项目已有的 ToolValidationError 类型化错误码模式(react.py:2269-2277

Test scenarios:

  • 验收 LLM 不可用: gateway 为 None → ReviewResult(passed=True, degraded=True)
  • 验收 LLM 超时: gateway 抛 TimeoutError → ReviewResult(passed=True, degraded=True)
  • 验收 LLM 返回无效: gateway 返回非 JSON → 解析失败,ReviewResult(passed=False, feedback="...")
  • 验收正常通过: gateway 返回 "passed" → ReviewResult(passed=True, degraded=False)
  • 工具执行失败: 工具抛 ValueError → _execute_loop 记录错误码,循环继续
  • LLM 调用失败: gateway 抛 ConnectionError → final_result 携带结构化错误码
  • CancellationToken: 中途取消 → CancelledError 正确传播,不被 except Exception 吞掉
  • 调用方迁移回归: _review_phase_output 所有调用点(_execute_execution_phase 等)正确解构 ReviewResultdegraded 字段向后兼容(旧调用点未迁移时不报错,默认 False
  • review_result WS 事件 payloadAE3: 验收降级时广播的 review_result 事件 payload 含 degraded: true 字段;正常通过时 degraded: false

Verification: 基线 core/ + experts/ 共 84 处 except Exceptionreact.py 23 + rewoo.py 21 + base.py 12 + orchestrator.py 20 + board_orchestrator.py 6 + 其余 2整改后减少 ≥50%;验收降级返回结构化 ReviewResultreview_result WS 事件含 degraded 字段;现有测试通过。


U4. Any 类型残留治理

Goal: bitable/、pipeline_state.py、tools/computer_use_session.py 的 Any 替换为具体类型或 object + Protocol。

Requirements: R4, R6

Dependencies: 无(可与 U1-U3 并行)

Files:

  • src/agentkit/bitable/service.py — 6 处 Any
  • src/agentkit/bitable/db.py — 6 处 Any
  • src/agentkit/bitable/formula/functions.py — 7 处 Any
  • src/agentkit/bitable/formula/parser.py — 4 处 Any
  • src/agentkit/orchestrator/pipeline_state.py — 9 处 Anyself._redis: Any 等)
  • src/agentkit/tools/computer_use_session.py — 8 处 Any
  • 对应测试文件

Deferred独立 PR本 U 不处理):

  • src/agentkit/bitable/repository.py — 5 处
  • src/agentkit/bitable/recalc_worker.py — 2 处
  • src/agentkit/bitable/ingestion/database.py — 2 处
  • src/agentkit/bitable/ingestion/excel.py — 1 处
  • 注:bitable/formula/engine.py 经核实 : Any 数量为 0无需处理bitable/formula.py 文件不存在(实际为 formula/ 目录下的 functions.py + parser.py + engine.py

Approach:

  1. bitable/ in-scope23 处service.py 6 + db.py 6 + formula/functions.py 7 + formula/parser.py 4deferred 10 处见上):定义 BitableRecord = dict[str, str | int | float | None] TypeAlias 替换 dict[str, Any];公式求值结果用 FormulaResult = str | int | float | None
  2. pipeline_state.py9 处):self._redis: Anyobject | None(运行时用 isinstance 检查);Callable[..., Coroutine[Any, Any, Any]] 保留Coroutine 类型参数合理);session_factory: Anyobject | None
  3. tools/computer_use_session.py8 处):定义 SessionState = dict[str, str | int | bool | None] TypeAlias截图数据用 bytes 而非 Any
  4. 每个模块顶部用 TYPE_CHECKING 块定义 Protocol_RedisLike),描述期望接口
  5. 对无法静态推断的动态字段,用 dict[str, object] + 显式访问器方法

Patterns to follow: U0 已修的 skill_routing.py 模式(Anyobject + getattr

Test scenarios:

  • 类型检查: ruff check 通过,无 : Any 残留(除 Coroutine[Any, Any, Any]
  • bitable service 行为等价: 现有 bitable 测试全部通过
  • pipeline_state Redis 降级: Redis 不可用 → 降级到 InMemory行为不变
  • computer_use_session: 现有测试通过,截图数据类型正确

Verification: 目标文件 Any 数量降至 ≤5保留 Coroutine[Any, Any, Any]ruff check 通过;现有测试通过。


U5. 前端 chat.ts 拆分 + vitest 补充

Goal: 将 2025 行 chat.ts 拆分为 chatSocket/chatStream/chatStore 三个模块,补充关键路径 vitest 测试。

Requirements: R5, R6

Dependencies: 无(前端独立,可与后端并行)

Files:

  • src/agentkit/server/frontend/src/stores/chat.ts — 瘦身为 chatStore.ts会话/消息状态/computed
  • src/agentkit/server/frontend/src/stores/chatSocket.ts — 新建WebSocket 连接/心跳/重连
  • src/agentkit/server/frontend/src/stores/chatStream.ts — 新建,流式步骤聚合/事件分发
  • src/agentkit/server/frontend/src/stores/__tests__/chatStream.test.ts — 新建dispatchWsEvent 测试
  • src/agentkit/server/frontend/src/stores/__tests__/chatSocket.test.ts — 新建,重连/心跳测试
  • src/agentkit/server/frontend/src/stores/index.ts — 如有,更新 re-export

Approach:

  1. chatSocket.ts~200 行):提取 connectWebSocket, disconnectWebSocket, _heartbeatTimer, _reconnectTimer, resolveIncomingConvId, _intentionalDisconnect;导出 useChatSocket() composable
  2. chatStream.ts~300 行):提取 getConvSteps, appendStep, updateLastStep, clearConvSteps, handleWsMessage 的事件分发逻辑(重命名为 dispatchWsEvent);导出 useChatStream() composable
  3. chatStore.ts≤500 行):保留 loadConversations, selectConversation, createConversation, deleteConversation, sendMessage, sendWsMessage, computed组合 useChatSocketuseChatStream
  4. handleWsMessage 的 discriminated union 分发改为 chatStream.ts 中的 dispatchWsEvent(event, streamState) 纯函数,便于单元测试
  5. vitest 测试覆盖:dispatchWsEvent 的 10+ 事件类型、resolveIncomingConvId 启发式、心跳/重连时序

Patterns to follow: Vue 3 Composition API composable 模式;现有 useChatStore = defineStore 结构

Test scenarios:

  • dispatchWsEvent token: token 事件 → streamingStepsByConv 更新
  • dispatchWsEvent thinking: thinking 事件 → appendStep(type=thinking)
  • dispatchWsEvent step: step 事件 → appendStep(type=tool_call)
  • dispatchWsEvent final_answer: final_answer 事件 → 标记完成,清除 pending
  • dispatchWsEvent team_formed: team_formed 事件 → planExecState 更新
  • dispatchWsEvent expert_step: expert_step 事件 → appendStep(type=expert)
  • dispatchWsEvent error: error 事件 → 错误状态设置
  • resolveIncomingConvId: 多会话 pending → 返回最近使用的 convId
  • 心跳: 30s 间隔 → 发送 ping
  • 重连: 断连后 3s → 重连,_intentionalDisconnect 防级联

Verification: 三个文件每个 ≤500 行vitest 测试 ≥10 个;npm run typecheck 通过;npm run build:frontend 成功。


Risks & Dependencies

Risk Analysis

风险 概率 影响 缓解
U1 ReActEngine 重构引入流式路径回归 Characterization-first重构前补 golden trajectory 测试,锁定事件序列
U2 TeamOrchestrator mixin 拆分后共享状态访问混乱 TYPE_CHECKING Protocol 声明共享状态接口mixin 文件顶部注明依赖
U3 验收降级结构化改动破坏调用方 ReviewResult dataclass 保持 passed 字段向后兼容;逐步迁移调用方
U4 bitable formula 动态类型治理过度 保留 Coroutine[Any, Any, Any];动态字段用 dict[str, object] 而非强类型
U5 前端拆分后 composable 间状态同步问题 保持 useChatStore 作为单一状态源socket/stream 作为内部 composable
跨 U 回归U1+U2 同时改 core/experts U1 完成并验证后再启动 U2U4/U5 可并行

Dependencies

  • U1 → U2U2 的 ReviewGateMixin 依赖 U1 的 ReActEngine 稳定(减少测试耦合)
  • U2 → U3U3 的验收降级整改在 U2 拆分后的 ReviewGateMixin 中进行
  • U4 独立:可与 U1-U3 并行
  • U5 独立:前端独立,可与后端并行
  • 测试基础5989 单测 + 5 个 react 测试文件 + test_team_orchestrator.py 必须在重构前绿色

Acceptance Examples

  • AE1: execute()execute_stream() 对同一 mock 输入产生等价结果ReActResult 字段一致),事件序列长度一致
  • AE2: TeamOrchestrator 主类 ≤600 行7 个 mixin 文件各自独立,test_team_orchestrator.py 全部通过
  • AE3: 验收 LLM 不可用时,ReviewResult(passed=True, degraded=True) 返回,review_result WS 事件包含 degraded: true 字段
  • AE4: in-scope 文件bitable/ service.py + db.py + formula/functions.py + formula/parser.py、pipeline_state.py、tools/computer_use_session.py共 40 处 Any)中 Any 数量降至 ≤5保留 Coroutine[Any, Any, Any]
  • AE5: 前端 chat.ts 拆分为 3 个文件,每个 ≤500 行vitest ≥10 个测试通过

Documentation Plan

  • 更新 AGENTS.mdTeamOrchestrator 模块映射表补充 mixin 文件列表
  • 更新 CONCEPTS.md:如需,补充 ReviewResultReActEvent'final_result' 事件值术语
  • 不新增独立文档(重构不改变外部 API

Operational / Rollout Notes

  • 每个 U 作为独立 PR按依赖顺序合并U1 → U2 → U3U4/U5 可并行)
  • 每个 PR 必须通过 pytest tests/unit/ -x -q + ruff check src/ + 前端 npm run typecheck(如涉及)
  • U1 PR 需额外验证:流式路径 golden trajectory 快照比对
  • 回滚策略:任意 PR 引入回归revert 该 PR重构不涉及数据迁移回滚零成本

Future Considerations

  • U2 升级mixin 拆分稳定后,可进一步迁移到组合模式(独立类 + 依赖注入),完全消除共享状态耦合
  • except Exception 全量整治U3 完成后,可排期 server/routes/ 的 35 处整治
  • Any 全量治理U4 完成后,可排期 llm/memory/client/ 残留治理
  • 前端 vitest 覆盖率U5 完成后,逐步提升到 60% 行覆盖

Sources & Research

  • 综合评审报告(双 agent 评审2026-06-30架构与工程 3.63/5、产品与运维 4.0/5
  • 代码取证:core/react.py 方法结构Grep 32 方法)、experts/orchestrator.py37 方法)、chat.ts20+ 函数)
  • 项目规则:.trae/rules/project_rules.mdasync generator 安全)、AGENTS.md(禁止 any、禁止 except Exception 滥用)