Skip to content

fix: updates log details view to show input images from user messages#2983

Merged
akshaydeo merged 2 commits into
mainfrom
04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages
Apr 24, 2026
Merged

fix: updates log details view to show input images from user messages#2983
akshaydeo merged 2 commits into
mainfrom
04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages

Conversation

@roroghost17
Copy link
Copy Markdown
Contributor

@roroghost17 roroghost17 commented Apr 23, 2026

Summary

Images attached to log messages were not being rendered visually in the log detail view. Instead, image content blocks were displayed as raw JSON in a collapsible code editor, making it difficult to inspect attached images at a glance.

Changes

  • Replaced the JSON/code editor rendering of image_url content blocks in logChatMessageView.tsx with an inline <img> tag that renders the image directly.
  • Added inline image rendering in logDetailView.tsx for image_url-type content blocks in chat messages and input_image-type content blocks in Responses API messages.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Create a log entry that includes a message with an attached image (via image_url or input_image content block).
  2. Open the log detail view for that entry.
  3. Verify the image renders inline within the message row rather than as a JSON blob.
cd ui
pnpm i || npm i
pnpm build || npm run build

Screenshots/Recordings

Before: Image content blocks were shown as collapsed JSON in a code editor.
After: Images are rendered inline as <img> elements with rounded borders.

After screenshots:

image.png

Breaking changes

  • No

Related issues

Security considerations

Image sources are rendered directly from log data. Ensure that only trusted or sanitized URLs are stored in log entries to avoid rendering arbitrary external content.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Log messages with image attachments now display images inline within both input-history and response areas instead of showing raw JSON. Images render only when a valid URL is available; entries without usable URLs are omitted. This makes visual content easier to review directly in the log view and reduces clutter from non-displayable image blocks.

Walkthrough

The PR updates two UI components to extract image URLs from message content arrays and render inline <img> elements instead of showing image objects as JSON.

Changes

Cohort / File(s) Summary
Detail view image rendering
ui/app/workspace/logs/sheets/logDetailView.tsx
Detects image_url (input history) and input_image (responses) blocks in message.content arrays, extracts image_url?.url, imports ContentBlock and ResponsesMessageContentBlock, and renders <img> elements for each URL.
Chat message image display
ui/app/workspace/logs/views/logChatMessageView.tsx
Replaces JSON/code-editor rendering of image blocks with direct block.image_url.url extraction and inline <img> rendering when url is present; falls back to null if absent.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through logs with a curious eye,
Found URLs tucked where JSON used to lie,
Now thumbnails bloom and images reply,
A rabbit’s cheer for pixels passing by 🥕📷

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding image rendering to the log details view for user message images.
Description check ✅ Passed The description covers all required template sections: summary, changes, type of change, affected areas, testing steps, screenshots, breaking changes, and security considerations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages

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

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@roroghost17 roroghost17 marked this pull request as ready for review April 23, 2026 20:47
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 23, 2026

Confidence Score: 5/5

Safe to merge; the one open finding is a minor hardening suggestion, not a blocking defect.

All remaining findings are P2 style/hardening suggestions (adding referrerPolicy="no-referrer"). The core logic is correct, and the previously flagged null-guard issue on input_image is a known open item. No blocking bugs were found.

No files require special attention beyond the optional referrerPolicy addition.

Security Review

  • Referrer leakage via external image URLs (logDetailView.tsx, logChatMessageView.tsx): All three new <img> tags render URLs from log data without referrerPolicy="no-referrer". Viewing a log entry that contains an external image URL causes the browser to request that URL with a Referer header revealing the admin panel origin. Adding referrerPolicy="no-referrer" closes this leak at zero cost.

Important Files Changed

Filename Overview
ui/app/workspace/logs/sheets/logDetailView.tsx Adds inline image rendering for image_url (chat) and input_image (Responses API) content blocks; logic is correct but images lack referrerPolicy="no-referrer"
ui/app/workspace/logs/views/logChatMessageView.tsx Replaces JSON code-editor rendering of image_url blocks with an inline <img> tag; fallthrough when url is empty is safe (returns null at end of function)

Reviews (3): Last reviewed commit: "fix: updates log details view to show in..." | Re-trigger Greptile

Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx Outdated
Copy link
Copy Markdown
Contributor

