* Switch reasoning, mode, plan, and fast from the Command Center Extend the Command Center (Cmd-K) with selectors for a focused agent's Thinking (reasoning effort), access Mode, Plan mode, and Fast mode, mirroring the model switcher. Typing surfaces tiered "<Setting> › <Value>" breadcrumb rows with icons and a check on the current value, for both a running agent and a new draft tab. Rows only appear while typing, so the default palette is unchanged. - Thinking and Mode are multi-option selects; Plan mode and Fast mode are On/Off toggles. - Plan mode is dual-natured: a permission mode for Claude/Copilot/OpenCode (excluded from the Mode list, given its own toggle) and the plan_mode feature for Codex. Fast mode drives the fast_mode feature (model-gated). - All logic lives in command-center/agent-setting-contributions.ts as pure, unit-tested builders, with a small icon helper and a hook that registers the running-agent selectors; the draft registers from its composer tab. No changes to the command palette component and no protocol changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Unify Command Center agent controls * refactor: clarify agent control ownership * refactor(app): tighten command center agent controls --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
168 lines
4.8 KiB
TypeScript
168 lines
4.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
getFeatureHighlightColor,
|
|
getFeatureTooltip,
|
|
getAgentControlHintKey,
|
|
normalizeModelId,
|
|
resolveAgentModelSelection,
|
|
} from "./utils";
|
|
|
|
describe("getAgentControlHintKey", () => {
|
|
it("returns translation keys for each editable agent control hint", () => {
|
|
expect(getAgentControlHintKey("thinking")).toBe("agentControls.hints.thinking");
|
|
expect(getAgentControlHintKey("model")).toBe("agentControls.hints.model");
|
|
expect(getAgentControlHintKey("mode")).toBe("agentControls.hints.mode");
|
|
});
|
|
});
|
|
|
|
describe("feature metadata helpers", () => {
|
|
it("prefers explicit feature tooltip copy", () => {
|
|
expect(
|
|
getFeatureTooltip({
|
|
label: "Plan",
|
|
tooltip: "Toggle plan mode",
|
|
}),
|
|
).toBe("Toggle plan mode");
|
|
});
|
|
|
|
it("falls back to the feature label when no tooltip is provided", () => {
|
|
expect(
|
|
getFeatureTooltip({
|
|
label: "Custom",
|
|
}),
|
|
).toBe("Custom");
|
|
});
|
|
|
|
it("maps feature highlight colors by feature id", () => {
|
|
expect(getFeatureHighlightColor("fast_mode")).toBe("yellow");
|
|
expect(getFeatureHighlightColor("plan_mode")).toBe("blue");
|
|
expect(getFeatureHighlightColor("other")).toBe("default");
|
|
});
|
|
});
|
|
|
|
describe("normalizeModelId", () => {
|
|
it("treats empty values as unset", () => {
|
|
expect(normalizeModelId("")).toBeNull();
|
|
expect(normalizeModelId(undefined)).toBeNull();
|
|
});
|
|
|
|
it("returns trimmed model ids", () => {
|
|
expect(normalizeModelId(" gpt-5.1-codex ")).toBe("gpt-5.1-codex");
|
|
expect(normalizeModelId(" default ")).toBe("default");
|
|
});
|
|
});
|
|
|
|
describe("resolveAgentModelSelection", () => {
|
|
it("prefers runtime model over configured model", () => {
|
|
const selection = resolveAgentModelSelection({
|
|
models: [
|
|
{
|
|
id: "a",
|
|
provider: "codex",
|
|
label: "Model A",
|
|
thinkingOptions: [{ id: "low", label: "Low" }],
|
|
defaultThinkingOptionId: "low",
|
|
},
|
|
],
|
|
runtimeModelId: "a",
|
|
configuredModelId: "b",
|
|
explicitThinkingOptionId: null,
|
|
});
|
|
|
|
expect(selection.activeModelId).toBe("a");
|
|
expect(selection.displayModel).toBe("Model A");
|
|
expect(selection.selectedThinkingId).toBe("low");
|
|
});
|
|
|
|
it("uses explicit thinking option when provided", () => {
|
|
const selection = resolveAgentModelSelection({
|
|
models: [
|
|
{
|
|
id: "a",
|
|
provider: "codex",
|
|
label: "Model A",
|
|
thinkingOptions: [
|
|
{ id: "low", label: "Low" },
|
|
{ id: "high", label: "High" },
|
|
],
|
|
defaultThinkingOptionId: "low",
|
|
},
|
|
],
|
|
runtimeModelId: "a",
|
|
configuredModelId: null,
|
|
explicitThinkingOptionId: "high",
|
|
});
|
|
|
|
expect(selection.selectedThinkingId).toBe("high");
|
|
expect(selection.displayThinking).toBe("High");
|
|
});
|
|
|
|
it("formats raw thinking labels in the selected model display", () => {
|
|
const selection = resolveAgentModelSelection({
|
|
models: [
|
|
{
|
|
id: "a",
|
|
provider: "claude",
|
|
label: "Model A",
|
|
thinkingOptions: [
|
|
{ id: "none", label: "none" },
|
|
{ id: "xhigh", label: "xhigh" },
|
|
],
|
|
},
|
|
],
|
|
runtimeModelId: "a",
|
|
configuredModelId: null,
|
|
explicitThinkingOptionId: "xhigh",
|
|
});
|
|
|
|
expect(selection.selectedThinkingId).toBe("xhigh");
|
|
expect(selection.displayThinking).toBe("Extra high");
|
|
});
|
|
|
|
it("falls back to the provider default model label instead of Auto", () => {
|
|
const selection = resolveAgentModelSelection({
|
|
models: [
|
|
{
|
|
id: "a",
|
|
provider: "codex",
|
|
label: "Model A",
|
|
isDefault: true,
|
|
thinkingOptions: [{ id: "low", label: "Low" }],
|
|
defaultThinkingOptionId: "low",
|
|
},
|
|
],
|
|
runtimeModelId: null,
|
|
configuredModelId: null,
|
|
explicitThinkingOptionId: null,
|
|
});
|
|
|
|
expect(selection.displayModel).toBe("Model A");
|
|
expect(selection.displayThinking).toBe("Low");
|
|
});
|
|
|
|
it("prefers the configured model when runtime model is not in the model list", () => {
|
|
const selection = resolveAgentModelSelection({
|
|
models: [
|
|
{
|
|
id: "default",
|
|
provider: "claude",
|
|
label: "Default (Sonnet 4.6)",
|
|
isDefault: true,
|
|
thinkingOptions: [
|
|
{ id: "low", label: "Low" },
|
|
{ id: "medium", label: "Medium" },
|
|
],
|
|
},
|
|
],
|
|
runtimeModelId: "claude-sonnet-4-6-20260101",
|
|
configuredModelId: "default",
|
|
explicitThinkingOptionId: null,
|
|
});
|
|
|
|
expect(selection.activeModelId).toBe("default");
|
|
expect(selection.displayModel).toBe("Default (Sonnet 4.6)");
|
|
expect(selection.selectedThinkingId).toBe("low");
|
|
expect(selection.displayThinking).toBe("Low");
|
|
});
|
|
});
|