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
core: audio and video prompt attachments are silently dropped #54600
Audio and video prompt attachments never reach the model, even when the model's capabilities.input includes audio or video.
attachmentContent in packages/core/src/session/runner/to-llm-message.ts only lowers text/plain, directories, PNG/JPEG/GIF/WebP and PDF. Anything else returns [], so an audio/wav or video/mp4 attachment is dropped before unsupportedParts ever sees it. The user gets no error and the model never sees the file.
This is separate from #54491 / #54496, which cover the read tool. Once the MIME sniffing in #54496 lands, prompt attachments get the right audio/* / video/* type but are still dropped here.
Plugins
none
OpenCode version
2.0.26
Steps to reproduce
Configure a model with capabilities.input including audio and video (e.g. a Gemini model).
Send a prompt with a WAV or MP4 attachment whose MIME type is declared.
The outgoing request contains the prompt text but no audio/video part.
The script below calls toLLMMessages with a user message that has one inline attachment:
image/png: the model gets the prompt text and a media part.
audio/wav and video/mp4: the model gets only the prompt text. The attachment disappears and nothing reports an error.
As you found, attachmentContent in packages/core/src/session/runner/to-llm-message.ts returns [] for any MIME type other than text, directories, the image types and PDF.
This still happens on the latest dev (38454c6). That file hasn't changed since v2.0.26.
// Copy into packages/core/test/ of an opencode checkout and run:// cd packages/core && bun test test/audio-video-attachments.test.tsimport{expect,test}from"bun:test"import{Model}from"@opencode/core/model"import{Provider}from"@opencode/core/provider"import{SessionMessage}from"@opencode/core/session/message"import{Base64,FileAttachment}from"@opencode/schema/prompt"import{toLLMMessages}from"@opencode/core/session/runner/to-llm-message"import{DateTime}from"effect"constcreated=DateTime.makeUnsafe(0)constmodel=Model.Ref.make({id: Model.ID.make("gemini"),providerID: Provider.ID.make("google")})for(const[mime,name]of[["audio/wav","clip.wav"],["video/mp4","clip.mp4"],["image/png","control.png"],]asconst){test(`${mime} prompt attachment reaches the model`,()=>{constmessages=toLLMMessages([SessionMessage.User.make({id: SessionMessage.ID.make("msg_user"),type: "user",text: "Describe this file",files: [FileAttachment.make({data: Base64.make("AAECAw=="), mime,source: {type: "inline"}, name })],time: { created },}),],model,)console.log(mime,"->",JSON.stringify(messages[0]?.content))expect(messages[0]?.content.some((part)=>part.type==="media")).toBe(true)})}
Also hitting this on v2.0.30 (Linux), end to end against a real Gemini endpoint.
Setup: custom provider using @ai-sdk/google with a custom baseURL (Gemini-native /v1beta), model declared with modalities.input: ["text","image","audio","video","pdf"]. GET /api/model shows the capabilities correctly.
same via POST /api/session/:id/prompt with an explicit data:video/mp4;base64,... / data:audio/mpeg;base64,... → still only the text part
-f pic.png → arrives as inlineData as expected
Sending the same mp4/mp3 directly to the endpoint as inlineData works fine, so it's purely the client-side drop described here.
#54601 is green and mergeable. Would be great to get it reviewed, since right now the failure is silent and the model just replies that no file was attached.
Activity
opencode-agent commentedon Oct 11, 2026
Thanks for the clear report. I can confirm this.
The script below calls
toLLMMessageswith a user message that has one inline attachment:image/png: the model gets the prompt text and amediapart.audio/wavandvideo/mp4: the model gets only the prompt text. The attachment disappears and nothing reports an error.As you found,
attachmentContentinpackages/core/src/session/runner/to-llm-message.tsreturns[]for any MIME type other than text, directories, the image types and PDF.This still happens on the latest
dev(38454c6). That file hasn't changed sincev2.0.26.Related:
readtoolReproduction script (audio-video-attachments.test.ts)
Run it:
bun audio-video-attachments.test.tsdixiatielu commentedon Oct 16, 2026
Also hitting this on v2.0.30 (Linux), end to end against a real Gemini endpoint.
Setup: custom provider using
@ai-sdk/googlewith a custombaseURL(Gemini-native/v1beta), model declared withmodalities.input: ["text","image","audio","video","pdf"].GET /api/modelshows the capabilities correctly.I put a logging proxy in front of the endpoint:
opencode run -f clip.mp4/-f sound.mp3→ request contains only the text part (the local file is also sniffed asapplication/octet-stream, which feat(read): attach audio and video files for multimodal models #54496 addresses)POST /api/session/:id/promptwith an explicitdata:video/mp4;base64,.../data:audio/mpeg;base64,...→ still only the text part-f pic.png→ arrives asinlineDataas expectedSending the same mp4/mp3 directly to the endpoint as
inlineDataworks fine, so it's purely the client-side drop described here.#54601 is green and mergeable. Would be great to get it reviewed, since right now the failure is silent and the model just replies that no file was attached.