Model picker
ProWhich model the next message uses, as a small menu for Composer's tools slot. It takes the same ModelOption list as ModelSettings: models are grouped by vendor with their relative cost, and one whose zero-retention terms haven't been attested stays in the list, says so, and can't be picked. The button shows the model the app says is in use, or "Choose a model" when there is none; nothing is chosen for the person. When they can't change it, locked says why.
Version 5.2.0· other versions
This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0 and 2.8.0: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/model-picker
Brings in: bidi, dropdown-menu, know, locale, locked, tokens, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import { Composer } from "@/components/candor/composer"
import { ModelPicker } from "@/components/candor/model-picker"
import type { ModelOption } from "@/lib/candor/know"
/** The same list ModelSettings takes: every model the app offers, attested or not. */
const models: ModelOption[] = [
{ id: "claude-haiku", vendor: "Anthropic", name: "Claude Haiku", cost: 1, zdr: "attested", note: "Quick lookups" },
{ id: "claude-sonnet", vendor: "Anthropic", name: "Claude Sonnet", cost: 2, zdr: "attested", note: "Most work" },
{ id: "claude-opus", vendor: "Anthropic", name: "Claude Opus", cost: 4, zdr: "attested", note: "Design and review" },
{ id: "gemini-pro", vendor: "Google", name: "Gemini Pro", cost: 3, zdr: "not-attested" },
]
export default function Example() {
const [value, setValue] = React.useState("")
const [model, setModel] = React.useState("claude-sonnet")
return (
<div className="flex max-w-2xl flex-col gap-6">
<Composer value={value} onValueChange={setValue} onSubmit={() => setValue("")} tools={<ModelPicker models={models} value={model} onValueChange={setModel} />} />
{/* When the person can't change it, the picker stays and says why. */}
<Composer
value=""
onValueChange={() => {}}
onSubmit={() => {}}
tools={<ModelPicker models={models} value="claude-sonnet" onValueChange={() => {}} locked="Your workspace admin sets the model for this project." />}
/>
</div>
)
}<ModelPicker>
| Prop | Type | Default | Description |
|---|---|---|---|
| modelsrequired | ModelOption[] | — | Every model the app offers, from any vendor: the same list ModelSettings takes. |
| value | string | undefined | — | The id of the model in use, from your app. Without one, the button says "Choose a model". |
| onValueChangerequired | (id: string) => void | — | Called with the id of the model the person picks. Never called for a model that isn't attested. |
| locked | string | null | undefined | — | Why the person can't change the model, e.g. "Your workspace admin sets the model." The button stays, locked, and says it. `null` or left out: unlocked. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under modelPicker in <LocaleProvider strings={{ … }}>; the table is exported as modelPickerStrings.
| Key | English |
|---|---|
| label | Model: {name} |
| choose | Choose a model |
| notAttested | Zero-retention terms not attested |
| notAvailable | Not available until {vendor}’s zero-retention terms are attested. |
| cost | { one: "cost {count} of 4", other: "cost {count} of 4" } |
Motion
| Moment | Family | What it does |
|---|---|---|
| tint | tint | The button's background changes when the pointer is over it; a locked one doesn't change. |
Set with --cd-motion-model-picker-<moment>-* in your brand file; the families are in the design reference.
Types from other items
The props above take these. Each is defined by another item; import it from the path shown.
- ModelOption from @/lib/candor/know
{ id: string; vendor: ModelVendor; name: string; /** One line on what it's good for. */ note?: string | undefined; /** Relative cost, 1 (cheapest) to 4. */ cost: 1 | 2 | 3 | 4; /** The vendor's zero-retention contract has been attested by an operator. */ zdr: "attested" | "not-attested"; }- ModelVendor from @/lib/candor/know
- The four vendors Candor lists first, in this order. Any other vendor ("Meta", "Mistral", "Local") is listed after them, by the name you give.
"Anthropic" | "Google" | "OpenAI" | "xAI" | (string & {})