From bc73d6300c398fe993db9ede352f608004111e91 Mon Sep 17 00:00:00 2001 From: Josh France <12610835+16francej@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:29:59 -0700 Subject: [PATCH 1/2] Add Admin runtime reasoning controls --- .../pr-screenshots/admin-runtime-controls.jpg | Bin 0 -> 63748 bytes plugins/admin/public/index.html | 51 +++++++++++++- plugins/admin/test/default-view.test.ts | 12 ++++ src/api/routes/admin-resources.ts | 44 +++++++++++- src/api/routes/admin/scope-config.ts | 8 +++ src/harness/harness-router.ts | 65 ++++++++++++++---- src/model/pi-models.ts | 11 +++ test/admin-resources.test.ts | 64 +++++++++++++++++ test/runtime-selection.test.ts | 48 +++++++++++++ 9 files changed, 287 insertions(+), 16 deletions(-) create mode 100644 .github/pr-screenshots/admin-runtime-controls.jpg diff --git a/.github/pr-screenshots/admin-runtime-controls.jpg b/.github/pr-screenshots/admin-runtime-controls.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df5192ce91b0809b85730907f8f2e5e74662e0de GIT binary patch literal 63748 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 literal 0 HcmV?d00001 diff --git a/plugins/admin/public/index.html b/plugins/admin/public/index.html index e7c0367b..35651f25 100644 --- a/plugins/admin/public/index.html +++ b/plugins/admin/public/index.html @@ -4348,6 +4348,15 @@

Default harness and model

+ + +
Confirm governance change
harness.appendChild(o); }); harness.value = approvedHarnesses.includes(current.harnessId) ? current.harnessId : approvedHarnesses[0]; + const effort = $("base-effort"); + const thinkingLevelsByHarness = r.data.thinkingLevelsByHarness || {}; + const syncEffort = () => { + const thinkingLevels = thinkingLevelsByHarness[harness.value] || ["auto"]; + const prior = effort.value || current.effortLevel || "auto"; + effort.textContent = ""; + thinkingLevels.forEach((level) => { + const o = document.createElement("option"); + o.value = level; + o.textContent = + { + auto: "Auto", + low: "Low", + medium: "Medium", + high: "High", + xhigh: "Extra high", + max: "Max", + ultracode: "Ultracode", + }[level] || level; + effort.appendChild(o); + }); + effort.value = thinkingLevels.includes(prior) ? prior : "auto"; + }; + const fastMode = $("base-fast-mode"); + fastMode.checked = current.fastMode === true; + const syncFastMode = () => { + const fastCapable = + (r.data.fastModeHarnessIds || []).includes(harness.value) && + (r.data.fastModeModelIds || []).includes($("base-model").value); + fastMode.disabled = !fastCapable; + if (!fastCapable) fastMode.checked = false; + }; const syncModels = () => { const selectedHarness = harness.value; const compatible = modelsByHarness[selectedHarness] || opts; @@ -6352,6 +6393,9 @@

Confirm governance change

sel.appendChild(o); }); sel.value = compatible.some((m) => m.id === prior) ? prior : (compatible[0] || {}).id || ""; + sel.oninput = syncFastMode; + syncEffort(); + syncFastMode(); }; harness.oninput = syncModels; syncModels(); @@ -7937,7 +7981,12 @@

Confirm governance change

