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
- Configure jcode with a text-only model (e.g. GLM-5.2 via Z.AI coding endpoint)
- In a session, trigger any action that produces an image in the message history (screenshot tool, pasted image, browser automation screenshot, etc.)
- 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.
Problem
When jcode takes a screenshot or otherwise captures an image during a session, that image is stored as a
ContentBlock::Imagein 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::Imageinto history, and the provider has no way to handle it.Reproduction
Expected behavior
The session continues working. Either:
Providertrait already exposessupports_image_input()for this), OR/remove-imagecommand), 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
api.z.ai/api/coding/paas/v4)Relevant code
ContentBlock::Imagevariant incrates/jcode-message-types/src/lib.rsProvider::supports_image_input()already exists on the trait but is not consulted before replaying image blocksjcode-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::Imagewhensupports_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.