fix(coding-agent): size title/commit/speech/classifier budgets for backends that ignore disableReasoning
Sizing `maxTokens` off the static `model.reasoning` catalog flag cannot
distinguish a thinking model catalogued `reasoning: false` (e.g. Qwen3
served locally via llama.cpp, whose bundled jinja chat template defaults
`enable_thinking: true`) from a model that never emits thinking. The
tight non-reasoning budget was consumed by the thinking preamble before
the useful output could be emitted, so every affected call silently
failed with `stopReason: "length"`.
Drop the `model.reasoning` conditional across every affected online call
site and always reserve the reasoning-safe budget. `maxTokens` is a hard
cap, not a target — non-thinking completions still return in the tiny
happy-path budget.
Sites fixed:
- utils/title-generator.ts (30 -> 1024)
- utils/commit-message-generator (60 -> 1024)
- tts/speech-enhancer (512 -> 1536)
- auto-thinking/classifier online path (8 -> 1024); classifyLocal
keeps its separate LOCAL_ANSWER_MAX_TOKENS
- session/unexpected-stop-classifier online path (16 -> 1024);
classifyLocal keeps ANSWER_MAX_TOKENS
Fixes #4355
This commit is contained in:
@@ -16,8 +16,11 @@ const CLASSIFIER_SYSTEM_PROMPT = prompt.render(unexpectedStopClassifierPrompt);
|
||||
*/
|
||||
const ANSWER_MAX_TOKENS = 16;
|
||||
/**
|
||||
* Reasoning backends ignore `disableReasoning` on some providers, so reserve
|
||||
* enough output room for the keyword to still land after unavoidable thinking.
|
||||
* Online classifier budget. Sized to survive backends that ignore
|
||||
* `disableReasoning` (e.g. Qwen3 via llama.cpp catalogued `reasoning: false`
|
||||
* but still emitting thinking): the yes/no keyword needs to land after any
|
||||
* unavoidable thinking preamble. `maxTokens` is a hard cap — non-thinking
|
||||
* completions still return in a single word (issue #4355).
|
||||
*/
|
||||
const REASONING_SAFE_MAX_TOKENS = 1024;
|
||||
|
||||
@@ -74,7 +77,7 @@ async function classifyOnline(text: string, deps: ClassifyUnexpectedStopDeps): P
|
||||
throw new Error(`unexpected-stop: no API key for ${model.provider}/${model.id}`);
|
||||
}
|
||||
const metadata = deps.metadataResolver?.(model.provider);
|
||||
const maxTokens = model.reasoning ? Math.max(ANSWER_MAX_TOKENS, REASONING_SAFE_MAX_TOKENS) : ANSWER_MAX_TOKENS;
|
||||
const maxTokens = REASONING_SAFE_MAX_TOKENS;
|
||||
|
||||
const response = await completeSimple(
|
||||
model,
|
||||
|
||||
Reference in New Issue
Block a user