mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-18 05:05:28 +00:00
* fix(agent-core): recover sessions bricked by orphan tool results A stray `tool` message with no preceding assistant `tool_calls` permanently bricked a session on OpenAI-compatible providers: every turn re-sent the same malformed history and got a 400, and switching model/provider did not help. Two independent gaps caused this: - kosong did not recognize the OpenAI / DeepSeek / vLLM / Qwen phrasings of the tool-exchange structural 400 (`role 'tool' must be a response to a preceding message with 'tool_calls'` and the mirror `assistant message with 'tool_calls' must be followed by tool messages`), so the post-400 strict-resend fallback that drops the orphan never fired. - The legacy-restore compaction path kept a verbatim tail `history.slice(compactedCount)`; when the cut landed inside a tool exchange the tail began with an orphan tool result whose assistant was summarized away. The normal projection does not repair a leading orphan, so the malformed history was baked in and re-sent every turn. Recognize the additional phrasings so the strict resend un-bricks any session, and trim leading tool results from the legacy-restore tail so the orphan is never persisted in the first place. * fix(agent-core): drop orphan tool results at the projection boundary Rework the legacy-restore half of the fix based on review feedback: mutating `_history` at restore time desyncs every consumer that models the history from the wire records — the transcript reducer's fold length would overcount and make MessageService skip unflushed live-tail messages. Keep the restored history faithful to the wire records instead, and drop a `tool` result whose call is nowhere in the history at the projection boundary, on every request-building projection: the normal wire (`messages`), the post-400 strict resend (`strictMessages`), and the compaction summarizer. An orphan is wire-invalid on strict providers and useless to the model either way, so it never reaches a provider — no longer relying on recognizing the provider's 400 phrasing to recover. Fragment projections (e.g. token-estimating a history slice) leave results untouched, since a matching call may legitimately sit outside the slice. |
||
|---|---|---|
| .. | ||
| fixtures | ||
| abort.e2e.test.ts | ||
| api-shape.e2e.test.ts | ||
| error-paths.e2e.test.ts | ||
| events.e2e.test.ts | ||
| hooks.e2e.test.ts | ||
| retry.test.ts | ||
| streaming.e2e.test.ts | ||
| tool-args-parse.test.ts | ||
| tool-call.e2e.test.ts | ||
| tool-exchange-fallback.e2e.test.ts | ||
| tool-scheduler.test.ts | ||
| transcript.e2e.test.ts | ||
| turn-lifecycle.e2e.test.ts | ||