Skip to content

fix(components): render blob images inline in tool call resource blocks - #506

Open
clanzhang wants to merge 3 commits into
LodyAI:mainfrom
clanzhang:fix/render-resource-blob-images-in-tool-output
Open

fix(components): render blob images inline in tool call resource blocks#506
clanzhang wants to merge 3 commits into
LodyAI:mainfrom
clanzhang:fix/render-resource-blob-images-in-tool-output

Conversation

@clanzhang

@clanzhang clanzhang commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Related issue

Closes #462

Problem / pressure

When an ACP agent reads an image (e.g. Kimi's "reading media" tool), the tool returns a resource content block with binary blob data and an image/* mimeType. The StandardToolContentBlock component in view.tsx only checks for text in the resource — it falls through to rendering a "Download blob" link using content.resource.uri as the href. The URI is the resource's original identifier (e.g. file:///path/to/image.png), not a downloadable URL, so clicking it exposes the raw base64 string to the user instead of rendering the image.

Summary

Add a blob branch to the resource case in StandardToolContentBlock. When the resource contains a blob with an image/* mimeType, construct a data URL via the existing buildSafeBase64DataUrl() helper and render an inline <img> tag, matching the pattern already used by the image content type case. Non-image blobs fall through to the existing download link.

Before / after

Before After
Tool returns a resource with blob + image/* mimeType → "Download blob" link → raw base64 displayed to user Tool returns a resource with blob + image/* mimeType → inline <img> renders the image

Test plan

  • Have an agent (e.g. Kimi) read an image via its tool
  • Observe the tool output in chat — the image should render inline instead of showing base64 data
  • Verify non-image blob resources (e.g. PDF) still show the download link
  • Verify text resources still render as markdown
  • Run pnpm --dir packages/components test if available

Context handoff

Instructions for reviewing agents

  • Review focus: packages/components/src/components/ai-gui/view.tsx — the resource case in StandardToolContentBlock (around line 6121). Verify the new blob branch correctly reuses buildSafeBase64DataUrl() and the image/* mimeType guard.
  • Decisions to challenge: Whether non-image blob types should also get inline rendering (audio, PDF). The current fix is image-only to match the reported bug; extending to other types is a separate scope.
  • Plausible failures / evidence gaps: The fix depends on content.resource having blob and mimeType fields from the ACP SDK EmbeddedResource type. If a specific agent sends blob data under a different key (e.g. data instead of blob), it would not be caught. The buildSafeBase64DataUrl helper validates both fields so malformed data renders nothing rather than breaking.

Authoring context

  • User goal / directives: Fix issue [Bug] 点击reading media,展开了媒体的base64 #462 so that image resources from agent tool calls render visually instead of exposing base64 data.
  • Constraints / non-goals: Only fix the rendering path in StandardToolContentBlock. Do not change the ACP protocol, CLI-side materialization, or other content block types.
  • Risk-bearing decisions: The buildSafeBase64DataUrl helper already validates mimeType format and base64 alphabet, so no new sanitization was added. The data URL is consumed only by an <img> tag's src attribute.
  • Destructive or irreversible behavior: None. The change is purely additive — a new branch before the existing fallback.
  • Deliberately not done or tested: Audio and PDF blob rendering. The issue specifically concerns images. Other blob types continue to show the download link. Integration testing against a live agent was not performed.
  • Unknowns / confidence: High confidence for image/* blobs. The pattern is a direct copy of the existing image case at line 6067-6081. Moderate uncertainty on whether all agents use blob as the key name — the ACP SDK EmbeddedResource type distinguishes TextResourceContents (with text) from BlobResourceContents (with blob), so this matches the protocol contract.

When an ACP tool returns a resource content block with binary blob data
(e.g., an image the agent read), the renderer now displays it inline
instead of showing a "Download blob" link that navigates to raw base64.

The fix checks for blob resources with image/* mimeType and renders them
using buildSafeBase64DataUrl(), matching the pattern used for the image
content type. Non-image blobs still fall through to the download link.

Fixes LodyAI#462
@github-actions github-actions Bot added scope: components status:needs-pr-attention External PR needs contributor attention before review labels Sep 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d9e3adcac

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/components/src/components/ai-gui/view.tsx Outdated
Comment thread packages/components/src/components/ai-gui/view.tsx Outdated
Comment thread packages/components/src/components/ai-gui/view.tsx Outdated
Comment thread packages/components/src/components/ai-gui/view.tsx Outdated
@github-actions github-actions Bot removed the status:needs-pr-attention External PR needs contributor attention before review label Sep 8, 2026
`StandardToolContentBlock` only handled text resources. Blob resources
with `image/*` mimeType fell through to a download link that exposed
raw base64. Now renders inline `<img>` via `buildSafeBase64DataUrl()`,
falling through to the download link when the image cannot be inlined.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3c3e88c5a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

) {
const src = buildSafeBase64DataUrl(content.resource.mimeType, content.resource.blob);
if (src) {
<div className="space-y-2">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Return the inline resource image

When a resource contains a valid image/* blob, this JSX element is merely evaluated and discarded because the branch does not return it. Execution therefore always continues to the URI fallback; typical file: resource URIs are rejected and render nothing, while HTTP(S) URIs still render a download link, so the newly added image path never displays the image.

Useful? React with 👍 / 👎.

@wibus-wee wibus-wee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I traced the actual Kimi path. Lody pins acp-extension-kimi@38fb45e, where structured tool results are serialized into ACP text via JSON.stringify(...), not emitted as resource.blob.

So this blob renderer doesn't address the actual base64 path. Also, the new if (src) branch is missing a return, so it currently renders nothing anyway.

I think the better fix is in acp-extension-kimi: normalize Kimi's media result into standard ACP image/resource content, then let the existing UI renderer handle it.

@github-actions github-actions Bot added the status:needs-pr-attention External PR needs contributor attention before review label Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

@clanzhang, this pull request needs updates before review.

It is marked status:needs-pr-attention. Address the findings below by 2026-09-16 08:23:26 UTC. The label and this comment are removed automatically after the PR passes validation.

If the PR remains invalid for 7 days, it will be closed and marked status:pr-policy-expired. Continue afterward by opening a new pull request with the current template.

Policy findings
PR does not meet Lody contribution requirements:

- Missing required heading: ## Visual explanation

See `CONTRIBUTING.md` and `.github/PULL_REQUEST_TEMPLATE.md`.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: components status:needs-pr-attention External PR needs contributor attention before review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 点击reading media,展开了媒体的base64

2 participants