Skip to content

feat(llm): add configurable thinkTagName for thinking output formats#12934

Open
vinaychauhannumber wants to merge 2 commits into
continuedev:mainfrom
vinaychauhannumber:5992-configurable-thinking-output-formats
Open

feat(llm): add configurable thinkTagName for thinking output formats#12934
vinaychauhannumber wants to merge 2 commits into
continuedev:mainfrom
vinaychauhannumber:5992-configurable-thinking-output-formats

Conversation

@vinaychauhannumber

@vinaychauhannumber vinaychauhannumber commented Jul 1, 2026

Copy link
Copy Markdown

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 thinkTagName option on LLMOptions (defaulting to "think") so users can configure the tag name to match their provider.

Changes

core/config/types.ts

  • Added thinkTagName?: string to the LLMOptions interface with full JSDoc documentation

core/llm/index.ts

  • Added thinkTagName: string property to the BaseLLM class
  • Wired it up in the constructor with a default of "think" (fully backward-compatible)

core/llm/llms/Ollama.ts

  • Replaced hardcoded "<think>" / "</think>" strings with dynamic thinkOpenTag / thinkCloseTag values derived from this.thinkTagName

core/util/index.ts

  • Updated removeCodeBlocksAndTrim to accept an optional thinkTagName parameter
  • The think-block regex is now built dynamically instead of being hardcoded

core/autocomplete/postprocessing/index.ts

  • Updated the Qwen3 postprocessing block to use llm.thinkTagName for regex construction instead of hardcoded <think> tags

Usage 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 — thinkTagName defaults to "think", so all existing configs work unchanged.

References


Summary by cubic

Make the reasoning tag name configurable via thinkTagName so providers like vLLM and Ollama work correctly; default stays "think" for backward compatibility. Fixes #5992.

  • New Features
    • Added thinkTagName?: string to LLMOptions; wired through BaseLLM, ILLM, and public types (core/index.d.ts).
    • Updated Ollama streaming to use dynamic open/close tags.
    • Made regexes dynamic in Qwen3 postprocessing and removeCodeBlocksAndTrim to strip custom thinking blocks.

Written for commit f23b9e5. Summary will update on new commits.

Review in cubic

…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
@vinaychauhannumber vinaychauhannumber requested a review from a team as a code owner July 1, 2026 23:09
@vinaychauhannumber vinaychauhannumber requested review from sestinj and removed request for a team July 1, 2026 23:09
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@vinaychauhannumber

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@vinaychauhannumber

Copy link
Copy Markdown
Author

recheck

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread core/config/types.ts
* Set this to match your provider's reasoning output format.
* See: https://docs.vllm.ai/en/latest/features/reasoning_outputs.html
*/
thinkTagName?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support configurable thinking output formats

1 participant