diff --git a/AGENTS.md b/AGENTS.md index d007ca31..d6e04a17 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,6 +51,18 @@ Use `testing::TempDir()` or `std::filesystem::temp_directory_path()` for file I/ If CMake test discovery/build integration is unavailable in the editor, still keep changes compatible with the documented `cmake --build` and `ctest` commands. For web-only changes, at minimum run `pnpm test` and `pnpm build` from [web/](web). +## 研发实施中的通用注意事项 + +- 重构或迁移功能时,先明确新旧路径的责任边界,再逐步切换调用入口;如果新旧状态、事件处理或兼容分支同时生效,同一个输入可能被重复处理,问题通常只在特定交互顺序下暴露。 +- 事件驱动程序需要明确每类事件的唯一所有者。键盘、鼠标、定时器、重绘和后台回调应经过统一适配层进入业务状态机,不能只迁移最常见的事件而遗漏边缘输入路径。 +- 业务状态、传输格式和展示文本应分层维护。不要用格式化后的字符串推断状态;空字符串、缺失字段和显式的空值可能代表不同语义,跨线程或跨进程传输时应保留必要的结构化信息。 +- 不要把布局、分页或超时等动态行为写成固定常量。可视区域、终端尺寸、配置值和运行时状态变化后,固定步长或固定边界容易产生越界、跳过内容或无法操作的问题。 +- 将时间、外部 IO、线程调度和平台资源封装在边界上,核心逻辑尽量使用可注入的时钟、输入和依赖。这样既能避免测试永久等待,也能稳定覆盖超时、取消和竞态场景。 +- Windows 增量构建前确认没有残留进程占用输出文件,并加载正确的编译器开发环境;链接错误有时来自文件锁或环境变量缺失,而不是源代码错误。 +- 多步骤任务应采用“小范围修改 → 定向编译/测试 → 再扩大范围”的节奏。遇到失败先判断是代码错误、环境问题、并发进程、缓存还是测试基线问题,不要在未定位原因前反复重试。 +- 修改前后都要检查工作区范围。不要使用会清理或覆盖无关用户文件的命令;提交时精确选择相关文件,并通过 `git diff --check`、差异审查和测试结果确认改动没有夹带无关内容。 +- 非平凡行为变更应同步更新设计文档、任务清单和测试;不要等全部代码完成后才补记录,否则容易遗漏已验证的约束和未完成事项。 + ## Commit & Pull Request Guidelines Recent history uses short imperative commits, sometimes with `feat:` prefixes, for example `feat: Implement AskUserQuestion tool` or `Add unit tests for session serialization`. Keep commits focused and mention tests when relevant. diff --git a/CMakeLists.txt b/CMakeLists.txt index e2077f77..04179661 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,7 +259,14 @@ set(ACECODE_TESTABLE_TUI_SOURCES ${CMAKE_SOURCE_DIR}/src/markdown/mermaid_renderer.cpp ${CMAKE_SOURCE_DIR}/src/markdown/link_safety.cpp ${CMAKE_SOURCE_DIR}/src/markdown/syntax_highlight.cpp - ${CMAKE_SOURCE_DIR}/src/tui/ask_question_overlay.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_controller.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_editor.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_layout.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_adapter.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_panel.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_view.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_session.cpp + ${CMAKE_SOURCE_DIR}/src/tui/ask_question_text.cpp ${CMAKE_SOURCE_DIR}/src/tui/chat_file_link.cpp ${CMAKE_SOURCE_DIR}/src/tui/text_truncation.cpp ${CMAKE_SOURCE_DIR}/src/tui/paste_handler.cpp diff --git a/docs/help/configuration.html b/docs/help/configuration.html index 4b0f49a0..9434d5ea 100644 --- a/docs/help/configuration.html +++ b/docs/help/configuration.html @@ -35,18 +35,24 @@

配置文件与生效范围