"external-slack-participants": () => ({ on: $("external-slack-participants").checked }), "org-ambient": () => ({ on: $("org-ambient").checked }), "interactive-fast-mode": () => ({ on: $("interactive-fast-mode").checked }), - runtime: () => ({ harnessId: $("base-harness").value, modelId: $("base-model").value }), + runtime: () => ({ + harnessId: $("base-harness").value, + modelId: $("base-model").value, + effortLevel: $("base-effort").value, + fastMode: $("base-fast-mode").checked, + }), "approved-harnesses": () => ({ ids: Array.from(document.querySelectorAll("#approved-harnesses-list input[type=checkbox]:checked")).map( (c) => c.value, diff --git a/plugins/admin/test/default-view.test.ts b/plugins/admin/test/default-view.test.ts index 68543ffe..634a7bd7 100644 --- a/plugins/admin/test/default-view.test.ts +++ b/plugins/admin/test/default-view.test.ts @@ -157,6 +157,18 @@ test("governance renders simple settings as compact rows with contextual actions assert.match(html, /"turnWallClockSec" in r\.data/); }); +test("default runtime controls save reasoning level and fast mode", () => { + assert.match(html, /id="base-effort"/); + assert.match(html, /id="base-fast-mode"/); + assert.match(html, /thinkingLevelsByHarness/); + assert.match(html, /fastModeModelIds/); + assert.match(html, /fastModeHarnessIds/); + assert.match( + html, + /runtime: \(\) => \(\{[\s\S]*effortLevel: \$\("base-effort"\)\.value,[\s\S]*fastMode: \$\("base-fast-mode"\)\.checked/, + ); +}); + test("compact governance rows preserve policy detail and collapse before they overflow", () => { assert.doesNotMatch(html, /#view-governance \.setting-row > \.head p[^}]*line-clamp/); assert.doesNotMatch(html, /#view-governance \.setting-row > \.foot \.status[^}]*white-space:\s*nowrap/); diff --git a/src/api/routes/admin-resources.ts b/src/api/routes/admin-resources.ts index 6d3c2f22..1ffeb83d 100644 --- a/src/api/routes/admin-resources.ts +++ b/src/api/routes/admin-resources.ts @@ -5,6 +5,8 @@ import { parseCommandPolicy } from "../../policy/command-policy.ts"; import { parseScopeId, scopeId, type CommandPolicy, type Grant } from "../../types.ts"; import { defaultModelForHarness, + FAST_MODE_MODEL_IDS, + harnessSupportsFastMode, HARNESS_IDS, isHarnessId, modelSupportedByHarness, @@ -12,6 +14,7 @@ import { modelProviderAvailabilityFor, resolveModel, SELECTABLE_BASE_MODELS, + thinkingLevelsForHarness, ALL_PROVIDERS_AVAILABLE, } from "../../model/pi-models.ts"; import { resolveRuntimeChoiceDurable } from "../../harness/harness-router.ts"; @@ -372,7 +375,19 @@ export const ADMIN_RESOURCES: readonly AdminResource[] = [ return { error: `model ${modelId} is not supported by ${runtime.harnessId}` }; const bad = unserviceable(runtime.harnessId); if (bad) return bad; - await ctx.deps.config!.setRuntimeSelectionLatest(scope, { harnessId: runtime.harnessId, modelId }); + await ctx.deps.config!.setRuntimeSelectionLatest(scope, { + harnessId: runtime.harnessId, + modelId, + ...(runtime.effortLevel ? { effortLevel: runtime.effortLevel } : {}), + ...(typeof runtime.fastMode === "boolean" + ? { + fastMode: + runtime.fastMode && + harnessSupportsFastMode(runtime.harnessId) && + FAST_MODE_MODEL_IDS.includes(modelId), + } + : {}), + }); } else { const harnessId = isHarnessId(ctx.deps.harnessId) ? ctx.deps.harnessId : "pi"; const effective = await resolveRuntimeChoiceDurable(ctx.deps.config!, scopeId("org", configOrgId()), scope, { @@ -383,7 +398,19 @@ export const ADMIN_RESOURCES: readonly AdminResource[] = [ return { error: `model ${modelId} is not supported by ${effective.harnessId}` }; const bad = unserviceable(effective.harnessId); if (bad) return bad; - await ctx.deps.config!.setRuntimeSelectionLatest(scope, { harnessId: effective.harnessId, modelId }); + await ctx.deps.config!.setRuntimeSelectionLatest(scope, { + harnessId: effective.harnessId, + modelId, + ...(effective.effortLevel ? { effortLevel: effective.effortLevel } : {}), + ...(typeof effective.fastMode === "boolean" + ? { + fastMode: + effective.fastMode && + harnessSupportsFastMode(effective.harnessId) && + FAST_MODE_MODEL_IDS.includes(modelId), + } + : {}), + }); } return { ok: true }; }, @@ -402,17 +429,28 @@ export const ADMIN_RESOURCES: readonly AdminResource[] = [ } const harnessId = (ctx.body as { harnessId?: unknown }).harnessId; const modelId = (ctx.body as { modelId?: unknown }).modelId; + const effortLevel = (ctx.body as { effortLevel?: unknown }).effortLevel ?? "auto"; + const fastMode = (ctx.body as { fastMode?: unknown }).fastMode ?? false; if (!isHarnessId(harnessId)) return { error: `runtime requires harnessId (${HARNESS_IDS.join(" | ")})` }; const approved = (await ctx.deps.config!.getApprovedHarnessesDurable()) ?? [ctx.deps.harnessId ?? "pi"]; if (!approved.includes(harnessId)) return { error: `harness ${harnessId} is not approved` }; if (typeof modelId !== "string" || !modelSupportedByHarness(modelId, harnessId)) return { error: `model ${String(modelId)} is not supported by ${harnessId}` }; + const thinkingLevels = thinkingLevelsForHarness(harnessId); + if (typeof effortLevel !== "string" || !thinkingLevels.includes(effortLevel)) + return { error: `runtime requires effortLevel (${thinkingLevels.join(" | ")}) for ${harnessId}` }; + if (typeof fastMode !== "boolean") return { error: "runtime requires fastMode (boolean)" }; const runtimeKeys = ctx.deps.providerKeys ?? ALL_PROVIDERS_AVAILABLE; if (!modelServiceable(modelId, modelProviderAvailabilityFor(harnessId, runtimeKeys))) return { error: `model ${modelId} isn't serviceable on this deployment: its provider key is not configured for the ${harnessId} harness`, }; - await ctx.deps.config!.setRuntimeSelectionLatest(scope, { harnessId, modelId }); + await ctx.deps.config!.setRuntimeSelectionLatest(scope, { + harnessId, + modelId, + effortLevel, + fastMode: fastMode && harnessSupportsFastMode(harnessId) && FAST_MODE_MODEL_IDS.includes(modelId), + }); return { ok: true }; }, }, diff --git a/src/api/routes/admin/scope-config.ts b/src/api/routes/admin/scope-config.ts index 22acc4f7..a9e8846a 100644 --- a/src/api/routes/admin/scope-config.ts +++ b/src/api/routes/admin/scope-config.ts @@ -2,6 +2,8 @@ import { parseScopeId } from "../../../types.ts"; import { encodeRef, serviceCredRef } from "../../../acl/resource-ref.ts"; import { computeRetention } from "../../../admin/retention.ts"; import { + FAST_MODE_MODEL_IDS, + harnessSupportsFastMode, HARNESS_IDS, SELECTABLE_BASE_MODELS, defaultModelForHarness, @@ -9,6 +11,7 @@ import { modelServiceable, ALL_PROVIDERS_AVAILABLE, resolveModel, + thinkingLevelsForHarness, } from "../../../model/pi-models.ts"; import { builtInModelCatalog, @@ -270,6 +273,11 @@ export async function getScopeConfig(ctx: ApiCtx): Promise { harnessDefault: deps.harnessId ?? "pi", harnessOptions: HARNESS_IDS.filter((id) => id !== "mock"), modelsByHarness: Object.fromEntries(HARNESS_IDS.map((id) => [id, modelsFor(id)])), + thinkingLevelsByHarness: Object.fromEntries( + HARNESS_IDS.filter((id) => id !== "mock").map((id) => [id, thinkingLevelsForHarness(id)]), + ), + fastModeModelIds: FAST_MODE_MODEL_IDS, + fastModeHarnessIds: HARNESS_IDS.filter(harnessSupportsFastMode), browseModelOptions: SELECTABLE_BASE_MODELS.filter((m) => modelServiceable(m.id, providersFor(deps.harnessId ?? "pi")), ), diff --git a/src/harness/harness-router.ts b/src/harness/harness-router.ts index 28089627..db90d0ed 100644 --- a/src/harness/harness-router.ts +++ b/src/harness/harness-router.ts @@ -1,5 +1,13 @@ import type { ScopedConfigStore } from "../resolution/config-store.ts"; -import { defaultModelForHarness, isHarnessId, modelSupportedByHarness, type HarnessId } from "../model/pi-models.ts"; +import { + defaultModelForHarness, + FAST_MODE_MODEL_IDS, + harnessSupportsFastMode, + isHarnessId, + modelSupportedByHarness, + thinkingLevelsForHarness, + type HarnessId, +} from "../model/pi-models.ts"; import type { ScopeId } from "../types.ts"; import type { Harness, HarnessTurnInput } from "./harness.ts"; import { NonRetryableTurnError } from "../core/turn-error.ts"; @@ -7,6 +15,26 @@ import { NonRetryableTurnError } from "../core/turn-error.ts"; export interface RuntimeChoice { harnessId: HarnessId; modelId: string; + effortLevel?: string; + fastMode?: boolean; +} + +function normalizeRuntimeChoice(choice: RuntimeChoice): RuntimeChoice { + return { + harnessId: choice.harnessId, + modelId: choice.modelId, + ...(choice.effortLevel && thinkingLevelsForHarness(choice.harnessId).includes(choice.effortLevel) + ? { effortLevel: choice.effortLevel } + : {}), + ...(typeof choice.fastMode === "boolean" + ? { + fastMode: + choice.fastMode && + harnessSupportsFastMode(choice.harnessId) && + FAST_MODE_MODEL_IDS.includes(choice.modelId), + } + : {}), + }; } export function resolveRuntimeChoice( @@ -19,9 +47,14 @@ export function resolveRuntimeChoice( const approved = config.getApprovedHarnesses() ?? [fallback.harnessId]; const orgStored = config.getRuntimeSelection(orgScopeId); const orgLegacy = config.getBaseModel(orgScopeId); - const configuredOrg = + const configuredOrg: RuntimeChoice = orgStored && isHarnessId(orgStored.harnessId) - ? { harnessId: orgStored.harnessId, modelId: orgStored.modelId } + ? { + harnessId: orgStored.harnessId, + modelId: orgStored.modelId, + ...(orgStored.effortLevel ? { effortLevel: orgStored.effortLevel } : {}), + ...(typeof orgStored.fastMode === "boolean" ? { fastMode: orgStored.fastMode } : {}), + } : { harnessId: fallback.harnessId, modelId: orgLegacy ?? fallback.modelId }; const firstApproved = approved.find(isHarnessId) ?? fallback.harnessId; const safeFallback = @@ -35,22 +68,24 @@ export function resolveRuntimeChoice( : safeFallback; const scopedStored = scope === orgScopeId ? null : config.getRuntimeSelection(scope); const scopedLegacy = scope === orgScopeId ? null : config.getBaseModel(scope); - let inherited = org; + let inherited: RuntimeChoice = org; if (scopedStored && isHarnessId(scopedStored.harnessId)) { - inherited = { harnessId: scopedStored.harnessId, modelId: scopedStored.modelId }; + inherited = { + harnessId: scopedStored.harnessId, + modelId: scopedStored.modelId, + ...(scopedStored.effortLevel ? { effortLevel: scopedStored.effortLevel } : {}), + ...(typeof scopedStored.fastMode === "boolean" ? { fastMode: scopedStored.fastMode } : {}), + }; } else if (scopedLegacy) { inherited = { harnessId: fallback.harnessId, modelId: scopedLegacy }; } - const choice = - requested?.harnessId || requested?.modelId - ? { harnessId: requested.harnessId ?? inherited.harnessId, modelId: requested.modelId ?? inherited.modelId } - : inherited; + const choice = requested?.harnessId || requested?.modelId ? { ...inherited, ...requested } : inherited; if (!approved.includes(choice.harnessId) || !modelSupportedByHarness(choice.modelId, choice.harnessId)) { if (requested?.harnessId || requested?.modelId) throw new NonRetryableTurnError(`runtime ${choice.harnessId}/${choice.modelId} is not approved`); - return org; + return normalizeRuntimeChoice(org); } - return choice; + return normalizeRuntimeChoice(choice); } export async function resolveRuntimeChoiceDurable( @@ -102,7 +137,13 @@ export function createHarnessRouter( await adapter.turns.resetSession?.(input.session.id); } lastHarness.set(input.session.id, choice.harnessId); - return adapter.turns.runTurn({ ...input, harness: choice.harnessId, model: choice.modelId }); + return adapter.turns.runTurn({ + ...input, + harness: choice.harnessId, + model: choice.modelId, + thinkingLevel: input.thinkingLevel ?? choice.effortLevel, + fastMode: input.fastMode ?? choice.fastMode, + }); }, async resetSession(sessionId) { lastHarness.delete(sessionId); diff --git a/src/model/pi-models.ts b/src/model/pi-models.ts index 7d193eec..c8d0973e 100644 --- a/src/model/pi-models.ts +++ b/src/model/pi-models.ts @@ -11,6 +11,17 @@ export const THINKING_LEVELS = ["auto", "low", "medium", "high", "xhigh", "max", export const HARNESS_IDS = ["pi", "opencode", "codex", "claude", "mock"] as const; export type HarnessId = (typeof HARNESS_IDS)[number]; +export function thinkingLevelsForHarness(harnessId: HarnessId): readonly string[] { + if (harnessId === "pi") return THINKING_LEVELS; + if (harnessId === "claude") return THINKING_LEVELS.filter((level) => level !== "ultracode"); + if (harnessId === "codex") return THINKING_LEVELS.filter((level) => level !== "max" && level !== "ultracode"); + return ["auto"]; +} + +export function harnessSupportsFastMode(harnessId: HarnessId): boolean { + return harnessId === "pi" || harnessId === "claude"; +} + export const MODEL_PROVIDERS = ["anthropic", "openai", "openrouter"] as const; export type ModelProvider = (typeof MODEL_PROVIDERS)[number]; diff --git a/test/admin-resources.test.ts b/test/admin-resources.test.ts index c0bb8545..d121984c 100644 --- a/test/admin-resources.test.ts +++ b/test/admin-resources.test.ts @@ -529,6 +529,70 @@ test("base-model is a sparse per-scope override: a channel pins its own model, e } }); +test("admin runtime saves reasoning level and fast mode with the default model", async () => { + const srv = start(); + const url = `${srv.base}/v1/admin/scopes/org:default-org/runtime`; + try { + srv.built.config.setApprovedHarnesses(["pi", "opencode", "codex"]); + await srv.built.config.flushScope("org:default-org"); + const saved = await fetch(url, { + method: "PUT", + headers: ADMIN, + body: JSON.stringify({ harnessId: "pi", modelId: "claude-opus-5", effortLevel: "high", fastMode: true }), + }); + assert.equal(saved.status, 200); + assert.deepEqual(await srv.built.config.getRuntimeSelectionDurable("org:default-org"), { + harnessId: "pi", + modelId: "claude-opus-5", + effortLevel: "high", + fastMode: true, + orgRevision: 1, + revision: 1, + }); + + const changedModel = await fetch(`${srv.base}/v1/admin/scopes/org:default-org/base-model`, { + method: "PUT", + headers: ADMIN, + body: JSON.stringify({ modelId: "claude-fable-5" }), + }); + assert.equal(changedModel.status, 200); + assert.deepEqual(await srv.built.config.getRuntimeSelectionDurable("org:default-org"), { + harnessId: "pi", + modelId: "claude-fable-5", + effortLevel: "high", + fastMode: false, + orgRevision: 2, + revision: 2, + }); + + const unsupported = await fetch(url, { + method: "PUT", + headers: ADMIN, + body: JSON.stringify({ harnessId: "pi", modelId: "claude-fable-5", effortLevel: "low", fastMode: true }), + }); + assert.equal(unsupported.status, 200); + assert.equal((await srv.built.config.getRuntimeSelectionDurable("org:default-org"))?.fastMode, false); + + const unsupportedHarness = await fetch(url, { + method: "PUT", + headers: ADMIN, + body: JSON.stringify({ harnessId: "opencode", modelId: "claude-opus-5", effortLevel: "auto", fastMode: true }), + }); + assert.equal(unsupportedHarness.status, 200); + assert.equal((await srv.built.config.getRuntimeSelectionDurable("org:default-org"))?.fastMode, false); + + for (const body of [ + { harnessId: "pi", modelId: "claude-opus-5", effortLevel: "extreme", fastMode: true }, + { harnessId: "codex", modelId: "gpt-5.5", effortLevel: "max", fastMode: false }, + { harnessId: "pi", modelId: "claude-opus-5", effortLevel: "high", fastMode: "yes" }, + ]) { + assert.equal((await fetch(url, { method: "PUT", headers: ADMIN, body: JSON.stringify(body) })).status, 400); + } + } finally { + await srv.close(); + } +}); + test("ambient-policy edits a channel's standing order and bot ledger through the registry", async () => { const srv = start(); try { diff --git a/test/runtime-selection.test.ts b/test/runtime-selection.test.ts index 81d92c91..7184e2ec 100644 --- a/test/runtime-selection.test.ts +++ b/test/runtime-selection.test.ts @@ -51,6 +51,54 @@ test("runtime resolution uses explicit choice, then scope, then org and rejects ); }); +test("runtime resolution carries reasoning and fast-mode defaults into turns", () => { + const config = createMemoryConfigStore("default-org"); + config.setApprovedHarnesses(["pi", "opencode", "codex"]); + config.setRuntimeSelection(ORG, { + harnessId: "pi", + modelId: "claude-opus-5", + effortLevel: "high", + fastMode: true, + }); + assert.deepEqual(resolveRuntimeChoice(config, ORG, PERSONAL, { harnessId: "pi", modelId: "claude-fable-5" }), { + harnessId: "pi", + modelId: "claude-opus-5", + effortLevel: "high", + fastMode: true, + }); + assert.deepEqual( + resolveRuntimeChoice( + config, + ORG, + PERSONAL, + { harnessId: "pi", modelId: "claude-fable-5" }, + { + harnessId: "codex", + modelId: "gpt-5.5", + }, + ), + { + harnessId: "codex", + modelId: "gpt-5.5", + effortLevel: "high", + fastMode: false, + }, + ); + assert.deepEqual( + resolveRuntimeChoice( + config, + ORG, + PERSONAL, + { harnessId: "pi", modelId: "claude-fable-5" }, + { + harnessId: "opencode", + modelId: "claude-opus-5", + }, + ), + { harnessId: "opencode", modelId: "claude-opus-5", fastMode: false }, + ); +}); + test("runtime resolution falls back to the first approved harness when deployment defaults are not approved", () => { const config = createMemoryConfigStore("default-org"); config.setApprovedHarnesses(["codex"]); From 713e534b5db56a2d11172110a0e28b028080b524 Mon Sep 17 00:00:00 2001 From: Josh France <12610835+16francej@users.noreply.github.com> Date: Tue, 11 Aug 2026 19:20:55 -0700 Subject: [PATCH 2/2] Reset auto reasoning on reused Pi sessions --- src/harness/pi-harness.ts | 12 +++++++----- test/pi-harness-fast-mode.test.ts | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/harness/pi-harness.ts b/src/harness/pi-harness.ts index 0c8a96b3..ff74176d 100644 --- a/src/harness/pi-harness.ts +++ b/src/harness/pi-harness.ts @@ -1192,15 +1192,17 @@ function applyEffortAliases(model: unknown): void { }; } -function applyTurnEffort(session: AgentSession, level?: string): void { +export function applyTurnEffort(session: AgentSession, level?: string): void { if (!level || !TURN_EFFORT_LEVELS.has(level)) return; - if (level === "auto") return; + const effectiveLevel = + level === "auto" && session.state.model ? defaultInteractiveThinkingLevel(session.state.model) : level; + const normalizedLevel = effectiveLevel === "auto" ? "medium" : effectiveLevel; applyEffortAliases(session.state.model); try { - if (LEGACY_THINKING_LEVELS.has(level)) { - session.setThinkingLevel(level as LegacyThinkingLevel); + if (LEGACY_THINKING_LEVELS.has(normalizedLevel)) { + session.setThinkingLevel(normalizedLevel as LegacyThinkingLevel); } else { - session.state.thinkingLevel = level as typeof session.state.thinkingLevel; + session.state.thinkingLevel = normalizedLevel as typeof session.state.thinkingLevel; } } catch (e) { swallow("pi: set thinking level", e); diff --git a/test/pi-harness-fast-mode.test.ts b/test/pi-harness-fast-mode.test.ts index 0d6d5f45..fdb4db9a 100644 --- a/test/pi-harness-fast-mode.test.ts +++ b/test/pi-harness-fast-mode.test.ts @@ -1,6 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { + applyTurnEffort, applyFastSpeed, modelSupportsFastMode, wantsFastMode, @@ -70,3 +71,17 @@ test("an explicit opt-in still cannot select fast mode on a model that lacks it" assert.equal(wantsFastMode(true, undefined), false); assert.equal(wantsFastMode(true, ""), false); }); + +test("auto resets a reused Anthropic session to its interactive default", () => { + const session = { + state: { + model: { provider: "anthropic", api: "anthropic-messages" }, + thinkingLevel: "high", + }, + setThinkingLevel(level: string) { + this.state.thinkingLevel = level; + }, + }; + applyTurnEffort(session as never, "auto"); + assert.equal(session.state.thinkingLevel, "low"); +});