Skip to content

refactor:TUI 架构渐进式整理并补充单元测试#43

Merged
minorcell merged 10 commits into1024XEngineer:mainfrom
creatang:main
Mar 24, 2026
Merged

refactor:TUI 架构渐进式整理并补充单元测试#43
minorcell merged 10 commits into1024XEngineer:mainfrom
creatang:main

Conversation

@creatang
Copy link
Copy Markdown
Collaborator

背景

本次 PR 继续基于#39,完成 docs/TUI_REFINED_ARCHITECTURE.md,并依据文档对 TUI 做渐进式整理。
目标不是重写功能,也不是强行复制文档结构,而是在不改变现有启动方式、交互行为、流式输出和命令语义的前提下,逐步收敛 TUI 的分层边界,并补齐一批稳定的单元测试。

本次完成内容

  • 将部分纯展示逻辑从 core 下沉到 components
    • 抽离帮助面板渲染
    • 抽离输入区 footer 渲染
  • 建立并落地 state
    • 抽离聊天消息 Message
    • 引入 ChatStateUIState
    • core.Model 中可独立的纯状态聚合到 state
  • 建立并完善 bootstrap
    • 抽离 Program 装配逻辑
    • 抽离 workspace 准备与 API key 交互 setup 逻辑
    • cmd/tui/main.go 更接近纯入口
  • 整理 services 边界
    • 将 TUI 服务适配入口统一收敛到 internal/tui/services/
    • 通过薄封装隔离 TUI 对后端基础设施细节的直接依赖
  • 清理已确认未使用的冗余内容
    • 删除旧的 internal/tui/infra 路径与空目录
    • 删除未使用的旧输入组件实现
    • 删除 core/msg.go 中未使用的消息辅助符号
  • 补充 TUI 单元测试
    • cmd/tui/main_test.go
    • internal/tui/bootstrap/setup_test.go
    • internal/tui/components/layout_helpers_test.go
    • internal/tui/core/view_test.go
    • 保留并延续现有 internal/tui/core/update_test.go

架构结果

当前 TUI 已基本形成以下职责边界:

  • cmd/tui/
    • 入口层,只负责参数解析、调用 bootstrap、运行 program
  • internal/tui/bootstrap/
    • 启动前准备、依赖装配、交互式 setup
  • internal/tui/core/
    • 主状态机、消息处理、顶层视图编排
  • internal/tui/state/
    • 纯状态定义
  • internal/tui/components/
    • 纯展示组件
  • internal/tui/services/
    • TUI 与后端/环境能力的接入边界

保持不变的内容

本次 PR 不改变以下行为:

  • 命令行启动方式
  • 现有交互行为
  • 流式输出语义
  • 输入/回退/状态栏/消息展示行为
  • 命令处理语义
  • 后端实现、协议结构、领域模型和核心业务逻辑

测试

已执行:

go test ./cmd/tui ./internal/tui/...
结果通过。
说明
这次改动是“渐进式贴近文档”,不是强行完全照搬文档结构。
有意避免了以下高风险或低收益动作:
- 不必要的新接口层
- 过薄且无价值的抽象堆叠
- 仅为了命名一致而强行将 core 直接重命名为 app
- 对 TUI 以外模块的侵入式修改

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 87.78802% with 53 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/tui/bootstrap/setup.go 81.69% 16 Missing and 10 partials ⚠️
internal/tui/core/update.go 82.69% 17 Missing and 1 partial ⚠️
cmd/tui/main.go 83.01% 7 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Collaborator

@minorcell minorcell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整体重构方向清晰,分层目标明确,测试覆盖也补充得比较扎实。以下是几处值得关注的具体问题,请评估是否需要在本 PR 或后续跟进修复。

