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

# refactor: 系统性技术债清理

## Summary

针对综合评审识别的 5 项系统性技术债制定分阶段重构 plan：ReActEngine 流式/非流式 ~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.py（9 处）、tools/computer_use_session.py（8 处）等，违反 AGENTS.md "禁止 any 类型"。
5. **前端 chat.ts 巨型文件**：2025 行、20+ 内部函数，`handleWsMessage` 单函数处理 10+ 事件类型，vitest 仅 3 个测试。

## Requirements

- **R1**：ReActEngine `execute` 与 `execute_stream` 共用同一循环骨架，消除 80% 重复代码，行为等价（golden trajectory 验证）
- **R2**：TeamOrchestrator 按职责拆分为 ≤7 个模块，主类 ≤600 行，单方法 ≤100 行
- **R3**：关键路径（`core/`、`experts/`）的 `except Exception` 禁止静默降级为"自动通过"，必须返回 `passed=False` 或 `degraded=True` 结构化标记
- **R4**：bitable/、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 Exception` 在 `core/`、`experts/` 目录的关键路径整改
- `Any` 在 bitable/、pipeline_state.py、tools/computer_use_session.py 的治理
- 前端 chat.ts 拆分 + 关键路径 vitest 补充

### Out of Scope

- 功能变更或新功能开发
- `except Exception` 在 `server/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 ReActEvent`；`execute` 收集所有事件并从最终事件提取 `ReActResult`；`execute_stream` 直接 `async for` 透传事件。

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

**替代方案**：事件回调（`event_sink: Callable | None`）——需 queue 桥接 async generator 与 coroutine，复杂度高，违反 ponytail。

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

**决策**：采用 mixin 模式拆分 `TeamOrchestrator`——`PhaseExecutorMixin`、`DebateRunnerMixin`、`ReviewGateMixin`、`DivergenceDetectorMixin`、`RollbackHandlerMixin`、`SynthesizerMixin`、`InterventionHandlerMixin`，主类组合这些 mixin。

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

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

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

**决策**：关键路径（验收/质量门）的 `except Exception` 改为捕获具体异常（`LLMGatewayError`、`asyncio.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.ts`（WebSocket 连接/心跳/重连）、`chatStream.ts`（流式步骤聚合/事件分发）、`chatStore.ts`（会话/消息状态/computed）。`handleWsMessage` 的事件分发逻辑提取到 `chatStream.ts` 的 `dispatchWsEvent` 函数。

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

### KTD6: Characterization-first 执行姿态

**决策**：U1（ReActEngine）和 U2（TeamOrchestrator）在重构前先补充 characterization/golden 测试，锁定现有行为，再执行重构。

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

## High-Level Technical Design

### ReActEngine 事件回调驱动重构（U1）

```mermaid
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）

```mermaid
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 generator，`execute` 与 `execute_stream` 共用同一骨架，消除 80% 重复代码。

**Requirements**: R1, R6

**Dependencies**: 无（首个单元）

**Files**:
- `src/agentkit/core/react.py` — 重构 `_execute_loop`、`execute`、`execute_stream`；`ReActEvent` 扩展 `'final_result'` 事件值
- `tests/unit/test_react_engine.py` — 补充 golden trajectory 测试
- `tests/unit/test_react_token_streaming.py` — 验证流式行为等价

**Approach**:
1. 扩展 `ReActEvent`（line 130，`event_type: str` 字符串字段）增加 `'final_result'` 字符串值，在 `data` dict 中携带 `ReActResult`（不新建 EventType 枚举）
2. 将 `_execute_loop`（529-1174）改为 async generator，在每个关键节点（think/act/observe/phase_violation/compress）`yield ReActEvent`，结束时 `yield ReActEvent(event_type='final_result', data={'result': final_result})`
3. `execute`（396-527）改为 `[e async for e in self._execute_loop(...)]`，从最后一个 event 提取 `ReActResult` 返回
4. `execute_stream`（1176-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**: `execute` 与 `execute_stream` 对同一输入产生等价结果；现有 5 个 react 测试文件全部通过（`tests/unit/test_react_engine.py`、`tests/unit/test_react_token_streaming.py`、`tests/unit/test_react_phase_enforcement.py`、`tests/unit/test_react_skill_mcp_integration.py`、`tests/unit/test_react_compression.py`）；新增 golden trajectory 测试通过；`_execute_loop` 是唯一的循环实现。

---

### U2. TeamOrchestrator Mixin 拆分

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

**Requirements**: R2, R6

**Dependencies**: U1（ReActEngine 重构完成后，减少 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=True`（U3 联动）
- **回滚**: 阶段失败 → 依赖阶段标记 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**: U2（TeamOrchestrator 拆分后，验收逻辑在 ReviewGateMixin 中）

**Files**:
- `src/agentkit/experts/_review_gate.py` — 验收降级改结构化 `degraded` 字段（联动 U2）
- `src/agentkit/core/react.py` — `_execute_loop` 内的 `except Exception` 分类
- `src/agentkit/core/base.py` — `execute()` 的 `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_output`）：`except Exception` 改为 `except (LLMGatewayError, asyncio.TimeoutError, ConnectionError)`，降级返回 `(True, ReviewResult(degraded=True, reason="..."))` 而非字符串前缀
2. 定义 `ReviewResult` dataclass：`passed: 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` 等）正确解构 `ReviewResult`，`degraded` 字段向后兼容（旧调用点未迁移时不报错，默认 `False`）
- **review_result WS 事件 payload（AE3）**: 验收降级时广播的 `review_result` 事件 payload 含 `degraded: true` 字段；正常通过时 `degraded: false`

**Verification**: 基线 core/ + experts/ 共 84 处 `except Exception`（react.py 23 + rewoo.py 21 + base.py 12 + orchestrator.py 20 + board_orchestrator.py 6 + 其余 2）；整改后减少 ≥50%；验收降级返回结构化 `ReviewResult` 且 `review_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 处 `Any`（`self._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-scope**（23 处：service.py 6 + db.py 6 + formula/functions.py 7 + formula/parser.py 4；deferred 10 处见上）：定义 `BitableRecord = dict[str, str | int | float | None]` TypeAlias 替换 `dict[str, Any]`；公式求值结果用 `FormulaResult = str | int | float | None`
2. **pipeline_state.py**（9 处）：`self._redis: Any` → `object | None`（运行时用 `isinstance` 检查）；`Callable[..., Coroutine[Any, Any, Any]]` 保留（Coroutine 类型参数合理）；`session_factory: Any` → `object | None`
3. **tools/computer_use_session.py**（8 处）：定义 `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` 模式（`Any` → `object` + `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；组合 `useChatSocket` 和 `useChatStream`
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 完成并验证后再启动 U2；U4/U5 可并行 |

### Dependencies

- **U1 → U2**：U2 的 ReviewGateMixin 依赖 U1 的 ReActEngine 稳定（减少测试耦合）
- **U2 → U3**：U3 的验收降级整改在 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.md`：TeamOrchestrator 模块映射表补充 mixin 文件列表
- 更新 `CONCEPTS.md`：如需，补充 `ReviewResult`、`ReActEvent` 的 `'final_result'` 事件值术语
- 不新增独立文档（重构不改变外部 API）

## Operational / Rollout Notes

- 每个 U 作为独立 PR，按依赖顺序合并（U1 → U2 → U3，U4/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.py`（37 方法）、`chat.ts`（20+ 函数）
- 项目规则：`.trae/rules/project_rules.md`（async generator 安全）、`AGENTS.md`（禁止 any、禁止 except Exception 滥用）
