chat: clear thinking and fast defaults

This commit is contained in:
VACInc
2026-05-08 06:26:22 -04:00
committed by Peter Steinberger
parent 5ac1fee4de
commit b8e2f648a7
19 changed files with 209 additions and 47 deletions

View File

@@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
### Changes
- Chat commands: add `/think default` and `/fast default` to clear session overrides and inherit configured/provider defaults. (#79385) Thanks @VACInc.
- Dependencies: refresh workspace dependency pins and lockfile, including `@openai/codex` `0.130.0`, `acpx` `0.7.0`, AWS SDK `3.1044.0`, OpenTelemetry `0.217.0`, `typebox` `1.1.38`, `vite` `8.0.11`, `oxfmt` `0.48.0`, and `oxlint` `1.63.0`, and update the Codex harness model snapshot for the new bundled app-server catalog.
- Plugins/install: add guarded plugin install overrides so onboarding and repair tests can route specific plugins to registry specs or local `npm pack` artifacts via environment variables.
- Tests/Docker: add Codex on-demand install and live plugin-tool dependency E2E lanes for packaged onboarding and npm-pack plugin proof.

View File

@@ -135,10 +135,10 @@ Current source-of-truth:
</Accordion>
<Accordion title="Model and run controls">
- `/think <level>` sets the thinking level. Options come from the active model's provider profile; common levels are `off`, `minimal`, `low`, `medium`, and `high`, with custom levels such as `xhigh`, `adaptive`, `max`, or binary `on` only where supported. Aliases: `/thinking`, `/t`.
- `/think <level|default>` sets the thinking level or clears the session override. Options come from the active model's provider profile; common levels are `off`, `minimal`, `low`, `medium`, and `high`, with custom levels such as `xhigh`, `adaptive`, `max`, or binary `on` only where supported. Aliases: `/thinking`, `/t`.
- `/verbose on|off|full` toggles verbose output. Alias: `/v`.
- `/trace on|off` toggles plugin trace output for the current session.
- `/fast [status|on|off]` shows or sets fast mode.
- `/fast [status|on|off|default]` shows, sets, or clears fast mode.
- `/reasoning [on|off|stream]` toggles reasoning visibility. Alias: `/reason`.
- `/elevated [on|off|ask|full]` toggles elevated mode. Alias: `/elev`.
- `/exec host=<auto|sandbox|gateway|node> security=<deny|allowlist|full> ask=<off|on-miss|always> node=<id>` shows or sets exec defaults.

View File

@@ -48,7 +48,8 @@ title: "Thinking levels"
## Setting a session default
- Send a message that is **only** the directive (whitespace allowed), e.g. `/think:medium` or `/t high`.
- That sticks for the current session (per-sender by default); cleared by `/think:off` or session idle reset.
- That sticks for the current session (per-sender by default). Use `/think default` to clear the session override and inherit the configured/provider default; aliases include `inherit`, `clear`, `reset`, and `unpin`.
- `/think off` stores an explicit off override. It disables thinking until you change or clear the session override.
- Confirmation reply is sent (`Thinking level set to high.` / `Thinking disabled.`). If the level is invalid (e.g. `/thinking big`), the command is rejected with a hint and the session state is left unchanged.
- Send `/think` (or `/think:`) with no argument to see the current thinking level.
@@ -59,11 +60,11 @@ title: "Thinking levels"
## Fast mode (/fast)
- Levels: `on|off`.
- Directive-only message toggles a session fast-mode override and replies `Fast mode enabled.` / `Fast mode disabled.`.
- Levels: `on|off|default`.
- Directive-only message toggles a session fast-mode override and replies `Fast mode enabled.` / `Fast mode disabled.`. Use `/fast default` to clear the session override and inherit the configured default; aliases include `inherit`, `clear`, `reset`, and `unpin`.
- Send `/fast` (or `/fast status`) with no mode to see the current effective fast-mode state.
- OpenClaw resolves fast mode in this order:
1. Inline/directive-only `/fast on|off`
1. Inline/directive-only `/fast on|off` override (`/fast default` clears this layer)
2. Session override
3. Per-agent default (`agents.list[].fastModeDefault`)
4. Per-model config: `agents.defaults.models["<provider>/<model>"].params.fastMode`

View File

@@ -59,9 +59,9 @@ export function buildHelpMessage(cfg?: OpenClawConfig): string {
lines.push("");
const optionParts = [
"/think <level>",
"/think <level|default>",
"/model <id>",
"/fast status|on|off",
"/fast status|on|off|default",
"/verbose on|off|full",
"/trace on|off|raw",
];

View File

@@ -13,7 +13,7 @@ type ListThinkingLevels = (
provider?: string | null,
model?: string | null,
catalog?: CommandArgChoiceContext["catalog"],
) => ThinkLevel[];
) => string[];
const BROWSER_SAFE_THINKING_LEVELS: ThinkLevel[] = [
...BASE_THINKING_LEVELS,
@@ -147,8 +147,12 @@ export function assertCommandRegistry(commands: ChatCommandDefinition[]): void {
export function buildBuiltinChatCommands(
params: { listThinkingLevels?: ListThinkingLevels } = {},
): ChatCommandDefinition[] {
const listThinkingLevelChoices =
const configuredThinkingLevels =
params.listThinkingLevels ?? (() => BROWSER_SAFE_THINKING_LEVELS);
const listThinkingLevelChoices: ListThinkingLevels = (provider, model, catalog) => {
const levels = configuredThinkingLevels(provider, model, catalog);
return ["default", ...levels.filter((level) => level !== "default")];
};
const commands: ChatCommandDefinition[] = [
defineChatCommand({
key: "help",
@@ -799,9 +803,9 @@ export function buildBuiltinChatCommands(
args: [
{
name: "mode",
description: "status, on, or off",
description: "status, on, off, or default",
type: "string",
choices: ["status", "on", "off"],
choices: ["status", "on", "off", "default"],
},
],
argsMenu: "auto",

View File

@@ -377,7 +377,7 @@ describe("commands registry", () => {
category: "options",
});
const modeArg = requireCommandArg(fast, "mode");
expect(modeArg.choices).toEqual(["status", "on", "off"]);
expect(modeArg.choices).toEqual(["status", "on", "off", "default"]);
});
it("detects known text commands", () => {
@@ -633,6 +633,7 @@ describe("commands registry args", () => {
expect(menu.arg.name).toBe("level");
expect(menu.choices.map((choice) => choice.value)).toEqual([
"default",
"off",
"low",
"medium",
@@ -640,7 +641,7 @@ describe("commands registry args", () => {
"max",
]);
expect(formatCommandArgMenuTitle({ command, menu })).toBe(
"Choose level for /think.\nOptions: off, low, medium, high, max.",
"Choose level for /think.\nOptions: default, off, low, medium, high, max.",
);
});

View File

@@ -69,6 +69,21 @@ describe("directive parsing", () => {
expect(res.fastMode).toBe(true);
});
it("parses default thinking and fast directives as override clears", () => {
expect(parseInlineDirectives("/think default")).toMatchObject({
hasThinkDirective: true,
thinkLevel: undefined,
rawThinkLevel: "default",
clearThinkLevel: true,
});
expect(parseInlineDirectives("/fast inherit")).toMatchObject({
hasFastDirective: true,
fastMode: undefined,
rawFastMode: "inherit",
clearFastMode: true,
});
});
it("matches elevated with leading space", () => {
const res = extractElevatedDirective(" please /elevated on now");
expect(res.hasDirective).toBe(true);

View File

@@ -241,4 +241,45 @@ describe("handleFastCommand", () => {
}),
);
});
it("clears fast mode for /fast default", async () => {
const params = buildUsageParams();
params.command.commandBodyNormalized = "/fast default";
params.sessionEntry = {
sessionId: "target-session",
updatedAt: Date.now(),
fastMode: true,
};
params.sessionStore = { [params.sessionKey]: params.sessionEntry };
const result = await handleFastCommand(params, true);
expect(result?.shouldContinue).toBe(false);
expect(result?.reply?.text).toBe("⚙️ Fast mode reset to default.");
expect(params.sessionEntry.fastMode).toBeUndefined();
expect(params.sessionStore[params.sessionKey]?.fastMode).toBeUndefined();
});
it("clears fast mode on the target store entry for /fast default", async () => {
const params = buildUsageParams();
params.command.commandBodyNormalized = "/fast default";
params.sessionEntry = {
sessionId: "wrapper-session",
updatedAt: Date.now(),
fastMode: false,
};
params.sessionStore = {
[params.sessionKey]: {
sessionId: "target-session",
updatedAt: Date.now(),
fastMode: true,
},
};
const result = await handleFastCommand(params, true);
expect(result?.reply?.text).toBe("⚙️ Fast mode reset to default.");
expect(params.sessionEntry.fastMode).toBe(false);
expect(params.sessionStore[params.sessionKey]?.fastMode).toBeUndefined();
});
});

View File

@@ -29,7 +29,12 @@ import {
import { formatTokenCount, formatUsd } from "../../utils/usage-format.js";
import { parseActivationCommand } from "../group-activation.js";
import { parseSendPolicyCommand } from "../send-policy.js";
import { normalizeFastMode, normalizeUsageDisplay, resolveResponseUsageMode } from "../thinking.js";
import {
isSessionDefaultDirectiveValue,
normalizeFastMode,
normalizeUsageDisplay,
resolveResponseUsageMode,
} from "../thinking.js";
import { resolveCommandSurfaceChannel } from "./channel-context.js";
import { rejectNonOwnerCommand, rejectUnauthorizedCommand } from "./command-gates.js";
import { handleAbortTrigger, handleStopCommand } from "./commands-session-abort.js";
@@ -412,17 +417,29 @@ export const handleFastCommand: CommandHandler = async (params, allowTextCommand
};
}
const nextMode = normalizeFastMode(rawMode);
const targetSessionEntry = params.sessionStore?.[params.sessionKey] ?? params.sessionEntry;
const resetsToDefault = isSessionDefaultDirectiveValue(rawMode);
const nextMode = resetsToDefault ? undefined : normalizeFastMode(rawMode);
if (nextMode === undefined) {
if (resetsToDefault) {
if (targetSessionEntry && params.sessionStore && params.sessionKey) {
delete targetSessionEntry.fastMode;
await persistSessionEntry({ ...params, sessionEntry: targetSessionEntry });
}
return {
shouldContinue: false,
reply: { text: "⚙️ Fast mode reset to default." },
};
}
return {
shouldContinue: false,
reply: { text: "⚙️ Usage: /fast status|on|off" },
reply: { text: "⚙️ Usage: /fast status|on|off|default" },
};
}
if (params.sessionEntry && params.sessionStore && params.sessionKey) {
params.sessionEntry.fastMode = nextMode;
await persistSessionEntry(params);
if (targetSessionEntry && params.sessionStore && params.sessionKey) {
targetSessionEntry.fastMode = nextMode;
await persistSessionEntry({ ...params, sessionEntry: targetSessionEntry });
}
return {

View File

@@ -48,8 +48,10 @@ export function createEmptyInlineDirectives(): InlineDirectives {
return {
cleaned: "",
hasThinkDirective: false,
clearThinkLevel: false,
hasVerboseDirective: false,
hasFastDirective: false,
clearFastMode: false,
hasReasoningDirective: false,
hasTraceDirective: false,
hasElevatedDirective: false,

View File

@@ -142,25 +142,28 @@ export async function handleDirectiveOnly(
provider: resolvedProvider,
model: resolvedModel,
agentId: activeAgentId,
sessionEntry,
sessionEntry: directives.clearFastMode ? undefined : sessionEntry,
});
const effectiveFastMode = directives.fastMode ?? currentFastMode ?? fastModeState.enabled;
const effectiveFastMode =
directives.fastMode ??
(directives.clearFastMode ? fastModeState.enabled : currentFastMode) ??
fastModeState.enabled;
const effectiveFastModeSource =
directives.fastMode !== undefined ? "session" : fastModeState.source;
if (directives.hasThinkDirective && !directives.thinkLevel) {
if (directives.hasThinkDirective && !directives.thinkLevel && !directives.clearThinkLevel) {
// If no argument was provided, show the current level
if (!directives.rawThinkLevel) {
const level = currentThinkLevel ?? "off";
return {
text: withOptions(
`Current thinking level: ${level}.`,
formatThinkingLevels(resolvedProvider, resolvedModel, ", ", thinkingCatalog),
`default, ${formatThinkingLevels(resolvedProvider, resolvedModel, ", ", thinkingCatalog)}`,
),
};
}
return {
text: `Unrecognized thinking level "${directives.rawThinkLevel}". Valid levels: ${formatThinkingLevels(resolvedProvider, resolvedModel, ", ", thinkingCatalog)}.`,
text: `Unrecognized thinking level "${directives.rawThinkLevel}". Valid levels: default, ${formatThinkingLevels(resolvedProvider, resolvedModel, ", ", thinkingCatalog)}.`,
};
}
if (directives.hasVerboseDirective && !directives.verboseLevel) {
@@ -185,7 +188,11 @@ export async function handleDirectiveOnly(
text: `Unrecognized trace level "${directives.rawTraceLevel}". Valid levels: off, on, raw.`,
};
}
if (directives.hasFastDirective && directives.fastMode === undefined) {
if (
directives.hasFastDirective &&
directives.fastMode === undefined &&
!directives.clearFastMode
) {
if (
!directives.rawFastMode ||
normalizeLowercaseStringOrEmpty(directives.rawFastMode) === "status"
@@ -199,12 +206,12 @@ export async function handleDirectiveOnly(
return {
text: withOptions(
`Current fast mode: ${effectiveFastMode ? "on" : "off"}${sourceSuffix}.`,
"status, on, off",
"status, on, off, default",
),
};
}
return {
text: `Unrecognized fast mode "${directives.rawFastMode}". Valid levels: status, on, off.`,
text: `Unrecognized fast mode "${directives.rawFastMode}". Valid levels: status, on, off, default.`,
};
}
if (directives.hasReasoningDirective && !directives.reasoningLevel) {
@@ -351,8 +358,10 @@ export async function handleDirectiveOnly(
elevatedAllowed;
let modelSelectionUpdated = false;
const shouldPersistSessionEntry =
(directives.hasThinkDirective && Boolean(directives.thinkLevel)) ||
(directives.hasFastDirective && directives.fastMode !== undefined) ||
(directives.hasThinkDirective &&
(Boolean(directives.thinkLevel) || directives.clearThinkLevel)) ||
(directives.hasFastDirective &&
(directives.fastMode !== undefined || directives.clearFastMode)) ||
(directives.hasVerboseDirective &&
Boolean(directives.verboseLevel) &&
allowInternalVerbosePersistence) ||
@@ -364,16 +373,25 @@ export async function handleDirectiveOnly(
directives.hasQueueDirective ||
shouldRemapUnsupportedThinkLevel;
const fastModeChanged =
directives.hasFastDirective &&
directives.fastMode !== undefined &&
directives.fastMode !== currentFastMode;
(directives.hasFastDirective &&
directives.fastMode !== undefined &&
directives.fastMode !== currentFastMode) ||
(directives.clearFastMode && currentFastMode !== fastModeState.enabled);
let reasoningChanged =
directives.hasReasoningDirective && directives.reasoningLevel !== undefined;
if (shouldPersistSessionEntry) {
if (directives.hasThinkDirective && directives.thinkLevel && resolvedDirectiveThinkLevel) {
if (directives.clearThinkLevel) {
delete sessionEntry.thinkingLevel;
} else if (
directives.hasThinkDirective &&
directives.thinkLevel &&
resolvedDirectiveThinkLevel
) {
sessionEntry.thinkingLevel = resolvedDirectiveThinkLevel;
}
if (directives.hasFastDirective && directives.fastMode !== undefined) {
if (directives.clearFastMode) {
delete sessionEntry.fastMode;
} else if (directives.hasFastDirective && directives.fastMode !== undefined) {
sessionEntry.fastMode = directives.fastMode;
}
if (shouldRemapUnsupportedThinkLevel && remappedUnsupportedThinkLevel) {
@@ -488,7 +506,9 @@ export async function handleDirectiveOnly(
});
const parts: string[] = [];
if (directives.hasThinkDirective && directives.thinkLevel) {
if (directives.clearThinkLevel) {
parts.push("Thinking level reset to default.");
} else if (directives.hasThinkDirective && directives.thinkLevel) {
const displayedThinkLevel = resolvedDirectiveThinkLevel ?? directives.thinkLevel;
parts.push(
displayedThinkLevel === "off"
@@ -501,7 +521,9 @@ export async function handleDirectiveOnly(
);
}
}
if (directives.hasFastDirective && directives.fastMode !== undefined) {
if (directives.clearFastMode) {
parts.push(formatDirectiveAck("Fast mode reset to default."));
} else if (directives.hasFastDirective && directives.fastMode !== undefined) {
parts.push(
directives.fastMode
? formatDirectiveAck("Fast mode enabled.")
@@ -617,9 +639,10 @@ export async function handleDirectiveOnly(
parts.push(formatDirectiveAck(`Queue drop set to ${directives.dropPolicy}.`));
}
if (fastModeChanged) {
enqueueSystemEvent(`Fast mode ${sessionEntry.fastMode ? "enabled" : "disabled"}.`, {
const nextFastMode = directives.clearFastMode ? fastModeState.enabled : sessionEntry.fastMode;
enqueueSystemEvent(`Fast mode ${nextFastMode ? "enabled" : "disabled"}.`, {
sessionKey,
contextKey: `fast:${sessionEntry.fastMode ? "on" : "off"}`,
contextKey: `fast:${nextFastMode ? "on" : "off"}`,
});
}
const ack = parts.join(" ").trim();

View File

@@ -1331,6 +1331,22 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
expect(sessionStore["agent:main:dm:1"]?.thinkingLevel).toBe("off");
});
it("clears thinking override for default directives", async () => {
const sessionEntry = createSessionEntry({ thinkingLevel: "high" });
const sessionStore = { [sessionKey]: sessionEntry };
const result = await handleDirectiveOnly(
createHandleParams({
directives: parseInlineDirectives("/think default"),
sessionEntry,
sessionStore,
}),
);
expect(result?.text).toContain("Thinking level reset to default.");
expect(sessionEntry.thinkingLevel).toBeUndefined();
expect(sessionStore["agent:main:dm:1"]?.thinkingLevel).toBeUndefined();
});
it("reports current thinking status", async () => {
setDirectiveTestProviders([
{
@@ -1358,7 +1374,7 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
);
expect(result?.text).toContain("Current thinking level: low");
expect(result?.text).toContain("Options: off, minimal, low, medium, adaptive, high.");
expect(result?.text).toContain("Options: default, off, minimal, low, medium, adaptive, high.");
});
it("uses catalog reasoning metadata for provider-owned thinking levels", async () => {
@@ -1468,6 +1484,17 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
);
expect(offReply?.text).toContain("Fast mode disabled");
expect(sessionEntry.fastMode).toBe(false);
const defaultReply = await handleDirectiveOnly(
createHandleParams({
directives: parseInlineDirectives("/fast default"),
sessionEntry,
sessionStore,
currentFastMode: sessionEntry.fastMode,
}),
);
expect(defaultReply?.text).toContain("Fast mode reset to default");
expect(sessionEntry.fastMode).toBeUndefined();
});
it("persists and reports elevated-mode directives when allowed", async () => {

View File

@@ -1,5 +1,6 @@
import type { ExecAsk, ExecSecurity, ExecTarget } from "../../infra/exec-approvals.js";
import { extractModelDirective } from "../model.js";
import { isSessionDefaultDirectiveValue } from "../thinking.js";
import type {
ElevatedLevel,
ReasoningLevel,
@@ -25,6 +26,7 @@ export type InlineDirectives = {
hasThinkDirective: boolean;
thinkLevel?: ThinkLevel;
rawThinkLevel?: string;
clearThinkLevel: boolean;
hasVerboseDirective: boolean;
verboseLevel?: VerboseLevel;
rawVerboseLevel?: string;
@@ -34,6 +36,7 @@ export type InlineDirectives = {
hasFastDirective: boolean;
fastMode?: boolean;
rawFastMode?: string;
clearFastMode: boolean;
hasReasoningDirective: boolean;
reasoningLevel?: ReasoningLevel;
rawReasoningLevel?: string;
@@ -173,6 +176,7 @@ export function parseInlineDirectives(
hasThinkDirective,
thinkLevel,
rawThinkLevel,
clearThinkLevel: hasThinkDirective && isSessionDefaultDirectiveValue(rawThinkLevel),
hasVerboseDirective,
verboseLevel,
rawVerboseLevel,
@@ -182,6 +186,7 @@ export function parseInlineDirectives(
hasFastDirective,
fastMode,
rawFastMode,
clearFastMode: hasFastDirective && isSessionDefaultDirectiveValue(rawFastMode),
hasReasoningDirective,
reasoningLevel,
rawReasoningLevel,

View File

@@ -166,10 +166,21 @@ export async function persistInlineDirectives(params: {
directives.hasReasoningDirective && directives.reasoningLevel !== undefined;
let updated = false;
if (directives.hasThinkDirective && directives.thinkLevel) {
if (directives.clearThinkLevel) {
if (sessionEntry.thinkingLevel) {
delete sessionEntry.thinkingLevel;
updated = true;
}
} else if (directives.hasThinkDirective && directives.thinkLevel) {
sessionEntry.thinkingLevel = directives.thinkLevel;
updated = true;
}
if (directives.clearFastMode) {
if (sessionEntry.fastMode !== undefined) {
delete sessionEntry.fastMode;
updated = true;
}
}
if (
directives.hasVerboseDirective &&
directives.verboseLevel &&

View File

@@ -23,6 +23,7 @@ export function clearInlineDirectives(cleaned: string): InlineDirectives {
hasThinkDirective: false,
thinkLevel: undefined,
rawThinkLevel: undefined,
clearThinkLevel: false,
hasVerboseDirective: false,
verboseLevel: undefined,
rawVerboseLevel: undefined,
@@ -32,6 +33,7 @@ export function clearInlineDirectives(cleaned: string): InlineDirectives {
hasFastDirective: false,
fastMode: undefined,
rawFastMode: undefined,
clearFastMode: false,
hasReasoningDirective: false,
reasoningLevel: undefined,
rawReasoningLevel: undefined,

View File

@@ -334,8 +334,10 @@ export async function resolveReplyDirectives(params: {
: {
...parsedDirectives,
hasThinkDirective: false,
clearThinkLevel: false,
hasVerboseDirective: false,
hasFastDirective: false,
clearFastMode: false,
hasReasoningDirective: false,
reasoningLevel: undefined,
rawReasoningLevel: undefined,
@@ -422,10 +424,11 @@ export async function resolveReplyDirectives(params: {
groupResolution,
});
const defaultActivation = defaultGroupActivation(requireMention);
const sessionThinkLevel = directives.clearThinkLevel
? undefined
: (targetSessionEntry?.thinkingLevel as ThinkLevel | undefined);
const resolvedThinkLevel =
normalizeThinkLevel(opts?.thinkingLevelOverride) ??
directives.thinkLevel ??
(targetSessionEntry?.thinkingLevel as ThinkLevel | undefined);
normalizeThinkLevel(opts?.thinkingLevelOverride) ?? directives.thinkLevel ?? sessionThinkLevel;
const resolvedFastMode =
opts?.fastModeOverride ??
directives.fastMode ??
@@ -434,7 +437,7 @@ export async function resolveReplyDirectives(params: {
provider,
model,
agentId,
sessionEntry: targetSessionEntry,
sessionEntry: directives.clearFastMode ? undefined : targetSessionEntry,
}).enabled;
const resolvedVerboseLevel =
@@ -537,7 +540,7 @@ export async function resolveReplyDirectives(params: {
const thinkingExplicitlySet =
directives.thinkLevel !== undefined ||
targetSessionEntry?.thinkingLevel !== undefined ||
sessionThinkLevel !== undefined ||
agentCfg?.thinkingDefault !== undefined;
// When neither directive nor session nor agent set reasoning, default to model capability

View File

@@ -2103,7 +2103,7 @@ describe("buildHelpMessage", () => {
});
it("includes /fast in help output", () => {
expect(buildHelpMessage()).toContain("/fast status|on|off");
expect(buildHelpMessage()).toContain("/fast status|on|off|default");
});
it("includes raw trace mode in help output", () => {

View File

@@ -83,6 +83,14 @@ export function normalizeThinkLevel(raw?: string | null): ThinkLevel | undefined
return undefined;
}
export function isSessionDefaultDirectiveValue(raw?: string | null): boolean {
const key = normalizeOptionalLowercaseString(raw);
if (!key) {
return false;
}
return ["default", "inherit", "inherited", "clear", "reset", "unpin"].includes(key);
}
export function formatXHighModelHint(): string {
return "provider models that advertise xhigh reasoning";
}

View File

@@ -8,6 +8,7 @@ import {
import type { ThinkLevel, ThinkingCatalogEntry } from "./thinking.shared.js";
export {
formatXHighModelHint,
isSessionDefaultDirectiveValue,
normalizeElevatedLevel,
normalizeFastMode,
normalizeNoticeLevel,