Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/claude/pi-model-resolution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,15 @@ export function buildSyntheticPiModel(
provider,
baseUrl: baseUrl || '',
reasoning: autoReasoning,
input: ['text', 'image'],
// Default unknown/synthetic models to text-only input. We cannot know whether
// an arbitrary model supports image input, and falsely claiming vision support
// causes hard request failures rather than gracefully dropping images — e.g.
// Ollama returns HTTP 400 "this model does not support image input" for a
// text-only model like deepseek-v4-pro, which surfaces to the user as an
// opaque "invalid message format" error. Vision-capable models resolved from
// the pi-ai registry keep their real input modalities; only synthetic
// fallbacks are affected here.
input: ['text'],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: contextWindow || knownSpecs?.contextWindow || 128000,
maxTokens: maxTokens || knownSpecs?.maxTokens || 16384,
Expand Down
29 changes: 29 additions & 0 deletions tests/synthetic-model-input.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, it, expect } from 'vitest';
import { buildSyntheticPiModel } from '../src/main/claude/pi-model-resolution';

/**
* Regression guard for the text-only-model image bug.
*
* Synthetic models (built for ids not in the pi-ai registry) must NOT claim
* image input. Falsely advertising vision support means image content — e.g.
* screenshots from the GUI/computer-use tools — is sent to text-only endpoints,
* which hard-fail instead of gracefully dropping the images. For example Ollama
* returns HTTP 400 "this model does not support image input" for a text-only
* model like deepseek-v4-pro, which the app surfaces as an opaque
* "invalid message format" error.
*/
describe('buildSyntheticPiModel input modalities', () => {
it('defaults an unknown synthetic model to text-only input', () => {
const m = buildSyntheticPiModel('deepseek-v4-pro', 'openai', 'openai', 'https://ollama.com/v1');
expect(m.input).toEqual(['text']);
expect(m.input).not.toContain('image');
});

it('still resolves other core model fields normally', () => {
const m = buildSyntheticPiModel('some-custom-model', 'openai', 'openai', 'https://example.com/v1');
expect(m.id).toBe('some-custom-model');
expect(m.api).toBeTruthy();
expect(m.contextWindow).toBeGreaterThan(0);
expect(m.maxTokens).toBeGreaterThan(0);
});
});
Loading