docs: harden tui optimization design

This commit is contained in:
秦奇 2026-04-21 16:25:42 +08:00
parent 88efd775db
commit e2be1bd548
7 changed files with 1549 additions and 145 deletions

View file

@ -1,6 +1,6 @@
# TUI 优化方案总览
> 本文档是 qwen-code TUI 优化的整体方案概览,详细设计分别见三个子文档
> 本文档是 qwen-code TUI 优化的整体方案概览。除三份实施设计外,现已补充 Gemini CLI 与 Claude Code 的独立源码调研文档,用来校准方案优先级和技术路线
## 1. 背景与动机
@ -36,25 +36,39 @@ Entry (gemini.tsx)
| Markdown | 逐行正则解析器 | `packages/cli/src/ui/utils/MarkdownDisplay.tsx` |
| 代码高亮 | lowlight (基于 highlight.js) | `packages/cli/src/ui/utils/CodeColorizer.tsx` |
| 防闪烁 | stdout 拦截器,折叠重复 ANSI 序列 | `packages/cli/src/ui/utils/terminalRedrawOptimizer.ts` |
| 主题 | ThemeManager 单例15+ 内置主题 | `packages/cli/src/ui/themes/theme-manager.ts` |
| MCP | 跨 Server 并行发现;整体仍等待全部完成,默认 10 分钟超时;工具注册和 Gemini tools 刷新需要拆开设计 | `packages/core/src/tools/mcp-client-manager.ts` |
| 启动分析 | 环境变量开启的 checkpoint 记录器;当前主要覆盖 render 前阶段 | `packages/cli/src/utils/startupProfiler.ts` |
| 主题 | ThemeManager 单例15 个内置主题(另有 no-color fallback | `packages/cli/src/ui/themes/theme-manager.ts` |
| MCP | 跨 Server 并行发现;已有单 server 重发现与增量发现基础,但启动 wiring、运行期 refresh 路径和 Gemini tools 刷新仍需补齐 | `packages/core/src/tools/mcp-client-manager.ts` |
| 启动分析 | 环境变量开启的 checkpoint 记录器;当前仅在 sandbox child process 中生效,且主要覆盖 render 前阶段 | `packages/cli/src/utils/startupProfiler.ts` |
### 2.2 竞品分析Claude Code
### 2.2 外部源码调研结论
Claude Code 使用**自研的 Ink 深度定制版本**(非 npm 库),包含以下关键优化
本轮补充调研覆盖两个代码库
| 能力 | Claude Code 实现 | qwen-code 现状 |
| -------- | ------------------------------------- | ------------------ |
| 渲染缓冲 | 前后双缓冲 + diff patch | 无,每帧全量输出 |
| 同步输出 | CSI BSU/ESU 原子帧更新 | 无 |
| 硬件滚动 | DECSTBM 滚动区域 | 无 |
| 布局检测 | 布局稳定时窄范围 diff变化时全量重绘 | 无 diff始终全量 |
| 样式池化 | StylePool 整数 ID 内化 + 转换缓存 | 无,每次重新计算 |
| Markdown | marked 库 + LRU 令牌缓存500条 | 自定义正则,无缓存 |
| MCP 启动 | 提前并行启动 + Promise.race 超时 | UI 渲染后初始化,跨 Server 并行但整体等待 |
- Gemini CLI`/Users/gawain/Documents/codebase/opensource/gemini-cli`
- Claude Code`/Users/gawain/Documents/codebase/opensource/claude-code`
### 2.3 社区反馈汇总
两者给 qwen-code 的启发点并不相同:
| 维度 | Gemini CLI | Claude Code | 对 qwen-code 的意义 |
| --- | --- | --- | --- |
| 启动策略 | 入口动态导入交互 UIrender 前后初始化分层 | 顶层并行预取feature-gated requiredeferred prefetch | 先瘦冷启动,再拆关键/非关键初始化 |
| 渲染模式 | alternate buffer / terminal buffer / render process / incrementalRendering | 自定义 Ink + screen buffer + diff pipeline | 短期优先做“模式化渲染”,长期再评估自研渲染内核 |
| 防闪烁 | `findLastSafeSplitPoint()` + `useFlickerDetector()` + ScrollableList | synchronized output + diff + DECSTBM + output buffer | Phase 1 借鉴 Gemini 的中层优化Phase 3 参考 Claude 的底层路线 |
| 长会话滚动 | `ScrollableList` / `VirtualizedList` / `StaticRender` | `ScrollBox` / `useVirtualScroll` / `VirtualMessageList` | qwen-code 需要正式设计滚动/虚拟化层,而不是继续把它藏在 `MainContent` 里 |
| Markdown | 仍是自定义正则解析器 | `marked` + token cache + streaming stable prefix | parser 迁移应更多参考 Claude不应把 Gemini 当 parser 终局 |
| 代码高亮 | 同步 `lowlight(common)` | Suspense + fallback +宽度测量 | qwen-code 需要“同步基线 + 异步增强”而非直接 await grammar |
| MCP 生命周期 | UI 可先起来MCP 状态事件化展示 | 批量状态更新、list-changed 增量刷新、远端重连 | MCP 设计要从“启动 discover”升级为“运行期生命周期管理” |
### 2.3 新增调研文档
为避免把竞品经验压缩成几行摘要,现已将外部源码分析独立成两份文档:
| 文档 | 说明 |
| --- | --- |
| [04-gemini-cli-research.md](./04-gemini-cli-research.md) | Gemini CLI 的启动、渲染模式、防闪烁、滚动、Markdown、MCP 调研 |
| [05-claude-code-research.md](./05-claude-code-research.md) | Claude Code 的自定义 Ink、diff 输出、虚拟滚动、Markdown、MCP 生命周期调研 |
### 2.4 社区反馈汇总
| 问题类别 | 代表性 Issues | 严重程度 |
| ---------- | ----------------------------------------------- | -------- |
@ -65,7 +79,7 @@ Claude Code 使用**自研的 Ink 深度定制版本**(非 npm 库),包含
| 窄屏问题 | claude-code#13504, #18493, #5408 | 中 |
| LaTeX 支持 | claude-code#21433 | 低 |
## 3. 三大工作流概览
## 3. 核心工作流概览
| 工作流 | 核心问题 | 关键指标 | 依赖关系 |
| -------------- | -------------------------------------- | ------------------------------ | -------------------------- |
@ -76,6 +90,8 @@ Claude Code 使用**自研的 Ink 深度定制版本**(非 npm 库),包含
**执行顺序**:观测基线 -> 屏幕闪烁低风险治理 -> 启动/MCP 渐进可用 -> 渲染缓存与扩展。MCP 与渲染可并行推进,但必须共享同一套指标口径。
**实施约束**:从这一版开始,所有落地工作默认都应同时参考 [06-implementation-rollout-checklist.md](./06-implementation-rollout-checklist.md)。如果某项优化没有满足对应的验收清单、灰度顺序和回滚条件,就不应直接进入默认开启阶段。
## 4. 分阶段实施计划
### Phase 0观测基线第 1 周)
@ -102,6 +118,7 @@ Claude Code 使用**自研的 Ink 深度定制版本**(非 npm 库),包含
| 周次 | 变更 | 工作流 | 风险 |
| ---- | ------------------------------------ | ------ | ---- |
| 6-7 | 渐进式 MCP 可用性 + Gemini tools debounce 刷新 | 性能 | 中 |
| 6-7 | 运行期 MCP refresh/reload 路径增量化(避免 `restartMcpServers()` 全量重启) | 性能 | 中 |
| 7 | 动态内容高度阈值优化 + 现有渐进提升增强 | 闪烁 | 中 |
| 7-8 | 切换到 marked 解析器(特性开关) | 渲染 | 中 |
| 8-9 | 智能 refreshStatic()(定向更新) | 闪烁 | 中 |
@ -125,18 +142,37 @@ Claude Code 使用**自研的 Ink 深度定制版本**(非 npm 库),包含
- **解析器**:特性开关控制,旧解析器作为过渡期回退
- **MCP**:所有 Server 快速响应时行为等价;慢 Server 不再阻塞快 Server但工具声明只保证从下一次模型请求开始生效
## 6. 验证策略
## 6. 实施门禁
1. **自动化基准测试**启动分段耗时、渲染时间、stdout writes/sec、stdout 字节/帧
除各子文档自己的验证章节外,还应统一遵守以下门禁:
1. **先补观测,再改行为**
没有 `first_paint``input_enabled``mcp_server_ready`、输出层 counters 的变更,不应宣称性能收益。
2. **先加开关,再做灰度**
同步输出、渐进式 MCP、parser 切换、虚拟滚动都应先具备独立回退能力。
3. **先做主路径,后做高风险路径**
冷启动并行化、流式节流、token cache 应先于 DECSTBM、自研 diff renderer、全量虚拟滚动。
4. **运行期路径必须和启动路径一起设计**
MCP 如果只优化首次启动,而保留 runtime refresh 的全量重启,方案仍然不完整。
## 7. 验证策略
1. **自动化基准测试**启动分段耗时、渲染时间、stdout writes/sec、stdout 字节/帧;启动 profile 需明确在 sandbox child process 中采集
2. **多终端视觉测试**iTerm2、Terminal.app、WezTerm、kitty、Windows Terminal、tmux
3. **回归检测**:滚动启动 profile 对比MCP 首工具/全工具可用时间对比
4. **边界场景**:窄终端 (< 40 )、超长输出 (5000+ )、CJK 内容tmux/SSH
5. **特性开关**Phase 2+ 所有变更可安全回滚
## 7. 子文档索引
## 8. 子文档索引
| 文档 | 说明 |
| ---------------------------------------------------------------- | --------------------------- |
| [01-performance.md](./01-performance.md) | 启动性能与 MCP 优化详细设计 |
| [02-screen-flickering.md](./02-screen-flickering.md) | 屏幕闪烁问题分析与解决方案 |
| [03-rendering-extensibility.md](./03-rendering-extensibility.md) | 渲染性能与可扩展性设计 |
| [04-gemini-cli-research.md](./04-gemini-cli-research.md) | Gemini CLI 源码调研 |
| [05-claude-code-research.md](./05-claude-code-research.md) | Claude Code 源码调研 |
| [06-implementation-rollout-checklist.md](./06-implementation-rollout-checklist.md) | 实施门禁、验收、灰度与回滚清单 |