Skip to content

fix: streaming tool call rendering truncated during execution - #834

Merged
AAswordman merged 1 commit into
AAswordman:mainfrom
CATMIAOZHI:fix/streaming-tool-call-rendering
Jul 29, 2026
Merged

fix: streaming tool call rendering truncated during execution#834
AAswordman merged 1 commit into
AAswordman:mainfrom
CATMIAOZHI:fix/streaming-tool-call-rendering

Conversation

@CATMIAOZHI

Copy link
Copy Markdown
Collaborator

变更说明 / Description

流式输出期间,工具调用卡片的参数渲染会被截断,直到工具执行结束后才补全。此 PR 用基于 revision 的 RenderBatchCoordinator 替换原有的字符到达触发批量更新逻辑,确保渲染节点变更不会丢失。

背景与动机 / Context and motivation

详见 #833。开启流式输出时,BatchNodeUpdater.startBatchUpdates() 在已有刷新任务运行时直接 return,导致后续的节点变更(如工具 XML block 的 command 参数后半部分)不会被同步到 renderNodes。工具实际收到的参数是完整的,但 UI 卡片在执行期间显示不完整。

改动范围 / Changes

  • 新增 RenderBatchCoordinator:revision-based 批量渲染协调器,循环 drain 所有 pending revision 后才退出
  • 修改 StreamMarkdownRenderer:在每次可渲染状态变更后调用 requestUpdate(),替换原来的 startBatchUpdates();新增 appendBlockChunk() 原子化追加 block 内容并请求渲染
  • 新增 RenderBatchCoordinatorTest:3 个单元测试覆盖 coalescing、drain-on-exit 和 tool XML tail mutation 场景

不包含:打字机动画、主题偏好、Canvas 渲染器等其他改动。

兼容性与风险 / Compatibility and risks

  • 不影响工具调用的实际参数解析与执行,仅影响流式 UI 渲染时序
  • 保留了原有的批量刷新间隔和节流机制,未改为逐字符重组
  • RenderBatchCoordinatorinternal 类,不影响公开 API

关联 Issue / Related issue

Fixes #833

验证方式 / Verification

检查或命令:RenderBatchCoordinatorTest(3 个测试用例)
环境与变体:Redmi K80 Pro / HyperOS 3 / Android 15 / v1.12.0+4 / DeepSeek V4 Flash / 流式输出 + 全部工具调用
结果:
- 测试 1:requestWhileBatchIsPending_isIncludedWithoutAnotherInput — 通过,同一批次内的多次 request 只触发一次 flush
- 测试 2:requestDuringFlush_isDrainedBeforeCoordinatorBecomesIdle — 通过,flush 期间的新 request 会被 drain
- 测试 3:toolXmlTailMutation_isRenderedWithoutAnotherInput — 通过,XML block 尾部追加内容后渲染节点同步更新
- 设备实测:修复前工具执行期间 command 参数未渲染,修复后执行期间已显示完整参数

证据 / Evidence

修复前截图见 #833

检查清单 / Checklist

  • 我已记录可复现验证和未运行项原因 / Reproducible verification and reasons for unrun checks are recorded
  • 我已确认 Candidate checks 覆盖改动范围,并会处理技术失败项 / Candidate checks covers the change scope and technical failures will be addressed
  • 最终 diff 无无关、临时、生成、二进制或敏感内容 / Final diff has no unrelated, temporary, generated, binary, or secret content
  • 已提供对应的回归、UI、文档/字符串或兼容性证据 / Relevant regression, UI, docs/strings, or compatibility evidence is provided

Replace the char-arrival-triggered BatchNodeUpdater with a
RenderBatchCoordinator that tracks revision numbers, ensuring
mutations occurring during an active flush are not lost.

Key changes:
- Add RenderBatchCoordinator with revision-based coalescing loop
- Call requestUpdate() after every renderable state mutation
  (node creation, content append, child node changes, XML stream
  registration, HTML break nodes, latex node replacement)
- Replace BatchNodeUpdater.startBatchUpdates() with
  RenderBatchCoordinator.requestUpdate(); the loop drains all
  pending revisions before going idle
- Introduce BatchNodeUpdater.appendBlockChunk() to atomically
  append content and request a render update for XML/text blocks

Resolves: streaming tool call cards display truncated parameters
during execution; full parameters only appear after tool completion.
@CATMIAOZHI

Copy link
Copy Markdown
Collaborator Author

The lint-baseline check failure is not introduced by this PR. It is a pre-existing issue on main.

The script ci/script/normalize_lint_baseline.py hardcodes EXPECTED_SHA256 = "396e0383...", but the current app/lint-baseline.xml on main has SHA-256 485d7680....

The mismatch comes from an extra UnusedResources entry for R.string.theme_default_character_card that exists on main but is not reflected in the hardcoded checksum.

This PR does not modify app/lint-baseline.xml. Any PR targeting main will hit the same failure until the upstream baseline checksum is updated.

@CATMIAOZHI

Copy link
Copy Markdown
Collaborator Author

Post-fix verification on device

This fix was verified on a Redmi K80 Pro (HyperOS 3 / Android 15) running a personal build (personal/dev) that includes this fix alongside other personal customizations.

  • Before fix: Tool call card showed only tool_name during execution; command parameter was not rendered until the tool completed.
  • After fix: Full parameters (including command) are displayed on the card while the tool is still running, without waiting for tool completion.

The personal/dev branch contains additional features and optimizations beyond this fix. However, the fix itself is self-contained — the 3 files in this PR (RenderBatchCoordinator.kt, StreamMarkdownRenderer.kt, RenderBatchCoordinatorTest.kt) are the complete change and do not depend on any other personal modifications.

@CATMIAOZHI

Copy link
Copy Markdown
Collaborator Author

Nightly build with fix applied

A nightly build containing this fix is available for testing:

https://github.com/CATMIAOZHI/OperitNightlyRelease/releases/tag/v1.12.0%2B4-ry.1-dev.127

This build was used for the on-device verification mentioned above.

@luojiaping

Copy link
Copy Markdown
Collaborator

Ci不用管

@luojiaping

Copy link
Copy Markdown
Collaborator

Ci不用管

待会儿可能要发+5补丁,我看一下来得及的话就合,来不及的话就等一下

@AAswordman
AAswordman merged commit 57ab3fa into AAswordman:main Jul 29, 2026
1 check failed
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.

[Bug] 流式工具调用执行期间参数显示被截断,工具结束后才补全

3 participants