@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: 3

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

Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1507: The image rendering block is producing duplicate images
for image-only chat messages because LogChatMessageView already renders
image_url blocks; update the conditional around the
Array.isArray(message.content) ... .filter(...) rendering so it skips rendering
when the message is a chat message with no text (e.g., check message.text or
message.type === 'chat' and message.text?.trim() === ''), or otherwise only
render image_url blocks when LogChatMessageView is not responsible; reference
message.content, ContentBlock, and LogChatMessageView to locate and change the
logic so image-only messages don't render images twice.
- Around line 1500-1502: Replace the unstable index keys and guard undefined
URLs when rendering images: change the list item that currently uses key={i}
with key derived from the image URL (e.g., use key={src} where the variable src
is the image URL), and in the mapping over msg.content (the items named b with
b.type === "input_image") either filter out falsy b.image_url first
(msg.content.filter(b => b?.type === "input_image" && b.image_url).map(...)) or
add an in-map guard and skip rendering when b.image_url is missing; when
rendering use a stable key such as key={b.image_url} instead of the array index.

In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: The code reads an untrusted image URL from
block.image_url.url into src and renders it directly in an <img>, which can leak
data or solicit unsafe schemes; validate and sanitize the URL before rendering
in logChatMessageView.tsx by constructing a URL object from block.image_url.url
and only allowing safe schemes (e.g., https and optionally http if you accept
it), optionally check against an allowlist of hosts, and reject anything else
(fall back to a placeholder or skip rendering); when rendering the <img>, set
safer attributes such as loading="lazy" and referrerPolicy="no-referrer" (and
avoid crossorigin unless explicitly needed) to reduce privacy exposure.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1ba98e9f-7433-47c7-8a9a-477cf052bec1

📥 Commits

Reviewing files that changed from the base of the PR and between 59e37e6 and 7793cb2.

📒 Files selected for processing (2)
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/views/logChatMessageView.tsx

Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx Outdated
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Comment thread ui/app/workspace/logs/views/logChatMessageView.tsx
@roroghost17 roroghost17 force-pushed the 04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages branch from 7793cb2 to f5332b9 Compare April 23, 2026 21:07
@roroghost17 roroghost17 force-pushed the 04-23-fix_fixes_otel_exporting_to_show_input_and_output_messages_correctly branch from 59e37e6 to 8836145 Compare April 23, 2026 21:07
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (2)
ui/app/workspace/logs/sheets/logDetailView.tsx (1)

1501-1503: ⚠️ Potential issue | 🟡 Minor

Avoid index-derived keys for image lists.

Line 1502 and Line 1619 still include the loop index in keys. Prefer stable content-based keys (src / b.image_url) for these mapped image blocks.

