MoonshotAI / MoonshotAI/kimi-code
[kosong] OpenAI-compatible stream parser journals an empty think part per chunk carrying reasoning_content: ""
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
What version of Kimi Code is running?
0.31.1
Which open platform/subscription were you using?
Third-party OpenAI-compatible provider (custom base_url), not a Kimi subscription.
Which model were you using?
qwen3.8-max-preview — again provider-agnostic; depends on the endpoint's streaming habit, not the model.
What platform is your computer?
Linux 7.0.0-28-generic x86_64 x86_64
What issue are you seeing?
Some OpenAI-compatible endpoints (e.g. Alibaba DashScope compatible-mode) keep the reasoning_content key present with an empty string in stream chunks after the thinking phase ends. kosong's stream parser yields a think part for any string value — including '':
packages/kosong/src/providers/reasoning-key.ts:44—extractReasoningaccepts any string (typeof value === 'string'), empty or not.packages/kosong/src/providers/openai-legacy.ts:445—if (reasoning !== undefined) yield { type: 'think', think: reasoning }(same at :391 for the non-stream path).
Result: thousands of no-op content.part records get journaled into wire.jsonl. In one real session: 3,041 empty think parts vs 44 non-empty ones. This bloats session files and transcripts, and amplifies per-part rendering issues in the web UI.
What steps can reproduce the bug?
- Configure an OpenAI-compatible endpoint that keeps
reasoning_content: ""in its stream chunks (e.g. DashScope compatible-mode). - Run any session with a few model turns.
- Inspect the session's
wire.jsonl: most think-typecontent.partrecords are empty strings.
What is the expected behavior?
Empty reasoning strings should not produce think parts — e.g. if (reasoning) instead of if (reasoning !== undefined) at openai-legacy.ts:391/:445 (and the equivalent spots in other providers).
Additional information
Harmless for model requests (the context projector only strips blank text parts; empty think parts never affect the prompt sent to the model), so this is a journal-size/noise issue rather than a correctness one — but on chunk-heavy endpoints it inflates wire.jsonl by thousands of records per session.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/kosong/src/providers/reasoning-key.ts:44 and packages/kosong/src/providers/openai-legacy.ts at lines 391 and 445, then inspect the equivalent spots in other providers. Reproduce the stream behavior with an endpoint that sends reasoning_content as an empty string and verify that empty values no longer create think parts in wire.jsonl while non-empty reasoning remains recorded.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100