Files
paseo/packages/app/src/command-center/agent-control-registration.tsx
T
35f985baff Switch reasoning, mode, plan, and fast from the Command Center (#2274)
* 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>
2026-07-31 17:37:04 +02:00

157 lines
4.6 KiB
TypeScript

import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import type {
AgentFeature,
AgentMode,
AgentProvider,
AgentSelectOption,
} from "@getpaseo/protocol/agent-types";
import type { AgentProviderDefinition } from "@getpaseo/protocol/provider-manifest";
import {
getAgentFeatureIcon,
getAgentModeIcon,
PlanModeIcon,
ThinkingIcon,
} from "@/agent-controls/icons";
import { getProviderIcon } from "@/components/provider-icons";
import type { ProviderSelectorProvider } from "@/provider-selection/provider-selection";
import {
buildAgentControlContributions,
buildAgentControlContributionLabels,
type AgentControlContributionSource,
} from "./agent-control-contributions";
import { getCommandCenterIcon } from "./icon";
import { useCommandCenterActions } from "./provider";
export interface AgentControlCommandCenterSource {
serverId: string;
ownerKey: string;
provider: string | null | undefined;
providerDefinitions: AgentProviderDefinition[];
models: {
providers: readonly ProviderSelectorProvider[];
selectedProvider: string | null | undefined;
selectedModelId: string | null | undefined;
select(provider: AgentProvider, modelId: string): void | Promise<void>;
};
thinking: {
options: readonly AgentSelectOption[] | null | undefined;
selectedId: string | null | undefined;
select(optionId: string): void | Promise<void>;
};
modes?: {
options: readonly AgentMode[];
selectedId: string | null | undefined;
select(modeId: string): void | Promise<void>;
};
features: {
list: readonly AgentFeature[] | undefined;
set?: (featureId: string, value: unknown) => void | Promise<void>;
};
}
function ignoreAgentFeatureChange(): void {
return;
}
function resolveDefaultModeId(
provider: string | null | undefined,
providerDefinitions: AgentProviderDefinition[],
): string | null {
return (
providerDefinitions.find((definition) => definition.id === provider)?.defaultModeId ?? null
);
}
function buildModeContributionSource(
options: readonly AgentMode[] | undefined,
selectedId: string | null | undefined,
select: ((modeId: string) => void | Promise<void>) | undefined,
defaultModeId: string | null,
): Pick<AgentControlContributionSource, "modes"> {
if (!options || !select) return {};
return {
modes: {
options,
selectedId: selectedId ?? null,
defaultModeId,
select,
},
};
}
export function useAgentControlCommandCenterActions(input: {
sourceId: string;
enabled: boolean;
controls: AgentControlCommandCenterSource;
}): void {
const { t } = useTranslation();
const { controls } = input;
const { features, models, modes, thinking } = controls;
const actions = useMemo(
() =>
buildAgentControlContributions({
serverId: controls.serverId,
ownerKey: controls.ownerKey,
provider: controls.provider ?? null,
labels: buildAgentControlContributionLabels(t),
icons: {
provider: (provider) => getCommandCenterIcon(getProviderIcon(provider)),
thinking: getCommandCenterIcon(ThinkingIcon),
planMode: getCommandCenterIcon(PlanModeIcon),
mode: (modeId) =>
getCommandCenterIcon(
getAgentModeIcon(controls.provider ?? "", modeId, controls.providerDefinitions),
),
feature: (feature) => getCommandCenterIcon(getAgentFeatureIcon(feature.icon)),
},
models: {
providers: models.providers,
selectedProvider: models.selectedProvider ?? null,
selectedModelId: models.selectedModelId ?? null,
select: models.select,
},
thinking: {
options: thinking.options ?? [],
selectedId: thinking.selectedId ?? null,
select: thinking.select,
},
...buildModeContributionSource(
modes?.options,
modes?.selectedId,
modes?.select,
resolveDefaultModeId(controls.provider, controls.providerDefinitions),
),
features: {
list: features.set ? (features.list ?? []) : [],
set: features.set ?? ignoreAgentFeatureChange,
},
}),
[
controls.ownerKey,
controls.provider,
controls.providerDefinitions,
controls.serverId,
features.list,
features.set,
models.providers,
models.select,
models.selectedModelId,
models.selectedProvider,
modes?.options,
modes?.select,
modes?.selectedId,
thinking.options,
thinking.select,
thinking.selectedId,
t,
],
);
useCommandCenterActions({
sourceId: input.sourceId,
enabled: input.enabled,
actions,
});
}