mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-10-17 05:14:19 +02:00
ThinkTagSplitter was wired into both streaming paths but neither non-streaming one, and every ancillary call goes through non-streaming chat(). So a reasoning tasks model put its reasoning transcript into the sidebar title, into the suggestion chips, and — worst — into the string that gets embedded and sent to Qdrant, silently corrupting retrieval for the rest of the conversation. splitThinkTags() already existed and was already unit tested; it just had no production callers. Fixed in three layers: 1. Strip at the transport. New normalizeNonStreamed() in think_stream.ts merges structured reasoning (native `thinking`, /v1 `reasoning`) with anything the splitter pulls out of inline tags, and both _chatNative and _chatCompat now return through it. That covers every caller at once, including the legacy controller path and the eval harness. 2. Suppress at the source. _chatNative and _chatStreamNative forwarded `think` only when truthy, so `think: false` was never sent and Ollama left reasoning on for capable models. Guard is now definedness. This also fixes the ai.autoThinking=off setting, which had no effect on the native streaming transport. 3. Guard the call sites. Title, suggestions, and query rewrite now pass think:false plus thinkingCapable (from the memoized capability check, so no extra round-trip), and handle an empty-after-strip result. The rewrite matters most: QUERY_REWRITE_MAX_TOKENS caps it at 120, which a reasoning model burns entirely on thinking, so stripping alone would have turned a corrupt query into an empty one. It now falls back to the raw user message instead of embedding "". Verified: think_stream.spec.ts 17/17 (6 new cases, including the truncated-mid-thought case that drives the fallback), typecheck clean, full test:unit failures byte-identical to the pre-change baseline. |
||
|---|---|---|
| .. | ||
| eval | ||
| functional | ||
| standalone | ||
| unit | ||
| bootstrap.ts | ||