1jehuang / 1jehuang/jcode

Images in chat history break text-only model sessions (GLM-5.2 and other non-vision providers)

Open
#755 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug priority: high triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Problem

When jcode takes a screenshot or otherwise captures an image during a session, that image is stored as a ContentBlock::Image in the message history. On every subsequent turn, the full message history (including image blocks) is replayed to the provider.

For vision-capable models this is fine. But for text-only models like GLM-5.2 (via Z.AI OpenAI-compatible endpoint), the image content is sent to an API that cannot accept it. The request fails, the chat is permanently broken, and there is no in-TUI way to recover. The only option is to start a new session, losing all conversation context.

This happens even when the system prompt explicitly tells the agent not to capture screenshots. Tool calls that produce images (browser screenshot, computer_use, etc.) still inject ContentBlock::Image into history, and the provider has no way to handle it.

Reproduction

  1. Configure jcode with a text-only model (e.g. GLM-5.2 via Z.AI coding endpoint)
  2. In a session, trigger any action that produces an image in the message history (screenshot tool, pasted image, browser automation screenshot, etc.)
  3. Send another prompt

Expected behavior

The session continues working. Either:

  • (A) Image blocks are automatically stripped from the request payload when the active provider does not support vision (the Provider trait already exposes supports_image_input() for this), OR
  • (B) The user can remove individual images from the chat history via the TUI (hover/click an X on the image, or a /remove-image command), so the next request no longer contains them.

Ideally both. (A) prevents the problem. (B) gives the user manual control.

Actual behavior

The API request includes the image block. The text-only provider rejects it (400 error or similar). The session is stuck. Every subsequent prompt re-sends the same broken history. There is no way to delete the offending image without abandoning the session.

Environment

  • jcode v0.66.0
  • Provider: Z.AI GLM-5.2 (OpenAI-compatible, api.z.ai/api/coding/paas/v4)
  • macOS 26.5.1, Apple Silicon

Relevant code

  • ContentBlock::Image variant in crates/jcode-message-types/src/lib.rs
  • Provider::supports_image_input() already exists on the trait but is not consulted before replaying image blocks
  • Message serialization for provider requests happens in the provider runtime crates (e.g. jcode-provider-openai-runtime, jcode-provider-openrouter-runtime)

Proposed approach

Option A (automatic stripping) would be the least invasive fix. In the request-building path for each provider, filter out ContentBlock::Image when supports_image_input() == false. This is a one-line guard per provider message serialization.

Option B (manual deletion) requires TUI work: a hover-to-reveal delete affordance on rendered images, or a slash command, that removes the image block from the persisted session history.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with ContentBlock::Image in crates/jcode-message-types/src/lib.rs and trace provider request serialization in jcode-provider-openai-runtime and jcode-provider-openrouter-runtime. Check how Provider::supports_image_input() is exposed and identify the request-building paths that replay message history. Done means text-only sessions can continue after image-producing actions without sending unsupported image blocks; TUI deletion is an additional option described by the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.