fix(tuiv2): 修复浮层回车不关闭/多行错位,完成 Phase 9 Command Prompt 与交互增强体系#718
Merged
Conversation
实现设计文档 Phase 3(交互增强)和 Phase 4(打磨)的全部功能: Step 9a - 键位系统重构与 Ctrl+C 双退保护: - 新增 keymap 包,实现 Input/Normal/Leader 三层键位抽象 - Leader Key 状态机:Space 进入等待,1 秒超时回退 Normal - Ctrl+C 双退保护:运行中取消 Agent,空闲时双击退出 - 运行取消:调用 client.CancelRun() RPC - Normal Mode 增强:Ctrl+D/Ctrl+U 半页滚动 - 修复 stream.go 重复 doc comment Step 9b - 命令面板、帮助浮层与会话管理: - 实现 Telescope 风格命令面板 (Ctrl+P / Space p) - 实现分组快捷键帮助浮层 (? / Space h) - 实现会话切换器 (Space s) - ViewState 新增 OverlayState 浮层状态 - Slash 命令拦截 (/exit, /help, /session, /clear) - 会话切换 RPC 调用 (loadSessionCmd) Step 9c - 角色感知渲染与视觉打磨: - 用户消息显示 you 标签 (Cyan),助手消息显示 neo 标签 (Blue) - Reducer 自动注入 role: assistant 到 Agent 消息 - Inspector 新增 Active Tools 和 Files 区块 - 使用 DiffAdd/DiffDel 主题色显示文件变更 - 新增 theme.InfoStyle() 访问器 - 补充 status_bar_test.go 和 inspector_test.go - 删除 fakegateway/.gitkeep Step 9d - 鼠标支持与 Slash 命令: - 启用 tea.WithMouseCellMotion() 鼠标支持 - 鼠标滚轮在 Stream 区域滚动 - 浮层内鼠标事件路由到对应组件 - Slash 命令模式 (Prompt 组件自动拦截 / 开头输入) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
自审发现 22 项设计规范差距,本次修复 P0+P1 共 16 项: P0 修复(规范强制要求): 1. Space n → 新建会话(createSessionCmd + sessionCreatedMsg) 2. Space c → 手动 compact(status 提示,待后端 RPC) 3. Space m → 切换 build/plan(RuntimeState.AgentMode) 4. Space f → 切换 Full Access(RuntimeState.FullAccess) 5. Space l → 日志查看预留(status 提示) 6. Normal Mode ? → 打开帮助浮层(原 ActionSearchBackward 重映射) 7. Ctrl+L → 日志查看预留(新增 ActionLogViewer) 8. /model 命令 + 模型选择器浮层(components/model_picker.go) 9. 危险操作确认弹窗(components/confirm.go) P1 修复(体验增强): 10. Palette 鼠标点击执行选项(MouseButtonLeft + MouseActionPress) 11. Session Picker 鼠标点击选择会话 12. Palette 鼠标滚轮滚动列表 13. Session Picker 鼠标滚轮滚动列表 14. /mode /compact /clear 命令路由补齐(palette + slash) 15. /model slash 命令路由 16. Normal Mode : Ex 命令预留位 新增文件: - components/model_picker.go — Telescope 风格模型选择器 - components/confirm.go — 危险操作确认弹窗 修改文件: - app.go — Leader handler 补全、新组件注册、消息路由 - state/viewstate.go — 新增 AgentMode/FullAccess/ConfirmState - keymap/keys.go — 新增 ActionLogViewer、NormalHelp ? 条目 - palette.go — 重构 Update 为 handleKey/handleMouse,鼠标支持 - session_picker.go — 同上重构,鼠标支持,删除走确认弹窗 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
核心修复:事件流导致浮层组件持有过期 state 指针 state.Reduce 每次返回新的 *ViewState,a.state 会被替换;而 bindComponents 此前 只重新绑定 4 个静态组件(status/stream/prompt/inspector),遗漏了 palette、 helpOverlay、sessionPicker、modelPicker、confirmOverlay 等浮层组件。结果浮层的 按键操作改在旧 state 上、当前 state 的 Overlay.Active 始终不变,表现为:方向键 移到 /mode 后回车,面板不关闭、高亮跳回第一项 /model。同一根因也影响会话/模型 选择器与确认弹窗。现在 bindComponents 绑定全部子组件,问题根除。 其余配套修复: - 命令面板 matchedItems 改用「精确名 → 前缀 → 子串」三级匹配(替换模糊匹配), 避免 "mode" 因评分排序命中 /model;并将空格键改为「选中」,与会话选择器一致。 - 确认弹窗:确认/取消时调用 closeOverlay 重置 Overlay.Active,修复回车不关闭。 - 会话切换:sessionSwitchedMsg 重载历史后追加 "Switched to session" 状态提示。 - 多行消息:renderMessage 续行缩进对齐到首行标签宽度,修复流内正文错位。 - 输入提示符 › 改为 ASCII '>',消除歧义宽度在 CJK 终端导致的列错位。 - 换行键:新增 Ctrl+J(Shift+Enter 在 bubbletea v1.3.10 中与回车不可区分), 并更新 keymap 帮助文案为 Alt+Enter / Ctrl+J。 测试:新增 repro_test.go(含模拟事件流复现过期指针的回归测试),并为 prompt、 stream 多行渲染与浮层交互补充回归测试。
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
Review findings:
- Permission and ask-user responses currently do not preserve the backend request identifiers, so real Gateway resolution cannot target the pending request.
- Session deletion is exposed in the UI but only emits a local deletion event; it does not call the Gateway/backend.
Collaborator
Author
当前只是使用假数据实现前端界面效果,并没有真实连通网关,并且现阶段也不打算这么做。 |
针对 codecov 80% 门槛补齐 tuiv2 各包测试:
- app_handlers_test.go:App 消息处理、Ctrl+C、命令分发、Cmd 工厂、模式键、鼠标、View
- components: picker_test/coverage_test/prompt_keys_test — 直接覆盖 palette/model/session
组件级函数、confirm/help/inspector/status_bar/stream 与 prompt 编辑/模式
- theme/coverage_test.go:样式工厂与符号/颜色分支
- gateway/real_test.go:RealClient 占位方法
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
本 PR 在 TUI v2(
neocode-tuiv2独立二进制)落地 Phase 9:Command Prompt 组件及其交互增强体系(三层键位 / 命令面板 / 会话·模型选择器 / 危险确认弹窗 / 鼠标),并随后修复了联调阶段发现的一组交互缺陷。main领先origin/main3 个提交,工作树干净。4281377d实现交互增强与视觉打磨 — 键位/面板/浮层/会话/鼠标/命令 (Phase 9)9d0b937a补全 Phase 9 交互增强 — Leader 键/模型选择器/确认弹窗/鼠标/命令路由a6f590a4修复浮层回车不关闭与多行渲染错位等交互问题(本轮重点)🔧 本轮核心修复:浮层组件持有过期 state 指针
现象:命令面板里用方向键移到
/mode后按回车,面板不关闭、高亮跳回第一项/model;会话/模型选择器、确认弹窗同样「回车无响应」。根因:
state.Reduce每次返回新的*ViewState,a.state随之替换;而bindComponents()此前只重新绑定 4 个静态组件(status/stream/prompt/inspector),遗漏了 palette / help / sessionPicker / modelPicker / confirmOverlay 等浮层组件。这些浮层仍持有旧 state 指针,按键改在废弃状态上,当前state.Overlay.Active始终不变 → 回车不关闭、选中复位。修复:
bindComponents()绑定全部子组件,根除问题(app.go)。配套修复(同一提交)
mode因评分命中/model而非/mode;移除sahilm/fuzzy依赖palette.go⏎ / ␣ : executepalette.gocloseOverlay()重置Overlay.Active,修复回车不关闭app.gosessionSwitchedMsg重载历史(会清空 Stream)之后追加Switched to session: <title>提示app.goyou/neo)宽度,修复第二行起错位stream.go›→ ASCII>:前者是东亚宽度「歧义」字符,CJK 终端下被渲染成双宽,导致首行前缀与续行缩进列数不一致prompt.goprompt.go、keys.go变更说明(功能全景)
1. Command Prompt 组件(Phase 9 核心)
components/prompt.go按
InputState.Mode渲染三种内联模式并路由按键:message/command>(Accent)Enter发送、Alt+Enter / Ctrl+J 换行;/开头走 Slash 命令permission_response◌(Warning)y/n/d/a单键响应,无需 Enter;Esc取消question_answer·配套:光标闪烁(500ms)/ 左右移动 / Home·End(按 rune,中文无错位);输入历史 Normal Mode
Up/Down;底部状态行[input]/[normal]/[leader]+ 会话名 + 模型名。闪烁状态存于中央 ViewState,组件重建不丢失。2. 三层键位系统
keymap/keys.goInput / Normal / Leader 三层
Action映射,由app.go统一派发;Leader 1s 超时回退 Normal;FullHelp()分组供帮助浮层。3. 命令面板
components/palette.goCtrl+P或/打开,确定性三级匹配;Up/Down或j/k选择、Enter/Space执行、Esc关闭;支持鼠标滚轮与点击。内置/model /mode /session /compact /checkpoint /skills /help /exit。4. 浮层与选择器
会话选择器(切换/
d删除经确认弹窗)、模型选择器(切换并回写ActiveModel)、危险确认弹窗(Y/Enter确认、N/Esc/Ctrl+C取消)、帮助浮层(分组键位)。5. App 装配与命令路由
app.go组件动作 → Gateway RPC 管线(
submitMessageCmd/resolvePermissionCmd/answerQuestionCmd/loadSessionCmd/deleteSessionCmd/createSessionCmd);Ctrl+C 双退保护;鼠标分发(浮层优先,主视图滚轮控 Stream);浮层互斥 + 统一Esc逃生。变更文件清单(三个提交合计,本轮修复项加粗)
如何手工验证
0. 构建与测试(前置)
go build ./... go test ./internal/tuiv2/... -count=1 gofmt -l cmd internal预期:全绿、无格式化遗留。
1. 消息模式(默认场景)
Enter→ 进入行为流并清空;提示符为 ASCII>。第一行→ Alt+Enter(或 Ctrl+J)换行 →第二行→Enter多行整段提交。/helpEnter→ 打开帮助浮层。a中b);光标约每 0.5s 闪烁。2. 权限确认模式(单键响应)
◌与tool.* 请求 …、快捷栏[Y] 允许 [n] 拒绝 [d] 查看 diff [a] 允许全部。y(无 Enter)→ allowed;n→ denied;Esc→ 取消并回消息模式。3. ask_user 问答模式(长选项换行对齐)
Enter提交;Esc取消。4. 输入历史(Normal Mode)
发两条消息 →
Esc进 Normal →Up/Up/Down浏览,越过尾部清空。5. 底部状态行
切换模式确认
[input]/[normal]/[leader],右侧会话名 + 模型名。6. Leader 键
Esc→Space(瞬时[leader],1s 超时回退)→ 验证h/m/f/c/p/s/n/q。7. ⭐ 命令面板(本轮修复重点)
Ctrl+P打开,输入mode→ 高亮应停在/mode而非/model(修复前会错跳)。/mode,按Enter或空格 → 面板立即关闭并切到 build/plan(修复前不关闭、跳回/model)。Esc关闭;鼠标滚轮翻页、点击执行。8. 会话 / 模型选择器与确认弹窗
Space s打开会话选择器,选条目 → 切换,流内出现Switched to session: <title>(修复前无提示)。d→ 红色确认弹窗 →Y删除 /N取消,弹窗均正确关闭(修复前回车不关)。Space p→选/model(或/model)打开模型选择器,切换后状态行右侧模型名更新。9. 多行消息对齐(本轮修复)
you/neo标签宽度,不再左侧塌缩错位。10. 鼠标滚动 / Ctrl+C / 自适应
--scenario=long_output:滚轮上停自动滚动、到底恢复。--scenario=cancel_running:运行中Ctrl+C取消;空闲双击 2s 内退出。--scenario=small_terminal:缩放窗口,Prompt 宽自适应、Inspector 按断点显隐、无残留。测试
go build ./...go test ./internal/tuiv2/... -count=1app_overlay_test.go(+285)含「模拟事件流复现过期指针」回归;prompt_test.go(+37)、stream_test.go(+32) 多行渲染回归Phase 9 验收标准对照(8/8)
Enter发送、换行(Alt+Enter / Ctrl+J)y/n/d/a单键响应Up/Downgo test ./internal/tuiv2/components/覆盖三模式输入处理已知限制 / 后续
·当前用 Accent 色(文档原定 Info 色),纯视觉细节,留待打磨阶段。--backend=gateway真实后端、Checkpoint/Skills 面板项为占位,留待后续 Phase。Breaking Changes
无。仅新增独立二进制
cmd/neocode-tuiv2与internal/tuiv2包;本轮移除对sahilm/fuzzy的运行时依赖,不影响 v1 主链路。Close #708