Skip to content

fix(issue-39839): handle kimi anthropic-messages tool-call extra params#39854

Merged
steipete merged 1 commit intoopenclaw:mainfrom
GeekCheyun:fix/kimi-tool-calls-39839
Mar 8, 2026
Merged

fix(issue-39839): handle kimi anthropic-messages tool-call extra params#39854
steipete merged 1 commit intoopenclaw:mainfrom
GeekCheyun:fix/kimi-tool-calls-39839

Conversation

@GeekCheyun
Copy link
Copy Markdown
Contributor

Summary

  • harden extra params parsing for pi embedded runner tool calls under anthropic-messages
  • add focused regression tests for kimi-k2.5 style payloads

Validation

  • targeted unit tests for parser scenarios

Closes #39839

@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: XS labels Mar 8, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR hardens normalizeKimiCodingToolChoice in extra-params.ts to correctly convert Anthropic-style tool_choice objects ({ type: "auto" }, { type: "none" }, { type: "required" }) into their OpenAI/Kimi string equivalents before sending them to the Kimi Coding anthropic-messages endpoint. Without this fix, those objects were passed through unchanged, causing the Kimi API to reject or mishandle the request.

  • The implementation changes are minimal, correct, and well-scoped — the three new if branches slot in cleanly before the pre-existing "any" and "tool" cases.
  • The new regression test covers the "auto" mapping but leaves the "none" and "required" branches untested. All three paths are exercised by the same wrapper code, so extending the test to cover all three cases would fully pin the new behaviour.

Confidence Score: 4/5

  • Safe to merge — the logic change is correct and well-contained; only minor test coverage gaps exist.
  • The three new branches in normalizeKimiCodingToolChoice are straightforwardly correct and do not interact with any other code paths. The sole concern is that the accompanying test only exercises the "auto" normalisation while the "none" and "required" paths go uncovered, leaving a small regression risk for those cases.
  • No files require special attention for correctness; src/agents/pi-embedded-runner-extraparams.test.ts could benefit from broader coverage of the new normalization branches.

Last reviewed commit: 98ddae9

Comment on lines +806 to +838
it("normalizes anthropic tool_choice modes for kimi-coding endpoints", () => {
const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = {
tools: [
{
name: "read",
description: "Read file",
input_schema: { type: "object", properties: {} },
},
],
tool_choice: { type: "auto" },
};
options?.onPayload?.(payload);
payloads.push(payload);
return {} as ReturnType<StreamFn>;
};
const agent = { streamFn: baseStreamFn };

applyExtraParamsToAgent(agent, undefined, "kimi-coding", "k2p5", undefined, "low");

const model = {
api: "anthropic-messages",
provider: "kimi-coding",
id: "k2p5",
baseUrl: "https://api.kimi.com/coding/",
} as Model<"anthropic-messages">;
const context: Context = { messages: [] };
void agent.streamFn?.(model, context, {});

expect(payloads).toHaveLength(1);
expect(payloads[0]?.tool_choice).toBe("auto");
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing coverage for none and required normalizations

The new test only exercises the { type: "auto" }"auto" path, but the PR also adds { type: "none" }"none" and { type: "required" }"required" branches in normalizeKimiCodingToolChoice. Neither of those new branches is covered by a test, which means a future regression could go undetected.

Consider extending this test (or adding a parameterized table) to cover all three new cases — "none" and "required" alongside "auto" — so the behaviour is pinned:

it.each([
  ["auto", "auto"],
  ["none", "none"],
  ["required", "required"],
])("normalizes tool_choice {type: %s} to string %s for kimi-coding", (inputType, expected) => {
  const payloads: Record<string, unknown>[] = [];
  const baseStreamFn: StreamFn = (_model, _context, options) => {
    const payload: Record<string, unknown> = {
      tools: [{ name: "read", description: "Read file", input_schema: { type: "object", properties: {} } }],
      tool_choice: { type: inputType },
    };
    options?.onPayload?.(payload);
    payloads.push(payload);
    return {} as ReturnType<StreamFn>;
  };
  const agent = { streamFn: baseStreamFn };
  applyExtraParamsToAgent(agent, undefined, "kimi-coding", "k2p5", undefined, "low");
  const model = { api: "anthropic-messages", provider: "kimi-coding", id: "k2p5", baseUrl: "https://api.kimi.com/coding/" } as Model<"anthropic-messages">;
  void agent.streamFn?.(model, { messages: [] } as Context, {});
  expect(payloads[0]?.tool_choice).toBe(expected);
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner-extraparams.test.ts
Line: 806-838

Comment:
**Missing coverage for `none` and `required` normalizations**

The new test only exercises the `{ type: "auto" }``"auto"` path, but the PR also adds `{ type: "none" }``"none"` and `{ type: "required" }``"required"` branches in `normalizeKimiCodingToolChoice`. Neither of those new branches is covered by a test, which means a future regression could go undetected.

Consider extending this test (or adding a parameterized table) to cover all three new cases — `"none"` and `"required"` alongside `"auto"` — so the behaviour is pinned:

```ts
it.each([
  ["auto", "auto"],
  ["none", "none"],
  ["required", "required"],
])("normalizes tool_choice {type: %s} to string %s for kimi-coding", (inputType, expected) => {
  const payloads: Record<string, unknown>[] = [];
  const baseStreamFn: StreamFn = (_model, _context, options) => {
    const payload: Record<string, unknown> = {
      tools: [{ name: "read", description: "Read file", input_schema: { type: "object", properties: {} } }],
      tool_choice: { type: inputType },
    };
    options?.onPayload?.(payload);
    payloads.push(payload);
    return {} as ReturnType<StreamFn>;
  };
  const agent = { streamFn: baseStreamFn };
  applyExtraParamsToAgent(agent, undefined, "kimi-coding", "k2p5", undefined, "low");
  const model = { api: "anthropic-messages", provider: "kimi-coding", id: "k2p5", baseUrl: "https://api.kimi.com/coding/" } as Model<"anthropic-messages">;
  void agent.streamFn?.(model, { messages: [] } as Context, {});
  expect(payloads[0]?.tool_choice).toBe(expected);
});
```

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

@GeekCheyun
Copy link
Copy Markdown
Contributor Author

收尾同步:该 PR 当前状态 clean,历史 CI 全绿,可直接 review/merge。若需要我补充任何回归用例我会立即跟进。

@steipete steipete merged commit 76e4b82 into openclaw:main Mar 8, 2026
31 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented Mar 8, 2026

Landed via temp rebase onto main.

  • Gate: pnpm check && pnpm build && pnpm test
  • Land commit: c7bca64
  • Merge commit: 76e4b82

Thanks @GeekCheyun!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Tool calls broken with kimi-k2.5 (anthropic-messages API) after upgrade to 2026.3.7

2 participants