MoonshotAI / MoonshotAI/kimi-code
[BUG] Gemini 3+ 工具结果包含图片时,后续请求失败("Requests ending with a model turn are not supported")
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
What version of Kimi Code is running?
0.38.0
Which open platform/subscription were you using?
kimi code
Which model were you using?
gemini-3.7-flash
What platform is your computer?
windows 11
What issue are you seeing?
问题描述
使用 google-genai 协议、gemini-3.7-flash(思考型模型)时,会话在调用工具后(尤其是工具结果包含图片,例如 ReadMediaFile 读取多帧图像),下一个请求会被上游 Gemini API 以 HTTP 400 拒绝:
Requests ending with a model turn are not supported.
该错误对 finishReason 重试无影响,直接终止本轮对话;长会话中只要工具结果带媒体就稳定复现。
原因分析
上游 Gemini 3+ 对 contents 中 functionResponse 的结构有明确规定(官方文档 "Multimodal function responses":媒体部分(图片/PDF 等)必须嵌套在 functionResponse.parts[] 内部,不能在 functionResponse 之后作为兄弟 part 出现)。
当前转换逻辑(messagesToGoogleGenAIContents 中的 toolMessageToFunctionResponseParts)生成的是:
[functionResponse, inlineData, functionResponse, inlineData, ...]
媒体作为 functionResponse 的兄弟 part 紧跟其后。经验证(直接对上游构造请求):
| 结构 | 结果 |
|---|---|
[functionResponse] 纯 functionResponse |
✅ 200 |
[functionResponse, text/media...] |
❌ 400 "Requests ending with a model turn are not supported." |
functionResponse.parts 内嵌媒体 |
✅ 200 |
修复方案
将工具结果中的媒体 part 移入 functionResponse 自身的 parts 数组,即生成:
[{ functionResponse: { name, response, parts: [inlineData/fileData...] } }]
附带问题
部分会话中,并行函数调用只有第一个 functionCall 带 thought_signature,其余调用为 null——如果上游要求每个调用都回传签名,可能还需要在流式解析中补充签名提取逻辑。
What steps can reproduce the bug?
- 配置
google-genaiprovider,模型为gemini-3.7-flash,开启 thinking(参考配置):[providers.google] type = "google-genai" base_url = "https://example.com" api_key = "YOUR_API_KEY" [models."google/gemini-3.7-flash"] provider = "google" model = "gemini-3.7-flash" - 在任意工作目录(非 git 仓库亦可)中给 agent 发送一条要求读取图像的 prompt,例如:"读取
gif_frames/f0_i0.png~f5_i37.png这 6 张图片并描述内容"。 - 模型会并行调用
ReadMediaFile6 次,每次返回[text, image_url(data: URI), text]。 - 工具全部执行成功后,携带图片的工具结果被回传给模型 —— 此时请求 400,错误信息如上,会话终止。
What is the expected behavior?
模型收到工具结果并继续回答。实际:HTTP 400,turnStep= 停留在工具调用后的下一步。
Additional information
No response
Contribution
- I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in the messagesToGoogleGenAIContents conversion, focusing on toolMessageToFunctionResponseParts and how media-bearing tool results are assembled. Reproduce the google-genai request with Gemini 3.7 Flash and image results, then verify that media is nested in functionResponse.parts and the follow-up request no longer returns HTTP 400; the optional thought_signature concern is a separate scope question.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- google-cloud, typescript
- Domain
- api, cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100