Repository navigation
Description
Description
Editing a queued message that contains ordinary prompt text and a path attachment can leave the removed attachment in the text sent to the model. Keeping the attachment and changing only the prompt text has a related effect: the model receives the same attachment reference twice. In both cases, the visible composer and the replacement prompt's attachment metadata can disagree with the replacement prompt's actual text.
For example, queue the text summarize data with an uploaded file stored at /repo/confidential.csv. The app represents the upload as a path attachment and builds the model-visible prompt as:
summarize data
Attached file: `/repo/confidential.csv`
The presentation metadata separately stores displayText: "summarize data" and the attachment reference. When editing the queued message, the composer displays the ordinary text and restores the attachment as a removable card. Change the text to Use only public data, remove the file card, and save the edit. The replacement metadata correctly has an empty attachments list, but the replacement text still contains Attached file: /repo/confidential.csv, with the same backtick formatting shown above. The instruction to remove the attachment therefore does not remove its reference from the prompt the model receives.
If the file card is kept instead, saving a text change produces two copies of the attachment reference: one generated from the retained card and another copied from the original message. This can be reproduced without any model response; it is already present in the replacement request to the session prompt endpoint.
The cause is the treatment of the original prompt's text suffix in packages/app/src/session/composer/queue.ts. editedPromptInput rebuilds the request from the current composer contents, then retains everything after the original display text as notes. That suffix contains both comment notes and path attachment references. Preserving the entire suffix makes sense for retaining review context, but it also copies attachment references that the new request has already regenerated or that the user has removed.
The expected behavior is for the current composer attachments to determine the replacement's attachment references. Removing a card should remove its generated reference from both the model-visible text and presentation metadata. Retaining a card while editing the text should produce one reference. Existing review and browser comments should survive once, along with their file context, because those comments belong to the queued message being edited. A literal Attached file: phrase typed by the user must remain ordinary text.
The fix can use the existing structured prompt presentation to distinguish comments from attachments. When a hidden suffix belongs to a readable app presentation, rebuild the retained notes from the presentation's comments and let the newly built request supply the current path references. For messages from another client without that structured presentation, preserve the opaque suffix rather than trying to remove attachment-looking text with a regular expression. This keeps the change grounded in the metadata that owns the generated content.
The accompanying local patch follows that approach. The existing session queue regression suite now covers removing and retaining a path attachment, checking the replacement request rather than relying on a model response. The five focused cases pass while preserving review comments, browser comments, a user-typed attachment-looking phrase, and the comment's file:// context. They also cover opaque context from another client, deleted file mentions, and comment-only editing. The resulting request and attachment metadata agree with the edited composer.
This report concerns messages with non-empty display text and a hidden generated suffix.
Plugins
No plugin is required to reproduce this queue editing behavior.
OpenCode version
App package 2.0.28, reproduced from the dev source at 1015cb67d. The affected code is unchanged through 23e3493ab.
Steps to reproduce
- Open an app session with execution in progress, so follow-up messages can be queued.
- Write a non-empty prompt, such as
summarize data, attach a non-image file that the app stores as a path reference, and queue the message. - Click the queued message to edit it. Confirm that the prompt text appears in the editor and the file appears as an attachment card.
- Change the text to
Use only public data, remove the file card, and save the queued edit. - Inspect the replacement session prompt request. Its metadata has
attachments: [], but its text still includes the removed file's generated reference. - Repeat with another queued message, retaining the attachment card while changing the prompt text. The replacement request contains the same generated file reference twice.
Screenshot and/or share link
The discrepancy is in the submitted request text. The reproduction above shows the relevant prompt content; no shared session is needed.
Operating System
Windows. The cause is in shared app prompt construction rather than an operating-system-specific upload implementation.
Terminal
PowerShell for local verification; the affected editing flow is in the app composer.
Linked fix
A focused fix is available in #55180.
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the detailed report. I can confirm this on the latest
dev(23e3493ab). The relevant composer code is unchanged since 2.0.28.The script below calls the app's real
editedPromptInputwith a queued message (summarize dataplus a path attachment to/repo/confidential.csv) and changes the text toUse only public data:Attached file: `/repo/confidential.csv`whilemetadata.attachmentsis[].Related: #55180 (your proposed fix) and #49081 (the earlier change that restored queued attachments to the composer when editing).
Reproduction script (repro.sh)
Run it:
bash repro.sh