Skip to content

RFC: NeoCode TUI v2 — Ghost Console 独立实现 #660

@pionxe

Description

@pionxe

RFC: NeoCode TUI v2 — Ghost Console 独立实现

  • RFC ID: NEO-RFC-001
  • 状态: 草案
  • 日期: 2026-05-18
  • 作者: NeoCode Team
  • 涉及模块: cmd/neocode-tuiv2, internal/tuiv2(含 gateway/fakegateway/ 子包)

摘要

本 RFC 提议为 NeoCode 新增 TUI v2(Ghost Console),作为与当前 TUI v1 并行独立 的第二套终端界面。TUI v2 采用独立二进制(neocode-tuiv2),通过 GatewayClient 接口契约与后端解耦,现阶段使用 FakeGatewayClient 进行设计验证,后续替换为真实 Gateway JSON-RPC 客户端。

TUI v1 保持不变,不受任何影响。


动机:为什么要做 TUI v2

当前痛点

TUI v1(internal/tui/)功能完整但存在结构性瓶颈:

  1. 视觉语言不统一:混用面板边框、内联消息、弹窗,缺乏一致的设计语言。大量 ┌ ┐ ├ ┤ │ 字符产生"低配 IDE/后台管理"感。
  2. 信息层级不清晰:所有消息线性排列,长时间会话中难以快速定位关键信息。
  3. 组件高度耦合update.go 7603 行,view.go 985 行,app.go 458 行 — 修改风险高、测试困难、新人理解成本高。
  4. 键位系统不够灵活:单一输入模式,缺乏 Vim 风格的双模式操作(Normal Mode / Input Mode / Leader Key)。
  5. 缺乏产品气质:"能用的终端工具" vs "为 Agent 编程设计的黑客控制台"。

为什么不能渐进改造 v1

  • 键位系统不兼容:v2 的 Esc=Normal Mode、Shift+Enter=换行、Ctrl+C=取消/双退 等语义与 v1 的 Esc=聚焦输入、Ctrl+J=换行、Ctrl+W=取消运行 完全冲突。两套键位语义无法共存于同一套 keyMap
  • 组件架构差异大:v2 采用独立的 tea.Model 子组件 + 集中式 ViewModel,v1 的 App struct 承载几乎所有状态。渐进式拆分 v1 的风险等同于重写。
  • 零风险共存:v1 是稳定版本,用户不应被迫接受任何变更。v2 独立二进制允许用户自主选择。

设计概览

视觉方向:Ghost Console

终端原生 · 黑客控制台 · 命令界面 · Agent 行为流 · 环境状态

核心原则:

  • 默认不画框 — 线框仅用于命令面板、帮助、会话选择器、危险确认、diff 预览、错误详情
  • 语义标签代替标题栏tool.read_file 而非 ┌─ Tool Call ─┐
  • 状态符号建立节奏✓ ◉ ○ ◌ × · 比进度条更终端原生
  • 缩进表达层级 — 不用表格和竖线
  • 单布局自动响应 — Focus-Only 布局随终端宽度自动调整,Soft Inspector ≥100 列自动显示/隐藏

键位系统:三层模式

进入 职责
Input Mode 默认 / Normal i 输入、发送、命令
Normal Mode Esc 导航、搜索、:q 退出
Leader Key Normal 下 Space Space p 面板, Space n 新会话等

与 v1 完全不兼容。

架构边界

neocode-tuiv2 (独立二进制)
  └── internal/tuiv2/ (TUI v2 App)
        ├── gateway/ (Client 接口 + DTO + 真实适配器)
        └── fakegateway/ (FakeClient + 场景)

TUI v2 禁止直接访问:
  ✗ internal/runtime
  ✗ internal/session
  ✗ internal/repository
  ✗ SQLite

构建策略:独立二进制

neocode              # TUI v1(稳定,不动)
neocode-tuiv2        # TUI v2(新入口,默认 fake backend)
  • cmd/neocode/ — 不变
  • cmd/neocode-tuiv2/ — 新增,仅启动 TUI v2
  • 同一仓库,同一 go.mod,独立入口

开发策略:FakeGatewayClient 驱动

TUI v2 从第一天就按真实架构写,所有数据来自 gateway.Client 接口。当前阶段 FakeGatewayClient 提供可控的假数据。

neocode-tuiv2 --scenario=default          # 完整 Ghost Console 演示
neocode-tuiv2 --scenario=tool_approval    # 权限审批流程
neocode-tuiv2 --scenario=gateway_offline  # 离线/错误状态

这确保了后续替换真实 Gateway 时,TUI 代码零改动——只需换一个 Client 实现。


为什么这么做

为什么用 FakeGatewayClient 而不是 FakeRuntime

FakeRuntime 会让 TUI 组件直接依赖 Runtime 领域类型,破坏架构边界。FakeGatewayClient 模拟的是 Gateway 的对外契约(RPC 方法 + 事件流),TUI 只看到 DTO 和事件,不知道 Gateway 背后是什么。

为什么是独立二进制而不是 CLI flag

  • v1 入口零改动,零风险
  • v2 可以独立发布、独立测试、独立回滚
  • 两个二进制可以同时运行(不同终端窗口),方便对比测试

为什么权限和 ask_user 不弹窗

权限确认和 ask_user 属于对话流内的交互,弹窗会打断用户对 Stream 上下文的感知。两者统一在底部 prompt 区域以内联方式处理,保持 Agent 行为流的连续性。

弹窗仅用于需要独立交互空间的场景:命令面板(搜索优先)、帮助(分组信息多)、会话选择(列表搜索)、危险操作确认(防误操作)。


实施阶段

完整 22 个阶段详见子issue。按优先级:

优先级 阶段 目标
P0 Phase 0–9 骨架 + FakeGateway + 布局 + Stream/Prompt + 键位 + 核心流程
P1 Phase 10–16 命令面板 + 弹窗 + 会话/模型闭环 + 鼠标 + 响应式 + 测试
P2 Phase 17–22 真实 Gateway + 联调 + 打磨 + 发布

MVP 范围:Phase 0–9 子集,做到独立运行 + Ghost Console 视觉 + streaming + 基础键位即可验证设计方向。


验收标准

  • neocode-tuiv2 可独立运行,不影响 neocode
  • TUI v2 代码不 import internal/runtime, internal/session, internal/repository, SQLite
  • 所有数据流经过 gateway.Client 接口
  • Ghost Console 视觉语言成立(默认无框、无药丸、无玻璃拟态)
  • 三层键位可操作,不依赖鼠标也能完成所有操作
  • FakeGateway 支持 ≥ 10 个场景,可通过 --scenario 切换
  • 后续替换真实 Gateway 时 TUI 组件代码零改动

相关文档

文档 路径
架构导航 docs/tui-v2/tui-v2-architecture-hub.md
UI/UX 规范 docs/tui-v2/tui-v2-ui-ux-design.md
数据与 Gateway 契约 docs/tui-v2/tui-v2-data-and-gateway.md
工程实现指南 docs/tui-v2/tui-v2-implementation-guide.md
HTML 视觉原型 docs/design/tui-v2-terminal-preview.html

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions