Skip to content

feat(tui): 工具显示卡片 + /model 与 /effort 运行时切换#593

Merged
lsdefine merged 2 commits into
lsdefine:mainfrom
nianyucatfish:feat/tui-tool-cards
Jun 11, 2026
Merged

feat(tui): 工具显示卡片 + /model 与 /effort 运行时切换#593
lsdefine merged 2 commits into
lsdefine:mainfrom
nianyucatfish:feat/tui-tool-cards

Conversation

@nianyucatfish

Copy link
Copy Markdown
Collaborator

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 钩子,/continueiter_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 端到端。

把 agent_loop verbose 的 `🛠️ Tool` 块替换为紧凑卡片:
- file_write/file_patch:带行号+上下文的主题化 diff(append/prepend 走整文件 diff)
- file_read:读到的内容带行号 gutter,噪音剥离,超长折叠
- code_run:CC/Codex 式 gutter 卡(命令 │ / 输出 └),保尾截断
- 三卡共用 _CardWriter/_card_status_row/_emit_gutter;2 格 margin 不进复制
- capture:tool_before/after 钩子(live) + iter_write_captures(continue) 内容寻址
- 双流渲染对齐(_align_md_renders)支持 margin 映射,复制不含视觉缩进
- /model:在线拉模型列表的 searchable picker;搜索框兼作自定义模型名输入
  (无匹配时 Enter 直设)。逻辑在 model_cmd.py(agent 无关、可单测)。
- /effort:reasoning effort 档位切换。各协议差异在 effort_note 单点编码:
  Claude(output_config.effort) low/med/high 原样、xhigh→max、none/minimal 忽略;
  OpenAI(reasoning_effort / reasoning.effort) 透传。mixin 经 _BROADCAST_ATTRS
  广播到全部子渠道。
- model_cmd:_resolve/fetch_models/set_model/set_effort,mixin 落子 session。

@lsdefine lsdefine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

@lsdefine
lsdefine merged commit a6c712b into lsdefine:main Jun 11, 2026
lsdefine pushed a commit that referenced this pull request Jun 12, 2026
The tool-cards change (#593) tightened _md_line_has_box_drawing to exempt
pure-horizontal '─' runs as markdown hr. But a SIMPLE-box Markdown table's
only box glyph is its header rule, so that exemption dropped whole tables
out of the passthrough copy path and into the wide-render aligner, which
maps selection cell-columns to character indices — misaligning copy of any
table with CJK (wide) cells.

Remove the pure-horizontal exemption so a table's header rule is detected
again and the table run stays passthrough. Card gutters (└─ / │ / └) keep
their own prefix-based exemptions, so tool cards are unaffected. The only
cost is a real markdown hr copying as a dash run — the pre-#593 behavior.
lsdefine pushed a commit that referenced this pull request Jul 23, 2026
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 端到端。
lsdefine pushed a commit that referenced this pull request Jul 23, 2026
The tool-cards change (#593) tightened _md_line_has_box_drawing to exempt
pure-horizontal '─' runs as markdown hr. But a SIMPLE-box Markdown table's
only box glyph is its header rule, so that exemption dropped whole tables
out of the passthrough copy path and into the wide-render aligner, which
maps selection cell-columns to character indices — misaligning copy of any
table with CJK (wide) cells.

Remove the pure-horizontal exemption so a table's header rule is detected
again and the table run stays passthrough. Card gutters (└─ / │ / └) keep
their own prefix-based exemptions, so tool cards are unaffected. The only
cost is a real markdown hr copying as a dash run — the pre-#593 behavior.
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.

2 participants