feat(llm): add configurable thinkTagName for thinking output formats#12934
feat(llm): add configurable thinkTagName for thinking output formats#12934vinaychauhannumber wants to merge 2 commits into
Conversation
…ontinuedev#5992) Different LLM providers use different XML tag names for reasoning/thinking output. Previously, Continue hardcoded '<think>...</think>' everywhere, which broke support for providers like vLLM that use custom tag formats. Changes: - Add `thinkTagName` option to `LLMOptions` interface (defaults to 'think') - Wire `thinkTagName` through the BaseLLM constructor with a default of 'think', ensuring full backward compatibility - Update Ollama streaming chat handler to use configurable open/close tags instead of hardcoded '<think>' / '</think>' - Update `removeCodeBlocksAndTrim` in core/util to accept an optional `thinkTagName` param and build the regex dynamically - Update autocomplete postprocessing (Qwen3 block) to use `llm.thinkTagName` instead of hardcoded '<think>' regex Usage example in config: { "provider": "openai-compatible", "model": "my-vllm-model", "apiBase": "http://localhost:8000/v1", "thinkTagName": "reasoning" // strips <reasoning>...</reasoning> } Fixes continuedev#5992 Ref: https://docs.vllm.ai/en/latest/features/reasoning_outputs.html
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
recheck |
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="core/config/types.ts">
<violation number="1" location="core/config/types.ts:583">
P2: The configurable `thinkTagName` is documented as an XML tag name, but downstream code interpolates it directly into `new RegExp()` without escaping regex metacharacters. A user setting `thinkTagName` to something like `reason[ing]` or `think.*` would hit a runtime `SyntaxError` or match unintended content. The codebase already has `escapeLiteralForRegex` in `core/util/regexValidator.ts`; it should be applied when building the think-block regexes in `core/util/index.ts` and `core/autocomplete/postprocessing/index.ts` (or the value should be escaped when assigned in `BaseLLM`).</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| * Set this to match your provider's reasoning output format. | ||
| * See: https://docs.vllm.ai/en/latest/features/reasoning_outputs.html | ||
| */ | ||
| thinkTagName?: string; |
There was a problem hiding this comment.
P2: The configurable thinkTagName is documented as an XML tag name, but downstream code interpolates it directly into new RegExp() without escaping regex metacharacters. A user setting thinkTagName to something like reason[ing] or think.* would hit a runtime SyntaxError or match unintended content. The codebase already has escapeLiteralForRegex in core/util/regexValidator.ts; it should be applied when building the think-block regexes in core/util/index.ts and core/autocomplete/postprocessing/index.ts (or the value should be escaped when assigned in BaseLLM).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At core/config/types.ts, line 583:
<comment>The configurable `thinkTagName` is documented as an XML tag name, but downstream code interpolates it directly into `new RegExp()` without escaping regex metacharacters. A user setting `thinkTagName` to something like `reason[ing]` or `think.*` would hit a runtime `SyntaxError` or match unintended content. The codebase already has `escapeLiteralForRegex` in `core/util/regexValidator.ts`; it should be applied when building the think-block regexes in `core/util/index.ts` and `core/autocomplete/postprocessing/index.ts` (or the value should be escaped when assigned in `BaseLLM`).</comment>
<file context>
@@ -572,6 +572,15 @@ declare global {
+ * Set this to match your provider's reasoning output format.
+ * See: https://docs.vllm.ai/en/latest/features/reasoning_outputs.html
+ */
+ thinkTagName?: string;
}
</file context>
The previous commit added thinkTagName to LLMOptions and BaseLLM but missed:
1. The ILLM interface in core/config/types.ts which explicitly declares
properties (TypeScript doesn't infer them from extends alone for build checks)
2. The public LLMOptions in core/index.d.ts used by the VSIX build pipeline
This caused CI failures:
- 'Property thinkTagName does not exist on type ILLM'
- 'Property thinkTagName does not exist on type { model: string; title: ... }'
Fixes both by adding thinkTagName to all relevant type definitions.
Summary
Fixes #5992
Different LLM providers use different XML tag names for reasoning/thinking output. Previously, Continue hardcoded
<think>...</think>in multiple places, which broke support for providers like vLLM that use custom tag formats.This PR introduces a
thinkTagNameoption onLLMOptions(defaulting to"think") so users can configure the tag name to match their provider.Changes
core/config/types.tsthinkTagName?: stringto theLLMOptionsinterface with full JSDoc documentationcore/llm/index.tsthinkTagName: stringproperty to theBaseLLMclass"think"(fully backward-compatible)core/llm/llms/Ollama.ts"<think>"/"</think>"strings with dynamicthinkOpenTag/thinkCloseTagvalues derived fromthis.thinkTagNamecore/util/index.tsremoveCodeBlocksAndTrimto accept an optionalthinkTagNameparametercore/autocomplete/postprocessing/index.tsllm.thinkTagNamefor regex construction instead of hardcoded<think>tagsUsage Example
{ "provider": "openai-compatible", "model": "my-vllm-model", "apiBase": "http://localhost:8000/v1", "thinkTagName": "reasoning" }This will correctly strip
<reasoning>...</reasoning>blocks instead of the default<think>...</think>.Backward Compatibility
Fully backward compatible —
thinkTagNamedefaults to"think", so all existing configs work unchanged.References
Summary by cubic
Make the reasoning tag name configurable via
thinkTagNameso providers like vLLM and Ollama work correctly; default stays "think" for backward compatibility. Fixes #5992.thinkTagName?: stringtoLLMOptions; wired throughBaseLLM,ILLM, and public types (core/index.d.ts).removeCodeBlocksAndTrimto strip custom thinking blocks.Written for commit f23b9e5. Summary will update on new commits.