优先通过界面修改对应设置;需要手动编辑时,先确认数据目录、字段范围和保存方式。

-
本页内容
+
本页内容

配置保存在哪里

个人安装的主配置是 ~/.acecode/config.json,Windows 对应 %USERPROFILE%\.acecode\config.json。模型预设、默认模型以及网络、技能、MCP 等全局选项保存在这套用户配置中。

Windows 服务模式使用 %PROGRAMDATA%\acecode,与个人安装的数据目录分开。连接远端后台时,配置属于远端用户或服务身份;编辑本机文件不会自动修改远端配置。

配置层适合保存的内容
全局配置服务商连接、默认值、扩展连接与运行选项。
工作目录覆盖例如 TUI 用 /model --cwd 保存的项目模型选择。
项目文件项目规则、项目技能和项目 Hooks。
当前任务任务选择的模型、权限与对话上下文。

具体位置见本地配置和数据。复制配置到其他计算机前,检查其中的绝对路径、可执行文件位置和认证信息。

修改与生效

模型页通过保存模型或保存修改提交;个性化文本和 MCP JSON 等控件会在离开编辑区时保存,并显示保存状态。TUI 设置中心的 General、Appearance 开关通常即时保存,配置与模型表单按底部提示使用 Ctrl+S

不同配置有不同生效边界。任务模型和权限使用专门的切换入口;后台连接与运行服务以界面的应用结果为准。出现“重启 daemon 后生效”时,保存正在进行的工作后重启。手动改动任意 JSON 文件,并不等于所有运行中的模块都已经重新加载。

+

TUI 问答配置

TUI 中的 AskUserQuestion 会在选项较多或说明较长时使用可滚动内容区。以下字段位于配置文件的 tui 对象中:

字段默认值有效范围说明
question_min_visible_rows42–12AskUserQuestion 内容区的最小可见行数。内容超出视口后,可使用鼠标滚轮或滚动条查看。
question_selection_feedback_ms2000–1000预设选项提交后保留选中视觉反馈的时长,单位为毫秒。设置为 0 可关闭反馈延迟。

例如:

{
+  "tui": {
+    "question_min_visible_rows": 4,
+    "question_selection_feedback_ms": 200
+  }
+}

这两个字段会在读取配置时限制在有效范围内。超出范围的整数会自动限制到边界,并记录警告;非整数值会被忽略并继续使用默认值。省略字段时使用默认值,配置保存采用稀疏写入,不会强制写出默认值。

手动编辑与错误恢复

  1. 先备份当前有效配置,使用支持 UTF-8 的编辑器打开。
  2. 只修改目标字段,保持正确的 JSON 类型,不加入注释或尾随逗号。
  3. 重新加载相关功能,或按该功能要求重启。
  4. 检查界面实际值和一次小操作,确认修改已生效。

当前版本会保存有效配置快照。配置损坏且存在有效快照时,会备份错误文件并尝试自动恢复;Web/Desktop 会显示一次配置已自动回滚提示。没有可用快照时仍会报告配置错误。按提示查看备份位置并修复目标字段,备份可能含密钥,不要直接公开。

