# zidane-ui/chat/composer

> The prompt box, model and reasoning pickers, attachment helpers and mention suggestions.

Import: `import { … } from 'zidane-ui/chat/composer'`. Source: [ui/src/chat/composer/index.ts](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/index.ts).

Use this entry point for the input side of a chat. `Composer` is the prompt box and needs no host. `HostComposer` binds it to a `ChatHost`. The pickers, the context meter (`ContextOrb`, `ContextBreakdown`), the badge strip (`ComposerBadges`, `orderComposerBadges`, `mergeBadgeOrder`), the catalog helpers and the attachment readers are exported for custom layouts. See [Composer](https://zidane.si/docs/ui-composer.md).

```tsx
import { Composer } from 'zidane-ui/chat/composer'
import { useState } from 'react'

export function Prompt() {
  const [running, setRunning] = useState(false)
  return (
    <Composer
      running={running}
      onSend={({ prompt }) => {
        setRunning(true)
        console.log(prompt)
        setTimeout(() => setRunning(false), 1000)
      }}
      onStop={() => setRunning(false)}
    />
  )
}
```

## Components

### `AgentPicker`

Component.

Renders the agent profile pill of the composer controls and its menu, with the current profile checked.

```ts
function AgentPicker(props: AgentPickerProps): Element | null
```

**Parameters**

- `props` (`AgentPickerProps`): The [`AgentPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#AgentPickerProps).

**Returns** `Element | null`

**Props**

- `align?` (`Align`, default `'start'`): How the menu lines up along the trigger's edge.
- `className?` (`string`): Extra classes on the root element (the default trigger pill; ignored with `trigger`).
- `draft?` (`boolean`): No session yet: the pick applies to the next chat.
- `fallback?` (`string`): The profile the pill names when `value` is not offered (a session saved on a removed profile).
- `onOpenChange?` (`(open: boolean) => void`): Called when the menu opens or closes.
- `profiles` (`readonly AgentProfile[]`): The profiles to offer. With none, the picker renders nothing.
- `side?` (`Side`, default `'top'`): Preferred side of the trigger for the menu. It flips when it does not fit.
- `style?` (`CSSProperties`): Inline styles on the root element (the default trigger pill; ignored with `trigger`).
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the trigger in place of the pill (a settings row): spread the props onto it.
- `value` (`string`): The current profile id.
- `onChange` (`(id: string) => void | Promise<void>`): Called with the picked profile id. Return a promise to keep the menu open and show "switching" on the picked row until it settles.

Source: [ui/src/chat/composer/AgentPicker.tsx:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AgentPicker.tsx#L69)

### `AgentPickerDialog`

Component.

The agent dialog (see the header).

```ts
function AgentPickerDialog(props: AgentPickerDialogProps): Element
```

**Parameters**

- `props` (`AgentPickerDialogProps`): The [`AgentPickerDialogProps`](https://zidane.si/docs/reference/ui-chat-composer.md#AgentPickerDialogProps).

**Returns** `Element`

**Props**

- `onClose` (`() => void`): Closes the dialog.
- `onCommitted?` (`() => void | Promise<void>`): Called once a switch is written (refresh the app's session list).
- `session` (`ComposerSessionView`): The session whose agent is switched.

Source: [ui/src/chat/composer/AgentPickerDialog.tsx:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AgentPickerDialog.tsx#L38)

### `ApprovalDock`

Component.

The session's next approval, docked above the prompt (see the header).

```ts
function ApprovalDock(props: ApprovalDockProps): Element
```

**Parameters**

- `props` (`ApprovalDockProps`): The [`ApprovalDockProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ApprovalDockProps).

**Returns** `Element`

**Props**

- `sessionId` (`string | null`): The conversation whose next approval shows, `null` for a draft.

Source: [ui/src/chat/composer/ApprovalDock.tsx:56](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ApprovalDock.tsx#L56)

### `ArchivedBanner`

Component.

The archived session's banner in place of its composer.

```ts
function ArchivedBanner(props: ArchivedBannerProps): Element
```

**Parameters**

- `props` (`ArchivedBannerProps`): The [`ArchivedBannerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ArchivedBannerProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the tray.
- `onUnarchive` (`() => void`): Unarchives the session.
- `style?` (`CSSProperties`): Inline styles on the tray.

Source: [ui/src/chat/composer/ArchivedBanner.tsx:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ArchivedBanner.tsx#L26)

### `AttachmentNotices`

Component.

The files the composer just refused, one line each, until dismissed. Nothing renders without any.

```ts
function AttachmentNotices(props: AttachmentNoticesProps): Element | null
```

**Parameters**

- `props` (`AttachmentNoticesProps`): The `notices` to show, `onDismiss`, called by the close button, and an optional `className`.

**Returns** `Element | null`

**Props**

- `className?` (`string`): Where it sits. Default: inset in the composer card, above the tiles.
- `notices` (`readonly string[]`): One sentence per refused file.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onDismiss` (`() => void`): Called when the user closes the notice.

Source: [ui/src/chat/composer/attachments.tsx:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachments.tsx#L69)

### `AttachmentRow`

Component.

A row of staged attachment tiles that collapses when its last tile leaves.

```ts
function AttachmentRow(props: AttachmentRowProps): Element
```

**Parameters**

- `props` (`AttachmentRowProps`): The attachments, the removal state and the handlers.

**Returns** `Element`

**Props**

- `attachmentLabel?` (`AttachmentLabelFn`): The icon and name a file tile shows. Default: [`defaultAttachmentTileLabel`](https://zidane.si/docs/reference/ui-chat-composer.md#defaultAttachmentTileLabel).
- `attachments` (`readonly ComposerAttachment[]`): The staged attachments, in order.
- `className?` (`string`): Classes merged on the root.
- `exitingIds` (`Set<string>`): Ids of tiles leaving (`useAttachmentRemoval`).
- `onExited` (`(id: string) => void`): A leaving tile finished its exit.
- `onOpenLightbox` (`(id: string, origin: HTMLElement) => void`): Opens the lightbox on a tile, from its element.
- `onRemove` (`(id: string) => void`): Starts removing a tile.
- `style?` (`CSSProperties`): Styles on the root.

Source: [ui/src/chat/composer/AttachmentTiles.tsx:105](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AttachmentTiles.tsx#L105)

### `AttachmentTiles`

Component.

Renders the composer's attachments as a row of tiles: image thumbnails and file tiles, each with a remove button.

```ts
function AttachmentTiles(props: AttachmentTilesProps): Element | null
```

**Parameters**

- `props` (`AttachmentTilesProps`): Tiles props: `attachments`, `onRemove`, and `onOpen`.

**Returns** `Element | null`

**Props**

- `attachments` (`readonly ComposerAttachment[]`): The attachments to show. With none, nothing renders.
- `className?` (`string`): Extra classes on the root element.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onOpen` (`(id: string, origin: HTMLElement) => void`): Called with the attachment id and the clicked element when the user opens a preview. Only images, PDFs and text-like files can be opened.
- `onRemove` (`(id: string) => void`): Called with the attachment id when the user removes a tile.

Source: [ui/src/chat/composer/attachments.tsx:112](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachments.tsx#L112)

### `Composer`

Component.

Renders the chat prompt box: a text editor with staged attachments, a controls row, and Send or Stop. Enter sends, Shift+Enter adds a line, Escape stops a running agent, and the arrow keys recall earlier prompts.

```ts
const Composer: ForwardRefExoticComponent<ComposerProps & RefAttributes<ComposerHandle>>
```

**Props**

- `ariaLabel?` (`string`): The textbox's accessible name (default: the `composerLabel` label).
- `attachments?` (`boolean`): Paste, drop and pick images, PDFs and text files.
- `autoFocus?` (`boolean`, default `false`): Focuses the editor on mount, with the caret at the end.
- `badges?` (`readonly ComposerBadge[]`): The badge strip at the top of the tray ring, above the card, in display order (see `ComposerBadges`).
- `badgesKey?` (`string`): What the badges belong to (a session id): a new key shows its badges without animating them.
- `below?` (`ReactNode`): A band under the card, inside the tray ring (the desktop app's git bar).
- `className?` (`string`): Extra class names for the composer's root element.
- `commands?` (`SuggestionSource`): `/` completions, at the start of the prompt.
- `defaultAttachments?` (`readonly ComposerAttachment[]`): Attachments staged on mount (a restored draft).
- `defaultValue?` (`string`): Initial text of an uncontrolled draft.
- `delivery?` (`MessageDelivery`, default `'queue'`): What Enter does with the draft while `running`: `steer` it into the run or `queue` it for when the run ends.
  Alt+Enter does the other. Pass the user's "Messages during a run" setting.
- `disabled?` (`boolean`, default `false`): Makes the editor read-only and disables sending and attaching.
- `footer?` (`ReactNode`): Controls after the attach button (pickers).
- `history?` (`readonly string[]`): Earlier prompts for ↑ / ↓, oldest first. Absent: what this composer sent while mounted.
- `mentions?` (`SuggestionSource`): `@` completions.
- `onBadgesReorder?` (`(ids: readonly string[]) => void`): Makes the badges draggable; receives every badge id in the new order.
- `placeholder?` (`string`): Placeholder shown while the draft is empty. Default: the `composerPlaceholder` label.
- `running?` (`boolean`): A run is in flight: Enter steers or queues (`delivery`), Escape and the button stop.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`): Controls at the end of the controls row, before Send (a context meter).
- `value?` (`string`): Controlled text of the draft. Use with `onChange`. Omit for an uncontrolled draft.
- `onChange?` (`(text: string) => void`): Called with the draft's text each time it changes.
- `onError?` (`(error: unknown) => void`): The send handler threw (the draft is already back). Absent: the composer shows the error itself.
- `onSend` (`(input: ComposerSubmit) => ComposerResult`): Called when the user sends the draft with Enter or the Send button, also while `running` (see `ComposerSubmit.delivery`). Return `false` or reject to put the draft back.
- `onStop?` (`() => void`): Called when the user stops the running agent with Escape or the Stop button. Without it the composer offers no stop.

Source: [ui/src/chat/composer/Composer.tsx:154](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/Composer.tsx#L154)

### `ComposerBadges`

Component.

Renders the composer's badge strip (see the module comment). Place it as
the first child of the composer's tray ring, before the card.

```ts
function ComposerBadges(props: ComposerBadgesProps): Element
```

**Parameters**

- `props` (`ComposerBadgesProps`): The [`ComposerBadgesProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerBadgesProps).

**Returns** `Element`

**Props**

- `badges` (`readonly ComposerBadge[]`): The badges, in display order. An empty list closes the band.
- `className?` (`string`): Extra classes on the band.
- `label?` (`string`): Accessible name of the strip. Default: the `composerBadges` label.
- `onReorder?` (`(ids: readonly string[]) => void`): Makes badges draggable (and movable with Alt+Shift+←/→); receives every id in the new order, once per move.
- `resetKey?` (`string | null`): What the badges belong to (a session id). A new key shows its badges as
  they are, without animating them in or the previous ones out.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ComposerBadges.tsx:110](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerBadges.tsx#L110)

### `ComposerControls`

Component.

The left cluster: agent, model and options pickers (see the header).

```ts
function ComposerControls(props: ComposerControlsProps): Element
```

**Parameters**

- `props` (`ComposerControlsProps`): The [`ComposerControlsProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerControlsProps).

**Returns** `Element`

**Props**

- `activeEnabledOptions` (`Record<string, boolean>`): The session's enabled options.
- `activeModelOptions` (`readonly ComposerModelOption[]`): The feature toggles the session's model declares.
- `activeSupportsReasoning` (`boolean`): Whether the session's model has a reasoning knob (a draft looks its default model up in the catalog).
- `defaults` (`ComposerDefaults`): The next new chat's defaults.
- `hostId?` (`string | null`): The server the session (or draft) runs on: the pickers list its models. `null`: this computer.
- `images?` (`HostModelImages | null`): The model picker's Image tab. Absent: none.
- `modelId` (`string | null`): The session's model (its own pick, or the one its context status reports).
- `modelShortcut?` (`ReactNode`): The model picker's keyboard shortcut, for its tooltip.
- `onCommitted?` (`() => void | Promise<void>`): Called once a session write lands (refresh the app's session list).
- `onDefaultAgentChange` (`(id: string) => void`): Sets the next new chat's agent.
- `onDefaultModel` (`SetDefaultModel`): Sets the next new chat's model.
- `providerKey` (`string | null`): That model's provider.
- `retry?` (`ReactNode`): Shown between the agent and the model pills (a retry pill).
- `serving?` (`{ model: string; provider: string } | null`): The model serving the run after a fallback.
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft.

Source: [ui/src/chat/composer/ComposerControls.tsx:87](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerControls.tsx#L87)

### `ComposerDock`

Component.

The column above the prompt. `zg-composer-dock` carries `:empty { display:
none }` (styles/composer.css): every child renders null on an idle
session, and a zero-height flex item would still consume one of the
footer column's 8px gaps, pushing the composer down at rest.

```ts
function ComposerDock(props: ComposerDockProps): Element
```

**Parameters**

- `props` (`ComposerDockProps`): The [`ComposerDockProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerDockProps).

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The docked cards; each may render nothing.
- `className?` (`string`): Extra classes on the dock.
- `style?` (`CSSProperties`): Inline styles on the dock.

Source: [ui/src/chat/composer/DockCard.tsx:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L38)

### `ComposerHostProvider`

Component.

Provides a [`ComposerHost`](https://zidane.si/docs/reference/ui-chat-headless.md#ComposerHost) to the composer components below it.

```ts
function ComposerHostProvider(props: ComposerHostProviderProps): Element
```

**Parameters**

- `props` (`ComposerHostProviderProps`): The `host`, optional `labels` and the `children`.

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The app's components.
- `host` (`ComposerHost`): What the composer reads and does beyond sending.
- `labels?` (`Partial<ComposerLabels>`): Overrides for the composer's strings. Keys you leave out keep the default English label.

Source: [ui/src/chat/composer/ComposerHostProvider.tsx:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerHostProvider.tsx#L31)

### `ComposerStatusPills`

Component.

The right cluster: the run chip and the context orb. The only part of the
conversation that re-renders on the run's progress ticks.

```ts
function ComposerStatusPills(props: ComposerStatusPillsProps): Element | null
```

**Parameters**

- `props` (`ComposerStatusPillsProps`): The [`ComposerStatusPillsProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerStatusPillsProps).

**Returns** `Element | null`

**Props**

- `autoCompactThreshold?` (`number | null`): The fraction auto-compaction starts at, `null` when it is off.
- `contextStatus` (`ComposerContextStatus | null`): Its context status.
- `fetchedCost` (`ComposerCostStatus | null`): Its cost as last read; the pills add what the run settled and streams since (`ComposerHost.runs`).
- `running` (`boolean`): Whether it runs now.
- `sessionId` (`string | null`): The live session, `null` for a draft (nothing shows).

Source: [ui/src/chat/composer/ComposerControls.tsx:204](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerControls.tsx#L204)

### `ContextBreakdown`

Component.

Renders the context window breakdown: a stacked bar and a list of categories with their token shares. While there is no breakdown it shows a plain gauge from the fallback values.

```ts
function ContextBreakdown(props: ContextBreakdownProps): Element
```

**Parameters**

- `props` (`ContextBreakdownProps`): The [`ContextBreakdownProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ContextBreakdownProps).

**Returns** `Element`

**Props**

- `breakdown` (`ContextBreakdown | null | undefined`): undefined: loading; null: no breakdown (no live agent yet).
- `className?` (`string`): Extra classes on the root element.
- `fallbackColor` (`string`): CSS color of the fallback gauge.
- `fallbackPct` (`number`): The orb's share and color, for the plain gauge while there is no breakdown.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ContextBreakdown.tsx:102](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextBreakdown.tsx#L102)

### `ContextOrb`

Component.

Renders the context usage donut and, in its popover, the window breakdown and session cost.

```ts
function ContextOrb(props: ContextOrbProps): Element
```

**Parameters**

- `props` (`ContextOrbProps`): The [`ContextOrbProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ContextOrbProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element (the orb's trigger button).
- `renderBreakdown?` (`(gauge: ContextGauge) => ReactNode`): The popover's breakdown body, mounted while it is open (a host that
  fetches the breakdown on open renders its own). Default:
  `<ContextBreakdown breakdown={usage.breakdown} … />`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `usage` (`ContextUsage`): Everything the orb and its popover show.

Source: [ui/src/chat/composer/ContextOrb.tsx:86](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L86)

### `ConversationBadges`

Component.

The badge strip of one conversation (see the header).

```ts
const ConversationBadges: MemoExoticComponent<(__namedParameters: ConversationBadgesProps) => Element>
```

Source: [ui/src/chat/composer/ConversationBadges.tsx:71](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ConversationBadges.tsx#L71)

### `DockCard`

Component.

One raised card in the dock.

```ts
function DockCard(props: DockCardProps): Element
```

**Parameters**

- `props` (`DockCardProps`): The [`DockCardProps`](https://zidane.si/docs/reference/ui-chat-composer.md#DockCardProps).

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The card's content.
- `className?` (`string`): Extra classes on the card.
- `padded?` (`boolean`): `false` when one full-bleed child (a button) owns the padding and the hover.
- `style?` (`CSSProperties`): Inline styles on the card, merged after its own.
- `tone?` (`'attention' | 'default'`): `attention` tints the surface with the warn color, for things awaiting the user.

Source: [ui/src/chat/composer/DockCard.tsx:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L70)

### `DockRow`

Component.

One line of a dock card: glyph, body, actions.

```ts
function DockRow(props: DockRowProps): Element
```

**Parameters**

- `props` (`DockRowProps`): The [`DockRowProps`](https://zidane.si/docs/reference/ui-chat-composer.md#DockRowProps).

**Returns** `Element`

**Props**

- `align?` (`'start' | 'center'`): `start` pins the glyph and trailing actions to the first 28px line of a
  tall body (an inline editor) instead of floating them at its middle.
- `children` (`ReactNode`): The row's body.
- `className?` (`string`): Extra classes on the row.
- `glyph?` (`ReactNode`): Leading glyph in the fixed 12px slot; omit for text flush at the card inset.
- `style?` (`CSSProperties`): Inline styles on the row.
- `trailing?` (`ReactNode`): Actions at the end.

Source: [ui/src/chat/composer/DockCard.tsx:107](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L107)

### `EffortPickerDialog`

Component.

The model options dialog (see the header).

```ts
function EffortPickerDialog(props: EffortPickerDialogProps): Element
```

**Parameters**

- `props` (`EffortPickerDialogProps`): The [`EffortPickerDialogProps`](https://zidane.si/docs/reference/ui-chat-composer.md#EffortPickerDialogProps).

**Returns** `Element`

**Props**

- `enabled` (`Record<string, boolean>`): Currently-enabled option ids.
- `onApplyEffort` (`(effort: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive') => void | Promise<void>`): Applies an effort (the dialog closes once it settles).
- `onToggleOption` (`(next: Record<string, boolean>) => void | Promise<void>`): Applies the enabled options after a toggle (the dialog stays open).
- `options` (`readonly ComposerModelOption[]`): Feature options the active model declares (toggle section).
- `session` (`ComposerSessionView`): The session whose knobs are set.
- `supportsReasoning` (`boolean`): Whether the active model exposes a reasoning knob (effort section).

Source: [ui/src/chat/composer/EffortPickerDialog.tsx:54](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/EffortPickerDialog.tsx#L54)

### `HostAgentPicker`

Component.

The agent pill:

- a live session: writes its profile (`controls.setAgent`) so the host
  rebuilds with the new preset on the next prompt;
- a draft: edits the default the next send creates the session under.

```ts
function HostAgentPicker(props: HostAgentPickerProps): Element
```

**Parameters**

- `props` (`HostAgentPickerProps`): The [`HostAgentPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostAgentPickerProps).

**Returns** `Element`

**Props**

- `defaultAgentId` (`string`): The next new chat's agent.
- `defaultCwd?` (`string`): The folder a draft's profiles come from (`''`: none).
- `onCommitted?` (`() => void | Promise<void>`): Called once a session's switch is written (refresh the app's session list).
- `onDefaultAgentChange` (`(id: string) => void`): Sets it (a draft's pick).
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft (the pick is the next chat's default).

Source: [ui/src/chat/composer/HostPickers.tsx:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L57)

### `HostComposer`

Component.

Renders a [`Composer`](https://zidane.si/docs/reference/ui-chat-composer.md#Composer) bound to the `ChatHost` in context for one session. Controls the host leaves out are hidden; without `send` nothing renders.

```ts
function HostComposer(props: HostComposerProps): Element | null
```

**Parameters**

- `props` (`HostComposerProps`): The [`HostComposerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostComposerProps).

**Returns** `Element | null`

**Props**

- `ariaLabel?` (`string`, from `Omit`): The textbox's accessible name (default: the `composerLabel` label).
- `attachments?` (`boolean`, from `Omit`): Paste, drop and pick images, PDFs and text files.
- `autoFocus?` (`boolean`, from `Omit`, default `false`): Focuses the editor on mount, with the caret at the end.
- `badges?` (`readonly ComposerBadge[]`, from `Omit`): The badge strip at the top of the tray ring, above the card, in display order (see `ComposerBadges`).
- `badgesKey?` (`string`, from `Omit`): What the badges belong to (a session id): a new key shows its badges without animating them.
- `below?` (`ReactNode`, from `Omit`): A band under the card, inside the tray ring (the desktop app's git bar).
- `className?` (`string`, from `Omit`): Extra class names for the composer's root element.
- `commands?` (`SuggestionSource`, from `Omit`): `/` completions, at the start of the prompt.
- `defaultAttachments?` (`readonly ComposerAttachment[]`, from `Omit`): Attachments staged on mount (a restored draft).
- `defaultModel?` (`string`): The model to start on (`provider/model` or a bare id). Default: the session's, else the first offered.
- `defaultThinking?` (`ThinkingLevel`): Default `medium`.
- `defaultValue?` (`string`, from `Omit`): Initial text of an uncontrolled draft.
- `delivery?` (`MessageDelivery`, from `Omit`, default `'queue'`): What Enter does with the draft while `running`: `steer` it into the run or `queue` it for when the run ends.
  Alt+Enter does the other. Pass the user's "Messages during a run" setting.
- `disabled?` (`boolean`, from `Omit`, default `false`): Makes the editor read-only and disables sending and attaching.
- `footer?` (`ReactNode`): Controls after the pickers.
- `history?` (`readonly string[]`, from `Omit`): Earlier prompts for ↑ / ↓, oldest first. Absent: what this composer sent while mounted.
- `mentions?` (`SuggestionSource`, from `Omit`): `@` completions.
- `onBadgesReorder?` (`(ids: readonly string[]) => void`, from `Omit`): Makes the badges draggable; receives every badge id in the new order.
- `onChange?` (`(text: string) => void`, from `Omit`)
- `onError?` (`(error: unknown) => void`, from `Omit`)
- `onModelChange?` (`(key: string) => void`): Called with the `provider/model` key when the user picks a model.
- `placeholder?` (`string`, from `Omit`): Placeholder shown while the draft is empty. Default: the `composerPlaceholder` label.
- `sessionId` (`string`): Id of the session the composer sends to.
- `style?` (`CSSProperties`, from `Omit`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`, from `Omit`): Controls at the end of the controls row, before Send (a context meter).
- `value?` (`string`, from `Omit`): Controlled text of the draft. Use with `onChange`. Omit for an uncontrolled draft.

Source: [ui/src/chat/composer/HostComposer.tsx:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostComposer.tsx#L57)

### `HostContextOrb`

Component.

The context orb over the host (see the header).

```ts
function HostContextOrb(props: HostContextOrbProps): Element
```

**Parameters**

- `props` (`HostContextOrbProps`): The [`HostContextOrbProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostContextOrbProps).

**Returns** `Element`

**Props**

- `autoCompactThreshold?` (`number | null`): The fraction auto-compaction starts at, `null` when it is off.
- `className?` (`string`): Extra classes on the orb.
- `cost` (`LiveCostStatus | null`): Its live cost.
- `modelName?` (`string`): The model's display name. Default: its id.
- `sessionId` (`string`): The session the gauge measures.
- `status` (`ComposerContextStatus`): Its context status.

Source: [ui/src/chat/composer/HostContextOrb.tsx:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostContextOrb.tsx#L69)

### `HostModelChainList`

Component.

The host's model list (see the header).

```ts
function HostModelChainList(props: HostModelChainListProps): Element
```

**Parameters**

- `props` (`HostModelChainListProps`): The [`HostModelChainListProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelChainListProps).

**Returns** `Element`

**Props**

- `catalog?` (`readonly ComposerModelEntry[] | null`): Pre-loaded catalog, or `null` to load the host's for `cwd`.
- `className?` (`string`): Max list height class.
- `cwd?` (`string`): The folder whose models are listed.
- `dense?` (`boolean`): Compact one-line rows for a popover.
- `hostId?` (`string | null`): A server's session: its models.
- `initialChain` (`readonly ModelPickRef[]`): Seed chain: entry 0 = current primary, 1+ = persisted fallbacks. Empty = nothing picked yet.
- `onChainChange` (`(chain: ModelPickRef[]) => void`): Every draft change, including the initial seed.
- `onQuickPick?` (`(chain: ModelPickRef[]) => void`): A plain click / ↵ on a row while the chain has at most one entry: the
  user is doing a quick swap, not building a chain. Callers that want
  "pick and close" act here; the dialog ignores it.
- `sessionId?` (`string | null`): The session a pick switches: models other than its own say what they would re-read.
- `single?` (`boolean`): One model, no chain (a settings default): every pick fires `onQuickPick`; no fallbacks.

Source: [ui/src/chat/composer/HostModelChainList.tsx:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostModelChainList.tsx#L57)

### `HostModelOptionsPicker`

Component.

The model options pill for a live session: `ModelOptionsPicker` (reasoning
effort, then feature toggles) applying picks to the session, each
remembered for its model so the next new chat starts there.

```ts
function HostModelOptionsPicker(props: HostModelOptionsPickerProps): Element
```

**Parameters**

- `props` (`HostModelOptionsPickerProps`): The [`HostModelOptionsPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelOptionsPickerProps).

**Returns** `Element`

**Props**

- `commitTo?` (`() => Promise<string>`): The session a pick applies to, resolved on commit (see `HostModelPicker`). Default: `session`.
- `enabled` (`Record<string, boolean>`): The session's enabled options.
- `modelId` (`string | null`): Its model: picks are remembered for it.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `options` (`readonly ComposerModelOption[]`): The feature toggles it declares.
- `remember?` (`boolean`): Whether picks are remembered for their model (the next new chat's knobs). `false` for a side chat.
- `session` (`ComposerSessionView`): The live session.
- `supportsReasoning` (`boolean`): The model has a reasoning effort knob.
- `title?` (`string`): The pill's tooltip. Default: the `modelOptionsTitle` label.

Source: [ui/src/chat/composer/HostPickers.tsx:267](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L267)

### `HostModelPicker`

Component.

The model chain pill. Run-sticky fallback: when this run's stream failed on
the picked model and the agent advanced down its chain, the pill shows the
model actually serving the run (`serving`), until the next run or a re-pick.

```ts
function HostModelPicker(props: HostModelPickerProps): Element
```

**Parameters**

- `props` (`HostModelPickerProps`): The [`HostModelPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelPickerProps).

**Returns** `Element`

**Props**

- `account?` (`string | null`): The stored account it runs on; `null` = the active one.
- `catalog` (`readonly ComposerModelEntry[] | null`): The catalog the controls loaded; `null` while it loads.
- `catalogError?` (`string | null`): Why the catalog failed to load (the list offers a retry).
- `commitTo?` (`() => Promise<string>`): The session a pick applies to, resolved on commit (a side chat creates its session then). Default: `session`.
- `hostId?` (`string | null`): The server the session (or draft) runs on: its models are listed.
- `images?` (`HostModelImages | null`): The Image tab. Absent: none.
- `modelId` (`string | null`): The model being steered: the session's, or the draft's default.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `onDefaultModel` (`SetDefaultModel`): Sets the app's default model.
- `onRetryCatalog?` (`() => void`): Reads the catalog again.
- `providerKey` (`string | null`): Its provider.
- `remember?` (`boolean`): Whether a pick also becomes the next new chat's model. `false` for a side chat.
- `serving?` (`{ model: string; provider: string } | null`): The model actually serving the run after a fallback (the pill shows it, amber).
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft.
- `shortcut?` (`ReactNode`): The keyboard shortcut the pill's tooltip shows.

Source: [ui/src/chat/composer/HostPickers.tsx:150](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L150)

### `HostPicker`

Component.

A composer pill naming the host a new chat runs on, opening a menu of the hosts (unreachable ones disabled).

```ts
function HostPicker(props: HostPickerProps): Element | null
```

**Parameters**

- `props` (`HostPickerProps`): The [`HostPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#HostPickerProps).

**Returns** `Element | null`

**Props**

- `className?` (`string`): Extra classes on the root element (the trigger's segment track).
- `hosts` (`readonly HostView[]`): This computer first, then the servers.
- `onChange` (`(hostId: string) => void`): A host was picked.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`string`): The picked host's id.

Source: [ui/src/chat/composer/HostPicker.tsx:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPicker.tsx#L34)

### `ImageModelList`

Component.

Renders the image models in the chat models' list. A pick reports its key.

```ts
function ImageModelList(props: ImageModelListProps): Element
```

**Parameters**

- `props` (`ImageModelListProps`): List props.

**Returns** `Element`

**Props**

- `className?` (`string`): Height class of the list.
- `dense?` (`boolean`): Compact one-line rows, as in the popover. Default true.
- `loadError?` (`string | null`): Why the list failed to load.
- `onPick` (`(key: string) => void`): Called with the picked model's `providerKey/modelId`.
- `onQueryChange?` (`(query: string) => void`): Called on each edit of a caller-kept `query`.
- `onRetry?` (`() => void`): Asks for the list again; shown as a Retry next to `loadError`.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the Legacy switch.
- `query?` (`string`): The search text, when the caller keeps it (shared with another list). Absent: the list keeps its own.
- `rows` (`readonly ImageModelRow[] | null`): The image models; `null` while they load.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls on the row under the search field, before the Legacy switch.
- `value` (`string`): The stored default, `providerKey/modelId` or '' (the model the tool falls back to).

Source: [ui/src/chat/composer/ImageModelList.tsx:104](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ImageModelList.tsx#L104)

### `ModelChainFooter`

Component.

The model pickers' footer: the keys, the hidden legacy models, how many are selected.

```ts
function ModelChainFooter(props: ModelChainFooterProps): Element
```

**Parameters**

- `props` (`ModelChainFooterProps`): The [`ModelChainFooterProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainFooterProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `hiddenLegacy` (`number`): Legacy models the lineup hides; 0: no hint.
- `multi` (`boolean`): The chain has more than one model: the count explains the order.
- `onShowLegacy` (`() => void`): Called when the user clicks the hidden legacy models hint.
- `pad` (`string`): Horizontal padding class, the picker's.
- `selected` (`number`): Models in the chain.
- `single` (`boolean`): One model, no chain: no fallback hint and no selected count.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainParts.tsx:110](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L110)

### `ModelChainHeader`

Component.

The pickers' header, the same for every list (chat models, image models):
the search field across the full width, a row with the caller's `toolbar`
(the popover's Chat / Image tabs) and the Legacy switch at its end, then
the provider pills. One padding around it and one gap between rows, and
each row keeps its height when it is empty, so switching lists or
filtering to nothing never moves the list below.

```ts
function ModelChainHeader(props: ModelChainHeaderProps): Element
```

**Parameters**

- `props` (`ModelChainHeaderProps`): The [`ModelChainHeaderProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainHeaderProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `inputRef` (`RefObject<HTMLInputElement | null>`): The field, so the list can hand focus back to it after a jump.
- `onQuery` (`(query: string) => void`): Called with the search field's text on each edit.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the Legacy switch.
- `pad` (`string`): Horizontal padding class, the picker's.
- `pills?` (`ReactNode`): The provider pills (`ModelProviderPills`); absent while there are no sections.
- `query` (`string`): The search field's text.
- `showLegacy` (`boolean`): The Legacy switch is on: every model is listed.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls at the start of the row under the field.

Source: [ui/src/chat/composer/ModelChainParts.tsx:197](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L197)

### `ModelChainList`

Component.

Renders a searchable list of models for building a fallback chain: the first entry is the primary, the rest are fallbacks. A plain pick on a chain of one swaps the primary.

```ts
function ModelChainList(props: ModelChainListProps): Element
```

**Parameters**

- `props` (`ModelChainListProps`): The [`ModelChainListProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainListProps).

**Returns** `Element`

**Props**

- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered; `null` while they load.
- `className?` (`string`): Max list height class.
- `customIds?` (`boolean`): A query that matches nothing offers itself as a model id (`offCatalogRows`). Default true.
- `dense?` (`boolean`): Compact one-line rows for the popover.
- `emptyText?` (`string`): What the list says when the catalog is empty. Default: no provider is signed in.
- `initialChain` (`readonly ModelPickRef[]`): Seed chain: entry 0 = current primary, 1+ = fallbacks. Empty = nothing picked yet.
- `loadError?` (`string | null`): Why the catalog failed to load.
- `onChainChange` (`(chain: ModelPickRef[]) => void`): Every draft change, including the initial seed.
- `onQueryChange?` (`(query: string) => void`): Called on each edit of a caller-kept `query`.
- `onQuickPick?` (`(chain: ModelPickRef[]) => void`): A plain click / ↵ on a row while the chain has at most one entry: a
  quick swap, not building a chain. A popover picks and closes here.
- `onRetry?` (`() => void`): Asks for the catalog again; shown as a Retry next to `loadError`.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the list between the newest models of each family and every model.
- `query?` (`string`): The search text, when the caller keeps it (shared with another list). Absent: the list keeps its own.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `single?` (`boolean`): One model, no chain: every pick replaces the selection and fires `onQuickPick`; no fallbacks.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls on the row under the search field, before the Legacy switch.

Source: [ui/src/chat/composer/ModelChainList.tsx:128](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainList.tsx#L128)

### `ModelChainPopover`

Component.

Renders the model pill with a popover over the chain picker. A plain pick commits and closes; a chain edited in the popover commits when it is dismissed.

```ts
function ModelChainPopover(props: ModelChainPopoverProps): Element
```

**Parameters**

- `props` (`ModelChainPopoverProps`): The [`ModelChainPopoverProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainPopoverProps).

**Returns** `Element`

**Props**

- `ariaLabel?` (`string`): The popover's name. Default `labels.switchModel`, or `labels.chooseModel` with nothing picked.
- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered; `null` while they load.
- `chain` (`readonly ModelPickRef[]`): The chain in force: the primary, then its fallbacks. Empty: none picked yet.
- `className?` (`string`): Extra classes on the root element (the model pill's frame).
- `forNextChat?` (`boolean`): The chain is the default for the next chat, not a session's: the tooltip says so.
- `images?` (`ModelChainImages`): The image models and the default one: adds the Image tab. Absent: the popover lists chat models only.
- `kind?` (`ModelKind`): Shows one kind of model only, with no Chat / Image switch. `image` needs
  `images`, and the pill then names the default image model. Default: both
  kinds when `images` is given, chat models otherwise.
- `loadError?` (`string | null`): Why the catalog failed to load.
- `name?` (`string | null`): The pill's name. Default: the primary's natural name from the catalog (`modelNameOf`).
- `onCommit` (`(chain: ModelPickRef[]) => void | Promise<void>`): A pick: a plain one (the popover closes after it settles), or an edited chain on dismiss.
- `onOpenChange?` (`(open: boolean) => void`): Called when the popover opens or closes (a row's `details` can then carry what picking it would cost).
- `onRetry?` (`() => void`): Asks for the catalog again (a Retry next to `loadError`).
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the list between the newest models of each family and every model.
- `serving?` (`string | null`): A fallback serving this run instead of the primary, by name: the pill shows it in amber.
- `shortcut?` (`ReactNode`): The key binding that opens the popover (`ctrl+m`), drawn as keycaps on the tooltip's last line.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `single?` (`boolean`): One model, no fallbacks.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelPicker.tsx:248](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L248)

### `ModelChainRow`

Component.

One row of the model chain picker: the model's name and meta, and its place in the chain.

```ts
const ModelChainRow: MemoExoticComponent<(__namedParameters: ModelChainRowProps) => Element>
```

Source: [ui/src/chat/composer/ModelChainRow.tsx:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainRow.tsx#L66)

### `ModelChainRows`

Component.

Renders the picker's sections and the rows of each that are in view.

```ts
const ModelChainRows: MemoExoticComponent<(__namedParameters: ModelChainRowsProps) => Element>
```

Source: [ui/src/chat/composer/ModelChainRows.tsx:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainRows.tsx#L84)

### `ModelChainTooltip`

Component.

Renders the chain the model pill stands for, as tooltip content.

```ts
function ModelChainTooltip(props: ModelChainTooltipProps): Element
```

**Parameters**

- `props` (`ModelChainTooltipProps`): The [`ModelChainTooltipProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainTooltipProps).

**Returns** `Element`

**Props**

- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered, to describe each pick; `null` while they load (picks show by id).
- `chain` (`readonly ModelPickRef[]`): The chain in force: the primary, then its fallbacks. Empty: none picked yet.
- `className?` (`string`): Extra classes on the root element.
- `footer?` (`ReactNode`): How to change it, on the last line (`Switch model` and its keycaps).
- `forNextChat?` (`boolean`): The chain is the default for the next chat, not a session's.
- `serving?` (`string | null`): A fallback serving this run instead of the primary, by name.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainTooltip.tsx:59](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainTooltip.tsx#L59)

### `ModelFlag`

Component.

A capability glyph with a one-line tooltip. The tooltip is portalled: the
rows sit in a scrolling list that would clip it.

```ts
function ModelFlag(props: ModelFlagProps): Element
```

**Parameters**

- `props` (`ModelFlagProps`): Component props.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `hint` (`string`): The tooltip.
- `icon` (`string`): Icon class, for example `i-ph-brain`.
- `label` (`string`): What the glyph stands for, read by assistive tech.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:110](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L110)

### `ModelGroupHeader`

Component.

A model list's sticky section header: a provider, the pinned chain, or a typed id's routes.

```ts
const ModelGroupHeader: MemoExoticComponent<(__namedParameters: ModelGroupHeaderProps) => Element>
```

Source: [ui/src/chat/composer/ModelChainParts.tsx:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L29)

### `ModelMeta`

Component.

A picker row's meta, in order: `legacy`, its `details`, the window (or
`not in catalog`), then the capability glyphs: reasoning, reference images,
transparency, and a lock with the reason when the row is unavailable.

```ts
function ModelMeta(props: ModelMetaProps): Element
```

**Parameters**

- `props` (`ModelMetaProps`): Component props.

**Returns** `Element`

**Props**

- `entry` (`ModelCatalogRow`): The catalog row.
- `legacy?` (`boolean`): Newer models exist in its family.
- `route?` (`boolean`): A typed id's route: the route row says what it is, so no `not in catalog` mark.

Source: [ui/src/chat/composer/ModelFacts.tsx:173](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L173)

### `ModelOptionsPicker`

Component.

Renders the model options pill and its menu: a reasoning effort section and feature checkboxes. Picks apply in place and keep the menu open.

```ts
function ModelOptionsPicker<L extends string = 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'>(
  props: ModelOptionsPickerProps<L>,
): Element
```

**Type parameters**

- `L` (`extends string`, default `'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'`)

**Parameters**

- `props` (`ModelOptionsPickerProps<L>`): The [`ModelOptionsPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelOptionsPickerProps).

**Returns** `Element`

**Props**

- `align?` (`Align`, default `'start'`): How the menu lines up along the trigger's edge.
- `className?` (`string`): Extra classes on the root element (the default trigger pill; ignored with `trigger`).
- `effort` (`L | undefined`): The current reasoning effort level; `undefined` while none is chosen (a default left unset).
- `effortHints?` (`Partial<Record<L, string>>`): A dim note at the end of an effort row, by level (what picking it would cost).
- `enabled` (`Record<string, boolean>`): Currently-enabled option ids.
- `levels?` (`readonly L[]`): The effort rows. Default `EFFORT_LEVELS`.
- `onEffort` (`(level: L) => void | Promise<void>`): Called with the level the user picks. Return a promise to keep the menu busy until it settles.
- `onOpenChange?` (`(open: boolean) => void`): Called when the menu opens or closes.
- `onOptions` (`(next: Record<string, boolean>) => void | Promise<void>`): Called with the full enabled map after the user toggles an option.
- `options` (`readonly ModelOption[]`): The feature toggles the model declares, listed as checkboxes.
- `side?` (`Side`, default `'top'`): Preferred side of the trigger for the menu. It flips when it does not fit.
- `style?` (`CSSProperties`): Inline styles on the root element (the default trigger pill; ignored with `trigger`).
- `supportsReasoning` (`boolean`): The model supports reasoning effort. When false the menu has no effort section.
- `title?` (`string`): The pill's tooltip. Default `labels.modelOptionsHint`.
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the trigger in place of the pill (a settings row): spread the props onto it.

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:88](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L88)

### `ModelPicker`

Component.

Renders the model pill and popover over the models a host offers. It picks one model with no fallback chain.

```ts
function ModelPicker(props: ModelPickerProps): Element
```

**Parameters**

- `props` (`ModelPickerProps`): The [`ModelPickerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPickerProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element (the model pill's frame).
- `providers` (`readonly ChatModelProvider[]`): The providers and models to offer, usually `host.models`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`string | null`): The current `provider/model` key (or bare id); null: none picked yet.
- `onChange` (`(choice: ModelChoice) => void`): Called with the choice when the user picks a model.

Source: [ui/src/chat/composer/ModelPicker.tsx:494](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L494)

### `ModelPickerDialog`

Component.

The Model dialog (see the header).

```ts
function ModelPickerDialog(props: ModelPickerDialogProps): Element
```

**Parameters**

- `props` (`ModelPickerDialogProps`): The [`ModelPickerDialogProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPickerDialogProps).

**Returns** `Element`

**Props**

- `currentModelId` (`string | null`): Its model now (may differ from its own pick when it has none).
- `currentProviderKey` (`string | null`): That model's provider.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `onDefaultModel` (`SetDefaultModel`): Sets the app's default model (the next new chat's).
- `session` (`ComposerSessionView`): The session whose model is picked.

Source: [ui/src/chat/composer/ModelPickerDialog.tsx:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPickerDialog.tsx#L38)

### `ModelPickerFrame`

Component.

Renders the model pill and the popover around a model list.

```ts
function ModelPickerFrame(props: ModelPickerFrameProps): Element
```

**Parameters**

- `props` (`ModelPickerFrameProps`): The [`ModelPickerFrameProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPickerFrameProps).

**Returns** `Element`

**Props**

- `ariaLabel?` (`string`): The popover's name. Default `labels.switchModel`, or `labels.chooseModel` with nothing picked.
- `children` (`(close: () => void) => ReactNode`): Renders the popover's body. Receives a function that closes the popover.
- `className?` (`string`): Extra classes on the root element (the pill, or its tooltip's wrapper when `tooltip` is set).
- `fallbacks?` (`number`): How many fallbacks follow it in its chain: a `+N` suffix.
- `name` (`string | null`): The picked model's name; null: none picked yet (`labels.chooseModel`).
- `onDismiss?` (`() => void`): Called when the popover is dismissed (Escape, outside press, or the trigger).
- `onOpenChange?` (`(open: boolean) => void`): Called when the popover opens or closes.
- `serving?` (`string | null`): A fallback serving this run instead of the pick: shown in amber in its place.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `tooltip?` (`ReactNode`): Shown while the pill is hovered or keyboard-focused, never while the popover is open. Absent: none.
- `width?` (`number`): Default 440.

Source: [ui/src/chat/composer/ModelPicker.tsx:114](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L114)

### `ModelProviderChip`

Component.

The provider chip: its color dot and name, with the account when the provider has several
("Anthropic (Work)").

```ts
function ModelProviderChip(props: ModelProviderChipProps): Element
```

**Parameters**

- `props` (`ModelProviderChipProps`): Component props.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'providerKey' | 'providerLabel' | 'account'>`): The catalog row whose provider and account to name.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:35](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L35)

### `ModelProviderPills`

Component.

The model chain picker's tabs: a pill for the pinned chain, then one per provider section.

```ts
const ModelProviderPills: MemoExoticComponent<(__namedParameters: ModelProviderPillsProps) => Element>
```

Source: [ui/src/chat/composer/ModelProviderPills.tsx:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelProviderPills.tsx#L34)

### `ModelReasoning`

Component.

The reasoning glyph, when the model supports reasoning effort.

```ts
function ModelReasoning(props: ModelReasoningProps): Element | null
```

**Parameters**

- `props` (`ModelReasoningProps`): Component props.

**Returns** `Element | null`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'supportsReasoning'>`): The catalog row.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L140)

### `ModelWindow`

Component.

The model's context window, or `not in catalog` for a typed id the catalog does not know.
Nothing when the window is unknown.

```ts
function ModelWindow(props: ModelWindowProps): Element | null
```

**Parameters**

- `props` (`ModelWindowProps`): Component props.

**Returns** `Element | null`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'contextWindow' | 'offCatalog'>`): The catalog row.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L70)

### `PickerPill`

Component.

Renders the trigger chip for a composer picker, an item of the controls' segmented track. Spread a `Popover` trigger's props onto it.

```ts
const PickerPill: ForwardRefExoticComponent<PickerPillProps & RefAttributes<HTMLButtonElement>>
```

**Props**

- `children` (`ReactNode`): The pill's content: an icon, a label (`min-w-0 truncate`: a squeezed pill truncates it), and a caret.
- `collapsible?` (`boolean`): Folds to its `zg-pill-icon` on a tight composer (styles/composer.css)
  instead of shrinking: mark the icon `zg-pill-icon` and the label and
  caret `zg-pill-label`.

Source: [ui/src/chat/composer/PickerPill.tsx:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PickerPill.tsx#L25)

### `ProjectMenu`

Component.

Renders the folder pill and its project menu (see the header).

```ts
function ProjectMenu(props: ProjectMenuProps): Element
```

**Parameters**

- `props` (`ProjectMenuProps`): The [`ProjectMenuProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ProjectMenuProps).

**Returns** `Element`

**Props**

- `active` (`boolean`): The pill shows as the picked side of the toggle.
- `align?` (`Align`): How the menu lines up with its trigger. Default: its end.
- `ariaLabel` (`string`): The menu's accessible name.
- `browse?` (`(close: () => void) => ReactNode`): "Select directory…" shows this in the menu instead; `close` closes the menu.
- `className?` (`string`): Extra classes on the pill.
- `current` (`string | null`): The picked folder, checked in the list.
- `disabled?` (`boolean`): The pill can't be opened (a send is using the pick).
- `hostId?` (`string`): The host the projects are on (`HostView.id`), for showing their paths. Absent: this computer.
- `icon?` (`string`): The pill's icon class. Default: a folder.
- `label` (`string`): What the pill says.
- `leading?` (`(close: () => void) => ReactNode`): Rows above the projects; `close` closes the menu.
- `onImportRepo?` (`() => void | Promise<void>`): Imports a repository. Absent: not offered.
- `onPick` (`(folder: string) => void`): Picks a project.
- `onSelectDirectory?` (`() => void | Promise<void>`): "Select directory…" calls this (a native dialog). Ignored with `browse`.
- `projects` (`readonly string[]`): The projects to pick from, most recent first.
- `style?` (`CSSProperties`): Inline styles on the pill.
- `title` (`string`): The pill's tooltip.
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the element that opens the menu instead of the pill (`label`, `title`, `icon`, `active` then unused).

Source: [ui/src/chat/composer/ProjectMenu.tsx:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ProjectMenu.tsx#L69)

### `PromptHistoryProvider`

Component.

Holds every session's prompt ring for ↑ / ↓ recall, for the composers below it.

```ts
function PromptHistoryProvider(props: PromptHistoryProviderProps): Element
```

**Parameters**

- `props` (`PromptHistoryProviderProps`): The `children`.

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The app's components.

Source: [ui/src/chat/composer/PromptHistoryProvider.tsx:78](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PromptHistoryProvider.tsx#L78)

### `RetryPill`

Component.

The retry pill (see the header).

```ts
function RetryPill(props: RetryPillProps): Element | null
```

**Parameters**

- `props` (`RetryPillProps`): The [`RetryPillProps`](https://zidane.si/docs/reference/ui-chat-composer.md#RetryPillProps).

**Returns** `Element | null`

**Props**

- `className?` (`string`): Extra classes on the pill.
- `retry` (`{ attempt: number; max: number; source: string } | null`): The retry in progress, `null` for none (the pill hides).
- `style?` (`CSSProperties`): Inline styles, merged after its own.

Source: [ui/src/chat/composer/RetryPill.tsx:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/RetryPill.tsx#L33)

### `RunStatusChip`

Component.

The run's live indicator (see the header).

```ts
function RunStatusChip(props: RunStatusChipProps): Element
```

**Parameters**

- `props` (`RunStatusChipProps`): The [`RunStatusChipProps`](https://zidane.si/docs/reference/ui-chat-composer.md#RunStatusChipProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the chip's wrapper.
- `cost` (`LiveCostStatus | null`): The live session cost.
- `progress` (`LiveStreamProgress | null`): The streaming turn's live counters, `null` between turns.
- `running` (`boolean`): Whether it runs now: the chip shows from start to end.
- `sessionId` (`string`): The session that runs.
- `settledOutputTokens` (`number`): Output tokens of the run's settled parent turns.
- `style?` (`CSSProperties`): Inline styles on the chip.

Source: [ui/src/chat/composer/RunStatusChip.tsx:71](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/RunStatusChip.tsx#L71)

### `ScopeToggle`

Component.

The draft's Chat / folder toggle (see the header).

```ts
function ScopeToggle(props: ScopeToggleProps): Element
```

**Parameters**

- `props` (`ScopeToggleProps`): The [`ScopeToggleProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ScopeToggleProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the group.
- `folderPath` (`string | null`): The draft's folder: `''` no folder (Chat), `null` undecided.
- `onImportRepo?` (`() => void | Promise<void>`): Imports a repository into the draft. Absent: the menu doesn't offer it.
- `onJustChat` (`() => void`): Makes the draft folderless.
- `onPickFolder` (`() => void | Promise<void>`): Opens the app's folder picker.
- `onPickRecent` (`(dir: string) => void`): Picks a recent folder.
- `recents` (`readonly string[]`): Recent folders, offered first.
- `style?` (`CSSProperties`): Inline styles on the group.

Source: [ui/src/chat/composer/ScopeToggle.tsx:49](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ScopeToggle.tsx#L49)

### `SelectTurnHint`

Component.

Renders select-turn mode's keys and its exit in the composer's dock, or nothing while the mode is off here.

```ts
function SelectTurnHint(props: SelectTurnHintProps): Element | null
```

**Parameters**

- `props` (`SelectTurnHintProps`): The `sessionId`, `className` and `style`.

**Returns** `Element | null`

**Props**

- `className?` (`string`): Extra classes on the card.
- `sessionId` (`string | null`): The composer's session: the row shows while select-turn mode is on in it.
- `style?` (`CSSProperties`): Inline styles on the card.

Source: [ui/src/chat/composer/SelectTurnHint.tsx:27](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/SelectTurnHint.tsx#L27)

### `SendButton`

Component.

Renders the Send or Stop button: a circle that sends the draft, or stops the run while one streams and can be stopped.

```ts
function SendButton(props: SendButtonProps): Element
```

**Parameters**

- `props` (`SendButtonProps`): Button props: `stoppable`, `route`, `canSend`, `onSend`, and `onStop`.

**Returns** `Element`

**Props**

- `canSend` (`boolean`): The draft can be sent now. When false the button is disabled unless it is Stop.
- `className?` (`string`): Extra classes on the root element.
- `route` (`SendRoute`): Where the draft goes. Sets the button's label.
- `stoppable` (`boolean`): A run is streaming and can be stopped: the button is Stop.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onSend` (`() => void`): Called when the user sends the draft.
- `onStop` (`() => void`): Called when the user stops the run.

Source: [ui/src/chat/composer/SendButton.tsx:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/SendButton.tsx#L39)

### `ServerScopeToggle`

Component.

Renders the server folder pill and its project menu (see the header).

```ts
function ServerScopeToggle(props: ServerScopeToggleProps): Element
```

**Parameters**

- `props` (`ServerScopeToggleProps`): The [`ServerScopeToggleProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ServerScopeToggleProps).

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the group.
- `clone?` (`DraftRemoteClone | null`): What a send clones there while no folder is picked.
- `cloning?` (`boolean`): The send is cloning `ServerScopeToggleProps.clone`.
- `folder` (`string | null`): The folder picked there, `null` for none (the clone, else the first root).
- `hostId` (`string`): The saved server.
- `hostName` (`string`): Its name, as the pill and the menu say it.
- `onChange` (`(folder: string | null) => void`): Picks a folder there (`null`: none).
- `onImportRepo?` (`() => void | Promise<void>`): Clones a repository on the server into the draft. Absent: not offered.
- `projects` (`readonly string[]`): The server's recent folders, most recent first.
- `root?` (`string | null`): The server's first workspace root, once known.
- `style?` (`CSSProperties`): Inline styles on the group.

Source: [ui/src/chat/composer/ServerScopeToggle.tsx:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ServerScopeToggle.tsx#L62)

### `SuggestionPopup`

Component.

The popup over the caret: one row per item, the keyboard cursor raised.

```ts
function SuggestionPopup(props: SuggestionPopupProps): Element
```

**Parameters**

- `props` (`SuggestionPopupProps`): Popup props: the `state` to show.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element (the floating surface).
- `state` (`SuggestionState | null`): The open popup, or `null` to hide it.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/suggestions.tsx:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L70)

## Functions

### `__resetComposerScopesForTests`

Function.

Forgets every registered composer scope and focus claim. For tests.

```ts
function __resetComposerScopesForTests(): void
```

Source: [ui/src/chat/composer/composer-bus.ts:120](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L120)

### `attachmentErrorText`

Function.

The sentence a composer shows for a file it did not attach.

```ts
function attachmentErrorText(
  fileName: string,
  error: unknown,
  labels: { addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addToChat: string; agent: string; agentDraftNote: string; agentProfiles: string; archive: string; archived: string; attachFile: string; attachmentEmpty: (name: string) => string; attachmentExportPdf: (name: string) => string; attachmentNotices: string; attachmentReadFailed: (name: string) => string; attachments: string; attachmentTitle: (name: string, detail: string) => string; attachmentTooLarge: (name: string, size: string, limit: string) => string; attachmentUnreadableImage: (name: string) => string; attachmentUnsupported: (name: string) => string; authCancel: string; authCard: string; authCopied: string; authCopyDetails: string; authEnterCode: (code: string) => string; authFailed: (message: string) => string; authFixed: string; authHeadline: (auth: AuthFailure, label: string) => string; authOpeningBrowser: string; authOpenPage: string; authPaste: string; authPasteSend: string; authSettings: string; authSettingsHint: string; authSignedIn: string; authSignedInRetrying: string; authSignInAgain: string; authSwitching: (account: string) => string; authTryAgain: string; authUseAccount: (account: string) => string; authWaiting: string; autoDenied: string; back: string; badgeCopied: string; badgeNoComposer: string; badgeOpenIn: (app: string) => string; badgeOpenInBrowserPane: string; badgePathUnavailable: string; blockRunAgain: string; blockRunAttach: string; blockRunAttachmentName: string; blockRunCopy: string; blockRunFailed: (reason: string) => string; blockRunHere: string; blockRunInTerminal: string; blockRunMenu: string; blockRunNeedsTerminal: string; blockRunning: string; blockRunOutput: string; blockRunRemove: string; blockRunStop: string; blockRunStopped: string; blockRunTimedOut: string; blockRunTruncated: string; cancel: string; chats: string; chipBranch: (name: string) => string; chipChat: (name: string) => string; chipCommand: (name: string) => string; chipCommit: (sha: string) => string; chipFactAliases: string; chipFactBranch: string; chipFactChanges: string; chipFactContext: string; chipFactDate: string; chipFactModel: string; chipFactPrompts: string; chipFactSize: string; chipFactTurns: string; chipFactUpdated: string; chipLoading: string; chipNotAmongChats: string; chipNotFound: (title: string) => string; chipRemoteFile: (path: string, host: string) => string; chipSessionError: string; chipSessionRunning: string; chipSkill: (name: string) => string; chipTokens: (count: string) => string; chipUntitledChat: string; chooseModel: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; commandDetail: string; commandSuggestions: string; completionSuggestions: string; composerBadges: string; composerLabel: string; composerPlaceholder: string; composerPlaceholderQueue: string; composerPlaceholderSteer: string; confirm: string; confirmNo: string; confirmYes: string; contextActiveSkills: string; contextAutoCompact: (pct: number) => string; contextCacheRead: string; contextCacheWrite: string; contextClickToCopy: (hasDescription: boolean) => string; contextCopied: string; contextDeferred: string; contextDetail: string; contextEstimated: string; contextFreshInput: string; contextLastTurn: string; contextNoBreakdown: string; contextOutput: string; contextRunCount: (runs: number) => string; contextSessionCost: string; contextSummary: (used: string, window: string, pct: number) => string; contextSummaryCost: (summary: string, cost: string) => string; contextWindow: string; continue: string; continueHint: string; continueRun: string; copied: string; copy: string; copyCode: string; copyDiagramSource: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; delete: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; diagram: (type: string | null) => string; diagramError: (message: string, at: string) => string; diagramErrorAt: (line: number, column: number) => string; dismiss: string; dismissHint: string; dotAttached: string; dotAttention: string; dotCompleted: string; dotError: string; dotIdle: string; dotPending: string; dotRunning: string; earlierHistory: string; earlierLines: (count: number) => string; earlierMessages: (count: number) => string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; effortLevel: (level: string) => string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; estimateDue: string; estimateDueTitle: string; estimateOver: string; estimateOverTitle: string; estimatePausedTitle: (left: string) => string; estimateProblemTitle: (reason: string, message?: string) => string; estimateTitle: (left: string) => string; expandGroup: (label: string) => string; favorites: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; filterActivities: { '1d': string; '30d': string; '3d': string; '7d': string; all: string }; filterActivity: string; filterAgent: string; filterAllAgents: string; filterAllAgentsOption: string; filterAllProjects: string; filterAllProjectsOption: string; filterAny: string; filterNoAgents: string; filterNoProjects: string; filterOrigin: string; filterOrigins: { all: string; scheduled: string; unscheduled: string }; filterPicked: (count: number) => string; filterProject: string; filterSaveView: string; filterSessions: string; filterSort: string; filterSorts: { alphabetical: string; createdTime: string; recency: string }; filterSpaceDefault: string; filterStatus: string; filterStatuses: { active: string; all: string; archived: string }; filterView: string; filterViews: { agent: string; date: string; host: string; none: string; project: string; state: string }; findClose: string; findCloseHint: string; findInConversation: string; findInConversationClose: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; fitDiagram: string; foldOutcomes: (ok: number, failed: number) => string; foldSteps: (count: number) => string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hostBadgeTitle: (host: string, status: string) => string; hostCollapse: (name: string) => string; hostExpand: (name: string) => string; hostOpenSettings: (host: string) => string; hostPicker: string; hostRunsOn: (name: string) => string; hostRunsOnSection: string; hostStatusError: (status: string, error: string) => string; hostStatuses: { 'auth-refused': string; connected: string; connecting: string; identity: string; local: string; offline: string; reconnecting: string; 'version-mismatch': string }; hostThisMachine: string; imageModelReferences: string; imageModelReferencesHint: string; imageModelsNone: string; imageModelsPill: string; imageModelTransparency: string; imageModelTransparencyHint: string; inboxEmpty: string; inboxInProgress: string; inboxNeedsYou: string; inboxPreviousSession: string; inboxRecent: string; inputCaption: string; interactionAnsweredBy: (who: string) => string; interactionApproved: string; interactionDismissed: string; interactionPlan: string; interactionQuestion: string; interactionRejected: string; interactionRevise: string; interactionsLabel: string; interactionWaitingAnswers: string; interactionWaitingDecision: string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mentionSuggestions: string; modalBack: string; modalFailed: string; modelAccountBlocked: (provider: string) => string; modelChain: string; modelChainNoModel: string; modelChainOrderHint: string; modelFallback: string; modelFallbackHint: string; modelFallbackPosition: (n: number) => string; modelFeatures: string; modelForNextChat: string; modelInUse: string; modelKinds: string; modelLegacy: string; modelLegacyHint: string; modelNotInCatalog: string; modelNotInCatalogHint: string; modelOptions: string; modelOptionsEmpty: string; modelOptionsHint: string; modelPrimary: string; modelPrimaryHint: string; modelReasoning: string; modelReasoningHint: string; modelRemoveFallback: (n: number) => string; modelRemoveFromChain: string; modelRemovePrimary: string; modelsChatTab: string; modelsCustomId: string; modelServing: (picked: string, serving: string) => string; modelServingFallback: string; modelsImageTab: string; modelsInUse: string; modelsJumpHint: (provider: string, digit: number | null) => string; modelsJumpToProvider: string; modelsLegacy: string; modelsLegacyHidden: (count: number) => string; modelsLoadFailed: (error: string) => string; modelsLoading: string; modelsNoMatch: (query: string) => string; modelsNoProviders: string; modelsSelected: (count: number) => string; modelsShowLegacy: string; modelsShowLegacyHint: string; modelsShownOf: (shown: number, total: number) => string; modelsTypeAnId: string; modelUnavailable: string; modelVerdictTitle: (approved: boolean, model: string, confidence: string | null) => string; modelVia: string; modelViaHint: (modelId: string, provider: string) => string; months: readonly string[]; moreActions: string; moreAttachments: (count: number) => string; newSession: string; newSessionIn: (label: string) => string; next: string; noAnswer: string; noMatches: (query: string) => string; noReferences: string; noSessions: string; noSuggestions: string; of: (index: number, count: number) => string; openFiles: string; openGroup: (label: string) => string; openImageFile: (path: string) => string; openInNewTab: string; openNamedSession: (title: string) => string; openSecrets: string; openSession: string; outputCaption: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; pickModel: string; pickOneOrMore: string; planApprove: string; planReject: string; planRejectAndStop: string; planRejectNote: string; planRejectPlaceholder: string; planRevise: string; planReviseNote: string; planRevisePlaceholder: string; planSendRevision: string; previewFailed: (name: string) => string; previewTooLarge: (name: string, size: string) => string; previous: string; questionCount: (count: number) => string; queueHint: string; queueMessage: string; reasoningEffort: string; receiptAgent: string; receiptAgentSwitched: string; receiptCost: string; receiptDuration: string; receiptModel: string; receiptModelOthers: (others: number) => string; receiptSpeed: string; receiptTokens: (sent: string, received: string) => string; receiptTurns: (turns: number) => string; reload: string; removeAttachment: (name: string) => string; removeFavorite: string; rename: string; requiredHint: string; requiredMark: string; resetsAt: (time: string) => string; retry: string; retryHint: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; saveSecurely: string; screenBack: (screen: string) => string; screenBackKey: string; scriptCallsDone: (done: number) => string; scriptCallsFailed: (failed: number) => string; scriptCallsOf: (done: number, total: number) => string; scriptCallsRunning: (running: number) => string; scriptLineCalls: (calls: number) => string; scriptLiveOutput: string; scriptLoop: string; scriptLoopRound: (round: number) => string; scriptLoopRounds: (rounds: number) => string; scriptLoopRuns: (runs: number) => string; scriptOptionOutput: string; scriptOptions: string; scriptOptionTimeout: string; scriptOptionTokens: (tokens: number) => string; scriptPercent: (percent: number) => string; scriptProgress: string; scriptWaitLeft: (seconds: number) => string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; secretDeclined: (name: string) => string; secretNote: (ttl: SecretTtl) => string; secretReused: (name: string) => string; secretSaved: (name: string, left: SecretTimeLeft) => string; secretSent: (name: string) => string; secretTtlLabel: string; secretTtlName: (ttl: SecretTtl) => string; secretValueLabel: string; secretValuePlaceholder: string; selectTurnCopied: string; selectTurnCopy: string; selectTurnDetails: string; selectTurnExit: string; selectTurnFork: string; selectTurnForkFailed: string; selectTurnMove: string; selectTurnNothingToCopy: string; selectTurnSelecting: string; sendAnswers: (count: number) => string; sendHint: string; sendMessage: string; sessionActions: string; sessionEventLabel: (title: string, verb: string, needsAttention: boolean) => string; sessions: string; setModelOptions: string; shellCancelled: string; shellExit: (code: number) => string; shellKilled: string; showDiagram: string; showDiagramSource: string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; spawnResumes: (childId: string) => string; spawnTask: string; stateCompleted: string; stateError: string; stateIdle: string; stateRunning: string; steerHint: string; steerMessage: string; stepDone: string; stepFailed: string; stepOf: (index: number, count: number) => string; stepResuming: string; stepRunning: string; steps: string; stepWaiting: string; stopCommand: string; stopHint: string; stopped: string; stoppedByYou: string; stopRun: string; switchAgent: string; switchingAgent: string; switchModel: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; thinkingLive: string; thoughtFor: (seconds: number) => string; thoughts: string; thoughtTimes: (count: number) => string; today: string; toolAttachments: string; transcriptLoading: string; turnMenuCopy: string; turnMenuCopySelection: string; turnMenuCopySelectionFailed: string; turnMenuDelete: string; turnMenuEdit: string; turnMenuEditNeedsComposer: string; turnMenuFork: string; turnMenuRewind: string; turnMenuSent: (age: string) => string; turnMenuStopFirst: (label: string) => string; turnsCompacted: string; unarchive: string; unsupportedInteraction: (tool: string) => string; viewAttachment: (name: string) => string; waitingForSlot: (max: number) => string; workerContinues: string; workerModel: string; workerSystemPrompt: string; workerSystemReplaced: string; workerType: string; working: string; wrapLines: string; yesterday: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string },
): string
```

**Parameters**

- `fileName` (`string`): The file's name.
- `error` (`unknown`): What [`readAttachment`](https://zidane.si/docs/reference/ui-chat-composer.md#readAttachment) rejected with.
- `labels` (`{ addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addToChat: string; agent: string; agentDraftNote: string; agentProfiles: string; archive: string; archived: string; attachFile: string; attachmentEmpty: (name: string) => string; attachmentExportPdf: (name: string) => string; attachmentNotices: string; attachmentReadFailed: (name: string) => string; attachments: string; attachmentTitle: (name: string, detail: string) => string; attachmentTooLarge: (name: string, size: string, limit: string) => string; attachmentUnreadableImage: (name: string) => string; attachmentUnsupported: (name: string) => string; authCancel: string; authCard: string; authCopied: string; authCopyDetails: string; authEnterCode: (code: string) => string; authFailed: (message: string) => string; authFixed: string; authHeadline: (auth: AuthFailure, label: string) => string; authOpeningBrowser: string; authOpenPage: string; authPaste: string; authPasteSend: string; authSettings: string; authSettingsHint: string; authSignedIn: string; authSignedInRetrying: string; authSignInAgain: string; authSwitching: (account: string) => string; authTryAgain: string; authUseAccount: (account: string) => string; authWaiting: string; autoDenied: string; back: string; badgeCopied: string; badgeNoComposer: string; badgeOpenIn: (app: string) => string; badgeOpenInBrowserPane: string; badgePathUnavailable: string; blockRunAgain: string; blockRunAttach: string; blockRunAttachmentName: string; blockRunCopy: string; blockRunFailed: (reason: string) => string; blockRunHere: string; blockRunInTerminal: string; blockRunMenu: string; blockRunNeedsTerminal: string; blockRunning: string; blockRunOutput: string; blockRunRemove: string; blockRunStop: string; blockRunStopped: string; blockRunTimedOut: string; blockRunTruncated: string; cancel: string; chats: string; chipBranch: (name: string) => string; chipChat: (name: string) => string; chipCommand: (name: string) => string; chipCommit: (sha: string) => string; chipFactAliases: string; chipFactBranch: string; chipFactChanges: string; chipFactContext: string; chipFactDate: string; chipFactModel: string; chipFactPrompts: string; chipFactSize: string; chipFactTurns: string; chipFactUpdated: string; chipLoading: string; chipNotAmongChats: string; chipNotFound: (title: string) => string; chipRemoteFile: (path: string, host: string) => string; chipSessionError: string; chipSessionRunning: string; chipSkill: (name: string) => string; chipTokens: (count: string) => string; chipUntitledChat: string; chooseModel: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; commandDetail: string; commandSuggestions: string; completionSuggestions: string; composerBadges: string; composerLabel: string; composerPlaceholder: string; composerPlaceholderQueue: string; composerPlaceholderSteer: string; confirm: string; confirmNo: string; confirmYes: string; contextActiveSkills: string; contextAutoCompact: (pct: number) => string; contextCacheRead: string; contextCacheWrite: string; contextClickToCopy: (hasDescription: boolean) => string; contextCopied: string; contextDeferred: string; contextDetail: string; contextEstimated: string; contextFreshInput: string; contextLastTurn: string; contextNoBreakdown: string; contextOutput: string; contextRunCount: (runs: number) => string; contextSessionCost: string; contextSummary: (used: string, window: string, pct: number) => string; contextSummaryCost: (summary: string, cost: string) => string; contextWindow: string; continue: string; continueHint: string; continueRun: string; copied: string; copy: string; copyCode: string; copyDiagramSource: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; delete: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; diagram: (type: string | null) => string; diagramError: (message: string, at: string) => string; diagramErrorAt: (line: number, column: number) => string; dismiss: string; dismissHint: string; dotAttached: string; dotAttention: string; dotCompleted: string; dotError: string; dotIdle: string; dotPending: string; dotRunning: string; earlierHistory: string; earlierLines: (count: number) => string; earlierMessages: (count: number) => string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; effortLevel: (level: string) => string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; estimateDue: string; estimateDueTitle: string; estimateOver: string; estimateOverTitle: string; estimatePausedTitle: (left: string) => string; estimateProblemTitle: (reason: string, message?: string) => string; estimateTitle: (left: string) => string; expandGroup: (label: string) => string; favorites: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; filterActivities: { '1d': string; '30d': string; '3d': string; '7d': string; all: string }; filterActivity: string; filterAgent: string; filterAllAgents: string; filterAllAgentsOption: string; filterAllProjects: string; filterAllProjectsOption: string; filterAny: string; filterNoAgents: string; filterNoProjects: string; filterOrigin: string; filterOrigins: { all: string; scheduled: string; unscheduled: string }; filterPicked: (count: number) => string; filterProject: string; filterSaveView: string; filterSessions: string; filterSort: string; filterSorts: { alphabetical: string; createdTime: string; recency: string }; filterSpaceDefault: string; filterStatus: string; filterStatuses: { active: string; all: string; archived: string }; filterView: string; filterViews: { agent: string; date: string; host: string; none: string; project: string; state: string }; findClose: string; findCloseHint: string; findInConversation: string; findInConversationClose: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; fitDiagram: string; foldOutcomes: (ok: number, failed: number) => string; foldSteps: (count: number) => string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hostBadgeTitle: (host: string, status: string) => string; hostCollapse: (name: string) => string; hostExpand: (name: string) => string; hostOpenSettings: (host: string) => string; hostPicker: string; hostRunsOn: (name: string) => string; hostRunsOnSection: string; hostStatusError: (status: string, error: string) => string; hostStatuses: { 'auth-refused': string; connected: string; connecting: string; identity: string; local: string; offline: string; reconnecting: string; 'version-mismatch': string }; hostThisMachine: string; imageModelReferences: string; imageModelReferencesHint: string; imageModelsNone: string; imageModelsPill: string; imageModelTransparency: string; imageModelTransparencyHint: string; inboxEmpty: string; inboxInProgress: string; inboxNeedsYou: string; inboxPreviousSession: string; inboxRecent: string; inputCaption: string; interactionAnsweredBy: (who: string) => string; interactionApproved: string; interactionDismissed: string; interactionPlan: string; interactionQuestion: string; interactionRejected: string; interactionRevise: string; interactionsLabel: string; interactionWaitingAnswers: string; interactionWaitingDecision: string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mentionSuggestions: string; modalBack: string; modalFailed: string; modelAccountBlocked: (provider: string) => string; modelChain: string; modelChainNoModel: string; modelChainOrderHint: string; modelFallback: string; modelFallbackHint: string; modelFallbackPosition: (n: number) => string; modelFeatures: string; modelForNextChat: string; modelInUse: string; modelKinds: string; modelLegacy: string; modelLegacyHint: string; modelNotInCatalog: string; modelNotInCatalogHint: string; modelOptions: string; modelOptionsEmpty: string; modelOptionsHint: string; modelPrimary: string; modelPrimaryHint: string; modelReasoning: string; modelReasoningHint: string; modelRemoveFallback: (n: number) => string; modelRemoveFromChain: string; modelRemovePrimary: string; modelsChatTab: string; modelsCustomId: string; modelServing: (picked: string, serving: string) => string; modelServingFallback: string; modelsImageTab: string; modelsInUse: string; modelsJumpHint: (provider: string, digit: number | null) => string; modelsJumpToProvider: string; modelsLegacy: string; modelsLegacyHidden: (count: number) => string; modelsLoadFailed: (error: string) => string; modelsLoading: string; modelsNoMatch: (query: string) => string; modelsNoProviders: string; modelsSelected: (count: number) => string; modelsShowLegacy: string; modelsShowLegacyHint: string; modelsShownOf: (shown: number, total: number) => string; modelsTypeAnId: string; modelUnavailable: string; modelVerdictTitle: (approved: boolean, model: string, confidence: string | null) => string; modelVia: string; modelViaHint: (modelId: string, provider: string) => string; months: readonly string[]; moreActions: string; moreAttachments: (count: number) => string; newSession: string; newSessionIn: (label: string) => string; next: string; noAnswer: string; noMatches: (query: string) => string; noReferences: string; noSessions: string; noSuggestions: string; of: (index: number, count: number) => string; openFiles: string; openGroup: (label: string) => string; openImageFile: (path: string) => string; openInNewTab: string; openNamedSession: (title: string) => string; openSecrets: string; openSession: string; outputCaption: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; pickModel: string; pickOneOrMore: string; planApprove: string; planReject: string; planRejectAndStop: string; planRejectNote: string; planRejectPlaceholder: string; planRevise: string; planReviseNote: string; planRevisePlaceholder: string; planSendRevision: string; previewFailed: (name: string) => string; previewTooLarge: (name: string, size: string) => string; previous: string; questionCount: (count: number) => string; queueHint: string; queueMessage: string; reasoningEffort: string; receiptAgent: string; receiptAgentSwitched: string; receiptCost: string; receiptDuration: string; receiptModel: string; receiptModelOthers: (others: number) => string; receiptSpeed: string; receiptTokens: (sent: string, received: string) => string; receiptTurns: (turns: number) => string; reload: string; removeAttachment: (name: string) => string; removeFavorite: string; rename: string; requiredHint: string; requiredMark: string; resetsAt: (time: string) => string; retry: string; retryHint: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; saveSecurely: string; screenBack: (screen: string) => string; screenBackKey: string; scriptCallsDone: (done: number) => string; scriptCallsFailed: (failed: number) => string; scriptCallsOf: (done: number, total: number) => string; scriptCallsRunning: (running: number) => string; scriptLineCalls: (calls: number) => string; scriptLiveOutput: string; scriptLoop: string; scriptLoopRound: (round: number) => string; scriptLoopRounds: (rounds: number) => string; scriptLoopRuns: (runs: number) => string; scriptOptionOutput: string; scriptOptions: string; scriptOptionTimeout: string; scriptOptionTokens: (tokens: number) => string; scriptPercent: (percent: number) => string; scriptProgress: string; scriptWaitLeft: (seconds: number) => string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; secretDeclined: (name: string) => string; secretNote: (ttl: SecretTtl) => string; secretReused: (name: string) => string; secretSaved: (name: string, left: SecretTimeLeft) => string; secretSent: (name: string) => string; secretTtlLabel: string; secretTtlName: (ttl: SecretTtl) => string; secretValueLabel: string; secretValuePlaceholder: string; selectTurnCopied: string; selectTurnCopy: string; selectTurnDetails: string; selectTurnExit: string; selectTurnFork: string; selectTurnForkFailed: string; selectTurnMove: string; selectTurnNothingToCopy: string; selectTurnSelecting: string; sendAnswers: (count: number) => string; sendHint: string; sendMessage: string; sessionActions: string; sessionEventLabel: (title: string, verb: string, needsAttention: boolean) => string; sessions: string; setModelOptions: string; shellCancelled: string; shellExit: (code: number) => string; shellKilled: string; showDiagram: string; showDiagramSource: string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; spawnResumes: (childId: string) => string; spawnTask: string; stateCompleted: string; stateError: string; stateIdle: string; stateRunning: string; steerHint: string; steerMessage: string; stepDone: string; stepFailed: string; stepOf: (index: number, count: number) => string; stepResuming: string; stepRunning: string; steps: string; stepWaiting: string; stopCommand: string; stopHint: string; stopped: string; stoppedByYou: string; stopRun: string; switchAgent: string; switchingAgent: string; switchModel: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; thinkingLive: string; thoughtFor: (seconds: number) => string; thoughts: string; thoughtTimes: (count: number) => string; today: string; toolAttachments: string; transcriptLoading: string; turnMenuCopy: string; turnMenuCopySelection: string; turnMenuCopySelectionFailed: string; turnMenuDelete: string; turnMenuEdit: string; turnMenuEditNeedsComposer: string; turnMenuFork: string; turnMenuRewind: string; turnMenuSent: (age: string) => string; turnMenuStopFirst: (label: string) => string; turnsCompacted: string; unarchive: string; unsupportedInteraction: (tool: string) => string; viewAttachment: (name: string) => string; waitingForSlot: (max: number) => string; workerContinues: string; workerModel: string; workerSystemPrompt: string; workerSystemReplaced: string; workerType: string; working: string; wrapLines: string; yesterday: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }`): The chat labels to word it with.

**Returns** `string`

Source: [ui/src/chat/composer/attachment-ingest.ts:46](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L46)

### `attachmentLightboxItems`

Function.

Every previewable attachment as one gallery: images, PDFs in the browser's viewer, and text as its decoded preview.

```ts
function attachmentLightboxItems(
  attachments: readonly ComposerAttachment[],
  Preview?: ComponentType<TextPreviewSlotProps>,
): LightboxItem[]
```

**Parameters**

- `attachments` (`readonly ComposerAttachment[]`): The composer's attachments. Images, PDFs and text-like files are included; other files are skipped.
- `Preview?` (`ComponentType<TextPreviewSlotProps>`, default `TextPreview`): What a text file opens as (default: the kit's `TextPreview`).

**Returns** `LightboxItem[]`

Source: [ui/src/chat/composer/attachments.tsx:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachments.tsx#L33)

### `canJoinChain`

Function.

Whether `pick` can join `chain` as a fallback: no other account of its provider is in it.

```ts
function canJoinChain(chain: readonly ModelPickRef[], pick: ModelPickRef): boolean
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The current chain.
- `pick` (`ModelPickRef`): The model to add as a fallback.

**Returns** `boolean`

Source: [ui/src/chat/composer/model-catalog.ts:149](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L149)

### `catalogFromProviders`

Function.

A `ChatHost`'s models as catalog rows, in the host's order.

```ts
function catalogFromProviders(
  providers: readonly ChatModelProvider[],
): ModelCatalogRow[]
```

**Parameters**

- `providers` (`readonly ChatModelProvider[]`): The providers a host offers, usually `host.models`.

**Returns** `ModelCatalogRow[]`

Source: [ui/src/chat/composer/model-catalog.ts:412](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L412)

### `claimComposerFocus`

Function.

The composer receiving `scopeKey` (`null`: a folderless draft) is the
window's: pushes without a target go to it until the returned release (a
no-op once another claim replaced it).

```ts
function claimComposerFocus(scopeKey: string | null): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope.

**Returns** `() => void`

Source: [ui/src/chat/composer/composer-bus.ts:108](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L108)

### `colorForCategory`

Function.

Returns the display color for a context category id, with a muted fallback for unknown ids.

```ts
function colorForCategory(id: string): string
```

**Parameters**

- `id` (`string`): The category id, for example `conversation` or `tools`.

**Returns** `string`

Source: [ui/src/chat/composer/ContextBreakdown.tsx:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextBreakdown.tsx#L48)

### `compactWindow`

Function.

`1M`, `1.5M`, `200k`: the row meta has no room for `1.00M`.

```ts
function compactWindow(tokens: number): string
```

**Parameters**

- `tokens` (`number`): A context window size in tokens.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L42)

### `contextGauge`

Function.

Computes the orb's percent and color from a used fraction.

```ts
function contextGauge(fraction: number): ContextGauge
```

**Parameters**

- `fraction` (`number`): Used share of the context window, from 0 to 1. Values outside the range are clamped.

**Returns** `ContextGauge`

Source: [ui/src/chat/composer/ContextOrb.tsx:60](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L60)

### `decodeDataUrlAsText`

Function.

Decodes a `data:` URL's payload as UTF-8 text. Returns an empty string when the URL has no payload and a placeholder message when decoding fails.

```ts
function decodeDataUrlAsText(dataUrl: string): string
```

**Parameters**

- `dataUrl` (`string`): The `data:` URL to decode.

**Returns** `string`

Source: [ui/src/chat/composer/attachment-ingest.ts:392](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L392)

### `detectLanguage`

Function.

Map an attachment to a Shiki language id. Extension wins; falls back
to MIME hints (`+json`, `+xml`, `text/markdown`); unknown →
`plaintext` so the preview still renders, just without colour.

```ts
function detectLanguage(att: Pick<ChatAttachment, 'mediaType' | 'name'>): string
```

**Parameters**

- `att` (`Pick<ChatAttachment, 'mediaType' | 'name'>`): The attachment's `name` and `mediaType`.

**Returns** `string`

Source: [ui/src/chat/composer/attachment-ingest.ts:204](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L204)

### `effectiveImageModel`

Function.

The row an `imageModel` setting names; when it is empty or stale, the model the tool falls back to
(`isDefault`), else the first available one.

```ts
function effectiveImageModel(
  rows: readonly ImageModelRow[],
  value: string,
): ImageModelRow | null
```

**Parameters**

- `rows` (`readonly ImageModelRow[]`): The listed image models.
- `value` (`string`): The stored `providerKey/modelId`, or ''.

**Returns** `ImageModelRow | null`

Source: [ui/src/chat/composer/ImageModelList.tsx:41](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ImageModelList.tsx#L41)

### `findModel`

Function.

The model a value names: a `provider/model` key, or a bare id (the first provider offering it).

```ts
function findModel(
  providers: readonly ChatModelProvider[],
  value: string | null | undefined,
): ModelChoice | null
```

**Parameters**

- `providers` (`readonly ChatModelProvider[]`): The providers to search.
- `value` (`string | null | undefined`): A `provider/model` key or a bare model id. A missing value returns `null`.

**Returns** `ModelChoice | null`

Source: [ui/src/chat/composer/ModelPicker.tsx:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L66)

### `focusComposer`

Function.

Move keyboard focus back to the composer (Esc out of a panel card).

```ts
function focusComposer(target?: ComposerTarget): void
```

**Parameters**

- `target?` (`ComposerTarget`): The composer it is for; without one, the window's.

Source: [ui/src/chat/composer/composer-bus.ts:241](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L241)

### `focusComposerWhenReady`

Function.

Move keyboard focus to the window's composer, or, while none takes it (a
conversation switch is still mounting it, or re-keying it to a scope that
resolves later), to the next composer to subscribe.

```ts
function focusComposerWhenReady(): void
```

Source: [ui/src/chat/composer/composer-bus.ts:274](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L274)

### `formatBytes`

Function.

Byte counts for people: `512 B`, `1.5 KB`, `2.0 MB`.

```ts
function formatBytes(bytes: number): string
```

**Parameters**

- `bytes` (`number`): Size in bytes.

**Returns** `string`

Source: [dist/chat/pure.d.ts:15](https://github.com/Tahul/zidane/blob/main/dist/chat/pure.d.ts#L15)

### `groupKeyOf`

Function.

Section a row lists under: its provider, or its provider's account when there are several.

```ts
function groupKeyOf(entry: Pick<ModelCatalogRow, 'providerKey' | 'account'>): string
```

**Parameters**

- `entry` (`Pick<ModelCatalogRow, 'providerKey' | 'account'>`): A row, or any object with its `providerKey` and `account`.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:93](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L93)

### `hasComposerFor`

Function.

Whether a composer in this window receives `scopeKey`.

```ts
function hasComposerFor(scopeKey: string | null | undefined): boolean
```

**Parameters**

- `scopeKey` (`string | null | undefined`): The scope to check.

**Returns** `boolean`

Source: [ui/src/chat/composer/composer-bus.ts:55](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L55)

### `hasFocusedComposer`

Function.

Whether the window has a composer: where a push without a target goes (producers without a scope of their own).

```ts
function hasFocusedComposer(): boolean
```

**Returns** `boolean`

Source: [ui/src/chat/composer/composer-bus.ts:76](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L76)

### `imageCatalogRows`

Function.

Image models as model-list rows: no context window or reasoning, the capabilities and availability instead.

```ts
function imageCatalogRows(rows: readonly ImageModelRow[]): ModelCatalogRow[]
```

**Parameters**

- `rows` (`readonly ImageModelRow[]`): The listed image models.

**Returns** `ModelCatalogRow[]`

Source: [ui/src/chat/composer/ImageModelList.tsx:55](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ImageModelList.tsx#L55)

### `imageModelKey`

Function.

`providerKey/modelId`, the form `Settings.imageModel` stores.

```ts
function imageModelKey(row: Pick<ImageModelRow, 'providerKey' | 'modelId'>): string
```

**Parameters**

- `row` (`Pick<ImageModelRow, 'providerKey' | 'modelId'>`): The image model.

**Returns** `string`

Source: [ui/src/chat/composer/ImageModelList.tsx:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ImageModelList.tsx#L31)

### `isCaretAtEnd`

Function.

Whether the caret is collapsed on the very last position of the document.

```ts
function isCaretAtEnd(state: Pick<EditorState, 'doc' | 'selection'>): boolean
```

**Parameters**

- `state` (`Pick<EditorState, 'doc' | 'selection'>`): The editor state.

**Returns** `boolean`

Source: [ui/src/chat/composer/prompt-history-nav.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/prompt-history-nav.ts#L31)

### `isCaretAtStart`

Function.

Whether the caret is collapsed on the very first position of the document.

```ts
function isCaretAtStart(state: Pick<EditorState, 'doc' | 'selection'>): boolean
```

**Parameters**

- `state` (`Pick<EditorState, 'doc' | 'selection'>`): The editor state.

**Returns** `boolean`

Source: [ui/src/chat/composer/prompt-history-nav.ts:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/prompt-history-nav.ts#L22)

### `isFocusedComposer`

Function.

Whether the composer receiving `scopeKey` (`null`: a folderless draft) is the window's: the one a push
without a target goes to.

```ts
function isFocusedComposer(scopeKey: string | null): boolean
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope.

**Returns** `boolean`

Source: [ui/src/chat/composer/composer-bus.ts:86](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L86)

### `isPdfAttachment`

Function.

A PDF attachment: previewed in the browser's own PDF viewer.

```ts
function isPdfAttachment(att: Pick<ChatAttachment, 'mediaType'>): boolean
```

**Parameters**

- `att` (`Pick<ChatAttachment, 'mediaType'>`): The attachment; only its media type is read.

**Returns** `boolean`

Source: [ui/src/chat/composer/attachment-ingest.ts:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L68)

### `isTextLike`

Function.

Treat as text any attachment whose MIME is in the `text/*` family,
or one of the structured-text types we routinely encounter (JSON,
XML, common script languages that browsers tag as `application/*`).
Falls back to an extension allowlist for files the OS picker
presents without a MIME — extensionless dotfiles and a handful of
common code extensions land here so the preview is useful.

```ts
function isTextLike(att: Pick<ChatAttachment, 'mediaType' | 'name'>): boolean
```

**Parameters**

- `att` (`Pick<ChatAttachment, 'mediaType' | 'name'>`): The attachment's `name` and `mediaType`.

**Returns** `boolean`

Source: [ui/src/chat/composer/attachment-ingest.ts:306](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L306)

### `lineupKeyOf`

Function.

A row's lineup identity (`currentModelKeys`: provider + model, whatever the account).

```ts
function lineupKeyOf(entry: ModelCatalogRow): string
```

**Parameters**

- `entry` (`ModelCatalogRow`): The catalog row.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L84)

### `mergeBadgeOrder`

Function.

The order to save after the user moved badges: the order shown now, with
each saved id that is not shown kept right after the shown badge it
followed, so it comes back in its place.

```ts
function mergeBadgeOrder(saved: readonly string[], shown: readonly string[]): string[]
```

**Parameters**

- `saved` (`readonly string[]`): The order saved so far.
- `shown` (`readonly string[]`): Every badge shown, in the new order.

**Returns** `string[]`: The order to save.

Source: [ui/src/chat/composer/badge-order.ts:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/badge-order.ts#L53)

### `modelKey`

Function.

Returns the `provider/model` key of a model, the form `SendInput` takes.

```ts
function modelKey(provider: ChatModelProvider, model: ChatModel): string
```

**Parameters**

- `provider` (`ChatModelProvider`): The model's provider.
- `model` (`ChatModel`): The model.

**Returns** `string`

Source: [ui/src/chat/composer/ModelPicker.tsx:58](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L58)

### `modelLineup`

Function.

The catalog's current models (core `currentModelKeys`: the newest of each
family, by `lineupKeyOf`), worked out once per catalog: hosts keep theirs
between openings, and it means parsing every model id. Read-only.

```ts
function modelLineup(catalog: readonly ModelCatalogRow[]): ReadonlySet<string>
```

**Parameters**

- `catalog` (`readonly ModelCatalogRow[]`): The catalog rows. The result is cached per array.

**Returns** `ReadonlySet<string>`

Source: [ui/src/chat/composer/model-catalog.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L31)

### `modelNameOf`

Function.

A model's natural name (`Opus 4.6`), from the catalog's display name when it lists the model.

```ts
function modelNameOf(
  catalog: readonly ModelCatalogRow[] | null,
  modelId: string,
  providerKey?: string | null,
): string
```

**Parameters**

- `catalog` (`readonly ModelCatalogRow[] | null`): The catalog rows, or `null` while it loads.
- `modelId` (`string`): The model id to name.
- `providerKey?` (`string | null`, default `null`): Limits the lookup to one provider. Defaults to `null`, which matches any provider.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:114](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L114)

### `modelSearchScore`

Function.

Search rank of one entry against the query terms, or `null` when a term is
missing. Lower is better: a term at the start of the model id beats one at
a word start inside it, which beats a substring of the id, which beats a
hit only in the name / provider corpus.

```ts
function modelSearchScore(
  entry: ModelCatalogRow,
  terms: readonly string[],
): number | null
```

**Parameters**

- `entry` (`ModelCatalogRow`): The catalog row.
- `terms` (`readonly string[]`): The lower-cased search terms. Every term must match.

**Returns** `number | null`

Source: [ui/src/chat/composer/model-catalog.ts:289](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L289)

### `nextProfileId`

Function.

The profile after `currentId` in `ids`, wrapping; the first one when
`currentId` is not listed. `null` when there is nothing to switch to.

```ts
function nextProfileId(ids: readonly string[], currentId: string): string | null
```

**Parameters**

- `ids` (`readonly string[]`): The offered profile ids, in the picker's order.
- `currentId` (`string`): The current profile.

**Returns** `string | null`

Source: [ui/src/chat/composer/use-agent-profiles.ts:54](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-agent-profiles.ts#L54)

### `offCatalogRows`

Function.

"Use this id via …" rows for a typed model id, one per provider in the
catalog (the provider the query names first, then the current one, then
the rest), minus routes the catalog already lists. Empty unless the query
names an id worth offering: when the catalog matched something, only an
id-shaped query (a digit, `-`, `.`, `/` or `:`, 3+ characters) gets typed
routes, so a plain word like "claude" stays a search.

```ts
function offCatalogRows(
  catalog: readonly ModelCatalogRow[],
  query: string,
  currentProviderKey: string | null,
  catalogMatched: boolean,
): ModelCatalogRow[]
```

**Parameters**

- `catalog` (`readonly ModelCatalogRow[]`): The catalog rows.
- `query` (`string`): What the user typed in the search field.
- `currentProviderKey` (`string | null`): Key of the provider in use, listed after the one the query names. `null` for none.
- `catalogMatched` (`boolean`): Whether the catalog already matched the query. If so, only an id-shaped query gets typed routes.

**Returns** `ModelCatalogRow[]`

Source: [ui/src/chat/composer/model-catalog.ts:239](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L239)

### `onComposerAttachment`

Function.

Takes the attachments pushed to a composer.

```ts
function onComposerAttachment(
  scopeKey: string | null,
  handler: (attachment: ComposerAttachment) => void,
): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`(attachment: ComposerAttachment) => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:180](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L180)

### `onComposerDraft`

Function.

Takes the drafts pushed to a composer.

```ts
function onComposerDraft(
  scopeKey: string | null,
  handler: (draft: ComposerDraft) => void,
): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`(draft: ComposerDraft) => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:342](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L342)

### `onComposerFocus`

Function.

Takes the focus requests pushed to a composer.

```ts
function onComposerFocus(scopeKey: string | null, handler: () => void): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`() => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:292](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L292)

### `onComposerInsert`

Function.

Takes the text inserts pushed to a composer.

```ts
function onComposerInsert(
  scopeKey: string | null,
  handler: (text: string) => void,
): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`(text: string) => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:230](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L230)

### `onComposerMention`

Function.

Takes the file mentions pushed to a composer.

```ts
function onComposerMention(
  scopeKey: string | null,
  handler: (path: string) => void,
): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`(path: string) => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:205](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L205)

### `onComposerPrompt`

Function.

Takes the prompts pushed to a composer.

```ts
function onComposerPrompt(
  scopeKey: string | null,
  handler: (text: string) => void,
): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope (`null`: a folderless draft).
- `handler` (`(text: string) => void`): Called with each push resolved to it.

**Returns** `() => void`: The unsubscribe.

Source: [ui/src/chat/composer/composer-bus.ts:313](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L313)

### `orderComposerBadges`

Function.

Badges in the order to show them: sorted by `order` (stable for ties),
then the saved order applied over the slots of the badges it names.

```ts
function orderComposerBadges<T extends OrderedBadge>(
  badges: readonly T[],
  saved?: readonly string[],
): T[]
```

**Type parameters**

- `T` (`extends OrderedBadge`)

**Parameters**

- `badges` (`readonly T[]`): The badges to show, in any order.
- `saved?` (`readonly string[]`, default `[]`): The user's order, as ids (stale and unknown ids are ignored).

**Returns** `T[]`: A new array, in display order.

Source: [ui/src/chat/composer/badge-order.ts:30](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/badge-order.ts#L30)

### `pastedTextFilename`

Function.

ISO-stamped filename for a paste-as-attachment write.

```ts
function pastedTextFilename(): string
```

**Returns** `string`

Source: [ui/src/chat/composer/attachment-ingest.ts:421](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L421)

### `pickerGroups`

Function.

The picker's list as groups. Empty query: the chain first ("In use"), then
each provider in catalog order with its current models (or all of them
with `showLegacy`), chain members not repeated. With a query: every model
of every provider that matches, grouped by provider, groups ordered by
their best match, rows by score then catalog order.

```ts
function pickerGroups<E extends ModelCatalogRow>(
  catalog: readonly E[],
  query: string,
  chain: readonly ModelPickRef[],
  showLegacy: boolean,
  current: ReadonlySet<string>,
): PickerGroup<E>[]
```

**Type parameters**

- `E` (`extends ModelCatalogRow`)

**Parameters**

- `catalog` (`readonly E[]`): The catalog rows.
- `query` (`string`): What the user typed in the search field. Blank lists by provider.
- `chain` (`readonly ModelPickRef[]`): The chain in force. Its models lead the list as "In use".
- `showLegacy` (`boolean`): Lists every model instead of only the current ones.
- `current` (`ReadonlySet<string>`): The lineup keys of the current models, from [`modelLineup`](https://zidane.si/docs/reference/ui-chat-composer.md#modelLineup).

**Returns** `PickerGroup<E>[]`

Source: [ui/src/chat/composer/model-catalog.ts:334](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L334)

### `pickRefOf`

Function.

The pick a catalog row makes: its provider, model and (when the provider has several) account.

```ts
function pickRefOf(entry: ModelCatalogRow): ModelPickRef
```

**Parameters**

- `entry` (`ModelCatalogRow`): The catalog row.

**Returns** `ModelPickRef`

Source: [ui/src/chat/composer/model-catalog.ts:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L62)

### `plainTextToDocJson`

Function.

Plain text → TipTap doc JSON, one paragraph per line. `setContent`
with a string parses it as HTML — multi-line history entries would
collapse to a single run and angle brackets would be swallowed as
tags. Building the JSON directly keeps recalled prompts (and restored
drafts) byte-faithful. Empty text yields a single empty paragraph,
the minimal valid `block+` doc.

```ts
function plainTextToDocJson(text: string): DocJson
```

**Parameters**

- `text` (`string`): The plain text. Each line becomes a paragraph.

**Returns** `DocJson`

Source: [ui/src/chat/composer/prompt-history-nav.ts:50](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/prompt-history-nav.ts#L50)

### `providerAccountLabel`

Function.

"Anthropic", or "Anthropic (Work)" for one of several accounts. Plain text: it also names
the account in tooltips and settings rows.

```ts
function providerAccountLabel(
  entry: Pick<ModelCatalogRow, 'providerLabel' | 'account'>,
): string
```

**Parameters**

- `entry` (`Pick<ModelCatalogRow, 'providerLabel' | 'account'>`): A row, or any object with its `providerLabel` and `account`.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:103](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L103)

### `pushComposerAttachment`

Function.

Stage an attachment in a composer.

```ts
function pushComposerAttachment(
  attachment: ComposerAttachment,
  target?: ComposerTarget,
): void
```

**Parameters**

- `attachment` (`ComposerAttachment`): The attachment, read into a data URL.
- `target?` (`ComposerTarget`): The composer it is for; without one, the window's.

Source: [ui/src/chat/composer/composer-bus.ts:169](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L169)

### `pushComposerDraft`

Function.

REPLACE the composer's draft (Edit message): the editor holds `text`, the
staged attachments become `attachments`, and the caret lands at the end.

```ts
function pushComposerDraft(draft: ComposerDraft & Partial<ComposerTarget>): void
```

**Parameters**

- `draft` (`ComposerDraft & Partial<ComposerTarget>`): The draft, and the scope of the composer it is for (absent: the window's).

Source: [ui/src/chat/composer/composer-bus.ts:331](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L331)

### `pushComposerInsert`

Function.

Append plain text at the end of the draft and focus the composer (a `/command ` awaiting arguments).

```ts
function pushComposerInsert(text: string, target?: ComposerTarget): void
```

**Parameters**

- `text` (`string`): The text to append.
- `target?` (`ComposerTarget`): The composer it is for; without one, the window's.

Source: [ui/src/chat/composer/composer-bus.ts:219](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L219)

### `pushComposerMention`

Function.

Insert an `@<path>` file mention at the caret. `path` is relative to the
session cwd, the same form the composer's own `@` completion produces.

```ts
function pushComposerMention(path: string, target?: ComposerTarget): void
```

**Parameters**

- `path` (`string`): The file, relative to the session's folder.
- `target?` (`ComposerTarget`): The composer it is for; without one, the window's.

Source: [ui/src/chat/composer/composer-bus.ts:194](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L194)

### `pushComposerPrompt`

Function.

Send `text` through the composer's send path, leaving the draft alone (palette prompts, Continue / Retry).

```ts
function pushComposerPrompt(text: string, target?: ComposerTarget): void
```

**Parameters**

- `text` (`string`): The prompt.
- `target?` (`ComposerTarget`): The composer it is for; without one, the window's.

Source: [ui/src/chat/composer/composer-bus.ts:302](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L302)

### `readAttachment`

Function.

Reads a file into a [`ComposerAttachment`](https://zidane.si/docs/reference/ui-chat-headless.md#ComposerAttachment) with a `data:` URL, as the
shared rule says (`planAttachment`): images, PDFs and text attach; an image
in another format, or over the image cap, is re-encoded to fit, and keeps
the file as picked in `original` (up to the file cap) so the host can save
it for the agent and say it was converted. An animated GIF under the cap
goes as it is, every frame. Rejects with
an [`AttachmentRefusedError`](https://zidane.si/docs/reference/ui-chat-composer.md#AttachmentRefusedError) for a file the rule refuses (or an image
that cannot be decoded), and with the read error when the file cannot be read.

```ts
function readAttachment(file: File): Promise<ComposerAttachment>
```

**Parameters**

- `file` (`File`): The file the user pasted, dropped, or picked.

**Returns** `Promise<ComposerAttachment>`

Source: [ui/src/chat/composer/attachment-ingest.ts:117](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L117)

### `refKey`

Function.

Identity of a pick: provider, model and account (core `modelPickKey`, the one key chains compare by).

```ts
function refKey(entry: ModelPickRef): string
```

**Parameters**

- `entry` (`ModelPickRef`): The pick.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L53)

### `registerComposerScope`

Function.

The mounted composer receives `scopeKey` (`null`: it has no scope, a
folderless draft); call the returned function when it stops.

```ts
function registerComposerScope(scopeKey: string | null): () => void
```

**Parameters**

- `scopeKey` (`string | null`): The composer's scope.

**Returns** `() => void`

Source: [ui/src/chat/composer/composer-bus.ts:35](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L35)

### `resolveChain`

Function.

A chain as the catalog lists it, [`resolvePick`](https://zidane.si/docs/reference/ui-chat-composer.md#resolvePick) on each entry: what the
picker shows (In use, places, checks) and edits. The chain itself when no
entry changes.

```ts
function resolveChain(
  chain: readonly ModelPickRef[],
  catalog: readonly ModelCatalogRow[],
): readonly ModelPickRef[]
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The chain: the primary, then its fallbacks.
- `catalog` (`readonly ModelCatalogRow[]`): The catalog rows.

**Returns** `readonly ModelPickRef[]`

Source: [ui/src/chat/composer/model-catalog.ts:186](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L186)

### `resolvePick`

Function.

A pick as the catalog lists it. A pick naming no account runs on its
provider's active account: where the catalog lists that provider per
account, the pick is that account's row (the one marked active, else the
first account that has the model). Any other pick comes back as it is.

```ts
function resolvePick(
  pick: ModelPickRef,
  catalog: readonly ModelCatalogRow[],
): ModelPickRef
```

**Parameters**

- `pick` (`ModelPickRef`): A pick of the chain.
- `catalog` (`readonly ModelCatalogRow[]`): The catalog rows.

**Returns** `ModelPickRef`

Source: [ui/src/chat/composer/model-catalog.ts:167](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L167)

### `resourceErrorText`

Function.

The text of a resource's error, `null` for none.

```ts
function resourceErrorText(error: unknown): string | null
```

**Parameters**

- `error` (`unknown`): The snapshot's `error`.

**Returns** `string | null`

Source: [ui/src/chat/composer/use-composer-stores.ts:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L42)

### `rowKey`

Function.

A catalog row's pick identity.

```ts
function rowKey(entry: ModelCatalogRow): string
```

**Parameters**

- `entry` (`ModelCatalogRow`): The catalog row.

**Returns** `string`

Source: [ui/src/chat/composer/model-catalog.ts:75](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L75)

### `shouldFoldPasteToAttachment`

Function.

Should a plain-text paste become a `.txt` attachment chip instead of
inline editor text? Mirrors the TUI's rule (line count after CRLF
normalisation + trim) with a lower character ceiling on top.

```ts
function shouldFoldPasteToAttachment(text: string): boolean
```

**Parameters**

- `text` (`string`): The pasted plain text.

**Returns** `boolean`

Source: [ui/src/chat/composer/attachment-ingest.ts:97](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L97)

### `suggestionExtension`

Function.

One trigger as a Tiptap extension. `source` and `state` are refs so the
editor, built once, always reads the latest props and popup.

```ts
function suggestionExtension(
  kind: SuggestionKind,
  source: RefObject<SuggestionSource | undefined>,
  state: RefObject<SuggestionState | null>,
  setState: (next: SuggestionState | null) => void,
): Node<MentionOptions<any, MentionNodeAttrs>, any>
```

**Parameters**

- `kind` (`SuggestionKind`): Which trigger the extension handles.
- `source` (`RefObject<SuggestionSource | undefined>`): Ref to the source that supplies items and serialization.
- `state` (`RefObject<SuggestionState | null>`): Ref to the popup state the keyboard handler reads.
- `setState` (`(next: SuggestionState | null) => void`): Updates the popup state.

**Returns** `Node<MentionOptions<any, MentionNodeAttrs>, any>`

Source: [ui/src/chat/composer/suggestion-extension.ts:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestion-extension.ts#L38)

### `takePendingComposerFocus`

Function.

Whether a [`focusComposerWhenReady`](https://zidane.si/docs/reference/ui-chat-composer.md#focusComposerWhenReady) request waits for a composer; taking it clears it.

```ts
function takePendingComposerFocus(): boolean
```

**Returns** `boolean`

Source: [ui/src/chat/composer/composer-bus.ts:279](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L279)

### `textAttachment`

Function.

Build a text attachment (UTF-8 data URL) the composer can carry.

```ts
function textAttachment(name: string, text: string): ComposerAttachment
```

**Parameters**

- `name` (`string`): The file name it shows.
- `text` (`string`): Its contents.

**Returns** `ComposerAttachment`

Source: [ui/src/chat/composer/composer-bus.ts:352](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L352)

### `unresolveChain`

Function.

An edit made on a resolved chain ([`resolveChain`](https://zidane.si/docs/reference/ui-chat-composer.md#resolveChain)), back on the chain
it was resolved from: an entry that was there keeps its own form (a pick
naming no account still names none, so it still follows the active
account), a new one stays as it was picked.

```ts
function unresolveChain(
  next: readonly ModelPickRef[],
  chain: readonly ModelPickRef[],
  shown: readonly ModelPickRef[],
): ModelPickRef[]
```

**Parameters**

- `next` (`readonly ModelPickRef[]`): The edited resolved chain.
- `chain` (`readonly ModelPickRef[]`): The chain before the edit.
- `shown` (`readonly ModelPickRef[]`): `chain` resolved, as the edit saw it.

**Returns** `ModelPickRef[]`

Source: [ui/src/chat/composer/model-catalog.ts:209](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L209)

### `useAgentProfiles`

Function.

The profiles `cwd` offers (`''`: no folder). Empty until read, and without `agents`.

```ts
function useAgentProfiles(
  cwd: string,
  agentsOverride?: ComposerAgents,
): readonly ComposerAgentProfile[]
```

**Parameters**

- `cwd` (`string`): The folder.
- `agentsOverride?` (`ComposerAgents`): The profiles' source. Default: the host's `agents`.

**Returns** `readonly ComposerAgentProfile[]`

Source: [ui/src/chat/composer/use-agent-profiles.ts:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-agent-profiles.ts#L22)

### `useAttachmentIngest`

Function.

Manages the composer's staged attachments and the ways in: paste, drop, and the file picker. Images, PDFs and text files attach; anything else is refused with a notice.

```ts
function useAttachmentIngest(
  enabled: boolean,
  initial?: readonly ComposerAttachment[],
): { attachments: ComposerAttachment[]; clear: () => void; dismissNotices: () => void; dragging: boolean; inputRef: RefObject<HTMLInputElement | null>; notices: string[]; remove: (id: string) => void; restore: (list: readonly ComposerAttachment[]) => void; dragLeave(event: DragEvent): void; dragOver(event: DragEvent): void; drop(event: DragEvent): void; paste(event: ClipboardEvent): boolean; pick(event: ChangeEvent<HTMLInputElement>): void }
```

**Parameters**

- `enabled` (`boolean`): Turns the handlers on. When false every handler is a no-op that lets the event through.
- `initial?` (`readonly ComposerAttachment[]`, default `[]`): Attachments staged on mount, for example a restored draft. Defaults to none.

**Returns** `{ attachments: ComposerAttachment[]; clear: () => void; dismissNotices: () => void; dragging: boolean; inputRef: RefObject<HTMLInputElement | null>; notices: string[]; remove: (id: string) => void; restore: (list: readonly ComposerAttachment[]) => void; dragLeave(event: DragEvent): void; dragOver(event: DragEvent): void; drop(event: DragEvent): void; paste(event: ClipboardEvent): boolean; pick(event: ChangeEvent<HTMLInputElement>): void }`

Source: [ui/src/chat/composer/useAttachmentIngest.ts:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/useAttachmentIngest.ts#L57)

### `useAttachmentNotices`

Function.

The notices about files a composer did not attach: `refuse` words what
`readAttachment` rejected with; they clear on `dismiss`, or
[`ATTACHMENT_NOTICE_MS`](https://zidane.si/docs/reference/ui-chat-composer.md#ATTACHMENT_NOTICE_MS) after the latest one.

```ts
function useAttachmentNotices(): { dismiss: () => void; notices: string[]; refuse: (fileName: string, error: unknown) => void }
```

**Returns** `{ dismiss: () => void; notices: string[]; refuse: (fileName: string, error: unknown) => void }`

Source: [ui/src/chat/composer/useAttachmentIngest.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/useAttachmentIngest.ts#L31)

### `useAttachmentRemoval`

Function.

Removal with the tile's exit: `removeAttachment` marks it exiting, and the
tile's width transition (or a timer on the `exit` motion's length, when
motion is reduced or off and there is no transition) drops it from the list. Only a removal still in
flight is finalized: once the list is replaced (`clearExiting`), a late
timer would remove a tile of the NEW list sharing that id.

```ts
function useAttachmentRemoval(
  setAttachments: Dispatch<SetStateAction<ComposerAttachment[]>>,
): { clearExiting: () => void; exitingIds: Set<string>; finalizeRemove: (id: string) => void; removeAttachment: (id: string) => void }
```

**Parameters**

- `setAttachments` (`Dispatch<SetStateAction<ComposerAttachment[]>>`): The staged list's setter.

**Returns** `{ clearExiting: () => void; exitingIds: Set<string>; finalizeRemove: (id: string) => void; removeAttachment: (id: string) => void }`

Source: [ui/src/chat/composer/AttachmentTiles.tsx:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AttachmentTiles.tsx#L34)

### `useCacheHints`

Function.

Cache hints for a picker's options, fetched once per open: an option's
estimate is asked the first time it renders. The first answer decides for
all: no live agent, an expired cache, a short prompt or an older daemon
means no option can show one, so nothing more is asked. Never blocks a
pick; a failed estimate shows nothing.

```ts
function useCacheHints(
  sessionId: string | null,
  open?: boolean,
): (key: string, change: CacheImpactChange) => string | undefined
```

**Parameters**

- `sessionId` (`string | null`): The session the pick applies to; `null` (a draft) shows no hints.
- `open?` (`boolean`, default `true`): Whether the picker is showing. A modal is (the default); a popover passes its open state: closed asks nothing, and each opening asks afresh.

**Returns** `(key: string, change: CacheImpactChange) => string | undefined`: A lookup: the hint for option `key` (the change it would make), `undefined` while unknown or when there is none. A new lookup each time an answer arrives, so it can key a memo.

Source: [ui/src/chat/composer/use-cache-hints.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-cache-hints.ts#L28)

### `useComposerFor`

Function.

Where a scoped producer pushes: its scope's composer while one is mounted (live), else `null`.

```ts
function useComposerFor(scopeKey: string | null): ComposerTarget | null
```

**Parameters**

- `scopeKey` (`string | null`): The producer's scope.

**Returns** `ComposerTarget | null`

Source: [ui/src/chat/composer/composer-bus.ts:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L69)

### `useComposerHost`

Function.

The nearest [`ComposerHost`](https://zidane.si/docs/reference/ui-chat-headless.md#ComposerHost); an empty host (every capability left out) outside a provider.

```ts
function useComposerHost(): ComposerHost
```

**Returns** `ComposerHost`

Source: [ui/src/chat/composer/ComposerHostProvider.tsx:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerHostProvider.tsx#L37)

### `useComposerLabels`

Function.

The composer's strings: defaults, then `<LabelsProvider>` overrides, then the provider's `labels`.

```ts
function useComposerLabels(): ComposerLabels
```

**Returns** `ComposerLabels`

Source: [ui/src/chat/composer/ComposerHostProvider.tsx:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerHostProvider.tsx#L42)

### `useComposerModelName`

Function.

Names a model as the model picker does; re-renders when the catalog arrives or changes.

```ts
function useComposerModelName(): ModelNamer
```

**Returns** `ModelNamer`

Source: [ui/src/chat/composer/use-composer-stores.ts:128](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L128)

### `useComposerProviderLabel`

Function.

A provider's label as the model picker groups it (`Anthropic`).

```ts
function useComposerProviderLabel(): (providerKey: string) => string
```

**Returns** `(providerKey: string) => string`

Source: [ui/src/chat/composer/use-composer-stores.ts:133](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L133)

### `useCycleAgent`

Function.

Quick-cycle through the folder's agent profiles (the `cycleAgent`
shortcut). Mirrors the TUI's Shift+Tab: the next profile in the picker's
order, wrapping; a no-op with one profile, while the session runs, or while
it waits on an approval (`ApprovalsHost`) or a question (`ChatHost`).

```ts
function useCycleAgent(
  session: ComposerSessionView | null,
  options: CycleAgentOptions,
): () => Promise<void>
```

**Parameters**

- `session` (`ComposerSessionView | null`): The session, `null` for none (the callback does nothing).
- `options` (`CycleAgentOptions`): Whether it runs, and what to do after a switch.

**Returns** `() => Promise<void>`: A callback that moves the session to its next profile.

Source: [ui/src/chat/composer/use-agent-profiles.ts:78](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-agent-profiles.ts#L78)

### `useDraftKnobs`

Function.

A new chat's starting effort and options on `modelId`, live (its draft's pick, the configured defaults, the last used).

```ts
function useDraftKnobs(
  modelId: string | null,
  configured: SessionKnobs | undefined,
): ModelKnobs
```

**Parameters**

- `modelId` (`string | null`): The model the draft starts on.
- `configured` (`SessionKnobs | undefined`): The configured defaults.

**Returns** `ModelKnobs`

Source: [ui/src/chat/composer/use-composer-stores.ts:117](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L117)

### `useDraftTarget`

Function.

The new-chat draft's target, reset with the draft.

```ts
function useDraftTarget(options: DraftTargetOptions): DraftTarget
```

**Parameters**

- `options` (`DraftTargetOptions`): The open session and the app's folder, sessions and servers.

**Returns** `DraftTarget`

Source: [ui/src/chat/composer/use-draft-target.ts:142](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-draft-target.ts#L142)

### `useHasFocusedComposer`

Function.

Live [`hasFocusedComposer`](https://zidane.si/docs/reference/ui-chat-composer.md#hasFocusedComposer).

```ts
function useHasFocusedComposer(): boolean
```

**Returns** `boolean`

Source: [ui/src/chat/composer/composer-bus.ts:91](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L91)

### `useHostResource`

Function.

A host resource, kept current while mounted (`IDLE_RESOURCE` for `null`).

```ts
function useHostResource<T>(
  resource: Readable<ResourceSnapshot<T>> | null,
): ResourceSnapshot<T>
```

**Type parameters**

- `T`

**Parameters**

- `resource` (`Readable<ResourceSnapshot<T>> | null`): The resource; memoize it (a new one each render resubscribes).

**Returns** `ResourceSnapshot<T>`

Source: [ui/src/chat/composer/use-composer-stores.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L29)

### `useJoinedRunProgress`

Function.

A running session this window did not see start (opened, reloaded or
reconnected mid-run): reads its run from the host once (`runs.progress`),
so the chip neither restarts its time nor counts its output from zero. A
run whose `run:start` it saw counts from the start already.

```ts
function useJoinedRunProgress(sessionId: string | null, running: boolean): void
```

**Parameters**

- `sessionId` (`string | null`): The session, `null` for none.
- `running` (`boolean`): Whether it runs now.

Source: [ui/src/chat/composer/use-run-meter.ts:77](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L77)

### `useModelCatalog`

Function.

The catalog to list: `outer` when the caller loaded one, else the host's for `cwd` on `hostId`.

```ts
function useModelCatalog(
  outer: readonly ComposerModelEntry[] | null,
  cwd?: string,
  hostId?: string | null,
): ModelCatalogState
```

**Parameters**

- `outer` (`readonly ComposerModelEntry[] | null`): A catalog the caller already holds.
- `cwd?` (`string`): The folder.
- `hostId?` (`string | null`, default `null`): The server, `null` for this computer.

**Returns** `ModelCatalogState`

Source: [ui/src/chat/composer/use-composer-stores.ts:64](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L64)

### `useModelKnobs`

Function.

The remembered knobs of the nearest host, for actions.

```ts
function useModelKnobs(): ModelKnobsStore
```

**Returns** `ModelKnobsStore`

Source: [ui/src/chat/composer/use-composer-stores.ts:138](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L138)

### `useModelPickerPrefs`

Function.

The model picker's preferences, live.

```ts
function useModelPickerPrefs(): ModelPickerPrefs
```

**Returns** `ModelPickerPrefs`

Source: [ui/src/chat/composer/use-composer-stores.ts:88](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L88)

### `useModelPickerPrefsStore`

Function.

The host's picker preferences store (an in-memory one when it has none).

```ts
function useModelPickerPrefsStore(): ModelPickerPrefsStore
```

**Returns** `ModelPickerPrefsStore`

Source: [ui/src/chat/composer/use-composer-stores.ts:83](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L83)

### `useNewSessionDefaults`

Function.

The new session's defaults in a space, over the provided `ComposerHost`.

```ts
function useNewSessionDefaults(settings: Settings, spaceId: string): NewSessionDefaults
```

**Parameters**

- `settings` (`Settings`): The settings (the space presets).
- `spaceId` (`string`): The space new sessions go to.

**Returns** `NewSessionDefaults`

Source: [ui/src/chat/composer/use-new-session-defaults.ts:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-new-session-defaults.ts#L69)

### `usePromptHistory`

Function.

The prompt ring from the nearest [`PromptHistoryProvider`](https://zidane.si/docs/reference/ui-chat-composer.md#PromptHistoryProvider). Throws outside one.

```ts
function usePromptHistory(): PromptHistoryValue
```

**Returns** `PromptHistoryValue`

Source: [ui/src/chat/composer/PromptHistoryProvider.tsx:206](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PromptHistoryProvider.tsx#L206)

### `useProviderReadyPoll`

Function.

Keeps `store` on the chat host's provider check.

```ts
function useProviderReadyPoll(store: Writable<boolean | null>, paused?: boolean): void
```

**Parameters**

- `store` (`Writable<boolean | null>`): Where the answer goes: `true` / `false`, `null` when the check failed (unknown, not "none": it must not block sends).
- `paused?` (`boolean`, default `false`): Skip reading while true; turning false reads again.

Source: [ui/src/chat/composer/use-provider-ready-poll.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-provider-ready-poll.ts#L19)

### `useRememberedKnobs`

Function.

The last effort and options used with `modelId`, live.

```ts
function useRememberedKnobs(modelId: string | null): ModelKnobs
```

**Parameters**

- `modelId` (`string | null`): The model.

**Returns** `ModelKnobs`

Source: [ui/src/chat/composer/use-composer-stores.ts:106](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L106)

### `useRunAccruedCost`

Function.

Cost of turns settled since the last settling cost read.

```ts
function useRunAccruedCost(sessionId: string | null): number
```

**Parameters**

- `sessionId` (`string | null`): The session, `null` for none.

**Returns** `number`

Source: [ui/src/chat/composer/use-run-meter.ts:59](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L59)

### `useRunElapsedSec`

Function.

Whole-second elapsed counter for the session's current run, from its start
(the host's, so neither switching conversations nor opening a window
restarts it). Ticks every `tickMs`: 250 ms by default so `0s → 1s` is not
laggy, but renders once per second.

```ts
function useRunElapsedSec(
  sessionId: string,
  running: boolean,
  tickMs?: number,
  runsOverride?: ComposerRuns,
): number
```

**Parameters**

- `sessionId` (`string`): The session.
- `running` (`boolean`): Whether it runs now.
- `tickMs?` (`number`, default `250`): How often the clock is read.
- `runsOverride?` (`ComposerRuns`): The run counters to read. Default: the host's `runs`.

**Returns** `number`

Source: [ui/src/chat/composer/use-run-meter.ts:109](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L109)

### `useRunMeterValue`

Function.

One field of a session's run counters (`store`: `RunMeter.session(id)`, `null` for none).

```ts
function useRunMeterValue<K extends keyof RunMeterState>(
  store: Readable<RunMeterState> | null,
  key: K,
): RunMeterState[K]
```

**Type parameters**

- `K` (`extends keyof RunMeterState`)

**Parameters**

- `store` (`Readable<RunMeterState> | null`): The session's counters.
- `key` (`K`): The field to read.

**Returns** `RunMeterState[K]`

Source: [ui/src/chat/composer/use-run-meter.ts:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L22)

### `useRunOutputTokens`

Function.

Output tokens of the run's settled parent turns.

```ts
function useRunOutputTokens(sessionId: string | null): number
```

**Parameters**

- `sessionId` (`string | null`): The session, `null` for none.

**Returns** `number`

Source: [ui/src/chat/composer/use-run-meter.ts:52](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L52)

### `useRunProgress`

Function.

The streaming parent turn's live counters, `null` between turns.

```ts
function useRunProgress(sessionId: string | null): LiveStreamProgress | null
```

**Parameters**

- `sessionId` (`string | null`): The session, `null` for none.

**Returns** `LiveStreamProgress | null`

Source: [ui/src/chat/composer/use-run-meter.ts:45](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L45)

### `useRunStartedAt`

Function.

When the run started (epoch ms), `null` while this window knows of none.

```ts
function useRunStartedAt(sessionId: string | null): number | null
```

**Parameters**

- `sessionId` (`string | null`): The session, `null` for none.

**Returns** `number | null`

Source: [ui/src/chat/composer/use-run-meter.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-run-meter.ts#L66)

### `useSendPrompt`

Function.

Binds the send flow to the hosts and the app's inputs.

```ts
function useSendPrompt(options: SendPromptOptions): SendPromptControls
```

**Parameters**

- `options` (`SendPromptOptions`): See [`SendPromptOptions`](https://zidane.si/docs/reference/ui-chat-composer.md#SendPromptOptions).

**Returns** `SendPromptControls`

Source: [ui/src/chat/composer/use-send-prompt.ts:79](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-send-prompt.ts#L79)

### `useSessionContextStatus`

Function.

The context gauge of a session alone (what the model and effort pickers
read): the same keyed read as [`useSessionMeters`](https://zidane.si/docs/reference/ui-chat-composer.md#useSessionMeters)', so one request.

```ts
function useSessionContextStatus(
  session: SessionMetersTarget | null,
): ComposerContextStatus | null
```

**Parameters**

- `session` (`SessionMetersTarget | null`): The session, `null` for a draft.

**Returns** `ComposerContextStatus | null`: Its context status, `null` while unknown.

Source: [ui/src/chat/composer/use-session-meters.ts:55](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-session-meters.ts#L55)

### `useSessionMeters`

Function.

The meters of the session shown.

```ts
function useSessionMeters(
  session: SessionMetersTarget | null,
  running: boolean,
): SessionMeters
```

**Parameters**

- `session` (`SessionMetersTarget | null`): The session, `null` for a draft.
- `running` (`boolean`): Whether it runs now (a run boundary reads the cost again).

**Returns** `SessionMeters`

Source: [ui/src/chat/composer/use-session-meters.ts:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-session-meters.ts#L39)

### `useSustainedWork`

Function.

The running work to show for a conversation (see the header).

```ts
function useSustainedWork(
  sessionId: string | null,
  items: readonly RunningWorkItem[],
): readonly RunningWorkItem[]
```

**Parameters**

- `sessionId` (`string | null`): The conversation.
- `items` (`readonly RunningWorkItem[]`): Its running work now.

**Returns** `readonly RunningWorkItem[]`

Source: [ui/src/chat/composer/use-sustained-work.ts:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-sustained-work.ts#L40)

### `withPrimary`

Function.

The chain after making `pick` the primary: one account per provider, so
entries naming another account of its provider drop (core
`filterChainFallbacks` would drop them anyway, silently).

```ts
function withPrimary(chain: readonly ModelPickRef[], pick: ModelPickRef): ModelPickRef[]
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The current chain: the primary, then its fallbacks.
- `pick` (`ModelPickRef`): The model to make the primary.

**Returns** `ModelPickRef[]`

Source: [ui/src/chat/composer/model-catalog.ts:135](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L135)

### `workShowDelay`

Function.

How long until `items` should show, in ms: 0 when they already should.

```ts
function workShowDelay(items: readonly RunningWorkItem[], now: number): number
```

**Parameters**

- `items` (`readonly RunningWorkItem[]`): The running work, non-empty.
- `now` (`number`): The current time, epoch ms.

**Returns** `number`

Source: [ui/src/chat/composer/use-sustained-work.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-sustained-work.ts#L29)

## Classes

### `AttachmentRefusedError`

Class.

A file [`readAttachment`](https://zidane.si/docs/reference/ui-chat-composer.md#readAttachment) did not attach, and why.

```ts
class AttachmentRefusedError extends Error
```

**Constructor**

```ts
new AttachmentRefusedError(fileName: string, refusal: AttachmentRefusal)
```

**Parameters**

- `fileName` (`string`): The file's name, for the notice.
- `refusal` (`AttachmentRefusal`): Why it was refused (`empty`, `too-large` with the size and limit, …).

**Returns** `AttachmentRefusedError`

**Properties**

- `fileName` (`string`, readonly): The file's name, for the notice.
- `refusal` (`AttachmentRefusal`, readonly): Why it was refused (`empty`, `too-large` with the size and limit, …).

Source: [ui/src/chat/composer/attachment-ingest.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L28)

## Constants

### `ATTACHMENT_NOTICE_MS`

Constant.

How long the notices about refused files stay, in milliseconds.

```ts
const ATTACHMENT_NOTICE_MS = 8000
```

Source: [ui/src/chat/composer/useAttachmentIngest.ts:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/useAttachmentIngest.ts#L21)

### `DEFAULT_BADGE_ORDER`

Constant.

The default slot of a badge without an `order`.

```ts
const DEFAULT_BADGE_ORDER = 100
```

Source: [ui/src/chat/composer/badge-order.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/badge-order.ts#L20)

### `defaultAttachmentTileLabel`

Constant.

A generic file icon (the PDF icon for a `.pdf`) and the name. The default `AttachmentRowProps.attachmentLabel`.

```ts
const defaultAttachmentTileLabel: AttachmentLabelFn
```

Source: [ui/src/chat/composer/AttachmentTiles.tsx:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AttachmentTiles.tsx#L20)

### `EFFORT_LEVELS`

Constant.

Every reasoning effort level the agent knows, in the TUI picker's order.

```ts
const EFFORT_LEVELS: readonly ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'adaptive']
```

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L21)

### `MAX_FILE_ATTACHMENT_BYTES`

Constant.

Cap on a PDF's or a text file's bytes.

```ts
const MAX_FILE_ATTACHMENT_BYTES: number
```

Source: [dist/chat/pure.d.ts:610](https://github.com/Tahul/zidane/blob/main/dist/chat/pure.d.ts#L610)

### `MAX_IMAGE_ATTACHMENT_BYTES`

Constant.

Cap on an image's bytes. Base64 inflates \~33%, so this keeps the encoded
payload under Anthropic's 5 MB image ceiling while covering essentially
every screenshot. A composer scales a bigger image down to fit.

```ts
const MAX_IMAGE_ATTACHMENT_BYTES: number
```

Source: [dist/chat/pure.d.ts:608](https://github.com/Tahul/zidane/blob/main/dist/chat/pure.d.ts#L608)

### `NO_COMPOSER_HINT`

Constant.

Why a chat action is disabled (its tooltip).

```ts
const NO_COMPOSER_HINT = 'No chat to add to here'
```

Source: [ui/src/chat/composer/composer-bus.ts:96](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L96)

### `OPTION_ICON`

Constant.

Options drawn as a glyph wherever they are shown (the pill, the menu row).

```ts
const OPTION_ICON: Record<string, string>
```

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:41](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L41)

### `PASTE_FOLD_CHAR_THRESHOLD`

Constant.

Character ceiling for SINGLE-line (or few-line) pastes. In the GUI a
50 KB one-liner soft-wraps into a screenful of editor, so a paste of
this many characters folds too. The TUI's own ceiling is higher
(`PASTE_INLINE_MAX_CHARS` in src/tui/prompt/paste.ts, 10,000).

```ts
const PASTE_FOLD_CHAR_THRESHOLD = 4092
```

Source: [ui/src/chat/composer/attachment-ingest.ts:88](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L88)

### `PASTE_FOLD_LINE_THRESHOLD`

Constant.

Line threshold above which a multiline paste folds into a `.txt`
attachment. It matches the TUI (`planTextPaste` in src/tui/prompt/paste.ts
uses `lines.length > 10` after trimming leading and trailing blank lines).
Short multiline pastes (stack traces, paragraphs) stay inline so the
user can edit them; anything longer arrives at the model as a
discrete document part instead of a wall of prompt text.

```ts
const PASTE_FOLD_LINE_THRESHOLD = 10
```

Source: [ui/src/chat/composer/attachment-ingest.ts:80](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachment-ingest.ts#L80)

### `THINKING_LEVELS`

Constant.

The reasoning levels a `ChatHost` accepts in [`SendInput`](https://zidane.si/docs/reference/ui-chat-headless.md#SendInput), from least to most.

```ts
const THINKING_LEVELS: readonly ThinkingLevel[]
```

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L28)

### `TRIGGER`

Constant.

The character that opens each completion: `@` for mentions and `/` for commands.

```ts
const TRIGGER: Record<SuggestionKind, string>
```

Source: [ui/src/chat/composer/suggestions.tsx:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L53)

### `WORK_HOLD_MS`

Constant.

Work that ended keeps showing this long.

```ts
const WORK_HOLD_MS = 1500
```

Source: [ui/src/chat/composer/use-sustained-work.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-sustained-work.ts#L19)

### `WORK_SHOW_MS`

Constant.

Work shorter than this never shows.

```ts
const WORK_SHOW_MS = 800
```

Source: [ui/src/chat/composer/use-sustained-work.ts:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-sustained-work.ts#L17)

## Interfaces

### `AgentPickerDialogProps`

Interface.

Props for [`AgentPickerDialog`](https://zidane.si/docs/reference/ui-chat-composer.md#AgentPickerDialog).

```ts
interface AgentPickerDialogProps
```

**Properties**

- `onClose` (`() => void`): Closes the dialog.
- `onCommitted?` (`() => void | Promise<void>`): Called once a switch is written (refresh the app's session list).
- `session` (`ComposerSessionView`): The session whose agent is switched.

Source: [ui/src/chat/composer/AgentPickerDialog.tsx:24](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AgentPickerDialog.tsx#L24)

### `AgentPickerProps`

Interface.

Props for [`AgentPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#AgentPicker).

```ts
interface AgentPickerProps
```

**Properties**

- `align?` (`Align`, default `'start'`): How the menu lines up along the trigger's edge.
- `className?` (`string`): Extra classes on the root element (the default trigger pill; ignored with `trigger`).
- `draft?` (`boolean`): No session yet: the pick applies to the next chat.
- `fallback?` (`string`): The profile the pill names when `value` is not offered (a session saved on a removed profile).
- `onOpenChange?` (`(open: boolean) => void`): Called when the menu opens or closes.
- `profiles` (`readonly AgentProfile[]`): The profiles to offer. With none, the picker renders nothing.
- `side?` (`Side`, default `'top'`): Preferred side of the trigger for the menu. It flips when it does not fit.
- `style?` (`CSSProperties`): Inline styles on the root element (the default trigger pill; ignored with `trigger`).
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the trigger in place of the pill (a settings row): spread the props onto it.
- `value` (`string`): The current profile id.
- `onChange` (`(id: string) => void | Promise<void>`): Called with the picked profile id. Return a promise to keep the menu open and show "switching" on the picked row until it settles.

Source: [ui/src/chat/composer/AgentPicker.tsx:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AgentPicker.tsx#L33)

### `AgentProfile`

Interface.

An agent profile the picker offers.

```ts
interface AgentProfile
```

**Properties**

- `description?` (`string`): Short text shown under the label in the menu.
- `hint?` (`string`): A dim note at the end of the profile's menu row (what picking it would cost).
- `id` (`string`): Stable profile id. Passed to `onChange` and compared with `value`.
- `label` (`string`): Name shown in the pill and the menu.

Source: [ui/src/chat/composer/AgentPicker.tsx:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AgentPicker.tsx#L21)

### `ApprovalDockProps`

Interface.

Props for [`ApprovalDock`](https://zidane.si/docs/reference/ui-chat-composer.md#ApprovalDock).

```ts
interface ApprovalDockProps
```

**Properties**

- `sessionId` (`string | null`): The conversation whose next approval shows, `null` for a draft.

Source: [ui/src/chat/composer/ApprovalDock.tsx:46](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ApprovalDock.tsx#L46)

### `ArchivedBannerProps`

Interface.

Props for [`ArchivedBanner`](https://zidane.si/docs/reference/ui-chat-composer.md#ArchivedBanner).

```ts
interface ArchivedBannerProps
```

**Properties**

- `className?` (`string`): Extra classes on the tray.
- `onUnarchive` (`() => void`): Unarchives the session.
- `style?` (`CSSProperties`): Inline styles on the tray.

Source: [ui/src/chat/composer/ArchivedBanner.tsx:12](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ArchivedBanner.tsx#L12)

### `AttachmentNoticesProps`

Interface.

Props for [`AttachmentNotices`](https://zidane.si/docs/reference/ui-chat-composer.md#AttachmentNotices).

```ts
interface AttachmentNoticesProps
```

**Properties**

- `className?` (`string`): Where it sits. Default: inset in the composer card, above the tiles.
- `notices` (`readonly string[]`): One sentence per refused file.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onDismiss` (`() => void`): Called when the user closes the notice.

Source: [ui/src/chat/composer/attachments.tsx:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachments.tsx#L53)

### `AttachmentRowProps`

Interface.

Props for [`AttachmentRow`](https://zidane.si/docs/reference/ui-chat-composer.md#AttachmentRow).

```ts
interface AttachmentRowProps
```

**Properties**

- `attachmentLabel?` (`AttachmentLabelFn`): The icon and name a file tile shows. Default: [`defaultAttachmentTileLabel`](https://zidane.si/docs/reference/ui-chat-composer.md#defaultAttachmentTileLabel).
- `attachments` (`readonly ComposerAttachment[]`): The staged attachments, in order.
- `className?` (`string`): Classes merged on the root.
- `exitingIds` (`Set<string>`): Ids of tiles leaving (`useAttachmentRemoval`).
- `onExited` (`(id: string) => void`): A leaving tile finished its exit.
- `onOpenLightbox` (`(id: string, origin: HTMLElement) => void`): Opens the lightbox on a tile, from its element.
- `onRemove` (`(id: string) => void`): Starts removing a tile.
- `style?` (`CSSProperties`): Styles on the root.

Source: [ui/src/chat/composer/AttachmentTiles.tsx:78](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AttachmentTiles.tsx#L78)

### `AttachmentTilesProps`

Interface.

Props for [`AttachmentTiles`](https://zidane.si/docs/reference/ui-chat-composer.md#AttachmentTiles).

```ts
interface AttachmentTilesProps
```

**Properties**

- `attachments` (`readonly ComposerAttachment[]`): The attachments to show. With none, nothing renders.
- `className?` (`string`): Extra classes on the root element.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onOpen` (`(id: string, origin: HTMLElement) => void`): Called with the attachment id and the clicked element when the user opens a preview. Only images, PDFs and text-like files can be opened.
- `onRemove` (`(id: string) => void`): Called with the attachment id when the user removes a tile.

Source: [ui/src/chat/composer/attachments.tsx:94](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/attachments.tsx#L94)

### `ComposerBadge`

Interface.

One badge of a [`ComposerBadges`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerBadges) strip.

```ts
interface ComposerBadge
```

**Properties**

- `active?` (`boolean`): What the badge opens is on screen (its panel): the raised chip, `aria-pressed`.
- `count?` (`string`): A count or a short value after the label (`3`, `2/5`), drawn as a [`CountBadge`](https://zidane.si/docs/reference/ui-components-tab-pill.md#CountBadge).
- `countTone?` (`CountTone`, default ``'info' (`attention` on a highlighted badge)``): Look of the count.
- `highlight?` (`boolean`): Something waits on the user: raised in the warn tone, breathing, kept in view.
- `icon?` (`string`): Leading icon class (`i-ph-list-checks`).
- `id` (`string`): Stable id: the strip's key and what a saved order names.
- `label` (`string`): The badge's name (`Todos`, `Queued`).
- `loader?` (`boolean`): Work in progress: the running arc in place of the icon.
- `onSelect?` (`() => void`): Called on a click, or Enter / Space. Without it the badge is a plain status pill.
- `order?` (`number`): Default slot, lower first (see `orderComposerBadges`). The strip itself draws badges in the order given.
- `title?` (`string`): Tooltip, and the description assistive tech reads with it.
- `tone?` (`ComposerBadgeTone`): Tints the icon. Default: the badge's text color (warn on a highlighted badge).

Source: [ui/src/chat/composer/ComposerBadges.tsx:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerBadges.tsx#L38)

### `ComposerBadgesProps`

Interface.

Props for [`ComposerBadges`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerBadges).

```ts
interface ComposerBadgesProps
```

**Properties**

- `badges` (`readonly ComposerBadge[]`): The badges, in display order. An empty list closes the band.
- `className?` (`string`): Extra classes on the band.
- `label?` (`string`): Accessible name of the strip. Default: the `composerBadges` label.
- `onReorder?` (`(ids: readonly string[]) => void`): Makes badges draggable (and movable with Alt+Shift+←/→); receives every id in the new order, once per move.
- `resetKey?` (`string | null`): What the badges belong to (a session id). A new key shows its badges as
  they are, without animating them in or the previous ones out.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ComposerBadges.tsx:69](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerBadges.tsx#L69)

### `ComposerControlsProps`

Interface.

Props for [`ComposerControls`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerControls).

```ts
interface ComposerControlsProps
```

**Properties**

- `activeEnabledOptions` (`Record<string, boolean>`): The session's enabled options.
- `activeModelOptions` (`readonly ComposerModelOption[]`): The feature toggles the session's model declares.
- `activeSupportsReasoning` (`boolean`): Whether the session's model has a reasoning knob (a draft looks its default model up in the catalog).
- `defaults` (`ComposerDefaults`): The next new chat's defaults.
- `hostId?` (`string | null`): The server the session (or draft) runs on: the pickers list its models. `null`: this computer.
- `images?` (`HostModelImages | null`): The model picker's Image tab. Absent: none.
- `modelId` (`string | null`): The session's model (its own pick, or the one its context status reports).
- `modelShortcut?` (`ReactNode`): The model picker's keyboard shortcut, for its tooltip.
- `onCommitted?` (`() => void | Promise<void>`): Called once a session write lands (refresh the app's session list).
- `onDefaultAgentChange` (`(id: string) => void`): Sets the next new chat's agent.
- `onDefaultModel` (`SetDefaultModel`): Sets the next new chat's model.
- `providerKey` (`string | null`): That model's provider.
- `retry?` (`ReactNode`): Shown between the agent and the model pills (a retry pill).
- `serving?` (`{ model: string; provider: string } | null`): The model serving the run after a fallback.
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft.

Source: [ui/src/chat/composer/ComposerControls.tsx:49](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerControls.tsx#L49)

### `ComposerDefaults`

Interface.

What the next new chat starts on, as the app decides it.

```ts
interface ComposerDefaults
```

**Properties**

- `account` (`string | null`): The stored account its model runs on.
- `agentId` (`string`): Its agent.
- `folder` (`string | null`): Its folder (`null`: none picked yet).
- `knobs?` (`SessionKnobs`): The configured effort and options (the space's, else the app's).
- `modelId` (`string | null`): Its model.
- `providerKey` (`string | null`): Its model's provider.

Source: [ui/src/chat/composer/ComposerControls.tsx:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerControls.tsx#L33)

### `ComposerDockProps`

Interface.

Props for [`ComposerDock`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerDock).

```ts
interface ComposerDockProps
```

**Properties**

- `children` (`ReactNode`): The docked cards; each may render nothing.
- `className?` (`string`): Extra classes on the dock.
- `style?` (`CSSProperties`): Inline styles on the dock.

Source: [ui/src/chat/composer/DockCard.tsx:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L21)

### `ComposerDraft`

Interface.

A whole draft: its text and the attachments to stage, ready (data URLs).

```ts
interface ComposerDraft
```

**Properties**

- `attachments` (`readonly ComposerAttachment[]`): The attachments to stage.
- `text` (`string`): The draft's text.

Source: [ui/src/chat/composer/composer-bus.ts:318](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L318)

### `ComposerHandle`

Interface.

Imperative handle of the [`Composer`](https://zidane.si/docs/reference/ui-chat-composer.md#Composer), reached through its `ref`.

```ts
interface ComposerHandle
```

**Properties**

- `clear` (`() => void`): Empties the draft.
- `focus` (`() => void`): Moves focus to the editor.
- `getText` (`() => string`): The draft as it would be sent.
- `insertText` (`(text: string) => void`): Insert text at the caret (a dropped path, a quoted line).

Source: [ui/src/chat/composer/Composer.tsx:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/Composer.tsx#L140)

### `ComposerHostProviderProps`

Interface.

Props for [`ComposerHostProvider`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerHostProvider).

```ts
interface ComposerHostProviderProps
```

**Properties**

- `children` (`ReactNode`): The app's components.
- `host` (`ComposerHost`): What the composer reads and does beyond sending.
- `labels?` (`Partial<ComposerLabels>`): Overrides for the composer's strings. Keys you leave out keep the default English label.

Source: [ui/src/chat/composer/ComposerHostProvider.tsx:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerHostProvider.tsx#L17)

### `ComposerProps`

Interface.

Props for [`Composer`](https://zidane.si/docs/reference/ui-chat-composer.md#Composer).

```ts
interface ComposerProps
```

**Properties**

- `ariaLabel?` (`string`): The textbox's accessible name (default: the `composerLabel` label).
- `attachments?` (`boolean`): Paste, drop and pick images, PDFs and text files.
- `autoFocus?` (`boolean`, default `false`): Focuses the editor on mount, with the caret at the end.
- `badges?` (`readonly ComposerBadge[]`): The badge strip at the top of the tray ring, above the card, in display order (see `ComposerBadges`).
- `badgesKey?` (`string`): What the badges belong to (a session id): a new key shows its badges without animating them.
- `below?` (`ReactNode`): A band under the card, inside the tray ring (the desktop app's git bar).
- `className?` (`string`): Extra class names for the composer's root element.
- `commands?` (`SuggestionSource`): `/` completions, at the start of the prompt.
- `defaultAttachments?` (`readonly ComposerAttachment[]`): Attachments staged on mount (a restored draft).
- `defaultValue?` (`string`): Initial text of an uncontrolled draft.
- `delivery?` (`MessageDelivery`, default `'queue'`): What Enter does with the draft while `running`: `steer` it into the run or `queue` it for when the run ends.
  Alt+Enter does the other. Pass the user's "Messages during a run" setting.
- `disabled?` (`boolean`, default `false`): Makes the editor read-only and disables sending and attaching.
- `footer?` (`ReactNode`): Controls after the attach button (pickers).
- `history?` (`readonly string[]`): Earlier prompts for ↑ / ↓, oldest first. Absent: what this composer sent while mounted.
- `mentions?` (`SuggestionSource`): `@` completions.
- `onBadgesReorder?` (`(ids: readonly string[]) => void`): Makes the badges draggable; receives every badge id in the new order.
- `placeholder?` (`string`): Placeholder shown while the draft is empty. Default: the `composerPlaceholder` label.
- `running?` (`boolean`): A run is in flight: Enter steers or queues (`delivery`), Escape and the button stop.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`): Controls at the end of the controls row, before Send (a context meter).
- `value?` (`string`): Controlled text of the draft. Use with `onChange`. Omit for an uncontrolled draft.
- `onChange?` (`(text: string) => void`): Called with the draft's text each time it changes.
- `onError?` (`(error: unknown) => void`): The send handler threw (the draft is already back). Absent: the composer shows the error itself.
- `onSend` (`(input: ComposerSubmit) => ComposerResult`): Called when the user sends the draft with Enter or the Send button, also while `running` (see `ComposerSubmit.delivery`). Return `false` or reject to put the draft back.
- `onStop?` (`() => void`): Called when the user stops the running agent with Escape or the Stop button. Without it the composer offers no stop.

Source: [ui/src/chat/composer/Composer.tsx:76](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/Composer.tsx#L76)

### `ComposerStatusPillsProps`

Interface.

Props for [`ComposerStatusPills`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerStatusPills).

```ts
interface ComposerStatusPillsProps
```

**Properties**

- `autoCompactThreshold?` (`number | null`): The fraction auto-compaction starts at, `null` when it is off.
- `contextStatus` (`ComposerContextStatus | null`): Its context status.
- `fetchedCost` (`ComposerCostStatus | null`): Its cost as last read; the pills add what the run settled and streams since (`ComposerHost.runs`).
- `running` (`boolean`): Whether it runs now.
- `sessionId` (`string | null`): The live session, `null` for a draft (nothing shows).

Source: [ui/src/chat/composer/ComposerControls.tsx:185](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerControls.tsx#L185)

### `ComposerSubmit`

Interface.

What the composer hands to `onSend`.

```ts
interface ComposerSubmit
```

**Properties**

- `attachments` (`readonly ComposerAttachment[]`): The staged attachments.
- `delivery?` (`MessageDelivery`): Set while `running`: steer the draft into the run, or queue it for when the run ends.
- `prompt` (`string`): The draft as plain text. Mentions and commands are serialized to text.

Source: [ui/src/chat/composer/Composer.tsx:63](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/Composer.tsx#L63)

### `ComposerTarget`

Interface.

The one composer meant to take a push (a session key, a draft's scope); without one, the window's composer.

```ts
interface ComposerTarget
```

**Properties**

- `scopeKey` (`string`): The composer's scope key.

Source: [ui/src/chat/composer/composer-bus.ts:128](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/composer-bus.ts#L128)

### `ContextBreakdownData`

Interface.

The shaped, render-ready breakdown.

```ts
interface ContextBreakdownData
```

**Properties**

- `activeSkills?` (`string[]`): Names of currently-active skills. Informational — an activated skill's body
  lands in the conversation (tool-results), so its tokens are already counted
  under Conversation; this just surfaces "which skills are loaded". Empty/absent
  when none are active.
- `categories` (`ContextCategory[]`): Live categories (sum to `used`) followed by deferred + free-space buckets.
- `effectiveWindow` (`number`): Effective window (raw - output reserve), the bar's denominator.
- `extensionSections?` (`readonly ContextExtensionSection[]`): Extension-owned context panel sections.
- `fraction` (`number`): `used / effectiveWindow`, clamped to \[0, 1].
- `hasEstimates` (`boolean`): True when ANY live category is estimated (drives the panel's footnote).
- `modelId` (`string`): Model id the snapshot was built for.
- `usage?` (`ContextUsageSplit`): Exact last-turn usage split (cache read / write / fresh input / output),
  when the host supplied it. Always exact — rendered as an informational
  section below the categories. Absent when no usage is available yet.
- `used` (`number`): Real last-turn context size (provider-reported `input + cacheRead +
  cacheCreation`) — the SAME number the footer/orb shows. The non-deferred
  categories sum to this, unless the static categories alone exceed it.

Source: [dist/index-Bq87OcGy.d.ts:20171](https://github.com/Tahul/zidane/blob/main/dist/index-Bq87OcGy.d.ts#L20171)

### `ContextBreakdownProps`

Interface.

Props for [`ContextBreakdown`](https://zidane.si/docs/reference/ui-chat-composer.md#ContextBreakdown).

```ts
interface ContextBreakdownProps
```

**Properties**

- `breakdown` (`ContextBreakdown | null | undefined`): undefined: loading; null: no breakdown (no live agent yet).
- `className?` (`string`): Extra classes on the root element.
- `fallbackColor` (`string`): CSS color of the fallback gauge.
- `fallbackPct` (`number`): The orb's share and color, for the plain gauge while there is no breakdown.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ContextBreakdown.tsx:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextBreakdown.tsx#L84)

### `ContextCost`

Interface.

The session's spend, as the popover's last row and the orb's tooltip show it.

```ts
interface ContextCost
```

**Properties**

- `estimated` (`boolean`): The total includes a streaming turn's running estimate (`~` prefix, no money tint).
- `label` (`string`): Formatted total (`$0.42`).
- `runCount` (`number | null`): Number of runs the cost covers, or `null` when unknown.

Source: [ui/src/chat/composer/ContextOrb.tsx:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L18)

### `ContextGauge`

Interface.

The orb's share in percent and its color, for a breakdown's fallback gauge.

```ts
interface ContextGauge
```

**Properties**

- `color` (`string`): CSS color of the arc: red from 90%, amber from 70%, accent below.
- `pct` (`number`): The used share as a whole percent from 0 to 100.

Source: [ui/src/chat/composer/ContextOrb.tsx:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L48)

### `ContextOrbProps`

Interface.

Props for [`ContextOrb`](https://zidane.si/docs/reference/ui-chat-composer.md#ContextOrb).

```ts
interface ContextOrbProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element (the orb's trigger button).
- `renderBreakdown?` (`(gauge: ContextGauge) => ReactNode`): The popover's breakdown body, mounted while it is open (a host that
  fetches the breakdown on open renders its own). Default:
  `<ContextBreakdown breakdown={usage.breakdown} … />`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `usage` (`ContextUsage`): Everything the orb and its popover show.

Source: [ui/src/chat/composer/ContextOrb.tsx:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L66)

### `ContextUsage`

Interface.

Everything the orb and its popover show.

```ts
interface ContextUsage
```

**Properties**

- `autoCompactThreshold?` (`number | null`): Auto-compact threshold (0–1) when auto-compact is on.
- `breakdown?` (`ContextBreakdown | null`): The breakdown the default popover body renders: undefined loading, null unavailable.
- `cost?` (`ContextCost | null`): The session's spend, shown in the popover and tooltip. `null` or omitted: no cost row.
- `fraction` (`number`): Used share of the effective window, 0–1 (clamped).
- `modelId` (`string`): Id of the model the session runs.
- `modelName?` (`string`): The model's readable name (default: `modelId`).
- `usedLabel` (`string`): Formatted used tokens (`61k`).
- `windowLabel` (`string`): Formatted effective window (`200k`).

Source: [ui/src/chat/composer/ContextOrb.tsx:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ContextOrb.tsx#L28)

### `ConversationBadgesProps`

Interface.

Props for [`ConversationBadges`](https://zidane.si/docs/reference/ui-chat-composer.md#ConversationBadges).

```ts
interface ConversationBadgesProps
```

**Properties**

- `className?` (`string`): Extra classes on the strip.
- `onClosePanel?` (`() => void`): Closes the panel on screen.
- `onOpenPanel?` (`(panel: string) => void`): Opens (and focuses) a panel.
- `onOpenRunningWork?` (`(sessionId: string) => void`): Opens the conversation's Running work view. Absent: the Running badge is a plain pill.
- `onOrderChange?` (`(merge: (saved: readonly string[]) => string[]) => void`): Saves a new order: the saved one with the move merged in (`mergeBadgeOrder`). Absent: badges don't move.
- `onScreen?` (`string | null`): The panel on screen beside the conversation, `null` for none.
- `order?` (`readonly string[]`): The user's order (badge ids).
- `panels` (`ReadonlySet<string>`): The conversation's panel ids: a badge naming another opens nothing.
- `sessionId` (`string | null`): The conversation, `null` for a draft.
- `showTodos?` (`boolean`, default `true`): Show the todos' progress.
- `style?` (`CSSProperties`): Inline styles on the strip.

Source: [ui/src/chat/composer/ConversationBadges.tsx:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ConversationBadges.tsx#L43)

### `Cursor`

Interface.

The highlighted row, and what moved it there: only the keyboard scrolls the list to follow it.

```ts
interface Cursor
```

**Properties**

- `by` (`'key' | 'mouse'`): What moved it there: the keyboard or the pointer.
- `index` (`number`): Index of the row under the cursor.

Source: [ui/src/chat/composer/ModelChainRows.tsx:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainRows.tsx#L40)

### `CycleAgentOptions`

Interface.

Options for [`useCycleAgent`](https://zidane.si/docs/reference/ui-chat-composer.md#useCycleAgent).

```ts
interface CycleAgentOptions
```

**Properties**

- `onCommitted?` (`() => void | Promise<void>`): Called once a switch is written (refresh the app's session list).
- `running` (`boolean`): The session runs now (no switch mid-run).

Source: [ui/src/chat/composer/use-agent-profiles.ts:61](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-agent-profiles.ts#L61)

### `DockCardProps`

Interface.

Props for [`DockCard`](https://zidane.si/docs/reference/ui-chat-composer.md#DockCard).

```ts
interface DockCardProps
```

**Properties**

- `children` (`ReactNode`): The card's content.
- `className?` (`string`): Extra classes on the card.
- `padded?` (`boolean`): `false` when one full-bleed child (a button) owns the padding and the hover.
- `style?` (`CSSProperties`): Inline styles on the card, merged after its own.
- `tone?` (`'attention' | 'default'`): `attention` tints the surface with the warn color, for things awaiting the user.

Source: [ui/src/chat/composer/DockCard.tsx:47](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L47)

### `DockRowProps`

Interface.

Props for [`DockRow`](https://zidane.si/docs/reference/ui-chat-composer.md#DockRow).

```ts
interface DockRowProps
```

**Properties**

- `align?` (`'start' | 'center'`): `start` pins the glyph and trailing actions to the first 28px line of a
  tall body (an inline editor) instead of floating them at its middle.
- `children` (`ReactNode`): The row's body.
- `className?` (`string`): Extra classes on the row.
- `glyph?` (`ReactNode`): Leading glyph in the fixed 12px slot; omit for text flush at the card inset.
- `style?` (`CSSProperties`): Inline styles on the row.
- `trailing?` (`ReactNode`): Actions at the end.

Source: [ui/src/chat/composer/DockCard.tsx:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/DockCard.tsx#L84)

### `DraftServer`

Interface.

A saved server a draft can run on.

```ts
interface DraftServer
```

**Properties**

- `id` (`string`): Its host id.
- `name` (`string`): Its name.

Source: [ui/src/chat/composer/use-draft-target.ts:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-draft-target.ts#L37)

### `DraftTarget`

Interface.

The draft's target and its picks, as the composer's where menu and folder pickers read them.

```ts
interface DraftTarget
```

**Properties**

- `cloning` (`boolean`): The send is cloning `DraftTarget.remoteClone`.
- `environment` (`DraftEnvironment | null`): The draft's environment pick (`null`: the default).
- `environmentChoices` (`readonly EnvironmentDescriptor[]`): The environment kinds the draft's host offers.
- `error` (`string | null`): Why the last new chat could not be created (the prompt is back in the box).
- `folderPath` (`string | null`): `null`: no folder picked yet (the folder gate shows); `''`: none.
- `importRepoOnServer?` (`() => Promise<void>`): Clones a repository on the server and opens the draft in it. Absent: the server takes no clones.
- `machine?` (`{ id: string; name: string; status: 'online' | 'offline' }`): The machine the picked environment runs on.
- `machineFolder` (`string | null`): The machine's folder (`null`: its first one).
- `machineHost` (`string`): The host the machine's folders are browsed through.
- `recentFolders` (`readonly string[]`): This computer's recent folders.
- `remoteClone` (`DraftRemoteClone | null`): On a server with no folder picked: the local project's repository, cloned there on send. `null`: nothing to clone.
- `remoteFolder` (`string | null`): The server's folder (`null`: its first root).
- `remoteRoot` (`string | null`): The server's first workspace root (the default folder), once read.
- `server?` (`DraftServer`): The saved server the draft runs on (absent: this computer).
- `serverFolders` (`readonly string[]`): The server's recent folders (its sessions' folders), most recent first.
- `importRepoIntoDraft` (`() => Promise<void>`): Imports a repository and opens the draft in it.
- `justChat` (`() => void`): "Start without a folder" for this draft.
- `pickFolder` (`() => Promise<void>`): Picks a folder on this computer (the git host's dialog).
- `pickRecent` (`(folder: string) => void`): Picks one of `DraftTarget.recentFolders`.
- `setCloning` (`(cloning: boolean) => void`): Marks the clone of a send as running or done.
- `setEnvironment` (`(environment: DraftEnvironment | null) => void`): Picks the draft's environment.
- `setError` (`(error: string | null) => void`): Shows or clears `DraftTarget.error`.
- `setHostId` (`(hostId: string) => void`): Runs the draft on a saved server (`LOCAL_HOST_KEY`: this computer).
- `setMachineFolder` (`(folder: string | null) => void`): Picks the machine's folder.
- `setRemoteFolder` (`(folder: string | null) => void`): Picks the server's folder.

Source: [ui/src/chat/composer/use-draft-target.ts:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-draft-target.ts#L84)

### `DraftTargetOptions`

Interface.

What [`useDraftTarget`](https://zidane.si/docs/reference/ui-chat-composer.md#useDraftTarget) reads from the app.

```ts
interface DraftTargetOptions
```

**Properties**

- `defaultFolder` (`string | null`): The folder new chats open in (`null`: none picked yet).
- `request?` (`DraftTargetRequest | null`): A pick made elsewhere (a server project's header in the sidebar, the
  Chats header): the draft moves to that host and folder, or to no folder,
  once per `seq`. A folder on this computer goes through `defaultFolder`
  instead.
- `servers` (`readonly DraftServer[]`): The saved servers a draft can run on.
- `session` (`{ cwd: string; id: string } | null`): The open session (its folder, `''` for none); `null` for the new-chat draft.
- `sessions` (`readonly DraftFolderSource[]`): The session rows, most recently updated first: the folder menu's recent folders.
- `onLocalFolder?` (`(folder: string | null) => void`): Hears the draft's folder on this computer while the draft shows, `null` once it leaves. Absent: not told.
- `setDefaultFolder` (`(folder: string) => void`): Makes `folder` the one new chats open in.

Source: [ui/src/chat/composer/use-draft-target.ts:45](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-draft-target.ts#L45)

### `DraftTargetRequest`

Interface.

A draft target picked outside the composer.

```ts
interface DraftTargetRequest
```

**Properties**

- `environment?` (`string`): The environment kind to pick (a machine's: `local@<name>`); absent: the default.
- `folder` (`string | null`): Its folder (`null`: its first root).
- `folderless?` (`boolean`): A chat with no folder, on the request's host ("Start without a folder"); `folder` is ignored.
- `hostId` (`string`): The saved server.
- `machineFolder?` (`string`): The folder on the machine `DraftTargetRequest.environment` names, once that machine resolves.
- `seq` (`number`): Grows with each request: a new one applies even to the same target.

Source: [ui/src/chat/composer/use-draft-target.ts:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-draft-target.ts#L68)

### `EffortPickerDialogProps`

Interface.

Props for [`EffortPickerDialog`](https://zidane.si/docs/reference/ui-chat-composer.md#EffortPickerDialog).

```ts
interface EffortPickerDialogProps
```

**Properties**

- `enabled` (`Record<string, boolean>`): Currently-enabled option ids.
- `onApplyEffort` (`(effort: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive') => void | Promise<void>`): Applies an effort (the dialog closes once it settles).
- `onToggleOption` (`(next: Record<string, boolean>) => void | Promise<void>`): Applies the enabled options after a toggle (the dialog stays open).
- `options` (`readonly ComposerModelOption[]`): Feature options the active model declares (toggle section).
- `session` (`ComposerSessionView`): The session whose knobs are set.
- `supportsReasoning` (`boolean`): Whether the active model exposes a reasoning knob (effort section).

Source: [ui/src/chat/composer/EffortPickerDialog.tsx:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/EffortPickerDialog.tsx#L31)

### `HostAgentPickerProps`

Interface.

Props for [`HostAgentPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#HostAgentPicker).

```ts
interface HostAgentPickerProps
```

**Properties**

- `defaultAgentId` (`string`): The next new chat's agent.
- `defaultCwd?` (`string`): The folder a draft's profiles come from (`''`: none).
- `onCommitted?` (`() => void | Promise<void>`): Called once a session's switch is written (refresh the app's session list).
- `onDefaultAgentChange` (`(id: string) => void`): Sets it (a draft's pick).
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft (the pick is the next chat's default).

Source: [ui/src/chat/composer/HostPickers.tsx:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L36)

### `HostComposerProps`

Interface.

Props for [`HostComposer`](https://zidane.si/docs/reference/ui-chat-composer.md#HostComposer): the [`ComposerProps`](https://zidane.si/docs/reference/ui-chat-composer.md#ComposerProps) the host does not drive, plus `sessionId`, `defaultModel`, `defaultThinking`, and `footer`.

```ts
interface HostComposerProps extends Omit<ComposerProps, 'onSend' | 'running' | 'onStop' | 'footer'>
```

**Properties**

- `ariaLabel?` (`string`, from `Omit`): The textbox's accessible name (default: the `composerLabel` label).
- `attachments?` (`boolean`, from `Omit`): Paste, drop and pick images, PDFs and text files.
- `autoFocus?` (`boolean`, from `Omit`, default `false`): Focuses the editor on mount, with the caret at the end.
- `badges?` (`readonly ComposerBadge[]`, from `Omit`): The badge strip at the top of the tray ring, above the card, in display order (see `ComposerBadges`).
- `badgesKey?` (`string`, from `Omit`): What the badges belong to (a session id): a new key shows its badges without animating them.
- `below?` (`ReactNode`, from `Omit`): A band under the card, inside the tray ring (the desktop app's git bar).
- `className?` (`string`, from `Omit`): Extra class names for the composer's root element.
- `commands?` (`SuggestionSource`, from `Omit`): `/` completions, at the start of the prompt.
- `defaultAttachments?` (`readonly ComposerAttachment[]`, from `Omit`): Attachments staged on mount (a restored draft).
- `defaultModel?` (`string`): The model to start on (`provider/model` or a bare id). Default: the session's, else the first offered.
- `defaultThinking?` (`ThinkingLevel`): Default `medium`.
- `defaultValue?` (`string`, from `Omit`): Initial text of an uncontrolled draft.
- `delivery?` (`MessageDelivery`, from `Omit`, default `'queue'`): What Enter does with the draft while `running`: `steer` it into the run or `queue` it for when the run ends.
  Alt+Enter does the other. Pass the user's "Messages during a run" setting.
- `disabled?` (`boolean`, from `Omit`, default `false`): Makes the editor read-only and disables sending and attaching.
- `footer?` (`ReactNode`): Controls after the pickers.
- `history?` (`readonly string[]`, from `Omit`): Earlier prompts for ↑ / ↓, oldest first. Absent: what this composer sent while mounted.
- `mentions?` (`SuggestionSource`, from `Omit`): `@` completions.
- `onBadgesReorder?` (`(ids: readonly string[]) => void`, from `Omit`): Makes the badges draggable; receives every badge id in the new order.
- `onChange?` (`(text: string) => void`, from `Omit`)
- `onError?` (`(error: unknown) => void`, from `Omit`)
- `onModelChange?` (`(key: string) => void`): Called with the `provider/model` key when the user picks a model.
- `placeholder?` (`string`, from `Omit`): Placeholder shown while the draft is empty. Default: the `composerPlaceholder` label.
- `sessionId` (`string`): Id of the session the composer sends to.
- `style?` (`CSSProperties`, from `Omit`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`, from `Omit`): Controls at the end of the controls row, before Send (a context meter).
- `value?` (`string`, from `Omit`): Controlled text of the draft. Use with `onChange`. Omit for an uncontrolled draft.

Source: [ui/src/chat/composer/HostComposer.tsx:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostComposer.tsx#L25)

### `HostContextOrbProps`

Interface.

Props for [`HostContextOrb`](https://zidane.si/docs/reference/ui-chat-composer.md#HostContextOrb).

```ts
interface HostContextOrbProps
```

**Properties**

- `autoCompactThreshold?` (`number | null`): The fraction auto-compaction starts at, `null` when it is off.
- `className?` (`string`): Extra classes on the orb.
- `cost` (`LiveCostStatus | null`): Its live cost.
- `modelName?` (`string`): The model's display name. Default: its id.
- `sessionId` (`string`): The session the gauge measures.
- `status` (`ComposerContextStatus`): Its context status.

Source: [ui/src/chat/composer/HostContextOrb.tsx:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostContextOrb.tsx#L18)

### `HostModelChainListProps`

Interface.

Props for [`HostModelChainList`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelChainList).

```ts
interface HostModelChainListProps
```

**Properties**

- `catalog?` (`readonly ComposerModelEntry[] | null`): Pre-loaded catalog, or `null` to load the host's for `cwd`.
- `className?` (`string`): Max list height class.
- `cwd?` (`string`): The folder whose models are listed.
- `dense?` (`boolean`): Compact one-line rows for a popover.
- `hostId?` (`string | null`): A server's session: its models.
- `initialChain` (`readonly ModelPickRef[]`): Seed chain: entry 0 = current primary, 1+ = persisted fallbacks. Empty = nothing picked yet.
- `onChainChange` (`(chain: ModelPickRef[]) => void`): Every draft change, including the initial seed.
- `onQuickPick?` (`(chain: ModelPickRef[]) => void`): A plain click / ↵ on a row while the chain has at most one entry: the
  user is doing a quick swap, not building a chain. Callers that want
  "pick and close" act here; the dialog ignores it.
- `sessionId?` (`string | null`): The session a pick switches: models other than its own say what they would re-read.
- `single?` (`boolean`): One model, no chain (a settings default): every pick fires `onQuickPick`; no fallbacks.

Source: [ui/src/chat/composer/HostModelChainList.tsx:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostModelChainList.tsx#L25)

### `HostModelImages`

Interface.

The image models tab of a model picker.

```ts
interface HostModelImages
```

**Properties**

- `onPick` (`(key: string) => void`): Picks one.
- `value` (`string`): The picked image model (`providerKey/modelId`, `''` for the default).

Source: [ui/src/chat/composer/HostPickers.tsx:102](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L102)

### `HostModelOptionsPickerProps`

Interface.

Props for [`HostModelOptionsPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelOptionsPicker).

```ts
interface HostModelOptionsPickerProps
```

**Properties**

- `commitTo?` (`() => Promise<string>`): The session a pick applies to, resolved on commit (see `HostModelPicker`). Default: `session`.
- `enabled` (`Record<string, boolean>`): The session's enabled options.
- `modelId` (`string | null`): Its model: picks are remembered for it.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `options` (`readonly ComposerModelOption[]`): The feature toggles it declares.
- `remember?` (`boolean`): Whether picks are remembered for their model (the next new chat's knobs). `false` for a side chat.
- `session` (`ComposerSessionView`): The live session.
- `supportsReasoning` (`boolean`): The model has a reasoning effort knob.
- `title?` (`string`): The pill's tooltip. Default: the `modelOptionsTitle` label.

Source: [ui/src/chat/composer/HostPickers.tsx:239](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L239)

### `HostModelPickerProps`

Interface.

Props for [`HostModelPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#HostModelPicker).

```ts
interface HostModelPickerProps
```

**Properties**

- `account?` (`string | null`): The stored account it runs on; `null` = the active one.
- `catalog` (`readonly ComposerModelEntry[] | null`): The catalog the controls loaded; `null` while it loads.
- `catalogError?` (`string | null`): Why the catalog failed to load (the list offers a retry).
- `commitTo?` (`() => Promise<string>`): The session a pick applies to, resolved on commit (a side chat creates its session then). Default: `session`.
- `hostId?` (`string | null`): The server the session (or draft) runs on: its models are listed.
- `images?` (`HostModelImages | null`): The Image tab. Absent: none.
- `modelId` (`string | null`): The model being steered: the session's, or the draft's default.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `onDefaultModel` (`SetDefaultModel`): Sets the app's default model.
- `onRetryCatalog?` (`() => void`): Reads the catalog again.
- `providerKey` (`string | null`): Its provider.
- `remember?` (`boolean`): Whether a pick also becomes the next new chat's model. `false` for a side chat.
- `serving?` (`{ model: string; provider: string } | null`): The model actually serving the run after a fallback (the pill shows it, amber).
- `session` (`ComposerSessionView | null`): The live session, `null` for a draft.
- `shortcut?` (`ReactNode`): The keyboard shortcut the pill's tooltip shows.

Source: [ui/src/chat/composer/HostPickers.tsx:110](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPickers.tsx#L110)

### `HostPickerProps`

Interface.

Props for [`HostPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#HostPicker).

```ts
interface HostPickerProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element (the trigger's segment track).
- `hosts` (`readonly HostView[]`): This computer first, then the servers.
- `onChange` (`(hostId: string) => void`): A host was picked.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`string`): The picked host's id.

Source: [ui/src/chat/composer/HostPicker.tsx:16](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/HostPicker.tsx#L16)

### `ImageModelListProps`

Interface.

Props for [`ImageModelList`](https://zidane.si/docs/reference/ui-chat-composer.md#ImageModelList).

```ts
interface ImageModelListProps
```

**Properties**

- `className?` (`string`): Height class of the list.
- `dense?` (`boolean`): Compact one-line rows, as in the popover. Default true.
- `loadError?` (`string | null`): Why the list failed to load.
- `onPick` (`(key: string) => void`): Called with the picked model's `providerKey/modelId`.
- `onQueryChange?` (`(query: string) => void`): Called on each edit of a caller-kept `query`.
- `onRetry?` (`() => void`): Asks for the list again; shown as a Retry next to `loadError`.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the Legacy switch.
- `query?` (`string`): The search text, when the caller keeps it (shared with another list). Absent: the list keeps its own.
- `rows` (`readonly ImageModelRow[] | null`): The image models; `null` while they load.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls on the row under the search field, before the Legacy switch.
- `value` (`string`): The stored default, `providerKey/modelId` or '' (the model the tool falls back to).

Source: [ui/src/chat/composer/ImageModelList.tsx:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ImageModelList.tsx#L70)

### `MentionItem`

Interface.

One completion offered by a [`SuggestionSource`](https://zidane.si/docs/reference/ui-chat-composer.md#SuggestionSource): a file, a session, a command.

```ts
interface MentionItem
```

**Properties**

- `description?` (`string`): Short text shown under the label in the popup.
- `icon?` (`string`): A Uno icon class (`i-ph-file`) drawn in the row.
- `id` (`string`): What the host resolves (a path, a session id, a command name).
- `label` (`string`): What the popup and the badge show.

Source: [ui/src/chat/composer/suggestions.tsx:16](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L16)

### `ModelCatalogState`

Interface.

A model catalog as a picker reads it.

```ts
interface ModelCatalogState
```

**Properties**

- `catalog` (`readonly ComposerModelEntry[] | null`): The rows, `null` while loading.
- `error` (`string | null`): Why it failed to load.
- `retry` (`(() => void) | undefined`): Reads it again.

Source: [ui/src/chat/composer/use-composer-stores.ts:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-composer-stores.ts#L48)

### `ModelChainFooterProps`

Interface.

Props for [`ModelChainFooter`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainFooter).

```ts
interface ModelChainFooterProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `hiddenLegacy` (`number`): Legacy models the lineup hides; 0: no hint.
- `multi` (`boolean`): The chain has more than one model: the count explains the order.
- `onShowLegacy` (`() => void`): Called when the user clicks the hidden legacy models hint.
- `pad` (`string`): Horizontal padding class, the picker's.
- `selected` (`number`): Models in the chain.
- `single` (`boolean`): One model, no chain: no fallback hint and no selected count.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainParts.tsx:86](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L86)

### `ModelChainHeaderProps`

Interface.

Props for [`ModelChainHeader`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainHeader).

```ts
interface ModelChainHeaderProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `inputRef` (`RefObject<HTMLInputElement | null>`): The field, so the list can hand focus back to it after a jump.
- `onQuery` (`(query: string) => void`): Called with the search field's text on each edit.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the Legacy switch.
- `pad` (`string`): Horizontal padding class, the picker's.
- `pills?` (`ReactNode`): The provider pills (`ModelProviderPills`); absent while there are no sections.
- `query` (`string`): The search field's text.
- `showLegacy` (`boolean`): The Legacy switch is on: every model is listed.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls at the start of the row under the field.

Source: [ui/src/chat/composer/ModelChainParts.tsx:164](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L164)

### `ModelChainImages`

Interface.

The Image tab of [`ModelChainPopover`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainPopover).

```ts
interface ModelChainImages
```

**Properties**

- `loadError?` (`string | null`): Why the list failed to load.
- `onPick` (`(key: string) => void`): Called with the picked `providerKey/modelId`. The popover stays open.
- `rows` (`readonly ImageModelRow[] | null`): The image models; `null` while they load.
- `value` (`string`): The stored default, `providerKey/modelId` or '' (the model the tool falls back to).

Source: [ui/src/chat/composer/ModelPicker.tsx:232](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L232)

### `ModelChainListProps`

Interface.

Props for [`ModelChainList`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainList).

```ts
interface ModelChainListProps
```

**Properties**

- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered; `null` while they load.
- `className?` (`string`): Max list height class.
- `customIds?` (`boolean`): A query that matches nothing offers itself as a model id (`offCatalogRows`). Default true.
- `dense?` (`boolean`): Compact one-line rows for the popover.
- `emptyText?` (`string`): What the list says when the catalog is empty. Default: no provider is signed in.
- `initialChain` (`readonly ModelPickRef[]`): Seed chain: entry 0 = current primary, 1+ = fallbacks. Empty = nothing picked yet.
- `loadError?` (`string | null`): Why the catalog failed to load.
- `onChainChange` (`(chain: ModelPickRef[]) => void`): Every draft change, including the initial seed.
- `onQueryChange?` (`(query: string) => void`): Called on each edit of a caller-kept `query`.
- `onQuickPick?` (`(chain: ModelPickRef[]) => void`): A plain click / ↵ on a row while the chain has at most one entry: a
  quick swap, not building a chain. A popover picks and closes here.
- `onRetry?` (`() => void`): Asks for the catalog again; shown as a Retry next to `loadError`.
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the list between the newest models of each family and every model.
- `query?` (`string`): The search text, when the caller keeps it (shared with another list). Absent: the list keeps its own.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `single?` (`boolean`): One model, no chain: every pick replaces the selection and fires `onQuickPick`; no fallbacks.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `toolbar?` (`ReactNode`): Controls on the row under the search field, before the Legacy switch.

Source: [ui/src/chat/composer/ModelChainList.tsx:83](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainList.tsx#L83)

### `ModelChainPopoverProps`

Interface.

Props for [`ModelChainPopover`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainPopover).

```ts
interface ModelChainPopoverProps
```

**Properties**

- `ariaLabel?` (`string`): The popover's name. Default `labels.switchModel`, or `labels.chooseModel` with nothing picked.
- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered; `null` while they load.
- `chain` (`readonly ModelPickRef[]`): The chain in force: the primary, then its fallbacks. Empty: none picked yet.
- `className?` (`string`): Extra classes on the root element (the model pill's frame).
- `forNextChat?` (`boolean`): The chain is the default for the next chat, not a session's: the tooltip says so.
- `images?` (`ModelChainImages`): The image models and the default one: adds the Image tab. Absent: the popover lists chat models only.
- `kind?` (`ModelKind`): Shows one kind of model only, with no Chat / Image switch. `image` needs
  `images`, and the pill then names the default image model. Default: both
  kinds when `images` is given, chat models otherwise.
- `loadError?` (`string | null`): Why the catalog failed to load.
- `name?` (`string | null`): The pill's name. Default: the primary's natural name from the catalog (`modelNameOf`).
- `onCommit` (`(chain: ModelPickRef[]) => void | Promise<void>`): A pick: a plain one (the popover closes after it settles), or an edited chain on dismiss.
- `onOpenChange?` (`(open: boolean) => void`): Called when the popover opens or closes (a row's `details` can then carry what picking it would cost).
- `onRetry?` (`() => void`): Asks for the catalog again (a Retry next to `loadError`).
- `onShowLegacyChange` (`(showLegacy: boolean) => void`): Called when the user toggles the list between the newest models of each family and every model.
- `serving?` (`string | null`): A fallback serving this run instead of the primary, by name: the pill shows it in amber.
- `shortcut?` (`ReactNode`): The key binding that opens the popover (`ctrl+m`), drawn as keycaps on the tooltip's last line.
- `showLegacy` (`boolean`): List every model, not only the newest of each family.
- `single?` (`boolean`): One model, no fallbacks.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelPicker.tsx:185](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L185)

### `ModelChainRowProps`

Interface.

Props for [`ModelChainRow`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainRow).

```ts
interface ModelChainRowProps
```

**Properties**

- `blocked?` (`boolean`): Another account of this provider is in the chain: picking replaces it, it can't be a fallback.
- `className?` (`string`): Extra classes on the root element.
- `dense` (`boolean`): Compact one-line row, as in the popover.
- `entry` (`ModelCatalogRow`): The model the row shows.
- `height` (`number`): The row's height in pixels.
- `idx` (`number`): The row's index in the list, handed back to the handlers.
- `isCursor` (`boolean`): The keyboard cursor is on the row.
- `isNew` (`(key: string) => boolean`): The row joined the list with this commit: it sharpens in.
- `legacy` (`boolean`): An older model the lineup would hide: drawn dimmed.
- `numbered` (`boolean`): Its place in the chain shows up front: the In use rows once two or more
  are picked. Elsewhere a chain member keeps its check, and no row keeps an
  empty column for a number.
- `onHover` (`(idx: number) => void`): Called with `idx` when the pointer moves over the row.
- `onPick` (`(idx: number, shift: boolean) => void`): Called with `idx` and whether Shift was held when the user picks the row.
- `onRemove?` (`(idx: number) => void`): Absent: the row can't be removed from here (single mode).
- `position` (`number | null`): 1-based place in the chain; `null`: not in it.
- `route?` (`boolean`): A typed id's route: the provider is the row's name, the id sits in the group header.
- `showProvider` (`boolean`): The provider chip (the pinned "In use" rows, from several providers).
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `top` (`number`): Offset below its section's header.

Source: [ui/src/chat/composer/ModelChainRow.tsx:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainRow.tsx#L22)

### `ModelChainRowsProps`

Interface.

Props for [`ModelChainRows`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainRows).

```ts
interface ModelChainRowsProps
```

**Properties**

- `chain` (`readonly ModelPickRef[]`): The picked models, primary first.
- `className?` (`string`): Extra classes on the root element.
- `countHidden` (`boolean`): Headers say how many models the lineup hides (not while searching, nor with Legacy on).
- `current` (`ReadonlySet<string>`): The lineup: a row outside it is tagged legacy.
- `cursor` (`Cursor`): The row under the cursor; a keyboard move keeps it in view.
- `dense` (`boolean`): Compact one-line rows, as in the popover.
- `isNew` (`(key: string) => boolean`): The row joined the list with this commit: it sharpens in. Asked as a row mounts.
- `jump` (`{ key: string; seq: number } | null`): A provider pill's jump: brings its section to the top; `seq` makes a repeat a new jump.
- `layout` (`ModelListLayout`): Where each section and row sits (`model-list-layout`).
- `onHover` (`(index: number) => void`): Called with a row's index when the pointer moves over it.
- `onPick` (`(index: number, shift: boolean) => void`): Called with a row's index and whether Shift was held when the user picks it.
- `onRemove` (`(index: number) => void`): Called with a row's index when the user removes it from the chain.
- `onSpy` (`(key: string | null) => void`): The section under the list's top edge, whenever it changes.
- `onUserMove` (`() => void`): The user moved the list (wheel, pointer): a pill's pin lets go.
- `single` (`boolean`): One model, no chain: rows can't be removed from the list.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainRows.tsx:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainRows.tsx#L48)

### `ModelChainTooltipProps`

Interface.

Props for [`ModelChainTooltip`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelChainTooltip).

```ts
interface ModelChainTooltipProps
```

**Properties**

- `catalog` (`readonly ModelCatalogRow[] | null`): The models offered, to describe each pick; `null` while they load (picks show by id).
- `chain` (`readonly ModelPickRef[]`): The chain in force: the primary, then its fallbacks. Empty: none picked yet.
- `className?` (`string`): Extra classes on the root element.
- `footer?` (`ReactNode`): How to change it, on the last line (`Switch model` and its keycaps).
- `forNextChat?` (`boolean`): The chain is the default for the next chat, not a session's.
- `serving?` (`string | null`): A fallback serving this run instead of the primary, by name.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainTooltip.tsx:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainTooltip.tsx#L19)

### `ModelChoice`

Interface.

A model picked from a provider's catalog.

```ts
interface ModelChoice
```

**Properties**

- `key` (`string`): `provider/model`, what `SendInput.model` takes.
- `model` (`ChatModel`): The model.
- `provider` (`ChatModelProvider`): The provider that offers the model.

Source: [ui/src/chat/composer/ModelPicker.tsx:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L43)

### `ModelFlagProps`

Interface.

Props for [`ModelFlag`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelFlag).

```ts
interface ModelFlagProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `hint` (`string`): The tooltip.
- `icon` (`string`): Icon class, for example `i-ph-brain`.
- `label` (`string`): What the glyph stands for, read by assistive tech.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:88](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L88)

### `ModelGroupHeaderProps`

Interface.

Props for [`ModelGroupHeader`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelGroupHeader).

```ts
interface ModelGroupHeaderProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `group` (`PickerGroup`): The section the header names.
- `hidden` (`number`): Models of the section the lineup hides; 0: no count.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelChainParts.tsx:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelChainParts.tsx#L17)

### `ModelMetaProps`

Interface.

Props for [`ModelMeta`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelMeta).

```ts
interface ModelMetaProps
```

**Properties**

- `entry` (`ModelCatalogRow`): The catalog row.
- `legacy?` (`boolean`): Newer models exist in its family.
- `route?` (`boolean`): A typed id's route: the route row says what it is, so no `not in catalog` mark.

Source: [ui/src/chat/composer/ModelFacts.tsx:154](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L154)

### `ModelOption`

Interface.

A feature toggle a model declares.

```ts
interface ModelOption
```

**Properties**

- `description?` (`string`): Short text shown under the label.
- `id` (`string`): Stable option id. Keys the `enabled` map.
- `label` (`string`): Name shown on the option's menu row.

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L31)

### `ModelOptionsPickerProps`

Interface.

Props for [`ModelOptionsPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelOptionsPicker). `L` is the type of the effort levels.

```ts
interface ModelOptionsPickerProps<L extends string>
```

**Type parameters**

- `L` (`extends string`)

**Properties**

- `align?` (`Align`, default `'start'`): How the menu lines up along the trigger's edge.
- `className?` (`string`): Extra classes on the root element (the default trigger pill; ignored with `trigger`).
- `effort` (`L | undefined`): The current reasoning effort level; `undefined` while none is chosen (a default left unset).
- `effortHints?` (`Partial<Record<L, string>>`): A dim note at the end of an effort row, by level (what picking it would cost).
- `enabled` (`Record<string, boolean>`): Currently-enabled option ids.
- `levels?` (`readonly L[]`): The effort rows. Default `EFFORT_LEVELS`.
- `onEffort` (`(level: L) => void | Promise<void>`): Called with the level the user picks. Return a promise to keep the menu busy until it settles.
- `onOpenChange?` (`(open: boolean) => void`): Called when the menu opens or closes.
- `onOptions` (`(next: Record<string, boolean>) => void | Promise<void>`): Called with the full enabled map after the user toggles an option.
- `options` (`readonly ModelOption[]`): The feature toggles the model declares, listed as checkboxes.
- `side?` (`Side`, default `'top'`): Preferred side of the trigger for the menu. It flips when it does not fit.
- `style?` (`CSSProperties`): Inline styles on the root element (the default trigger pill; ignored with `trigger`).
- `supportsReasoning` (`boolean`): The model supports reasoning effort. When false the menu has no effort section.
- `title?` (`string`): The pill's tooltip. Default `labels.modelOptionsHint`.
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the trigger in place of the pill (a settings row): spread the props onto it.

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:44](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L44)

### `ModelPickerDialogProps`

Interface.

Props for [`ModelPickerDialog`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPickerDialog).

```ts
interface ModelPickerDialogProps
```

**Properties**

- `currentModelId` (`string | null`): Its model now (may differ from its own pick when it has none).
- `currentProviderKey` (`string | null`): That model's provider.
- `onCommitted?` (`() => void | Promise<void>`): Called once a pick is written (refresh the app's session list).
- `onDefaultModel` (`SetDefaultModel`): Sets the app's default model (the next new chat's).
- `session` (`ComposerSessionView`): The session whose model is picked.

Source: [ui/src/chat/composer/ModelPickerDialog.tsx:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPickerDialog.tsx#L20)

### `ModelPickerFrameProps`

Interface.

Props for [`ModelPickerFrame`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPickerFrame).

```ts
interface ModelPickerFrameProps
```

**Properties**

- `ariaLabel?` (`string`): The popover's name. Default `labels.switchModel`, or `labels.chooseModel` with nothing picked.
- `children` (`(close: () => void) => ReactNode`): Renders the popover's body. Receives a function that closes the popover.
- `className?` (`string`): Extra classes on the root element (the pill, or its tooltip's wrapper when `tooltip` is set).
- `fallbacks?` (`number`): How many fallbacks follow it in its chain: a `+N` suffix.
- `name` (`string | null`): The picked model's name; null: none picked yet (`labels.chooseModel`).
- `onDismiss?` (`() => void`): Called when the popover is dismissed (Escape, outside press, or the trigger).
- `onOpenChange?` (`(open: boolean) => void`): Called when the popover opens or closes.
- `serving?` (`string | null`): A fallback serving this run instead of the pick: shown in amber in its place.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `tooltip?` (`ReactNode`): Shown while the pill is hovered or keyboard-focused, never while the popover is open. Absent: none.
- `width?` (`number`): Default 440.

Source: [ui/src/chat/composer/ModelPicker.tsx:84](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L84)

### `ModelPickerProps`

Interface.

Props for [`ModelPicker`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelPicker).

```ts
interface ModelPickerProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element (the model pill's frame).
- `providers` (`readonly ChatModelProvider[]`): The providers and models to offer, usually `host.models`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `value` (`string | null`): The current `provider/model` key (or bare id); null: none picked yet.
- `onChange` (`(choice: ModelChoice) => void`): Called with the choice when the user picks a model.

Source: [ui/src/chat/composer/ModelPicker.tsx:476](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L476)

### `ModelProviderChipProps`

Interface.

Props for [`ModelProviderChip`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelProviderChip).

```ts
interface ModelProviderChipProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'providerKey' | 'providerLabel' | 'account'>`): The catalog row whose provider and account to name.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L19)

### `ModelProviderPillsProps`

Interface.

Props for [`ModelProviderPills`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelProviderPills).

```ts
interface ModelProviderPillsProps
```

**Properties**

- `active` (`string | null`): The section under the list's top edge.
- `className?` (`string`): Extra classes on the root element.
- `dense` (`boolean`): Compact one-line rows, as in the popover.
- `groups` (`readonly PickerGroup<ModelCatalogRow>[]`): The sections to jump to, in list order: In use, then each provider.
- `onJump` (`(key: string) => void`): Called with a section's key when the user clicks its pill.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelProviderPills.tsx:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelProviderPills.tsx#L18)

### `ModelReasoningProps`

Interface.

Props for [`ModelReasoning`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelReasoning).

```ts
interface ModelReasoningProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'supportsReasoning'>`): The catalog row.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:125](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L125)

### `ModelWindowProps`

Interface.

Props for [`ModelWindow`](https://zidane.si/docs/reference/ui-chat-composer.md#ModelWindow).

```ts
interface ModelWindowProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `entry` (`Pick<ModelCatalogRow, 'contextWindow' | 'offCatalog'>`): The catalog row.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/ModelFacts.tsx:54](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelFacts.tsx#L54)

### `NewSessionDefaults`

Interface.

What a new session starts with, and the writers of each pick.

```ts
interface NewSessionDefaults
```

**Properties**

- `defaultAccount` (`string | null`): The stored account the model runs on, `null` for the active one.
- `defaultAgentId` (`string`): The agent: this chat's pick, else the space's, else `build`.
- `defaultFolder` (`string | null`): The folder a new session opens in, `null` until known or when there is none.
- `defaultModelId` (`string | null`): The model, `null` until resolved.
- `defaultProviderKey` (`string | null`): The model's provider, `null` until resolved.
- `modelSource` (`NewSessionModelSource | null`): Where the model comes from, `null` until resolved.
- `newSessionKnobs` (`SessionKnobs`): The effort and options the space's preset sets.
- `projectRoot` (`string | null`): The project root of `defaultFolder`, `null` without a folder or a project.
- `setDefaultAgentId` (`(id: string | null) => void`): Picks the agent for this chat (`null`: back to the space's).
- `setDefaultFolder` (`(path: string | null) => void`): Sets the folder and remembers it (`null`: none, nothing remembered).
- `setDefaultModel` (`(pick: ModelPickRef, opts?: { persist?: boolean }) => void`): Picks the model and remembers it, unless `persist` is `false`.

Source: [ui/src/chat/composer/use-new-session-defaults.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-new-session-defaults.ts#L28)

### `OrderedBadge`

Interface.

What ordering needs of a badge: its id and its default slot.

```ts
interface OrderedBadge
```

**Properties**

- `id` (`string`): Stable id of the badge.
- `order?` (`number`): Default left-to-right slot, lower first. Default 100.

Source: [ui/src/chat/composer/badge-order.ts:12](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/badge-order.ts#L12)

### `PickerGroup`

Interface.

One section of the model picker list.

```ts
interface PickerGroup<E extends ModelCatalogRow = ModelCatalogRow>
```

**Type parameters**

- `E` (`extends ModelCatalogRow`, default `ModelCatalogRow`)

**Properties**

- `detail?` (`string`): Shown after the label as typed (not uppercased): the typed id of the routes group.
- `key` (`string`): Provider key (`provider@account` for one of several accounts), `in-use` for the pinned chain, `typed` for a typed id's routes.
- `label` (`string`): Heading of the section.
- `providerKey` (`string | null`): Provider key for coloring; `null` for the in-use and typed groups.
- `rows` (`E[]`): The models listed in the section.
- `total` (`number`): Models of this provider in the catalog, before the lineup filter.

Source: [ui/src/chat/composer/model-catalog.ts:306](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/model-catalog.ts#L306)

### `PickerPillProps`

Interface.

Props for [`PickerPill`](https://zidane.si/docs/reference/ui-chat-composer.md#PickerPill): the attributes of a `button`, plus its content and `collapsible`.

```ts
interface PickerPillProps extends ButtonHTMLAttributes<HTMLButtonElement>
```

**Properties**

- `children` (`ReactNode`): The pill's content: an icon, a label (`min-w-0 truncate`: a squeezed pill truncates it), and a caret.
- `collapsible?` (`boolean`): Folds to its `zg-pill-icon` on a tight composer (styles/composer.css)
  instead of shrinking: mark the icon `zg-pill-icon` and the label and
  caret `zg-pill-label`.

Source: [ui/src/chat/composer/PickerPill.tsx:13](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PickerPill.tsx#L13)

### `ProjectMenuProps`

Interface.

Props for [`ProjectMenu`](https://zidane.si/docs/reference/ui-chat-composer.md#ProjectMenu).

```ts
interface ProjectMenuProps
```

**Properties**

- `active` (`boolean`): The pill shows as the picked side of the toggle.
- `align?` (`Align`): How the menu lines up with its trigger. Default: its end.
- `ariaLabel` (`string`): The menu's accessible name.
- `browse?` (`(close: () => void) => ReactNode`): "Select directory…" shows this in the menu instead; `close` closes the menu.
- `className?` (`string`): Extra classes on the pill.
- `current` (`string | null`): The picked folder, checked in the list.
- `disabled?` (`boolean`): The pill can't be opened (a send is using the pick).
- `hostId?` (`string`): The host the projects are on (`HostView.id`), for showing their paths. Absent: this computer.
- `icon?` (`string`): The pill's icon class. Default: a folder.
- `label` (`string`): What the pill says.
- `leading?` (`(close: () => void) => ReactNode`): Rows above the projects; `close` closes the menu.
- `onImportRepo?` (`() => void | Promise<void>`): Imports a repository. Absent: not offered.
- `onPick` (`(folder: string) => void`): Picks a project.
- `onSelectDirectory?` (`() => void | Promise<void>`): "Select directory…" calls this (a native dialog). Ignored with `browse`.
- `projects` (`readonly string[]`): The projects to pick from, most recent first.
- `style?` (`CSSProperties`): Inline styles on the pill.
- `title` (`string`): The pill's tooltip.
- `trigger?` (`(props: PopoverTriggerProps, open: boolean) => ReactNode`): Draws the element that opens the menu instead of the pill (`label`, `title`, `icon`, `active` then unused).

Source: [ui/src/chat/composer/ProjectMenu.tsx:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ProjectMenu.tsx#L25)

### `PromptHistoryProviderProps`

Interface.

Props for [`PromptHistoryProvider`](https://zidane.si/docs/reference/ui-chat-composer.md#PromptHistoryProvider).

```ts
interface PromptHistoryProviderProps
```

**Properties**

- `children` (`ReactNode`): The app's components.

Source: [ui/src/chat/composer/PromptHistoryProvider.tsx:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PromptHistoryProvider.tsx#L68)

### `PromptHistoryValue`

Interface.

The per-session prompt ring [`usePromptHistory`](https://zidane.si/docs/reference/ui-chat-composer.md#usePromptHistory) returns.

```ts
interface PromptHistoryValue
```

**Properties**

- `cycle` (`(sessionId: string, direction: 'down' | 'up', currentBufferText: string) => string | null`): Move through the history. Returns the text the prompt should
  display, or `null` when the cycle is a no-op (e.g. ↓ while already
  on the live draft).
- `push` (`(sessionId: string, text: string) => void`): Records a sent prompt as the session's newest entry and leaves navigation.
- `reset` (`(sessionId: string) => void`): Reset the navigation cursor for a session (e.g. after submit).
- `status` (`(sessionId: string) => { position: number; total: number } | null`): Navigation position while cycling: `position` counts back from the
  newest entry (1 = most recent). `null` when the live draft is
  showing.

Source: [ui/src/chat/composer/PromptHistoryProvider.tsx:41](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/PromptHistoryProvider.tsx#L41)

### `RetryPillProps`

Interface.

Props for [`RetryPill`](https://zidane.si/docs/reference/ui-chat-composer.md#RetryPill).

```ts
interface RetryPillProps
```

**Properties**

- `className?` (`string`): Extra classes on the pill.
- `retry` (`{ attempt: number; max: number; source: string } | null`): The retry in progress, `null` for none (the pill hides).
- `style?` (`CSSProperties`): Inline styles, merged after its own.

Source: [ui/src/chat/composer/RetryPill.tsx:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/RetryPill.tsx#L17)

### `RunStatusChipProps`

Interface.

Props for [`RunStatusChip`](https://zidane.si/docs/reference/ui-chat-composer.md#RunStatusChip).

```ts
interface RunStatusChipProps
```

**Properties**

- `className?` (`string`): Extra classes on the chip's wrapper.
- `cost` (`LiveCostStatus | null`): The live session cost.
- `progress` (`LiveStreamProgress | null`): The streaming turn's live counters, `null` between turns.
- `running` (`boolean`): Whether it runs now: the chip shows from start to end.
- `sessionId` (`string`): The session that runs.
- `settledOutputTokens` (`number`): Output tokens of the run's settled parent turns.
- `style?` (`CSSProperties`): Inline styles on the chip.

Source: [ui/src/chat/composer/RunStatusChip.tsx:49](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/RunStatusChip.tsx#L49)

### `ScopeToggleProps`

Interface.

Props for [`ScopeToggle`](https://zidane.si/docs/reference/ui-chat-composer.md#ScopeToggle).

```ts
interface ScopeToggleProps
```

**Properties**

- `className?` (`string`): Extra classes on the group.
- `folderPath` (`string | null`): The draft's folder: `''` no folder (Chat), `null` undecided.
- `onImportRepo?` (`() => void | Promise<void>`): Imports a repository into the draft. Absent: the menu doesn't offer it.
- `onJustChat` (`() => void`): Makes the draft folderless.
- `onPickFolder` (`() => void | Promise<void>`): Opens the app's folder picker.
- `onPickRecent` (`(dir: string) => void`): Picks a recent folder.
- `recents` (`readonly string[]`): Recent folders, offered first.
- `style?` (`CSSProperties`): Inline styles on the group.

Source: [ui/src/chat/composer/ScopeToggle.tsx:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ScopeToggle.tsx#L25)

### `SelectTurnHintProps`

Interface.

Props for [`SelectTurnHint`](https://zidane.si/docs/reference/ui-chat-composer.md#SelectTurnHint).

```ts
interface SelectTurnHintProps
```

**Properties**

- `className?` (`string`): Extra classes on the card.
- `sessionId` (`string | null`): The composer's session: the row shows while select-turn mode is on in it.
- `style?` (`CSSProperties`): Inline styles on the card.

Source: [ui/src/chat/composer/SelectTurnHint.tsx:13](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/SelectTurnHint.tsx#L13)

### `SendButtonProps`

Interface.

Props for [`SendButton`](https://zidane.si/docs/reference/ui-chat-composer.md#SendButton).

```ts
interface SendButtonProps
```

**Properties**

- `canSend` (`boolean`): The draft can be sent now. When false the button is disabled unless it is Stop.
- `className?` (`string`): Extra classes on the root element.
- `route` (`SendRoute`): Where the draft goes. Sets the button's label.
- `stoppable` (`boolean`): A run is streaming and can be stopped: the button is Stop.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `onSend` (`() => void`): Called when the user sends the draft.
- `onStop` (`() => void`): Called when the user stops the run.

Source: [ui/src/chat/composer/SendButton.tsx:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/SendButton.tsx#L17)

### `SendPromptControls`

Interface.

The composer's send and stop.

```ts
interface SendPromptControls
```

**Properties**

- `needsProvider` (`boolean`): A send found no provider: the app asks to connect one, until one is ready.
- `send` (`(text: string, attachments: readonly SendAttachment[], activatedSkills?: readonly string[], options?: { delivery?: MessageDelivery; keepDraft?: boolean }) => Promise<void>`): Sends one prompt; rejects (the composer keeps the text) when it could not go.
- `stop` (`() => void`): Stops the conversation's run.

Source: [ui/src/chat/composer/use-send-prompt.ts:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-send-prompt.ts#L57)

### `SendPromptOptions`

Interface.

What [`useSendPrompt`](https://zidane.si/docs/reference/ui-chat-composer.md#useSendPrompt) sends from and through.

```ts
interface SendPromptOptions
```

**Properties**

- `draft` (`DraftTarget`): The draft's target (`useDraftTarget`).
- `hostId` (`string | null`): The server the composer talks to (`null`: this computer).
- `providerReady?` (`Writable<boolean | null>`): Whether a provider is ready on this computer (`null`: not known), which a send checks and updates. Absent: never checked.
- `running` (`boolean`): A run is in flight: a prompt is queued.
- `session` (`{ id: string } | null`): The conversation, `null` for the new-chat draft.
- `createSession` (`(request: NewSessionRequest) => Promise<{ id: string; provisioning?: boolean }>`): Creates the draft's session. Rejects with why it can't (shown on the draft).
- `newSessionDefaults` (`() => Omit<NewSessionDefaults, 'untitled'>`): What a new session starts with, read as it is created.
- `onSessionCreated?` (`() => void`): The draft's session exists: the picks that were for that chat only can reset.
- `reveal?` (`() => void`): Brings what was just sent into view (on the next frame).
- `side?` (`(sessionId: string | null, question: string) => string | null`): Hands `/side [question]` over; returns why it can't, `null` once handed over. Absent: `/side` is a prompt.

Source: [ui/src/chat/composer/use-send-prompt.ts:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-send-prompt.ts#L33)

### `ServerScopeToggleProps`

Interface.

Props for [`ServerScopeToggle`](https://zidane.si/docs/reference/ui-chat-composer.md#ServerScopeToggle).

```ts
interface ServerScopeToggleProps
```

**Properties**

- `className?` (`string`): Extra classes on the group.
- `clone?` (`DraftRemoteClone | null`): What a send clones there while no folder is picked.
- `cloning?` (`boolean`): The send is cloning `ServerScopeToggleProps.clone`.
- `folder` (`string | null`): The folder picked there, `null` for none (the clone, else the first root).
- `hostId` (`string`): The saved server.
- `hostName` (`string`): Its name, as the pill and the menu say it.
- `onChange` (`(folder: string | null) => void`): Picks a folder there (`null`: none).
- `onImportRepo?` (`() => void | Promise<void>`): Clones a repository on the server into the draft. Absent: not offered.
- `projects` (`readonly string[]`): The server's recent folders, most recent first.
- `root?` (`string | null`): The server's first workspace root, once known.
- `style?` (`CSSProperties`): Inline styles on the group.

Source: [ui/src/chat/composer/ServerScopeToggle.tsx:32](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ServerScopeToggle.tsx#L32)

### `SessionMeters`

Interface.

A conversation's meters.

```ts
interface SessionMeters
```

**Properties**

- `contextStatus` (`ComposerContextStatus | null`): Its context gauge, `null` while unknown.
- `fetchedCost` (`ComposerCostStatus | null`): The cost as last read; the pills add what the run settled and streams since (`ComposerHost.runs`).
- `modelId` (`string | null`): The session's model: its own pick, else the one its context status reports.

Source: [ui/src/chat/composer/use-session-meters.ts:24](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-session-meters.ts#L24)

### `SessionMetersTarget`

Interface.

What [`useSessionMeters`](https://zidane.si/docs/reference/ui-chat-composer.md#useSessionMeters) reads of a session.

```ts
interface SessionMetersTarget
```

**Properties**

- `id` (`string`): The session.
- `modelId?` (`string`): Its own model pick, if it has one.
- `providerKey?` (`string`): That model's provider.

Source: [ui/src/chat/composer/use-session-meters.ts:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-session-meters.ts#L14)

### `SuggestionPopupProps`

Interface.

Props for [`SuggestionPopup`](https://zidane.si/docs/reference/ui-chat-composer.md#SuggestionPopup).

```ts
interface SuggestionPopupProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element (the floating surface).
- `state` (`SuggestionState | null`): The open popup, or `null` to hide it.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/chat/composer/suggestions.tsx:56](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L56)

### `SuggestionSource`

Interface.

Feeds one completion trigger of the composer: the items for what the user typed, and how a picked item is written into the prompt.

```ts
interface SuggestionSource
```

**Properties**

- `items` (`(query: string) => readonly MentionItem[] | Promise<readonly MentionItem[]>`): Items for what follows the trigger, ranked. Called on every keystroke while the popup is open.
- `serialize?` (`(item: Pick<MentionItem, 'id' | 'label'>) => string`): The prompt text for a picked item. Default: `@label` for mentions, `/label` for commands.

Source: [ui/src/chat/composer/suggestions.tsx:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L28)

### `SuggestionState`

Interface.

The open popup, as the composer renders it.

```ts
interface SuggestionState
```

**Properties**

- `active` (`number`): Index in `items` of the row under the keyboard cursor.
- `anchor` (`{ x: number; y: number }`): Viewport position the popup attaches to, at the caret.
- `items` (`readonly MentionItem[]`): The items shown, ranked.
- `kind` (`SuggestionKind`): Which trigger opened the popup.
- `pick` (`(item: MentionItem) => void`): Inserts an item into the draft as a badge.

Source: [ui/src/chat/composer/suggestions.tsx:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L39)

## Types

### `AttachmentLabelFn`

Type.

The icon and name a file tile shows; `fallbackIcon` is the icon for a name with nothing to say.

```ts
type AttachmentLabelFn = (name: string, fallbackIcon?: string) => AttachmentLabelParts
```

Source: [ui/src/chat/composer/AttachmentTiles.tsx:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/AttachmentTiles.tsx#L17)

### `ComposerBadgeTone`

Type.

The tint of a badge's icon: the theme's quiet tones and its status colors.

```ts
type ComposerBadgeTone = 'muted' | 'subtle' | 'accent' | 'success' | 'warn' | 'danger'
```

Source: [ui/src/chat/composer/ComposerBadges.tsx:35](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ComposerBadges.tsx#L35)

### `ComposerResult`

Type.

`false` (or a rejection) keeps the draft: the composer puts it back.

```ts
type ComposerResult = void | boolean | Promise<void | boolean>
```

Source: [ui/src/chat/composer/Composer.tsx:73](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/Composer.tsx#L73)

### `ComposerRetry`

Type.

A stream being retried (the stream store's retry state).

```ts
type ComposerRetry = Parameters<typeof retryLabel>[0]
```

Source: [ui/src/chat/composer/RetryPill.tsx:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/RetryPill.tsx#L14)

### `EffortLevel`

Type.

One of the reasoning effort levels in [`EFFORT_LEVELS`](https://zidane.si/docs/reference/ui-chat-composer.md#EFFORT_LEVELS).

```ts
type EffortLevel = typeof EFFORT_LEVELS[number]
```

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L23)

### `ModelKind`

Type.

The kinds of model the popover lists: chat models or image models.

```ts
type ModelKind = 'chat' | 'image'
```

Source: [ui/src/chat/composer/ModelPicker.tsx:229](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelPicker.tsx#L229)

### `NewSessionModelSource`

Type.

Where the default model comes from.

```ts
type NewSessionModelSource = 'preset' | 'remembered' | 'builtin'
```

Source: [ui/src/chat/composer/use-new-session-defaults.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/use-new-session-defaults.ts#L25)

### `SendRoute`

Type.

Where Enter sends the draft: `send` as a new prompt, `steer` into the run in flight, or `queue` for after the run ends.

```ts
type SendRoute = 'send' | 'steer' | 'queue'
```

Source: [ui/src/chat/composer/SendButton.tsx:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/SendButton.tsx#L14)

### `SuggestionKind`

Type.

Which trigger a completion belongs to: `mention` (`@`) or `command` (`/`).

```ts
type SuggestionKind = 'mention' | 'command'
```

Source: [ui/src/chat/composer/suggestions.tsx:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/suggestions.tsx#L36)

### `ThinkingLevel`

Type.

`SendInput.thinking`'s levels, least to most: what a `ChatHost` takes.

```ts
type ThinkingLevel = NonNullable<SendInput['thinking']>
```

Source: [ui/src/chat/composer/ModelOptionsPicker.tsx:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/composer/ModelOptionsPicker.tsx#L26)

## Re-exports

These names are documented on the entry point that owns them.

- [zidane-ui/chat/headless](https://zidane.si/docs/reference/ui-chat-headless.md): [`ComposerAttachment`](https://zidane.si/docs/reference/ui-chat-headless.md#ComposerAttachment), [`ImageModelRow`](https://zidane.si/docs/reference/ui-chat-headless.md#ImageModelRow), [`ModelCatalogRow`](https://zidane.si/docs/reference/ui-chat-headless.md#ModelCatalogRow), [`ModelPickRef`](https://zidane.si/docs/reference/ui-chat-headless.md#ModelPickRef)
