# Agent Note: TUI QuestionDialog 以多行方式渲染选项

Status: implemented
Archived: 2026-08-04

[English](2026-07-24-tui-question-dialog-multiline.md) | 中文

## 问题

`ctx.userInteraction.ask()` 必须确保问题正文、`detail` 补充内容、选项标签、描述、校验信息和控件在已配置的宽度与高度边界内均可读。问题面板也直接位于编辑器上方：若将其置于终端边缘，待处理决策就会同时脱离触发该决策的 transcript（文本记录）和后续输入。

## 决策

TUI 将待处理问题渲染为位于 transcript／状态区域与编辑器之间的内联模态框，同时仍与模型浮层和插件浮层共享 FIFO：

- `InlineModalComponent` 在正常组件流内应用 `questionDialogWidth` 和 `questionDialogMaxHeight`。系统在为编辑器预留空间后，还会根据当前视口限制问题的实际高度，因此调整窗口大小时，编辑器仍位于问题下方。
- `renderOptionBlock` 将每个标签换行到光标／编号前缀下方，并在另行换行且缩进相同的行上渲染弱化的描述。进度标题、问题、自定义答案提示、校验文本和末尾行也受宽度边界约束；最终的省略号截断仅作为前缀或其他不可拆分内容的安全边界。明确的 `↑ N lines hidden` 回退仅用于低于已配置最小值、无法容纳完整语义布局的视口。
- 当问题正文或 `detail` 超出头部分配的空间时，头部会成为带有独立 `… lines A-B/N • PgUp/PgDn` 状态行的分页行视口。Page Up 和 Page Down 会遍历这两个行视口：向前导航先翻完问题正文／`detail` 页面，再进入超大选中选项页面；向后导航则采用相反顺序。这样可确保计划评审的 `detail` 内容始终可达，而不会被高度边界挡住。
- 在 `windowBlocks` 运行前，选项行预算会扣除内边距、标题行、位置行和页脚行。窗口同时遵守 `maxQuestionOptions` 和剩余行预算，保持选中项可见，并将省略的选项渲染为 `↑ N more`／`↓ N more` 标记。若固定界面元素会使选项行少于四行，紧凑头部会转为行分页器，从而容纳选中内容、分页状态和上下两个选项标记。
- 当一个选中块超出分配空间时，它会成为带有 `lines A-B/N • PgUp/PgDn` 状态行的行视口。Page Up 和 Page Down 可展示每一行已换行内容，同时防止该块遮住选项标记、校验信息或控件。

包（package）测试固定数量和高度边界、头部与选中块的分页顺序、窄宽度换行、选择行为，以及问题相对于保留的编辑器输入的位置。语义 TUI 快照固定组装后的终端布局、头部／详情与选中选项的分页转换，以及校验状态。

## 备选方案

**仅用省略号进行横向截断。** 保持每个选项占一行，只能提示文本有所丢失，无法使描述变得可读，也无法处理纵向边界。该实现会对可读内容换行，仅将省略号保留为最终安全边界。

**将标签与描述合并后换行。** 组合行会将两者的宽度耦合在一起，任一方都可能挤占另一方的空间。分行渲染可使二者的宽度保持可预测。

**将问题保留为终端底边浮层。** 根据 transcript 和视口高度，锚定在终端边缘的面板可能出现在编辑器之后，也可能遮盖下方界面元素。内联模态框可保留顺序，同时由模态管理器继续负责焦点和 FIFO 所有权。

**将边界处理下推至 pi-tui。** 通用浮层切片无法识别选项边界、选中内容、控件或内联编辑器关系。因此，负责该语义的对话框会应用数量、行数和分页规则。

**仅使用选项数量上限。** `maxQuestionOptions` 仍是公开的数量边界，但仅靠它无法容纳已换行的块。对话框会同时执行数量边界和行数边界。

## 后果

- 描述会占用额外行，因此可见选项数可能少于 `maxQuestionOptions`；标记会说明省略的选项数量。
- 较长的问题正文和计划评审 `detail` 在受高度约束的面板内仍然可达，代价是 Page Up 和 Page Down 需要与选中选项分页共用。
- 超出空间的选中块会预留一行状态信息；若要阅读当前页面之外的行，必须使用 Page Up 或 Page Down。
- 在较矮的视口内，内联问题可能将较早的 transcript 行挤出可见区域。低于已配置最小高度时，最终回退可能将上部行折叠到明确的隐藏行标记之后，从而让输入控件和编辑器仍然可用。
- 面向模型的 schema、选中的标签、中止／取消行为，以及 ACP（Agent Client Protocol）的 elicitation 路径均保持不变。
