fix(plugins): attachment commands honor the composer lock

The creation request captures the attachments when it starts, so an attachment a plugin added or
removed afterwards was lost or left in the request. They refuse like the prompt commands.
This commit is contained in:
Mohamed Boudra
2026-11-02 07:20:56 +01:00
parent b965a3db7c
commit ca178b6578
2 changed files with 11 additions and 0 deletions
@@ -205,6 +205,9 @@ describe("toPluginComposer", () => {
expect(() => composer.setPrompt("a")).toThrow("The composer is locked");
expect(() => composer.insertText("b")).toThrow("The composer is locked");
expect(() => composer.addAttachment({ sourceId: "issues", item: issue })).toThrow(
"The composer is locked",
);
await expect(composer.setProvider("codex")).rejects.toThrow("The composer is locked");
await expect(composer.setModel("gpt")).rejects.toThrow("The composer is locked");
await expect(composer.setMode("plan")).rejects.toThrow("The composer is locked");
@@ -231,6 +234,12 @@ describe("toPluginComposer", () => {
input.isLocked = () => lock.locked;
expect(() => composer.insertText("late")).toThrow("The composer is locked");
expect(() => composer.addAttachment({ sourceId: "issues", item: issue })).toThrow(
"The composer is locked",
);
expect(() => composer.removeAttachment({ sourceId: "issues", itemId: issue.id })).toThrow(
"The composer is locked",
);
await expect(composer.setOptions({ effort: "low" })).rejects.toThrow("The composer is locked");
});
@@ -68,6 +68,7 @@ export function toPluginComposer(input: {
composerInput.insertText(text);
},
addAttachment({ sourceId, item }) {
assertUnlocked(composerInput.isLocked);
const source = plugin.attachmentSources.find((candidate) => candidate.id === sourceId);
if (!source) throw new Error(`Unknown attachment source: ${sourceId}`);
const attachment = createPluginResourceAttachment(
@@ -86,6 +87,7 @@ export function toPluginComposer(input: {
);
},
removeAttachment({ sourceId, itemId }) {
assertUnlocked(composerInput.isLocked);
composerInput.changeAttachments((current) =>
current.filter((candidate) => !isPluginAttachment(candidate, plugin.id, sourceId, itemId)),
);