feat(console): Always-on thinking-mode option in the model form

Post effort-knob rework, "Enabled" (manual) means knob-controlled —
effort none turns thinking off. Operators who want the pre-#771
always-on behavior (knob never disables) previously had to hand-write
thinking_mode "adaptive" into the raw capabilities JSON. The dropdown
now offers all three representable modes — None / Effort-knob
controlled / Always on — and the edit-load lift captures adaptive
instead of relegating it to raw JSON.
This commit is contained in:
Patrick Buckley
2026-07-04 01:19:24 -07:00
parent d564cee43d
commit c64dc16319
3 changed files with 18 additions and 15 deletions
+9 -8
View File
@@ -807,14 +807,15 @@ the levers live in the chat template, reached through
`chat_template_kwargs` in the request body. Two channels, dynamic first:
* **Session effort knob (dynamic).** Set the model's thinking mode to
Enabled in the admin Models form (or `thinking_mode = "manual"` +
`thinking_param` under `[models.*.capabilities]`) and the provider
maps the session's reasoning-effort knob onto the template toggle
per-request: effort `none` sends `{<thinking_param>: false}`, any
other level sends `true` — the same contract as the real lane's
manual mode. (`thinking_mode = "adaptive"` instead always sends
`true`: adaptive means the model self-regulates, so the knob never
force-disables — mirroring the native adaptive branch.) Templates
"Effort-knob controlled" in the admin Models form (or
`thinking_mode = "manual"` + `thinking_param` under
`[models.*.capabilities]`) and the provider maps the session's
reasoning-effort knob onto the template toggle per-request: effort
`none` sends `{<thinking_param>: false}`, any other level sends
`true` — the same contract as the real lane's manual mode. ("Always
on" / `thinking_mode = "adaptive"` instead always sends `true`: the
model self-regulates, so the knob never force-disables — mirroring
the native adaptive branch.) Templates
with a graded effort key (gpt-oss-style) additionally set
`effort_param` (e.g. `"reasoning_effort"`), plus optional
`reasoning_effort_values` / `default_reasoning_effort` to validate
+7 -6
View File
@@ -6980,13 +6980,14 @@ function showEditModelModal(definitionId) {
? capsObj.server_compat
: {};
// Only extract thinking_mode into the dropdown when the UI can
// represent it ("manual" or ""). Unrepresentable values like
// "adaptive" keep thinking_mode in the raw capabilities JSON so it
// isn't silently lost on save. Both compat lanes round-trip the
// dropdown: on anthropic-compatible it drives the effort-knob →
// chat_template_kwargs mapping (merge_reasoning_template_kwargs).
// represent it ("", "manual" = effort-knob controlled, "adaptive" =
// always on). Unrepresentable/garbage values keep thinking_mode in
// the raw capabilities JSON so they aren't silently lost on save.
// Both compat lanes round-trip the dropdown: it drives the
// effort-knob → chat_template_kwargs mapping
// (merge_reasoning_template_kwargs).
const tmVal = capsObj.thinking_mode || "";
const tmCaptured = tmVal === "" || tmVal === "manual";
const tmCaptured = tmVal === "" || tmVal === "manual" || tmVal === "adaptive";
if (tmCaptured) {
document.getElementById("model-thinking-mode").value = tmVal;
document.getElementById("model-thinking-param").value =
+2 -1
View File
@@ -1771,7 +1771,8 @@
>
<select id="model-thinking-mode">
<option value="">None</option>
<option value="manual">Enabled</option>
<option value="manual">Effort-knob controlled</option>
<option value="adaptive">Always on</option>
</select>
<div id="model-thinking-param-row" hidden>
<label for="model-thinking-param"