feat: warn about unsupported attachment inputs

Compare normalized attachment MIME types with the selected model's declared input modalities and show a non-blocking warning for incompatible files.

Recheck newly added attachments, restored drafts, async metadata, and existing files after model changes while avoiding warnings when capability metadata is unavailable. Summarize affected filenames and localize the warning across every supported locale.

Add focused modality compatibility coverage, document the composer behavior, and keep model metadata subscriptions stable to prevent startup render loops.
This commit is contained in:
Bohdan Triapitsyn
2026-07-22 14:40:40 +03:00
parent fd0f6a6bac
commit d654911925
14 changed files with 123 additions and 1 deletions
+27
View File
@@ -149,6 +149,33 @@ type OpenCodeAttachmentMimeType =
| "application/pdf"
| "text/plain"
export type AttachmentInputModality = "text" | "image" | "pdf" | "audio" | "video"
export const getAttachmentInputModality = (mimeType: string): AttachmentInputModality | undefined => {
const normalizedMimeType = mimeType.toLowerCase().split(";", 1)[0]?.trim() ?? ""
if (normalizedMimeType.startsWith("image/")) return "image"
if (normalizedMimeType.startsWith("audio/")) return "audio"
if (normalizedMimeType.startsWith("video/")) return "video"
if (normalizedMimeType === "application/pdf") return "pdf"
if (normalizedMimeType.startsWith("text/")) return "text"
return undefined
}
export const getUnsupportedAttachmentInputs = <T extends { mimeType: string }>(
attachments: T[],
supportedInputModalities: string[],
): Array<{ attachment: T; modality: AttachmentInputModality }> => {
const supportedModalities = new Set(supportedInputModalities.map((modality) => modality.toLowerCase()))
const unsupportedInputs: Array<{ attachment: T; modality: AttachmentInputModality }> = []
for (const attachment of attachments) {
const modality = getAttachmentInputModality(attachment.mimeType)
if (modality && !supportedModalities.has(modality)) {
unsupportedInputs.push({ attachment, modality })
}
}
return unsupportedInputs
}
const SUPPORTED_BINARY_MIMES = new Map<string, OpenCodeAttachmentMimeType>([
["image/png", "image/png"],
["image/jpeg", "image/jpeg"],