fix(server): a reply gets the context its prompt leaves instead of a 400
Merged
DA
2d ago+45+45+01234567890123456789-6-6-0123456789
Clients send their usual output cap whatever the prompt: Claude Code asks for 32000 tokens on every turn. Once prompt + max_tokens passed the context, the server refused the request with a 400. With a 131072-token context and the model cards' 32768 default, a session stopped working at about 99K tokens of prompt, long before the context was full.
What changes
- Direct requests:
max_tokensis trimmed to the context the prompt leaves (fit_reply_to_contextinadmission.h), as llama.cpp does withn_predict. The server logs the trim. - A prompt that fills the context is still refused with a 400.
- Routed requests keep the old rule, so the router can still send the request whole to a model with room for it.
- Thinking budgets follow the trimmed cap.
Measured
Qwen 3.8 27B on an R9700, launched with the model card's 32768 default instead of a fixed 4096:
| Request | Before | After |
|---|---|---|
108,802-token prompt, max_tokens 32000 | 400 | 200, cap trimmed to 22,270 |
reasoning_effort: medium | no thinking under a 4096 cap | 218 reasoning tokens |
Messages API, thinking.budget_tokens 2048 | no thinking under a 4096 cap | thinking block, then the answer |
The last two rows depend on the launcher dropping its fixed 4096 cap. This change is what makes dropping it safe for long prompts.
Tests
test_admission: a new case covers the trim and the refusal of a prompt that fills the context. test_server_unit passes on a HIP build.
🤖 Generated with Claude Code