You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Attached images degrade to a bare text placeholder when the model lacks vision — agent has no way to read them #42758
When a user pastes images into a chat and the active model does not support vision (e.g. a text-only model like deepseek-v4-flash), the image file parts are replaced by a plain text placeholder before being sent to the model. The agent then has no way to access the actual image content — the placeholder carries no reference to how the image can be retrieved.
Current behavior
In packages/opencode/src/session/message-v2.ts (around line 213):
So the model sees only [Attached image/png: image-2.png]. There is no session/message/part id, no API reference, no data URL — nothing the agent could use to fetch the image itself. The only way to recover the image is to query the local opencode.db (the part table stores {type:"file", mime, filename, url} with session_id/message_id) or hit the local serve API, which is undocumented for this purpose and requires guessing the current session.
Why it matters
This forces workarounds: to read a pasted image, an agent (or a skill like an "image recognition" skill) has to:
guess the current session (no env var exposes session_id),
query the sqlite DB / serve API to find the most recent image part,
forward the data: URL to a separate vision model.
That's fragile (parallel sessions race) and entirely non-obvious from the placeholder alone.
Proposal (any of these would help)
Include a retrievable reference in the placeholder, e.g. [Attached image/png: image-2.png] (session: …, message: …, part: …) or a URL like opencode://session/{sessionID}/message/{messageID}/part/{partID} the agent can dereference.
Expose the current session id to agents (e.g. OPENCODE_SESSION_ID env var when running tool calls) so tools/skills can scope queries precisely.
A config option to keep sending lightweight media metadata (mime, filename, session/message/part ids) to text-only models instead of dropping it.
This issue might be a duplicate of existing issues. Please check:
[FEATURE]: Allow plugins to customize behavior when a model doesn't support a media modality (image/audio/video) #36006: Same root problem — when a model doesn't support a media modality, the agent has no actionable path. That issue also proposes plugin hooks and richer replacement text (including file paths) so agents can recover. The proposals in both issues overlap substantially (exposing retrievable references / file paths, configurable replacement text, and hooks after the strip step).
If your issue adds meaningful new detail or a distinct angle not covered by those, feel free to clarify the difference so maintainers can decide whether to merge them.
Thanks for the duplicate check — #36006 is indeed the same root problem and its proposals are excellent. I want to clarify one gap my report adds that #36006 does not cover: images pasted from the clipboard have no local file path at all.
The paste scenario
When a user pastes an image (rather than @-referencing a file), the image never touches disk:
It is stored as a data:image/...;base64,... URL inside the part table of opencode.db (verified: {type:"file", mime:"image/png", filename:"image-2.png", url:"data:..."} with session_id/message_id).
filename is a synthetic name (image-2.png), not a path.
So for pasted images, none of #36006's options help directly:
Option C (put the file path in the replacement text) — there is no path to put there.
Options A/B (plugin hook / custom template pointing at a path) — same problem.
The only way to recover a pasted image is via the session/message/part identity (querying the local DB or the serve API GET /session/:id/message). The agent currently cannot know even the current session_id (no env var, no context injection).
Concrete suggestion to cover both scenarios
If #36006's Option A hook were extended to include the original part's identity (or its data: URL) rather than only a file path, both scenarios would be covered:
input: {
sessionID: string
messageID?: string
partID?: string
dataURL?: string// for pasted media that never touched disk
filename?: string
mime: string
...
}
That way a plugin can guide the LLM to a tool that reads pasted images from the DB/serve API (which is exactly the workaround my team built: a skill that pulls the latest image part via the serve API and forwards it to a separate vision model).
Also worth noting: exposing the current session_id to agents (e.g. an OPENCODE_SESSION_ID env var for tool calls) would fix the related issue #33035 and remove the need to guess the session at all.
Happy to consolidate this detail into #36006 if maintainers prefer a single issue.
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.
Activity
github-actions commentedon Aug 15, 2026
This issue might be a duplicate of existing issues. Please check:
session_idto MCP tools/agents (one of the workarounds your issue describes needing to find images via the serve API).If your issue adds meaningful new detail or a distinct angle not covered by those, feel free to clarify the difference so maintainers can decide whether to merge them.
sumwcc commentedon Aug 16, 2026
Thanks for the duplicate check — #36006 is indeed the same root problem and its proposals are excellent. I want to clarify one gap my report adds that #36006 does not cover: images pasted from the clipboard have no local file path at all.
The paste scenario
When a user pastes an image (rather than
@-referencing a file), the image never touches disk:data:image/...;base64,...URL inside theparttable ofopencode.db(verified:{type:"file", mime:"image/png", filename:"image-2.png", url:"data:..."}withsession_id/message_id).filenameis a synthetic name (image-2.png), not a path.So for pasted images, none of #36006's options help directly:
The only way to recover a pasted image is via the session/message/part identity (querying the local DB or the serve API
GET /session/:id/message). The agent currently cannot know even the currentsession_id(no env var, no context injection).Concrete suggestion to cover both scenarios
If #36006's Option A hook were extended to include the original part's identity (or its
data:URL) rather than only a file path, both scenarios would be covered:That way a plugin can guide the LLM to a tool that reads pasted images from the DB/serve API (which is exactly the workaround my team built: a skill that pulls the latest image part via the serve API and forwards it to a separate vision model).
Also worth noting: exposing the current
session_idto agents (e.g. anOPENCODE_SESSION_IDenv var for tool calls) would fix the related issue #33035 and remove the need to guess the session at all.Happy to consolidate this detail into #36006 if maintainers prefer a single issue.
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