Reviewed PR details and related session.
UnderstandIdentified API differences between OpenRouter and Vercel.
UnderstandAnalyzed tool call token leakage issue in Vercel session.
UnderstandYou are given one or more GitHub PR URLs: https://github.com/badlogic/pi-mono/pull/987 pull inot a local branch please
For each PR URL, do the following in order:
packages/*/CHANGELOG.md files. Report whether an entry exists. If missing, state that a changelog entry is required before merge and that you will add it if the user decides to merge. Follow the changelog format rules in AGENTS.md. Verify:
### Breaking Changes, ### Added, ### Fixed, etc.)Fixed foo ([#123](https://github.com/badlogic/pi-mono/pull/123) by [@user](https://github.com/user))### Breaking Changes, not just ### FixedOutput format per PR: PR: Changelog:
If no issues are found, say so under Bad and Ugly.
continue
Let me read the relevant source files to understand the full context:
Let me check if there are any documentation updates needed and review the PR comments more carefully:
Now let me pull the PR into a local branch:
PR: https://github.com/badlogic/pi-mono/pull/987
packages/ai/CHANGELOG.md under ### FixedFixed OpenRouter Kimi K2.5 tool-call replay by mapping reasoning fields to reasoning_content and ensuring it is present when reasoning is enabled.Fixed OpenRouter Kimi K2.5 tool-call replay by mapping reasoning fields to \reasoning_content` and ensuring it is present when reasoning is enabled (#987 by @banteg)`reasoning_content specifically, not reasoning or reasoning_textreasoning_content: "" when missing prevents 400 errors without changing behavior for working conversationsreasoningEnabled && isOpenRoutermodel.provider === "openrouter" won't work for Vercel AI Gateway or other proxies that route to Kimi. Checking model slug would be more robust (though this is an enhancement, not blocking)reasoning_details with type: "reasoning.text" but pi-ai only stores reasoning.encrypted type. The PR's empty string fix stops the error but doesn't preserve actual reasoning. This is a valid observation, though the current fix is simpler and sufficient for the error casereasoningEnabled boolean to convertMessages() based on options.reasoningEffortmodel.provider === "openrouter"reasoning, reasoning_text, reasoning_content) to reasoning_content for OpenRouterreasoning_content: "" to assistant tool-call messages when reasoning is enabled, OpenRouter, and the field is missingreasoning_content"npm run check passes (per PR description)The PR is now in local branch fix/kimi-pr-987-work. If you want to merge, I'll need to fix the changelog attribution first.
/Users/badlogic/.pi/agent/sessions/--Users-badlogic-workspaces-pi-mono--/2026-01-29T02-05-25-874Z_bb1f1612-2f68-4d2b-a37e-f97536a9d087.jsonl
any idea if we use @packages/ai/src/providers/openai-completions.ts for vercel? this is a session where the model eventually spits out a thinking trace that includes a tool call
Looking at the session, Vercel AI Gateway with Kimi K2.5 uses anthropic-messages API, not openai-completions:
"api":"anthropic-messages","provider":"vercel-ai-gateway","model":"moonshotai/kimi-k2.5"So the PR fix won't help Vercel because it only modifies openai-completions.ts.
The last message in that session shows the problem: Kimi's internal tool call format leaked into the thinking trace:
<|tool_calls_section_begin|> <|tool_call_begin|> functions.bash:22 <|tool_call_argument_begin|> {"command": "..."} <|tool_call_end|>...This is the model outputting what should be tool calls as raw text inside the thinking block. The stop reason is "stop" (not "toolUse"), so the tool calls were never properly parsed.
Let me check how Vercel models are configured:
So the picture is:
openai-completions API → PR fix applies hereanthropic-messages API → PR fix does NOT applyThe session you shared shows Kimi outputting its internal tool call format (<|tool_calls_section_begin|>) as raw text inside the thinking block instead of proper tool calls. This is a different bug that the PR doesn't address.
Let me check the Anthropic provider to see if there's anything relevant:
The Anthropic provider has proper thinking handling for Claude, but Kimi isn't Claude. When Vercel routes Kimi through anthropic-messages API format, Kimi appears to emit its internal control tokens (<|tool_calls_section_begin|>, <|tool_call_begin|>, etc.) as raw text instead of proper tool calls.
Summary:
openai-completions APIanthropic-messages API for Kimi, and the model outputs its internal tool call format as literal text in thinking tracesThe Vercel issue is likely:
This aligns with badlogic's comment on the PR: "It craps itself on Vercel as well" and "OpenRouter is clown shit, HF is meh, rest is fine". The "rest is fine" probably refers to providers that route directly to Moonshot (like OpenCode Zen), not Vercel.
Should we still merge the PR for the OpenRouter fix, or wait for broader Kimi support to stabilize?
"api":"anthropic-messages","provider":"vercel-ai-gateway","model":"moonshotai/kimi-k2.5"<|tool_calls_section_begin|> <|tool_call_begin|> functions.bash:22 <|tool_call_argument_begin|> {"command": "..."} <|tool_call_end|>...