- Complete architectural overhaul of useUnifiedCompletion hook - Unified state management: 8 separate states → single CompletionState interface - Simplified core logic: getWordAtCursor 194 lines → 42 lines (78% reduction) - Fixed infinite React update loops with ref-based input tracking - Smart triggering mechanism replacing aggressive auto-completion - Integrated @agent and @file mention system with system reminders - Added comprehensive agent loading and mention processing - Enhanced Tab/Arrow/Enter key handling with clean event management - Maintained 100% functional compatibility across all completion types Key improvements: • File path completion (relative, absolute, ~expansion, @references) • Slash command completion (/help, /model, etc.) • Agent completion (@agent-xxx with intelligent descriptions) • System command completion (PATH scanning with fallback) • Terminal-style Tab cycling, Enter confirmation, Escape cancellation • Preview mode with boundary calculation • History navigation compatibility • Empty directory handling with user feedback Architecture: Event-driven @mention detection → system reminder injection → LLM tool usage Performance: Eliminated 7-layer nested conditionals, reduced state synchronization issues Reliability: Fixed maximum update depth exceeded warnings, stable state management
4.5 KiB
4.5 KiB
终端行为对比:标准 Terminal vs 我们的实现
🔴 关键差异对比
场景1:多个匹配文件
# 文件列表:package.json, package-lock.json, public/
# ✅ 真正的终端(bash/zsh)
$ cat p[Tab]
$ cat p█ # 第一次Tab:没反应(或蜂鸣)
$ cat p[Tab][Tab]
package.json package-lock.json public/ # 第二次Tab:显示选项
$ cat pa[Tab]
$ cat package█ # 补全到公共前缀 "package"
$ cat package[Tab][Tab]
package.json package-lock.json # 再显示剩余选项
# ❌ 我们当前的实现
$ cat p[Tab]
▸ 📄 package.json # 立即显示菜单
📄 package-lock.json
📁 public/
场景2:唯一匹配
# ✅ 真正的终端
$ cat READ[Tab]
$ cat README.md█ # 立即补全,一步到位
# ✅ 我们的实现(这个是对的!)
$ cat READ[Tab]
$ cat README.md█ # 也是立即补全
场景3:目录补全后继续
# ✅ 真正的终端
$ cd src[Tab]
$ cd src/█ # 补全并加斜杠,光标在斜杠后
$ cd src/[Tab] # 可以继续Tab
components/ hooks/ utils/ # 显示src/下的内容
# ❌ 我们的实现
$ cd src[Tab]
$ cd src/█ # 补全后结束
$ cd src/[Tab] # 需要重新检测上下文
场景4:命令补全
# ✅ 真正的终端
$ git a[Tab]
$ git add█ # 唯一匹配,直接补全
$ git [Tab][Tab] # 空前缀,需要双Tab
add commit push pull status # 显示所有git命令
# ⚠️ 我们的实现
$ /he[Tab]
$ /help█ # 命令补全工作正常
$ /[Tab] # 但立即显示菜单(应该需要双Tab)
▸ help
model
agents
📊 行为差异总结
| 特性 | 标准终端 | 我们的实现 | 影响 |
|---|---|---|---|
| 双Tab显示 | ✅ 需要按两次 | ❌ 第一次就显示 | 打断输入流程 |
| 公共前缀 | ✅ 智能补全 | ❌ 直接显示菜单 | 多余的选择步骤 |
| 连续补全 | ✅ 自然流畅 | ❌ 需要重新触发 | 效率降低 |
| 空前缀Tab | ✅ 需要双击 | ❌ 立即显示 | 意外触发 |
| 蜂鸣反馈 | ✅ 无匹配时蜂鸣 | ❌ 静默 | 缺少反馈 |
🎯 核心问题
1. Tab计数缺失
// 我们现在的代码(错误)
if (key.tab) {
showSuggestions() // 立即显示
}
// 应该是
if (key.tab) {
if (isSecondTab()) {
showSuggestions()
} else {
tryComplete()
}
}
2. 公共前缀算法缺失
// 需要添加
function getCommonPrefix(items: string[]): string {
if (items.length === 0) return ''
if (items.length === 1) return items[0]
let prefix = items[0]
for (let i = 1; i < items.length; i++) {
while (!items[i].startsWith(prefix)) {
prefix = prefix.slice(0, -1)
}
}
return prefix
}
3. 状态管理不足
// 当前:无状态
// 需要:
interface CompletionState {
lastTabTime: number
tabCount: number
lastPrefix: string
lastSuggestions: string[]
isShowingMenu: boolean
}
💡 为什么这些差异重要?
用户期望
- 肌肉记忆:数十年的终端使用习惯
- 效率优先:最少的按键完成任务
- 预测性:行为必须可预测
实际影响
- 输入中断:过早显示菜单打断思路
- 额外操作:本可以自动补全的需要手动选择
- 认知负担:行为不一致增加心智负担
🔧 改进优先级
🔴 必须修复(破坏体验)
- 双Tab机制 - 这是最基础的终端行为
- 公共前缀补全 - 减少不必要的选择
- 连续补全 - 路径导航的基础
🟡 应该改进(提升体验)
- 蜂鸣反馈 - 告诉用户发生了什么
- 灰色提示 - 现代终端的标配
- 历史感知 - 更智能的排序
🟢 可以添加(锦上添花)
- 模糊匹配 - 容错输入
- 预览功能 - 显示文件内容
- 自定义规则 - 用户定制
📝 用户故事
当前体验 😤
我:想输入 "cat package.json"
我:输入 "cat p" + Tab
系统:弹出菜单让我选择
我:需要按方向键选择
我:按Enter确认
结果:5个操作才完成
理想体验 😊
我:想输入 "cat package.json"
我:输入 "cat pa" + Tab
系统:自动补全到 "cat package"
我:输入 ".j" + Tab
系统:补全到 "cat package.json"
结果:3个操作完成
🎬 下一步
最小可行改进(MVP):
- 实现Tab计数器
- 添加公共前缀补全
- 修复连续补全
这三个改动就能让体验提升80%!