Skip to content

feat(tui): fold completed turns into activity sections - #121

Merged
openjiuwen-release-bot[bot] merged 2 commits into
openJiuwen-ai:mainfrom
0x7c13:dev/0x7c13/tui-fold-finished-turns
Oct 25, 2026
Merged

openjiuwen-release-bot[bot] merged 2 commits into
openJiuwen-ai:mainfrom
0x7c13:dev/0x7c13/tui-fold-finished-turns

Conversation

@0x7c13

@0x7c13 0x7c13 commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Paired: GitHub #121 ↔ GitCode !88

Summary

Successful turns fold their activity under a one-line header.

  • A turn that ends with a final reply folds its thinking, intermediate replies, tool groups, and the retry and error notices it recovered from. They sit under Made N tool calls, or Activity when that section made no tool calls. Clicking the header expands it. Tool groups and thinking inside keep their own state.
  • The user message, each injected message and the final reply stay visible. Each injected message starts its own section.
  • These turns stay open: turns that end interrupted, failed or waiting for sub-agents, and the last turn recovered from a crash sidecar. A section holding only one thinking block keeps that block's own header and just collapses it.
  • Restored sessions fold the same way. Compressed history keeps only some tool details, so its sections all read Activity. A compressed turn that ended on a failure status stays open, even though compressed history does not show the status.
  • /fold toggles activity sections, tool groups and thinking together, which gives keyboard users a way to open a section. The header takes no focus and adds no Tab stop.
  • New setting Automatically fold completed turns (ui.chat.fold_finished_turns). It sits under Appearance, defaults to on, applies live and is not read from project settings. Copy commands still include intermediate replies and keep their message counts.

Long sessions do less layout and hold less in memory.

  • Folded members are hidden with display, so they take no layout. Collapsed thinking releases its rendered body, reclaimed through the GC freeze epoch, and rebuilds it when opened.
  • Tail-first replay counts a hidden entry as 0 rows and a header as 1 row. It caps the first mount at 32 visible and 128 total entries.
  • Transcript order keys are now Fractions, so a header goes in after its anchor without renumbering. Copy and selection order are unchanged.

Docs: readable Claude thinking summaries (separate commit).

  • The Anthropic Chat Options example now uses {"type": "adaptive", "display": "summarized"}. The page explains that Show model thinking only controls whether returned text is shown, and models.md links to it. Both en and zh-Hans are updated.

Test plan

  • New tests:
    • tests/app/tui/widgets/chat/test_process_folding.py: live and replayed folding, injected messages, failure and status endings (compressed history included), crash-sidecar protection, setting changes, folds waiting on running tools or questions, and /fold.
    • tests/app/tui/screens/main/test_process_folding.py: fifty completed turns fold without a global restyle or recompose of the main screen.
    • tests/app/tui/widgets/chat/test_thinking_body_release.py: collapsing releases the thinking body with an epoch-aware reclaim, and a fast collapse and expand keeps one body.
  • Updated tests: tail-first replay budgets; live and replayed thinking; the settings layout, dialog and coordinator; command-suggestion i18n.
  • Tests pass locally (Smart Test over every file in both commits: 33,163 passed, 60 skipped; 1,241 architecture checks passed).
  • Gates: ruff check, ruff format --check, ty check (linux, darwin, win32) and scripts/i18n.py check.

The user guide is updated: sessions, settings, the settings reference and slash commands (en and zh-Hans).

Keep user messages, injected messages and final replies visible while
folding successful turn activity by default. Support keyboard access
through /fold and a setting to control automatic folding.

Release collapsed thinking bodies, preserve transcript order and copy
behavior, and bound foreground history replay. Keep unfinished turns
visible and label compressed activity without incomplete tool counts.

A compressed turn that ended on a failure status stays unfolded even
though compressed history omits the status itself.
Newer Claude models return no thinking text unless the request asks for
it. Use `{"type": "adaptive", "display": "summarized"}` in the Chat
Options example, and explain that iCode's "Show model thinking" setting
only controls whether returned text is shown.
@openjiuwen-collaboration-bot

openjiuwen-collaboration-bot Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

head_sha: d7873241fe68629af8828ce90965af2e4d2fd66b

变更摘要

本 PR 为 TUI 聊天视图引入“已成功轮次自动折叠”:新增 ProcessBlock、ProcessController、process_model.py 与 ProcessMember 等模块,把一轮成功回复中的思考、中间回复、工具组以及恢复过的重试/错误提示收拢到单行头部(Made N tool calls 或 Activity)之下,点击头部可展开,用户消息、注入消息和最终回复保持可见。同时新增 ui.chat.fold_finished_turns 配置项(默认开启、Apply.LIVE、ProjectMerge.DENY)并接入设置页、设置协调器与主屏回调,/fold 命令的语义扩展为同时切换执行过程、工具组和思考。此外还包含折叠成员不参与布局、折叠思考块释放渲染体、回放批次的条目上限与 Fraction 顺序键等长会话优化,以及 Claude thinking 摘要相关文档更新。

