diff --git a/.changeset/quiet-pandas-strip-media.md b/.changeset/quiet-pandas-strip-media.md new file mode 100644 index 0000000000..f83d555402 --- /dev/null +++ b/.changeset/quiet-pandas-strip-media.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix context compaction for text-only models by retrying rejected image content without media. diff --git a/packages/agent-core-v2/src/kosong/contract/errors.ts b/packages/agent-core-v2/src/kosong/contract/errors.ts index bea23797a8..4c66ca46d6 100644 --- a/packages/agent-core-v2/src/kosong/contract/errors.ts +++ b/packages/agent-core-v2/src/kosong/contract/errors.ts @@ -229,6 +229,7 @@ const IMAGE_FORMAT_PROVIDER_MESSAGE_PATTERNS = [ const IMAGE_FORMAT_STATUS_MESSAGE_PATTERNS = [ /unsupported image (?:url|format|type)/, + /unknown variant [`'"]?image_url[`'"]?/, /does not represent a valid image/, /could not (?:process|decode) (?:the |input )?image/, /unable to process (?:the |input )?image/, diff --git a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts index f32a9c1959..d87acd885c 100644 --- a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts +++ b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts @@ -649,7 +649,7 @@ describe('FullCompaction', () => { ); if (hasMedia) { sawMedia = true; - throw new APIStatusError(400, 'unsupported image format: image/avif'); + throw new APIStatusError(400, 'unknown variant image_url, expected text'); } sawStrippedResend = true; return textResult('Recovered compacted summary.'); diff --git a/packages/agent-core-v2/test/kosong/contract/errors.test.ts b/packages/agent-core-v2/test/kosong/contract/errors.test.ts index a6e9537f5a..9ddd94009d 100644 --- a/packages/agent-core-v2/test/kosong/contract/errors.test.ts +++ b/packages/agent-core-v2/test/kosong/contract/errors.test.ts @@ -22,6 +22,7 @@ import { classifyApiError, createAbortError, isAbortError, + isImageFormatError, isRetryableGenerateError, normalizeAPIStatusError, throwIfAbortError, @@ -131,6 +132,17 @@ describe('isRetryableGenerateError', () => { }); }); +describe('isImageFormatError', () => { + it('recognizes providers that reject the image_url content variant', () => { + const error = new APIStatusError( + 400, + 'messages[124]: unknown variant image_url, expected text at line 1 column 811568', + ); + + expect(isImageFormatError(error)).toBe(true); + }); +}); + describe('classifyApiError', () => { it('classifies typed errors and carries the status code', () => { expect(classifyApiError(new APIContextOverflowError(400, 'context length exceeded'))).toEqual({