diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index e83c3ae4a..067f085f3 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -612,6 +612,8 @@ export async function runEmbeddedAttempt( onAssistantMessageStart: params.onAssistantMessageStart, onAgentEvent: params.onAgentEvent, enforceFinalTag: params.enforceFinalTag, + provider: params.provider, + modelId: params.modelId, }); const { diff --git a/src/agents/pi-embedded-subscribe.handlers.messages.ts b/src/agents/pi-embedded-subscribe.handlers.messages.ts index 1f515e113..ed72a60da 100644 --- a/src/agents/pi-embedded-subscribe.handlers.messages.ts +++ b/src/agents/pi-embedded-subscribe.handlers.messages.ts @@ -165,6 +165,25 @@ export function handleMessageEnd( const assistantMessage = msg as AssistantMessage; promoteThinkingTagsToBlocks(assistantMessage); + // Normalize Moonshot thinking signatures on receipt (not on send) + // Moonshot via OpenRouter returns "reasoning" but expects "reasoning_content" on replay + if ( + ctx.params.provider === "openrouter" && + ctx.params.modelId?.startsWith("moonshotai/kimi-") && + Array.isArray(assistantMessage.content) + ) { + for (const block of assistantMessage.content) { + if ( + block && + typeof block === "object" && + (block as { type?: unknown }).type === "thinking" && + (block as { thinkingSignature?: unknown }).thinkingSignature === "reasoning" + ) { + (block as { thinkingSignature: string }).thinkingSignature = "reasoning_content"; + } + } + } + const rawText = extractAssistantText(assistantMessage); appendRawStream({ ts: Date.now(), diff --git a/src/agents/pi-embedded-subscribe.types.ts b/src/agents/pi-embedded-subscribe.types.ts index 766ff7f18..bcb7bf5bf 100644 --- a/src/agents/pi-embedded-subscribe.types.ts +++ b/src/agents/pi-embedded-subscribe.types.ts @@ -31,6 +31,10 @@ export type SubscribeEmbeddedPiSessionParams = { onAssistantMessageStart?: () => void | Promise; onAgentEvent?: (evt: { stream: string; data: Record }) => void | Promise; enforceFinalTag?: boolean; + /** Provider ID for provider-specific message normalization */ + provider?: string; + /** Model ID for model-specific message normalization */ + modelId?: string; }; export type { BlockReplyChunking } from "./pi-embedded-block-chunker.js";