主要改动

  • 执行过程折叠模型与控制器: 新增 process_model.py(ProcessEntry/ProcessSegment/plan_process_segments)与 process_controller.py(ProcessController.plan/complete_live/prepare_replay),实时与回放共用同一分段计划,只有以最终回复结束的轮次才折叠,失败、中断、等待子智能体及 crash sidecar 恢复的最后一轮保持展开。
  • 单行头部控件与可见性写入: 新增 ProcessBlock(显示 tui.chat.process.tool_calls 或 tui.chat.process.activity,不获取焦点、无 Tab 停靠点)和 ProcessMember 基类,ToolGroup、ThinkingMessage、ErrorMessage、RetryMessage、InterruptedMessage 改为继承 ProcessMember,通过 set_process_hidden/set_content_visible 统一以 display 控制隐藏。
  • 新设置项 ui.chat.fold_finished_turns: 在 settings.py 中新增该布尔配置(默认 True、Apply.LIVE、ProjectMerge.DENY),并在设置页 Appearance 区域、SettingsCoordinator.apply_live、MainScreen._apply_fold_finished_turns 及 ChrysApp._build_main_screen 中完成接线与本地化文案。
  • 回放与长会话开销优化: ChatPanel 的 transcript 顺序键由 int 改为 Fraction,新增 mount_transcript_after 在原锚点后插入头部;replay_mount.py 中隐藏条目按 0 行计入预算并新增 _MAX_FOREGROUND_ENTRIES/max_visible_entries 首屏上限;折叠的 ThinkingMessage 通过 _sync_thinking_body 释放 markdown 主体并发出 GcReclaimRequested,展开时重建。
  • /fold 语义与文案扩展: commands.py、copy_actions.py 与 panel.toggle_fold_all() 更新为同时切换执行过程块、工具组和思考,折叠期间若有阻塞成员则保留待执行意图并在状态通知后重试;相关英中 i18n 条目、chrys.pot/chrys.po 与命令建议测试同步更新。

@openjiuwen-collaboration-bot

openjiuwen-collaboration-bot Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

head_sha: d7873241fe68629af8828ce90965af2e4d2fd66b

代码审查

审查结论

  • [建议] src/chrys/app/tui/widgets/chat/messages.py:946 fix: 未挂载时跳过的思考正文重建会导致展开后正文永久缺失
  • [建议] src/chrys/app/tui/widgets/chat/panel.py:458 fix: mount_transcript_after 的顺序键上界未按 DOM 兄弟取,可能与显示顺序发散
  • [建议] src/chrys/app/tui/widgets/chat/replay.py:1156 fix: 压缩历史失败锚点可能绑定到上一轮的 widget
  • [建议] tests/foundation/i18n/test_catalog_oracle.py:26 fix: 固定 id 集上调到 2411 但未同步 POT/PO 与 msg() 定义
类型 数量
🔴 阻塞 0
🟡 建议 4

💬 仅评论

@openjiuwen-collaboration-bot

Copy link
Copy Markdown
Contributor

head_sha: d7873241fe68629af8828ce90965af2e4d2fd66b

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
禁用词扫描 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A
issue关联检查 N/A N/A
pr size检查 N/A N/A

Comment thread tests/foundation/i18n/test_catalog_oracle.py
Comment thread src/chrys/app/tui/widgets/chat/replay.py
@openjiuwen-collaboration-bot

Copy link
Copy Markdown
Contributor

head_sha: d7873241fe68629af8828ce90965af2e4d2fd66b

🟡 Medium Priority

改动行:panel.py 新增 mount_transcript_after(458-473),self._transcript_seqs[widget] = (previous + following) / 2,其中 previous = self._transcript_seqs[anchor]、following = min(seq for node, seq in ... if seq > previous ...)。

