| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
This PR fixes a Kimi k2.5 session poisoning issue where MCP screenshot tools returning image-only content with empty text caused persistent "Text content is empty" errors that rendered sessions unusable.
Changes:
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file| File | Description |
|---|---|
| packages/opencode/src/provider/transform.ts | Added Kimi k2.5 detection function and empty tool-result normalization at API send-time |
| packages/opencode/src/session/message-v2.ts | Added replay-time healing for empty tool outputs and errors when using Kimi |
| packages/opencode/src/session/prompt.ts | Added MCP normalization helpers for content and output with Kimi-specific fallback logic |
| packages/opencode/src/session/processor.ts | Added circuit breaker tracking identical tool errors with auto-retry limit |
| packages/opencode/src/flag/flag.ts | Added OPENCODE_DEBUG_MCP_PAYLOAD debug flag |
| packages/opencode/test/session/prompt-mcp-normalization.test.ts | Tests for MCP normalization with Figma-like image and resource blob schemas |
| packages/opencode/test/session/message-v2.test.ts | Tests for Kimi tool result normalization during message conversion |
| packages/opencode/test/session/kimi-session-regression.test.ts | Regression test for empty screenshot results followed by valid results |
| packages/opencode/test/provider/transform.test.ts | Tests for Kimi-specific transform logic and non-Kimi guard |
| packages/web/src/content/docs/troubleshooting.mdx | Added troubleshooting section for "Text content is empty" error |
| packages/web/src/content/docs/mcp-servers.mdx | Added documentation about screenshot tool output normalization |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
| const key = [match.tool, JSON.stringify(value.input ?? match.state.input ?? {}), errorText].join("|") | ||
| const count = (toolErrors.get(key) ?? 0) + 1 | ||
| toolErrors.set(key, count) | ||
| if (count >= TOOL_ERROR_REPEAT_THRESHOLD) { | ||
| blocked = true | ||
| await Session.updatePart({ | ||
| id: Identifier.ascending("part"), | ||
| messageID: input.assistantMessage.id, | ||
| sessionID: input.assistantMessage.sessionID, | ||
| type: "text", | ||
| text: "Stopped auto-retrying after 3 identical tool errors in this session. Verify MCP server response and retry.", | ||
| synthetic: true, | ||
| }) | ||
| } |
There was a problem hiding this comment.
The circuit breaker implementation tracks identical tool errors and stops auto-retrying after 3 occurrences, but there are no automated tests to verify this behavior. Consider adding tests to ensure the circuit breaker correctly:
Sorry, something went wrong.
| export function isKimiK25(model: Pick<Provider.Model, "api" | "id">) { | ||
| if (model.api.npm !== "@ai-sdk/openai-compatible") return false | ||
| const id = `${model.id} ${model.api.id}`.toLowerCase() | ||
| return ["kimi-k2.5", "kimi-k2p5", "kimi-k2-5", "k2p5"].some((part) => id.includes(part)) |
There was a problem hiding this comment.
The Kimi K2.5 detection uses substring matching with the pattern "k2p5" which could potentially match non-Kimi models that happen to include this substring. While the additional check for "@ai-sdk/openai-compatible" reduces this risk, consider whether the patterns could be more specific. For example, "k2p5" might match a hypothetical model named "mock2p5" or "pk2p5test". If this is deemed too broad, consider using more anchored patterns or checking the providerID field more strictly.
| return ["kimi-k2.5", "kimi-k2p5", "kimi-k2-5", "k2p5"].some((part) => id.includes(part)) | |
| const kimiPatterns = [ | |
| /\bkimi-k2\.5\b/, | |
| /\bkimi-k2p5\b/, | |
| /\bkimi-k2-5\b/, | |
| /\bk2p5\b/, | |
| ] | |
| return kimiPatterns.some((pattern) => pattern.test(id)) |
Sorry, something went wrong.
|
Closing this pull request because it has had no updates for more than 60 days. If you plan to continue working on it, feel free to reopen or open a new PR. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
What does this PR do?
Fixes a Kimi k2.5 + MCP screenshot regression where image-only tool results could serialize as empty tool text, triggering "Text content is empty" and then repeatedly failing on subsequent turns.
Root cause
Fix approach
Why Kimi was affected
Kimi k2.5 (OpenAI-compatible) is stricter about empty tool text payloads. Other providers/models either tolerate this shape or handle media/tool-result content differently.
Tests added
How did you verify your code works?
Automated:
Manual verification steps (for macOS 26.1 + iTerm2 + Figma Desktop MCP) included in issue workflow:
Release notes
Fixes #14107