- +
diff --git a/docs/specs/2026-09-07-tui-ask-user-question-requirements.md b/docs/specs/2026-09-07-tui-ask-user-question-requirements.md new file mode 100644 index 00000000..10fb786c --- /dev/null +++ b/docs/specs/2026-09-07-tui-ask-user-question-requirements.md @@ -0,0 +1,420 @@ +# TUI AskUserQuestion 重设计需求 + +**日期:** 2026-09-07 +**状态:** 需求已确认,功能已实现,待真实交互式 TUI 手动验收 + +## 1. 目标 + +将 ACECode 的 TUI `AskUserQuestion` 重新设计为自适应决策界面:单个简单问题应能快速完成;多个问题则提供可回看、可修改、可汇总确认的完整问卷流程。 + +本次要解决当前简单单选题也暴露较重问卷流程、`Other...` 编辑模式割裂、键盘与鼠标操作不一致等问题。新的体验保留现有提问能力,但统一选择、自定义回答、导航、编辑、取消、滚动与提交反馈。 + +## 2. 范围 + +### 本轮范围 + +- ACECode 交互式 TUI 的 `AskUserQuestion`。 +- TUI 布局、键盘、鼠标、行内自定义编辑、滚动、视觉状态、TUI 本地配置、请求队列展示与 TUI 转录展示。 +- 为本地转录区分用户作答、未作答、超时自动选择所需的 TUI 行为。 + +### 不在本轮范围 + +- Desktop 或 Web 端问答界面重设计。 +- 多端交互一致性改造。 +- 公开工具参数 schema 约束: + - 每次调用默认支持 1-10 题,实际上限由跨端配置 `ask.max_questions` 控制,合法范围为 1-50; + - 每题仍为 2-4 个预设选项; + - `multiSelect` 仍是唯一题型标识; + - 单次超过上限时工具返回错误,由模型自行分多次调用,系统不自动拆分或合并。 +- 新增纯文本题。 +- 新增独立确认题类型;确认类问题属于普通单选题。 + +后续可单独讨论跨端结果语义和非 TUI 界面统一。 + +## 3. 产品模型 + +### 3.1 自适应模式 + +界面仅根据一次调用中的题目数量切换模式。 + +| 调用题数 | 用户流程 | +|---|---| +| 1 题 | 快问模式。没有汇总页、没有题间导航;完成答案后直接提交。 | +| 2–`ask.max_questions` 题 | 问卷模式。完成当前题后自动进入下一题;完成最后一题后进入只读汇总页,再最终提交。 | + +两种模式共用视觉语言、选项布局、选择行为、自定义回答、键盘、鼠标和滚动规则。 + +### 3.2 支持的题型 + +- **单选题:** 任意时刻只能有一个有效预设选项或一个有效自定义答案。 +- **多选题:** 可同时选择多个预设项;自定义答案可作为补充说明同时存在。 + +## 4. 题目展示 + +### 4.1 头部 + +题目页显示题号和 header 标签,例如 `Question 2/4 [Decision]`。 + +- 单题不额外显示多题进度图。 +- 子任务发起的问题,在底部状态/帮助区域显示来源;主会话不显示来源。 + +### 4.2 选项行 + +每个选项行由四个固定槽位组成:编号列、选择标记列、标题列、说明列。 + +- 四个槽位在整题内列宽固定,所有选项共用同一组边界,逐列左对齐。 +- 编号列与选择标记列各自独立成列;标记不使用固定字母,也不与编号拼成同一个字符串。 +- 标题列为白色不加粗;说明列为灰色不加粗。说明列只使用弱化前景色,不改变字重。 +- 标题列与说明列之间保留 2 个 ASCII 空格作为列间距;短标题在列内补齐,以保持说明列左对齐。 +- 标题列按本题最长标题收紧,不固定占用屏幕比例。 +- 长标题或长说明只在各自列内换行,续行与所在列左边界对齐;任何内容都不能越出面板。 +- 只有焦点行使用选中底色,且焦点底色不改变文字颜色与字重。 +- 已选中行不使用任何底色,选中状态只通过选择标记表达。 +- 单选标记:已选 `(*)`,未选 `( )`。 +- 多选标记:已选 `[x]`,未选 `[ ]`。 +- 推荐项在标题后显示 `[Recommended]`,但不自动选中。 + +首次进入题目、或自动进入一题未访问的新题时,焦点落在第一个选项。手动回到已访问题目时,恢复离开时的焦点行,但不自动重新进入自定义编辑。 + +### 4.3 自定义回答行 + +自定义回答行位于预设选项之后,与其他选项共用同一组列边界,使用“预设选项数 + 1”作为编号,而非固定字母。 + +- 两个预设项时,自定义行为 `3`。 +- 四个预设项时,自定义行为 `5`。 +- 自定义行同样显示选择标记:单选 `( )` / `(*)`,多选 `[ ]` / `[x]`,标记列与预设项对齐。 +- 自定义行的文本列与预设项标题列左边界完全一致,占位文字不得比其他选项更靠左或更靠右。 +- 文本为空且未选中时显示 `Type your own answer here`。 +- 有草稿但未选中时,显示草稿第一行,替代占位文字;多行草稿折叠为第一行并带省略提示。 +- 单选题从自定义答案改选预设项后,草稿保留为灰色非激活状态;只有重新选中自定义项才会提交该草稿。 + +## 5. 选择与答案语义 + +### 5.1 单选题 + +- 选择新的预设项会立即替换此前的预设选择。 +- 选择自定义项会清除所有预设选择,使自定义答案成为唯一有效答案。 +- 从已选自定义项改选预设项时,自定义项取消选中,但文本保留为灰色草稿。 +- 仅当自定义项处于选中状态时,自定义文本才是有效答案。 + +### 5.2 多选题 + +- 可同时选择多个预设项。 +- 自定义项可与预设项共同选中,作为补充说明。 +- 已选中但为空的自定义项,在正常提交时不贡献文本;若存在预设项,只提交预设项。 +- 已选预设项按题目中显示顺序提交;有效的非空自定义说明追加在最后。 + +### 5.3 交给模型的答案 + +- 预设项仅提交 `label`,`description` 只用于界面理解与复制。 +- 多选结果按显示顺序拼接预设项 label,再追加有效的非空自定义文本。 +- 没有已选预设项且没有有效非空自定义文本时,明确返回 `Not answered`。 +- 全局取消不是成功的未作答结果,仍应返回失败结果,并明确告诉模型用户取消了问答。 + +## 6. 行内自定义编辑 + +问答面板打开时替代正常提示词输入框。自定义文本直接在自定义选项行内编辑,不使用底部输入框。 + +编辑态示例: + +```text +5 (*) > My answer| +``` + +### 6.1 进入编辑 + +- 按自定义项对应数字:选中自定义项并进入编辑,但该数字不写入文本。 +- 在预设项焦点输入普通字符:进入自定义编辑并保留首字符: + - 单选题清除预设选择并选中自定义项; + - 多选题保留预设选择并选中自定义项。 +- 不匹配预设项或自定义项的数字:进入自定义编辑,并将该数字作为首字符。 +- 自定义项获得焦点时,`j`、`k`、`y` 都是普通文本;必要时进入编辑。 + +### 6.2 编辑能力 + +行内编辑支持: + +- 普通文本输入; +- `Left` / `Right` 移动光标; +- `Up` / `Down` 在多行文本间移动光标; +- `Home`、`End`、`Backspace`、`Delete`; +- `Shift + 方向键` 选择文本; +- `Ctrl+Enter` 插入换行; +- `Ctrl+X` 剪切、`Ctrl+V` 粘贴; +- 单击进入编辑并定位光标; +- 鼠标拖动选择文字; +- 仅在存在选区时右键复制;无选区右键不处理。 + +问答打开期间 `Ctrl+C` 不复制文本,而是保留给全局取消问答。 + +重新编辑已有的多行自定义文本时,完整展开全部行、恢复此前光标位置,并滚动到使光标可见的位置。 + +### 6.3 离开编辑 + +- 非空自定义文本按 `Enter`:立即提交当前题;不等待预设项选择反馈。 +- 空自定义文本按 `Enter`:当没有其他有效答案时,将本题作为 `Not answered` 前进。 +- 非空文本按 `Esc`:保留文本和自定义项选中状态,仅退出编辑。 +- 空文本按 `Esc`:取消自定义项选中并退出编辑。 + +## 7. 键盘行为 + +### 7.1 预设选项 + +| 上下文 | `Space` | `Enter` | 对应预设项数字 | +|---|---|---|---| +| 单选预设项 | 选中/取消选中,停留当前题 | 选中焦点项后提交 | 选中对应项后提交 | +| 多选预设项 | 选中/取消选中,停留当前题 | 确保焦点项被选中后提交当前组合 | 确保对应项被选中后提交当前组合 | + +多选题中,对已选项重复按数字键只保持选中,绝不取消选中。 + +预设项提交后使用可配置的视觉反馈再前进;自定义文本提交后立即前进。 + +### 7.2 题目导航 + +非编辑态题目页: + +- `Up` / `Down` 移动选项焦点;到首尾后停留,不循环、不跨题。 +- 预设项焦点时,`k` 上移、`j` 下移。 +- 多题模式: + - `Left` 和 `Shift+Tab` 到上一题; + - `Right` 和 `Tab` 到下一题; + - 最后一题按 `Right` 或 `Tab` 进入汇总页。 +- 单题模式没有题间导航。 + +行内编辑态: + +- `Left` / `Right` 仅移动光标,不切题; +- `Up` / `Down` 仅移动光标,不移动选项; +- 退出编辑后恢复题间导航。 + +### 7.3 汇总页内容与导航 + +汇总页仅用于多题请求,逐题只读展示“问题+答案”,未答显示 `Not answered`。 + +内容排版按独立的 Q/A 两列块: + +- 每道题是一个两列块,问题列与答案列顶部对齐,都从该题第 1 行开始。 +- 单题占用行数取“问题换行行数”与“答案换行行数”的较大值;较短一侧的剩余行留空,下一题不得提前顶上。 +- 每两道题之间空一行。 +- `:` 并入问题文本,紧跟问题最后一个字符;它不单独成行,也不单独成列。 +- 所有答案共用同一个左边界;该边界由本页最宽的“问题+:”决定,再加 2 个 ASCII 空格作为列间距。 +- 问题与答案各自在自己的列内换行;换行不拆分连续 ASCII 单词,行首不得出现 `,。?!:、;` 这类收尾标点。 +- 序号列左对齐;问题续行与问题首行左对齐;答案续行与答案首行左对齐。 +- 面板宽度不足以维持两列时,降级为上下堆叠:问题在上,答案统一缩进到固定列,仍保持同类内容左对齐。 +- 内容超过视口时按动态视口规则滚动,滚动不改变题目索引。 + +导航: + +- `Enter` 提交完整问卷。 +- `Esc` 取消整个问答。 +- `Left` 和 `Shift+Tab` 回到最后一题。 +- `Right` 和 `Tab` 回到第一题。 +- `Up` 和 `Down` 不响应。 + +## 8. 取消 + +取消行为分层: + +1. **行内编辑态 `Esc`:** 按第 6.3 节规则退出编辑或取消空自定义选择。 +2. **题目页非编辑态 `Esc`:** + - 单选:清除当前题全部选择; + - 多选:清除当前题所有选中状态,但保留非激活自定义草稿; + - 焦点保持在当前行。 +3. **全局取消:** + - `Shift+X` 立即取消; + - 问答面板打开时 `Ctrl+C` 取消问答,而不是停止 Agent 或退出程序; + - 一秒内连续两次 `Esc` 取消问答; + - 汇总页 `Esc` 取消问答。 + +## 9. 鼠标行为 + +### 9.1 预设项 + +- 单击切换选中状态。 +- 双击确保该项选中并提交当前题。 + +### 9.2 自定义项 + +自定义项单击为切换行为: + +- 未选中时:选中并进入行内编辑; +- 已选中时:取消选中并退出行内编辑。 + +双击等价于连续两次单击,不提交当前题。 + +## 10. 复制预设选项文本 + +焦点位于预设项时,按 `y` 将以下文本复制到系统剪贴板: + +```text +