Skip to content

Model picker ​

Which model answers and how. The composer draws all of this inside RunSettings, behind one pill; ModelPicker and ModelOptionControl are for a form outside a chat, such as the defaults of a new chat.

tsx
import { ModelPicker } from '@adecore/agents-react/chat/ui/Pickers';
import { ModelOptionControl } from '@adecore/agents-react/agents/ModelOptionControl';
tsx
import { useState } from 'react';
import type { AgentKind, ModelSelection } from '@adecore/agent-contracts';
import { ModelOptionControl } from '@adecore/agents-react/agents/ModelOptionControl';
import { carryOptions } from '@adecore/agents-react/agents/model-options';
import { ModelPicker } from '@adecore/agents-react/chat/ui/Pickers';
import { PROVIDERS } from '../shared/agents-data.ts';
import '../shared/agents-host.ts';

export default function ModelPickerDemo() {
    const [provider, setProvider] = useState<AgentKind>('claude');
    const [selection, setSelection] = useState<ModelSelection>({ model: 'sonnet', options: {} });
    const [open, setOpen] = useState(false);
    const model = PROVIDERS.find((entry) => entry.kind === provider)?.models.find((entry) => entry.slug === selection.model);

    return (
        <div className="flex w-full max-w-sm flex-col gap-3">
            <ModelPicker
                providers={PROVIDERS}
                provider={provider}
                selection={selection}
                open={open}
                onOpenChange={setOpen}
                onChange={(next, slug) => {
                    const target = PROVIDERS.find((entry) => entry.kind === next)?.models.find((entry) => entry.slug === slug);
                    setProvider(next);
                    setSelection({ model: slug, options: carryOptions(selection.options, target) });
                }}
                kbd={null}
                side="bottom"
                trigger="chip"
            />
            {model?.options.map((option) => (
                <ModelOptionControl
                    key={option.id}
                    option={option}
                    options={selection.options}
                    layout="row"
                    onChange={(value) => setSelection({ ...selection, options: { ...selection.options, [option.id]: value } })}
                />
            ))}
        </div>
    );
}

ModelPicker ​

A trigger with the CLI's mark and the model's short name, and a popup with a search field, a group per CLI and the legacy models behind an expander. Passing more than one CLI is how a chat that has not spoken picks its CLI; pass one and the group headers go.

PropType
providersProviderInfo[]Whose models may be picked.
providerAgentKindThe CLI of the current selection.
selectionModelSelection
open, onOpenChangeControlled, so a command can open the same popup.
onChange(provider: AgentKind, model: string) => void
kbdstring | nullThe command named in the tooltip, /model by default; null outside a chat.
side'top' | 'bottom'Where the popup opens. top by default.
trigger'plain' | 'chip'chip names the CLI beside the model on a ground of its own, for a form.
finalFocusRefObject<HTMLElement | null>Where the focus goes when the popup closes.
footerReactNodeA note under the list.

ModelOptionControl ​

One of a model's own options, such as effort, drawn from its ModelOptionDescriptor: a Switch for a boolean, a Segmented for up to three choices in the row layout, a Select otherwise. It reads options[option.id] and calls onChange with the new value. With defaultLabel a choice gets an item that leaves it to the model, answered as undefined.

optionValue(option, options) answers the value an option runs at: the one picked when it still fits, else the model's default. carryOptions(options, model) keeps the options the next model also offers, for a switch between models.

Names ​

modelName(slug, models) answers a model's name from the catalog, or makes one from the slug. useModelName(provider, slug) does the same from the scope's CLIs, and shortModelName(name, models) drops the prefix all of a CLI's models share. agentChipOf and modelNameFromSlug are the parts.

Run settings and accounts ​

RunSettings is the pill under the composer: the model, its options, the permission mode with what the CLI confirmed, the context the chat holds with its breakdown, compacting, and the account when the CLI has more than one. Its props mirror the composer's state; draw a Composer rather than this alone. RUNTIME_MODES, runtimeModeLabel(mode) and runtimeModeHint(mode) name the modes.

useAccountChoice(kind, account) answers the accounts a chat may pick, or null while the CLI has only one. accountFor, startingSelection and the other helpers in chat/preferences read the remembered model and account per CLI and per host.

Licenses and third-party notices are listed in each package.