/** Accessible HUX-06 mode intent selector. The feature is default-off. */ import { useMemo } from "react"; import { buildModeRequest, friendlyModesEnabled, normalizeAdvancedRoutes, normalizeModeCatalog, normalizeResolvedRoute, } from "./model.ts"; import type { FriendlyModeIntent, FriendlyModeName, RawAdvancedRouteChoice, RawModeIntent, RawResolvedRoute, } from "./types.ts"; interface FriendlyModeSelectorProps { flags?: Iterable; modes: readonly RawModeIntent[]; selectedMode: FriendlyModeName; advancedRoutes?: readonly RawAdvancedRouteChoice[]; resolvedRoute?: RawResolvedRoute; disabled?: boolean; onChange(intent: FriendlyModeIntent): void; } const MODE_HELP: Readonly> = { fast: "Quick, direct answers with light reasoning.", thoughtful: "More reasoning for careful decisions.", research: "Source-backed investigation with citations.", create: "Generative work with artifact support.", private: "Local-only processing with ephemeral retention.", }; const PROVIDER_LABELS = { codex: "OpenAI", claude: "Anthropic", local: "Local", } as const; /** Render nothing unless HUX-11 and HUX-06 are both explicitly enabled. */ export function FriendlyModeSelector({ flags, modes, selectedMode, advancedRoutes = [], resolvedRoute, disabled = false, onChange, }: FriendlyModeSelectorProps) { const enabled = friendlyModesEnabled(flags); const catalog = useMemo(() => normalizeModeCatalog(modes), [modes]); const choices = useMemo( () => normalizeAdvancedRoutes(advancedRoutes), [advancedRoutes], ); const resolved = useMemo( () => normalizeResolvedRoute(resolvedRoute), [resolvedRoute], ); if (!enabled) return null; if (!catalog) { return (

Mode choices are unavailable because their safety contract could not be verified.

); } const selected = catalog.find((mode) => mode.mode === selectedMode); if (!selected) { return (

The selected mode could not be verified. No routing change was made.

); } const compatibleChoices = choices.filter((choice) => selected.mode === "private" ? choice.localOnly && choice.provider === "local" : !choice.localOnly && selected.constraints.providers.includes(choice.provider), ); return (

Response mode

Choose the intent; Switchyard selects from the allowed pool.

{selected.label}
Choose a response mode {catalog.map((mode) => ( ))}
Advanced routing details
Allowed pools
{selected.constraints.providers .map((provider) => PROVIDER_LABELS[provider]) .join(" + ")}
Requested route
{selected.switchyard.route_id}
{resolved?.target && (
Resolved route
{resolved.target}
)} {resolved?.provider && (
Resolved provider
{PROVIDER_LABELS[resolved.provider]}
)} {resolved?.effort && (
Resolved effort
{resolved.effort}
)}

Pinning bypasses automatic selection for this choice. Automatic modes otherwise keep both OpenAI and Anthropic eligible.

); }