Skip to content

fix(kimi): tag content parts so serde emits the type discriminant - #99

Merged
raine merged 1 commit into
raine:mainfrom
flaviomartil:fix/kimi-content-part-type-discriminant
Aug 2, 2026
Merged

fix(kimi): tag content parts so serde emits the type discriminant#99
raine merged 1 commit into
raine:mainfrom
flaviomartil:fix/kimi-content-part-type-discriminant

Conversation

@flaviomartil

@flaviomartil flaviomartil commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Addresses #98.

Problem

KimiUserContentPart and KimiToolResultPart are declared #[serde(untagged)], so they serialize without a discriminant:

{"text": "..."}
{"image_url": {"url": "..."}}

Kimi expects the OpenAI multimodal shape and rejects the payload:

the message at position 0 with role 'user' contains an invalid part type:
the message at position 2 with role 'tool' contains an invalid part type:

The value after the colon is empty because the discriminant is missing.

The practical impact is that subagents do not work through the proxy. Claude Code's Task tool returns a multi-block tool_result, which always takes this path. Single-output tools such as Bash and Read are unaffected, because tool_result_content collapses a lone text part back into a plain string before serializing.

Change

Tag both enums:

#[serde(tag = "type", rename_all = "snake_case")]

Output becomes {"type":"text","text":"..."} and {"type":"image_url","image_url":{...}}.

Tests

Two regression tests added, one per enum, asserting the discriminant is present:

  • user_content_parts_carry_a_type_discriminant
  • tool_result_parts_carry_a_type_discriminant

The existing translate_tool_result_with_image, translate_tool_result_with_unsupported_blocks and translate_user_text_and_image_collapse_correctly assert only on the text and image_url keys, so they are unaffected.

Verification

Built and tested against a live Kimi account on macOS arm64. Before the change, a multimodal user message and any subagent invocation both returned invalid part type. After the change, both succeed.

Copilot AI review requested due to automatic review settings August 2, 2026 18:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Kimi request translation so multimodal user content and multi-part tool results serialize with an explicit "type" discriminant, matching the OpenAI-style content-part shape that Kimi expects (and preventing invalid part type: errors that break subagents and multimodal messages).

Changes:

  • Switch KimiUserContentPart and KimiToolResultPart from #[serde(untagged)] to #[serde(tag = "type", rename_all = "snake_case")] so serialized parts include "type": "text" / "type": "image_url".
  • Add regression tests verifying "type" is present for both user content parts and tool result parts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@raine
raine merged commit d2375cf into raine:main Aug 2, 2026
@raine

raine commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Thanks!

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.

3 participants