nianyucatfish
9badef879d
feat(tui): 工具显示卡片 + /model 与 /effort 运行时切换 ( #593 )
...
tuiapp_v2 的两项增强,拆成两个 commit。
## 1. 工具显示卡片(file_write / file_patch / file_read / code_run)
把 agent_loop verbose 的 `🛠️ Tool` 块替换为紧凑卡片:
- **file_write / file_patch**:行号 + 上下文的主题化 diff;append/prepend 走整文件 diff 拿真实上下文。
- **file_read**:读到的内容带行号 gutter,剥离 LLM-facing 噪音(`[FILE]`/show_linenos 前言/截断提示),超长折叠;行号在不可知处(keyword 窗口 / 挖洞后)留空。
- **code_run**:参考 Claude Code / Codex 的 exec 渲染,无边框、`│` 命令 gutter + `└` 输出 gutter,输出 dim、**保尾截断**(traceback 关键在末尾);代码来自正文 ```块``` 时不重复展示。
- 三卡共用 `_CardWriter` / `_card_status_row` / `_emit_gutter`;2 格左 margin 只进显示流、不进复制源。
- capture 机制:live 走 `tool_before/after` 钩子,`/continue` 走 `iter_write_captures` 从历史 tool_result 重建,按 `hash(get_pretty_json(args))` 内容寻址。
- 双流渲染对齐(`_align_md_renders`)支持 margin 映射,鼠标复制不含视觉缩进。
## 2. /model 与 /effort 渠道内运行时切换
- **/model**:在线拉模型列表的 searchable picker;搜索框兼作自定义模型名输入(无匹配时 Enter 直设)。
- **/effort**:reasoning effort 档位切换,协议差异在 `effort_note` 单点编码——Claude(`output_config.effort`) low/med/high 原样、xhigh→max、none/minimal 忽略;OpenAI(`reasoning_effort` / `reasoning.effort`) 透传;mixin 经 `_BROADCAST_ATTRS` 广播到全部子渠道。
- 逻辑收在 `frontends/model_cmd.py`(agent 无关、可单测)。
## 测试
- 卡片:两份真实会话日志全链路重放,51 个 code_run + 23 read + 20 write 全部渲染、双流 parity、复制不含 margin。
- /model /effort:拦截真实 llmcore 请求构造验证 effort 进 payload(含 mixin 广播、各协议字段);picker 自定义输入走 Textual pilot 端到端。
2026-06-11 09:19:09 +08:00