src/utils/no-think-fetch.ts provides a multi-strategy fetch wrapper for suppressing LLM thinking/reasoning tokens, defining the DisableThinkingStrategy type as false | "vllm" | "deepseek" | "dashscope" | "openai" | "anthropic" | "kimi" | "gemini".[1] The llm.disableThinking config option (and its parallel offload.disableThinking) accepts false (default — no suppression) or one of those seven provider strategy strings; the TDAI_LLM_DISABLE_THINKING environment variable is also accepted and normalized via normalizeDisableThinking from no-think-fetch.js.[2][3] Thinking/reasoning tokens are intermediate chain-of-thought outputs generated by some LLMs before their final answer; suppressing them reduces latency and cost when only the final response is needed.
Each strategy injects provider-specific request fields via STRATEGY_TRANSFORMERS in no-think-fetch.ts: "vllm" → chat_template_kwargs.enable_thinking = false; "deepseek"/"dashscope" → top-level enable_thinking: false; "openai" → reasoning_effort: "low"; "anthropic"/"kimi" → thinking: { type: "disabled" }; "gemini" → thinking_config: { thinking_budget: 0 }.[1][4] The "openai" strategy sets reasoning_effort: "low" rather than fully disabling thinking, because the OpenAI o-series API does not support full reasoning suppression.[1] The "vllm" strategy merges enable_thinking: false into any pre-existing chat_template_kwargs object rather than replacing it, preserving other keys already present on the request body.[1] The "kimi" (Moonshot) strategy shares the same transformer as "anthropic", injecting thinking: { type: "disabled" }.[1]
normalizeDisableThinking() treats true as a shorthand for "vllm" (the most common self-hosted scenario), treats false/undefined as false, and emits a console.warn for any unrecognized string before falling back to false.[1] createNoThinkFetch() silently passes through requests with non-JSON bodies: parse errors are caught and the original request is forwarded unchanged.[1]
Sources