Pasted images are never rendered in the transcript, only the [image N] placeholder
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
Paste an image and press Enter: the transcript only ever shows the literal [image N] placeholder. The bytes do reach the model, but nothing renders, so there is no way to confirm which image was actually attached.
Images coming back the other way (tool results, generated images) already render inline, so the two directions behave inconsistently.
This is a UX gap rather than a defect. Filing it because the rendering machinery is already fully in place and unused, which makes it look intentional when reading the code.
Environment
- macOS 15, aarch64
- jcode v0.84.0 and current
master
What already exists
Everything needed is present:
RenderedImageSource::UserInput— the variant for exactly this caseRenderedImageAnchor::UserPrompt { ordinal }— the anchor for exactly this caseresolve_anchored_items_innerbuckets by prompt ordinal (by_prompt)render_message_intoemits those buckets under the user's message- the server-side history renderer (
session/render.rs) does anchor user images viaimage_anchor_for_message
The gap
Nothing pushes a RenderedImage for the images the client just submitted.
submit_input takes pending_images, sends them to the provider, and stores them on the session, but never adds a rendered image for the live transcript. A remote client only rebuilds remote_side_pane_images from a full History payload, so the attachment stays invisible for the whole turn even though the model received it.
Net effect: the persisted session knows the image belongs to that prompt, but the live view never shows it.
Suggested fix
Echo the submitted images as RenderedImage { source: UserInput, anchor: UserPrompt { ordinal } } right after the user's DisplayMessage is pushed, in both paths that consume pending_images:
submit_input(local turns)submit_prepared_remote_input(remote turns)
Two details that cost me a debugging cycle, in case they help:
- The ordinal must be counted the way the renderer counts it: rendered user display messages, excluding synthetic attached-image label messages, matching
prepare_body_incrementalandsession/render.rs. compacted_hidden_user_prompts()must not be added. It offsets the human-visible prompt number, not the anchor, which is relative to the rendered window. Adding it pushes every image past its real bucket. I got this wrong first.
The local side_pane_images merge dedupes on (media_type, data), so echoing before the turn is persisted does not double-render.
Branch, if useful as a reference: https://github.com/aphelion31/jcode/tree/fix/macos-clipboard-image-applescript
Tests cover presence, payload identity, per-prompt ordinal advance (a fixed ordinal stacks turn 2 under turn 1), and that a text-only turn fabricates nothing. All three fail against the unpatched submit paths.
Not covered
stage_turn_for_remote_tick_loop (queued / interleave sends) still echoes nothing. Those hand the images to process_remote_followups, which owns its own user-message echo, so wiring that up wants its own change rather than a second echo site.
Note
Filing as an issue rather than a PR because pull_request_creation_policy is collaborators_only, so CreatePullRequest is rejected for non-collaborators. Happy to open one if that changes.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at submit_input and submit_prepared_remote_input, then read session/render.rs and the existing ordinal logic in prepare_body_incremental. Verify how pending_images and RenderedImageSource::UserInput are handled, and run the tests described in the issue. Done means submitted images render under the correct user prompt in both local and remote turns without fabricating images for text-only turns.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100