feat: block sending images when selected model lacks vision support#457
feat: block sending images when selected model lacks vision support#457RobinAngele wants to merge 2 commits into
Conversation
When a user pastes a screenshot in the Cline chat composer or attaches images to a new task, and the selected Cline model does not support vision (supportsVision === false), the send/start action is now blocked with a clear error message. Previously only a non-blocking warning was shown, allowing the user to send images to a model that could not process them, resulting in errors and broken tasks. Changes: - cline-chat-composer.tsx: canSubmit now checks attachmentWarningMessage to disable the send button and Enter key when images are incompatible - cline-agent-chat-panel.tsx: strengthened warning message to clearly state the model does not support images - task-create-dialog.tsx: added vision support check that disables Create and Start buttons and shows an error when images are attached to a non-vision Cline model - runtime-api.ts: added server-side validation in startTaskSession and sendTaskChatMessage handlers to reject image input for models that do not support vision, serving as a backend safety net Related issues and PRs: - Fixes cline#307: Kanban failed to recognise the attached screenshot - Closes cline#413: Cline Kanban doesn't see attached files - Mitigates cline#395: Unable to update model capabilites (we only block when supportsVision is explicitly false, never when undefined) - Builds on PR cline#35: feat: support image attachments in Cline SDK chat (which added the initial warning but did not block sending) - Relates to cline#156: Feature: Allow agents to attach screenshots/images to tasks (the original feature request that introduced image support) Signed-off-by: Robin Angelé <git@robin4consulting.com>
Greptile SummaryThis PR upgrades the vision-incompatibility warning from informational to blocking: the chat composer's send button is disabled, the task-create dialog's start buttons are disabled, and a new backend safety net rejects requests when the selected Cline model has
Confidence Score: 3/5Not safe to merge as-is: the FUNDING.yml addition requires explicit maintainer review and removal, and the agentId='' bypass in the dialog leaves the image-blocking logic with a silent gap. The FUNDING.yml change adds the PR author's personal funding link to the repository without any justification — this alone warrants blocking the merge. The task-create-dialog image-blocking logic also silently skips the check when the user explicitly selects 'Default' from the override dropdown (agentId becomes ''), allowing images to reach a non-vision Cline model.
|
| Filename | Overview |
|---|---|
| .github/FUNDING.yml | Adds the PR author's personal GitHub account as a repository funding recipient — unrelated to the vision-blocking feature and should not be in this PR. |
| web-ui/src/components/task-create-dialog.tsx | Adds imagesBlockedByModel guard to single-mode Create/Start buttons and an orange warning banner; has a nullish-coalescing edge case where agentId='' bypasses the check. |
| src/trpc/runtime-api.ts | Adds backend vision checks for startTaskSession and the home-agent sendTaskChatMessage path; regular running Cline sessions still lack a backend guard but the frontend is the primary defense. |
| web-ui/src/components/detail-panels/cline-chat-composer.tsx | Adds !attachmentWarningMessage to canSubmit, correctly disabling the send button and Enter key when vision is unsupported. |
| web-ui/src/components/detail-panels/cline-agent-chat-panel.tsx | Tightens warning copy from 'may not accept' to 'does not support' — straightforward message improvement. |
Sequence Diagram
sequenceDiagram
participant User
participant TaskCreateDialog
participant ClineChatComposer
participant RuntimeAPI
User->>TaskCreateDialog: attach image + select non-vision model
TaskCreateDialog->>TaskCreateDialog: "imagesBlockedByModel = true"
TaskCreateDialog-->>User: orange banner + Create/Start disabled
User->>ClineChatComposer: attach image + select non-vision model
ClineChatComposer->>ClineChatComposer: "attachmentWarningMessage != null, canSubmit = false"
ClineChatComposer-->>User: warning shown, send button disabled
Note over User,RuntimeAPI: If frontend check bypassed (home-agent path)
User->>RuntimeAPI: startTaskSession or sendTaskChatMessage with images
RuntimeAPI->>RuntimeAPI: getProviderModels, check supportsVision
alt "supportsVision === false"
RuntimeAPI-->>User: "ok=false, error message"
else "supportsVision !== false"
RuntimeAPI-->>User: "ok=true, summary"
end
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
.github/FUNDING.yml:1
**Unrelated personal funding link in feature PR**
This file adds the PR author's personal GitHub account (`RobinAngele`) as a funding recipient for the `cline/kanban` repository. It is entirely unrelated to the vision-blocking feature and should not be part of this PR. If the repo maintainers want to add funding links, that decision belongs to the repo owners, not to a contributor as part of a feature commit.
### Issue 2 of 3
web-ui/src/components/task-create-dialog.tsx:206-218
**Image blocking silently skipped when agent override is set to "Default"**
`effectiveAgentIdForImages` uses `??` (nullish coalescing), which only bypasses `null` / `undefined`. When a user opens "Override Agent Settings" and explicitly selects **Default** from the agent dropdown, the picker emits an empty string `""` for `agentId`. Because `"" ?? defaultAgentId` evaluates to `""`, `effectiveAgentIdForImages` stays `""`, never equals `"cline"`, and `imagesBlockedByModel` stays `false` — even though the task will actually run on Cline. The same `??` pattern in `useTaskAgentModelPicker` also causes `providerModels` to be empty, making the check a silent no-op.
### Issue 3 of 3
src/trpc/runtime-api.ts:643-662
**Backend vision check only covers the home-agent path in `sendTaskChatMessage`**
The vision check in `sendTaskChatMessage` is scoped to the `isHomeAgentSessionId` branch. For regular running Cline tasks where the message goes directly to `sendTaskSessionInput`, there is no backend guard. The PR description acknowledges this ("UI blocks are the primary defense"), but if the frontend check is bypassed on an active non-home-agent Cline session, images will reach the model unchecked.
Reviews (1): Last reviewed commit: "Enable GitHub Sponsors button" | Re-trigger Greptile
Three issues fixed from PR review: 1. task-create-dialog.tsx: Changed effectiveAgentIdForImages from agentId ?? defaultAgentId ?? null to (agentId || defaultAgentId) ?? null to handle the edge case where agentId is an empty string. 2. runtime-api.ts: Moved the vision check in sendTaskChatMessage to the top of the function, before sendTaskSessionInput. This covers ALL code paths. Wrapped in try-catch so provider lookup failures never block. Removed the duplicate check from the home-agent else branch. 3. Removed .github/FUNDING.yml that was accidentally included. Signed-off-by: RobinAngele <git@robin4consulting.com>
Problem
When a user pastes a screenshot in the Cline chat composer or attaches images to a new task, and the selected Cline model does not support vision (
supportsVision === false), only a non-blocking warning was shown. The send/start button remained enabled, allowing the user to proceed. This caused model errors and broken, unusable tasks.Reported in:
Solution
When images are present and the effective Cline model has
supportsVision === false, sending is now blocked with a clear error message. The send/start button is disabled.Changes
web-ui/.../cline-chat-composer.tsxcanSubmitnow also checks!attachmentWarningMessage— disables send button + Enter key when images are incompatibleweb-ui/.../cline-agent-chat-panel.tsxweb-ui/.../task-create-dialog.tsxsrc/trpc/runtime-api.tsstartTaskSessionand beforesendTaskChatMessage(home agent path) — returns an error if the model lacks vision supportDesign decisions
false: IfsupportsVisionisundefined(e.g. custom providers that can't persist capabilities, see Unable to update model capabilites #395), we do NOT block. This avoids breaking users whose providers have unknown capabilities.runtime-api.tscatches edge cases where the frontend check is bypassed. Both use.catch(() => ({ models: [] }))so a network error during model lookup never blocks legitimate requests.Related issues / PRs
false, safe for undefined capabilitiesTesting
What was tested
runtime-api.ts(passed)What was NOT tested
npm run check(lint + typecheck + tests) —npm installnpm run web:dev(did not start due to missingweb-ui/node_modules)npm run buildHow to test manually
Prerequisites:
npm install(root) +npm install(web-ui) must complete.Scenario 1 — Chat composer blocking:
Scenario 2 — Task creation blocking:
Scenario 3 — Non-Cline agents unaffected:
Scenario 4 — Unknown capability (safe):
supportsVisionis undefinedfalse)