Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: add per-model default and max reasoning effort with per-turn selection - #26970

Closed
DanielleMaywood wants to merge 4 commits into
mainfrom
dm/model-reasoning-effort-slider
Closed

feat: add per-model default and max reasoning effort with per-turn selection#26970
DanielleMaywood wants to merge 4 commits into
mainfrom
dm/model-reasoning-effort-slider

Conversation

@DanielleMaywood

Copy link
Copy Markdown
Contributor

Reasoning effort was a fixed per-model setting stored at provider-specific paths in chat_model_configs.options, so offering the same model at multiple efforts required duplicate model configs. Each model config now carries a reasoning_effort {default, max} pair, and the chat model selector gains an effort slider so users pick the per-turn effort, clamped to the model's max.

Changes

  • codersdk: new ChatModelReasoningEffortConfig (default/max) on ChatModelCallConfig; the per-provider effort fields (openai.reasoning_effort, anthropic.effort, openaicompat.reasoning_effort, openrouter/vercel reasoning.effort) are removed. CreateChatRequest, CreateChatMessageRequest, and EditChatMessageRequest gain reasoning_effort for the per-turn selection, and Chat exposes last_reasoning_effort.
  • Migration (000536): adds chats.last_reasoning_effort, chat_messages.reasoning_effort, and chat_queued_messages.reasoning_effort; rewrites chat_model_configs.options so the legacy per-provider effort value becomes both default and max, stripping the legacy keys. Down migration restores the provider-appropriate path via ai_providers.type.
  • chatd: the per-turn value flows through send/edit/queued-message promotion into chats.last_reasoning_effort (mirroring last_model_config_id). At generation, chatprovider.ResolveReasoningEffort picks the requested value (else the config default), clamps to the config max on the global scale none < minimal < low < medium < high < xhigh < max, and snaps into the provider's runtime-supported set before injecting it into the fantasy provider options. Documented in coderd/x/chatd/ARCHITECTURE.md.
  • Model selector (site): an "Effort" row with an info tooltip, a discrete slider, and a value badge renders at the bottom of the model dropdown when the selected model has effort configured. Selection re-clamps on model switch and is sent with create-chat, send, and edit requests.
  • Admin panel (site): the per-provider effort selects are replaced by "Default reasoning effort" / "Max reasoning effort" selects limited to the provider's supported values, with default <= max validation. Known-model catalog defaults now populate the new pair.

Validation: config values must be in the provider's supported set with default <= max; per-turn values are validated against the global scale (400 otherwise) and re-clamped server-side at generation.

Implementation plan

Effort scale

One global ordered scale used for clamping and the slider: minimal < low < medium < high < xhigh < max ("none" normalizes to unset everywhere). Provider-supported sets follow the existing runtime normalization: openai/openaicompat minimal..xhigh, anthropic low..max, openrouter low..high, vercel none..xhigh.

Model config schema (codersdk)

Replace the five per-provider effort fields with one top-level ChatModelReasoningEffortConfig { default, max } on ChatModelCallConfig. Backend validation: both values in the provider's supported set, default <= max, single value mirrors into the other.

Per-turn effort selection

Mirror the existing model_config_id flow: reasoning_effort on create/edit message requests, nullable columns on chat_messages and chat_queued_messages, chats.last_reasoning_effort updated by InsertChatMessages from the last message carrying one (so queued messages promote correctly).

Generation resolution

In prepareGeneration: effective = user-selected (chats.last_reasoning_effort) else config default; clamped to config max on the global scale; normalized/snapped into the provider's supported range; injected into the provider-native fantasy options. Models without effort config ignore user values.

Migration

One migration adds the three columns and rewrites chat_model_configs.options: COALESCE across the five legacy provider effort paths becomes reasoning_effort {default: v, max: v}, legacy keys stripped. Down migration reverses via the ai_providers join.

Frontend

Model selector dropdown gets a bottom Effort row (label + info tooltip, shared Slider, value badge) shown only when the selected model has effort configured; steps span the provider's supported values up to the model's max; re-clamps on model switch; value sent with each message and on chat creation. Admin panel gets Default/Max effort selects replacing the per-provider selects.

Tests

Go: migration fixture for the JSONB rewrite, clamp/resolution unit tests, handler validation tests, send/create persistence tests. Frontend: vitest for pure effort helpers and form logic, Storybook play tests for the slider row and create form.

🤖 Generated by Coder Agents on behalf of @DanielleMaywood

…lection

Replace the fixed per-provider reasoning effort in chat model configs
with a default/max pair, migrate existing values so the old effort
becomes both, and let users pick the per-turn effort with a slider in
the chat model selector, clamped to the model's max.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Docs preview

📖 View docs preview for docs/admin/security/audit-logs.md

… models page

Migration 000536 collided with main's ai_user_daily_spend migration.
The default and max reasoning effort selects now render in the
always-visible section of the model form instead of under Advanced.
Make the effort data migration provider-aware, allow configuring none
where the provider runtime supports it, fail model config updates when
the provider is soft-deleted, preserve a message's original effort on
edit unless the user changes it, and trim unused helpers and redundant
tests.

Copy link
Copy Markdown
Contributor Author

Split into a stacked series per review feedback: #26974 (model config default/max + migration) -> #26975 (per-turn API) -> #26976 (models page UI, on #26974) and #26977 (chat slider, on #26975). The combined content of the stack is identical to this branch. 🤖 Generated by Coder Agents on behalf of @DanielleMaywood

@github-actions github-actions Bot locked and limited conversation to collaborators Jul 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant