Skip to content

fix: TUI 超宽行崩溃(related 浏览器 + /db query 渲染路径) - #20

Merged
zavier merged 4 commits into
mainfrom
fix/related-overflow
Aug 3, 2026
Merged

fix: TUI 超宽行崩溃(related 浏览器 + /db query 渲染路径)#20
zavier merged 4 commits into
mainfrom
fix/related-overflow

Conversation

@zavier

@zavier zavier commented Aug 3, 2026

Copy link
Copy Markdown
Owner

问题

/db related/db query 在长表名/长 SQL/中文数据/展开态长值场景下崩溃:

Error: Rendered line N exceeds terminal width (248 > 163).
This is likely caused by a custom TUI component not truncating its output.

根因(三处,同一崩溃模式)

  1. related-browser overlay:表切换行(6 个长表名标签 join)与表格行未按 overlay 宽度截断——Text 不自动截断。
  2. /db query 渲染路径(本 PR 第二部分):
    • SQL: ${doc.sql} 元数据行不截断(长 SQL 直接展示)
    • 折叠态表格 pad() 按 UTF-16 码元截断、布局预算按码元计算——中文/emoji 显示宽度 2 倍,行必然超宽
    • 展开态 formatVerticalFull 长值完全不截断
    • 关联表摘要长表名 join 不截断
  3. result-table 转置/纵向下限钳制:窄宽度下 cellWidth 下限 4 / valueCap 下限 20 使行宽超出给定 width。

修复

  • related-browserbuild() 对所有行 truncateToWidth(ANSI 安全)。
  • renderers(/db query):渲染边界对每行 truncateToWidth(width)——兜底覆盖所有超宽来源。
  • result-table
    • 理想列宽、单元格截断、列名补齐全部改用 visibleWidth(与 TUI 宽度断言同一把尺子);纯文本截断自实现 truncatePlain(不用 truncateToWidth,它会注入 \x1b[0m,破坏表格行纯文本契约)
    • 转置 cellWidth 下限 4→1、纵向 valueCap 下限 20→1,数学上保证行宽 ≤ width

验证

新增 15 个回归测试:窄宽度(40/55/70/90)下转置/纵向所有行 visibleWidth ≤ width;中文单元格/中文列名表格行宽约束 + 无 ANSI 断言;长表名标签截断保留省略号;renderQueryResult 长 SQL/展开态长值/关联表摘要全行 ≤ width。

npx tsc --noEmit ✓ · vitest 271 tests ✓ · oxlint 0 errors ✓ · oxfmt ✓

zavier added 3 commits August 3, 2026 23:08
db_query/db_tables/db_discover/db_tools 此前未定义 renderResult,
pi 默认把 content 全文展示在页面上,表数量多或 schema 大时刷屏。

新增 tools/tool-result-summary.ts(纯函数,按 details 形状生成中文
摘要,未知形状返回 undefined)+ tools/tool-result-render.ts(薄层
渲染器工厂:isPartial 显示处理中、错误红色展示、展开态全文、折叠态
摘要 + keyHint 提示)。db_tables 的 details 补充 columnCount/
indexCount,db_discover 补充 databaseCount 供摘要使用。渲染器抛错
时 pi 自动回退默认渲染,无兜底负担。
/db related 在关联表名较长时崩溃:Rendered line 101 exceeds terminal
width (248 > 163)。根因是 tabs 行(6 个标签 join)与表格行未按 overlay
宽度截断,Text 组件不自动截断,触发 pi-tui 的宽度断言。

修复:
- related-browser 的 build() 对标题/表切换/路径/表格/底栏所有行应用
  truncateToWidth(ANSI 安全),截断到内容宽度。
- result-table 转置模式 cellWidth 下限从 4 降到 1、纵向模式 valueCap
  下限从 20 降到 1——原下限在窄宽度下会使行宽超出给定 width,
  /db query 与 related 的窄终端场景同样可能触发崩溃。

新增回归测试:窄宽度下转置/纵向模式所有行可见宽度 ≤ width;
长表名标签行截断到内容宽度并保留省略号(truncateToWidth 冒烟契约)。
/db query 渲染路径存在 4 个未截断的超宽来源(终端 163 列时触发
Rendered line N exceeds terminal width 崩溃):
- SQL 元数据行(长 SQL 直接展示)
- 折叠态表格中文单元格(pad 按 UTF-16 码元截断,显示宽度 2 倍)
- 展开态长值(formatVerticalFull 不截断)
- 关联表摘要(长表名 join)

修复:
- commands/renderers.ts:渲染边界对每行 truncateToWidth(兜底所有
  来源;样式化文本需要 ANSI 感知,这里用 pi-tui 的 truncateToWidth)。
- formatting/result-table.ts:理想列宽/截断/补齐全部改用 visibleWidth
  (与 TUI 宽度断言同一把尺子)。纯文本截断自实现 truncatePlain,
  不用 truncateToWidth——它会注入 \x1b[0m,破坏表格行纯文本契约。

新增测试:renderers.test.ts 7 个用例(长 SQL/展开态长值/中文表格/
关联表摘要全行宽 ≤ width);result-table 追加中文单元格、中文列名
行宽约束与无 ANSI 断言。
@zavier zavier changed the title fix(related): 关联表浏览器超宽行导致 TUI 崩溃 fix: TUI 超宽行崩溃(related 浏览器 + /db query 渲染路径) Aug 3, 2026
全局审计超宽行崩溃(Rendered line exceeds terminal width)后的收尾:

- 唯一裸 string[] 渲染路径是 renderers.ts 的 EntryRenderer(已修);
  其余自定义 UI 均返回组件树,Text 自带 word wrap + 长词断开,
  SelectList 内部 truncateToWidth——组件层安全。
- 新增 formatting/display-width.ts:truncateToDisplayWidth /
  padToDisplayWidth(纯文本按显示宽度截断/补齐,不注入 ANSI),
  result-table.ts 去重改用。
- mutate-confirm 的 SQL 框:按码元 slice/padEnd 改为按显示宽度
  (中文 SQL 行不再超出边框宽度)。
- tool-result-render 展开态:多行全文改为逐行按容器宽度截断的
  TruncatedMultiline 组件(最长渲染路径的额外防线)。

新增 display-width.test.ts 7 个用例。
@zavier
zavier merged commit 9c3e69f into main Aug 3, 2026
1 check passed
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.

1 participant