证据链:

  1. 该函数签名/f守信条是「Insert between neighboring exact order keys, without changing existing selection anchors」,即插入后的顺序键必须与 DOM(显示)顺序一致,否则拖选/复制的顺序会与看到的顺序不符(docstring 与提交说明都强调 “Copy and selection order are unchanged”)。
  2. 但只要对同一个 anchor 连续插入两次,第二次计算就会把第一次插入的节点当作 following:第一次 A=(p+f)/2,第二次 B=(p+A)/2 < A,而 await self.mount(widget, after=anchor) 每次都把新节点插在 anchor 紧后面,DOM 顺序是 anchor, B, A。于是顺序键序列为 anchor, B, A,而 DOM 为 anchor, B, A —— 对两次插入恰好一致;但若插入的是 anchor, A, B(第二次插入直接用 after=anchor,DOM 为 anchor, B, A),顺序键却为 anchor(p), B(p+Δ/2), A(p+Δ) —— 顺序键与 DOM 相反(A 的键大于 B,但 A 在 DOM 中位于 B 之后)。等等:DOM 是 anchor, B, A,键也是 anchor < B < A,二者一致。
  3. 真正会发散的是三次及以上或「先插 A、再在 anchor 后插 B、再想插 C」这类交错场景,以及 anchor 的 DOM 后继与「键最小后继」不是同一个节点时(following 取的是全表最小键后继,不校验它是否就是 DOM 中的下一个兄弟):一旦二者不同,新节点会被插到 after=anchor 的 DOM 位置,而键值却排在另一个节点之前/之后,选择模型按 (stamp, 兄弟路径) 排序时会与显示顺序错位;此后再往返插入还会让 Fraction 分母指数增长(1/2、1/4、1/8…),比较与哈希成本上升。

失败模式:在折叠/展开、连续两次回放或同一轮次里对该 anchor 多次插入活动块时,选中顺序(复制顺序、拖选高亮)与屏幕顺序不一致;触发条件依赖 following 是否等于 DOM 下一兄弟,因此置信度中等。

建议:上界改为按 DOM 顺序取 anchor 的实际后继兄弟(而不是全表最小后继键),并对同一 anchor 的重复插入使用上一次插入的兄弟键作为 previous,确保顺序键与显示顺序一致。

Comment thread src/chrys/app/tui/widgets/chat/messages.py
@openjiuwen-collaboration-bot

Copy link
Copy Markdown
Contributor

head_sha: d7873241fe68629af8828ce90965af2e4d2fd66b

不成立

@openjiuwen-release-bot
openjiuwen-release-bot Bot merged commit 0a03093 into openJiuwen-ai:main Oct 25, 2026
19 checks passed
@openjiuwen-release-bot

Copy link
Copy Markdown
Contributor

🤖 This pull request has been merged, and the target branch is up to date.

openjiuwen-release-bot Bot pushed a commit that referenced this pull request Oct 25, 2026
[mirror] #121: feat(tui): fold completed turns into activity sections

