首页
/ pi 终端 UI 演进实录:从 @earendil-works/pi-tui 变更日志看差分渲染、备用屏 TUI 与键盘协议的完整实现脉络

pi 终端 UI 演进实录:从 @earendil-works/pi-tui 变更日志看差分渲染、备用屏 TUI 与键盘协议的完整实现脉络

2026-09-06 14:30:03作者:俞予舒Fleming

pi 项目的终端交互层由 packages/tui 中的 @earendil-works/pi-tui 包承载:这是一个带差分渲染(differential rendering)与同步输出(CSI 2026)的最小化终端 UI 框架,也是上层 coding-agent CLI 的全部界面基础。本文以 packages/tui/CHANGELOG.md 为主体,完整梳理该包从 0.29.0(2025-12-25)到 0.84.4(2026-08-28)的版本演进,并结合 packages/tui/src 的源码与 packages/tui/package.json 配置,还原每一项关键变更背后的 API 形态、默认值与实现位置,帮助你既能读懂变更日志的每条记录,也能定位到对应的源码进行二次开发。

一、包概览与运行前提

packages/tui/package.json 可以确认当前发布状态:

  • 包名 @earendil-works/pi-tui,当前版本 0.84.4,MIT 许可,type: module,入口 dist/index.js
  • engines.node>=22.19.0——这是 0.75.0 版本(2026-05-17)作为破坏性变更提出的最低 Node.js 要求,使用该包需要以此版本为前提;
  • 运行时依赖只有两个:marked@18.0.5(Markdown 解析,0.79.5 版本升级至此版本)与 get-east-asian-width@1.6.0(东亚字符宽度计算,支撑 CJK/宽字符排版);
  • 开发依赖 @xterm/headlessVirtualTerminal 测试用)与 chalk(示例主题着色);
  • 包内附带 native/win32native/darwin 两套预编译原生模块(prebuilds/**/*.node、C 源码与构建脚本),用于 Windows VT 输入修饰键检测等场景。0.75.5 版本(2026-05-23)把原先可选的 koffi 依赖替换为这个极小的 vendored native helper,显著减小安装体积同时保留 Shift+Tab 等按键处理;0.84.0 还修复了 npm 包遗漏 Darwin/Windows 原生模块重建所需源码与构建脚本的问题。
  • 测试方式为 node --test test/*.test.ts(见 package.json 的 test 脚本),演示程序为 packages/tui/test/chat-simple.ts,可用 npx tsx test/chat-simple.ts 运行。

框架的整体能力在 packages/tui/README.md 中概括为:可互换的渲染器(TuiMainScreen / TuiAltScreen)、仅重绘变化行的差分渲染、CSI 2026 同步输出防闪烁、Bracketed Paste(超过 10 行的粘贴生成 [paste #1 +50 lines] 标记)、组件化接口(render(width) 返回行数组)、主题支持、内联图片(Kitty/iTerm2 图形协议)、文件路径与斜杠命令自动补全。变更日志中的绝大多数条目,都是围绕这些核心能力展开的迭代。

二、版本时间线:从按键解析工具到全屏 TUI 框架

变更日志共覆盖约 9.5 周内的 100+ 个版本号。按主题聚类后,演进脉络可分为六个阶段:

阶段 版本区间 时间 核心主题
1 0.29.0 → 0.37.8 2025-12-25 ~ 2026-01-07 按键检测体系重构(matchesKey 取代 isXxx())、Kitty 键盘协议与按键释放事件、粘贴文件路径自动补空格
2 0.38.0 → 0.49.3 2026-01-08 ~ 2026-01-22 组件生态成型:EditorComponent 接口、StdinBuffer 批量输入拆分、Overlay 合成与 CSS 式定位、IME 硬件光标、kill ring/undo、fuzzy 匹配、OSC 8 超链接
3 0.50.0 → 0.62.0 2026-01-26 ~ 2026-03-23 编辑体验打磨:全局键位管理器(破坏性变更)、16ms 帧预算渲染调度、OSC 52/OSC 11 终端查询、CJK/宽字符换行与宽度计算
4 0.63.0 → 0.74.x 2026-03-27 ~ 2026-05-07 多终端兼容性攻坚:Kitty 协议协商、tmux/Zellij 下 modifyOtherKeys 回退、WezTerm/iTerm2 图片放置、Node.js 22.19 门槛
5 0.75.x → 0.83.0 2026-05-17 ~ 2026-07-29 平台与工具链收敛:vendored 原生模块替代 koffi、PI_TUI_WRITE_LOG 目录模式、宽字符宽度修正
6 0.84.0 → 0.84.4 2026-08-06 ~ 2026-08-28 备用屏全屏 TUI 大版本:TuiAltScreen 布局/滚动/搜索/选择/滚动条,以及 LaTeX 终端渲染、能力检测的环境与程序化覆盖

其中值得完整保留记录的破坏性变更有三处(变更日志中以 Breaking Changes 小节标出):

  1. 0.33.0(2026-01-04):删除全部 isXxx() 按键检测函数(isEnter()isEscape()isCtrlC() 等),统一改用 matchesKey(data, keyId)(如 matchesKey(data, "ctrl+c")"shift+enter""alt+left")。这影响所有使用 ctx.ui.custom() 处理键盘输入的钩子与自定义工具。同期引入 Editor.insertTextAtCursor(text)EditorKeybindingsManager
  2. 0.47.0(2026-01-16)Editor 构造函数改为必须接收 TUI 作为第一个参数:new Editor(tui, theme),以启用内容超过终端高度时的自动垂直滚动(最大高度为终端的 30%,最少 5 行);新增 Focusable 接口、CURSOR_MARKER 常量与 isFocusable() 类型守卫,用于 IME 候选窗定位。
  3. 0.61.0(2026-03-20):用单一全局键位管理器替换原“仅编辑器”的键位存储,键位 id 全部加命名空间。完整映射关系如下(keybindings.json 保持向后兼容,每个定义会把新内部 id 映射回原公开配置键):
旧 id 新 id
cursorUp / cursorDown / cursorLeft / cursorRight tui.editor.cursorUp / cursorDown / cursorLeft / cursorRight
cursorWordLeft / cursorWordRight tui.editor.cursorWordLeft / cursorWordRight
cursorLineStart / cursorLineEnd tui.editor.cursorLineStart / cursorLineEnd
jumpForward / jumpBackward tui.editor.jumpForward / jumpBackward
pageUp / pageDown tui.editor.pageUp / pageDown
deleteCharBackward / deleteCharForward tui.editor.deleteCharBackward / deleteCharForward
deleteWordBackward / deleteWordForward tui.editor.deleteWordBackward / deleteWordForward
deleteToLineStart / deleteToLineEnd tui.editor.deleteToLineStart / deleteToLineEnd
yank / yankPop / undo tui.editor.yank / yankPop / undo
newLine tui.input.newLine
submit / tab / copy tui.input.submit / tab / copy
selectUp / selectDown tui.select.up / down
selectPageUp / selectPageDown tui.select.pageUp / pageDown
selectConfirm / selectCancel tui.select.confirm / cancel

应用侧扩展方式为:通过 TypeScript 声明合并扩展 interface Keybindings,用 TUI 与应用两套定义创建一个管理器,再 setKeybindings(...) 安装。该版本同时修复了用户自定义键位无法遮蔽同键默认绑定的问题。 4. 0.75.0(2026-05-17):最低 Node.js 版本提升至 22.19.0。

三、双渲染器架构:主屏与备用屏

0.84.0(2026-08-06)是变更日志中体量最大的一个版本,它把“备用屏全屏 TUI”推为一等公民。结合源码可以确认其结构:

  • 共享 TuiMode 类型,主屏/备用屏渲染器各自带 mode 判别值(对应 packages/tui/src/tui-main-screen.tspackages/tui/src/tui-alt-screen.ts 中的 TuiMainScreenTuiAltScreen 两个类,TuiAltScreenmode"fullscreen",并实现 ViewportTUI 接口,可经 isViewportTUI() 类型守卫判断);
  • 接口兼容的两种渲染器,应用自持滚动(issue #7304):TuiMainScreen 写入主终端缓冲区、保留终端 scrollback;TuiAltScreen 在备用缓冲区维护固定高度视口,退出时恢复主缓冲区并打印完整最终文档;
  • TUI 生命周期与渲染状态交接 API,支持在不重放主屏内容的情况下替换渲染器;
  • 备用屏布局系统:VStackHStack 与嵌套 ScrollView,支持受限尺寸分配、sticky 区域、指针目标化滚动(栈条目支持 basisgrowshrinkminSizemaxSize 与响应式 visible 回调;0.84.0 的 Fixed 条目还记录了“嵌套栈布局忽略子组件最小尺寸”的修复);
  • 拖选跨屏外滚动视图内容时的边缘自动滚动;比例滚动条(鼠标拖拽、Home/End 文档导航、auto 瞬态模式与预留最右列的 always 模式,模式可运行时切换);
  • 视口分页滚动与 OSC 133 语义提示符导航;与垂直光标移动解耦的、可配置的上一/下一提示符历史动作;
  • 备用屏渲染器上的堆叠瞬态通知(issue #7361)。

TuiAltScreen 的构造参数在 packages/tui/src/tui-alt-screen.ts 中定义为 TuiAltScreenOptions,变更日志与源码可互相印证其默认值:

export interface TuiAltScreenOptions {
  wheelScrollLines?: number;   // 每次滚轮事件滚动的逻辑行数(默认 1,0.84.0 从 3 调细)
  mouse?: boolean;             // 是否捕获鼠标事件(默认 true)
  searchMatchStyle?: (text: string) => string;         // 非当前搜索命中的样式(默认下划线)
  searchCurrentMatchStyle?: (text: string) => string;  // 当前命中样式(默认加粗+反色)
  openUrl?: (url: string) => void;          // 主键点击激活 OSC 8 超链接的回调
  onRightClickPaste?: () => void;           // 右击粘贴(目前仅在 Windows 启用)
  copyOnSelect?: boolean;    // 鼠标释放时自动复制选区(默认 true)
  copySelection?: (text: string) => Promise<boolean>; // 自定义剪贴板写入,返回 false 会闪错误提示
}

源码中的默认实现(tui-alt-screen.ts):wheelScrollLines = max(1, floor(options.wheelScrollLines ?? 1))mouse ?? truesearchMatchStyle 默认 \x1b[4m...\x1b[24m(下划线)、searchCurrentMatchStyle 默认 \x1b[1;7m...\x1b[22;27m(加粗反色)、copyOnSelect ?? true。0.84.4 进一步为 copyOnSelect 提供了 getCopyOnSelect()/setCopyOnSelect() 运行时切换,以及 hasActiveSelection()copyActiveSelectionToClipboard() 等程序化检测/复制当前全屏选区的辅助 API(issue #7720)。

主屏一侧的渲染策略在 packages/tui/src/tui-main-screen.ts 中可直接读到:宽度变化总是全量重渲染(换行结果变化);高度变化通常也全量重渲染,但检测到 Termux 会话时跳过(避免软键盘显隐触发整屏历史重放);常规更新则通过逐行比较找到首末变化行做增量重绘;整个更新被包在 \x1b[?2026h/\x1b[?2026l(synchronized output)之间保证原子刷新。0.84.4 还修复了“图片密集输出超过 V8 字符串长度上限导致主屏渲染崩溃”的问题(issue #8028)。

四、全屏键位体系:从 unbound 动作到可绑定快捷键

0.84.x 连续两个版本为备用屏视口引入了新的“无默认按键”(unbound)动作,供宿主应用自行绑定,这在 packages/tui/src/keybindings.tsTUI_KEYBINDINGS 中都有对应条目:

  • 0.84.1:tui.altScreen.halfPageUp / tui.altScreen.halfPageDown(半屏滚动);
  • 0.84.2:tui.altScreen.lineUp / tui.altScreen.lineDown(单行滚动,issue #7903,贡献者 @midastruth)。

连同既有条目,当前备用屏键位空间包括:pageUp/pageDownpreviousPrompt/nextPrompt(OSC 133 语义提示符跳转)、search(默认 ctrl+shift+f,见 keybindings.ts)、searchNextEnter/Ctrl+G)、searchPreviousShift+Enter/Ctrl+Shift+G)、searchCloseEscape)、top(默认 home)、bottom(默认 end)。其中增量搜索是 0.84.2 加入的:对主滚动视图内容做可配置样式的匹配高亮,并修复了“手动滚动时搜索位置弹回当前命中”“碎片化 SGR 鼠标输入泄漏进搜索框”两个问题。

0.84.1 还为全屏选择体验补全了编辑器式语义:双击按词/空白选择、粒度感知的拖拽选择、三击按段落选择(issue #7725/#7733,@volsa)。0.84.4 的 Fixed 条目进一步修正了“全屏双击选词在 /- 处错误切分路径与 kebab-case 标识符”(issue #7746)。

键盘协议协商是这条时间线里反复出现的主题,可以按版本回溯其收敛过程:

  • 0.37.6(2026-01-06):支持 Kitty 键盘协议 flag 2 的按键释放事件,导出 isKeyRelease(data)isKeyRepeat(data)KeyEventType 类型;
  • 0.46.0:Kitty 协议终端下非拉丁键盘布局(俄语、乌克兰语等)的 Ctrl 组合键可正常工作;
  • 0.56.3:Kitty 协议不可用时回退到 xterm modifyOtherKeys 模式 2,使 tmux 内的 Shift+Enter/Ctrl+Enter 可用;
  • 0.60.0:修复 tmux 下 modifyOtherKeys 对 Backspace/Escape/Space 的匹配,并按 Windows Terminal 与旧式终端区分处理裸 \x08 退格歧义;
  • 0.70.3/0.70.1:Kitty CSI-u + 原始字符叠加导致的重复字符(意大利语布局)、括号粘贴内 CSI-u Ctrl+字母解码问题;
  • 0.77.0:键盘协议协商忽略错配或延迟的终端响应,避免误判 Kitty 协议(@mitsuhiko 贡献);
  • 0.79.0:Shift+Enter 的 Kitty 协议回退从“超时驱动”改为“响应驱动”,消除间歇性失效(issue #5188)。

与之配套的 SSH 高延迟修复在 0.84.2:经 SSH 传输时被拆成多段的 Alt+Enter 曾被误判为 Escape。修复引入 PI_TUI_ESC_TIMEOUT 环境变量且该超时仅作用于“孤立 Escape 输入”。其实现见 packages/tui/src/terminal.ts

const DEFAULT_ESCAPE_TIMEOUT_MS = 10;
const DEFAULT_SSH_ESCAPE_TIMEOUT_MS = 100;

export function resolveEscapeTimeoutMs(env: NodeJS.ProcessEnv = process.env): number {
  const configured = Number(env.PI_TUI_ESC_TIMEOUT);
  if (Number.isFinite(configured) && configured > 0) {
    return configured;
  }
  if (env.SSH_CONNECTION || env.SSH_TTY) {
    return DEFAULT_SSH_ESCAPE_TIMEOUT_MS;
  }
  return DEFAULT_ESCAPE_TIMEOUT_MS;
}

即:显式配置 > 0 时生效;否则检测到 SSH_CONNECTION/SSH_TTY 时放宽到 100ms;本地默认 10ms。

五、编辑器与输入:粘贴、撤销、IME

变更日志中 Editor/Input 组件的迭代密度最高,按主题归并:

  • 粘贴标记(paste marker):大段粘贴(>10 行)折叠为 [paste #1 +50 lines] 标记。围绕标记的记账逻辑历经多轮修复——0.58.0 将标记视为不可分割的原子段(换行/光标导航不拆散标记);0.80.4 修复标记删除或终端状态清空后的陈旧粘贴状态(issue #6397);0.81.0 修复“删除粘贴标记时撤销注册表损坏”,撤销会连同文本一起恢复粘贴注册表、标记重编号按 id 升序平移注册表条目,提交后的提示词不再残留字面 [paste #N ...] 文本(issue #6844)。另有 0.29.0 的“粘贴文件路径后自动补空格”(拖拽 macOS 截图场景,@mitsuhiko 贡献)、0.79.0 的“历史导航返回时恢复当前草稿”、0.50.8 的垂直导航 sticky column(优先列恢复)、0.50.6 的“在首/末视觉行按 Up/Down 跳到行首/行尾”、0.50.4 的 Ctrl+B/Ctrl+F 词导航与 Ctrl+]/Ctrl+Alt+] 字符跳转。
  • kill ring 与 undo:0.49.0 引入 Emacs 式 kill ring(Ctrl+K 删到行尾、Ctrl+Y 粘回、Alt+Y 弹栈,配合 Ctrl+- undo,连续词字符合并为单一 undo 单元,fish 风格);0.52.8 将同样的能力(含 Ctrl+Z undo)带到 Input 组件;Ctrl+D 删词前向在 0.50.2 加入。
  • IME 硬件光标:0.47.0 起 Editor/Input 实现 Focusable,TUI 扫描渲染输出中的 CURSOR_MARKER(零宽 APC 转义)并把硬件光标定位到该处,供终端的 IME 候选窗定位;0.48.0 起硬件光标默认隐藏(PI_HARDWARE_CURSOR=1 开启,取代旧的 PI_NO_HARDWARE_CURSOR=1 语义),0.49.0 提供 showHardwareCursor getter/setter;0.79.1 修复斜杠命令补全弹出时 IME 光标错位(issue #5283)。
  • 宽字符/CJK:0.58.0 一族修复集中处理了 CJK 全角字符下的 Input 横向滚动(按视觉列宽严格切分,防溢出与崩溃)、wordWrapLine 在宽字符恰好落在换行边界时的溢出、制表符归一化为空格(setText()/粘贴路径);0.74.1 修复泰语 Sara Am/老挝 AM 元音的渲染伪影;0.79.1/0.79.2 修复混排拉丁与 CJK 文本的换行空隙问题(按 grapheme 边界断行)。
  • 其他:0.51.4 修复输入滚动切碎 emoji 序列;0.50.2 新增 autocompleteMaxVisible 选项(含 getter/setter)控制补全下拉高度;0.50.2 修复带空格路径的引号补全;0.81.0 修复终端关闭时先清除软件光标再恢复硬件光标,避免双光标伪影(issue #6790)。

六、Markdown 与 LaTeX 渲染演进

Markdown 组件的迭代在变更日志中留下了清晰轨迹,解析底座为 marked(0.79.5 固定到 18.0.5,与 package.json 一致):

  • 流式渲染:0.79.9 修复流式输出中“部分闭合的代码栅栏导致代码块收缩/闪烁”(issue #5846,@xl0)——这对 agent 流式输出场景至关重要;
  • 表格:0.50.2 引入正确的行分隔线与最小列宽(issue #997);0.84.3 修复换行表格内链接的颜色泄漏到边框与相邻单元格(含引用块内表格,issue #8335);
  • 引用块:0.56.1 隔离 blockquote 样式防泄漏;0.56.0 修复嵌套列表内容丢失(按块级 token 渲染子节点);0.63.0 修复内联链接后 blockquote 文字色断链;
  • 列表:0.44.0 修复代码块打断列表连续性导致所有项显示“1.”;0.74.1 修复任务列表复选框;0.79.2 修复松散列表项之间的空行分隔;0.80.2 保留无序列表源标记,孤立的 + 不再渲染成 -;0.76.0 提供可选渲染器选项保留有序列表源标记(issue #5013),0.80.3 提供保留源反斜杠转义的选项(issue #6105);
  • 样式一致性:0.43.0 起每行渲染后重置 ANSI 样式防跨行泄漏;0.62.0 修复标题内联代码后标题样式丢失、H1 下划线样式泄漏到行尾填充(0.65.0);0.67.4 起删除线要求严格 ~~text~~ 双波浪号且非空白边界;
  • LaTeX:0.84.0 新增“终端友好的 Unicode LaTeX 渲染”——覆盖行内/行间公式、分式、上下标、常用符号、对齐方程、cases 与矩阵;0.84.1 修复关系符/乘号/命名算子的间距,并支持叠分式矩阵、算子极限、相邻矩阵的组合;0.84.2 修复“跨行换行的必填参数被解析为空”(issue #7760)与“控制空格被换行拆开导致整个表达式回退为原始源码”。对应实现为 packages/tui/src/latex.ts 中的 LatexParser 与导出的 renderLatex(见 packages/tui/src/index.ts)。

七、终端能力检测与内联图片

能力检测(capability detection)与图片协议是 0.84.4 的另一条主线,其源码位于 packages/tui/src/terminal-image.ts(导出 detectCapabilitiessetCapabilitiessetCapabilityOverridesresetCapabilitiesCachehyperlink、Kitty/iTerm2 编解码等,见 index.ts):

  • 0.84.4(Added):为 OSC 8 超链接、内联图片协议、truecolor 能力增加环境变量与程序化覆盖入口(issue #8665)。这与导出列表中新增的 setCapabilityOverrides() 对应,用于在 CI、嵌入式终端或测试中强制指定能力;
  • OSC 8 超链接:0.67.6 引入——终端声明支持时为 Markdown 链接渲染可点击超链接,并收紧 detectCapabilities():未知终端默认 hyperlinks: false,tmux/screen(含嵌套会话)下强制关闭,防止终端静默吞掉 OSC 8 序列导致 URL 消失;0.70.0 修复换行链接的 BEL 终止符丢失(OAuth 登录 URL 每一行都可点击);0.76.0 使 Windows Terminal 启用 OSC 8、JetBrains 终端启用 truecolor 但禁用 OSC 8(issue #4923/#5037);0.78.0 修复 tmux 透传(客户端支持时,@mpazik 贡献);0.84.0 修复截断宽度后 OSC 8 未闭合(issue #7657);
  • 图片协议:Kitty 图形协议(Kitty/Ghostty/WezTerm)与 iTerm2 内联图片。典型修复包括:0.74.1 视口高度小于渲染图片时的放置(issue #4461)、0.73.1 图片 id 由终端分配并将解析值限制到合法范围、cmux 终端禁用内联图片、0.79.4 WezTerm 全量重绘回退下的内联图片(issue #5618/#4415)、0.79.7 Warp 终端检测(@dodiego 贡献)、0.84.0 修复 iTerm2 图片 payload 缺失 xterm.js 图片插件所需的尺寸元数据(issue #7612)、备用屏重绘时重复发送 Kitty 图片数据与越界重叠 sticky 区域等;
  • 备用屏图片兼容性(README 与变更日志一致):TuiAltScreen 支持 Kitty 协议终端下的内联图片与视口裁剪;iTerm2 协议无法删除既有放置或裁剪源,因此 TuiAltScreen 在 iTerm2 下将图片组件渲染为文本占位,TuiMainScreen 则正常渲染 iTerm2 图片;
  • OSC 9;4 进度指示:0.69.0 在 Terminal 接口新增 setProgress(active: boolean);0.70.0 以周期性更新保活,避免 Ghostty 在长任务中清除指示器(issue #3610);0.84.0 修复清除时输出完整 OSC 9;4 序列(issue #7581);
  • 终端外观查询:0.79.4 支持 OSC 11 背景色查询(issue #5385);0.79.7 增加颜色方案查询/通知 API(TUI.queryTerminalColorScheme()Tui.onTerminalColorSchemeChange()TUI.setTerminalColorSchemeNotifications(),issue #5874),0.84.0 修复批量颜色方案报告被解析成单条畸形响应的问题(issue #7550)。

八、性能与渲染调度的关键节点

变更日志中的性能条目可归纳为四个里程碑:

  1. 0.42.5(2026-01-11):差分渲染只重绘变化行,减少闪烁(issue #617);
  2. 0.31.0(2026-01-02)visibleWidth() 重写为基于 grapheme 的宽度计算,Bun 上约 10 倍、Node 上约 15% 提速(@nathyong 贡献);同版本修复 ZWJ emoji(彩虹旗、家庭序列)被拆分为多字符的宽度错误;
  3. 0.65.2(2026-04-06):流式高负载输出下把 requestRender() 合并到 16ms 帧预算,同时保留 requestRender(true) 的立即渲染语义。配套地,0.67.0 为测试套件新增 VirtualTerminal.waitForRender() 辅助,等待 16ms 节流渲染管线稳定后再断言视口状态;
  4. 0.84.2(2026-08-14):备用屏每帧分配开销降低约 9-18 倍——把整宽布局行作为直接行引用绘制,而非每帧都通过 ANSI/grapheme 分段重新合成每个可见行。

此外还有若干“防栈溢出/防崩溃”的底层修复,体现对超长内容的防御:0.67.0 Container.render() 用循环 push 替换 Array.push(...spread),避免长会话触发 V8 参数上限(issue #2651);0.78.0 修复超长换行行的 ANSI 换行栈溢出(issue #5185);0.62.0 truncateToWidth() 对超大字符串采用流式截断并保持 SGR 样式安全闭合(issue #2447);0.84.4 修复图片密集输出超过 V8 字符串长度上限时主屏渲染崩溃(issue #8028)。

输入侧,0.38.0 引入 StdinBuffer(改编自 OpenTUI,MIT 许可)把 SSH 批处理到达的 stdin 拆分为独立按键序列,解决按键丢失;0.52.12 提供 Terminal.drainInput() 在退出前排空 stdin(最长 1s),防止 Kitty 按键释放事件经慢速 SSH 泄漏到父 shell(issue #1204)。

九、调试环境变量速查

变更日志中沉淀了一组调试/行为开关,均可在源码中核实:

环境变量 作用 默认值 源码位置
PI_TUI_WRITE_LOG 捕获写入 stdout 的原始 ANSI 流;值为文件路径时直接写入该文件,值为已存在目录时按实例生成唯一文件 tui-<时间戳>-<pid>.log(0.63.0 起支持目录,issue #2508,@mrexodia) 未设置则不记录 terminal.ts
PI_DEBUG_REDRAW=1 记录全量重绘触发原因到 <logDirectory>/pi-debug.log 关闭 tui-main-screen.ts
PI_HARDWARE_CURSOR=1 显示硬件光标(默认隐藏,保留软件光标渲染,0.48.0 起) 关闭 tui.ts
PI_CLEAR_ON_SHRINK=1 内容收缩时清屏重绘(0.51.1 起默认关闭,也可用 setClearOnShrink(true) 打开) 关闭 tui.tstui-main-screen.ts
PI_TUI_ESC_TIMEOUT 孤立 Escape 的重组等待毫秒数,用于高延迟/SSH 终端 本地 10ms,SSH 会话 100ms terminal.ts

相关但属于 coding-agent 层的目录配置也可在日志中找到呼应:0.82.0 修复了调试/崩溃日志总是写到 ~/.pi/agent 的问题,现在会使用已配置的 TUI 日志目录(包括 PI_CODING_AGENT_DIR 指定的位置,issue #6958)。

十、其他值得记录的 API 增量

变更日志中还有不少单点但实用的 API 变化,按版本列出以便检索:

  • 0.34.1:键位系统支持 32 个符号键(SymbolKey 类型、Key.backtickKey.comma 等),matchesKey()/parseKey() 同步更新;
  • 0.34.0Editor.getExpandedText() 返回粘贴标记展开后的真实内容;
  • 0.37.6/0.37.8Component.wantsKeyRelease 属性(默认 false)选择接收按键释放事件;
  • 0.38.0EditorComponent 接口(自定义编辑器实现入口);
  • 0.43.0fuzzyFilter()/fuzzyMatch() 工具,斜杠命令补全由前缀匹配升级为模糊匹配(0.73.0 又让精确匹配在排序上优先);
  • 0.45.6OverlayOptions 的 CSS 式定位/尺寸(width/maxHeight/row/col 支持数字或 "50%" 百分比串、minWidthanchoroffsetX/Ymargin)、visible 响应式回调、showOverlay() 返回 OverlayHandlehide/setHidden/isHidden),0.57.0 再补 nonCapturing 非捕获模式与 focus()/unfocus()/isFocused()(overlay 合成顺序改为按焦点排序,聚焦者在上);
  • 0.49.0showHardwareCursor getter/setter;
  • 0.49.3MarkdownTheme.codeBlockIndent(默认 2 空格);
  • 0.50.0PI_TUI_WRITE_LOG 首次引入、TUI.fullRedraws 只读属性;
  • 0.52.8EditorComponent.pasteToEditor() 程序化粘贴;
  • 0.52.10TUI.addInputListener/removeInputListener,允许在组件处理前拦截、转换或消费原始输入;
  • 0.54.1:koffi 改为动态 require,避免 bun 把全部 18 个平台 .node 文件(约 74MB)打进每个编译产物;
  • 0.58.2SelectListLayoutOptions 可配置主列尺寸与自定义主标签截断钩子;
  • 0.60.0:tmux 下 modifyOtherKeys 的 Backspace/Escape/Space 修复;
  • 0.68.0LoaderIndicatorOptionsLoader.setIndicator(),支持动画/静态/隐藏三种加载指示(issue #3413);
  • 0.69.0Terminal.setProgress(active)(OSC 9;4);AutocompleteProvider.shouldTriggerFileCompletion?() 让扩展包装器获得通用堆叠补全,# 成为与 @ 并列的自然补全触发符(issue #2983);
  • 0.71.0ProcessTerminal 在回退 80x24 前先读取 COLUMNS/LINES(issue #4004);
  • 0.79.1AutocompleteProvider.triggerCharacters,编辑器补全可按 provider 定义的 token 前缀自然触发(issue #4703);
  • 0.79.4:OSC 11 背景色查询;0.79.7:sliceByColumn(ANSI 感知的水平列切片)导出;
  • 0.80.0Ctrl+J 成为与 Shift+Enter 并列的默认换行键;
  • 0.83.0:长图片回退路径在窄终端中溢出、家目录路径缩写、终端支持超链接时绝对路径可点击(issue #7262)。

十一、如何验证与深入阅读

本包为只读仓库,验证方式如下(均从 monorepo 根目录执行,工作目录为 packages/tui):

# 从 monorepo 根安装依赖
npm install

# 类型检查(根目录脚本)
npm run check

# 运行 TUI 包的单元测试(node --test 驱动,含 VirtualTerminal 差分渲染断言)
node --test --test-reporter=dot test/*.test.ts

# 交互式演示:Markdown 消息 + 加载指示 + 自动补全编辑器
npx tsx test/chat-simple.ts

# 抓取原始 ANSI 流用于调试
PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx test/chat-simple.ts

建议的源码阅读路线(均由变更日志条目反向定位):

十二、小结

packages/tui/CHANGELOG.md 的九个半月迭代史可以看到一条清晰的主线:pi-tui 从“按键解析 + 组件渲染”的底层工具,逐步长成具备双渲染器(主屏/备用屏)、应用自持滚动视口、模糊搜索、鼠标选择复制、LaTeX/Markdown 富文本与多终端能力协商的完整 TUI 框架。变更日志中每条记录都能在 packages/tui/src 中找到对应实现——从 TuiAltScreenOptions 的默认值、resolveEscapeTimeoutMs() 的 SSH 分支,到 TUI_KEYBINDINGS 中的 tui.altScreen.* 动作表——这使得该文档不仅是发布说明,更是一份可溯源的 API 演进索引。升级该包时,建议重点核对 0.33.0、0.47.0、0.61.0、0.75.0 四个破坏性变更点的迁移要求,以及你所在终端环境(tmux、WezTerm、iTerm2、Windows Terminal)对应的能力检测修复版本。

登录后查看全文
热门项目推荐
相关项目推荐