Suggested key update
- .map((b, i) => {
+ .map((b) => {
    const src = b.image_url?.url;
    if (!src) return null;
    return (
      <img
-       key={`${i}-${src}`}
+       key={src}
        src={src}
        alt="Attached image"
        className="mt-2 max-w-full rounded border"
      />
    );
  })
...
- .map((b, i) => (
-   <img key={`${i}-${b.image_url}`} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" />
+ .map((b) => (
+   <img key={b.image_url} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" />
  ))

As per coding guidelines: "Always use stable, unique keys in lists; never use array index as key unless unavoidable".

Also applies to: 1618-1619

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 1501 - 1503, The
mapped image elements in logDetailView (the <img> rendered with
key={`${i}-${src}`} and the other using index + b.image_url) are using
index-derived keys; change both to use stable unique content-based keys (e.g.,
use src as the key for the first image map and b.image_url for the second) so
keys become something like key={src} / key={b.image_url} and remove the index
portion to ensure stable reconciliation.
ui/app/workspace/logs/views/logChatMessageView.tsx (1)

45-48: ⚠️ Potential issue | 🟠 Major

Harden untrusted image URLs before rendering.

Line 45 feeds log data directly into <img src>. This enables arbitrary external fetches from the operator browser. Gate allowed schemes and add safer image attributes.

Suggested hardening
+const isSafeImageSrc = (value: string) =>
+  /^(https?:\/\/|data:image\/|blob:)/i.test(value);
+
 // Handle image content
 if (block.image_url) {
   const src = block.image_url.url;
-  if (src) {
-    return <img src={src} alt="Attached image" className="max-w-full rounded border" />;
+  if (src && isSafeImageSrc(src)) {
+    return (
+      <img
+        src={src}
+        alt="Attached image"
+        loading="lazy"
+        referrerPolicy="no-referrer"
+        className="max-w-full rounded border"
+      />
+    );
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/views/logChatMessageView.tsx` around lines 45 - 48, The
image URL is used raw in the JSX (block.image_url.url in logChatMessageView.tsx)
which can trigger unsafe external fetches; add a validation step (e.g.,
implement an isSafeImageUrl or sanitizeImageUrl helper) that parses the URL (new
URL(...)) and only allows safe schemes (http, https, optionally data) and
rejects javascript:, blob:, and other schemes, and if the URL is invalid or
disallowed render a safe placeholder or nothing; when rendering the <img>
include safer attributes such as referrerPolicy="no-referrer", loading="lazy",
decoding="async" and crossOrigin="anonymous" to limit information leakage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1508: The image-rendering paths in logDetailView.tsx render
untrusted URLs directly into <img src> (see the inline branch that filters
message.content for type "image_url" and the other branch around lines
1615-1620); update both branches to run each image URL through the existing
safe-src sanitization utility (reuse the same guard used elsewhere in this
file), skip rendering if the sanitized URL is falsy, and add privacy-friendly
attributes to the <img> tag (e.g., referrerPolicy="no-referrer" and
decoding="async" or appropriate attributes used elsewhere) so that all
log-provided URLs are validated and rendered consistently across both code
paths.

---

Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1501-1503: The mapped image elements in logDetailView (the <img>
rendered with key={`${i}-${src}`} and the other using index + b.image_url) are
using index-derived keys; change both to use stable unique content-based keys
(e.g., use src as the key for the first image map and b.image_url for the
second) so keys become something like key={src} / key={b.image_url} and remove
the index portion to ensure stable reconciliation.

In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: The image URL is used raw in the JSX (block.image_url.url
in logChatMessageView.tsx) which can trigger unsafe external fetches; add a
validation step (e.g., implement an isSafeImageUrl or sanitizeImageUrl helper)
that parses the URL (new URL(...)) and only allows safe schemes (http, https,
optionally data) and rejects javascript:, blob:, and other schemes, and if the
URL is invalid or disallowed render a safe placeholder or nothing; when
rendering the <img> include safer attributes such as
referrerPolicy="no-referrer", loading="lazy", decoding="async" and
crossOrigin="anonymous" to limit information leakage.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3bc0a110-e629-44ad-9bcd-756f39249197

📥 Commits

Reviewing files that changed from the base of the PR and between 7793cb2 and f5332b9.

📒 Files selected for processing (2)
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/views/logChatMessageView.tsx

Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 23, 2026
akshaydeo
akshaydeo previously approved these changes Apr 24, 2026
Copy link
Copy Markdown
Contributor

akshaydeo commented Apr 24, 2026

Merge activity

@akshaydeo akshaydeo changed the base branch from 04-23-fix_fixes_otel_exporting_to_show_input_and_output_messages_correctly to graphite-base/2983 April 24, 2026 06:10
@roroghost17 roroghost17 force-pushed the 04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages branch from f5332b9 to ee59cfb Compare April 24, 2026 06:13
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (2)
ui/app/workspace/logs/sheets/logDetailView.tsx (1)

1493-1508: ⚠️ Potential issue | 🟠 Major

Apply safe-src validation consistently for both image-rendering branches.

At Line 1503 and Line 1619, URLs from logs are used directly in <img src>. Reuse a safe-source guard and privacy attributes in both branches.

Suggested fix
+const isSafeImageSrc = (value: string) =>
+  /^(https?:\/\/|data:image\/|blob:)/i.test(value);

 {text &&
   Array.isArray(message.content) &&
   (message.content as ContentBlock[])
     .filter((b) => b.type === "image_url")
     .map((b, i) => {
       const src = b.image_url?.url;
-      if (!src) return null;
+      if (!src || !isSafeImageSrc(src)) return null;
       return (
         <img
           key={`${i}-${src}`}
           src={src}
           alt="Attached image"
+          loading="lazy"
+          referrerPolicy="no-referrer"
           className="mt-2 max-w-full rounded border"
         />
       );
     })}

 {Array.isArray(msg.content) &&
   msg.content
     .filter((b) => b?.type === "input_image" && b.image_url)
-    .map((b, i) => (
-      <img key={`${i}-${b.image_url}`} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" />
-    ))}
+    .map((b, i) =>
+      isSafeImageSrc(b.image_url as string) ? (
+        <img
+          key={`${i}-${b.image_url}`}
+          src={b.image_url}
+          alt="Attached image"
+          loading="lazy"
+          referrerPolicy="no-referrer"
+          className="mt-2 max-w-full rounded border"
+        />
+      ) : null
+    )}

Also applies to: 1615-1620

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 1493 - 1508, The
image branch using (message.content as ContentBlock[]).filter(... type ===
"image_url") currently injects raw URLs into <img src> without the same
safe-source validation and privacy attributes used elsewhere; update this branch
to run each b.image_url?.url through the existing safeSrc (or equivalent) guard
before rendering and skip images that fail validation, and add the same privacy
attributes (e.g., referrerPolicy="no-referrer", loading="lazy", and any other
attrs used in the other branch) to the <img> element so both image-rendering
paths use consistent validation and privacy protections (refer to
message.content, ContentBlock, and image_url in logDetailView.tsx to locate the
code).
ui/app/workspace/logs/views/logChatMessageView.tsx (1)

45-48: ⚠️ Potential issue | 🟠 Major

Harden image URL rendering before using it in src.

At Line 45 and Line 47, the URL is rendered directly from log data. Please gate to safe schemes and add privacy/perf-safe attributes.

Suggested fix
+const isSafeImageSrc = (value: string) =>
+  /^(https?:\/\/|data:image\/|blob:)/i.test(value);

 // Handle image content
 if (block.image_url) {
   const src = block.image_url.url;
-  if (src) {
-    return <img src={src} alt="Attached image" className="max-w-full rounded border" />;
+  if (src && isSafeImageSrc(src)) {
+    return (
+      <img
+        src={src}
+        alt="Attached image"
+        loading="lazy"
+        referrerPolicy="no-referrer"
+        className="max-w-full rounded border"
+      />
+    );
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/views/logChatMessageView.tsx` around lines 45 - 48, In
logChatMessageView.tsx, avoid rendering block.image_url.url directly into the
img src; validate and sanitize the URL (e.g., using the URL constructor to parse
block.image_url.url and only allow http: or https: schemes), and if invalid or
unsafe, skip rendering or render a safe fallback; when rendering, add
privacy/perf attributes such as loading="lazy" decoding="async" and
rel="noreferrer noopener" (for linked images) and consider adding crossOrigin as
appropriate to the <img> output to prevent leaking referrers and improve
performance. Ensure these checks are performed at the place where src is
assigned (reference block.image_url.url and the rendering branch in the
component) so unsafe schemes are never passed to the img element.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1508: The image branch using (message.content as
ContentBlock[]).filter(... type === "image_url") currently injects raw URLs into
<img src> without the same safe-source validation and privacy attributes used
elsewhere; update this branch to run each b.image_url?.url through the existing
safeSrc (or equivalent) guard before rendering and skip images that fail
validation, and add the same privacy attributes (e.g.,
referrerPolicy="no-referrer", loading="lazy", and any other attrs used in the
other branch) to the <img> element so both image-rendering paths use consistent
validation and privacy protections (refer to message.content, ContentBlock, and
image_url in logDetailView.tsx to locate the code).

In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: In logChatMessageView.tsx, avoid rendering
block.image_url.url directly into the img src; validate and sanitize the URL
(e.g., using the URL constructor to parse block.image_url.url and only allow
http: or https: schemes), and if invalid or unsafe, skip rendering or render a
safe fallback; when rendering, add privacy/perf attributes such as
loading="lazy" decoding="async" and rel="noreferrer noopener" (for linked
images) and consider adding crossOrigin as appropriate to the <img> output to
prevent leaking referrers and improve performance. Ensure these checks are
performed at the place where src is assigned (reference block.image_url.url and
the rendering branch in the component) so unsafe schemes are never passed to the
img element.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c5511e16-799e-44a5-9862-b3b1a72fa50a

📥 Commits

Reviewing files that changed from the base of the PR and between f5332b9 and ee59cfb.

📒 Files selected for processing (2)
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/views/logChatMessageView.tsx

@akshaydeo akshaydeo changed the base branch from graphite-base/2983 to main April 24, 2026 06:23
@akshaydeo akshaydeo dismissed stale reviews from coderabbitai[bot] and themself April 24, 2026 06:23

The base branch was changed.

@akshaydeo akshaydeo merged commit 25233ef into main Apr 24, 2026
15 of 16 checks passed
@akshaydeo akshaydeo deleted the 04-24-fix_updates_log_details_view_to_show_input_images_from_user_messages branch April 24, 2026 06:24
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.

3 participants