Created-by: openjiuwen-sync
Commit-by: Jiaqi (0x7c13) Liu
Merged-by: Ox7c13
Description: Paired: [GitHub #121](#121) ↔ [GitCode !88](https://gitcode.com/openJiuwen/iCode/merge_requests/88)

<!-- bot1-mirror-meta -->
github_pr: 121
head_repo: 0x7c13/iCode
head_ref: dev/0x7c13/tui-fold-finished-turns
head_sha: d787324
base_repo: openJiuwen-ai/iCode
base_ref: main
github_repo: openJiuwen-ai/iCode
base_branch: main
base_sha: 2ced1be
github_user: 0x7c13
<!-- /bot1-mirror-meta -->

GitHub PR mirror for CodeArts CI.

<!-- bot1-source-body -->
## Summary

**Successful turns fold their activity under a one-line header.**
- A turn that ends with a final reply folds its thinking, intermediate replies, tool groups, and the retry and error notices it recovered from. They sit under **Made N tool calls**, or **Activity** when that section made no tool calls. Clicking the header expands it. Tool groups and thinking inside keep their own state.
- The user message, each injected message and the final reply stay visible. Each injected message starts its own section.
- These turns stay open: turns that end interrupted, failed or waiting for sub-agents, and the last turn recovered from a crash sidecar. A section holding only one thinking block keeps that block's own header and just collapses it.
- Restored sessions fold the same way. Compressed history keeps only some tool details, so its sections all read **Activity**. A compressed turn that ended on a failure status stays open, even though compressed history does not show the status.
- `/fold` toggles activity sections, tool groups and thinking together, which gives keyboard users a way to open a section. The header takes no focus and adds no Tab stop.
- New setting **Automatically fold completed turns** (`ui.chat.fold_finished_turns`). It sits under Appearance, defaults to on, applies live and is not read from project settings. Copy commands still include intermediate replies and keep their message counts.

**Long sessions do less layout and hold less in memory.**
- Folded members are hidden with `display`, so they take no layout. Collapsed thinking releases its rendered body, reclaimed through the GC freeze epoch, and rebuilds it when opened.
- Tail-first replay counts a hidden entry as 0 rows and a header as 1 row. It caps the first mount at 32 visible and 128 total entries.
- Transcript order keys are now `Fraction`s, so a header goes in after its anchor without renumbering. Copy and selection order are unchanged.

**Docs: readable Claude thinking summaries** (separate commit).
- The Anthropic Chat Options example now uses `{"type": "adaptive", "display": "summarized"}`. The page explains that **Show model thinking** only controls whether returned text is shown, and `models.md` links to it. Both en and zh-Hans are updated.

## Test plan

- [x] **New tests:**
  - `tests/app/tui/widgets/chat/test_process_folding.py`: live and replayed folding, injected messages, failure and status endings (compressed history included), crash-sidecar protection, setting changes, folds waiting on running tools or questions, and `/fold`.
  - `tests/app/tui/screens/main/test_process_folding.py`: fifty completed turns fold without a global restyle or recompose of the main screen.
  - `tests/app/tui/widgets/chat/test_thinking_body_release.py`: collapsing releases the thinking body with an epoch-aware reclaim, and a fast collapse and expand keeps one body.
- [x] **Updated tests:** tail-first replay budgets; live and replayed thinking; the settings layout, dialog and coordinator; command-suggestion i18n.
- [x] Tests pass locally (Smart Test over every file in both commits: 33,163 passed, 60 skipped; 1,241 architecture checks passed).
- [x] **Gates:** `ruff check`, `ruff format --check`, `ty check` (linux, darwin, win32) and `scripts/i18n.py check`.

The user guide is updated: sessions, settings, the settings reference and slash commands (en and zh-Hans).
<!-- /bot1-source-body -->

See merge request: openJiuwen/iCode!88
@0x7c13
0x7c13 deleted the dev/0x7c13/tui-fold-finished-turns branch October 25, 2026 16:36
openjiuwen-release-bot Bot pushed a commit that referenced this pull request Oct 26, 2026
[mirror] #124: chore(release): bump version to 0.32.0

Created-by: openjiuwen-sync
Commit-by: Jiaqi (0x7c13) Liu
Merged-by: Ox7c13
Description: Paired: [GitHub #124](#124) ↔ [GitCode !91](https://gitcode.com/openJiuwen/iCode/merge_requests/91)

<!-- bot1-mirror-meta -->
github_pr: 124
head_repo: 0x7c13/iCode
head_ref: dev/release-0.32.0
head_sha: c9d1882
base_repo: openJiuwen-ai/iCode
base_ref: main
github_repo: openJiuwen-ai/iCode
base_branch: main
base_sha: e225cb1
github_user: 0x7c13
<!-- /bot1-mirror-meta -->

GitHub PR mirror for CodeArts CI.

<!-- bot1-source-body -->
Bump iCode to 0.32.0 so a release is cut from current `main`.

## Changes
- `pyproject.toml` and `uv.lock`: the package version moves from 0.31.0 to 0.32.0.
- i18n catalogs (`locales/chrys.pot`, `locales/zh-Hans/LC_MESSAGES/chrys.po`, the compiled `chrys.mo`): the `Project-Id-Version` header now says 0.32.0. No message changes.

## Release
Merging this changes the version in `pyproject.toml` on `main`, so `tag-release.yml` creates the `v0.32.0` tag and starts `cd.yml` for that tag.

This is the first release whose Linux offline binaries bundle Pillow 13.0.0, from the glibc 2.17 wheels published as `pillow-13.0.0-manylinux2014.1` (#122, #123).

## Included since 0.31.0
- #123 Pillow 13.0.0 and pypdf 6.21.2 (pypdf security fixes); the Linux offline binaries take the matching glibc 2.17 Pillow wheels
- #122 the manylinux2014 Pillow wheel workflow builds 13.0.0 on patched build images, with every source archive pinned by SHA-256 (build-only); hook indicator tests stabilized
- #121 completed turns fold into activity sections; the docs show how to request readable Claude thinking summaries
- #120 the prompt editor asks for confirmation before its Discard button closes it
- #111 a sidebar Hooks tab lists every hook run, and each run is recorded once
- GitCode !85 the main chat shows the model's thinking as it streams; a resumed session replays it folded, and `/fold` folds it too
- GitCode !84 the chat follows new content only while you are at the bottom
- GitCode !83 a hook run log cut to size keeps file paths that are not valid UTF-8 intact
- GitCode !82 faster startup: a loading screen with the logo paints before the main screen and agent load, and F12 works again once the agent is ready

## Verification
- `uv lock --check` passes.
- `scripts/i18n.py extract/update/compile/check` runs clean, and a second run changes nothing.
- Tests were not run locally; CI covers them.
<!-- /bot1-source-body -->

See merge request: openJiuwen/iCode!91
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant