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.
What do you want to change?
Allow models to define their own thinking levels in
models.json, soShift+Tabonly cycles through levels the model actually supports. The extension API should support this viapi.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_effortvalues (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
/infoendpoint with model metadata, includingsupported_reasoning_effortper 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:
reasoningEffortMapmaps pi levels to provider values, but all 6 levels still appear in the UIbefore_provider_requestcan injectreasoning_effort, but can't change which levels are selectableHow? (optional)
Add a way to define custom thinking levels per model. A few options:
Option 1: New
thinkingLevelsfield - 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:
reasoningEffortMapkeys define visible levels - single field for both UI and mapping. Only mapped keys are selectable. Optional:nullas value omitsreasoning_effortfor 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
defaultThinkingLevelfield. Key requirement: backward compatibility.