Skip to content

fix: parse kimi tagged tool calls#60051

Merged
obviyus merged 3 commits into
mainfrom
fix/kimi-tool-call-markup
Apr 3, 2026
Merged

fix: parse kimi tagged tool calls#60051
obviyus merged 3 commits into
mainfrom
fix/kimi-tool-call-markup

Conversation

@obviyus

@obviyus obviyus commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • parse Kimi tagged tool-call text into structured tool calls on the provider stream path
  • cover sync and async stream functions in regression tests
  • verified with a real kimi-coding local-agent run that now dispatches read instead of echoing raw tool markup

@greptile-apps

greptile-apps Bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes Kimi's tagged tool-call markup not being dispatched as structured tool calls by adding a stream-wrapper layer (extensions/kimi-coding/stream.ts) that intercepts the provider stream, detects <|tool_calls_section_begin|>...<|tool_calls_section_end|> blocks in text content items, and rewrites them into toolCall content blocks with the correct stopReason: "toolUse". The wrapper is wired in via the public wrapStreamFn plugin-SDK hook and is exercised by three new Vitest cases covering sync streams, async streams, and normal-text pass-through.

Key observations:

  • The parser is correct and well-structured; it handles whitespace around tags, strips :N call-counter suffixes from tool names, validates JSON arguments, and falls back to a no-op (return null) on any malformed input.
  • Mutations to stream.result and stream[Symbol.asyncIterator] are applied cleanly: original bindings are captured before replacement, preventing infinite recursion or accidental prototype pollution.
  • The strict startsWith/endsWith guard means the parser silently no-ops if tool-call markup is embedded inside a longer text block with any preamble/suffix. A clarifying comment explaining that this is intentional (Kimi always emits tool-call markup as the full content of a text block) would help future readers.
  • The test suite lacks a case for multiple tool calls in one section, which would exercise the inner while loop and cursor-advance logic in parseKimiTaggedToolCalls.

Confidence Score: 4/5

Safe to merge; the change is scoped to the Kimi provider plugin with no impact on core or other providers.

The implementation is logically correct, cleanly uses the public wrapStreamFn seam, and has three passing tests. The only gaps are a missing test for multiple concurrent tool calls and an undocumented assumption that Kimi always emits tool-call markup as the sole content of a text block — both are P2 style concerns that don't affect correctness for the verified real-world usage.

extensions/kimi-coding/stream.ts — the strict startsWith/endsWith guard warrants a clarifying comment.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/kimi-coding/stream.ts
Line: 21-25

Comment:
**Silent pass-through when tool markup is mixed with preamble text**

`parseKimiTaggedToolCalls` requires the entire (trimmed) text block to begin with `<|tool_calls_section_begin|>` and end with `<|tool_calls_section_end|>`. If Kimi ever emits a response where the tool-call section is preceded by a short preamble (e.g. `"Alright, let me do that: <|tool_calls_section_begin|>...<|tool_calls_section_end|>"`), the text block won't match the strict start-check, `parseKimiTaggedToolCalls` returns `null`, and the raw markup is silently passed through as plain text — no tool call will fire.

If this strict match is intentional (Kimi always emits the section tags as the sole content of a text block), a brief comment documenting that assumption would make the invariant explicit and help future maintainers understand why a substring search isn't used instead.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/kimi-coding/stream.test.ts
Line: 29-114

Comment:
**Missing test for multiple tool calls in a single section**

The parser's inner `while` loop is designed to handle multiple `<|tool_call_begin|>...<|tool_call_end|>` blocks within one `<|tool_calls_section_begin|>...<|tool_calls_section_end|>` section, but no test exercises this path. A model response with two parallel tool calls (e.g. `read` + `write`) would exercise the cursor-advance logic on line 82 and the multi-push on line 117. Adding a case here would give confidence that the counter-suffix stripping and `id` uniqueness work correctly across multiple calls.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: parse kimi tagged tool calls" | Re-trigger Greptile

Comment thread extensions/kimi-coding/stream.ts
Comment thread extensions/kimi-coding/stream.test.ts
@obviyus
obviyus force-pushed the fix/kimi-tool-call-markup branch from c7452d0 to 5516d5c Compare April 3, 2026 04:06
@obviyus
obviyus merged commit d5ea5f2 into main Apr 3, 2026
9 checks passed
@obviyus
obviyus deleted the fix/kimi-tool-call-markup branch April 3, 2026 04:09
@obviyus

obviyus commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Landed on main.

ngutman pushed a commit that referenced this pull request Apr 3, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (#60051)

* fix: parse kimi tagged tool calls (#60051)
steipete pushed a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
* fix: parse kimi tagged tool calls

* fix: parse kimi tagged tool calls (openclaw#60051)

* fix: parse kimi tagged tool calls (openclaw#60051)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant