feat: add vision support validation for image processing

- Introduced a new method in ProviderFactory to check if a model supports vision/image input.
- Updated AgentService and AutoModeService to validate vision support before processing images, throwing an error if the model does not support it.
- Enhanced error messages to guide users on switching models or removing images if necessary.

These changes improve the robustness of image processing by ensuring compatibility with the selected models.
This commit is contained in:
DhanushSantosh
2026-01-07 20:12:39 +05:30
parent 92195340c6
commit fe305bbc81
4 changed files with 51 additions and 2 deletions

View File

@@ -156,6 +156,32 @@ export class ProviderFactory {
static getRegisteredProviderNames(): string[] {
return Array.from(providerRegistry.keys());
}
/**
* Check if a specific model supports vision/image input
*
* @param modelId Model identifier
* @returns Whether the model supports vision (defaults to true if model not found)
*/
static modelSupportsVision(modelId: string): boolean {
const provider = this.getProviderForModel(modelId);
const models = provider.getAvailableModels();
// Find the model in the available models list
for (const model of models) {
if (
model.id === modelId ||
model.modelString === modelId ||
model.id.endsWith(`-${modelId}`) ||
model.modelString === modelId.replace(/^(claude|cursor|codex)-/, '')
) {
return model.supportsVision ?? true;
}
}
// Default to true (Claude SDK supports vision by default)
return true;
}
}
// =============================================================================

View File

@@ -174,6 +174,18 @@ export class AgentService {
session.thinkingLevel = thinkingLevel;
}
// Validate vision support before processing images
const effectiveModel = model || session.model;
if (imagePaths && imagePaths.length > 0 && effectiveModel) {
const supportsVision = ProviderFactory.modelSupportsVision(effectiveModel);
if (!supportsVision) {
throw new Error(
`This model (${effectiveModel}) does not support image input. ` +
`Please switch to a model that supports vision, or remove the images and try again.`
);
}
}
// Read images and convert to base64
const images: Message['images'] = [];
if (imagePaths && imagePaths.length > 0) {

View File

@@ -1989,6 +1989,18 @@ This helps parse your summary correctly in the output logs.`;
const planningMode = options?.planningMode || 'skip';
const previousContent = options?.previousContent;
// Validate vision support before processing images
const effectiveModel = model || 'claude-sonnet-4-20250514';
if (imagePaths && imagePaths.length > 0) {
const supportsVision = ProviderFactory.modelSupportsVision(effectiveModel);
if (!supportsVision) {
throw new Error(
`This model (${effectiveModel}) does not support image input. ` +
`Please switch to a model that supports vision (like Claude models), or remove the images and try again.`
);
}
}
// Check if this planning mode can generate a spec/plan that needs approval
// - spec and full always generate specs
// - lite only generates approval-ready content when requirePlanApproval is true

View File

@@ -179,8 +179,7 @@ describe('validation-storage.ts', () => {
});
it('should return false for validation exactly at 24 hours', () => {
const exactDate = new Date();
exactDate.setHours(exactDate.getHours() - 24);
const exactDate = new Date(Date.now() - 24 * 60 * 60 * 1000 + 100);
const validation = createMockValidation({
validatedAt: exactDate.toISOString(),