import (
"time"

"go-llm-demo/internal/tui/services"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[架构分层违反] state 层导入了 services 包,这与架构文档中「纯状态定义,只存放纯粹的 Go 结构体」的原则相矛盾。

state 是最底层的数据容器,不应依赖 services(后者本身依赖 internal/server/infra/...)。

建议:将 MemoryStatsstate 包内自行定义(或复制所需字段),或抽到独立的 types 包中,切断 state → services → server/infra 这条依赖链。

HistoryTurns int
Generating bool
ActiveModel string
MemoryStats services.MemoryStats
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[同上] MemoryStats services.MemoryStatsstate 引入 services 依赖的根因。若将此字段的类型改为在 state 包内定义,上面的 import 可以一并去掉。


const (
ModeChat Mode = iota
ModeCodeInput
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[未使用的常量] ModeCodeInputModeMemory 在整个代码库中未见任何引用(含测试)。如果这两个模式是将来规划的占位符,建议加注释说明;如果当前不需要,可以先删除,避免 iota 序号被无谓占用导致潜在混乱。

}

func (i InputBox) Render() string {
helpText := "[Enter换行 F5/F8发送 PgUp/PgDn滚动]"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[逻辑可读性] 默认值设置后立即在常规分支(!Generating)中被覆盖,使读者需要二次反应才能理解真正的默认行为。

建议改写为:

var helpText string
if i.Generating {
    helpText = "[Enter换行 F5/F8发送 PgUp/PgDn滚动]"
} else {
    helpText = "[Enter换行 F5/F8发送 Ctrl+V粘贴 PgUp/PgDn滚动]"
}

这样 Generating=true/false 的分支一目了然,也更容易在未来单独扩展两种状态。

Comment thread cmd/tui/main.go Outdated
workspaceRoot, err := tools.ResolveWorkspaceRoot(*workspaceFlag)
workspaceRoot, err := bootstrap.PrepareWorkspace(*workspaceFlag)
if err != nil {
fmt.Fprintf(os.Stderr, "解析工作区失败: %v\n", err)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[错误信息不准确] PrepareWorkspace 内部合并了 ResolveWorkspaceRootSetWorkspaceRoot 两步,但调用方只有一条错误信息「解析工作区失败」。如果是 SetWorkspaceRoot 失败,这条消息会产生误导。

可以让 PrepareWorkspace 对两种失败返回带前缀的错误(fmt.Errorf("解析工作区: %w", err) / fmt.Errorf("设置工作区: %w", err)),调用方统一用 "初始化工作区失败: %v" 即可,信息更完整。

* 将这些服务注入到 `app` 层中。
* **关键作用**:通过在这一层注入不同的实现,可以轻松实现“离线测试模式”或“Mock 测试”。

### 应用逻辑层 (App/Core) - `internal/tui/app/`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[文档与实现不一致] 这里写的目录路径是 internal/tui/app/,但实际代码中保留的是 internal/tui/core/,PR 描述中也说明有意不强行重命名。

建议将此处(及下方目录结构示意图中的 app/ 引用)同步修改为 core/,避免文档成为误导性参考。

Copy link
Copy Markdown
Collaborator

@minorcell minorcell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@creatang 有很多中文乱码;

测试用例里面尽量不要使用中文。

Comment thread cmd/tui/main.go Outdated
fs := flag.NewFlagSet("tui", flag.ContinueOnError)
fs.SetOutput(stderr)

workspaceFlag := fs.String("workspace", "", "鎸囧畾宸ヤ綔鍖烘牴鐩綍")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有乱码?

@minorcell
Copy link
Copy Markdown
Collaborator

@creatang 这个PR先合并了,后续你们组应该讨论一下“把喂给 llm 的信息换成英文”的事情,包括这些测试用例。

@minorcell minorcell merged commit 1c91391 into 1024XEngineer:main Mar 24, 2026
2 checks passed
@creatang
Copy link
Copy Markdown
Collaborator Author

@creatang 这个PR先合并了,后续你们组应该讨论一下“把喂给 llm 的信息换成英文”的事情,包括这些测试用例。

好的,我们今天中午确定一下~

@creatang
Copy link
Copy Markdown
Collaborator Author

整体重构方向清晰,分层目标明确,测试覆盖也补充得比较扎实。以下是几处值得关注的具体问题,请评估是否需要在本 PR 或后续跟进修复。

今天完成测试之后,待其他相关pr合并后进行修复

phantom5099 added a commit that referenced this pull request Apr 19, 2026
test: improve coverage for provider defaults and migration script
phantom5099 pushed a commit that referenced this pull request Apr 24, 2026
test: improve coverage for verification and acceptance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants