mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
fix: broaden OpenAI image schema recovery
OpenAI-compatible text-only providers do not all report the same schema error when they reject image_url content parts. Match the broader protocol-level shape instead of one DeepSeek-style deserialization sentence, while still avoiding preflight image stripping for vision-capable endpoints. Constraint: OpenAI-compatible upstream validation wording varies by provider and framework. Rejected: Treat every image_url error as unsupported media | malformed image URLs should not be conflated unless the message says the part is disallowed or text-only. Confidence: high Scope-risk: narrow Directive: Keep this classifier focused on image_url part rejection; provider capability modeling is the cleaner long-term preflight path. Tested: bun test src/services/api/errors.test.ts Tested: bun test tests/mediaRecoveryAndEstimation.test.ts Tested: bun run check:server Not-tested: Live provider matrix across every OpenAI-compatible endpoint.
This commit is contained in:
parent
8366e259ba
commit
d1b5174fb8
@ -7,21 +7,18 @@ import {
|
||||
|
||||
describe('image unsupported API errors', () => {
|
||||
test('detects provider-specific text-only model image rejections', () => {
|
||||
expect(
|
||||
isUnsupportedImageInputErrorMessage(
|
||||
'This model does not support image blocks',
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
isUnsupportedImageInputErrorMessage(
|
||||
'unsupported modality: image input is not available',
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
isUnsupportedImageInputErrorMessage(
|
||||
'Failed to deserialize the JSON body into the target type: messages[1]: unknown variant `image_url`, expected `text` at line 1 column 394097',
|
||||
),
|
||||
).toBe(true)
|
||||
const unsupportedImageErrors = [
|
||||
'This model does not support image blocks',
|
||||
'unsupported modality: image input is not available',
|
||||
'Failed to deserialize the JSON body into the target type: messages[1]: unknown variant `image_url`, expected `text` at line 1 column 394097',
|
||||
"Invalid value for 'messages[0].content[1].type': 'image_url' is not one of ['text']",
|
||||
"messages.0.content.1.type: Input should be 'text'; received 'image_url'",
|
||||
'image_url content parts are not allowed for this model',
|
||||
]
|
||||
|
||||
for (const message of unsupportedImageErrors) {
|
||||
expect(isUnsupportedImageInputErrorMessage(message)).toBe(true)
|
||||
}
|
||||
expect(isUnsupportedImageInputErrorMessage('image exceeds maximum')).toBe(false)
|
||||
})
|
||||
|
||||
|
||||
@ -430,7 +430,7 @@ export function extractUnknownErrorFormat(value: unknown): string | undefined {
|
||||
export function isUnsupportedImageInputErrorMessage(message: string): boolean {
|
||||
const raw = message.toLowerCase()
|
||||
if (!raw.includes('image')) return false
|
||||
if (raw.includes('image_url') && raw.includes('expected') && raw.includes('text')) {
|
||||
if (isOpenAIImageUrlTextOnlySchemaError(raw)) {
|
||||
return true
|
||||
}
|
||||
return (
|
||||
@ -444,6 +444,31 @@ export function isUnsupportedImageInputErrorMessage(message: string): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
function isOpenAIImageUrlTextOnlySchemaError(raw: string): boolean {
|
||||
if (!raw.includes('image_url')) return false
|
||||
if (
|
||||
raw.includes('not allowed') ||
|
||||
raw.includes('not permitted') ||
|
||||
raw.includes('disallowed') ||
|
||||
raw.includes('forbidden')
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (!raw.includes('text')) return false
|
||||
return (
|
||||
raw.includes('expected') ||
|
||||
raw.includes('input should be') ||
|
||||
raw.includes('not one of') ||
|
||||
raw.includes('permitted') ||
|
||||
raw.includes('received') ||
|
||||
raw.includes('unknown variant') ||
|
||||
raw.includes('invalid value') ||
|
||||
raw.includes('invalid type') ||
|
||||
raw.includes('valid enumeration') ||
|
||||
raw.includes('only text')
|
||||
)
|
||||
}
|
||||
|
||||
export function getAssistantMessageFromError(
|
||||
error: unknown,
|
||||
model: string,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user