Skip to content

feat: block sending images when selected model lacks vision support#457

Open
RobinAngele wants to merge 2 commits into
cline:mainfrom
RobinAngele:main
Open

feat: block sending images when selected model lacks vision support#457
RobinAngele wants to merge 2 commits into
cline:mainfrom
RobinAngele:main

Conversation

@RobinAngele
Copy link
Copy Markdown

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

File Change
web-ui/.../cline-chat-composer.tsx canSubmit now also checks !attachmentWarningMessage — disables send button + Enter key when images are incompatible
web-ui/.../cline-agent-chat-panel.tsx Strengthened warning message from "may not accept" to "does not support"
web-ui/.../task-create-dialog.tsx Added vision support check: disables Create / Start / Start & Open buttons and shows an orange error banner when images are attached to a non-vision Cline model
src/trpc/runtime-api.ts Server-side safety net: validates model vision support before startTaskSession and before sendTaskChatMessage (home agent path) — returns an error if the model lacks vision support

Design decisions

  • Only blocks when capability is explicitly false: If supportsVision is undefined (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.
  • Only applies to the Cline agent: Non-Cline agents (Claude Code, Codex, Gemini, etc.) convert images to file path references in the prompt text, so the vision check is not applicable.
  • Frontend + backend: The UI blocks are the primary defense. The backend validation in runtime-api.ts catches 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

Ref Status Relationship
#307 open Fixes — screenshots unrecognised by non-vision models
#413 closed Closes — attached files not seen
#395 open Mitigates — only blocks on explicit false, safe for undefined capabilities
PR #35 merged Builds on — added the initial warning, this PR adds blocking
#156 closed Relates — original feature request for image attachments

Testing

What was tested

  • Manual code review and logic verification of all 4 files
  • Node.js syntax check on runtime-api.ts (passed)
  • Full diff review for correctness

What was NOT tested

  • npm run check (lint + typecheck + tests) — npm install
  • Manual browser testing — npm run web:dev (did not start due to missing web-ui/node_modules)
  • npm run build

How to test manually

Prerequisites: npm install (root) + npm install (web-ui) must complete.

Scenario 1 — Chat composer blocking:

  1. Start Kanban, open a project, create a task with the Cline agent, start it
  2. In the chat composer model picker, select a model that does NOT support vision
  3. Paste a screenshot (Ctrl+V / Cmd+V)
  4. Expected: Orange error banner appears, send button is disabled, Enter does nothing
  5. Remove images → send button re-enables
  6. Switch to a vision-capable model → warning disappears, sending works with images

Scenario 2 — Task creation blocking:

  1. Open "New task" dialog, expand "Override Agent Settings", select Cline
  2. Select a non-vision model, paste a screenshot
  3. Expected: Orange error banner above buttons, Create/Start disabled
  4. Remove images → buttons re-enable

Scenario 3 — Non-Cline agents unaffected:

  1. New task with images, agent is Claude Code/Codex/etc (not Cline)
  2. Expected: No blocking — check only applies to Cline agent

Scenario 4 — Unknown capability (safe):

  1. Use a custom provider where supportsVision is undefined
  2. Paste images → Expected: No blocking (only blocks on explicit false)

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-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 7, 2026

Greptile Summary

This 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 supportsVision === false. A FUNDING.yml file that is completely unrelated to the feature is also included.

  • Frontend blocking (cline-chat-composer.tsx, task-create-dialog.tsx): canSubmit now requires !attachmentWarningMessage, and the task dialog disables Create/Start buttons with an orange banner when images are attached to a non-vision Cline model.
  • Backend safety net (runtime-api.ts): Two new guards return a clear error when images are present and the resolved model lacks vision support; network failures during model lookup are swallowed so they never block legitimate requests.
  • Unrelated change (.github/FUNDING.yml): Adds the PR author's personal GitHub account as a repository funding recipient — this should be reviewed and removed by maintainers.

Confidence Score: 3/5

Not 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.

.github/FUNDING.yml must be removed. web-ui/src/components/task-create-dialog.tsx needs the effectiveAgentIdForImages logic corrected to handle the empty-string agentId case.

Important Files Changed

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
Loading
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

Comment thread .github/FUNDING.yml Outdated
Comment thread web-ui/src/components/task-create-dialog.tsx Outdated
Comment thread src/trpc/runtime-api.ts Outdated
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cline Kanban: Kanban failed to recognise the attached screenshot. Cline Kanban doesn't see attached files

1 participant