Skip to content

Feature Request: Custom Thinking Levels per Model #3208

Description

@ghost91-

What do you want to change?

Allow models to define their own thinking levels in models.json, so Shift+Tab only cycles through levels the model actually supports. The extension API should support this via pi.registerProvider() as well. I'd like to implement this myself once the approach is decided.

Related: #3016. That issue describes the broader problem well. This issue focuses on a specific, actionable proposal.

Why?

I'm working with a custom OpenAI-compatible provider whose models support only specific reasoning_effort values (e.g., ["none", "medium"]). The provider defaults to thinking ON when the parameter isn't sent, which clashes with pi's "thinking off" display that omits the parameter entirely. Users see "off" but get thinking enabled on the backend.

The provider exposes a custom /info endpoint with model metadata, including supported_reasoning_effort per model. I'd like to build an extension that auto-discovers these models and configures thinking levels correctly, but extensions can't define custom levels today.

Current workarounds are insufficient:

  • reasoningEffortMap maps pi levels to provider values, but all 6 levels still appear in the UI
  • before_provider_request can inject reasoning_effort, but can't change which levels are selectable
  • Mapping 6 levels down to 2 works-ish but confuses users

How? (optional)

Add a way to define custom thinking levels per model. A few options:

Option 1: New thinkingLevels field - levels appear in UI and are sent directly to API. Simple, but no mapping for non-standard level names.

{ "id": "model-a", "thinkingLevels": ["none", "medium"] }

Option 2: reasoningEffortMap keys define visible levels - single field for both UI and mapping. Only mapped keys are selectable. Optional: null as value omits reasoning_effort for that level. Risk: changes semantics for existing configs that only map a subset.

{ "id": "model-a", "reasoningEffortMap": { "off": "none", "medium": "medium" } }

Option 3: Both fields together - separate control over UI and mapping. Useful for non-standard level names, but more verbose.

{ "id": "model-a", "thinkingLevels": ["off", "high"], "reasoningEffortMap": { "off": "disabled", "high": "turbo" } }

All options need to handle the "thinking off" case: either disable the special "off" behavior when custom levels are set, or add a defaultThinkingLevel field. Key requirement: backward compatibility.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions