fix(moonshot): preserve native Kimi tool_call IDs in openai-completions replay

This commit is contained in:
dulingxiao
2026-04-22 14:34:18 +08:00
committed by Peter Steinberger
parent 23a448986f
commit c4dea58712
7 changed files with 73 additions and 17 deletions

View File

@@ -5,22 +5,22 @@ import { createCapturedThinkingConfigStream } from "../../test/helpers/plugins/s
import plugin from "./index.js";
describe("moonshot provider plugin", () => {
it("owns replay policy for OpenAI-compatible Moonshot transports", async () => {
it("owns replay policy for OpenAI-compatible Moonshot transports without mangling native Kimi tool_call IDs", async () => {
const provider = await registerSingleProviderPlugin(plugin);
expect(
provider.buildReplayPolicy?.({
provider: "moonshot",
modelApi: "openai-completions",
modelId: "kimi-k2.6",
} as never),
).toMatchObject({
sanitizeToolCallIds: true,
toolCallIdMode: "strict",
const policy = provider.buildReplayPolicy?.({
provider: "moonshot",
modelApi: "openai-completions",
modelId: "kimi-k2.6",
} as never);
expect(policy).toMatchObject({
applyAssistantFirstOrderingFix: true,
validateGeminiTurns: true,
validateAnthropicTurns: true,
});
expect(policy).not.toHaveProperty("sanitizeToolCallIds");
expect(policy).not.toHaveProperty("toolCallIdMode");
});
it("wires moonshot-thinking stream hooks", async () => {

View File

@@ -1,5 +1,5 @@
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
import { OPENAI_COMPATIBLE_REPLAY_HOOKS } from "openclaw/plugin-sdk/provider-model-shared";
import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared";
import { MOONSHOT_THINKING_STREAM_HOOKS } from "openclaw/plugin-sdk/provider-stream-family";
import { applyMoonshotNativeStreamingUsageCompat } from "./api.js";
import { moonshotMediaUnderstandingProvider } from "./media-understanding-provider.js";
@@ -57,7 +57,13 @@ export default defineSingleProviderPluginEntry({
},
applyNativeStreamingUsageCompat: ({ providerConfig }) =>
applyMoonshotNativeStreamingUsageCompat(providerConfig),
...OPENAI_COMPATIBLE_REPLAY_HOOKS,
// Kimi K2+ returns native tool_call IDs shaped like `functions.<name>:<index>`.
// Sanitizing them to alphanumeric-only breaks Kimi's serving-layer matching in
// multi-turn replay. See openclaw/openclaw#62319.
...buildProviderReplayFamilyHooks({
family: "openai-compatible",
sanitizeToolCallIds: false,
}),
...MOONSHOT_THINKING_STREAM_HOOKS,
resolveThinkingProfile: () => ({
levels: [