Skip to content

fix(agent-runtime): preserve non-text content blocks in MessageConverter#426

Merged
jerryliang64 merged 1 commit intomasterfrom
worktree-fix-lossy-content-blocks
Apr 1, 2026
Merged

fix(agent-runtime): preserve non-text content blocks in MessageConverter#426
jerryliang64 merged 1 commit intomasterfrom
worktree-fix-lossy-content-blocks

Conversation

@jerryliang64
Copy link
Copy Markdown
Contributor

@jerryliang64 jerryliang64 commented Apr 1, 2026

Summary

  • 修复 MessageConverter.toContentBlocks() 有损转换问题:原实现通过 .filter(part => part.type === 'text') 过滤掉了所有非 text 类型的 content block(如 tool_usetool_result),导致基于 @anthropic-ai/claude-agent-sdk 实现 execRun 时,工具调用信息在转换后丢失
  • 修复 MessageConverter.toInputMessageObjects() 同样的有损问题:原实现将所有 content part 当作 text 处理,非 text 块的 .text 为 undefined
  • 扩展类型系统:在 ContentBlockType 中新增 ToolUseToolResult,新增对应的输入/输出类型接口,并增加 GenericContentBlock 兜底未来新类型
  • 提供 type guard 函数isTextBlock()isToolUseBlock()isToolResultBlock() 方便业务代码做类型收窄

Affected areas

影响面 修复前 修复后
Thread 历史消息 tool_use 块被丢弃 完整保留
SSE 流式 delta 不包含 tool_use 事件 包含所有 content block
Run output 缺少 tool_use block 完整保留

Test plan

  • toContentBlocks 保留 tool_use content parts
  • toContentBlocks 保留 tool_result content parts(含 is_error 标记)
  • toContentBlocks 保留未知类型 content parts(generic 兜底)
  • toContentBlocks 保持混合类型的顺序
  • toMessageObject 保留 tool_use blocks
  • extractFromStreamMessages 正确提取包含 tool_use 的消息
  • toInputMessageObjects 保留 tool_use / tool_result blocks
  • type guard 函数正确收窄类型
  • 所有 116 个测试通过

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for tool use and tool result content blocks in message handling.
    • Message conversion now preserves all content block types instead of filtering non-text content.
  • Improvements

    • Enhanced type safety with expanded content block type definitions.
    • Improved message processing to handle mixed content ordering across text, tool use, and tool result blocks.

MessageConverter.toContentBlocks() was filtering out all non-text content
blocks (tool_use, tool_result, etc.), causing lossy message conversion when
execRun is implemented with @anthropic-ai/claude-agent-sdk.

Changes:
- Widen ContentBlockType to include ToolUse and ToolResult
- Add ToolUseContentBlock, ToolResultContentBlock, GenericContentBlock types
- Add corresponding input types (TextInputContentPart, etc.)
- Fix toContentBlocks(): .filter().map() → .map() with text wrapping and
  non-text passthrough
- Fix toInputMessageObjects(): same treatment for input messages
- Add isTextBlock/isToolUseBlock/isToolResultBlock type guard helpers
- Update InputMessage.content type to use InputContentPart[]
- Add comprehensive test coverage for non-text content preservation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

📝 Walkthrough

Walkthrough

The changes expand message content handling to support tool-related blocks (tool_use, tool_result, generic) alongside text blocks. Type guards are added to discriminate content variants. Conversion logic in MessageConverter is updated to preserve non-text blocks instead of filtering them, and new content-part interfaces are introduced for input/output typing.

Changes

Cohort / File(s) Summary
Message Conversion Logic
core/agent-runtime/src/MessageConverter.ts
Added type-guard functions (isTextBlock, isToolUseBlock, isToolResultBlock) to discriminate MessageContentBlock variants. Updated toContentBlocks and toInputMessageObjects to preserve and pass through non-text content blocks instead of filtering them out.
Type Definitions
core/types/agent-runtime/AgentMessage.ts
Expanded ContentBlockType to include ToolUse and ToolResult. Introduced distinct content-part interfaces for input (TextInputContentPart, ToolUseInputContentPart, ToolResultInputContentPart, GenericInputContentPart) and output (ToolUseContentBlock, ToolResultContentBlock, GenericContentBlock). Updated InputContentPart and MessageContentBlock to unions of their variants. Updated InputMessage.content type to reflect new structure.
Type Exports
core/tegg/agent.ts
Added re-exports of new content-part and content-block types, plus type-guard functions (isTextBlock, isToolUseBlock, isToolResultBlock) from agent-runtime.
Test Coverage
core/agent-runtime/test/MessageConverter.test.ts
Extended assertions to validate type-guard narrowing. Added tests for preservation of tool_use, tool_result, and generic blocks through conversion methods. Added dedicated type-guard validation tests.
Runtime Tests
core/agent-runtime/test/AgentRuntime.test.ts
Updated completion test assertions to validate first content block is text before accessing text.value property.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 We've woven new threads through the types today,
Tool blocks now dance in the content's ballet,
Guards keep things safe, type-checked all the way,
From text to tools—no more sorting fray,
The message now flows like clover at play! 🍀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding preservation of non-text content blocks in MessageConverter, which is the core fix addressed across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-fix-lossy-content-blocks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for tool-related content blocks (tool_use, tool_result) and generic blocks within the agent runtime. It includes new type definitions, type guards, and updates to the MessageConverter to ensure these blocks are preserved during message processing. Comprehensive tests have been added to verify the handling of mixed content types. A review comment identifies an opportunity to reduce code duplication in MessageConverter.ts by reusing the toContentBlocks method.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/types/agent-runtime/AgentMessage.ts`:
- Around line 76-78: The InputMessage.content type change breaks existing
callers and the MessageConverter which assumes non-string content is an array;
update the InputMessage interface to accept string | InputContentPart |
InputContentPart[] (restore single-object support) and then normalize inside the
MessageConverter method that maps content (the mapping call around
MessageConverter.ts:148) by treating a single InputContentPart as [part] before
calling .map(); ensure the converter branches handle string, single object, and
array uniformly so tests and examples continue to work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d8cfd482-70d7-4340-b704-3b69475a85d9

📥 Commits

Reviewing files that changed from the base of the PR and between 0c77cd1 and 5b93066.

📒 Files selected for processing (5)
  • core/agent-runtime/src/MessageConverter.ts
  • core/agent-runtime/test/AgentRuntime.test.ts
  • core/agent-runtime/test/MessageConverter.test.ts
  • core/tegg/agent.ts
  • core/types/agent-runtime/AgentMessage.ts

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.

1 participant