# zidane-ui/chat/headless

> The React-free chat model, with the ChatHost interface, stores and the transcript pipeline.

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

Use this entry point to write a host, or to test transcript logic without React. It holds the `ChatHost` interface, the `writable` and `constant` stores, the session-list model and the transcript pipeline. The fixture host, `createFixtureHost`, is in [`zidane-ui/chat/testing`](https://zidane.si/docs/reference/ui-chat-testing.md). [What a host offers](https://zidane.si/docs/ui-kit.md#what-a-host-offers) lists each `ChatHost` member and the control it drives.

```ts
import { createFixtureHost } from 'zidane-ui/chat/testing'

const now = Date.now()
const host = createFixtureHost(
  { sessions: [{ id: 's1', title: 'First session', status: 'idle', createdAt: now, updatedAt: now }] },
  { reply: prompt => [{ kind: 'markdown', text: `You said: ${prompt}` }] },
)
const transcript = host.transcript('s1')
const stop = transcript.subscribe(() => console.log(transcript.get().events.length))
await host.send?.({ sessionId: 's1', prompt: 'hello' })
stop()
```

## Functions

### `activityLabel`

Function.

The row's words for an activity: the newest running tool, else the phase.

```ts
function activityLabel(
  activity: SessionActivity,
  labels?: Pick<SidebarLabels, 'activityCompacting' | 'activityRetrying' | 'activityWriting' | 'activityThinking'>,
): { text: string; title?: string }
```

**Parameters**

- `activity` (`SessionActivity`): What the run is doing.
- `labels?` (`Pick<SidebarLabels, 'activityCompacting' | 'activityRetrying' | 'activityWriting' | 'activityThinking'>`, default `DEFAULT_SIDEBAR_LABELS`): The phase words.

**Returns** `{ text: string; title?: string }`

Source: [ui/src/chat/headless/sidebar/activity.ts:46](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/activity.ts#L46)

### `authFailureDetails`

Function.

What the card's Copy details writes: the headline, the reason, and the
provider's own words when the reason rephrased them.

```ts
function authFailureDetails(headline: string, reason: string, raw?: string): string
```

**Parameters**

- `headline` (`string`): The card's headline.
- `reason` (`string`): The run's stop reason.
- `raw?` (`string`): The provider's own words (`RunErrorDetail.raw`).

**Returns** `string`

Source: [ui/src/chat/headless/transcript/auth-failure.ts:87](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L87)

### `availableProjectsOf`

Function.

Every project the sessions belong to, by folder name, sorted.

```ts
function availableProjectsOf(sessions: readonly SidebarListSession[]): string[]
```

**Parameters**

- `sessions` (`readonly SidebarListSession[]`): The listed sessions.

**Returns** `string[]`

Source: [ui/src/chat/headless/sidebar/directory.ts:989](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L989)

### `batchThinkingRuns`

Function.

Fold runs of ≥2 closed `thinking` rows into one `thinking-batch` row —
the exact interaction model of [`batchToolRuns`](https://zidane.si/docs/reference/ui-chat-headless.md#batchToolRuns): the group lands
in the FIRST thought's slot, interleaved tool rows keep their
positions after it, and the group id is keyed off the first thought so
it stays stable while the exchange grows.

Grouping rule (consecutive-only): thinking rows chain when separated
by nothing or only tool / tool-batch rows with the SAME owner
(`childId`); a markdown / user-prompt / separator / spawn row breaks
the chain. A live (still streaming) thinking row never joins — it
must stay expanded and in view; the chain it would have extended is
flushed before it.

Run AFTER `batchToolRuns` so tool batches are already folded and the
chain check sees `tool-batch` rows, not raw runs.

```ts
function batchThinkingRuns(rows: readonly Row[]): Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows after [`batchToolRuns`](https://zidane.si/docs/reference/ui-chat-headless.md#batchToolRuns), oldest first.

**Returns** `Row[]`

Source: [ui/src/chat/headless/transcript/batch.ts:411](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/batch.ts#L411)

### `batchToolRuns`

Function.

Group consecutive `tool` rows (≥2) into a single `tool-batch` row so
the renderer can paint one Claude-Code-style collapsible header
instead of a wall of individual tool entries between two assistant
messages. Single tool rows pass through untouched (per the user's
"don't edit single tool calls" requirement).

Constraints:

- Only batches tool rows sharing the same `childId` (incl. both
  `undefined`). Mixing subagent + main-stream tools would muddle
  the SubagentBlock cluster — those stay separate.
- Edit-style tools (`edit`, `multi_edit`, `write_file`) participate
  in batching like any other tool; the per-row diff stays available
  on expand.

With `groupToolCalls` on, parent-owned tool rows are first lifted
exchange-wide by `liftExchangeToolGroups`; the adjacency pass
below then only batches subagent-owned (`childId`) tool rows, so
subagent clusters keep their existing behavior.

```ts
function batchToolRuns(rows: readonly Row[], groupToolCalls?: boolean): Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows, oldest first.
- `groupToolCalls?` (`boolean`, default `false`): Lifts parent-owned tool calls into one group per exchange before batching adjacent runs. Defaults to `false`.

**Returns** `Row[]`

Source: [ui/src/chat/headless/transcript/batch.ts:309](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/batch.ts#L309)

### `beginChipWork`

Function.

Mark one lookup as started; call the returned function once when it ends (success or not).

```ts
function beginChipWork(): () => void
```

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

Source: [ui/src/chat/headless/chip-settle.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-settle.ts#L15)

### `buildHostSidebarRows`

Function.

The sidebar's rows over every host. Per host: This computer's section
first, then each saved server's, each host's sessions grouped per folder
under its header. Any other view lists every host in one list, a server's
folder headers naming the server, and a repository's sessions on every
machine under one header ([`repoGroups`](https://zidane.si/docs/reference/ui-chat-headless.md#repoGroups)). Sessions of a server no
longer saved are not listed.

```ts
function buildHostSidebarRows<S extends SidebarListSession>(
  sessions: S[],
  hosts: readonly HostView[],
  groupBy: 'none' | 'date' | 'project' | 'state' | 'host',
  sortBy: SidebarSortBy,
  options?: BuildSidebarRowsOptions,
): SidebarListRow<S>[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `sessions` (`S[]`): The sessions to list.
- `hosts` (`readonly HostView[]`): This machine and each saved server, in order.
- `groupBy` (`'none' | 'date' | 'project' | 'state' | 'host'`): The view.
- `sortBy` (`SidebarSortBy`): The order inside a group.
- `options?` (`BuildSidebarRowsOptions`, default `{}`): Collapsed groups, expanded "show more", pinned projects.

**Returns** `SidebarListRow<S>[]`

Source: [ui/src/chat/headless/sidebar/rows.ts:222](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L222)

### `buildQuerySidebarRows`

Function.

The sidebar's rows under a query grouping (a space's, an extension's, the agents'): favorites
first, then one group per value in the grouping's order, the items of each group leading it. A
session whose value is a list is in each of its groups. The sessions come sorted.

```ts
function buildQuerySidebarRows<S extends SidebarListSession>(
  sessions: readonly S[],
  groupBy: SessionGroupBy,
  options?: BuildQuerySidebarRowsOptions<S>,
): SidebarListRow<S>[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `sessions` (`readonly S[]`): The sessions to list, in order.
- `groupBy` (`SessionGroupBy`): The grouping.
- `options?` (`BuildQuerySidebarRowsOptions<S>`, default `{}`): Collapse, labels, favorites and items.

**Returns** `SidebarListRow<S>[]`

Source: [ui/src/chat/headless/sidebar/rows.ts:314](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L314)

### `buildSessionRows`

Function.

Builds the flat row list for a session list: favorites first, then groups with headers, collapse state, and "show more" caps for project groups. Pure: the same input gives the same rows.

```ts
function buildSessionRows<S extends ListableSession>(
  sessions: readonly S[],
  options?: SessionListOptions<S>,
): SessionListRow<S>[]
```

**Type parameters**

- `S` (`extends ListableSession`)

**Parameters**

- `sessions` (`readonly S[]`): The sessions to list.
- `options?` (`SessionListOptions<S>`, default `{}`): Grouping, sorting, collapse state, and labels.

**Returns** `SessionListRow<S>[]`

Source: [ui/src/chat/headless/session-list.ts:288](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L288)

### `buildSidebarRows`

Function.

The sidebar's rows over the kit's session-list model: favorites, git repositories and the project of each session.

```ts
function buildSidebarRows<S extends SidebarListSession>(
  sessions: S[],
  groupBy: SessionGroupBy,
  sortBy: SidebarSortBy,
  options?: BuildSidebarRowsOptions,
  project?: (session: S) => string,
): SidebarListRow<S>[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `sessions` (`S[]`): The sessions to list.
- `groupBy` (`SessionGroupBy`): The session-list grouping.
- `sortBy` (`SidebarSortBy`): The order inside a group.
- `options?` (`BuildSidebarRowsOptions`, default `{}`): Collapsed groups, expanded "show more", id prefix, pinned projects.
- `project?` (`(session: S) => string`, default `projectPathOf`): The project a session groups under (defaults to [`projectPathOf`](https://zidane.si/docs/reference/ui-chat-headless.md#projectPathOf)).

**Returns** `SidebarListRow<S>[]`

Source: [ui/src/chat/headless/sidebar/rows.ts:98](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L98)

### `caretEffectivelyAtStart`

Function.

Is the caret effectively at the buffer start for the mode-exit check?

The obvious answer (`selection.empty && from === atStart`) misses a
ProseMirror trap: Cmd/Ctrl+A creates an `AllSelection`, and deleting
it leaves that SAME AllSelection spanning the now-empty doc — `empty`
stays `false`, `from` stays `0` — until a click or a typed character
replaces it. Without the empty-doc escape hatch, Backspace after a
select-all-clear can never exit shell mode (Esc doesn't exit it
either), so the mode — and its ghost-autocomplete suppression — stick
for the rest of the draft.

A Backspace on an empty doc is a no-op edit whatever the selection
shape — exactly the TUI's "backspace at offset 0" exit trigger
(`handleShellExitKey`, src/tui/prompt/prompt-key-handlers.ts).

```ts
function caretEffectivelyAtStart(
  selection: { empty: boolean; from: number },
  atStartPos: number,
  docEmpty: boolean,
): boolean
```

**Parameters**

- `selection` (`{ empty: boolean; from: number }`): The editor's selection: where the caret is and whether it spans text.
- `atStartPos` (`number`): The document position of the start of the text.
- `docEmpty` (`boolean`): Whether the document holds no text.

**Returns** `boolean`

Source: [ui/src/chat/headless/composer-modes.ts:71](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer-modes.ts#L71)

### `chipForPath`

Function.

The chip of a path known to be a file or folder (a mention): never plain code.

```ts
function chipForPath(path: string): FileChip
```

**Parameters**

- `path` (`string`): The file's path, as written.

**Returns** `FileChip`

Source: [ui/src/chat/headless/file-chip.ts:178](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L178)

### `chipWorkBusy`

Function.

Whether any lookup is in flight.

```ts
function chipWorkBusy(): boolean
```

**Returns** `boolean`

Source: [ui/src/chat/headless/chip-settle.ts:27](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-settle.ts#L27)

### `claimChildSessions`

Function.

Each item with its child sessions (a session goes to the first item that claims it), and the
sessions no item claims.

```ts
function claimChildSessions<S extends SidebarListSession>(
  items: readonly ExtensionItem<'sidebar-row'>[],
  sessions: readonly S[],
  now?: number,
): { items: SidebarItemEntry<S>[]; rest: S[] }
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `items` (`readonly ExtensionItem<'sidebar-row'>[]`): The space's items.
- `sessions` (`readonly S[]`): The sessions the space lists.
- `now?` (`number`): Clock for relative times.

**Returns** `{ items: SidebarItemEntry<S>[]; rest: S[] }`

Source: [ui/src/chat/headless/sidebar/query.ts:560](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L560)

### `classifyInlineCode`

Function.

What inline code names, read from its text alone: a file or folder chip, or `null` for plain code.

```ts
function classifyInlineCode(raw: string): FileChip | null
```

**Parameters**

- `raw` (`string`): The inline code's text.

**Returns** `FileChip | null`

Source: [ui/src/chat/headless/file-chip.ts:101](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L101)

### `clearedViewFilters`

Function.

The patch that turns every filter of a view off ([`viewFiltersOn`](https://zidane.si/docs/reference/ui-chat-headless.md#viewFiltersOn)), keeping its grouping,
sort and the contributed grouping and sort picked.

```ts
function clearedViewFilters(view: SidebarView): Partial<SidebarView>
```

**Parameters**

- `view` (`SidebarView`): The space's view.

**Returns** `Partial<SidebarView>`

Source: [ui/src/chat/headless/sidebar/query.ts:602](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L602)

### `clusterByOwner`

Function.

Group contiguous rows with the same `childId` so the renderer can
wrap a subagent's output in a single bordered card — and nest the card
of a worker a worker started inside its spawner's (spawner from the
markers' `spawn.parentChildId`). A row's block chain is its worker's
ancestry; the open chain is reused as far as it matches, so a
grandchild's rows land inside the spawner's block that is still open,
and the spawner's later rows close the grandchild's block. A row of
another lane (main rows, an unrelated sibling) closes the chain: a later
grandchild row then reopens its spawner's block around itself.

```ts
function clusterByOwner(rows: readonly Row[]): Cluster[]
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows, oldest first.

**Returns** `Cluster[]`

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

### `collapseEvents`

Function.

Turns transcript events into rows: pairs tool calls with their results, merges streamed text, reconciles edits and spawns. Rows are cached per source event, so appending an event keeps every earlier row identical.

```ts
function collapseEvents(
  events: readonly ChatEvent[],
  showEditDiffs: boolean,
  isStreaming: boolean,
): Row[]
```

**Parameters**

- `events` (`readonly ChatEvent[]`): The transcript events, oldest first.
- `showEditDiffs` (`boolean`): Keeps the edit diff on edit tool rows. When false, the rows carry none.
- `isStreaming` (`boolean`): A run is in flight, so the last reply may still be streaming.

**Returns** `Row[]`

Source: [ui/src/chat/headless/transcript/collapse.ts:407](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/collapse.ts#L407)

### `commandName`

Function.

The command a chip names (`/fix conflicts` → `fix`).

```ts
function commandName(text: string): string
```

**Parameters**

- `text` (`string`): The chip's text.

**Returns** `string`

Source: [ui/src/chat/headless/chip-views.ts:188](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L188)

### `commandRef`

Function.

The command an invocation starts with: its `/name`, plus the leading
argument when that is one of the command's fixed values (`args`, which
may be several words): `/fix conflicts now` reads `/fix conflicts`. The
longest value wins, and it must end at a space or the end of the text.

```ts
function commandRef(text: string, args?: ReadonlySet<string>): PromptSegmentRef | null
```

**Parameters**

- `text` (`string`): The prompt.
- `args?` (`ReadonlySet<string>`, default `NO_ARGS`): The command's fixed arguments, so `/fix conflicts` is one span.

**Returns** `PromptSegmentRef | null`

Source: [ui/src/chat/headless/badge-refs.ts:47](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/badge-refs.ts#L47)

### `commandView`

Function.

A command chip's card: the description and the aliases.

```ts
function commandView(
  labels: ChipViewLabels,
  text: string,
  command: ChatCommandFacts | null,
): ExtensionReferenceView
```

**Parameters**

- `labels` (`ChipViewLabels`): The chat labels (the facts' names).
- `text` (`string`): The chip's text.
- `command` (`ChatCommandFacts | null`): The command it names (`null`: none).

**Returns** `ExtensionReferenceView`

Source: [ui/src/chat/headless/chip-views.ts:197](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L197)

### `commitModelPick`

Function.

Commits a picked chain, the ONE path every model picker takes: the
session's model (when there is one), then the app's default (the next
chat's model and `lastModelChain`) when this computer can run it. A draft
whose pick only a server can run still launches under it: held for this
window, not remembered. `remember: false` (a side chat's pick) only sets
the session's model.

```ts
function commitModelPick(
  host: { controls?: ComposerControls; models?: ComposerModels; prefs?: ComposerPrefs },
  target: { hostId: string | null | undefined; sessionId: string | null },
  chain: readonly ModelPickRef[],
  setDefaultModel: SetDefaultModel,
  options?: { remember?: boolean },
): Promise<void>
```

**Parameters**

- `host` (`{ controls?: ComposerControls; models?: ComposerModels; prefs?: ComposerPrefs }`): The host's `controls`, `models` and `prefs`.
- `target` (`{ hostId: string | null | undefined; sessionId: string | null }`): The session (`null`: a draft) and the host it runs on.
- `chain` (`readonly ModelPickRef[]`): The picked chain, primary first.
- `setDefaultModel` (`SetDefaultModel`): Sets the app's default model.
- `options?` (`{ remember?: boolean }`, default `{}`): `remember: false` to leave the default alone.

**Returns** `Promise<void>`

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

### `commitView`

Function.

A sha chip's card: the short sha, the subject as its title, the author, the change size and the age.

```ts
function commitView(
  labels: ChipViewLabels,
  sha: string,
  info: ChatCommit | null | undefined,
  href: string | undefined,
  now?: number,
): ExtensionReferenceView
```

**Parameters**

- `labels` (`ChipViewLabels`): The chat labels (the facts' names).
- `sha` (`string`): The sha as the chip shows it.
- `info` (`ChatCommit | null | undefined`): The commit, once read (`null`: unknown).
- `href` (`string | undefined`): The commit's page.
- `now?` (`number`): The time ages are measured from.

**Returns** `ExtensionReferenceView`

Source: [ui/src/chat/headless/chip-views.ts:50](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L50)

### `compareSessions`

Function.

The order a sort puts two sessions in (negative: `a` first), as [`buildSessionRows`](https://zidane.si/docs/reference/ui-chat-headless.md#buildSessionRows) sorts them.

```ts
function compareSessions(
  a: ListableSession,
  b: ListableSession,
  sort: SessionSortBy,
): number
```

**Parameters**

- `a` (`ListableSession`): One session.
- `b` (`ListableSession`): The other.
- `sort` (`SessionSortBy`): The sort.

**Returns** `number`

Source: [ui/src/chat/headless/session-list.ts:249](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L249)

### `composeLiveCost`

Function.

The cost pill's figure while a run is in flight (see the header).

```ts
function composeLiveCost(
  fetched: ComposerCostStatus | null,
  accrued: number,
  progress: LiveStreamProgress | null,
): LiveCostStatus | null
```

**Parameters**

- `fetched` (`ComposerCostStatus | null`): The cost as last read.
- `accrued` (`number`): Settled turn costs since that read.
- `progress` (`LiveStreamProgress | null`): The streaming turn's counters.

**Returns** `LiveCostStatus | null`

Source: [ui/src/chat/headless/composer/live-cost.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/live-cost.ts#L51)

### `composeSubmitText`

Function.

Final submit text for the active mode, or `null` when the submit is
a no-op. Shell re-attaches the consumed bang (TUI `submit` in
src/tui/prompt/use-composer-actions.ts);
a blank shell command never submits, even with attachments staged.
Search mode never submits — Enter navigates matches instead.

```ts
function composeSubmitText(mode: ComposerMode, text: string): string | null
```

**Parameters**

- `mode` (`ComposerMode`): The composer's mode.
- `text` (`string`): The composer's text.

**Returns** `string | null`

Source: [ui/src/chat/headless/composer-modes.ts:119](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer-modes.ts#L119)

### `computeSelectStops`

Function.

Works out the stops of select-turn mode from the painted rows. Result-only turns join the turn that made the call, and work-only turns join the next answer in the same exchange.

```ts
function computeSelectStops(
  rows: readonly Row[],
  ownership: ReadonlyMap<string, string>,
  isHidden?: (row: Row) => boolean,
): SelectStops
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows as painted, oldest first.
- `ownership` (`ReadonlyMap<string, string>`): Maps a result-only turn id to the turn that owns it.
- `isHidden?` (`(row: Row) => boolean`): Tells whether a row is hidden, so the cursor skips it. Defaults to showing every row.

**Returns** `SelectStops`

Source: [ui/src/chat/headless/transcript/select-stops.ts:74](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/select-stops.ts#L74)

### `constant`

Function.

A store that never changes.

```ts
function constant<T>(value: T): Readable<T>
```

**Type parameters**

- `T`

**Parameters**

- `value` (`T`): The value the store always returns.

**Returns** `Readable<T>`

Source: [ui/src/chat/headless/store.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/store.ts#L51)

### `conversationBadges`

Function.

The badges to show, in their default order (the kit's
`orderComposerBadges` applies the user's).

```ts
function conversationBadges(
  input: ConversationBadgeInput,
  labels: { agentDialogDescription: string; agentDialogTitle: string; agentSwitching: string; archivedNotice: string; badgeFromPrevious: (title: string) => string; badgePlan: string; badgePlanTitle: (title: string) => string; badgeQuestions: (n: number) => string; badgeQuestionsTitle: (n: number) => string; badgeQueued: string; badgeQueuedTitle: (n: number) => string; badgeReminders: (when: string) => string; badgeRemindersTitle: (n: number, when: string) => string; badgeRunning: string; badgeRunningTitle: (names: readonly string[], more: number, total: number) => string; badgeTodos: string; badgeTodosCurrent: (content: string, progress: string) => string; badgeTodosProgress: (done: number, total: number) => string; badgeTodosStopped: (progress: string) => string; badgeWaiting: string; badgeWaitingTitle: string; breakdownError: (message: string) => string; effortDialogDescription: (title: string) => string; effortDialogFeatures: string; effortDialogReasoning: string; effortDialogTitle: string; modelDialogDescription: (title: string) => string; modelDialogTitle: string; modelOptionsTitle: string; modelPickDefault: string; modelSwitch: string; retryStallHint: (attempt: number, max: number) => string; runChipEstimatedHint: string; runChipHint: string; runChipRate: string; scopeBackToProjects: string; scopeChat: string; scopeChatHint: string; scopeChooseFolder: string; scopeCloneOffHint: (host: string) => string; scopeCloneOffTag: string; scopeCloneTag: string; scopeCloneThere: (path: string, host: string) => string; scopeCloneThereTag: string; scopeCloneWill: (name: string) => string; scopeCloneWillHint: (url: string, parent: string, host: string) => string; scopeCloning: (name: string) => string; scopeFolderHint: (folder: string) => string; scopeGroup: string; scopeImportRepo: string; scopeSelect: string; scopeSelectDirectory: string; scopeSelectHint: string; scopeServerChoose: (host: string) => string; scopeServerDefault: string; scopeServerDefaultHint: (host: string) => string; scopeServerFolderHint: (folder: string, host: string) => string; scopeServerGroup: (host: string) => string; sendCloneCancelled: string; sendCloneFailed: (url: string, message: string) => string; sendCreateFailed: (message: string) => string; sendUntitled: string; unarchive: string },
): ConversationBadge[]
```

**Parameters**

- `input` (`ConversationBadgeInput`): The conversation's state.
- `labels` (`{ agentDialogDescription: string; agentDialogTitle: string; agentSwitching: string; archivedNotice: string; badgeFromPrevious: (title: string) => string; badgePlan: string; badgePlanTitle: (title: string) => string; badgeQuestions: (n: number) => string; badgeQuestionsTitle: (n: number) => string; badgeQueued: string; badgeQueuedTitle: (n: number) => string; badgeReminders: (when: string) => string; badgeRemindersTitle: (n: number, when: string) => string; badgeRunning: string; badgeRunningTitle: (names: readonly string[], more: number, total: number) => string; badgeTodos: string; badgeTodosCurrent: (content: string, progress: string) => string; badgeTodosProgress: (done: number, total: number) => string; badgeTodosStopped: (progress: string) => string; badgeWaiting: string; badgeWaitingTitle: string; breakdownError: (message: string) => string; effortDialogDescription: (title: string) => string; effortDialogFeatures: string; effortDialogReasoning: string; effortDialogTitle: string; modelDialogDescription: (title: string) => string; modelDialogTitle: string; modelOptionsTitle: string; modelPickDefault: string; modelSwitch: string; retryStallHint: (attempt: number, max: number) => string; runChipEstimatedHint: string; runChipHint: string; runChipRate: string; scopeBackToProjects: string; scopeChat: string; scopeChatHint: string; scopeChooseFolder: string; scopeCloneOffHint: (host: string) => string; scopeCloneOffTag: string; scopeCloneTag: string; scopeCloneThere: (path: string, host: string) => string; scopeCloneThereTag: string; scopeCloneWill: (name: string) => string; scopeCloneWillHint: (url: string, parent: string, host: string) => string; scopeCloning: (name: string) => string; scopeFolderHint: (folder: string) => string; scopeGroup: string; scopeImportRepo: string; scopeSelect: string; scopeSelectDirectory: string; scopeSelectHint: string; scopeServerChoose: (host: string) => string; scopeServerDefault: string; scopeServerDefaultHint: (host: string) => string; scopeServerFolderHint: (folder: string, host: string) => string; scopeServerGroup: (host: string) => string; sendCloneCancelled: string; sendCloneFailed: (url: string, message: string) => string; sendCreateFailed: (message: string) => string; sendUntitled: string; unarchive: string }`): The words.

**Returns** `ConversationBadge[]`

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

### `createAuthFixes`

Function.

Creates an empty [`AuthFixes`](https://zidane.si/docs/reference/ui-chat-headless.md#AuthFixes).

```ts
function createAuthFixes(): AuthFixes
```

**Returns** `AuthFixes`

Source: [ui/src/chat/headless/transcript/auth-failure.ts:100](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L100)

### `createChatBlockRuns`

Function.

A [`ChatBlockRuns`](https://zidane.si/docs/reference/ui-chat-headless.md#ChatBlockRuns) over `transport`: each session's runs read on first ask, again on each change.

```ts
function createChatBlockRuns(transport: ChatBlockRunTransport): ChatBlockRuns
```

**Parameters**

- `transport` (`ChatBlockRunTransport`): The adapter's calls and change signal.

**Returns** `ChatBlockRuns`

Source: [ui/src/chat/headless/block-runs.ts:77](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/block-runs.ts#L77)

### `createCompactionProgress`

Function.

The compaction store over `subscribe`, the app's feed of every session's
stream signals (an Electron bus, a server connection's `ipc.signal`).

```ts
function createCompactionProgress(
  options: { now?: () => number; subscribe: (listener: (signal: { kind: string }) => void) => () => void },
): CompactionProgressStore
```

**Parameters**

- `options` (`{ now?: () => number; subscribe: (listener: (signal: { kind: string }) => void) => () => void }`): The signal feed, and the clock (default `Date.now`).

**Returns** `CompactionProgressStore`

Source: [ui/src/chat/headless/sidebar/compaction.ts:64](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/compaction.ts#L64)

### `createComposerLists`

Function.

The lists over a host's completions. `onCommands`: the command list changed (a typed `/name` may become, or
stop being, a badge).

```ts
function createComposerLists(
  completions: ComposerCompletions | undefined,
  onCommands: () => void,
): ComposerLists
```

**Parameters**

- `completions` (`ComposerCompletions | undefined`): The host's catalogs (absent: every list stays empty).
- `onCommands` (`() => void`): Called when the command list changes.

**Returns** `ComposerLists`

Source: [ui/src/chat/headless/composer/composer-sources.ts:112](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/composer-sources.ts#L112)

### `createDecorator`

Function.

The decorator for a set of decorations: each session's merged decoration, or `null` when none
matches. The first matching decoration gives the icon, tone, subtitle and component; every one
adds its chips. Templates render with `renderTemplate`.

The output is cached per session object: the same row object gets the same decoration object
back, so a row whose session didn't change keeps its memo. A row patched with new facets is a
new object and is decorated again. Relative times in `where` are read when a row is first
decorated: a new decorator (new decorations) reads them again.

```ts
function createDecorator<S extends SidebarListSession>(
  decorations: readonly ExtensionItem<'sidebar-decoration'>[],
  now?: number,
): (row: S) => SidebarRowDecoration | null
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `decorations` (`readonly ExtensionItem<'sidebar-decoration'>[]`): Every decoration item, in the host's order.
- `now?` (`number`): Clock for relative times in `where`.

**Returns** `(row: S) => SidebarRowDecoration | null`

Source: [ui/src/chat/headless/sidebar/query.ts:466](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L466)

### `createDraftScopeStore`

Function.

Creates the draft's scope store.

```ts
function createDraftScopeStore(options: DraftScopeStoreOptions): DraftScopeStore
```

**Parameters**

- `options` (`DraftScopeStoreOptions`): How roots resolve and what a replaced id releases.

**Returns** `DraftScopeStore`

Source: [ui/src/chat/headless/draft-scope.ts:74](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L74)

### `createModelKnobs`

Function.

Creates the remembered knobs over a host's prefs.

```ts
function createModelKnobs(prefs: ComposerPrefs | undefined): ModelKnobsStore
```

**Parameters**

- `prefs` (`ComposerPrefs | undefined`): Where picks are remembered. Absent: they last for the page's life.

**Returns** `ModelKnobsStore`

Source: [ui/src/chat/headless/composer/model-knobs.ts:73](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-knobs.ts#L73)

### `createModelNames`

Function.

Creates the names over a catalog and, optionally, the sign-in report's providers.
Both are read for the store's life once a reader subscribes.

```ts
function createModelNames(
  catalog: Readable<ResourceSnapshot<readonly Pick<ModelCatalogRow, 'providerKey' | 'modelId' | 'providerLabel' | 'modelName'>[]>>,
  providers?: Readable<ResourceSnapshot<readonly ModelNamesProvider[]>>,
): ModelNamesStore
```

**Parameters**

- `catalog` (`Readable<ResourceSnapshot<readonly Pick<ModelCatalogRow, 'providerKey' | 'modelId' | 'providerLabel' | 'modelName'>[]>>`): The model catalog.
- `providers?` (`Readable<ResourceSnapshot<readonly ModelNamesProvider[]>>`): The providers, signed in or not (labels for those with no model listed).

**Returns** `ModelNamesStore`

Source: [ui/src/chat/headless/composer/model-names.ts:72](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-names.ts#L72)

### `createModelPickerPrefs`

Function.

Creates the preferences over a Storage, read on first use.

```ts
function createModelPickerPrefs(
  storage?: ModelPickerPrefsStorage,
): ModelPickerPrefsStore
```

**Parameters**

- `storage?` (`ModelPickerPrefsStorage`): Where they are stored. Absent: `localStorage` when there is one, else memory only.

**Returns** `ModelPickerPrefsStore`

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

### `createNotificationStore`

Function.

An empty notification store.

```ts
function createNotificationStore(): SessionNotificationStore
```

**Returns** `SessionNotificationStore`

Source: [ui/src/chat/headless/sidebar/notifications.ts:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/notifications.ts#L23)

### `createPathResolver`

Function.

Creates the chip answers over a host's paths.

```ts
function createPathResolver(
  paths: ChatPaths,
  options?: PathResolverOptions,
): PathResolver
```

**Parameters**

- `paths` (`ChatPaths`): The host's `paths` member.
- `options?` (`PathResolverOptions`, default `{}`): The chip-work counter.

**Returns** `PathResolver`

Source: [ui/src/chat/headless/path-resolver.ts:57](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/path-resolver.ts#L57)

### `createReferenceStore`

Function.

Creates the reference cache over a host's references.

```ts
function createReferenceStore(
  references: ChatReferences,
  options?: ReferenceStoreOptions,
): ReferenceStore
```

**Parameters**

- `references` (`ChatReferences`): The host's `references` member.
- `options?` (`ReferenceStoreOptions`, default `{}`): Persistence and the chip-work counter.

**Returns** `ReferenceStore`

Source: [ui/src/chat/headless/reference-store.ts:100](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/reference-store.ts#L100)

### `createRunEstimates`

Function.

The store over `subscribe`, the app's feed of every session's stream
signals (an Electron bus, a server connection's `ipc.signal`).

```ts
function createRunEstimates(
  options: { subscribe: (listener: (signal: { kind: string }) => void) => () => void },
): RunEstimatesStore
```

**Parameters**

- `options` (`{ subscribe: (listener: (signal: { kind: string }) => void) => () => void }`): The signal feed.

**Returns** `RunEstimatesStore`

Source: [ui/src/chat/headless/sidebar/estimates.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/estimates.ts#L66)

### `createRunMeter`

Function.

Creates an empty [`RunMeter`](https://zidane.si/docs/reference/ui-chat-headless.md#RunMeter).

```ts
function createRunMeter(now?: () => number): RunMeter
```

**Parameters**

- `now?` (`() => number`): The clock (epoch ms), for runs whose start the host does not stamp.

**Returns** `RunMeter`

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

### `createSessionActivity`

Function.

The activity store over `subscribe`, the app's feed of every session's
stream signals (an Electron bus, a server connection's `ipc.signal`).

```ts
function createSessionActivity(
  options: { subscribe: (listener: (signal: { kind: string }) => void) => () => void },
): SessionActivityStore
```

**Parameters**

- `options` (`{ subscribe: (listener: (signal: { kind: string }) => void) => () => void }`): The signal feed.

**Returns** `SessionActivityStore`

Source: [ui/src/chat/headless/sidebar/activity.ts:143](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/activity.ts#L143)

### `createSessionBadges`

Function.

The badges store over `source`.

```ts
function createSessionBadges(source: SessionBadgesSource): SessionBadgesStore
```

**Parameters**

- `source` (`SessionBadgesSource`): Where the badges come from and when they change.

**Returns** `SessionBadgesStore`

Source: [ui/src/chat/headless/sidebar/badges.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/badges.ts#L66)

### `createSessionDirectory`

Function.

The directory over the app's ports; nothing runs until `start()`.

```ts
function createSessionDirectory<S extends SidebarListSession, P, C = unknown>(
  options: SessionDirectoryOptions<S, P, C>,
): SessionDirectory<S, C>
```

**Type parameters**

- `S` (`extends SidebarListSession`)
- `P`
- `C` (default `unknown`)

**Parameters**

- `options` (`SessionDirectoryOptions<S, P, C>`): The transport, stream store, settings, views and signals.

**Returns** `SessionDirectory<S, C>`

Source: [ui/src/chat/headless/sidebar/directory.ts:307](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L307)

### `createSessionHistory`

Function.

The history store: in memory, persisted through `store` once `SessionHistory.load` has read it.

```ts
function createSessionHistory<K extends string = string>(
  options?: SessionHistoryOptions,
): SessionHistory<K>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Parameters**

- `options?` (`SessionHistoryOptions`, default `{}`): The store, the cap and the error report.

**Returns** `SessionHistory<K>`

Source: [ui/src/chat/headless/sidebar/history.ts:142](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L142)

### `createSessionStreamActions`

Function.

Binds the writes of `streams` (and its store) into one stable object.

```ts
function createSessionStreamActions<K extends string>(
  streams: SessionStreams<K>,
): SessionStreamActions<K>
```

**Type parameters**

- `K` (`extends string`)

**Parameters**

- `streams` (`SessionStreams<K>`): The session streams to write to.

**Returns** `SessionStreamActions<K>`

Source: [ui/src/chat/headless/streams/actions.ts:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/actions.ts#L62)

### `createSessionStreams`

Function.

The session stream store: every session's live transcript and run state,
reduced from zidane's host signals, with per-session subscriptions,
smooth-stream pacing, lazy scrollback and run-end compaction. React-free.

```ts
function createSessionStreams<K extends string = string>(
  options?: SessionStreamsOptions<K>,
): SessionStreams<K>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Parameters**

- `options?` (`SessionStreamsOptions<K>`, default `{}`): Smoothing, the scheduler, the markdown rule and the page loaders.

**Returns** `SessionStreams<K>`

Source: [ui/src/chat/headless/streams/session-streams.ts:100](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/session-streams.ts#L100)

### `createSidebarViews`

Function.

The views store: Storage first, the host's copy merged in once (`SidebarViews.sync`).

```ts
function createSidebarViews(options?: SidebarViewsOptions): SidebarViews
```

**Parameters**

- `options?` (`SidebarViewsOptions`, default `{}`): Storage, host and fallback space.

**Returns** `SidebarViews`

Source: [ui/src/chat/headless/sidebar/view.ts:250](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L250)

### `createSiteIcons`

Function.

Creates the site icon cache over a fetcher.

```ts
function createSiteIcons(
  fetch: (origin: string) => Promise<string | null>,
): ChatSiteIcons
```

**Parameters**

- `fetch` (`(origin: string) => Promise<string | null>`): Loads an origin's icon as a data URL; `null` when it has none.

**Returns** `ChatSiteIcons`

Source: [ui/src/chat/headless/site-icons.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/site-icons.ts#L28)

### `dateBucket`

Function.

Today, Yesterday, a weekday within the week, `Mon D` this year, `Mon YYYY` before.

```ts
function dateBucket(
  at: number,
  now: number,
  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 },
  calendar?: CalendarOptions,
): string
```

**Parameters**

- `at` (`number`): Epoch milliseconds of the session's activity.
- `now` (`number`): Epoch milliseconds of the current time.
- `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 }`, default `DEFAULT_CHAT_LABELS`): Strings for `today`, `yesterday`, and the month names. Defaults to the default chat labels.
- `calendar?` (`CalendarOptions`): Pins the zone and locale the days are read in.

**Returns** `string`

Source: [ui/src/chat/headless/session-list.ts:193](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L193)

### `decodeHistoryEntry`

Function.

Decode a recalled history entry: `!`-prefixed entries recall INTO
shell mode with the bang stripped (`applyRecalledPrompt`,
src/tui/prompt/use-prompt-history.ts); everything else recalls as a normal prompt.

```ts
function decodeHistoryEntry(entry: string): { mode: 'shell' | 'normal'; text: string }
```

**Parameters**

- `entry` (`string`): A prompt history entry.

**Returns** `{ mode: 'shell' | 'normal'; text: string }`

Source: [ui/src/chat/headless/composer-modes.ts:164](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer-modes.ts#L164)

### `defaultModelPatch`

Function.

The prefs patch that remembers `pick` as the next new chat's model.

```ts
function defaultModelPatch(
  current: ComposerPrefsState | null | undefined,
  pick: ModelPickRef,
): ComposerPrefsState
```

**Parameters**

- `current` (`ComposerPrefsState | null | undefined`): The remembered picks now.
- `pick` (`ModelPickRef`): The new default.

**Returns** `ComposerPrefsState`

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

### `deleteSessionPrompt`

Function.

The delete confirmation: the question, and a warning when the session's sandbox goes with it.

```ts
function deleteSessionPrompt(
  title: string,
  environment: SessionEnvironmentSummary | undefined,
  labels: { activityCompacting: string; activityRetrying: string; activityThinking: string; activityWriting: string; addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addSpace: string; addToChat: string; agent: string; agentDraftNote: string; agentGroupDefault: string; agentProfiles: string; archive: string; archiveConfirmLabel: string; archived: string; archiveProjectMessage: (count: number) => 'It stays under Archived, where you can restore it.' | 'They stay under Archived, where you can restore them.'; archiveProjectTitle: (count: number, project: string) => 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; changeIconFor: (project: string) => string; changeMainIcon: string; changeProjectIcon: string; changeSpaceIcon: 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; chooseImage: string; chooseModel: string; chooseProjectIcon: string; chooseSpaceIcon: string; clearSearch: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; collapseItem: (title: string) => string; collapseSidebar: string; commandDetail: string; commandSuggestions: string; compactingTitle: 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; customEmoji: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; defaultSpaceName: string; delete: string; deleteConfirmLabel: string; deleteProjectArchived: (archived: number) => string; deleteProjectCannotUndo: string; deleteProjectSandboxes: (sandboxed: number) => string; deleteProjectTitle: (count: number, project: string) => string; deleteSessionQuestion: (title: string) => string; deleteSessionSandbox: (kind: string) => string; deleteSpace: string; deleteSpaceMessage: (fallback: string) => string; deleteSpaceNamed: (name: string) => string; deleteSpaceQuestion: (name: string) => 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; emojiPlaceholder: string; environmentActionFailed: (action: string, message: string) => string; environmentKept: (reason?: string) => string; environmentKinds: Readonly<Record<string, string>>; environmentOnBranch: (kind: string, branch: string) => string; environmentOnMachine: (kind: string, machine: string) => string; environmentPaused: (where: string) => string; environmentSettingUp: (where: string) => string; environmentSetupFailed: (where: string, error?: string) => string; environmentsKept: (count: number) => 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; expandItem: (title: string) => string; expandSidebar: 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; footerSettings: string; footerSettingsWithNote: (note: string) => string; footerSignIn: string; footerSignInTitle: string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hiddenSpaces: string; hideSpace: 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; itemActions: (title: string) => string; itemOpenFailed: (message: string) => string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mainSession: string; mentionSuggestions: string; menuAddFavorite: string; menuArchive: string; menuArchiveProject: string; menuCopyPath: string; menuDelete: string; menuDeleteProject: string; menuMoveProjectToSpace: string; menuMoveTo: string; menuMoveToSpace: string; menuOpenChatWindow: string; menuOpenPanelsWindow: string; menuOpenWindow: string; menuRemoveFavorite: string; menuRename: string; menuRetryEnvironment: string; menuReveal: string; menuUnarchive: 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; moveProjectFailed: (message: string) => string; moveSessionFailed: (message: string) => string; moveSpaceDown: (name: string) => string; moveSpaceLeft: string; moveSpaceRight: string; moveSpaceUp: (name: string) => string; newSession: string; newSessionIn: (project: string) => string; newSessionTitle: string; newSpaceName: (n: number) => string; next: string; noAnswer: string; noChatsMatchFilters: string; noChatsYet: 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; pinNamed: (project: string) => string; pinProject: 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; queryGroupOther: 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; resetFilters: string; resetsAt: (time: string) => string; resetToFolder: string; resetToInitial: string; retry: string; retryEnvironmentFailed: (message: string) => string; retryHint: string; rowNeedsYou: string; rowRunning: string; rowScheduled: string; rowWorking: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; savedViewName: (n: number) => string; saveSecurely: string; saveViewFailed: (message: string) => 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; searchingSessions: string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; searchSessionsLabel: 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; showHiddenSpace: (name: string) => string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; sidebarNoMatches: 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; spaceFromExtension: (extension: string) => string; spaceNamed: (name: string) => string; spaceNameOf: (name: string) => string; spaceOptions: (name: string) => string; spaces: string; spacesTitle: 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; unpinNamed: (project: string) => string; unpinProject: string; unsupportedInteraction: (tool: string) => string; usagePanelHint: string; usageWindow: (window: string, percent: string) => string; useSpaces: string; useSpacesDescription: 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; yourSpaces: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string },
): { detail?: string; question: string }
```

**Parameters**

- `title` (`string`): The session's title.
- `environment` (`SessionEnvironmentSummary | undefined`): Its environment, if any.
- `labels` (`{ activityCompacting: string; activityRetrying: string; activityThinking: string; activityWriting: string; addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addSpace: string; addToChat: string; agent: string; agentDraftNote: string; agentGroupDefault: string; agentProfiles: string; archive: string; archiveConfirmLabel: string; archived: string; archiveProjectMessage: (count: number) => 'It stays under Archived, where you can restore it.' | 'They stay under Archived, where you can restore them.'; archiveProjectTitle: (count: number, project: string) => 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; changeIconFor: (project: string) => string; changeMainIcon: string; changeProjectIcon: string; changeSpaceIcon: 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; chooseImage: string; chooseModel: string; chooseProjectIcon: string; chooseSpaceIcon: string; clearSearch: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; collapseItem: (title: string) => string; collapseSidebar: string; commandDetail: string; commandSuggestions: string; compactingTitle: 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; customEmoji: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; defaultSpaceName: string; delete: string; deleteConfirmLabel: string; deleteProjectArchived: (archived: number) => string; deleteProjectCannotUndo: string; deleteProjectSandboxes: (sandboxed: number) => string; deleteProjectTitle: (count: number, project: string) => string; deleteSessionQuestion: (title: string) => string; deleteSessionSandbox: (kind: string) => string; deleteSpace: string; deleteSpaceMessage: (fallback: string) => string; deleteSpaceNamed: (name: string) => string; deleteSpaceQuestion: (name: string) => 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; emojiPlaceholder: string; environmentActionFailed: (action: string, message: string) => string; environmentKept: (reason?: string) => string; environmentKinds: Readonly<Record<string, string>>; environmentOnBranch: (kind: string, branch: string) => string; environmentOnMachine: (kind: string, machine: string) => string; environmentPaused: (where: string) => string; environmentSettingUp: (where: string) => string; environmentSetupFailed: (where: string, error?: string) => string; environmentsKept: (count: number) => 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; expandItem: (title: string) => string; expandSidebar: 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; footerSettings: string; footerSettingsWithNote: (note: string) => string; footerSignIn: string; footerSignInTitle: string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hiddenSpaces: string; hideSpace: 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; itemActions: (title: string) => string; itemOpenFailed: (message: string) => string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mainSession: string; mentionSuggestions: string; menuAddFavorite: string; menuArchive: string; menuArchiveProject: string; menuCopyPath: string; menuDelete: string; menuDeleteProject: string; menuMoveProjectToSpace: string; menuMoveTo: string; menuMoveToSpace: string; menuOpenChatWindow: string; menuOpenPanelsWindow: string; menuOpenWindow: string; menuRemoveFavorite: string; menuRename: string; menuRetryEnvironment: string; menuReveal: string; menuUnarchive: 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; moveProjectFailed: (message: string) => string; moveSessionFailed: (message: string) => string; moveSpaceDown: (name: string) => string; moveSpaceLeft: string; moveSpaceRight: string; moveSpaceUp: (name: string) => string; newSession: string; newSessionIn: (project: string) => string; newSessionTitle: string; newSpaceName: (n: number) => string; next: string; noAnswer: string; noChatsMatchFilters: string; noChatsYet: 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; pinNamed: (project: string) => string; pinProject: 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; queryGroupOther: 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; resetFilters: string; resetsAt: (time: string) => string; resetToFolder: string; resetToInitial: string; retry: string; retryEnvironmentFailed: (message: string) => string; retryHint: string; rowNeedsYou: string; rowRunning: string; rowScheduled: string; rowWorking: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; savedViewName: (n: number) => string; saveSecurely: string; saveViewFailed: (message: string) => 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; searchingSessions: string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; searchSessionsLabel: 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; showHiddenSpace: (name: string) => string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; sidebarNoMatches: 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; spaceFromExtension: (extension: string) => string; spaceNamed: (name: string) => string; spaceNameOf: (name: string) => string; spaceOptions: (name: string) => string; spaces: string; spacesTitle: 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; unpinNamed: (project: string) => string; unpinProject: string; unsupportedInteraction: (tool: string) => string; usagePanelHint: string; usageWindow: (window: string, percent: string) => string; useSpaces: string; useSpacesDescription: 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; yourSpaces: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }`): The sidebar labels.

**Returns** `{ detail?: string; question: string }`

Source: [ui/src/chat/headless/sidebar/environment.ts:60](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/environment.ts#L60)

### `deriveDotState`

Function.

The dot state. Presence follows the TUI: awaiting input (◉) beats running
(▶) beats attached (○). This window's own pending ask sits on top; a
finished run's notification (completed / error) outranks attached.

```ts
function deriveDotState(input: DotStateInput): SidebarDotState
```

**Parameters**

- `input` (`DotStateInput`): This window's signals and the session's presence.

**Returns** `SidebarDotState`

Source: [ui/src/chat/headless/sidebar/dot-state.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/dot-state.ts#L29)

### `dockRunReceipts`

Function.

Fold `run-summary` rows into the assistant row that closed the run: the
receipt renders as one line under that reply instead of a row (and a dot)
of its own.

Docked by ORDER (the nearest preceding assistant row), not by turn id. Live,
the receipt lands while that row may still be streaming and before `run:end`
settles it; matching ids across the live and persisted paths is one more
thing that can disagree, and then the receipt would fall out as a
standalone block with its own dot, a "new step" the reload path never
produces. The transcript's own order is the authoritative fact: whatever
assistant prose came last IS the run's end.

A receipt with no preceding assistant row IN ITS OWN RUN (a tool-only run,
or one that errored right after a tool) keeps a standalone row rather than
docking onto the row that closed the PREVIOUS run — which would both
mis-attribute it and overwrite that run's receipt. Hence the candidate is
cleared once consumed and at every user prompt: a receipt may only ever
dock onto prose that came after its own run's prompt.

`show === false` (`Settings.showRunReceipt` off) drops the receipts
entirely — no standalone row, nothing docked. Receipts are synthesized both
live and on replay and never persisted, so this is the only gate.

```ts
function dockRunReceipts(
  rows: readonly Row[],
  show: boolean,
): { receiptByRowId: Map<string, RunReceipt>; visibleRows: Row[] }
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows, oldest first.
- `show` (`boolean`): Whether to show run receipts. When false they are dropped.

**Returns** `{ receiptByRowId: Map<string, RunReceipt>; visibleRows: Row[] }`

Source: [ui/src/chat/headless/transcript/fold.ts:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold.ts#L39)

### `dotVariantFor`

Function.

Picks the status dot a row shows.

```ts
function dotVariantFor(row: Row): DotVariant
```

**Parameters**

- `row` (`Row`): The transcript row.

**Returns** `DotVariant`

Source: [ui/src/chat/headless/transcript/fold.ts:328](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold.ts#L328)

### `draftFolderPath`

Function.

The conversation's folder: `null` while the draft has none picked (the
folder gate shows), `''` for none (a server's draft has none on this
computer), else the folder.

```ts
function draftFolderPath(state: DraftFolderState): string | null
```

**Parameters**

- `state` (`DraftFolderState`): The draft's picks, or the open session's folder.

**Returns** `string | null`

Source: [ui/src/chat/headless/draft-target.ts:73](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-target.ts#L73)

### `draftLocalFolder`

Function.

The draft's folder when it is a folder on this computer, the only kind that
makes a draft scope (a server's or machine's draft, or a folderless one, has none).

```ts
function draftLocalFolder(state: DraftFolderState): string | null
```

**Parameters**

- `state` (`DraftFolderState`): The draft's picks (`sessionCwd` set: not a draft, `null`).

**Returns** `string | null`

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

### `draftScopeOf`

Function.

The scope of a draft state, `null` while it has none.

```ts
function draftScopeOf(state: DraftScopeState): DraftScope | null
```

**Parameters**

- `state` (`DraftScopeState`): The draft's state.

**Returns** `DraftScope | null`

Source: [ui/src/chat/headless/draft-scope.ts:65](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L65)

### `drainBucket`

Function.

Pop the head off `bucket.pending` using the surrogate-safe slice.
Convenience over a raw `safeSurrogateSlice` call when the caller
doesn't need the remainder.

```ts
function drainBucket(bucket: DeltaBucket, n: number): string
```

**Parameters**

- `bucket` (`DeltaBucket`): The bucket to drain.
- `n` (`number`): How many code units to take (see [`tickBucket`](https://zidane.si/docs/reference/ui-chat-headless.md#tickBucket)).

**Returns** `string`

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

### `effortPickerTarget`

Function.

What the effort picker offers for a session, `null` when its model has
nothing to set (no dead-end dialog).

```ts
function effortPickerTarget(
  status: ComposerContextStatus | null | undefined,
  sessionOptions?: Record<string, boolean>,
): EffortPickerTarget | null
```

**Parameters**

- `status` (`ComposerContextStatus | null | undefined`): The session's context status (`null` while unknown).
- `sessionOptions?` (`Record<string, boolean>`): The session's own enabled options, which win over the status's.

**Returns** `EffortPickerTarget | null`

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

### `encodeHistoryDraft`

Function.

Encode the in-progress draft for the prompt-history stash so a
shell-mode draft survives the cycle round trip with its bang
(`usePromptHistory`, src/tui/prompt/use-prompt-history.ts). Search-mode drafts are never stashed (history
cycling is disabled in search mode).

```ts
function encodeHistoryDraft(mode: ComposerMode, text: string): string
```

**Parameters**

- `mode` (`ComposerMode`): The composer's mode the entry was sent in.
- `text` (`string`): The text sent.

**Returns** `string`

Source: [ui/src/chat/headless/composer-modes.ts:153](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer-modes.ts#L153)

### `environmentKindLabel`

Function.

An environment kind's display name: a built-in kind's name, a machine's kind as `Local @ laptop`, else the id.

```ts
function environmentKindLabel(
  kind: string,
  labels: Pick<SidebarLabels, 'environmentKinds' | 'environmentOnMachine'>,
): string
```

**Parameters**

- `kind` (`string`): The kind (`worktree`, `local@laptop`, an extension's id).
- `labels` (`Pick<SidebarLabels, 'environmentKinds' | 'environmentOnMachine'>`): The sidebar labels.

**Returns** `string`

Source: [ui/src/chat/headless/sidebar/environment.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/environment.ts#L29)

### `environmentSummaryText`

Function.

Where a session runs, in one line: tooltips and screen readers.

```ts
function environmentSummaryText(
  environment: SessionEnvironmentSummary,
  labels: { activityCompacting: string; activityRetrying: string; activityThinking: string; activityWriting: string; addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addSpace: string; addToChat: string; agent: string; agentDraftNote: string; agentGroupDefault: string; agentProfiles: string; archive: string; archiveConfirmLabel: string; archived: string; archiveProjectMessage: (count: number) => 'It stays under Archived, where you can restore it.' | 'They stay under Archived, where you can restore them.'; archiveProjectTitle: (count: number, project: string) => 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; changeIconFor: (project: string) => string; changeMainIcon: string; changeProjectIcon: string; changeSpaceIcon: 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; chooseImage: string; chooseModel: string; chooseProjectIcon: string; chooseSpaceIcon: string; clearSearch: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; collapseItem: (title: string) => string; collapseSidebar: string; commandDetail: string; commandSuggestions: string; compactingTitle: 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; customEmoji: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; defaultSpaceName: string; delete: string; deleteConfirmLabel: string; deleteProjectArchived: (archived: number) => string; deleteProjectCannotUndo: string; deleteProjectSandboxes: (sandboxed: number) => string; deleteProjectTitle: (count: number, project: string) => string; deleteSessionQuestion: (title: string) => string; deleteSessionSandbox: (kind: string) => string; deleteSpace: string; deleteSpaceMessage: (fallback: string) => string; deleteSpaceNamed: (name: string) => string; deleteSpaceQuestion: (name: string) => 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; emojiPlaceholder: string; environmentActionFailed: (action: string, message: string) => string; environmentKept: (reason?: string) => string; environmentKinds: Readonly<Record<string, string>>; environmentOnBranch: (kind: string, branch: string) => string; environmentOnMachine: (kind: string, machine: string) => string; environmentPaused: (where: string) => string; environmentSettingUp: (where: string) => string; environmentSetupFailed: (where: string, error?: string) => string; environmentsKept: (count: number) => 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; expandItem: (title: string) => string; expandSidebar: 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; footerSettings: string; footerSettingsWithNote: (note: string) => string; footerSignIn: string; footerSignInTitle: string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hiddenSpaces: string; hideSpace: 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; itemActions: (title: string) => string; itemOpenFailed: (message: string) => string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mainSession: string; mentionSuggestions: string; menuAddFavorite: string; menuArchive: string; menuArchiveProject: string; menuCopyPath: string; menuDelete: string; menuDeleteProject: string; menuMoveProjectToSpace: string; menuMoveTo: string; menuMoveToSpace: string; menuOpenChatWindow: string; menuOpenPanelsWindow: string; menuOpenWindow: string; menuRemoveFavorite: string; menuRename: string; menuRetryEnvironment: string; menuReveal: string; menuUnarchive: 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; moveProjectFailed: (message: string) => string; moveSessionFailed: (message: string) => string; moveSpaceDown: (name: string) => string; moveSpaceLeft: string; moveSpaceRight: string; moveSpaceUp: (name: string) => string; newSession: string; newSessionIn: (project: string) => string; newSessionTitle: string; newSpaceName: (n: number) => string; next: string; noAnswer: string; noChatsMatchFilters: string; noChatsYet: 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; pinNamed: (project: string) => string; pinProject: 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; queryGroupOther: 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; resetFilters: string; resetsAt: (time: string) => string; resetToFolder: string; resetToInitial: string; retry: string; retryEnvironmentFailed: (message: string) => string; retryHint: string; rowNeedsYou: string; rowRunning: string; rowScheduled: string; rowWorking: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; savedViewName: (n: number) => string; saveSecurely: string; saveViewFailed: (message: string) => 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; searchingSessions: string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; searchSessionsLabel: 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; showHiddenSpace: (name: string) => string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; sidebarNoMatches: 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; spaceFromExtension: (extension: string) => string; spaceNamed: (name: string) => string; spaceNameOf: (name: string) => string; spaceOptions: (name: string) => string; spaces: string; spacesTitle: 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; unpinNamed: (project: string) => string; unpinProject: string; unsupportedInteraction: (tool: string) => string; usagePanelHint: string; usageWindow: (window: string, percent: string) => string; useSpaces: string; useSpacesDescription: 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; yourSpaces: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string },
): string
```

**Parameters**

- `environment` (`SessionEnvironmentSummary`): The session's environment.
- `labels` (`{ activityCompacting: string; activityRetrying: string; activityThinking: string; activityWriting: string; addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addSpace: string; addToChat: string; agent: string; agentDraftNote: string; agentGroupDefault: string; agentProfiles: string; archive: string; archiveConfirmLabel: string; archived: string; archiveProjectMessage: (count: number) => 'It stays under Archived, where you can restore it.' | 'They stay under Archived, where you can restore them.'; archiveProjectTitle: (count: number, project: string) => 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; changeIconFor: (project: string) => string; changeMainIcon: string; changeProjectIcon: string; changeSpaceIcon: 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; chooseImage: string; chooseModel: string; chooseProjectIcon: string; chooseSpaceIcon: string; clearSearch: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; collapseItem: (title: string) => string; collapseSidebar: string; commandDetail: string; commandSuggestions: string; compactingTitle: 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; customEmoji: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; defaultSpaceName: string; delete: string; deleteConfirmLabel: string; deleteProjectArchived: (archived: number) => string; deleteProjectCannotUndo: string; deleteProjectSandboxes: (sandboxed: number) => string; deleteProjectTitle: (count: number, project: string) => string; deleteSessionQuestion: (title: string) => string; deleteSessionSandbox: (kind: string) => string; deleteSpace: string; deleteSpaceMessage: (fallback: string) => string; deleteSpaceNamed: (name: string) => string; deleteSpaceQuestion: (name: string) => 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; emojiPlaceholder: string; environmentActionFailed: (action: string, message: string) => string; environmentKept: (reason?: string) => string; environmentKinds: Readonly<Record<string, string>>; environmentOnBranch: (kind: string, branch: string) => string; environmentOnMachine: (kind: string, machine: string) => string; environmentPaused: (where: string) => string; environmentSettingUp: (where: string) => string; environmentSetupFailed: (where: string, error?: string) => string; environmentsKept: (count: number) => 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; expandItem: (title: string) => string; expandSidebar: 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; footerSettings: string; footerSettingsWithNote: (note: string) => string; footerSignIn: string; footerSignInTitle: string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hiddenSpaces: string; hideSpace: 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; itemActions: (title: string) => string; itemOpenFailed: (message: string) => string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mainSession: string; mentionSuggestions: string; menuAddFavorite: string; menuArchive: string; menuArchiveProject: string; menuCopyPath: string; menuDelete: string; menuDeleteProject: string; menuMoveProjectToSpace: string; menuMoveTo: string; menuMoveToSpace: string; menuOpenChatWindow: string; menuOpenPanelsWindow: string; menuOpenWindow: string; menuRemoveFavorite: string; menuRename: string; menuRetryEnvironment: string; menuReveal: string; menuUnarchive: 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; moveProjectFailed: (message: string) => string; moveSessionFailed: (message: string) => string; moveSpaceDown: (name: string) => string; moveSpaceLeft: string; moveSpaceRight: string; moveSpaceUp: (name: string) => string; newSession: string; newSessionIn: (project: string) => string; newSessionTitle: string; newSpaceName: (n: number) => string; next: string; noAnswer: string; noChatsMatchFilters: string; noChatsYet: 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; pinNamed: (project: string) => string; pinProject: 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; queryGroupOther: 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; resetFilters: string; resetsAt: (time: string) => string; resetToFolder: string; resetToInitial: string; retry: string; retryEnvironmentFailed: (message: string) => string; retryHint: string; rowNeedsYou: string; rowRunning: string; rowScheduled: string; rowWorking: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; savedViewName: (n: number) => string; saveSecurely: string; saveViewFailed: (message: string) => 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; searchingSessions: string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; searchSessionsLabel: 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; showHiddenSpace: (name: string) => string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; sidebarNoMatches: 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; spaceFromExtension: (extension: string) => string; spaceNamed: (name: string) => string; spaceNameOf: (name: string) => string; spaceOptions: (name: string) => string; spaces: string; spacesTitle: 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; unpinNamed: (project: string) => string; unpinProject: string; unsupportedInteraction: (tool: string) => string; usagePanelHint: string; usageWindow: (window: string, percent: string) => string; useSpaces: string; useSpacesDescription: 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; yourSpaces: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }`): The sidebar labels.

**Returns** `string`

Source: [ui/src/chat/headless/sidebar/environment.ts:44](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/environment.ts#L44)

### `exitsModeOnKey`

Function.

Whether `key` (a DOM `KeyboardEvent.key`) exits the active mode.
`caretAtStart` = collapsed selection at buffer offset 0.

- shell: Backspace-at-0 only (`handleShellExitKey`) — Esc stays free
  for its global meaning (stop run).
- search: Backspace/Delete-at-0 (`isTranscriptSearchExitKey`,
  src/tui/prompt/prompt-key-handlers.ts) or Esc (`usePromptModes`,
  src/tui/prompt/use-prompt-modes.ts).

```ts
function exitsModeOnKey(mode: ComposerMode, key: string, caretAtStart: boolean): boolean
```

**Parameters**

- `mode` (`ComposerMode`): The composer's mode now.
- `key` (`string`): The key pressed (`KeyboardEvent.key`).
- `caretAtStart` (`boolean`): Whether the caret is at the start of the text.

**Returns** `boolean`

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

### `extensionSpaceOf`

Function.

An extension's space as the sidebar lists it: read-only, its `newSession` defaults as the space's.

```ts
function extensionSpaceOf(entry: ExtensionItem<'space'>): SidebarSpace
```

**Parameters**

- `entry` (`ExtensionItem<'space'>`): The space item.

**Returns** `SidebarSpace`

Source: [ui/src/chat/headless/sidebar/query.ts:141](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L141)

### `failureTooltip`

Function.

The failure row's tooltip: the line, then what it leaves out (when the
limit resets, the provider's own words). Never inline: the row stays one
quiet line.

```ts
function failureTooltip(
  text: string,
  detail: RunErrorDetail | undefined,
  resetsAtLabel: (time: string) => string,
): string | undefined
```

**Parameters**

- `text` (`string`): The failure line.
- `detail` (`RunErrorDetail | undefined`): What the line leaves out.
- `resetsAtLabel` (`(time: string) => string`): Words a reset time (`Resets at 14:30`).

**Returns** `string | undefined`

Source: [ui/src/chat/headless/transcript/run-failures.ts:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/run-failures.ts#L37)

### `filterDirectorySessions`

Function.

The sessions the list shows: the space's (a remote session without a space
shows in every space), then the project and activity filters. The same
array when nothing filters.

```ts
function filterDirectorySessions<S extends SidebarListSession>(
  sessions: readonly S[],
  filter: { activity: SessionActivityFilter; inSpace: ((session: S) => boolean) | null; now?: number; project: string | null },
): readonly S[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `sessions` (`readonly S[]`): Every listed session.
- `filter` (`{ activity: SessionActivityFilter; inSpace: ((session: S) => boolean) | null; now?: number; project: string | null }`): The space predicate (`null`: spaces off), the project and activity axes.

**Returns** `readonly S[]`

Source: [ui/src/chat/headless/sidebar/directory.ts:1028](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L1028)

### `filterQueryOf`

Function.

The query one contributed filter applies at the value the user picked, or `null` (off, or an
option no longer offered). A multi filter keeps a session one of its picked options matches.

```ts
function filterQueryOf(
  filter: SidebarFilterWire,
  value: string | boolean | readonly string[] | undefined,
): SessionQuery | null
```

**Parameters**

- `filter` (`SidebarFilterWire`): The filter's wire form.
- `value` (`string | boolean | readonly string[] | undefined`): What the user picked.

**Returns** `SessionQuery | null`

Source: [ui/src/chat/headless/sidebar/query.ts:292](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L292)

### `filterSessions`

Function.

Sessions whose title contains every word of `query` (case-insensitive).

```ts
function filterSessions<S extends ListableSession>(
  sessions: readonly S[],
  query: string,
): S[]
```

**Type parameters**

- `S` (`extends ListableSession`)

**Parameters**

- `sessions` (`readonly S[]`): The sessions to filter.
- `query` (`string`): Space-separated words. A blank query returns a copy of every session.

**Returns** `S[]`

Source: [ui/src/chat/headless/session-list.ts:393](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L393)

### `filtersForSpace`

Function.

The contributed filters a space offers: those for every space and those naming it.

```ts
function filtersForSpace(
  filters: readonly ExtensionItem<'sidebar-filter'>[],
  spaceId: string,
): readonly ExtensionItem<'sidebar-filter'>[]
```

**Parameters**

- `filters` (`readonly ExtensionItem<'sidebar-filter'>[]`): Every filter item.
- `spaceId` (`string`): The space shown.

**Returns** `readonly ExtensionItem<'sidebar-filter'>[]`

Source: [ui/src/chat/headless/sidebar/query.ts:278](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L278)

### `findCommand`

Function.

The command `token` (a name or an alias, without the slash) names in `commands`, or `undefined`.

```ts
function findCommand(
  commands: readonly CommandSummary[],
  token: string,
): CommandSummary | undefined
```

**Parameters**

- `commands` (`readonly CommandSummary[]`): The catalog.
- `token` (`string`): What follows the `/`.

**Returns** `CommandSummary | undefined`

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

### `findLastStreamingRow`

Function.

The streaming reply that carries the caret, looking inside message groups.

```ts
function findLastStreamingRow(rows: readonly Row[]): Row | null
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows, oldest first.

**Returns** `Row | null`

Source: [ui/src/chat/headless/transcript/fold.ts:314](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold.ts#L314)

### `firstGrapheme`

Function.

First grapheme cluster of the input — `Intl.Segmenter` so ZWJ-joined
emoji (👨‍💻, 🏳️‍🌈) survive as one unit instead of splitting at the
first code point.

```ts
function firstGrapheme(value: string): string | null
```

**Parameters**

- `value` (`string`): What was typed.

**Returns** `string | null`

Source: [ui/src/chat/headless/sidebar/project-icons.ts:106](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L106)

### `firstRowId`

Function.

A block's first row in paint order (its own or a nested block's): a stable key.

```ts
function firstRowId(
  cluster: { body: Cluster[]; childId: string; depth: number; kind: 'group'; rows: Row[] },
): string | undefined
```

**Parameters**

- `cluster` (`{ body: Cluster[]; childId: string; depth: number; kind: 'group'; rows: Row[] }`): The subagent block to read.

**Returns** `string | undefined`

Source: [ui/src/chat/headless/transcript/rows.ts:310](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L310)

### `foldActionItems`

Function.

Every action of an exchange, in order (core `planFold`, shared with the
TUI): tool calls (batches seen through, the calls a call made nested under
it), consecutive thoughts merged, each worker one item holding its rows
and merged with the `spawn` call that started it. Rows that say nothing on
their own (plain notes) are skipped.

```ts
function foldActionItems(rows: readonly Row[]): FoldActionItem[]
```

**Parameters**

- `rows` (`readonly Row[]`): The rows of one exchange, oldest first.

**Returns** `FoldActionItem[]`

Source: [ui/src/chat/headless/transcript/fold-actions.ts:253](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold-actions.ts#L253)

### `foldExchanges`

Function.

Compact density: fold every exchange's work behind one `exchange-fold`
row. An exchange is the span between two boundary rows (`user-prompt`,
`separator`, `compact-summary`); rows that `foldsInCompact` move
into the fold, which sits RIGHT UNDER the exchange's prompt, ahead of the
prose (prose written before the first call still reads after the work
indicator, never between the prompt and it).

The exchange of a running run is `live` until the run ends (one working
indicator for the whole reply, however much prose streams in between).
It appears as soon as the prompt lands, before any action ("Working"),
so the indicator is always in place instead of jumping in later; a run
that ends without any action leaves no fold behind.

Runs after batching and receipt docking (so batches are already folded
and receipts already docked on their prose) and before owner clustering
(the fold's rows are clustered again when it is expanded, so worker
blocks paint exactly as in full density).

```ts
function foldExchanges(rows: readonly Row[], isStreaming: boolean): Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows after batching and receipt docking, oldest first.
- `isStreaming` (`boolean`): A run is in flight, so the last exchange is live.

**Returns** `Row[]`

Source: [ui/src/chat/headless/transcript/fold.ts:151](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold.ts#L151)

### `foldWorkerRows`

Function.

A worker's (subagent's) own rows folded like an exchange of the main
transcript: its tool calls, thoughts and the workers it started behind one
"Working" row, its earlier messages behind one group, its last message in
full. Its own rows are re-based to depth 0 (same row objects per input, so
folds keep their identity across stream ticks); rows of workers it started
keep their lane and fold as worker lines. Its lifecycle markers are left
out: the line or header showing the worker already carries them.

```ts
function foldWorkerRows(rows: readonly Row[], owner: string, live: boolean): Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): The rows that include the worker's own rows and those of workers it started.
- `owner` (`string`): The `childId` of the worker whose rows to fold.
- `live` (`boolean`): The worker is still running, so its last exchange is live.

**Returns** `Row[]`

Source: [ui/src/chat/headless/transcript/fold.ts:234](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold.ts#L234)

### `formatElapsedShort`

Function.

A running session's elapsed time: `42s`, `12m`, `1h 5m`.

```ts
function formatElapsedShort(sec: number): string
```

**Parameters**

- `sec` (`number`): Elapsed whole seconds.

**Returns** `string`

Source: [ui/src/chat/headless/session-list.ts:235](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L235)

### `formatSessionCostLabel`

Function.

Shared with the TUI (`formatCostLabel` in `src/chat/format.ts`).

```ts
function formatSessionCostLabel(usd: number): string | null
```

**Parameters**

- `usd` (`number`): Cost in USD.

**Returns** `string | null`

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

### `groupsByFolder`

Function.

Views whose groups are folders: Per directory, and each host's section in Per host.

```ts
function groupsByFolder(groupBy: SidebarGroupBy): boolean
```

**Parameters**

- `groupBy` (`SidebarGroupBy`): The view.

**Returns** `boolean`

Source: [ui/src/chat/headless/sidebar/rows.ts:58](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L58)

### `hostReachable`

Function.

Whether sessions on a host can be driven: This computer always, a server
only while connected. A host no longer saved (`undefined`) is not.

```ts
function hostReachable(host: HostView | undefined): boolean
```

**Parameters**

- `host` (`HostView | undefined`): The host, or `undefined` when it is not saved anymore.

**Returns** `boolean`

Source: [ui/src/chat/headless/hosts.ts:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/hosts.ts#L40)

### `hostStatusLabel`

Function.

One word for a host's status, for dots and labels, as the TUI words it.

```ts
function hostStatusLabel(
  host: HostView,
  labels?: Pick<ChatLabels, 'hostStatuses'>,
): string
```

**Parameters**

- `host` (`HostView`): The host.
- `labels?` (`Pick<ChatLabels, 'hostStatuses'>`, default `DEFAULT_CHAT_LABELS`): The label dictionary (default: the kit's English one).

**Returns** `string`

Source: [ui/src/chat/headless/hosts.ts:50](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/hosts.ts#L50)

### `inheritRowIdentity`

Function.

Hands the row identity of the prompts `next` dropped to their copies in
it. A store swaps a prompt on show for an updated copy when it learns its
turn (the host's binding, or the persisted copy a page read brings): the
copy's rows keep their keys, so they update in place instead of
remounting and playing their entrance again. A copy is the same prompt by
its words, as `reconcileEvents` matches prompts; the newest pair first, so
an older prompt with the same words keeps its own rows.

```ts
function inheritRowIdentity(
  prev: readonly ChatEvent[],
  next: readonly ChatEvent[],
): void
```

**Parameters**

- `prev` (`readonly ChatEvent[]`): The events on show before the update.
- `next` (`readonly ChatEvent[]`): The events after it.

Source: [ui/src/chat/headless/transcript/collapse.ts:103](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/collapse.ts#L103)

### `isAuthFixed`

Function.

Whether a failure's sign-in was fixed since.

```ts
function isAuthFixed(fixes: readonly AuthFailure[], auth: AuthFailure): boolean
```

**Parameters**

- `fixes` (`readonly AuthFailure[]`): The session's fixed sign-ins.
- `auth` (`AuthFailure`): The failure.

**Returns** `boolean`

Source: [ui/src/chat/headless/transcript/auth-failure.ts:125](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L125)

### `isProjectIcon`

Function.

Whether a stored entry is a well-formed icon.

```ts
function isProjectIcon(entry: unknown): entry is ProjectIcon
```

**Parameters**

- `entry` (`unknown`): The stored value.

**Returns** `entry is ProjectIcon`

Source: [ui/src/chat/headless/sidebar/project-icons.ts:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L53)

### `isProjectMember`

Function.

Whether `session` is listed under a project header: a local session in its
folder, or, for a header that names a `repoKey`, a server session of that
repository.

```ts
function isProjectMember(
  session: SidebarListSession,
  project: { hostId?: string; path: string; repoKey?: string },
): boolean
```

**Parameters**

- `session` (`SidebarListSession`): The session.
- `project` (`{ hostId?: string; path: string; repoKey?: string }`): The header's folder (`path`), its server (`hostId`) and its repository (`repoKey`).

**Returns** `boolean`

Source: [ui/src/chat/headless/sidebar/rows.ts:172](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L172)

### `itemRows`

Function.

An item's row and its child sessions' rows (none while it is collapsed).

```ts
function itemRows<S extends SidebarListSession>(
  item: SidebarItemEntry<S>,
  collapsedGroups?: ReadonlySet<string>,
): SidebarListRow<S>[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `item` (`SidebarItemEntry<S>`): The item and its child sessions.
- `collapsedGroups?` (`ReadonlySet<string>`, default `EMPTY_SET`): Collapsed row ids (an item collapses under its row id).

**Returns** `SidebarListRow<S>[]`

Source: [ui/src/chat/headless/sidebar/rows.ts:272](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L272)

### `itemsForSpace`

Function.

The items listed in a space: those naming it, where the space allows items (the default space
and user spaces always; an extension's when it says so).

```ts
function itemsForSpace(
  items: readonly ExtensionItem<'sidebar-row'>[],
  space: SidebarSpace,
): readonly ExtensionItem<'sidebar-row'>[]
```

**Parameters**

- `items` (`readonly ExtensionItem<'sidebar-row'>[]`): Every item.
- `space` (`SidebarSpace`): The space shown.

**Returns** `readonly ExtensionItem<'sidebar-row'>[]`

Source: [ui/src/chat/headless/sidebar/query.ts:536](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L536)

### `lastModelChainOf`

Function.

The prefs' `lastModelChain` entries for a chain (core `ModelChainEntry` shape, account included).

```ts
function lastModelChainOf(chain: readonly ModelPickRef[]): ComposerRememberedModel[]
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The chain.

**Returns** `ComposerRememberedModel[]`

Source: [ui/src/chat/headless/composer/remember-model-pick.ts:89](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/remember-model-pick.ts#L89)

### `markRunFailures`

Function.

Returns `rows` itself when no run failed, so memoised consumers stay put.
The rules are core's (`createRunStopMarker`), shared with the TUI; an
exchange whose rows did not change keeps its previous output rows.

```ts
function markRunFailures(rows: readonly Row[]): readonly Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): The transcript rows, oldest first.

**Returns** `readonly Row[]`

Source: [ui/src/chat/headless/transcript/run-failures.ts:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/run-failures.ts#L70)

### `mergeLiveTail`

Function.

Hydrate a live-only window: the disk page followed by the live events
that disk does not have yet. Persisted turns and their live events share
a `turnId` (hooks pre-mint it), so the boundary is the LAST live event
whose turn is on the page — everything after it (the in-flight turn's
streaming markdown, a display-only error row) is kept; everything before
it is superseded by its persisted form. No live turn on the page (the
run's first turn is still streaming) keeps the whole live lane.

Untagged live events in the kept suffix (a `user-prompt` echo is
broadcast bare and only retagged by `prompt-turns`, `steer:inject` echoes
likewise) are dropped when the page's trailing part already holds the
same `kind` + `text` — otherwise the disk copy and the echo both render.

```ts
function mergeLiveTail(
  live: readonly ChatEvent[],
  page: readonly ChatEvent[],
): ChatEvent[]
```

**Parameters**

- `live` (`readonly ChatEvent[]`): The window's live events (never hydrated from disk).
- `page` (`readonly ChatEvent[]`): The persisted page to hydrate it with.

**Returns** `ChatEvent[]`

Source: [ui/src/chat/headless/streams/merge.ts:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/merge.ts#L22)

### `mergePromptPreviews`

Function.

Fill `dataUrl` on image and PDF attachments that lack one, from `previews`:
same media type and name first, then the next unused preview of that media
type. With no incoming metadata at all (a local append that knew nothing
of the attachments) the previews are the attachments.

```ts
function mergePromptPreviews(
  attachments: readonly ChatAttachment[] | undefined,
  previews: readonly ChatAttachment[],
): ChatAttachment[] | undefined
```

**Parameters**

- `attachments` (`readonly ChatAttachment[] | undefined`): The attachments the prompt arrived with, metadata only for a host-sent copy.
- `previews` (`readonly ChatAttachment[]`): The attachments this client kept when it queued the prompt, with their bytes.

**Returns** `ChatAttachment[] | undefined`

Source: [ui/src/chat/headless/streams/prompt-previews.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/prompt-previews.ts#L29)

### `mergeSidebarSpaces`

Function.

The spaces the sidebar knows: the user's in their order (a saved view's query kept), then the
extensions' by `order`. A space the host already lists under an extension's id takes the
extension's base and keeps its place; one with an extension space's id (`<extension>/<id>`) whose
extension contributes it no more is dropped, as core and the terminal app drop it.

```ts
function mergeSidebarSpaces(
  user: readonly Space[],
  stored: unknown,
  extension: readonly ExtensionItem<'space'>[],
): SidebarSpace[]
```

**Parameters**

- `user` (`readonly Space[]`): The user's spaces, normalized (`normalizeSpaces`).
- `stored` (`unknown`): The settings' space list as stored, for what normalizing dropped (a saved view's query).
- `extension` (`readonly ExtensionItem<'space'>[]`): The extensions' space items.

**Returns** `SidebarSpace[]`

Source: [ui/src/chat/headless/sidebar/query.ts:189](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L189)

### `missingPreviewData`

Function.

True when some image or PDF attachment has no bytes to show.

```ts
function missingPreviewData(attachments: readonly ChatAttachment[] | undefined): boolean
```

**Parameters**

- `attachments` (`readonly ChatAttachment[] | undefined`): The prompt's attachments.

**Returns** `boolean`

Source: [ui/src/chat/headless/streams/prompt-previews.ts:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/prompt-previews.ts#L62)

### `modeForTypedChar`

Function.

Mode entered by typing `char` into the composer, or `null` when the
keystroke should be handled as ordinary input. Requires an empty
buffer and no active mode — matches the TUI's exactly-`!` /
exactly-`?` on `lastSynced === ''` checks (`useSyncBuffer`,
src/tui/prompt/use-sync-buffer.ts).

```ts
function modeForTypedChar(
  char: string,
  mode: ComposerMode,
  bufferEmpty: boolean,
): ComposerMode | null
```

**Parameters**

- `char` (`string`): The character just typed.
- `mode` (`ComposerMode`): The composer's mode now.
- `bufferEmpty` (`boolean`): Whether the composer was empty before it.

**Returns** `ComposerMode | null`

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

### `modelKnobsOf`

Function.

The one [`ModelKnobsStore`](https://zidane.si/docs/reference/ui-chat-headless.md#ModelKnobsStore) over a host's `prefs` (one shared in-memory store when it has none).

```ts
function modelKnobsOf(prefs: ComposerPrefs | undefined): ModelKnobsStore
```

**Parameters**

- `prefs` (`ComposerPrefs | undefined`): The host's member.

**Returns** `ModelKnobsStore`

Source: [ui/src/chat/headless/composer/model-knobs.ts:174](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-knobs.ts#L174)

### `modelNamesOf`

Function.

The one [`ModelNamesStore`](https://zidane.si/docs/reference/ui-chat-headless.md#ModelNamesStore) over a host's `models` (this computer's catalog, and its providers when listed).
Without `models`, every model keeps its readable id.

```ts
function modelNamesOf(models: ComposerModels | undefined): ModelNamesStore
```

**Parameters**

- `models` (`ComposerModels | undefined`): The host's member.

**Returns** `ModelNamesStore`

Source: [ui/src/chat/headless/composer/model-names.ts:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-names.ts#L140)

### `namerFor`

Function.

A namer reading `catalog`: the entry of that provider first, then any provider listing the id.

```ts
function namerFor(
  catalog: readonly Pick<ModelCatalogRow, 'providerKey' | 'modelId' | 'modelName'>[],
): ModelNamer
```

**Parameters**

- `catalog` (`readonly Pick<ModelCatalogRow, 'providerKey' | 'modelId' | 'modelName'>[]`): The catalog rows.

**Returns** `ModelNamer`

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

### `nestedCallVisible`

Function.

Whether a nested call's events show: core's `nestedCallShown` (a subagent,
a plan or a question always; the rest only with
`Settings.codemodeShowCalls`), the rule `isVisible` applies too.

```ts
function nestedCallVisible(event: ChatEvent, codemodeShowCalls: boolean): boolean
```

**Parameters**

- `event` (`ChatEvent`): The transcript event.
- `codemodeShowCalls` (`boolean`): The user's `codemodeShowCalls` setting.

**Returns** `boolean`

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

### `nestSidebarRows`

Function.

The flat rows as nested sections: a host's section holds its groups, a
group's holds its rows. Rows before any header (a flat view) stay at the
top level, and so do a flat view's rows after its Favorites.

```ts
function nestSidebarRows<S extends SidebarListSession>(
  rows: readonly SidebarListRow<S>[],
): SidebarNode<S>[]
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `rows` (`readonly SidebarListRow<S>[]`): The flat rows.

**Returns** `SidebarNode<S>[]`

Source: [ui/src/chat/headless/sidebar/rows.ts:389](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L389)

### `nestToolCalls`

Function.

Moves every tool row whose `parentId` names a call in `rows` (same owner)
into that call's `children`. A nested row whose parent is absent stays
where it is. Returns `rows` itself when nothing nests.

```ts
function nestToolCalls(rows: readonly Row[]): readonly Row[]
```

**Parameters**

- `rows` (`readonly Row[]`): Rows from [`collapseEvents`](https://zidane.si/docs/reference/ui-chat-headless.md#collapseEvents), oldest first.

**Returns** `readonly Row[]`

Source: [ui/src/chat/headless/transcript/nesting.ts:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/nesting.ts#L37)

### `newSessionRequest`

Function.

The session a first send creates from the draft: on a server, its folder
(or its first root), never one of this computer's; on a machine, the
machine's folder; otherwise the draft's folder, if any. The model pick goes
only when both halves are set.

```ts
function newSessionRequest(
  draft: SendDraft,
  text: string,
  defaults: NewSessionDefaults,
  machineCwd?: string | null,
): NewSessionRequest
```

**Parameters**

- `draft` (`SendDraft`): The draft.
- `text` (`string`): The prompt (its first line names the session).
- `defaults` (`NewSessionDefaults`): What the session starts with.
- `machineCwd?` (`string | null`, default `null`): The machine's folder when the draft runs on a machine.

**Returns** `NewSessionRequest`

Source: [ui/src/chat/headless/send-flow.ts:198](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L198)

### `nextSavedViewName`

Function.

The first saved-view name no space has yet: `nameOf(1)`, `nameOf(2)`…

```ts
function nextSavedViewName(
  spaces: readonly Pick<Space, 'name'>[],
  nameOf: (n: number) => string,
): string
```

**Parameters**

- `spaces` (`readonly Pick<Space, 'name'>[]`): Every space.
- `nameOf` (`(n: number) => string`): The name of the n-th saved view (`labels.savedViewName`).

**Returns** `string`

Source: [ui/src/chat/headless/sidebar/query.ts:619](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L619)

### `openFenceOf`

Function.

The fence a streaming chunk ends inside, when it opened at column 0 (an
indented one may belong to a list item, which only the parse can tell).
The open fence is the whole tail of the chunk, so parsing it again on
every delta re-parses a growing code block for nothing: the code block can
draw the text as is, and the chunk parses normally once the fence closes.

```ts
function openFenceOf(chunk: string): OpenFence | null
```

**Parameters**

- `chunk` (`string`): The last chunk of a streaming reply.

**Returns** `OpenFence | null`: The open fence, or `null` when the chunk does not end inside one.

Source: [ui/src/chat/headless/markdown-chunks.ts:75](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/markdown-chunks.ts#L75)

### `pairToolEvents`

Function.

Matches each `tool` event with its `tool-result` or `error` event. Pairs by `callId` when events carry one, and by position within the turn and tool name otherwise.

```ts
function pairToolEvents(events: readonly ChatEvent[]): PairingResult
```

**Parameters**

- `events` (`readonly ChatEvent[]`): The transcript events, oldest first.

**Returns** `PairingResult`

Source: [ui/src/chat/headless/transcript/pairing.ts:35](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/pairing.ts#L35)

### `parseBashExitMeta`

Function.

Parse the exit metadata the shell contract embeds in the persisted
result text (see `runBashCommand` in the TUI / `startShellRun` in
main): `(exit 0, Nms)` footer on success, `Exit code N (Nms)` /
`Killed (Nms)` header on failure, `(cancelled by user after Nms)`
footer on abort. Live and reloaded transcripts render identically
because both read the same text. Returns null when nothing matches
(still streaming, or a clipped tail dropped the footer).

```ts
function parseBashExitMeta(text: string): BashExitMeta | null
```

**Parameters**

- `text` (`string`): The shell tool's result text.

**Returns** `BashExitMeta | null`

Source: [ui/src/chat/headless/transcript/rows.ts:339](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L339)

### `parseModelPickerPrefs`

Function.

Parses stored preferences; `undefined` when they are not JSON.

```ts
function parseModelPickerPrefs(raw: string): ModelPickerPrefs | undefined
```

**Parameters**

- `raw` (`string`): The stored string.

**Returns** `ModelPickerPrefs | undefined`

Source: [ui/src/chat/headless/composer/model-picker-prefs.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-picker-prefs.ts#L26)

### `parsePinnedProjects`

Function.

Reads a stored pin map, dropping anything malformed and duplicate paths.

```ts
function parsePinnedProjects(raw: string): PinsBySpace
```

**Parameters**

- `raw` (`string`): The stored JSON.

**Returns** `PinsBySpace`

Source: [ui/src/chat/headless/sidebar/pinned-projects.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-projects.ts#L19)

### `parseProjectIcons`

Function.

Reads a stored icon map, keeping only well-formed entries.

```ts
function parseProjectIcons(raw: string): ProjectIconMap
```

**Parameters**

- `raw` (`string`): The stored JSON.

**Returns** `ProjectIconMap`

Source: [ui/src/chat/headless/sidebar/project-icons.ts:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L68)

### `parseSessionHistory`

Function.

A stored history, checked: entries are session keys (non-empty strings) or `null`, the cursor one of them.
Anything malformed reads as no history.

```ts
function parseSessionHistory<K extends string = string>(
  raw: unknown,
  limit?: number,
): SessionHistoryState<K>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Parameters**

- `raw` (`unknown`): The stored value.
- `limit?` (`number`, default `SESSION_HISTORY_LIMIT`): The most entries kept.

**Returns** `SessionHistoryState<K>`

Source: [ui/src/chat/headless/sidebar/history.ts:122](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L122)

### `parseSidebarView`

Function.

A stored view, every axis checked; what is missing or unknown takes the default.

```ts
function parseSidebarView(raw: unknown): SidebarView
```

**Parameters**

- `raw` (`unknown`): The stored value.

**Returns** `SidebarView`

Source: [ui/src/chat/headless/sidebar/view.ts:87](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L87)

### `parseSwitcherPrefs`

Function.

Stored switcher prefs, checked; anything malformed reads as none.

```ts
function parseSwitcherPrefs(raw: unknown): SpaceSwitcherPrefs
```

**Parameters**

- `raw` (`unknown`): The stored value.

**Returns** `SpaceSwitcherPrefs`

Source: [ui/src/chat/headless/sidebar/view.ts:128](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L128)

### `partitionMainSession`

Function.

Orchestration on: the main session is pulled out (pinned above the list).
Off: the main is not a chat; it is hidden, not regrouped.

```ts
function partitionMainSession<S extends SidebarListSession>(
  sessions: readonly S[],
  orchestrationEnabled: boolean,
): { main: S | null; rest: S[] }
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `sessions` (`readonly S[]`): The listed sessions.
- `orchestrationEnabled` (`boolean`): Orchestration is on.

**Returns** `{ main: S | null; rest: S[] }`

Source: [ui/src/chat/headless/sidebar/rows.ts:80](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L80)

### `pickRunEstimate`

Function.

The estimate a row shows: the session's own run (`depth` 0), or the
subagent named `label` (`child-3`). `undefined` when there is none.

```ts
function pickRunEstimate(
  estimates: readonly RunEstimateView[],
  label?: string,
): RunEstimateView | undefined
```

**Parameters**

- `estimates` (`readonly RunEstimateView[]`): The session's estimates (`RunEstimatesStore.get`).
- `label?` (`string`): A subagent's label; absent for the session's own run.

**Returns** `RunEstimateView | undefined`

Source: [ui/src/chat/headless/sidebar/estimates.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/estimates.ts#L51)

### `pinnedSessions`

Function.

The sessions pinned now (each once, however many pins).

```ts
function pinnedSessions(): Iterable<string>
```

**Returns** `Iterable<string>`

Source: [ui/src/chat/headless/sidebar/pinned-sessions.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-sessions.ts#L25)

### `pinSession`

Function.

Keep `key`'s transcript cached until the returned unpin runs.

```ts
function pinSession(key: string): () => void
```

**Parameters**

- `key` (`string`): The session to keep.

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

Source: [ui/src/chat/headless/sidebar/pinned-sessions.ts:12](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-sessions.ts#L12)

### `planAuthCard`

Function.

Plans the card of a failed sign-in: the provider's label, the stored
credential that failed (by its id, else its account name, else the one in
use when the failure names none), another OAuth account to switch to, and
the Settings target.

```ts
function planAuthCard(
  auth: AuthFailure,
  providers?: readonly SettingsProvider[],
): AuthCardPlan
```

**Parameters**

- `auth` (`AuthFailure`): The failed sign-in.
- `providers?` (`readonly SettingsProvider[]`): The providers of the host that holds the credentials; absent while unknown.

**Returns** `AuthCardPlan`

Source: [ui/src/chat/headless/transcript/auth-failure.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L51)

### `positionSuffix`

Function.

How a chip writes its position after the name: `:12`, `:12:5`, `:12-20`. Empty without one.

```ts
function positionSuffix(at: PathPosition | undefined): string
```

**Parameters**

- `at` (`PathPosition | undefined`): The chip's position.

**Returns** `string`

Source: [ui/src/chat/headless/file-chip.ts:117](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L117)

### `projectKeyOf`

Function.

The project filter's key for a session: its folder's name, as a query's
`projectName` reads it (`projectNameOf`: `/` and \`\` both separate), so a
view saved from the filter matches the same sessions.

```ts
function projectKeyOf(session: Pick<SidebarListSession, 'projectRoot' | 'cwd'>): string
```

**Parameters**

- `session` (`Pick<SidebarListSession, 'projectRoot' | 'cwd'>`): Its folder and project root.

**Returns** `string`

Source: [ui/src/chat/headless/sidebar/directory.ts:980](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L980)

### `projectPathOf`

Function.

The project a session is listed under: its repository's root, else its folder (`''`: none).

```ts
function projectPathOf(session: Pick<SidebarListSession, 'projectRoot' | 'cwd'>): string
```

**Parameters**

- `session` (`Pick<SidebarListSession, 'projectRoot' | 'cwd'>`): Its folder and project root.

**Returns** `string`

Source: [ui/src/chat/headless/sidebar/rows.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L26)

### `promptAttachments`

Function.

Staged attachments as the wire's: the `data:<mime>;base64,` prefix
stripped. One that is not a base64 data URL is dropped: the model still
gets the text.

```ts
function promptAttachments(
  attachments: readonly SendAttachment[],
): SendPromptAttachment[]
```

**Parameters**

- `attachments` (`readonly SendAttachment[]`): The staged attachments.

**Returns** `SendPromptAttachment[]`

Source: [ui/src/chat/headless/send-flow.ts:82](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L82)

### `promptDraftOf`

Function.

The prompt of a turn: a turn with several text blocks shows several prompts
(joined back with a blank line); their attachments ride along.

```ts
function promptDraftOf(
  events: readonly ChatEvent[],
  turnId: string,
  fallbackText?: string,
): TurnPromptDraft
```

**Parameters**

- `events` (`readonly ChatEvent[]`): The session's transcript events.
- `turnId` (`string`): The turn.
- `fallbackText?` (`string`, default `''`): The text when the transcript holds no prompt of it.

**Returns** `TurnPromptDraft`

Source: [ui/src/chat/headless/turn-prompt.ts:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/turn-prompt.ts#L23)

### `promptRefs`

Function.

The prompt's chips, for its echo: `/<skill>` tokens naming an activated
skill, `@<path>` mentions (zidane's `inferPromptRefs`, so every window
shows the same chips) and `#<chat>` tokens. Half-open spans, sorted.

```ts
function promptRefs(
  text: string,
  activatedSkills: readonly string[],
): PromptSegmentRef[]
```

**Parameters**

- `text` (`string`): The prompt.
- `activatedSkills` (`readonly string[]`): The skills picked through `/` completion.

**Returns** `PromptSegmentRef[]`

Source: [ui/src/chat/headless/send-flow.ts:52](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L52)

### `readSidebarViews`

Function.

The views the Storage holds: the per-space map, else the legacy per-axis keys as the default space's view.

```ts
function readSidebarViews(storage: SidebarViewsStorage | undefined): SidebarViewMap
```

**Parameters**

- `storage` (`SidebarViewsStorage | undefined`): Where the views persist; absent reads nothing.

**Returns** `SidebarViewMap`

Source: [ui/src/chat/headless/sidebar/view.ts:200](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L200)

### `recentHostFolders`

Function.

A saved server's recent folders (its sessions' folders there), most recent first, each once.

```ts
function recentHostFolders(
  sessions: readonly DraftFolderSource[],
  hostId: string,
  limit?: number,
): string[]
```

**Parameters**

- `sessions` (`readonly DraftFolderSource[]`): The session rows, most recently updated first.
- `hostId` (`string`): The server.
- `limit?` (`number`, default `5`): How many to keep.

**Returns** `string[]`

Source: [ui/src/chat/headless/draft-target.ts:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-target.ts#L40)

### `recentLocalFolders`

Function.

This computer's recent folders, most recent first (the rows' order), each once.

```ts
function recentLocalFolders(
  sessions: readonly DraftFolderSource[],
  limit?: number,
): string[]
```

**Parameters**

- `sessions` (`readonly DraftFolderSource[]`): The session rows, most recently updated first.
- `limit?` (`number`, default `5`): How many to keep.

**Returns** `string[]`

Source: [ui/src/chat/headless/draft-target.ts:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-target.ts#L21)

### `reduceActivity`

Function.

The next activity after `signal`; the same object when nothing a row shows changed, `null` once the run ended.

```ts
function reduceActivity(
  prev: SessionActivity | null,
  signal: SessionActivitySignal,
): SessionActivity | null
```

**Parameters**

- `prev` (`SessionActivity | null`): The activity so far, `null` for none.
- `signal` (`SessionActivitySignal`): The stream signal that arrived.

**Returns** `SessionActivity | null`

Source: [ui/src/chat/headless/sidebar/activity.ts:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/activity.ts#L68)

### `reduceCompaction`

Function.

The progress after `signal`: `null` once the compaction ended, `prev` for any other signal.

```ts
function reduceCompaction(
  prev: CompactionProgress | null,
  signal: { kind: string },
  now: number,
): CompactionProgress | null
```

**Parameters**

- `prev` (`CompactionProgress | null`): The progress so far, `null` for none.
- `signal` (`{ kind: string }`): The stream signal that arrived.
- `now` (`number`): The clock (ms), for the start.

**Returns** `CompactionProgress | null`

Source: [ui/src/chat/headless/sidebar/compaction.ts:30](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/compaction.ts#L30)

### `refusedSpawn`

Function.

A spawn the cap refused, as older recordings carry it: plain result text, not a failed call.

```ts
function refusedSpawn(
  tool: Pick<Extract<Row, { kind: 'tool' }>, 'name' | 'result'>,
): boolean
```

**Parameters**

- `tool` (`Pick<Extract<Row, { kind: 'tool' }>, 'name' | 'result'>`): The tool row: its `name` and `result`.

**Returns** `boolean`

Source: [ui/src/chat/headless/transcript/collapse.ts:396](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/collapse.ts#L396)

### `relativeTime`

Function.

How long ago, as short as it can say it: `now`, `5m`, `3h`, `2d`, `Mar 4`, `Mar 2024`.
Only a duration reads with "ago" in a sentence (core `ageStep` says which).

```ts
function relativeTime(
  at: number,
  now: number,
  labels?: Pick<ChatLabels, 'justNow' | 'months'>,
  calendar?: CalendarOptions,
): string
```

**Parameters**

- `at` (`number`): Epoch milliseconds of the event.
- `now` (`number`): Epoch milliseconds of the current time.
- `labels?` (`Pick<ChatLabels, 'justNow' | 'months'>`, default `DEFAULT_CHAT_LABELS`): Strings for `justNow` and the month names. Defaults to the default chat labels.
- `calendar?` (`CalendarOptions`): Pins the zone and locale the dates are read in.

**Returns** `string`

Source: [ui/src/chat/headless/session-list.ts:216](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L216)

### `rememberableChain`

Function.

The chain to remember, `null` for nothing (no primary, or a primary only the server runs).

```ts
function rememberableChain(
  chain: readonly ModelPickRef[],
  scope: { localProviders: ReadonlySet<string>; onServer: boolean },
): ModelPickRef[] | null
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The picked chain.
- `scope` (`{ localProviders: ReadonlySet<string>; onServer: boolean }`): Whether it was picked on a server, and the providers this computer can run.

**Returns** `ModelPickRef[] | null`

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

### `rememberedDefaultModel`

Function.

The model remembered as the next new chat's, `null` when there is none.
The account comes as remembered: check the catalog still serves it.

```ts
function rememberedDefaultModel(
  prefs: ComposerPrefsState | null | undefined,
): ModelPickRef | null
```

**Parameters**

- `prefs` (`ComposerPrefsState | null | undefined`): The remembered picks.

**Returns** `ModelPickRef | null`

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

### `rememberedPick`

Function.

[`rememberableChain`](https://zidane.si/docs/reference/ui-chat-headless.md#rememberableChain) for a pick made on `hostId` (a server, or `null` for this computer).

```ts
function rememberedPick(
  chain: readonly ModelPickRef[],
  hostId: string | null | undefined,
  models: ComposerModels | undefined,
): Promise<ModelPickRef[] | null>
```

**Parameters**

- `chain` (`readonly ModelPickRef[]`): The picked chain.
- `hostId` (`string | null | undefined`): Where it was picked.
- `models` (`ComposerModels | undefined`): This computer's catalog, to tell which providers it runs.

**Returns** `Promise<ModelPickRef[] | null>`

Source: [ui/src/chat/headless/composer/remember-model-pick.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/remember-model-pick.ts#L66)

### `repoGroups`

Function.

The group each repository's sessions share across machines, by `repoKey`. A
repository with one local folder groups under that folder: its sessions on
servers join it. A repository only on servers groups under its first
server folder, in key order. A repository with several local folders (two
clones) is left out: each folder keeps its own group, and so does each
server folder.

```ts
function repoGroups(sessions: readonly SidebarListSession[]): Map<string, string>
```

**Parameters**

- `sessions` (`readonly SidebarListSession[]`): The listed sessions.

**Returns** `Map<string, string>`

Source: [ui/src/chat/headless/sidebar/rows.ts:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L140)

### `resetChipWorkForTests`

Function.

Test seam.

```ts
function resetChipWorkForTests(): void
```

Source: [ui/src/chat/headless/chip-settle.ts:50](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-settle.ts#L50)

### `resolveBadgePanel`

Function.

The panel an extension badge names, among the conversation's panels: the
extension's own (a bare id), a full `<extension>/<id>`, or a built-in.
`null` when it names none of them.

```ts
function resolveBadgePanel(
  panel: string | undefined,
  extension: string,
  panels: ReadonlySet<string>,
): string | null
```

**Parameters**

- `panel` (`string | undefined`): What the badge named.
- `extension` (`string`): The extension that set the badge.
- `panels` (`ReadonlySet<string>`): The conversation's panel ids.

**Returns** `string | null`

Source: [ui/src/chat/headless/composer/conversation-badges.ts:247](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/conversation-badges.ts#L247)

### `resolveChipPath`

Function.

Absolute path for opening: relative chips resolve against `cwd`.

```ts
function resolveChipPath(chip: FileChip, cwd: string | null): string | null
```

**Parameters**

- `chip` (`FileChip`): The chip.
- `cwd` (`string | null`): The session's folder (`null`: none).

**Returns** `string | null`

Source: [ui/src/chat/headless/file-chip.ts:193](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L193)

### `resolveGrouping`

Function.

The grouping that applies: a contributed one the user picked, else the space's own (unless the
user picked a built-in one, [`VIEW_CHOICE`](https://zidane.si/docs/reference/ui-chat-headless.md#VIEW_CHOICE)), else the view's `groupBy` ('agent' as a query grouping).

```ts
function resolveGrouping(
  view: SidebarView,
  space: SidebarSpace,
  groups: readonly ExtensionItem<'sidebar-group'>[],
): SidebarGrouping
```

**Parameters**

- `view` (`SidebarView`): The space's view.
- `space` (`SidebarSpace`): The space shown.
- `groups` (`readonly ExtensionItem<'sidebar-group'>[]`): Every contributed grouping.

**Returns** `SidebarGrouping`

Source: [ui/src/chat/headless/sidebar/query.ts:353](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L353)

### `resolveSort`

Function.

The sort that applies: a contributed one the user picked, else the space's own (unless the user
picked a built-in one, [`VIEW_CHOICE`](https://zidane.si/docs/reference/ui-chat-headless.md#VIEW_CHOICE)). `null`: the view's `sortBy`.

```ts
function resolveSort(
  view: SidebarView,
  space: SidebarSpace,
  sorts: readonly ExtensionItem<'sidebar-sort'>[],
): readonly SessionSort[] | null
```

**Parameters**

- `view` (`SidebarView`): The space's view.
- `space` (`SidebarSpace`): The space shown.
- `sorts` (`readonly ExtensionItem<'sidebar-sort'>[]`): Every contributed sort.

**Returns** `readonly SessionSort[] | null`

Source: [ui/src/chat/headless/sidebar/query.ts:376](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L376)

### `rowTurnIds`

Function.

Every turn a painted row stands for (batches and folds see through to their members).

```ts
function rowTurnIds(row: Row): string[]
```

**Parameters**

- `row` (`Row`): A painted transcript row.

**Returns** `string[]`

Source: [ui/src/chat/headless/transcript/select-stops.ts:32](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/select-stops.ts#L32)

### `runsInRemoteSandbox`

Function.

Whether the session runs in a sandbox on a provider's machines, deleted with the session.

```ts
function runsInRemoteSandbox(
  environment: SessionEnvironmentSummary | undefined,
): boolean
```

**Parameters**

- `environment` (`SessionEnvironmentSummary | undefined`): The session's environment, if any.

**Returns** `boolean`

Source: [ui/src/chat/headless/sidebar/environment.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/environment.ts#L19)

### `safeSurrogateSlice`

Function.

Slice `n` UTF-16 code units off the head of `text`, extending by one
if the cut would land between a high surrogate and its low surrogate
(core's `takeChars`).

Returns `[head, tail]`: caller decides what to do with each side.
`n <= 0` yields `['', text]`; `n >= text.length` yields `[text, '']`.

```ts
function safeSurrogateSlice(text: string, n: number): [string, string]
```

**Parameters**

- `text` (`string`): The text to cut.
- `n` (`number`): How many code units the head takes.

**Returns** `[string, string]`

Source: [ui/src/chat/headless/smooth-stream.ts:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/smooth-stream.ts#L42)

### `secretExpiryWords`

Function.

When a saved secret goes, in words.

```ts
function secretExpiryWords(left: SecretTimeLeft): string
```

**Parameters**

- `left` (`SecretTimeLeft`): The time it has left.

**Returns** `string`

Source: [ui/src/chat/headless/labels.ts:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/labels.ts#L34)

### `secretTimeLeft`

Function.

The time left until `expiresAt`, rounded to the unit a person reads: minutes under an hour, hours under two
days, then days.

```ts
function secretTimeLeft(expiresAt: number | null, now: number): SecretTimeLeft
```

**Parameters**

- `expiresAt` (`number | null`): Expiry in Unix ms, `null` when it stays until revoked.
- `now` (`number`): The current time, in Unix ms.

**Returns** `SecretTimeLeft`

Source: [ui/src/chat/headless/secrets.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/secrets.ts#L19)

### `secretTimeLeftIso`

Function.

[`secretTimeLeft`](https://zidane.si/docs/reference/ui-chat-headless.md#secretTimeLeft) for an ISO expiry, as a `SecretReference` carries it.

```ts
function secretTimeLeftIso(expiresAt: string | null, now: number): SecretTimeLeft
```

**Parameters**

- `expiresAt` (`string | null`): ISO expiry, `null` when it stays until revoked.
- `now` (`number`): The current time, in Unix ms.

**Returns** `SecretTimeLeft`

Source: [ui/src/chat/headless/secrets.ts:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/secrets.ts#L34)

### `selectEditEvents`

Function.

The events that carry a file edit, in order.

```ts
function selectEditEvents<E extends ChatEvent>(events: readonly E[]): E[]
```

**Type parameters**

- `E` (`extends ChatEvent`)

**Parameters**

- `events` (`readonly E[]`): A session's events.

**Returns** `E[]`

Source: [ui/src/chat/headless/streams/selectors.ts:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/selectors.ts#L53)

### `sendPrompt`

Function.

Sends one prompt from the composer. Rejects (the composer keeps the text)
when no provider is connected, `/side` is refused, or the session could not
be created; a refused send or enqueue shows its error in the transcript.

```ts
function sendPrompt(request: SendRequest, deps: SendFlowDeps): Promise<void>
```

**Parameters**

- `request` (`SendRequest`): The prompt and where it goes.
- `deps` (`SendFlowDeps`): The hosts and app state it goes through.

**Returns** `Promise<void>`

Source: [ui/src/chat/headless/send-flow.ts:298](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L298)

### `sessionForToken`

Function.

The chat a `#token` names: the one session whose id starts with it.

```ts
function sessionForToken<S extends { id: string }>(
  sessions: readonly S[],
  token: string,
): S | null
```

**Type parameters**

- `S` (`extends { id: string }`)

**Parameters**

- `sessions` (`readonly S[]`): The sessions a token can name.
- `token` (`string`): The chip's text (`#3f2a`).

**Returns** `S | null`

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

### `sessionRefsOf`

Function.

Each session's [`SessionRef`](https://zidane.si/docs/reference/ui-chat-headless.md#SessionRef), by id.

```ts
function sessionRefsOf(sessions: readonly SidebarListSession[]): Map<string, SessionRef>
```

**Parameters**

- `sessions` (`readonly SidebarListSession[]`): The listed sessions.

**Returns** `Map<string, SessionRef>`

Source: [ui/src/chat/headless/sidebar/directory.ts:1011](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L1011)

### `sessionView`

Function.

A `#chat` chip's card: the title, the project, the model and context gauge, prompts and turns, the age.

```ts
function sessionView(
  labels: ChipViewLabels,
  token: string,
  session: ChatSessionFacts | null,
  context: ChatContextFacts | null,
  now?: number,
): ExtensionReferenceView
```

**Parameters**

- `labels` (`ChipViewLabels`): The chat labels (the facts' names).
- `token` (`string`): The chip's text.
- `session` (`ChatSessionFacts | null`): The chat it names (`null`: none).
- `context` (`ChatContextFacts | null`): Its context gauge, once read.
- `now?` (`number`): The time ages are measured from.

**Returns** `ExtensionReferenceView`

Source: [ui/src/chat/headless/chip-views.ts:107](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L107)

### `settledResource`

Function.

The first settled value of a resource (subscribing starts its read).

```ts
function settledResource<T>(resource: Readable<ResourceSnapshot<T>>): Promise<T>
```

**Type parameters**

- `T`

**Parameters**

- `resource` (`Readable<ResourceSnapshot<T>>`): The resource.

**Returns** `Promise<T>`

Source: [ui/src/chat/headless/composer/remember-model-pick.ts:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/remember-model-pick.ts#L37)

### `shellCommandOf`

Function.

The command of a `!` prompt (the TUI's `parseBashInvocation`), `''` for
any other prompt or a blank command.

```ts
function shellCommandOf(text: string): string
```

**Parameters**

- `text` (`string`): The prompt.

**Returns** `string`

Source: [ui/src/chat/headless/send-flow.ts:121](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L121)

### `shortUrl`

Function.

`https://www.github.com/a/b/` → `github.com/a/b`, ellipsized past `max` characters.

```ts
function shortUrl(url: string, max?: number): string
```

**Parameters**

- `url` (`string`): The address.
- `max?` (`number`, default `40`): The longest result, in characters.

**Returns** `string`

Source: [ui/src/chat/headless/badge-refs.ts:70](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/badge-refs.ts#L70)

### `sidebarContributionsOf`

Function.

The six sidebar token stores of an extensions host as one store: a new snapshot whenever one of them changes.

```ts
function sidebarContributionsOf(
  items: SidebarContributionStores,
): Readable<SidebarContributions>
```

**Parameters**

- `items` (`SidebarContributionStores`): The host's item stores (`ExtensionsHost.items`).

**Returns** `Readable<SidebarContributions>`

Source: [ui/src/chat/headless/sidebar/query.ts:109](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L109)

### `siteOrigin`

Function.

The `http(s)` origin a link's icon belongs to, or `null` when it has none.

```ts
function siteOrigin(url: string): string | null
```

**Parameters**

- `url` (`string`): The link's address.

**Returns** `string | null`

Source: [ui/src/chat/headless/site-icons.ts:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/site-icons.ts#L14)

### `skillName`

Function.

A skill's name in its chip text (`/review`, `$review`, `review`).

```ts
function skillName(text: string): string
```

**Parameters**

- `text` (`string`): The chip's text.

**Returns** `string`

Source: [ui/src/chat/headless/chip-views.ts:154](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L154)

### `skillView`

Function.

A skill chip's card: the description and the size in tokens.

```ts
function skillView(
  labels: ChipViewLabels,
  text: string,
  skill: ChatSkillFacts | null,
): ExtensionReferenceView
```

**Parameters**

- `labels` (`ChipViewLabels`): The chat labels (the facts' names).
- `text` (`string`): The chip's text.
- `skill` (`ChatSkillFacts | null`): The skill it names (`null`: none).

**Returns** `ExtensionReferenceView`

Source: [ui/src/chat/headless/chip-views.ts:166](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L166)

### `spaceMembership`

Function.

Which sessions a space lists, or `null` while spaces are off (every session). A session tagged
with the space is in it (an unknown tag reads as the default space); a space with a query also
lists the sessions it matches. The orchestration Main is in every space.

```ts
function spaceMembership<S extends SidebarListSession>(
  space: SidebarSpace,
  spaces: readonly Space[],
  spacesOn: boolean,
  now?: number,
): ((row: S) => boolean) | null
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `space` (`SidebarSpace`): The space shown.
- `spaces` (`readonly Space[]`): Every space.
- `spacesOn` (`boolean`): Spaces are on.
- `now?` (`number`): Clock for relative times in the query.

**Returns** `((row: S) => boolean) | null`

Source: [ui/src/chat/headless/sidebar/query.ts:258](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L258)

### `splitMarkdown`

Function.

Splits markdown into chunks that parse on their own, so a long or streaming reply can re-render only its last chunk. Text shorter than the threshold comes back as one chunk.

```ts
function splitMarkdown(text: string, opts?: { streaming?: boolean }): string[]
```

**Parameters**

- `text` (`string`): The markdown to split.
- `opts?` (`{ streaming?: boolean }`, default `{}`): Split options. `streaming: true` uses finer chunks for a reply that is still growing.

**Returns** `string[]`

Source: [ui/src/chat/headless/markdown-chunks.ts:104](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/markdown-chunks.ts#L104)

### `stableSelection`

Function.

A selection that keeps returning the previous list while the new one holds
the same items in the same order, so a reader re-renders only when an item
changes.

```ts
function stableSelection<E, T>(
  select: (events: readonly E[]) => readonly T[],
): (events: readonly E[]) => readonly T[]
```

**Type parameters**

- `E`
- `T`

**Parameters**

- `select` (`(events: readonly E[]) => readonly T[]`): Picks the items from the events.

**Returns** `(events: readonly E[]) => readonly T[]`

Source: [ui/src/chat/headless/streams/selectors.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/selectors.ts#L66)

### `stopForRow`

Function.

The stop a painted row belongs to, or `null` for rows that are not selectable.

```ts
function stopForRow(row: Row, stops: SelectStops): string | null
```

**Parameters**

- `row` (`Row`): A painted transcript row.
- `stops` (`SelectStops`): The stops from [`computeSelectStops`](https://zidane.si/docs/reference/ui-chat-headless.md#computeSelectStops).

**Returns** `string | null`

Source: [ui/src/chat/headless/transcript/select-stops.ts:145](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/select-stops.ts#L145)

### `switcherSpaces`

Function.

The switcher's spaces: the user's order first (ids it names), the rest in their own order, the
hidden ones left out. The default space never hides, so the switcher always has one.

```ts
function switcherSpaces<T extends SidebarSpace>(
  spaces: readonly T[],
  prefs: SpaceSwitcherPrefs,
): T[]
```

**Type parameters**

- `T` (`extends SidebarSpace`)

**Parameters**

- `spaces` (`readonly T[]`): Every space.
- `prefs` (`SpaceSwitcherPrefs`): The switcher's order and hidden spaces.

**Returns** `T[]`

Source: [ui/src/chat/headless/sidebar/query.ts:230](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L230)

### `tickBucket`

Function.

Compute how many chars to emit from `bucket` on this tick, at the pace
its backlog sets. Mutates `bucket.carry` so caller can repeatedly tick
without re-seeding. An empty bucket yields 0.

```ts
function tickBucket(bucket: DeltaBucket, dtMs: number): number
```

**Parameters**

- `bucket` (`DeltaBucket`): The bucket to tick.
- `dtMs` (`number`): Milliseconds since its last tick.

**Returns** `number`

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

### `toolAction`

Function.

The overview item for one tool call: the shared words, plus what the details show.

```ts
function toolAction(
  tool: Owned & { approval?: ModelApproval; callId?: string; children?: readonly Owned & { kind: "tool"; id: string; name: string; displayName: string; formatted: ToolFormatLine | null; rawInput?: Record<string, unknown> | undefined; edit?: EditPayload | undefined; ... 11 more ...; children?: readonly (Owned & ...)[] | undefined; }[]; displayName: string; durationMs?: number; edit?: EditPayload; formatted: ToolFormatLine | null; id: string; kind: 'tool'; name: string; ok: boolean | null; parentId?: string; rawInput?: Record<string, unknown>; result: string | null; resultClipped?: boolean; resuming?: true; scriptProgress?: ScriptProgress; startedAt?: number; waitingFor?: { active: number; max: number } },
): FoldActionItem
```

**Parameters**

- `tool` (`Owned & { approval?: ModelApproval; callId?: string; children?: readonly Owned & { kind: "tool"; id: string; name: string; displayName: string; formatted: ToolFormatLine | null; rawInput?: Record<string, unknown> | undefined; edit?: EditPayload | undefined; ... 11 more ...; children?: readonly (Owned & ...)[] | undefined; }[]; displayName: string; durationMs?: number; edit?: EditPayload; formatted: ToolFormatLine | null; id: string; kind: 'tool'; name: string; ok: boolean | null; parentId?: string; rawInput?: Record<string, unknown>; result: string | null; resultClipped?: boolean; resuming?: true; scriptProgress?: ScriptProgress; startedAt?: number; waitingFor?: { active: number; max: number } }`): The tool call's row.

**Returns** `FoldActionItem`

Source: [ui/src/chat/headless/transcript/fold-actions.ts:80](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold-actions.ts#L80)

### `toolFailed`

Function.

A tool call that failed: its result says so, or it is a spawn the cap
refused in plain text (older recordings do not mark that as failed).

```ts
function toolFailed(
  tool: Pick<Extract<Row, { kind: 'tool' }>, 'name' | 'ok' | 'result'>,
): boolean
```

**Parameters**

- `tool` (`Pick<Extract<Row, { kind: 'tool' }>, 'name' | 'ok' | 'result'>`): The tool row: its `name`, `ok`, and `result`.

**Returns** `boolean`

Source: [ui/src/chat/headless/transcript/collapse.ts:387](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/collapse.ts#L387)

### `unsentDraft`

Function.

A submit that was not sent (its chat could not be created) back as the
draft it came from: the box is cleared on Enter, so a failure must not
lose what was typed. The inverse of [`composeSubmitText`](https://zidane.si/docs/reference/ui-chat-headless.md#composeSubmitText).

```ts
function unsentDraft(submitted: string): { shell: boolean; text: string }
```

**Parameters**

- `submitted` (`string`): The text the composer submitted (a `!` command keeps its sentinel).

**Returns** `{ shell: boolean; text: string }`

Source: [ui/src/chat/headless/composer-modes.ts:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer-modes.ts#L140)

### `urlRefs`

Function.

The links in a text, as prompt spans (`urls`): where each starts and ends.

```ts
function urlRefs(text: string): PromptSegmentRef[]
```

**Parameters**

- `text` (`string`): The text to scan.

**Returns** `PromptSegmentRef[]`

Source: [ui/src/chat/headless/badge-refs.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/badge-refs.ts#L26)

### `useReadable`

Function.

Subscribes a component to a [`Readable`](https://zidane.si/docs/reference/ui-chat-headless.md#Readable) and returns its current value, re-rendering when it changes.

```ts
function useReadable<T>(store: Readable<T>): T
```

**Type parameters**

- `T`

**Parameters**

- `store` (`Readable<T>`): The store to read.

**Returns** `T`

Source: [ui/src/chat/headless/store.ts:60](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/store.ts#L60)

### `viewFilterOf`

Function.

The view layer's own narrowing: the agent, the origin and the contributed filters the space offers. `null`
when none applies.

```ts
function viewFilterOf<S extends SidebarListSession>(
  view: SidebarView,
  filters: readonly ExtensionItem<'sidebar-filter'>[],
  now?: number,
): ((row: S) => boolean) | null
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Parameters**

- `view` (`SidebarView`): The space's view.
- `filters` (`readonly ExtensionItem<'sidebar-filter'>[]`): The filters the space offers ([`filtersForSpace`](https://zidane.si/docs/reference/ui-chat-headless.md#filtersForSpace)).
- `now?` (`number`): Clock for relative times.

**Returns** `((row: S) => boolean) | null`

Source: [ui/src/chat/headless/sidebar/query.ts:315](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L315)

### `viewFiltersOn`

Function.

Whether the view narrows the space's sessions: an archive axis other than `active`, a project,
an activity window, an agent, an origin, or a contributed filter the space offers turned on. Grouping and
sort don't count.

```ts
function viewFiltersOn(
  view: SidebarView,
  filters: readonly ExtensionItem<'sidebar-filter'>[],
): boolean
```

**Parameters**

- `view` (`SidebarView`): The space's view.
- `filters` (`readonly ExtensionItem<'sidebar-filter'>[]`): The filters the space offers ([`filtersForSpace`](https://zidane.si/docs/reference/ui-chat-headless.md#filtersForSpace)); a value kept for another one doesn't count.

**Returns** `boolean`

Source: [ui/src/chat/headless/sidebar/query.ts:589](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L589)

### `whenChipsSettle`

Function.

Resolves once no lookup is in flight, or after `timeoutMs`, whichever is first.

```ts
function whenChipsSettle(timeoutMs: number): Promise<void>
```

**Parameters**

- `timeoutMs` (`number`): How long to wait at most.

**Returns** `Promise<void>`

Source: [ui/src/chat/headless/chip-settle.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-settle.ts#L36)

### `wireAttachmentsToChat`

Function.

A sent prompt's attachments → staged `ChatAttachment`s, for a draft that
re-stages them (Edit message). Data URLs stage as they are; a `zg-media:`
address (a PDF or text file served from the saved turn) is fetched and
re-encoded under the attachment's own media type, since the send path only
reads data URLs. Metadata-only chips (no address) and failed fetches drop.

```ts
function wireAttachmentsToChat(
  attachments: readonly ChatAttachment[],
  fetchImpl?: (url: string) => Promise<Response>,
): Promise<ComposerAttachment[]>
```

**Parameters**

- `attachments` (`readonly ChatAttachment[]`): The sent prompt's attachments.
- `fetchImpl?` (`(url: string) => Promise<Response>`): How a `zg-media:` address is read (default: `fetch`).

**Returns** `Promise<ComposerAttachment[]>`

Source: [ui/src/chat/headless/composer/draft-sync.ts:170](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/draft-sync.ts#L170)

### `wireOriginal`

Function.

A converted attachment's original as the wire carries it, or `undefined`
when there is none (or its URL is not a base64 data URL).

```ts
function wireOriginal(
  original: ChatAttachmentOriginal | undefined,
): { data: string; mediaType: string; name: string } | undefined
```

**Parameters**

- `original` (`ChatAttachmentOriginal | undefined`): The staged attachment's `original`.

**Returns** `{ data: string; mediaType: string; name: string } | undefined`

Source: [ui/src/chat/headless/send-flow.ts:99](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L99)

### `withoutPartialFence`

Function.

Holds back a fence still arriving at the end of a streaming reply. Text
reveals a few characters a frame, so a closing ` ``` ` lands as `` ` ``,
then ` `` `: until the third, an open code block shows the partial
marker as one more line of code, then drops it, and the reply shrinks by
a line under a view following its bottom. A frame later the whole fence
is there.

```ts
function withoutPartialFence(text: string): string
```

**Parameters**

- `text` (`string`): The reply so far.

**Returns** `string`

Source: [ui/src/chat/headless/markdown-chunks.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/markdown-chunks.ts#L51)

### `withPinnedProject`

Function.

`pins` with `fullPath` pinned or unpinned in `spaceId`; the same object when nothing changes.

```ts
function withPinnedProject(
  pins: PinsBySpace,
  spaceId: string,
  fullPath: string,
  pin: boolean,
): PinsBySpace
```

**Parameters**

- `pins` (`PinsBySpace`): The current pins.
- `spaceId` (`string`): The space the change is in.
- `fullPath` (`string`): The project folder.
- `pin` (`boolean`): Pin (true) or unpin (false).

**Returns** `PinsBySpace`

Source: [ui/src/chat/headless/sidebar/pinned-projects.ts:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-projects.ts#L43)

### `writable`

Function.

A plain value store: the building block for simple hosts and fixtures.

```ts
function writable<T>(initial: T): Writable<T>
```

**Type parameters**

- `T`

**Parameters**

- `initial` (`T`): The starting value.

**Returns** `Writable<T>`

Source: [ui/src/chat/headless/store.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/store.ts#L28)

## Classes

### `SessionStreamStore`

Class.

External store backing all per-session reads. Mutates the underlying
Maps in place and notifies only the per-`sessionId` listeners that
actually subscribed to the changed session — that's what isolates
sibling sessions from each other's stream churn. Every write path
replaces the session's events array, so identity says whether anything
landed in between (the run-end compaction and scrollback guards rely on
it).

The reducer alone: [`createSessionStreams`](https://zidane.si/docs/reference/ui-chat-headless.md#createSessionStreams) adds smooth-stream pacing,
lazy scrollback and run-end compaction around it.

```ts
class SessionStreamStore<K extends string = string>
```

**Constructor**

```ts
new SessionStreamStore<K extends string = string>(options?: SessionStreamStoreOptions)
```

**Type parameters**

- `K` (`extends string`, default `string`): The session key type (the desktop app's branded `SessionKey`). Default: `string`.

**Parameters**

- `options?` (`SessionStreamStoreOptions`, default `{}`): The scheduler for batched notifications, the markdown merge rule and whether to batch.

**Returns** `SessionStreamStore<K>`

**Type parameters**

- `K` (`extends string`, default `string`): The session key type (the desktop app's branded `SessionKey`). Default: `string`.

**Properties**

- `runStateVersion` (`number`, default `0`): Bumped by every run-state change (`run:start`, `run:end`, `dropAll`): a snapshot fetched before a bump is stale.

**Methods**

#### `appendErrorEvent()`

```ts
appendErrorEvent(sessionId: K, text: string): void
```

Appends a display-only error row (a send that failed before any run).

**Parameters**

- `sessionId` (`K`): The session.
- `text` (`string`): The error message.

#### `appendUserPrompt()`

```ts
appendUserPrompt(
  sessionId: K,
  text: string,
  refs?: readonly PromptSegmentRef[],
  rawAttachments?: readonly ChatAttachment[],
): void
```

Shows the user's prompt at once (optimistic append) and waits for its host echo, which is then dropped.

**Parameters**

- `sessionId` (`K`): The session.
- `text` (`string`): The prompt text.
- `refs?` (`readonly PromptSegmentRef[]`): The completions the prompt used (skills, files), for its chips.
- `rawAttachments?` (`readonly ChatAttachment[]`): The prompt's attachments. Omitted for a pushed queued prompt, which takes the previews this client remembered for it.

#### `applyDrainPlan()`

```ts
applyDrainPlan(plan: readonly DrainPlan<K>[]): void
```

Apply a batch of synthesized smooth-stream deltas in one shot.
Coalesces per-session work so a tick that touches sessions A and B
fires exactly one notify per session — not one per delta.

**Parameters**

- `plan` (`readonly DrainPlan<K>[]`): The text released from the smooth-stream buckets.

#### `applySignal()`

```ts
applySignal(input: OtherStreamSignal | SessionStreamSignal<K>): void
```

Reduces one live signal into its session (see [`SessionStreamSignal`](https://zidane.si/docs/reference/ui-chat-headless.md#SessionStreamSignal)). Signals of other kinds are ignored.

**Parameters**

- `input` (`OtherStreamSignal | SessionStreamSignal<K>`): The signal.

#### `drop()`

```ts
drop(sessionId: K): void
```

Drop a session entirely — called by `SessionsContext.deleteSession`
so a removed row's stored events don't leak past the IPC delete.

**Parameters**

- `sessionId` (`K`): The session.

#### `dropAll()`

```ts
dropAll(): void
```

Drop EVERY session's transient state — used when the execution runtime
changes underneath the window (`useDaemon` toggled: the authority for
every transcript, run flag and per-run chip just moved to another
process, or back). Unlike `evictExcept`, running sessions are NOT spared:
a `running` flag from the previous runtime is exactly the kind of stale
truth this exists to discard. Sessions re-hydrate through the ordinary
cold path on next view, and the new runtime's `run:start`/`run:end`
re-establish the flags.

#### `dropPendingEcho()`

```ts
dropPendingEcho(sessionId: K, text: string): void
```

Unwind ONE pending echo after a FAILED send — a refused/errored send
produces no run, so the `run:end` sweep never fires and the stale
entry would silently swallow an identical remote prompt later.

**Parameters**

- `sessionId` (`K`): The session.
- `text` (`string`): The prompt text.

#### `dropPromptPreviews()`

```ts
dropPromptPreviews(sessionId: K, text: string): void
```

Unwind the latest `rememberPromptPreviews` entry for `text` after a failed enqueue.

**Parameters**

- `sessionId` (`K`): The session.
- `text` (`string`): The queued prompt's text.

#### `evictExcept()`

```ts
evictExcept(keep: ReadonlySet<K>): void
```

Evict every hydrated window whose session id is not in `keep` — the
memory bound for a long-lived window. Prewarm slides a window of
likely-next sessions into the cache, and this slides old entries
OUT, so a long browsing session does not accumulate one tail page per
session ever visited. Revisiting an evicted session re-hydrates through the
exact same `hydrated()` → `loadEvents` path a cold session uses.

Never evicts:

- running sessions (live deltas exist only in this store — dropping
  them would blank an in-flight background run's transcript);
- sessions with a scrollback fetch in flight (`loadingEarlier` —
  the prepend landing after eviction would resurrect a window
  containing ONLY the old page).

**Parameters**

- `keep` (`ReadonlySet<K>`): The sessions to keep.

#### `flushNotifications()`

```ts
flushNotifications(): void
```

Deliver notifications `_notifySoon` held back (also called before anything that must be immediate).

#### `getEventsSnapshot()`

```ts
getEventsSnapshot(sessionId: K | null): readonly ChatEvent[]
```

A session's events: the stored array itself (stable identity until a write), or a shared empty array.

**Parameters**

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

**Returns** `readonly ChatEvent[]`

#### `getFallbackSnapshot()`

```ts
getFallbackSnapshot(sessionId: K | null): SessionFallbackModel | null
```

Stable-reference snapshot (the stored object itself) — safe for
`useSyncExternalStore`, which compares snapshots by identity.

**Parameters**

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

**Returns** `SessionFallbackModel | null`

#### `getPageSnapshot()`

```ts
getPageSnapshot(sessionId: K | null): SessionPageState
```

The session's scrollback bookkeeping (a shared empty state when it was never hydrated). Stable identity until a page write.

**Parameters**

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

**Returns** `SessionPageState`

#### `getRetrySnapshot()`

```ts
getRetrySnapshot(sessionId: K | null): SessionRetryState | null
```

Stable-reference snapshot of in-flight provider-retry state.

**Parameters**

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

**Returns** `SessionRetryState | null`

#### `getRunningSnapshot()`

```ts
getRunningSnapshot(sessionId: K | null): boolean
```

Whether a run is in flight for the session.

**Parameters**

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

**Returns** `boolean`

#### `getRunSeqSnapshot()`

```ts
getRunSeqSnapshot(sessionId: K | null): number
```

How many runs this client saw start for the session (0 for none). Read non-reactively: a snapshot fetched before a run started is stale.

**Parameters**

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

**Returns** `number`

#### `getSystemMdSnapshot()`

```ts
getSystemMdSnapshot(sessionId: K | null): SystemMdFile | null
```

Stable-reference snapshot of the active `SYSTEM.md` override, for
`useSyncExternalStore` (compared by identity, and the stored object is the
one the signal delivered).

**Parameters**

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

**Returns** `SystemMdFile | null`

#### `hasEvents()`

```ts
hasEvents(sessionId: K | null): boolean
```

Whether the store holds any record for the session (live-only windows included; see `isHydrated`).

**Parameters**

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

**Returns** `boolean`

#### `isHydrated()`

```ts
isHydrated(sessionId: K | null): boolean
```

Whether the session's window was hydrated from DISK (`setEventsPage`),
as opposed to merely having a record. `markRunning` and every live
signal seed `_events` for a session this window never loaded — a run
driven by the TUI or another window — and `hasEvents` alone read those
live-only windows as hydrated, so activation skipped `loadEvents` and
the transcript showed nothing but the deltas that had arrived so far,
with no page state to scroll back from.

**Parameters**

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

**Returns** `boolean`

#### `markRunning()`

```ts
markRunning(sessionId: K): void
```

Seed "running" from the store row for a run this window never saw
start — a session driven by the daemon or another client, opened
mid-run. Only ever sets TRUE: clearing belongs to `run:end` (or a
runtime drop), since a list fetched just before a local run:start
would otherwise flip a genuinely live session back to idle.

**Parameters**

- `sessionId` (`K`): The session.

#### `pendingEchoes()`

```ts
pendingEchoes(sessionId: K): string[]
```

The prompt texts this client appended that still await their host echo
(see `appendUserPrompt`). The live list: an adapter that keeps its own
echo rule (`createLiveState`) edits it in place.

**Parameters**

- `sessionId` (`K`): The session.

**Returns** `string[]`

#### `prependEventsPage()`

```ts
prependEventsPage(sessionId: K, page: SessionStreamPage): void
```

Splice an OLDER page in front of the hydrated window (lazy scrollback).

**Parameters**

- `sessionId` (`K`): The session.
- `page` (`SessionStreamPage`): The persisted page.

#### `rememberPromptPreviews()`

```ts
rememberPromptPreviews(
  sessionId: K,
  text: string,
  attachments: readonly ChatAttachment[],
): void
```

Remember the image previews of a prompt this window queued, so the copy
that reaches the transcript later (host drain / push) keeps thumbnails.
Bounded: a queue that never drains can't grow this without limit.

**Parameters**

- `sessionId` (`K`): The session.
- `text` (`string`): The queued prompt's text.
- `attachments` (`readonly ChatAttachment[]`): The prompt's attachments.

#### `renamePromptPreviews()`

```ts
renamePromptPreviews(sessionId: K, from: string, to: string): void
```

Follow a queued entry's text edit so its previews still match when it's sent.

**Parameters**

- `sessionId` (`K`): The session.
- `from` (`string`): The queued prompt's text before the edit.
- `to` (`string`): Its text after the edit.

#### `reset()`

```ts
reset(sessionId: K): void
```

Empties a session's window and run state, and drops its hydration so the next activation reloads from disk.

**Parameters**

- `sessionId` (`K`): The session.

#### `seedSystemMd()`

```ts
seedSystemMd(sessionId: K, file: SystemMdFile | null): void
```

Seed the override from the main-process PULL (`sessions.systemMd`).

The `system-md` signal only fires when an agent is BUILT, and agents are
cached — so opening the app onto a warm session, or switching back to one,
delivers no signal at all. Without this seed the badge is silent in the
most common flow rather than an edge case, which is the wrong direction
for a warning that the built-in doctrine has been replaced.

Skipped while a live signal already holds a value for the session: the
push is authoritative and may have landed while this fetch was in flight.

**Parameters**

- `sessionId` (`K`): The session.
- `file` (`SystemMdFile | null`): The override, or `null` for none.

#### `setEventsPage()`

```ts
setEventsPage(sessionId: K, page: SessionStreamPage): void
```

Hydrate one replay page as the session's full window — the
`loadEvents` (tail page) path. One notify covers both the events
swap and the page-state swap.

**Parameters**

- `sessionId` (`K`): The session.
- `page` (`SessionStreamPage`): The persisted page.

#### `setLoadingEarlier()`

```ts
setLoadingEarlier(sessionId: K, loading: boolean): void
```

Marks a fetch of the previous page in flight, or done.

**Parameters**

- `sessionId` (`K`): The session.
- `loading` (`boolean`): Whether a fetch is in flight.

#### `subscribeHas()`

```ts
subscribeHas(listener: () => void): () => void
```

Subscribe to "the set of known sessions changed" — used by
`useHasEvents` so we only re-render the consumer when its target
session flips between hydrated / not.

**Parameters**

- `listener` (`() => void`): Called after the state changes.

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

#### `subscribeSession()`

```ts
subscribeSession(sessionId: K | null, listener: () => void): () => void
```

Registers a listener for one session's changes. Returns the function that removes it.

**Parameters**

- `sessionId` (`K | null`): The session, or `null` for none.
- `listener` (`() => void`): Called after the state changes.

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

#### `write()`

```ts
write(sessionId: K, patch: SessionStreamWrite): void
```

Low-level write: sets any of a session's events, run flag and page state
in one notification, with none of the signal rules (no finalize, no
reconcile). For adapters that own their merge rules (`createLiveState`).
The store keeps `events` as given and never mutates it.

**Parameters**

- `sessionId` (`K`): The session.
- `patch` (`SessionStreamWrite`): The fields to set.

Source: [ui/src/chat/headless/streams/store.ts:98](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/store.ts#L98)

## Constants

### `AGENT_GROUPING`

Constant.

The agent grouping as a query grouping.

```ts
const AGENT_GROUPING: SessionGroupBy
```

Source: [ui/src/chat/headless/sidebar/query.ts:343](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L343)

### `CHATS_BUCKET`

Constant.

The directory-less bucket's label ("pure chat" sessions, no project).

```ts
const CHATS_BUCKET = 'Chats'
```

Source: [ui/src/chat/headless/sidebar/rows.ts:65](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L65)

### `CHUNK_THRESHOLD`

Constant.

Below this, one parse is cheap enough: no chunking at all.

```ts
const CHUNK_THRESHOLD = 6000
```

Source: [ui/src/chat/headless/markdown-chunks.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/markdown-chunks.ts#L20)

### `COMMON_EMOJI`

Constant.

Emoji grid — two dozen common project-marker choices. Ordered folders
first (nearest to the default), then general dev/project glyphs.

```ts
const COMMON_EMOJI: readonly ['📁', '📂', '🚀', '⚡', '🔥', '⭐', '🎨', '🧪', '🛠️', '🔧', '🐛', '🤖', '🧠', '💡', '📦', '🌐', '🖥️', '📚', '📝', '🎯', '🧩', '🔒', '💾', '🏗️']
```

Source: [ui/src/chat/headless/sidebar/project-icons.ts:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L21)

### `DEFAULT_CHAT_LABELS`

Constant.

The default English strings of the chat layer, merged over the design system's labels. Override any of them through `ChatProvider`.

```ts
const DEFAULT_CHAT_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 }
```

Source: [ui/src/chat/headless/labels.ts:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/labels.ts#L42)

### `DEFAULT_COMPOSER_CHROME_LABELS`

Constant.

The strings of the chrome around the editor (run chip, pickers, dock, badges). Merged into `DEFAULT_COMPOSER_LABELS`.

```ts
const DEFAULT_COMPOSER_CHROME_LABELS: { agentDialogDescription: string; agentDialogTitle: string; agentSwitching: string; archivedNotice: string; badgeFromPrevious: (title: string) => string; badgePlan: string; badgePlanTitle: (title: string) => string; badgeQuestions: (n: number) => string; badgeQuestionsTitle: (n: number) => string; badgeQueued: string; badgeQueuedTitle: (n: number) => string; badgeReminders: (when: string) => string; badgeRemindersTitle: (n: number, when: string) => string; badgeRunning: string; badgeRunningTitle: (names: readonly string[], more: number, total: number) => string; badgeTodos: string; badgeTodosCurrent: (content: string, progress: string) => string; badgeTodosProgress: (done: number, total: number) => string; badgeTodosStopped: (progress: string) => string; badgeWaiting: string; badgeWaitingTitle: string; breakdownError: (message: string) => string; effortDialogDescription: (title: string) => string; effortDialogFeatures: string; effortDialogReasoning: string; effortDialogTitle: string; modelDialogDescription: (title: string) => string; modelDialogTitle: string; modelOptionsTitle: string; modelPickDefault: string; modelSwitch: string; retryStallHint: (attempt: number, max: number) => string; runChipEstimatedHint: string; runChipHint: string; runChipRate: string; scopeBackToProjects: string; scopeChat: string; scopeChatHint: string; scopeChooseFolder: string; scopeCloneOffHint: (host: string) => string; scopeCloneOffTag: string; scopeCloneTag: string; scopeCloneThere: (path: string, host: string) => string; scopeCloneThereTag: string; scopeCloneWill: (name: string) => string; scopeCloneWillHint: (url: string, parent: string, host: string) => string; scopeCloning: (name: string) => string; scopeFolderHint: (folder: string) => string; scopeGroup: string; scopeImportRepo: string; scopeSelect: string; scopeSelectDirectory: string; scopeSelectHint: string; scopeServerChoose: (host: string) => string; scopeServerDefault: string; scopeServerDefaultHint: (host: string) => string; scopeServerFolderHint: (folder: string, host: string) => string; scopeServerGroup: (host: string) => string; sendCloneCancelled: string; sendCloneFailed: (url: string, message: string) => string; sendCreateFailed: (message: string) => string; sendUntitled: string; unarchive: string }
```

Source: [ui/src/chat/headless/composer/labels-chrome.ts:2](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/labels-chrome.ts#L2)

### `DEFAULT_COMPOSER_LABELS`

Constant.

The default English composer strings.

```ts
const DEFAULT_COMPOSER_LABELS: ComposerLabels
```

Source: [ui/src/chat/headless/composer/labels.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/labels.ts#L15)

### `DEFAULT_MODEL_PICKER_PREFS`

Constant.

The preferences before any change.

```ts
const DEFAULT_MODEL_PICKER_PREFS: ModelPickerPrefs
```

Source: [ui/src/chat/headless/composer/model-picker-prefs.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-picker-prefs.ts#L19)

### `DEFAULT_SIDEBAR_LABELS`

Constant.

The default English strings of the session sidebar, merged over the chat layer's.

```ts
const DEFAULT_SIDEBAR_LABELS: { activityCompacting: string; activityRetrying: string; activityThinking: string; activityWriting: string; addDiagnosticToChat: (message: string) => string; addFavorite: string; additionalInstructions: string; additionalInstructionsHint: string; additionalInstructionsPlaceholder: string; address: string; addressPlaceholder: string; addSpace: string; addToChat: string; agent: string; agentDraftNote: string; agentGroupDefault: string; agentProfiles: string; archive: string; archiveConfirmLabel: string; archived: string; archiveProjectMessage: (count: number) => 'It stays under Archived, where you can restore it.' | 'They stay under Archived, where you can restore them.'; archiveProjectTitle: (count: number, project: string) => 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; changeIconFor: (project: string) => string; changeMainIcon: string; changeProjectIcon: string; changeSpaceIcon: 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; chooseImage: string; chooseModel: string; chooseProjectIcon: string; chooseSpaceIcon: string; clearSearch: string; clickToAnswer: string; close: string; closeTab: (name: string) => string; code: string; collapseGroup: (label: string) => string; collapseItem: (title: string) => string; collapseSidebar: string; commandDetail: string; commandSuggestions: string; compactingTitle: 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; customEmoji: string; declineSecret: string; declineSecretHint: string; defaultAgent: string; defaultSpaceName: string; delete: string; deleteConfirmLabel: string; deleteProjectArchived: (archived: number) => string; deleteProjectCannotUndo: string; deleteProjectSandboxes: (sandboxed: number) => string; deleteProjectTitle: (count: number, project: string) => string; deleteSessionQuestion: (title: string) => string; deleteSessionSandbox: (kind: string) => string; deleteSpace: string; deleteSpaceMessage: (fallback: string) => string; deleteSpaceNamed: (name: string) => string; deleteSpaceQuestion: (name: string) => 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; emojiPlaceholder: string; environmentActionFailed: (action: string, message: string) => string; environmentKept: (reason?: string) => string; environmentKinds: Readonly<Record<string, string>>; environmentOnBranch: (kind: string, branch: string) => string; environmentOnMachine: (kind: string, machine: string) => string; environmentPaused: (where: string) => string; environmentSettingUp: (where: string) => string; environmentSetupFailed: (where: string, error?: string) => string; environmentsKept: (count: number) => 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; expandItem: (title: string) => string; expandSidebar: 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; footerSettings: string; footerSettingsWithNote: (note: string) => string; footerSignIn: string; footerSignInTitle: string; generatedImage: string; generatingImage: (model: string | null) => string; generatingImages: (count: number, model: string | null) => string; goToDefinition: string; goToStep: (step: string) => string; hiddenSpaces: string; hideSpace: 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; itemActions: (title: string) => string; itemOpenFailed: (message: string) => string; justNow: string; loadEarlierHistory: string; loadFullOutput: string; loading: string; loadingEarlierHistory: string; loadingEarlierMessages: string; loadingFullOutput: string; mainSession: string; mentionSuggestions: string; menuAddFavorite: string; menuArchive: string; menuArchiveProject: string; menuCopyPath: string; menuDelete: string; menuDeleteProject: string; menuMoveProjectToSpace: string; menuMoveTo: string; menuMoveToSpace: string; menuOpenChatWindow: string; menuOpenPanelsWindow: string; menuOpenWindow: string; menuRemoveFavorite: string; menuRename: string; menuRetryEnvironment: string; menuReveal: string; menuUnarchive: 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; moveProjectFailed: (message: string) => string; moveSessionFailed: (message: string) => string; moveSpaceDown: (name: string) => string; moveSpaceLeft: string; moveSpaceRight: string; moveSpaceUp: (name: string) => string; newSession: string; newSessionIn: (project: string) => string; newSessionTitle: string; newSpaceName: (n: number) => string; next: string; noAnswer: string; noChatsMatchFilters: string; noChatsYet: 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; pinNamed: (project: string) => string; pinProject: 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; queryGroupOther: 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; resetFilters: string; resetsAt: (time: string) => string; resetToFolder: string; resetToInitial: string; retry: string; retryEnvironmentFailed: (message: string) => string; retryHint: string; rowNeedsYou: string; rowRunning: string; rowScheduled: string; rowWorking: string; runningFor: (elapsed: string) => string; runReceipt: string; runRetrying: (attempt: number, max: number, source?: string) => string; runWaiting: string; savedViewName: (n: number) => string; saveSecurely: string; saveViewFailed: (message: string) => 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; searchingSessions: string; searchModels: string; searchModelsPlaceholder: string; searchSessions: string; searchSessionsLabel: 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; showHiddenSpace: (name: string) => string; showMore: string; showMoreAttachments: (count: number) => string; showOutput: string; showSystemPrompt: string; sidebarNoMatches: 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; spaceFromExtension: (extension: string) => string; spaceNamed: (name: string) => string; spaceNameOf: (name: string) => string; spaceOptions: (name: string) => string; spaces: string; spacesTitle: 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; unpinNamed: (project: string) => string; unpinProject: string; unsupportedInteraction: (tool: string) => string; usagePanelHint: string; usageWindow: (window: string, percent: string) => string; useSpaces: string; useSpacesDescription: 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; yourSpaces: string; zoomFit: string; zoomInDiagram: string; zoomOutDiagram: string; zoomPercent: (percent: number) => string }
```

Source: [ui/src/chat/headless/sidebar/labels.ts:9](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/labels.ts#L9)

### `DEFAULT_SIDEBAR_VIEW`

Constant.

A view nobody changed yet.

```ts
const DEFAULT_SIDEBAR_VIEW: SidebarView
```

Source: [ui/src/chat/headless/sidebar/view.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L25)

### `DEFAULT_SWITCHER_PREFS`

Constant.

No arrangement yet: the spaces' own order, nothing hidden.

```ts
const DEFAULT_SWITCHER_PREFS: SpaceSwitcherPrefs
```

Source: [ui/src/chat/headless/sidebar/view.ts:121](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L121)

### `defaultFrameScheduler`

Constant.

The browser's frames and timers, looked up on every call (so a test that
stubs `requestAnimationFrame` or fakes timers after the store exists is
still heard). Without `requestAnimationFrame` (a worker, Node) `frame`
returns `null` and the store paces on timers.

```ts
const defaultFrameScheduler: FrameScheduler
```

Source: [ui/src/chat/headless/streams/scheduler.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/scheduler.ts#L28)

### `EMPTY_RUN_METER`

Constant.

The counters of a session with no run seen.

```ts
const EMPTY_RUN_METER: RunMeterState
```

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

### `LIVE_BLOCK_RUN_LINES`

Constant.

Lines a live run keeps for its window.

```ts
const LIVE_BLOCK_RUN_LINES = 15
```

Source: [ui/src/chat/headless/block-runs.ts:24](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/block-runs.ts#L24)

### `MAIN_SESSION_ICON_KEY`

Constant.

Storage key for the orchestration Main session's icon. Not a path — the
main is directory-less and one per store — but it lives in the same
localStorage map so the picker, persistence and reset are shared.

```ts
const MAIN_SESSION_ICON_KEY = 'zg:main-session'
```

Source: [ui/src/chat/headless/sidebar/project-icons.ts:95](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L95)

### `MAX_EXTENSION_COMPOSER_BADGES`

Constant.

How many badges one extension shows in one composer (zidane's `MAX_COMPOSER_BADGES`).

```ts
const MAX_EXTENSION_COMPOSER_BADGES = 8
```

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

### `MAX_ROW_CHIPS`

Constant.

The most chips a row shows, whatever the decorations add.

```ts
const MAX_ROW_CHIPS = 8
```

Source: [ui/src/chat/headless/sidebar/query.ts:443](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L443)

### `MODEL_PICKER_STORAGE_KEY`

Constant.

The Storage key the preferences live under.

```ts
const MODEL_PICKER_STORAGE_KEY = 'zg:model-picker:v1'
```

Source: [ui/src/chat/headless/composer/model-picker-prefs.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-picker-prefs.ts#L8)

### `NO_PROVIDER_ERROR`

Constant.

The thrown text when no provider can answer: the composer puts the prompt back.

```ts
const NO_PROVIDER_ERROR = 'No provider is connected.'
```

Source: [ui/src/chat/headless/send-flow.ts:288](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L288)

### `NO_SIDEBAR_CONTRIBUTIONS`

Constant.

Nothing contributed.

```ts
const NO_SIDEBAR_CONTRIBUTIONS: SidebarContributions
```

Source: [ui/src/chat/headless/sidebar/query.ts:83](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L83)

### `PINNED_PROJECTS_KEY`

Constant.

Where the pins persist.

```ts
const PINNED_PROJECTS_KEY = 'zg-sidebar-pinned-projects'
```

Source: [ui/src/chat/headless/sidebar/pinned-projects.ts:9](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-projects.ts#L9)

### `PROJECT_GROUP_CAP`

Constant.

Default number of sessions a project group shows before its "show more" row.

```ts
const PROJECT_GROUP_CAP = 5
```

Source: [ui/src/chat/headless/session-list.ts:118](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L118)

### `PROJECT_ICONS_KEY`

Constant.

Where the icon map persists.

```ts
const PROJECT_ICONS_KEY = 'zg-sidebar-project-icons'
```

Source: [ui/src/chat/headless/sidebar/project-icons.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L8)

### `REFERENCES_STORAGE_KEY`

Constant.

Where the caches persist.

```ts
const REFERENCES_STORAGE_KEY = 'zg:references:v1'
```

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

### `RELATIVE_TIME_DATE_AFTER_DAYS`

Constant.

From this many days [`relativeTime`](https://zidane.si/docs/reference/ui-chat-headless.md#relativeTime) shows a date (`Mar 4`), not a duration: pass it to core `ageStep` to know whether the label takes "ago".

```ts
const RELATIVE_TIME_DATE_AFTER_DAYS = 7
```

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

### `SESSION_HISTORY_LIMIT`

Constant.

The most entries a history keeps by default.

```ts
const SESSION_HISTORY_LIMIT = 200
```

Source: [ui/src/chat/headless/sidebar/history.ts:83](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L83)

### `SIDEBAR_SPACE_KEY`

Constant.

Where the shown space persists.

```ts
const SIDEBAR_SPACE_KEY = 'zg-sidebar-space'
```

Source: [ui/src/chat/headless/sidebar/view.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L36)

### `SIDEBAR_SWITCHER_KEY`

Constant.

Where the switcher's own order and hidden spaces persist.

```ts
const SIDEBAR_SWITCHER_KEY = 'zg:sidebar-switcher:v1'
```

Source: [ui/src/chat/headless/sidebar/view.ts:107](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L107)

### `SIDEBAR_VIEW_KEY`

Constant.

Where the views persist: one map of space id → view.

```ts
const SIDEBAR_VIEW_KEY = 'zg-sidebar-view:v1'
```

Source: [ui/src/chat/headless/sidebar/view.ts:34](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L34)

### `SMOOTH_TICK_MS`

Constant.

Tick interval (ms). Matches one frame at 60fps.

```ts
const SMOOTH_TICK_MS = 16
```

Source: [ui/src/chat/headless/smooth-stream.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/smooth-stream.ts#L15)

### `VIEW_CHOICE`

Constant.

In [`SidebarExtensionView`](https://zidane.si/docs/reference/ui-chat-headless.md#SidebarExtensionView): the view's own axis (`groupBy`, `sortBy`) in a space that has a
grouping or sort of its own (an extension space, a saved view), where that one applies by default.

```ts
const VIEW_CHOICE = '@view'
```

Source: [ui/src/chat/headless/sidebar/types.ts:65](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L65)

## Interfaces

### `AuthCardPlan`

Interface.

What the card offers for one failure, given the host's providers.

```ts
interface AuthCardPlan
```

**Properties**

- `failed?` (`SettingsCredential`): The stored credential that failed, when it can be told.
- `label` (`string`): The provider as the user knows it (`Anthropic`): the host's label, else `auth.provider`.
- `otherAccount?` (`SettingsCredential`): Another stored OAuth account of the provider to switch to.
- `provider?` (`SettingsProvider`): The host's provider the failure is about, when the list names it.
- `replaceKey?` (`string`): The stored OAuth account to sign in again (`SettingsSignInOptions.replaceKey`).
- `settings` (`AuthSettingsTarget`): Where Settings opens for it.

Source: [ui/src/chat/headless/transcript/auth-failure.ts:27](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L27)

### `AuthFixes`

Interface.

The sign-ins fixed from a card, per session: every card for the same sign-in says so.

```ts
interface AuthFixes
```

**Properties**

- `add` (`(sessionId: string | null, auth: AuthFailure) => void`): Records that a sign-in of a session was fixed.
- `fixed` (`(sessionId: string | null) => Readable<readonly AuthFailure[]>`): The sign-ins fixed in a session (`null`: a session without an id).

Source: [ui/src/chat/headless/transcript/auth-failure.ts:92](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L92)

### `AuthSettingsTarget`

Interface.

Where the card's Settings button lands: the provider (or MCP server, integration) and the stored credential that failed.

```ts
interface AuthSettingsTarget
```

**Properties**

- `credential?` (`string`): The stored credential that failed (`SettingsCredential.key`), when it is known.
- `field?` (`'apikey'`): `apikey`: the credentials were an API key the provider refused; land on its key field.
- `provider` (`string`): The provider's key as the host lists it (or the MCP server's, the integration's name).
- `source` (`'mcp' | 'provider' | 'integration'`): What signs in.

Source: [ui/src/chat/headless/transcript/auth-failure.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/auth-failure.ts#L15)

### `BashExitMeta`

Interface.

Exit details of a shell command, parsed from its result text by [`parseBashExitMeta`](https://zidane.si/docs/reference/ui-chat-headless.md#parseBashExitMeta).

```ts
interface BashExitMeta
```

**Properties**

- `cancelled` (`boolean`): The user cancelled the command.
- `code` (`number | null`): null = killed by signal (abort / output-ceiling kill).
- `durationMs` (`number`): How long the command ran, in milliseconds.

Source: [ui/src/chat/headless/transcript/rows.ts:319](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L319)

### `BuildQuerySidebarRowsOptions`

Interface.

Options of [`buildQuerySidebarRows`](https://zidane.si/docs/reference/ui-chat-headless.md#buildQuerySidebarRows).

```ts
interface BuildQuerySidebarRowsOptions<S extends SidebarListSession>
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Properties**

- `collapsedGroups?` (`ReadonlySet<string>`): Collapsed header and item ids.
- `favoritesLabel?` (`string`): The favorites section's label. Default: the chat labels'.
- `isFavorite?` (`(session: S) => boolean`): Favorited sessions lead the list under their own header, as in every grouping.
- `items?` (`readonly SidebarItemEntry<S>[]`): Extension items, each listed first in the group its `group` names (no `group`: the group without a value).
- `labels?` (`Readonly<Record<string, string>>`): Labels by group key, under the grouping's own (agent names for the agent grouping).
- `missingLabel?` (`string`): The label of the group of sessions without a value.

Source: [ui/src/chat/headless/sidebar/rows.ts:288](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L288)

### `CalendarOptions`

Interface.

Which calendar day labels are read in. Default: the runtime's zone and
locale. Pin both when the same list renders on a server and in browsers
(a prerendered page), or the two disagree about "Yesterday" and hydration
fails.

```ts
interface CalendarOptions
```

**Properties**

- `locale?` (`string`): Locale of the weekday names (the other date words come from the labels).
- `timeZone?` (`string`): IANA time zone the days are read in, for example `Europe/Paris`. Default: the runtime's zone.

Source: [ui/src/chat/headless/session-list.ts:129](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L129)

### `ChatAttachment`

Interface.

An attachment on a prompt, as the components can show it.

```ts
interface ChatAttachment
```

**Properties**

- `dataUrl?` (`string`): Where a preview loads the bytes from (images and PDFs): a `data:` URL, an object URL, or any URL the page can load.
- `mediaType` (`string`): MIME type, for example `image/png`.
- `name` (`string`): File name shown on the attachment chip.
- `original?` (`ChatAttachmentOriginal`): The file as the user picked it, when the composer converted it to send
  (an image re-encoded to fit the cap). The host saves these bytes where
  the agent's tools can reach them; the model gets the converted copy.
- `size` (`number`): Size in bytes.

Source: [ui/src/chat/headless/host.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L28)

### `ChatAttachmentOriginal`

Interface.

The file a composer converted before sending (`ChatAttachment.original`).

```ts
interface ChatAttachmentOriginal
```

**Properties**

- `dataUrl` (`string`): The bytes, as a `data:` URL.
- `mediaType` (`string`): Its MIME type, for example `image/gif`.
- `name` (`string`): The file's own name.
- `size` (`number`): Size in bytes.

Source: [ui/src/chat/headless/host.ts:46](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L46)

### `ChatBadgeActions`

Interface.

The badge menu's extension actions (`badges:actions`). Absent: the built-in actions only.

```ts
interface ChatBadgeActions
```

**Properties**

- `actions` (`(cwd: string, target: BadgeTarget) => Promise<readonly BadgeMenuItem[]>`): The extensions' items for a badge.
- `run` (`(cwd: string, source: string, id: string, target: BadgeTarget) => Promise<BadgeActionEffect>`): Runs an extension's item and resolves with what to do.

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

### `ChatBlockRunOptions`

Interface.

How a run reports and stops.

```ts
interface ChatBlockRunOptions
```

**Properties**

- `signal?` (`AbortSignal`): Stops the run.
- `onOutput?` (`(stream: 'stdout' | 'stderr', text: string) => void`): Output as it arrives.

Source: [ui/src/chat/headless/block-runs.ts:16](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/block-runs.ts#L16)

### `ChatBlockRuns`

Interface.

Run here on a reply's shell blocks. Absent: blocks have no Run button.

```ts
interface ChatBlockRuns
```

**Properties**

- `live` (`(sessionId: string) => Readable<Readonly<Record<string, LiveBlockRun>>>`): A session's runs started here, by key: running, or failed to run.
- `remove` (`(sessionId: string, key: string) => Promise<void>`): Forgets a block's saved run.
- `run` (`(sessionId: string, request: BlockRunRequest, options?: ChatBlockRunOptions) => Promise<BlockRun>`): Runs a block in the session's folder with no input; resolves with the saved run. Rejects when it could not run.
- `runs` (`(sessionId: string) => Readable<Readonly<Record<string, BlockRun>>>`): A session's saved runs, by key (`blockRunKey`), kept current.
- `start` (`(sessionId: string, request: BlockRunRequest) => void`): Starts a run that `ChatBlockRuns.live` follows; once it ends it shows in `ChatBlockRuns.runs`. A block already running is left alone.
- `stop` (`(sessionId: string, key: string) => void`): Stops a block's run, or forgets why it could not run.

Source: [ui/src/chat/headless/block-runs.ts:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/block-runs.ts#L39)

### `ChatBlockRunTransport`

Interface.

What an adapter's transport offers for [`createChatBlockRuns`](https://zidane.si/docs/reference/ui-chat-headless.md#createChatBlockRuns).

```ts
interface ChatBlockRunTransport
```

**Properties**

- `remove` (`(sessionId: string, key: string) => Promise<void>`): Forgets a saved run on the host: `ChatBlockRuns.remove`.
- `run` (`(sessionId: string, request: BlockRunRequest, options?: ChatBlockRunOptions) => Promise<BlockRun>`): Runs a block on the host: `ChatBlockRuns.run`.
- `list` (`(sessionId: string) => Promise<Record<string, BlockRun>>`): The session's saved runs.
- `onChanged` (`(listener: (sessionId: string) => void) => () => void`): Calls `listener` with a session whose runs changed. Returns the unsubscribe.

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

### `ChatChipDetails`

Interface.

What chip hover cards read when they open. Each method left out leaves its card with the chip's own text.

```ts
interface ChatChipDetails
```

**Properties**

- `commands?` (`(cwd: string, hostId: string | null) => Promise<readonly ChatCommandFacts[]>`): The commands of `cwd` on a host (`null`: this one).
- `commit?` (`(cwd: string, sha: string) => Promise<ChatCommit | null>`): A commit of the repo at `cwd`; `null` when unknown.
- `context?` (`(sessionId: string) => Promise<ChatContextFacts | null>`): A session's context gauge; `null` when unknown.
- `sessions?` (`() => Promise<readonly ChatSessionFacts[]>`): The sessions a `#chat` chip can name.
- `skills?` (`(cwd: string) => Promise<readonly ChatSkillFacts[]>`): The skills of `cwd`.

Source: [ui/src/chat/headless/transcript-host.ts:156](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L156)

### `ChatCommandFacts`

Interface.

A command, as a command chip's hover card shows it.

```ts
interface ChatCommandFacts
```

**Properties**

- `aliases?` (`readonly string[]`): Other names it answers to.
- `description?` (`string`): One-line description.
- `group?` (`string`): Its group (`zidane`, an extension).
- `name` (`string`): Command name, without the slash.

Source: [ui/src/chat/headless/transcript-host.ts:144](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L144)

### `ChatCommit`

Interface.

One commit, for a sha chip's hover card.

```ts
interface ChatCommit
```

**Properties**

- `added` (`number`): Lines added.
- `author` (`string`): Author name.
- `authoredAt` (`number`): Author date, epoch ms.
- `files` (`number`): Files changed.
- `removed` (`number`): Lines removed.
- `sha` (`string`): The full sha.
- `subject` (`string`): First line of the message.

Source: [ui/src/chat/headless/transcript-host.ts:80](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L80)

### `ChatContextFacts`

Interface.

A session's context gauge, as a `#chat` card shows it.

```ts
interface ChatContextFacts
```

**Properties**

- `fraction` (`number`): Used share of the window, 0 to 1.
- `modelId` (`string`): The model the gauge is for.
- `usedLabel` (`string`): Tokens in use, formatted (`12.3k`).
- `windowLabel` (`string`): The window, formatted (`200k`).

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

### `ChatHost`

Interface.

The seam between the chat components and whatever runs the agent: readable stores plus optional actions. A component hides the control for any capability the host leaves out.

```ts
interface ChatHost
```

**Properties**

- `badges?` (`ChatBadgeActions`): The badge menu's extension actions. Absent: the built-in actions only.
- `blockRuns?` (`ChatBlockRuns`): Run here on a reply's shell blocks, and their saved runs. Absent: blocks have no Run button.
- `chips?` (`ChatChipDetails`): What chip hover cards show (a commit, a `#chat`, a skill, a command). Absent: chips have no hover card.
- `interactions?` (`{ all?(): Readable<readonly ChatInteraction[]>; answer(requestId: string, response: InteractionResponse): Promise<void>; cancel?(requestId: string, reason?: string): Promise<void>; pending(sessionId: string): Readable<readonly ChatInteraction[]> }`): Pending questions, plans, and approvals, and the way to answer or dismiss them.
- `models?` (`Readable<readonly ChatModelProvider[]>`): Providers and models for the model picker. Absent: no picker.
- `paths?` (`ChatPaths`): What prose chips name on disk. Absent: a chip opens the path as written.
- `references?` (`ChatReferences`): Extension text references (ticket ids, issue links) in prose. Absent: they stay plain text.
- `searchSync?` (`ChatSearchSync`): The transcript search a session's other windows share. Absent: the search stays in this window.
- `sessions?` (`{ list: Readable<readonly ChatSession[]>; views?: SidebarViewsHost; create?(input?: { title?: string }): Promise<ChatSession>; main?(): Promise<string | null>; onChanged?(listener: (sessionId: string) => void): () => void; onFacets?(listener: (sessionId: string, facets: Readonly<Record<string, unknown>>) => void): () => void; query?(filter: { archive: SessionArchiveFilter; hostId?: string }): Promise<readonly SidebarListSession[]>; remove?(sessionId: string): Promise<void | SessionRemoval>; rename?(sessionId: string, title: string): Promise<void>; search?(query: string, filter?: { archive?: SessionArchiveFilter }): Promise<readonly SessionSearchHit[]>; setArchived?(sessionId: string, archived: boolean): Promise<void>; setFavorite?(sessionId: string, favorite: boolean): Promise<void>; setSpace?(sessionId: string, spaceId: string): Promise<void> }`): Session list and management. Each method left out hides its control (rename, archive, favorite, delete).
- `siteIcons?` (`ChatSiteIcons`): Site icons for link badges. Absent: links show the globe.
- `cancelTool?` (`(sessionId: string, callId: string) => void`): Stop a running tool call (a shell command).
- `interrupt?` (`(sessionId: string) => void`): Stops the run in flight in a session. Absent: no stop button.
- `providerReady?` (`(cwd?: string) => Promise<boolean>`): Whether a model provider can answer a prompt sent from `cwd`. Absent: a send is never refused for want of one.
- `send?` (`(input: SendInput) => Promise<void>`): Sends a prompt to a session. Absent: the composer cannot send.
- `shell?` (`(sessionId: string, command: string) => Promise<void>`): Runs a `!` shell command in the session's folder, outside any agent run; its run streams into the
  transcript. Absent: a `!` prompt goes to the model as text.
- `toolOutput?` (`(sessionId: string, callId: string) => Promise<string | null>`): A tool call's full output, when the event carries a preview only.
- `transcript` (`(sessionId: string) => Transcript`): Returns the transcript store for a session.

Source: [ui/src/chat/headless/host.ts:207](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L207)

### `ChatInteraction`

Interface.

A request from the agent that waits for the user: a question, a plan, or an approval.

```ts
interface ChatInteraction
```

**Properties**

- `live?` (`boolean`): `false`: rehydrated from an earlier run, not raised by a run waiting right now (an inbox only badges it). Absent: live.
- `request` (`InteractionRequest`): The request itself: its kind and the content to show.
- `requestId` (`string`): Id of the request. Pass it to `interactions.answer` or `interactions.cancel`.
- `sessionId` (`string`): Id of the session the request belongs to.

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

### `ChatModel`

Interface.

A model a session can run.

```ts
interface ChatModel
```

**Properties**

- `contextWindow?` (`number`): Context window size in tokens. Drives the context meter.
- `details?` (`readonly string[]`): Short facts the picker shows beside the name, before the window (a download size, `Cached`).
- `id` (`string`): Model id within its provider. Combined with the provider key as `provider/model` in [`SendInput`](https://zidane.si/docs/reference/ui-chat-headless.md#SendInput).
- `label?` (`string`): Display name for pickers.
- `options?` (`readonly { description?: string; id: string; label: string }[]`): Feature toggles the model declares (fast mode), as the model options menu lists them.
- `thinking?` (`boolean`): Supports extended thinking / reasoning effort.

Source: [ui/src/chat/headless/host.ts:140](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L140)

### `ChatModelProvider`

Interface.

A provider and the models it offers, as the model picker groups them.

```ts
interface ChatModelProvider
```

**Properties**

- `key` (`string`): Provider id, the `provider` part of a `provider/model` reference.
- `label` (`string`): Provider name shown as the group heading.
- `models` (`readonly ChatModel[]`): Models the provider offers.

Source: [ui/src/chat/headless/host.ts:156](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L156)

### `ChatPaths`

Interface.

What prose chips name on the session's disk.

```ts
interface ChatPaths
```

**Properties**

- `onChanged?` (`(listener: (cwd: string) => void) => () => void`): Calls `listener` with a folder whose files may have moved (a commit, a checkout). Returns the unsubscribe.
- `resolve` (`(cwd: string, texts: readonly string[]) => Promise<readonly ChatResolvedPath[] | null>`): What each of `texts` names under `cwd`, in order; `null` when the folder can't be checked.

Source: [ui/src/chat/headless/transcript-host.ts:72](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L72)

### `ChatReferences`

Interface.

Extension text references (`ctx.registerReferences`): the providers' patterns per folder and the views of the keys found.

```ts
interface ChatReferences
```

**Properties**

- `resolveMax?` (`number`): Keys per `resolve` call, at most. Default 50.
- `onChanged?` (`(listener: (change: ChatReferencesChange) => void) => () => void`): Calls `listener` when providers or views change. Returns the unsubscribe. Absent: views refresh on their own schedule.
- `providers` (`(cwd: string, options?: { peek?: boolean }) => Promise<readonly ReferenceProviderWire[] | null>`): The providers for `cwd` (`''`: user-level). `peek`: only what the host already built, `null` when it
  has nothing cached (a sidebar title never builds a registry).
- `resolve` (`(cwd: string, items: readonly { key: string; providerId: string }[]) => Promise<readonly (ExtensionReferenceView | null)[]>`): The views of `items`, in order: `null` for a key that names nothing (it stays plain text).

Source: [ui/src/chat/headless/transcript-host.ts:45](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L45)

### `ChatSearchState`

Interface.

The transcript search of one session, as its windows share it.

```ts
interface ChatSearchState
```

**Properties**

- `active` (`boolean`): The search is open.
- `query` (`string`): The query as typed.
- `sessionId` (`string`): The session the search runs in.

Source: [ui/src/chat/headless/transcript-host.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L20)

### `ChatSearchSync`

Interface.

The transcript search a session's windows share (the composer's `?` mode).

```ts
interface ChatSearchSync
```

**Properties**

- `onChanged` (`(listener: (state: ChatSearchState) => void) => () => void`): Calls `listener` when another window changes a session's search. Returns the unsubscribe.
- `set` (`(sessionId: string, state: { active: boolean; query: string }) => Promise<void>`): Tells the session's other windows this window's search.

Source: [ui/src/chat/headless/transcript-host.ts:30](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L30)

### `ChatSession`

Interface.

A session as the list shows it.

```ts
interface ChatSession
```

**Properties**

- `archived?` (`boolean`): The session is archived. The list row shows an archive glyph.
- `createdAt` (`number`): Epoch milliseconds.
- `favorite?` (`boolean`): Listed first, in the favorites section.
- `group?` (`string`): Sessions sharing a group are listed together (a project, a folder, a host).
- `groupLabel?` (`string`): Shown as the group's heading; defaults to `group`.
- `id` (`string`): Stable session id. Passed to every host method that takes a `sessionId`.
- `modelId?` (`string`): Id of the model the session uses, as listed in `host.models`.
- `pinned?` (`boolean`): Kept at the top of the list (the orchestrating main session).
- `status` (`ChatSessionStatus`): Run state, shown as the row's status dot.
- `title` (`string`): Name shown in the list and used by the title search.
- `updatedAt` (`number`): Epoch milliseconds of the last activity. Drives recency sorting and relative times.

Source: [ui/src/chat/headless/host.ts:82](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L82)

### `ChatSessionFacts`

Interface.

A session as a `#chat` chip's hover card shows it.

```ts
interface ChatSessionFacts
```

**Properties**

- `branch?` (`string`): Branch of the session's environment.
- `id` (`string`): Session id. A `#token` names the one session whose id starts with it.
- `modelId?` (`string`): Model id.
- `project?` (`string`): The folder the session runs in (its last segment is shown).
- `prompts?` (`number`): Prompts sent.
- `status` (`ChatSessionStatus`): Run state.
- `title` (`string`): Title; empty when untitled.
- `turns?` (`number`): Turns stored.
- `updatedAt` (`number`): Epoch ms of the last activity.

Source: [ui/src/chat/headless/transcript-host.ts:98](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L98)

### `ChatSiteIcons`

Interface.

Site icons for link badges: one ask per origin, shared by every badge of the site.

```ts
interface ChatSiteIcons
```

**Properties**

- `get` (`(origin: string) => string | null`): The icon's data URL once known; `null` when the site has none or it has not loaded.
- `request` (`(origin: string) => void`): Asks for an origin's icon, once.
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` after a new icon arrives. Returns the unsubscribe.

Source: [ui/src/chat/headless/transcript-host.ts:170](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L170)

### `ChatSkillFacts`

Interface.

A skill, as a skill chip's hover card shows it.

```ts
interface ChatSkillFacts
```

**Properties**

- `description?` (`string`): One-line description.
- `instructions?` (`string`): The instructions (their size is shown).
- `name` (`string`): Skill name.
- `source?` (`string`): Where it was found (`project`, `user`, a plugin).

Source: [ui/src/chat/headless/transcript-host.ts:132](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L132)

### `CommandArgSuggestionSummary`

Interface.

Wire-safe projection of canonical `CommandArgSuggestion`.

```ts
interface CommandArgSuggestionSummary
```

**Properties**

- `description?` (`string`): Secondary text shown next to the label.
- `label?` (`string`): Display label. Defaults to `value`.
- `value` (`string`): Text inserted after `/<name> ` on accept.

Source: [dist/media-type-BzRZ4FqT.d.ts:7354](https://github.com/Tahul/zidane/blob/main/dist/media-type-BzRZ4FqT.d.ts#L7354)

### `CommandSummary`

Interface.

Wire-safe summary of an extension-contributed `/` command — the
projection of canonical `Command` (src/chat/commands.ts) minus its
function-valued fields (steps, completeArgs).

```ts
interface CommandSummary
```

**Properties**

- `aliases?` (`string[]`): Alternative names that run the same command.
- `description` (`string`): One-line description shown in completion lists.
- `group?` (`string`): Grouping label — defaults to the contributing extension's name.
- `hasArgCompletion?` (`boolean`): `true` when the canonical command declares `completeArgs` — lets a
  client wire an arg-completion shim only for commands that actually
  complete, instead of firing blind RPCs on every `/name <prefix>`.
- `name` (`string`): Command name, without the leading `/`.

Source: [dist/media-type-BzRZ4FqT.d.ts:7337](https://github.com/Tahul/zidane/blob/main/dist/media-type-BzRZ4FqT.d.ts#L7337)

### `CompactionProgress`

Interface.

A compaction's live progress.

```ts
interface CompactionProgress
```

**Properties**

- `estTokens` (`number | null`): The summary's estimated tokens so far, once the loop reports one.
- `startedAt` (`number`): When it started (ms).

Source: [ui/src/chat/headless/sidebar/compaction.ts:10](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/compaction.ts#L10)

### `CompactionProgressStore`

Interface.

Every session's compaction in progress, outside React.

```ts
interface CompactionProgressStore
```

**Properties**

- `get` (`(sessionId: string) => CompactionProgress | null`): The session's compaction in progress, `null` when none.
- `start` (`() => () => void`): Follow the signals; returns the stop. Call once at boot.
- `subscribe` (`(sessionId: string, listener: () => void) => () => void`): Fires when the session's compaction starts, reports progress or ends.

Source: [ui/src/chat/headless/sidebar/compaction.ts:49](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/compaction.ts#L49)

### `ComposerAgentProfile`

Interface.

An agent profile a folder offers.

```ts
interface ComposerAgentProfile
```

**Properties**

- `accent` (`string`): Its accent color (a theme color name or a CSS color).
- `description` (`string`): What it does.
- `id` (`string`): Stable id.
- `label` (`string`): Its name.

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

### `ComposerAgents`

Interface.

The agent profiles. Absent: the agent picker hides.

```ts
interface ComposerAgents
```

**Properties**

- `list` (`(cwd: string) => Promise<readonly ComposerAgentProfile[]>`): The profiles a folder offers (`''`: no folder).
- `onChanged?` (`(listener: () => void) => () => void`): Calls `listener` when the offered profiles may have changed. Returns the unsubscribe.

Source: [ui/src/chat/headless/composer/host-chrome.ts:87](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L87)

### `ComposerAttachment`

Interface.

An attachment staged in a composer: always read into a `data:` URL, keyed for removal.

```ts
interface ComposerAttachment extends ChatAttachment
```

**Properties**

- `dataUrl` (`string`): Where a preview loads the bytes from (images and PDFs): a `data:` URL, an object URL, or any URL the page can load.
- `fileKey?` (`string`): The dropped, pasted or picked file's `attachmentFileKey`, so the same file doesn't stage twice.
- `id` (`string`): Unique id (a random UUID) that keys the attachment and removes it.
- `mediaType` (`string`, from `ChatAttachment`): MIME type, for example `image/png`.
- `name` (`string`, from `ChatAttachment`): File name shown on the attachment chip.
- `original?` (`ChatAttachmentOriginal`, from `ChatAttachment`): The file as the user picked it, when the composer converted it to send
  (an image re-encoded to fit the cap). The host saves these bytes where
  the agent's tools can reach them; the model gets the converted copy.
- `size` (`number`, from `ChatAttachment`): Size in bytes.

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

### `ComposerAutocomplete`

Interface.

Inline ghost-text autocomplete. Absent: no ghost text.

```ts
interface ComposerAutocomplete
```

**Properties**

- `inline` (`(cwd: string, text: string, caret: number, sessionId?: string) => Promise<string[] | null>`): The completions for `text` with the caret at `caret`, `null` for none. `sessionId` shares the result with the session's other windows.
- `onShared?` (`(listener: (ghost: ComposerSharedGhost) => void) => () => void`): Calls `listener` when another window resolved a ghost text. Returns the unsubscribe.

Source: [ui/src/chat/headless/composer/host.ts:199](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L199)

### `ComposerCommandArgs`

Interface.

The commands' fixed argument values, shared by everything that reads a
`/command` (the composer's badge, the transcript's prompt rows): what the
`/` popover learns is noted here. The app keeps one; the rich composer takes
it as a prop.

```ts
interface ComposerCommandArgs
```

**Properties**

- `args` (`(scope: ComposerScope, name: string) => ReadonlySet<string>`): `name`'s values known so far in a scope.
- `note` (`(scope: ComposerScope, name: string, values: readonly string[]) => void`): Records values learned for `name` in a scope.
- `request` (`(scope: ComposerScope, name: string) => void`): Asks for `name`'s values in a scope (once; subscribers hear when they arrive).
- `subscribe` (`(listener: () => void) => () => void`): Calls `listener` when values arrive. Returns the unsubscribe.

Source: [ui/src/chat/headless/composer/host.ts:171](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L171)

### `ComposerCompletions`

Interface.

The catalogs behind the composer's completions. Each one left out empties its popover.

```ts
interface ComposerCompletions
```

**Properties**

- `chats?` (`() => Promise<readonly ChatReferenceEntry[]>`): The sessions `#` can reference.
- `commandArgs?` (`(scope: ComposerScope, name: string, prefix: string) => Promise<readonly CommandArgSuggestionSummary[]>`): Suggestions for `/name <prefix>`. Best effort: resolves `[]` on failure.
- `commands?` (`(scope: ComposerScope) => Promise<readonly CommandSummary[]>`): The `/` commands in a scope.
- `extensionItems?` (`(cwd: string, providerId: string, query: string, text: string, caret: number) => Promise<readonly ComposerExtensionItem[]>`): An extension trigger's items for what was typed after it.
- `files?` (`(root: string, hostId: string | null) => Promise<readonly FileEntry[]>`): The files under `root` for `@` mentions (`hostId`: the server holding `root`).
- `locationOf?` (`(cwd: string) => Promise<ComposerFolderLocation>`): Where a folder sits, so `@` mentions in a worktree list the project's files.
- `submit?` (`(scope: ComposerScope, text: string, caret: number) => Promise<void>`): Runs the extensions' submit hooks on a prompt before it is sent.
- `watchExtensionProviders?` (`(scope: ComposerScope, listener: (providers: readonly ComposerExtensionProvider[]) => void) => () => void`): Calls `listener` with the extensions' completion triggers in a scope, now and on each change. Returns the unsubscribe.
- `watchSkills?` (`(scope: ComposerScope, listener: (skills: readonly SkillConfig[]) => void) => () => void`): Calls `listener` with the enabled skills in a scope (`/skill` completion and badges), now and on each change. Returns the unsubscribe.

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

### `ComposerContext`

Interface.

A session's meters. Each one left out hides what reads it.

```ts
interface ComposerContext
```

**Properties**

- `breakdown?` (`(sessionId: string) => Readable<ResourceSnapshot<ContextBreakdown | null>>`): What fills the session's context, by category.
- `cost?` (`(sessionId: string) => Promise<ComposerCostStatus | null>`): The session's cost as its finished runs settled it.
- `status?` (`(sessionId: string, modelId: string | null, providerKey: string | null) => Readable<ResourceSnapshot<ComposerContextStatus | null>>`): The session's context gauge (keyed by its model, so a switch refetches it).

Source: [ui/src/chat/headless/composer/host-chrome.ts:164](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L164)

### `ComposerContextStatus`

Interface.

A session's context gauge and what its model offers.

```ts
interface ComposerContextStatus
```

**Properties**

- `availableOptions` (`readonly ComposerModelOption[]`): The feature toggles the model declares.
- `effectiveWindow` (`number`): The usable window.
- `fraction` (`number`): `used / effectiveWindow`, 0 to 1.
- `modelId` (`string`): The model the gauge measures.
- `modelOptions` (`Record<string, boolean>`): The session's enabled options.
- `supportsReasoning` (`boolean`): The model has a reasoning effort knob.
- `used` (`number`): Tokens in the last request.
- `usedLabel` (`string`): `used`, formatted.
- `windowLabel` (`string`): `effectiveWindow`, formatted.

Source: [ui/src/chat/headless/composer/host-chrome.ts:129](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L129)

### `ComposerControls`

Interface.

The pickers' writes on a session. Each one left out hides the control that needs it.

```ts
interface ComposerControls
```

**Properties**

- `cacheImpact?` (`(sessionId: string, change: CacheImpactChange) => Promise<CacheImpact | null>`): What a switch would cost the session's prompt cache, `null` when unknown. Absent: pickers show no cache hints.
- `setAgent?` (`(sessionId: string, agentId: string) => Promise<void>`): Sets the session's agent profile.
- `setEffort?` (`(sessionId: string, effort: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive') => Promise<void>`): Sets the session's reasoning effort.
- `setModel?` (`(sessionId: string, primary: ModelPickRef, fallbacks: readonly ModelPickRef[]) => Promise<void>`): Sets the session's model: `primary`, then `fallbacks` (replacing the chain).
- `setModelOptions?` (`(sessionId: string, options: Record<string, boolean>) => Promise<void>`): Sets the session's enabled model options.

Source: [ui/src/chat/headless/composer/host-chrome.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L51)

### `ComposerCostStatus`

Interface.

A session's total cost as last settled.

```ts
interface ComposerCostStatus
```

**Properties**

- `label` (`string | null`): `totalCost` formatted, `null` when zero.
- `runCount` (`number`): Runs counted.
- `totalCost` (`number`): Total in USD.

Source: [ui/src/chat/headless/composer/host-chrome.ts:151](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L151)

### `ComposerDrafts`

Interface.

The per-session draft every window of the app shares. Absent: each window keeps its own.

```ts
interface ComposerDrafts
```

**Properties**

- `get` (`(sessionId: string) => Promise<SharedDraft>`): The session's draft (`text: ''` when it has none).
- `onAttachmentsChanged?` (`(listener: (change: SharedDraftAttachmentsChange) => void) => () => void`): Calls `listener` when another window changes a draft's staged files. Returns the unsubscribe.
- `onChanged?` (`(listener: (change: SharedDraftChange) => void) => () => void`): Calls `listener` when another window changes a draft's text. Returns the unsubscribe.
- `set` (`(sessionId: string, text: string, shell?: boolean) => Promise<void>`): Replaces the session's draft text.
- `setAttachments?` (`(sessionId: string, attachments: PromptAttachment[]) => Promise<void>`): Replaces the session's staged files. Absent: staged files stay in this window.

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

### `ComposerExtensionItem`

Interface.

One item an extension's completion offers.

```ts
interface ComposerExtensionItem
```

**Properties**

- `description?` (`string`): Short text under the label.
- `id` (`string`): The item's id.
- `insertText` (`string`): What a pick writes into the prompt.
- `label` (`string`): What the row shows.

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

### `ComposerExtensionProvider`

Interface.

An extension's completion trigger (a character that opens its popover).

```ts
interface ComposerExtensionProvider
```

**Properties**

- `id` (`string`): The provider's id, passed back to `ComposerCompletions.extensionItems`.
- `label` (`string`): What the popover's header says.
- `trigger` (`string`): The character that opens it.

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

### `ComposerFolderLocation`

Interface.

Where a folder sits: its checkout and the project it belongs to.

```ts
interface ComposerFolderLocation
```

**Properties**

- `checkoutRoot` (`string`): The git checkout holding the folder (the folder itself outside git).
- `projectRoot` (`string`): The project root (the main checkout for a worktree).

Source: [ui/src/chat/headless/composer/host.ts:119](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L119)

### `ComposerFolders`

Interface.

The folder a new session opens in, remembered across launches.

```ts
interface ComposerFolders
```

**Properties**

- `lastUsed` (`() => Promise<string | null>`): The folder last picked for a new session, `null` when none was.
- `setLastUsed` (`(path: string) => Promise<void>`): Remembers `path` as the next new session's folder.

Source: [ui/src/chat/headless/composer/host.ts:127](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L127)

### `ComposerHost`

Interface.

The rich composer's host. Every member is optional.

```ts
interface ComposerHost
```

**Properties**

- `agents?` (`ComposerAgents`): The agent profiles the agent picker offers.
- `autocomplete?` (`ComposerAutocomplete`): Inline ghost text.
- `completions?` (`ComposerCompletions`): The completion catalogs.
- `context?` (`ComposerContext`): A session's context gauge, its breakdown and its settled cost.
- `controls?` (`ComposerControls`): The pickers' writes on a session (model, effort, options, agent) and their cache estimates.
- `drafts?` (`ComposerDrafts`): The shared per-session draft.
- `folders?` (`ComposerFolders`): The folder a new session opens in, remembered. Absent: a new session starts without one.
- `models?` (`ComposerModels`): The model catalogs the pickers list.
- `pickerPrefs?` (`ModelPickerPrefsStore`): The model picker's per-device preferences. Absent: an in-memory store for the page's life.
- `prefs?` (`ComposerPrefs`): Where picks are remembered across apps (effort and options per model, the next chat's model).
- `runs?` (`ComposerRuns`): The current run's counters per session (the run chip, the cost pill).
- `suggestions?` (`ComposerSuggestions`): Next-prompt suggestions.

Source: [ui/src/chat/headless/composer/host.ts:225](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L225)

### `ComposerLists`

Interface.

The composer's lazily read completion lists, for one scope at a time.

```ts
interface ComposerLists
```

**Properties**

- `chats` (`LazyList<ChatReferenceEntry>`): `#` chats.
- `commands` (`LazyList<CommandSummary>`): `/` commands.
- `files` (`LazyList<FileEntry>`): `@` files.
- `setScope` (`(scope: ComposerListScope | null) => void`): A new folder, file root or server (`null`: none): every list starts over.

Source: [ui/src/chat/headless/composer/composer-sources.ts:41](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/composer-sources.ts#L41)

### `ComposerListScope`

Interface.

Where the composer reads: its folder (`''`: folderless, rooted at HOME), the session's file root, its server.

```ts
interface ComposerListScope
```

**Properties**

- `fileRoot` (`string | null`): Where `@` lists files when it isn't the folder (a sandbox's root).
- `folderPath` (`string`): The composer's folder (`''`: folderless).
- `hostId` (`string | null`): The server the session runs on, `null` for this computer.

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

### `ComposerModelEntry`

Interface.

A catalog row with the options its model declares: what `ComposerModels.catalog` lists.

```ts
interface ComposerModelEntry extends ModelCatalogRow
```

**Properties**

- `account?` (`{ active?: boolean; id: string; label: string }`, from `ModelCatalogRow`): The provider's stored account this row runs on, when it has several. Absent: its only one.
- `contextWindow` (`number | null`, from `ModelCatalogRow`): Context window in tokens, or `null` when unknown.
- `details?` (`readonly string[]`, from `ModelCatalogRow`): Short facts shown beside the name, before the window (`ChatModel.details`).
- `modelId` (`string`, from `ModelCatalogRow`): Model id within the provider.
- `modelName` (`string`, from `ModelCatalogRow`): The catalog's display name (`Claude Opus 4.6`); the row shows its natural form (`Opus 4.6`).
- `modelProvider?` (`string`, from `ModelCatalogRow`): Attribution for an aggregator's row (`anthropic` on OpenRouter).
- `offCatalog?` (`boolean`, from `ModelCatalogRow`): A typed id the catalog does not know: used as typed, no metadata.
- `options?` (`readonly ComposerModelOption[]`): The feature toggles the model declares. Absent or empty: none.
- `providerKey` (`string`, from `ModelCatalogRow`): Key of the provider that serves the model.
- `providerLabel` (`string`, from `ModelCatalogRow`): Provider name shown as the group heading.
- `references?` (`boolean`, from `ModelCatalogRow`): An image model that takes reference images (to edit, or to match a style).
- `searchCorpus?` (`string`, from `ModelCatalogRow`): Pre-lowercased search text. Default: provider key and label, account, id, name, attribution.
- `supportsReasoning` (`boolean`, from `ModelCatalogRow`): The model supports reasoning effort.
- `transparency?` (`boolean`, from `ModelCatalogRow`): An image model that can make a transparent background.
- `unavailable?` (`string`, from `ModelCatalogRow`): Why the row cannot be picked with the current credentials. The row shows, greyed out, and picking it does nothing.

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

### `ComposerModelOption`

Interface.

A feature toggle a model declares (fast mode, …).

```ts
interface ComposerModelOption
```

**Properties**

- `description?` (`string`): What it does.
- `id` (`string`): The option's id, a key of the session's enabled options.
- `label` (`string`): Its name.

Source: [ui/src/chat/headless/composer/models.ts:73](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/models.ts#L73)

### `ComposerModels`

Interface.

The model catalogs, kept current.

```ts
interface ComposerModels
```

**Properties**

- `catalog` (`(cwd: string | undefined, hostId: string | null) => Readable<ResourceSnapshot<readonly ComposerModelEntry[]>>`): The chat models a folder (`cwd`, `undefined`: the host's default) on a host (`null`: this one) can run.
- `images?` (`(cwd: string | null) => Readable<ResourceSnapshot<readonly ImageModelRow[]>>`): The image models for a folder. Absent: the picker has no Image tab.
- `providers?` (`() => Readable<ResourceSnapshot<readonly { key: string; label: string }[]>>`): Every provider this computer knows, signed in or not (labels for model names).

Source: [ui/src/chat/headless/composer/host-chrome.ts:65](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L65)

### `ComposerPrefs`

Interface.

Where picks are remembered. Absent: they last for the page's life.

```ts
interface ComposerPrefs
```

**Properties**

- `get` (`() => Promise<ComposerPrefsState | null>`): The remembered picks, `null` when there are none.
- `set` (`(patch: ComposerPrefsState) => Promise<void>`): Merges `patch` into them (top-level keys replace).

Source: [ui/src/chat/headless/composer/host-chrome.ts:121](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L121)

### `ComposerPrefsState`

Interface.

The picks remembered across apps (the TUI's `state.json`).

```ts
interface ComposerPrefsState
```

**Properties**

- `lastAccountByProvider?` (`Partial<Record<string, string>>`): The stored account last picked with each provider.
- `lastEffortByModel?` (`Record<string, 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'>`): The last effort used with each model.
- `lastModelByProvider?` (`Partial<Record<string, string>>`): The last model picked with each provider.
- `lastModelChain?` (`ComposerRememberedModel[]`): The next new chat's model chain.
- `lastModelOptionsByModel?` (`Record<string, Record<string, boolean>>`): The last enabled options used with each model.
- `lastProvider?` (`string`): The provider of the last model picked as the next new chat's.

Source: [ui/src/chat/headless/composer/host-chrome.ts:105](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L105)

### `ComposerPromptSuggestion`

Interface.

A next prompt the host suggests once a run ends.

```ts
interface ComposerPromptSuggestion
```

**Properties**

- `runId` (`string`): The run that ended.
- `sessionId` (`string`): The session it is for.
- `text` (`string`): The suggested prompt.

Source: [ui/src/chat/headless/composer/host.ts:207](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L207)

### `ComposerRememberedModel`

Interface.

A model chain entry as remembered (`state.json`'s `lastModelChain`).

```ts
interface ComposerRememberedModel
```

**Properties**

- `account?` (`string`): The stored account it runs on.
- `model` (`string`): The model's id.
- `provider` (`string`): The provider's key.

Source: [ui/src/chat/headless/composer/host-chrome.ts:95](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L95)

### `ComposerRunProgress`

Interface.

A run joined midway, as its host counts it.

```ts
interface ComposerRunProgress
```

**Properties**

- `outputTokens` (`number`): Output tokens of its settled turns.
- `startedAt` (`number`): When it began (epoch ms).

Source: [ui/src/chat/headless/composer/host-chrome.ts:178](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L178)

### `ComposerRuns`

Interface.

The current run's counters per session. Absent: no run chip.

```ts
interface ComposerRuns
```

**Properties**

- `meter` (`(sessionId: string) => Readable<RunMeterState>`): The session's counters (`createRunMeter` keeps them from the stream).
- `noteProgress?` (`(sessionId: string, generation: number, progress: ComposerRunProgress) => void`): Records the joined run's progress, read during run `generation`.
- `noteSeen?` (`(sessionId: string) => void`): Records a run's start this window saw without a start stamp (the chip counts from now).
- `progress?` (`(sessionId: string) => Promise<ComposerRunProgress | null>`): Reads a run this window joined midway, `null` for none. Absent: the chip counts from when this window saw it.
- `settleCost?` (`(sessionId: string, generation: number) => void`): Zeroes the accrued cost when a cost read issued during run `generation` settled it.

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

### `ComposerScope`

Interface.

Where a completion list comes from: the composer's folder and the host it runs on (`null`: this computer).

```ts
interface ComposerScope
```

**Properties**

- `cwd` (`string`): The folder the session (or the new chat) runs in; `''` when it has none.
- `hostId` (`string | null`): The server the session runs on, `null` for this computer.

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

### `ComposerSessionView`

Interface.

What the pickers read of a session (the desktop app's session rows fit it as they are).

```ts
interface ComposerSessionView
```

**Properties**

- `account?` (`string`): The stored account its model runs on.
- `agentId?` (`string`): Its agent profile.
- `cwd?` (`string`): Its folder (`''`: none).
- `effort?` (`'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'`): Its reasoning effort.
- `hostId?` (`string | null`): The server it runs on, absent or `null` for this computer.
- `id` (`string`): The session's id.
- `modelFallbacks?` (`readonly ModelPickRef[]`): Its model's fallbacks, primary excluded.
- `modelOptions?` (`Record<string, boolean>`): Its enabled model options.
- `title?` (`string`): Its title.

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

### `ComposerSharedGhost`

Interface.

A ghost text another window resolved for a session's draft.

```ts
interface ComposerSharedGhost
```

**Properties**

- `basis` (`string`): The draft text it completes.
- `candidates?` (`string[]`): Every candidate, for ↑/↓ rotation.
- `caret` (`number`): The caret it completes at.
- `seq` (`number`): The request's sequence number.
- `sessionId` (`string`): The session whose draft it completes.
- `suggestion` (`string | null`): The completion, `null` for none.

Source: [ui/src/chat/headless/composer/host.ts:183](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L183)

### `ComposerSuggestions`

Interface.

Next-prompt suggestions. Absent: none are shown.

```ts
interface ComposerSuggestions
```

**Properties**

- `onReady` (`(listener: (suggestion: ComposerPromptSuggestion) => void) => () => void`): Calls `listener` with each suggestion. Returns the unsubscribe.
- `onStale?` (`(listener: (sessionId: string) => void) => () => void`): Calls `listener` with a session whose suggestion went stale (a run or a compaction started, a prompt was sent). Returns the unsubscribe.

Source: [ui/src/chat/headless/composer/host.ts:217](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L217)

### `ConversationBadge`

Interface.

A badge and what a click opens: a panel, the Running work dialog, or nothing (`panel: null`).

```ts
interface ConversationBadge extends ConversationBadgeData
```

**Properties**

- `command?` (`string`): A click runs this extension command (a `composer.badges` slot item's `command`).
- `count?` (`string`, from `ConversationBadgeData`): Its count.
- `countTone?` (`'neutral'`, from `ConversationBadgeData`): How the count speaks.
- `highlight?` (`boolean`, from `ConversationBadgeData`): It asks for attention.
- `icon?` (`string`, from `ConversationBadgeData`): Its icon class.
- `id` (`string`, from `ConversationBadgeData`): Stable id: keys the badge and the user's order.
- `label` (`string`, from `ConversationBadgeData`): What it says.
- `loader?` (`boolean`, from `ConversationBadgeData`): A spinner in place of the icon.
- `opensWork?` (`true`): A click opens the Running work dialog.
- `order?` (`number`, from `ConversationBadgeData`): Its default slot.
- `panel` (`string | null`): The panel a click opens, `null` for none.
- `title?` (`string`, from `ConversationBadgeData`): Its tooltip.
- `tone?` (`'danger' | 'muted' | 'accent' | 'success' | 'warn' | 'subtle'`, from `ConversationBadgeData`): Its tone.

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

### `ConversationBadgeData`

Interface.

One badge of the strip, as data (the kit's `ComposerBadge` without its click).

```ts
interface ConversationBadgeData
```

**Properties**

- `count?` (`string`): Its count.
- `countTone?` (`'neutral'`): How the count speaks.
- `highlight?` (`boolean`): It asks for attention.
- `icon?` (`string`): Its icon class.
- `id` (`string`): Stable id: keys the badge and the user's order.
- `label` (`string`): What it says.
- `loader?` (`boolean`): A spinner in place of the icon.
- `order?` (`number`): Its default slot.
- `title?` (`string`): Its tooltip.
- `tone?` (`'danger' | 'muted' | 'accent' | 'success' | 'warn' | 'subtle'`): Its tone.

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

### `ConversationBadgeInput`

Interface.

What the strip is built from.

```ts
interface ConversationBadgeInput
```

**Properties**

- `inbox` (`InboxSummary | null`): The pending requests, `null` for none.
- `now?` (`number`, default `Date.now()`): The clock, for the next reminder's day words.
- `panels` (`ReadonlySet<string>`): The conversation's panels (the catalog's ids): an extension badge opens one of them or nothing.
- `plans` (`PlansSnapshot | null`): The session's plans: the badge follows the plan worth a glance (`active`: applying, else stopped).
- `queued` (`number`): Messages in the conversation's queue.
- `reminders?` (`RemindersSummary | null`): The conversation's reminders that will fire (`remindersSummary`), `null` for none.
- `showTodos` (`boolean`): `Settings.showTodoIndicator`.
- `slotBadges?` (`readonly ExtensionItem<'slot'>[]`): The `composer.badges` slot items shown with the conversation (`slotItems`), lowest order first.
- `work` (`readonly RunningWorkItem[]`): Its running work, as the badge shows it (`useSustainedWork`).

Source: [ui/src/chat/headless/composer/conversation-badges.ts:72](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/conversation-badges.ts#L72)

### `DeltaBucket`

Interface.

One owner's streamed text waiting to reveal.

```ts
interface DeltaBucket
```

**Properties**

- `carry` (`number`): Fractional char accumulator — prevents drift when `cps * dtMs / 1000`
  doesn't divide evenly into 1 over a single tick. Without this, a slow
  base rate (200cps \* 0.016s = 3.2 chars) would always floor to 3,
  effectively running at 187cps.
- `pending` (`string`): Un-emitted text awaiting drain.

Source: [ui/src/chat/headless/smooth-stream.ts:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/smooth-stream.ts#L18)

### `DirectoryServer`

Interface.

A remote host as the directory follows it.

```ts
interface DirectoryServer
```

**Properties**

- `id` (`string`): The host id rows carry as `hostId`.
- `status` (`string`): Its connection status (`connected` when reachable).

Source: [ui/src/chat/headless/sidebar/directory.ts:126](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L126)

### `DirectorySettings`

Interface.

The settings the directory reads.

```ts
interface DirectorySettings
```

**Properties**

- `orchestration` (`boolean`): The orchestration main session is listed.
- `spaceList` (`unknown`): The settings' space list as stored (normalized here).
- `spaces` (`boolean`): Spaces are on.

Source: [ui/src/chat/headless/sidebar/directory.ts:134](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L134)

### `DotStateInput`

Interface.

What [`deriveDotState`](https://zidane.si/docs/reference/ui-chat-headless.md#deriveDotState) reads.

```ts
interface DotStateInput
```

**Properties**

- `notification` (`'error' | 'completed' | null`): How the run that ended while the session was not open ended.
- `pending` (`boolean`): An approval, plan or question of this window waits on the user.
- `presence` (`Pick<SessionPresence, 'attention' | 'running' | 'windows'> | null`): The daemon's presence for the session, when known.
- `running` (`boolean`): This window sees the session's run going.

Source: [ui/src/chat/headless/sidebar/dot-state.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/dot-state.ts#L11)

### `DraftFolderSource`

Interface.

A session row as [`recentLocalFolders`](https://zidane.si/docs/reference/ui-chat-headless.md#recentLocalFolders) reads it.

```ts
interface DraftFolderSource
```

**Properties**

- `cwd?` (`string | null`): The session's folder (`''`: none).
- `hostId?` (`string | null`): Set for a server's session: its folders are not on this computer.

Source: [ui/src/chat/headless/draft-target.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-target.ts#L8)

### `DraftFolderState`

Interface.

What [`draftFolderPath`](https://zidane.si/docs/reference/ui-chat-headless.md#draftFolderPath) and [`draftLocalFolder`](https://zidane.si/docs/reference/ui-chat-headless.md#draftLocalFolder) read.

```ts
interface DraftFolderState
```

**Properties**

- `defaultFolder` (`string | null`): The folder new chats open in (`null`: none picked yet).
- `folderless` (`boolean`): "Start without a folder" was picked for this draft.
- `onMachine?` (`boolean`): The draft runs on a machine's environment.
- `onServer` (`boolean`): The draft runs on a saved server.
- `sessionCwd?` (`string`): The open session's folder (`''` for none); `undefined` on the draft.

Source: [ui/src/chat/headless/draft-target.ts:53](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-target.ts#L53)

### `DraftScope`

Interface.

A draft's scope: where its terminals and layout attach.

```ts
interface DraftScope
```

**Properties**

- `cwd` (`string`): The folder things open in.
- `draft` (`string`): The draft's id.
- `root` (`string`): The project root.

Source: [ui/src/chat/headless/draft-scope.ts:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L21)

### `DraftScopeState`

Interface.

The draft's state, as [`DraftScopeStore`](https://zidane.si/docs/reference/ui-chat-headless.md#DraftScopeStore) holds it.

```ts
interface DraftScopeState
```

**Properties**

- `folder` (`string | null`): The local folder picked for the draft, `null` for none (or not local).
- `id` (`string`): The draft's id (what its terminals open under).
- `root` (`string | null`): The folder's project root once resolved.

Source: [ui/src/chat/headless/draft-scope.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L11)

### `DraftScopeStore`

Interface.

The draft's scope, readable (`get` returns the same state until it changes).

```ts
interface DraftScopeStore extends Readable<DraftScopeState>
```

**Properties**

- `get` (`() => DraftScopeState`, from `Readable`): Returns the current value.
- `publishFolder` (`(folder: string | null) => void`): The draft's local folder (`null` for folderless, server or machine drafts).
- `renew` (`() => void`): A send turned the draft into a session: the next draft starts fresh.
- `reset` (`() => void`): Back to a fresh draft with nothing cached (tests).
- `scope` (`() => DraftScope | null`): The draft's scope, `null` while it has no local folder or its root is still resolving.
- `subscribe` (`(onChange: () => void) => () => void`, from `Readable`): Registers a listener called after the value changes. Returns a function that removes the listener.

Source: [ui/src/chat/headless/draft-scope.ts:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L43)

### `DraftScopeStoreOptions`

Interface.

What [`createDraftScopeStore`](https://zidane.si/docs/reference/ui-chat-headless.md#createDraftScopeStore) asks the app.

```ts
interface DraftScopeStoreOptions
```

**Properties**

- `forget?` (`(draftId: string) => void`): A draft id is never shown again: forget what was kept for it (its layout record).
- `newId?` (`() => string`): A new draft id. Default: `crypto.randomUUID`, else a time-and-random id.
- `projectRoot` (`(folder: string) => Promise<string | null>`): The folder's project root (worktrees fold into their main checkout); `null` when unknown.
- `release?` (`(draftId: string) => void`): A draft id was replaced: release what was opened under it (its terminals stay with the old project).

Source: [ui/src/chat/headless/draft-scope.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/draft-scope.ts#L31)

### `DrainPlan`

Interface.

Streamed markdown released from a smooth-stream bucket, applied by `SessionStreamStore.applyDrainPlan`.

```ts
interface DrainPlan<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `childId?` (`string`): The subagent's child id, for a subagent's reply.
- `depth?` (`number`): The subagent's nesting depth.
- `ownerKey` (`string`): The owner it streamed under: `'parent'` or a subagent's child id.
- `sessionId` (`K`): The session the text belongs to.
- `text` (`string`): The text to reveal.
- `turnId?` (`string`): The turn the text belongs to.

Source: [ui/src/chat/headless/streams/pacer.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/pacer.ts#L28)

### `EffortPickerTarget`

Interface.

What the effort picker sets for a session's model.

```ts
interface EffortPickerTarget
```

**Properties**

- `enabled` (`Record<string, boolean>`): The options on now.
- `options` (`readonly ComposerModelOption[]`): The feature toggles it declares.
- `supportsReasoning` (`boolean`): The model has a reasoning effort knob.

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

### `ExchangeFoldStats`

Interface.

Counts shown on the summary line of a folded exchange.

```ts
interface ExchangeFoldStats
```

**Properties**

- `durationMs?` (`number`): Sum of known tool + thinking durations; undefined when nothing carries timing (replayed transcripts).
- `failed` (`number`): Tool calls that failed.
- `subagents` (`number`): Distinct worker (subagent) sessions whose rows folded.
- `thoughts` (`number`): Number of thinking segments folded.
- `tools` (`number`): Number of tool calls folded.

Source: [ui/src/chat/headless/transcript/rows.ts:274](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L274)

### `FileChip`

Interface.

A path in prose, as a chip shows it: its kind, name, icon or language letters, and tone.

```ts
interface FileChip
```

**Properties**

- `at?` (`PathPosition`): The line (and column, range) the text points at.
- `badge?` (`string`): Two-letter text badge used instead of an icon for languages that read better as text.
- `icon` (`string`): Iconify class, e.g. `i-ph-folder`.
- `kind` (`FileChipKind`): A file or a folder.
- `name` (`string`): What the chip shows: the last path segment (with trailing `/` stripped).
- `path` (`string`): Full text as written, without its position: for the tooltip and for opening.
- `tone?` (`string`): Accent hue token for the badge/icon: a `--zg-*` var name.

Source: [ui/src/chat/headless/file-chip.ts:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L23)

### `FileEntry`

Interface.

One row in the project file catalog. `path` is forward-slashed + relative to `cwd`.

```ts
interface FileEntry
```

**Properties**

- `kind` (`'dir' | 'file'`): Entry kind. Directories are derived from the discovered file paths
  (every ancestor of a listed file), so only directories that contain
  at least one non-ignored file appear — mirroring `git ls-files`
  semantics, which never lists empty or fully-ignored dirs.
- `name` (`string`): Basename — used for prefix ranking in the completion provider.
- `path` (`string`): Forward-slashed relative path from the discovery cwd. Stable across OSes. No trailing slash for dirs.
- `source` (`'git' | 'fs'`): Source — `git` when listed via `git ls-files`, `fs` from the walk fallback.

Source: [dist/media-type-BzRZ4FqT.d.ts:1535](https://github.com/Tahul/zidane/blob/main/dist/media-type-BzRZ4FqT.d.ts#L1535)

### `FoldActionItem`

Interface.

One overview line of a folded exchange: a tool call, a run of thoughts, a worker, or a note.

```ts
interface FoldActionItem
```

**Properties**

- `added?` (`number`): Edit line counts, shown after the label.
- `children?` (`FoldActionItem[]`): The calls this tool call made (its row's `children`), shown one step in under its line.
- `durationMs?` (`number`): How long the action took, in milliseconds, when known.
- `hint?` (`string`): Quiet context after the label: a file's directory, "+2" chained commands.
- `id` (`string`): Stable per action (its first row's id), so lists animate entries, not text changes.
- `kind` (`'note' | 'tool' | 'worker' | 'thought'`): What the line stands for: a `tool` call, consecutive `thought` segments, a `worker` (subagent), or a `note`.
- `label` (`string`): The overview: "Ran bun test", "Read select-stops.ts", "Thought".
- `model?` (`string`): A worker's model, shown as a badge on its line.
- `removed?` (`number`): Number of lines an edit removed, shown after the label.
- `resuming?` (`true`): While running: a call of a batch a durable run resumed after a process death.
- `startedAt?` (`number`): While running: when it started, for a live elapsed counter.
- `state` (`FoldActionState`): Progress of the action, shown as the line's status.
- `thoughts?` (`(Owned & { id: string; kind: 'thinking'; live?: boolean; text: string; thinkingMs?: number })[]`): The thinking rows a `thought` line stands for. Shown in the details.
- `title?` (`string`): Full payload for the tooltip (the whole command, the full path).
- `tool?` (`Owned & { approval?: ModelApproval; callId?: string; children?: readonly Owned & { kind: "tool"; id: string; name: string; displayName: string; formatted: ToolFormatLine | null; rawInput?: Record<string, unknown> | undefined; edit?: EditPayload | undefined; ... 11 more ...; children?: readonly (Owned & ...)[] | undefined; }[]; displayName: string; durationMs?: number; edit?: EditPayload; formatted: ToolFormatLine | null; id: string; kind: 'tool'; name: string; ok: boolean | null; parentId?: string; rawInput?: Record<string, unknown>; result: string | null; resultClipped?: boolean; resuming?: true; scriptProgress?: ScriptProgress; startedAt?: number; waitingFor?: { active: number; max: number } }`): What the details show.
- `waitingFor?` (`{ active: number; max: number }`): While waiting: the slots taken and the cap.
- `workerRows?` (`Row[]`): A worker's own rows (its lifecycle markers and everything it produced).

Source: [ui/src/chat/headless/transcript/fold-actions.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold-actions.ts#L25)

### `FrameScheduler`

Interface.

Frames and timers for the session stream store (see [`defaultFrameScheduler`](https://zidane.si/docs/reference/ui-chat-headless.md#defaultFrameScheduler)).

```ts
interface FrameScheduler
```

**Properties**

- `cancelFrame` (`(handle: unknown) => void`): Cancels a pending `FrameScheduler.frame` by its handle.
- `cancelTimeout` (`(handle: unknown) => void`): Cancels a pending `FrameScheduler.timeout` by its handle.
- `frame` (`(callback: (now: number) => void) => unknown`): Runs `callback` before the next paint, with the frame's time. Returns a handle, or `null` where there are no frames (the store falls back to `FrameScheduler.timeout`).
- `now` (`() => number`): The current time in milliseconds, on the clock frame callbacks receive (`performance.now()` in a browser).
- `timeout` (`(callback: () => void, ms: number) => unknown`): Runs `callback` after `ms` milliseconds. Returns a handle.

Source: [ui/src/chat/headless/streams/scheduler.ts:9](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/scheduler.ts#L9)

### `HostView`

Interface.

One host, as the kit's host parts show it.

```ts
interface HostView
```

**Properties**

- `error?` (`string`): Why the last connect failed.
- `home?` (`string`): The host's home folder, shown as `~` in its paths (`useDisplayPath`). Absent: its paths show in full.
- `id` (`string`): `'local'` for This computer, else the server's host id.
- `kind` (`'local' | 'server'`): This computer, or a saved server.
- `name` (`string`): The name the sidebar and picker show.
- `status` (`HostStatus`): The connection right now.
- `url?` (`string`): The server's URL.

Source: [ui/src/chat/headless/hosts.ts:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/hosts.ts#L17)

### `ImageModelRow`

Interface.

One image model, as the host lists it.

```ts
interface ImageModelRow
```

**Properties**

- `available` (`boolean`): The provider's credentials can generate with it.
- `isDefault?` (`boolean`): The model `generate_image` uses while no default is picked.
- `modelId` (`string`): The model's id at the provider.
- `modelName` (`string`): The model's display name.
- `providerKey` (`string`): The provider's key, for example `openai`.
- `providerLabel` (`string`): The provider's display name.
- `reason?` (`string`): Why it is not available.
- `references` (`boolean`): The model takes reference images.
- `transparency` (`boolean`): The model can return a transparent background.

Source: [ui/src/chat/headless/composer/models.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/models.ts#L51)

### `InboxSummary`

Interface.

What the Inbox badge reads of the conversation's pending requests.

```ts
interface InboxSummary
```

**Properties**

- `count` (`number`): How many requests wait.
- `head` (`InteractionRequest`): The oldest: the one the badge names.
- `live` (`boolean`): Raised by a run going on now, not rehydrated from an earlier process.

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

### `LazyList`

Interface.

A list read on demand.

```ts
interface LazyList<T>
```

**Type parameters**

- `T`

**Properties**

- `peek` (`() => readonly T[]`): The last list read (empty before the first); starts the first read of this scope.
- `read` (`() => Promise<readonly T[]>`): The list: the first read of a scope waits for it; later ones wait up to
  `FRESH_WAIT_MS` for a stale one's refetch, then answer the last.

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

### `ListableSession`

Interface.

The minimal session shape the list model needs. [`ChatSession`](https://zidane.si/docs/reference/ui-chat-headless.md#ChatSession) satisfies it.

```ts
interface ListableSession
```

**Properties**

- `createdAt` (`number`): Epoch milliseconds of creation. Used by the `createdTime` sort.
- `id` (`string`): Stable session id. Used as the row id.
- `status?` (`string`): Run state (`running`, `completed`, `error`, `idle`). Used for state grouping; missing counts as `idle`.
- `title?` (`string`): Session title. Used for alphabetical sorting and the title search.
- `updatedAt?` (`number`): Epoch milliseconds of the last activity. Used by the `recency` sort and date grouping.

Source: [ui/src/chat/headless/session-list.ts:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L17)

### `LiveBlockRun`

Interface.

A run this window started: running, or one that could not run.

```ts
interface LiveBlockRun
```

**Properties**

- `error?` (`string`): Why it could not run. Absent while it runs.
- `key` (`string`): The block's key (`blockRunKey`).
- `lines` (`readonly OutputLine[]`): Its last lines so far.
- `startedAt` (`number`): When it started (ms since epoch).

Source: [ui/src/chat/headless/block-runs.ts:27](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/block-runs.ts#L27)

### `LiveCostStatus`

Interface.

The cost pill's figure: settled, accrued and streaming.

```ts
interface LiveCostStatus extends ComposerCostStatus
```

**Properties**

- `estimated` (`boolean`): `true` while the total includes the streaming turn's running estimate.
- `label` (`string | null`, from `ComposerCostStatus`): `totalCost` formatted, `null` when zero.
- `runCount` (`number`, from `ComposerCostStatus`): Runs counted.
- `totalCost` (`number`, from `ComposerCostStatus`): Total in USD.

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

### `LiveStreamProgress`

Interface.

The streaming turn's live counters (`stream:progress`).

```ts
interface LiveStreamProgress
```

**Properties**

- `elapsedMs` (`number`): Time since the turn began.
- `estCostUsd?` (`number`): The turn's cost so far, estimated.
- `estimated` (`boolean`): `outputTokens` is an estimate.
- `outputTokens` (`number`): Output tokens so far.
- `turnId` (`string`): The streaming turn.

Source: [ui/src/chat/headless/composer/live-cost.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/live-cost.ts#L25)

### `LoadEarlierOptions`

Interface.

What `SessionStreams.loadEarlier` reports back.

```ts
interface LoadEarlierOptions
```

**Properties**

- `onSettled?` (`(prepended: boolean) => void`): Called once the fetch settles: `true` when the older page was spliced in.

Source: [ui/src/chat/headless/streams/session-streams.ts:52](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/session-streams.ts#L52)

### `ModelCatalogRow`

Interface.

One row of the catalog.

```ts
interface ModelCatalogRow
```

**Properties**

- `account?` (`{ active?: boolean; id: string; label: string }`): The provider's stored account this row runs on, when it has several. Absent: its only one.
- `contextWindow` (`number | null`): Context window in tokens, or `null` when unknown.
- `details?` (`readonly string[]`): Short facts shown beside the name, before the window (`ChatModel.details`).
- `modelId` (`string`): Model id within the provider.
- `modelName` (`string`): The catalog's display name (`Claude Opus 4.6`); the row shows its natural form (`Opus 4.6`).
- `modelProvider?` (`string`): Attribution for an aggregator's row (`anthropic` on OpenRouter).
- `offCatalog?` (`boolean`): A typed id the catalog does not know: used as typed, no metadata.
- `providerKey` (`string`): Key of the provider that serves the model.
- `providerLabel` (`string`): Provider name shown as the group heading.
- `references?` (`boolean`): An image model that takes reference images (to edit, or to match a style).
- `searchCorpus?` (`string`): Pre-lowercased search text. Default: provider key and label, account, id, name, attribution.
- `supportsReasoning` (`boolean`): The model supports reasoning effort.
- `transparency?` (`boolean`): An image model that can make a transparent background.
- `unavailable?` (`string`): Why the row cannot be picked with the current credentials. The row shows, greyed out, and picking it does nothing.

Source: [ui/src/chat/headless/composer/models.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/models.ts#L19)

### `ModelKnobs`

Interface.

An effort and the enabled options.

```ts
interface ModelKnobs
```

**Properties**

- `effort` (`'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'`): The reasoning effort.
- `options` (`Record<string, boolean>`): The enabled options (`{ fast: true }`).

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

### `ModelKnobsMemory`

Interface.

What the store holds.

```ts
interface ModelKnobsMemory
```

**Properties**

- `draft` (`{ effort?: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'; modelId: string; options?: Record<string, boolean> } | null`): The draft's own picks, until its chat is created (`clearDraft`).
- `effort` (`Record<string, ComposerEffort>`): The last effort per model.
- `options` (`Record<string, Record<string, boolean>>`): The last enabled options per model.

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

### `ModelKnobsStore`

Interface.

The remembered knobs.

```ts
interface ModelKnobsStore
```

**Properties**

- `clearDraft` (`() => void`): The draft became a chat: the next one starts from the defaults again.
- `draft` (`(modelId: string | null, configured: SessionKnobs | undefined, from?: ModelKnobsMemory) => ModelKnobs`): A new chat's starting effort and enabled options on `modelId` (see the header for the order).
- `load` (`() => Promise<void>`): Reads the remembered picks from the prefs, once.
- `pickDraftEffort` (`(modelId: string | null, effort: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive') => void`): A pick in the draft's pill: this chat starts on it, and it is remembered for the model.
- `pickDraftOptions` (`(modelId: string | null, options: Record<string, boolean>) => void`): A pick of options in the draft's pill.
- `remembered` (`(modelId: string | null, from?: ModelKnobsMemory) => ModelKnobs`): The last effort and enabled options used with `modelId` (medium, none, when never set).
- `rememberEffort` (`(modelId: string | null, effort: 'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive') => void`): Remembers an effort for a model.
- `rememberModelOptions` (`(modelId: string | null, options: Record<string, boolean>) => void`): Remembers the enabled options for a model.
- `reset` (`() => void`): Tests: forget everything, reload from the prefs on next use.
- `snapshot` (`() => ModelKnobsMemory`): The memory now (a new object on each change).
- `subscribe` (`(listener: () => void) => () => void`): Registers a listener called after the memory changes. Returns the unsubscribe.

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

### `ModelNames`

Interface.

How models and providers are named.

```ts
interface ModelNames
```

**Properties**

- `model` (`ModelNamer`): A model's name.
- `provider` (`(providerKey: string) => string`): A provider's label (`Anthropic`); its key when nothing names it.

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

### `ModelNamesProvider`

Interface.

A provider as the sign-in report lists it.

```ts
interface ModelNamesProvider
```

**Properties**

- `key` (`string`): The provider's key.
- `label` (`string`): Its label.

Source: [ui/src/chat/headless/composer/model-names.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-names.ts#L25)

### `ModelNamesStore`

Interface.

The live names.

```ts
interface ModelNamesStore
```

**Properties**

- `get` (`() => ModelNames`): The names now (a new object when the catalog changes).
- `subscribe` (`(listener: () => void) => () => void`): Registers a listener (the first one starts reading). Returns the unsubscribe.

Source: [ui/src/chat/headless/composer/model-names.ts:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-names.ts#L33)

### `ModelPickerPrefs`

Interface.

The model picker's preferences.

```ts
interface ModelPickerPrefs
```

**Properties**

- `showLegacy` (`boolean`): List every model a provider serves, not only the newest of each family (`currentModelKeys`).
- `version` (`1`): The stored shape's version.

Source: [ui/src/chat/headless/composer/model-picker-prefs.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-picker-prefs.ts#L11)

### `ModelPickerPrefsStore`

Interface.

The live preferences.

```ts
interface ModelPickerPrefsStore
```

**Properties**

- `get` (`() => ModelPickerPrefs`): The preferences now.
- `set` (`(update: Partial<ModelPickerPrefs>) => void`): Changes them (and stores them).
- `subscribe` (`(listener: () => void) => () => void`): Registers a listener called after they change. Returns the unsubscribe.

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

### `ModelPickRef`

Interface.

A model pick: provider, model and, when the provider has several, the stored account it runs on.

```ts
interface ModelPickRef
```

**Properties**

- `account?` (`string`): Id of the stored account the pick runs on. Only set when the provider has several.
- `modelId` (`string`): Model id within the provider.
- `providerKey` (`string`): Key of the provider, for example `anthropic`.

Source: [ui/src/chat/headless/composer/models.ts:9](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/models.ts#L9)

### `NewSessionDefaults`

Interface.

What a new session starts with when its draft picks nothing else.

```ts
interface NewSessionDefaults
```

**Properties**

- `account?` (`string | null`): The stored account the pick runs on (`null`: the active one).
- `agentId?` (`string | null`): The agent profile (`null`: the host's default).
- `knobs?` (`{ effort: string; options: Record<string, boolean> } | null`): The draft's effort and options (or the configured ones).
- `modelId?` (`string | null`): The model of the pick.
- `providerKey?` (`string | null`): The provider of the model pick.
- `untitled` (`string`): The title when neither the prompt nor a folder names one.

Source: [ui/src/chat/headless/send-flow.ts:141](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L141)

### `NewSessionRequest`

Interface.

The session [`newSessionRequest`](https://zidane.si/docs/reference/ui-chat-headless.md#newSessionRequest) asks the app to create.

```ts
interface NewSessionRequest
```

**Properties**

- `account?` (`string`): The account the pick runs on.
- `agentId?` (`string | null`): Its agent profile.
- `cwd?` (`string`): Its folder (absent: none).
- `effort?` (`string`): The reasoning effort it starts with.
- `environment?` (`EnvironmentRequest`): The environment it is created in.
- `hostId?` (`string`): The saved server the session runs on.
- `modelId?` (`string`): The model pick's model (set with `providerKey`).
- `modelOptions?` (`Record<string, boolean>`): The model options it starts with.
- `providerKey?` (`string`): The model pick's provider (set with `modelId`).
- `title` (`string`): Its title.

Source: [ui/src/chat/headless/send-flow.ts:157](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L157)

### `OpenFence`

Interface.

A streaming chunk's fence that has not closed yet, apart from the text before it.

```ts
interface OpenFence
```

**Properties**

- `before` (`string`): The markdown before the fence (may be empty).
- `code` (`string`): The code so far.
- `language` (`string`): The fence's language, as the parsed block names it (`plaintext` when the info string names none).

Source: [ui/src/chat/headless/markdown-chunks.ts:56](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/markdown-chunks.ts#L56)

### `OtherStreamSignal`

Interface.

A signal of a kind the store does not reduce (compaction pings, cache breaks …): ignored.

```ts
interface OtherStreamSignal
```

**Properties**

- `kind` (`string`, readonly): The signal's kind.

Source: [ui/src/chat/headless/streams/types.ts:81](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L81)

### `Owned`

Interface.

Every row carries the optional ownership metadata from its source
`StreamEvent`. `childId` + `depth` drive the subagent block grouping;
`turnId` drives select-turn mode highlighting.

```ts
interface Owned
```

**Properties**

- `childId?` (`string`): Id of the worker (subagent) session the row came from. Absent for the main session's own rows.
- `depth?` (`number`): Nesting level of the worker that owns the row: 1 for a direct subagent, 2 for one it spawned.
- `turnId?` (`string`): Id of the turn the row belongs to. Select-turn mode highlights rows by it.

Source: [ui/src/chat/headless/transcript/rows.ts:16](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L16)

### `PairingResult`

Interface.

The outcome of [`pairToolEvents`](https://zidane.si/docs/reference/ui-chat-headless.md#pairToolEvents).

```ts
interface PairingResult
```

**Properties**

- `consumedResultIndices` (`ReadonlySet<number>`): Indices of result events that were paired, so a renderer does not show them again on their own.
- `pairings` (`ReadonlyMap<number, ToolPairing>`): Pairings keyed by the index of the `tool` event that made the call.

Source: [ui/src/chat/headless/transcript/pairing.ts:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/pairing.ts#L23)

### `PathResolver`

Interface.

The chip answers of one host.

```ts
interface PathResolver
```

**Properties**

- `dispose` (`() => void`): Stops following the host's changes.
- `get` (`(cwd: string, text: string) => ChipResolution`): The current answer for `text` in `cwd`.
- `request` (`(cwd: string, text: string) => void`): Asks for `text` in `cwd` unless an answer is fresh or on the wire.
- `resolveNow` (`(cwd: string, text: string) => Promise<ChipResolution>`): Asks again now, bypassing the cache (a click: the file may exist since).
- `subscribe` (`(cwd: string, text: string, listener: () => void) => () => void`): Calls `listener` when the answer for `text` in `cwd` changes. Returns the unsubscribe.

Source: [ui/src/chat/headless/path-resolver.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/path-resolver.ts#L31)

### `PathResolverOptions`

Interface.

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

```ts
interface PathResolverOptions
```

**Properties**

- `beginWork?` (`() => () => void`): Marks a first ask (an answer may resize the chip); the returned function ends it (`beginChipWork`).

Source: [ui/src/chat/headless/path-resolver.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/path-resolver.ts#L25)

### `ProjectInSpace`

Interface.

A project as one space lists it: its path (`projectPathOf`), the host it is on, the space.

```ts
interface ProjectInSpace
```

**Properties**

- `hostId?` (`string`): A remote host's id; absent for this machine.
- `path` (`string`): The project's folder (`projectPathOf`).
- `repoKey?` (`string`): Its repository, when its group also lists the repository's sessions on other machines (`isProjectMember`).
- `spaceId?` (`string`): The space it is listed in (an unknown or absent id is the default space).

Source: [ui/src/chat/headless/sidebar/directory.ts:62](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L62)

### `PromptOrigin`

Interface.

A prompt's origin, as the transcript reads it. Mirrors zidane's `TextOrigin` (`src/text-origin.ts`), without its `messageId`.

```ts
interface PromptOrigin
```

**Properties**

- `kind` (`'user' | 'event' | 'signal'`): 'user': the session's user, through another surface; 'signal': someone else (a channel participant); 'event': something that happened (orchestration, a webhook).
- `sender?` (`{ id: string; name?: string }`): Who, when known: a provider id and a display name.
- `source` (`string`): Where it came from: 'slack', 'github', 'orchestration'…

Source: [ui/src/chat/headless/prompt-origin.ts:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/prompt-origin.ts#L14)

### `Readable`

Interface.

The shape every chat host exposes its data in: read the current value and subscribe to changes.

```ts
interface Readable<T>
```

**Type parameters**

- `T`

**Properties**

- `get` (`() => T`): Returns the current value.
- `subscribe` (`(onChange: () => void) => () => void`): Registers a listener called after the value changes. Returns a function that removes the listener.

Source: [ui/src/chat/headless/store.ts:10](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/store.ts#L10)

### `ReferenceStore`

Interface.

The reference cache of one host.

```ts
interface ReferenceStore
```

**Properties**

- `dispose` (`() => void`): Stops following the host's changes and drops pending saves.
- `loadProviders` (`(cwd: string, peek: boolean) => void`): Asks for `cwd`'s providers unless already asked (`peek`: only what the host has built).
- `providers` (`(cwd: string) => readonly ReferenceProviderWire[]`): The providers for `cwd` (`''`: user-level), empty until known.
- `requestView` (`(cwd: string, providerId: string, key: string) => void`): Asks for a key's view unless it is fresh or already asked.
- `subscribeProviders` (`(cwd: string, listener: () => void) => () => void`): Calls `listener` when `cwd`'s providers change. Returns the unsubscribe.
- `subscribeView` (`(cwd: string, providerId: string, key: string, listener: () => void) => () => void`): Calls `listener` when a key's view changes. Returns the unsubscribe.
- `view` (`(cwd: string, providerId: string, key: string) => ReferenceViewEntry | undefined`): The cached view of a key: `undefined` while unknown.

Source: [ui/src/chat/headless/reference-store.ts:59](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/reference-store.ts#L59)

### `ReferenceStoreOptions`

Interface.

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

```ts
interface ReferenceStoreOptions
```

**Properties**

- `beginWork?` (`() => () => void`): Marks a lookup that may resize a chip; the returned function ends it (`beginChipWork`).
- `storage?` (`Storage | null`): Where the caches persist across reloads. Default: `localStorage` when there is one; `null`: memory only.

Source: [ui/src/chat/headless/reference-store.ts:51](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/reference-store.ts#L51)

### `ReferenceViewEntry`

Interface.

A view as cached: `null` names nothing; `at` is when it was resolved (0: stale).

```ts
interface ReferenceViewEntry
```

**Properties**

- `at` (`number`): When it was resolved, epoch ms (`0`: stale).
- `view` (`ExtensionReferenceView | null`): The view; `null` when the key names nothing.

Source: [ui/src/chat/headless/reference-store.ts:43](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/reference-store.ts#L43)

### `RunEstimatesRow`

Interface.

What the store reads of a session row (`noteRows`).

```ts
interface RunEstimatesRow
```

**Properties**

- `id` (`string`): The session.
- `runEstimates?` (`readonly RunEstimateView[]`): The estimates of its runs in progress.
- `status` (`string`): Its run state: only a `running` row's estimates count.

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

### `RunEstimatesStore`

Interface.

Every session's run estimates, outside React.

```ts
interface RunEstimatesStore
```

**Properties**

- `get` (`(sessionId: string) => readonly RunEstimateView[]`): The session's estimates, the session's own run first; the same empty list when it has none.
- `noteRows` (`(rows: readonly RunEstimatesRow[]) => void`): The session list's word on its running sessions' estimates (a window that missed the signals).
- `start` (`() => () => void`): Follow the signals; returns the stop. Call once at boot.
- `subscribe` (`(sessionId: string, listener: () => void) => () => void`): Fires when the session's estimates change.

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

### `RunMeter`

Interface.

The run counters of every session.

```ts
interface RunMeter
```

**Properties**

- `forget` (`(sessionId: string) => void`): Drops a deleted session's counters.
- `generation` (`(sessionId: string) => number`): The session's run generation, to hand back to `settleCost` / `noteProgress`.
- `get` (`(sessionId: string) => RunMeterState`): A session's counters now.
- `handle` (`(signal: { kind: string; sessionId?: string }) => void`): Follows one stream signal. Other kinds are ignored.
- `noteProgress` (`(sessionId: string, generation: number, progress: { outputTokens: number; startedAt: number }) => void`): A run this window joined midway, as its host counts it; dropped when the run changed while it was read.
- `noteSeen` (`(sessionId: string) => void`): A running run with no start known yet counts from now.
- `noteStarts` (`(rows: readonly RunMeterRow[]) => void`): The session list's run starts: a window that missed a `run:start` times the run from its real start.
- `session` (`(sessionId: string) => Readable<RunMeterState>`): A session's counters as a store (one per session, the same each call).
- `settleCost` (`(sessionId: string, generation: number) => void`): A cost read issued while idle settled every turn: zero the accrual, unless a newer run started since.

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

### `RunMeterRow`

Interface.

A session row's word on its run (the session list's `runStartedAt`).

```ts
interface RunMeterRow
```

**Properties**

- `id` (`string`): The session.
- `runStartedAt?` (`number`): When its run began (epoch ms).
- `status` (`string`): Its status (`running` counts).

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

### `RunMeterState`

Interface.

One session's run counters.

```ts
interface RunMeterState
```

**Properties**

- `accruedCost` (`number`): Σ `turn:end` usage cost since the last cost read that settled it (`settleCost`).
- `generation` (`number`): Bumped at each run's start and end: a read issued during one run must
  not land on the next state (settle a newer run's accrual, seed a run
  that has ended).
- `outputTokens` (`number`): Output tokens of the run's settled parent turns: the host's count from
  each `turn:end` (`runOutputTokens`) or the joined run's read, summed
  here only for an older host.
- `progress` (`LiveStreamProgress | null`): The streaming parent turn's live counters, `null` between turns.
- `startedAt` (`number | null`): When the run began: the host's `run:start` stamp, else its saved run
  record (a session row's `runStartedAt`, or the read of a run this window
  joined mid-way), else when this window first saw it (an older host, which
  sends neither).
- `startedFrom` (`'host' | 'record' | 'seen' | null`): Where `startedAt` came from: the host's own signal wins, the run's record corrects a first sighting.

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

### `SelectStops`

Interface.

The turns select-turn mode can stop on, and how any turn id maps to its stop.

```ts
interface SelectStops
```

**Properties**

- `order` (`string[]`): Stop ids in transcript order; the cursor walks this.
- `stopOf` (`ReadonlyMap<string, string>`): Any turn id a row carries → the stop it belongs to.

Source: [ui/src/chat/headless/transcript/select-stops.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/select-stops.ts#L20)

### `SendAttachment`

Interface.

An attachment as the composer staged it: `dataUrl` is the paste, drop or picker URL.

```ts
interface SendAttachment
```

**Properties**

- `dataUrl` (`string`): The `data:` URL the composer built.
- `mediaType` (`string`): MIME type.
- `name` (`string`): File name.
- `original?` (`ChatAttachmentOriginal`): The file as picked, when the composer converted it (`ChatAttachment.original`).
- `size` (`number`): Size in bytes.

Source: [ui/src/chat/headless/send-flow.ts:19](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L19)

### `SendDraft`

Interface.

Where the new-chat draft runs, as [`newSessionRequest`](https://zidane.si/docs/reference/ui-chat-headless.md#newSessionRequest) reads it.

```ts
interface SendDraft
```

**Properties**

- `environment` (`DraftEnvironment | null`): The draft's environment pick (`null`: the default).
- `environmentChoices` (`readonly EnvironmentDescriptor[]`): The environment kinds the draft can pick.
- `folderPath` (`string | null`): `null`: no folder picked yet (sending is an implicit "just chat"); `''`: none.
- `remoteFolder` (`string | null`): The server's folder (`null`: its first root).
- `server?` (`{ id: string }`): The saved server the draft runs on.

Source: [ui/src/chat/headless/send-flow.ts:127](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L127)

### `SendFlowDeps`

Interface.

What the send flow sends through and writes to.

```ts
interface SendFlowDeps
```

**Properties**

- `host` (`Pick<ChatHost, 'send' | 'shell' | 'providerReady'>`): The chat host's send, `!` shell and provider check.
- `provider?` (`{ known(): boolean | null; missing(): void; ready(): void }`): The local provider state: what is known, and what the flow learned. Absent: never checked.
- `streams` (`{ appendErrorEvent(sessionId: string, text: string): void; dropPromptPreviews(sessionId: string, text: string): void; rememberPromptPreviews(sessionId: string, text: string, attachments: readonly ChatAttachment[]): void }`): The transcript's writes for a queued prompt and the error rows.
- `createSession` (`(text: string) => Promise<{ id: string; provisioning?: boolean }>`): Creates the session from the draft; `provisioning` while its environment is not ready. Rejects when it can't.
- `draftError?` (`(text: string) => void`): Shows why the draft could not take the send (no session to hold an error row).
- `enqueue?` (`(sessionId: string, text: string, options: QueueAddOptions) => Promise<unknown>`): Queues the prompt into the session's queue. Absent: a prompt sent mid-run goes straight to the host.
- `isCommand?` (`(text: string) => Promise<boolean>`): Whether the text runs one of the session's `/` commands (they show their own header: no echo).
- `remember?` (`(sessionId: string, text: string) => void`): Adds the prompt to the session's history.
- `reveal?` (`() => void`): Brings what was just sent into view (called as the send starts).
- `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/headless/send-flow.ts:251](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L251)

### `SendInput`

Interface.

What the composer sends to `ChatHost.send`.

```ts
interface SendInput
```

**Properties**

- `activatedSkills?` (`readonly string[]`): Skills picked through `/` completion, activated before the run.
- `attachments?` (`readonly ChatAttachment[]`): Files attached to the prompt.
- `delivery?` (`MessageDelivery`): Set when a run works in the session: `steer` hands the prompt to the run (the model reads it after its
  current step), `queue` holds it until the run ends. A run that ends first gets it as a new prompt.
- `echo?` (`boolean`): `false`: a `/` command that shows its own header, so the prompt is not echoed. Default: echoed.
- `keepDraft?` (`boolean`): Sent from outside the composer (a retry, a palette prompt): the shared draft stays.
- `model?` (`string`): `provider/model` or a bare model id, as the host understands it.
- `prompt` (`string`): The prompt text.
- `refs?` (`readonly PromptSegmentRef[]`): The completions the prompt used (skills, files, chats), for its echo's chips.
- `sessionId` (`string`): Id of the session to send to.
- `thinking?` (`'off' | 'minimal' | 'low' | 'medium' | 'high'`): Reasoning effort for this prompt. `off` turns extended thinking off.

Source: [ui/src/chat/headless/host.ts:166](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L166)

### `SendPromptAttachment`

Interface.

A prompt attachment on the wire: raw base64, no `data:` prefix.

```ts
interface SendPromptAttachment
```

**Properties**

- `data` (`string`): The bytes, base64.
- `mediaType` (`string`): MIME type.
- `name` (`string`): File name.
- `original?` (`{ data: string; mediaType: string; name: string }`): The file as picked, when `data` is a converted copy: the host saves these bytes.

Source: [ui/src/chat/headless/send-flow.ts:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L33)

### `SendRequest`

Interface.

One send from the composer.

```ts
interface SendRequest
```

**Properties**

- `activatedSkills?` (`readonly string[]`): The skills picked through `/` completion.
- `attachments` (`readonly SendAttachment[]`): What the composer staged with it.
- `cwd` (`string`): The folder the prompt runs in (`''`: none), for the provider check and command lookup.
- `delivery?` (`MessageDelivery`): While a run works: steer the prompt into it, or queue it. Absent: the host's setting.
- `keepDraft?` (`boolean`): Sent from outside the composer: the shared draft stays.
- `remote` (`boolean`): Runs on a server, on its credentials: no local provider check.
- `running` (`boolean`): A run is in flight: the prompt goes through the queue, into the run or held (`delivery`).
- `sessionId` (`string | null`): The conversation, `null` for the new-chat draft (created first).
- `text` (`string`): The prompt.

Source: [ui/src/chat/headless/send-flow.ts:229](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/send-flow.ts#L229)

### `SessionActivity`

Interface.

What a session's run is doing, as its row says it.

```ts
interface SessionActivity
```

**Properties**

- `phase` (`'thinking' | 'writing' | 'compacting' | 'retrying'`): What the model does when no tool runs.
- `run` (`boolean`): Inside a run (a compaction can also happen on its own, `/compact`).
- `tools` (`readonly { callId: string; label: string; title?: string }[]`): Tool calls still running, oldest first: the row names the newest.

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

### `SessionActivityStore`

Interface.

Every session's activity, outside React.

```ts
interface SessionActivityStore
```

**Properties**

- `get` (`(sessionId: string) => SessionActivity | null`): The session's activity, `null` when nothing of a run was seen (or it ended).
- `start` (`() => () => void`): Follow the signals; returns the stop. Call once at boot.
- `subscribe` (`(sessionId: string, listener: () => void) => () => void`): Fires only when what the session's row shows changes.

Source: [ui/src/chat/headless/sidebar/activity.ts:128](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/activity.ts#L128)

### `SessionBadgesEntry`

Interface.

One session's badges as a row shows them.

```ts
interface SessionBadgesEntry
```

**Properties**

- `badges` (`readonly SessionBadgeEntry[]`): The badges in the host's order.
- `grewAt` (`Readonly<Record<string, number>>`): Per kind: when a read brought more of its artifacts than the one before (`Date.now()`; absent for never).

Source: [ui/src/chat/headless/sidebar/badges.ts:24](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/badges.ts#L24)

### `SessionBadgesSource`

Interface.

Where the badges come from.

```ts
interface SessionBadgesSource
```

**Properties**

- `batchMax?` (`number`): The most sessions one read asks for. Defaults to 100.
- `onArtifactsChanged?` (`(listener: (sessionId: string) => void) => () => void`): Fires with a session whose artifacts were recorded or changed.
- `onRegistryChanged?` (`(listener: () => void) => () => void`): Fires when the badge kinds may have changed (extensions reloaded or built).
- `read` (`(sessionIds: readonly string[]) => Promise<Readonly<Record<string, readonly SessionBadgeEntry[]>>>`): Read the badges of up to `batchMax` sessions at once, keyed by session id.
- `shown?` (`(sessionIds: readonly string[]) => void`): Hears every session a row shows, once per change of the set (after the commit). Absent: not told.

Source: [ui/src/chat/headless/sidebar/badges.ts:32](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/badges.ts#L32)

### `SessionBadgesStore`

Interface.

Every session's badges, outside React.

```ts
interface SessionBadgesStore
```

**Properties**

- `apply` (`(sessionId: string, badges: readonly SessionBadgeEntry[], now?: number) => void`): Apply a read's answer (exposed for tests and for apps that push badges).
- `get` (`(sessionId: string) => SessionBadgesEntry | null`): The session's badges, `null` until read.
- `has` (`(sessionId: string) => boolean`): The session's badges were read.
- `request` (`(sessionId: string) => void`): Ask for the session's badges; the asks of one tick go out together.
- `start` (`() => () => void`): Follow the source's change feeds; returns the stop. Call once at boot.
- `subscribe` (`(sessionId: string, listener: () => void) => () => void`): Fires when the session's badges change.

Source: [ui/src/chat/headless/sidebar/badges.ts:46](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/badges.ts#L46)

### `SessionDirectory`

Interface.

The session directory: its state, notifications and views, and the actions on them.

```ts
interface SessionDirectory<S extends SidebarListSession, C = unknown>
```

**Type parameters**

- `S` (`extends SidebarListSession`)
- `C` (default `unknown`)

**Properties**

- `notifications` (`SessionNotificationStore`): What finished runs left on sessions not open.
- `saveViewAsSpace?` (`(name: string) => Promise<SidebarSpace>`): Saves the shown space's view as a new user space (its query, grouping and sort) and shows it.
  The query is `viewQuery`'s (`zidane/chat/pure`): the space's membership, then the project,
  activity, agent and contributed filters. Rejects with a `SessionQueryError` (nothing saved)
  when that query is not valid (too deep, too many nodes or values), and with `saveSpace`'s error.
  Undefined without `saveSpace`. The sidebar's `useSaveViewAsSpace` names the space and words a failure.
- `state` (`Readable<SessionDirectoryState<S>>`): The state, one snapshot per change.
- `views` (`SidebarViews`): The views and the shown space.
- `archiveMany` (`(sessionIds: readonly S['id'][]) => Promise<void>`): Archives sessions, then re-reads once.
- `attachContributions` (`(contributions: Readable<SidebarContributions>) => () => void`): Follow an extensions host's sidebar contributions from now on (replacing any); returns the detach.
- `create` (`(input: C & { spaceId?: string }) => Promise<S>`): Create a session in the shown space (unless the input names one) and list it.
- `dismissHostNotice` (`() => void`): Hides the host notice.
- `drop` (`(sessionId: S['id']) => Promise<SessionRemoval>`): Delete one session without re-reading; the caller refreshes.
- `listProjectSessions` (`(project: ProjectInSpace) => Promise<S[]>`): A project's sessions in its space (every archive state), read fresh from its host.
- `moveSpace` (`(spaceId: string, delta: -1 | 1) => void`): Moves a space one place left (-1) or right (1) in the switcher.
- `refresh` (`() => Promise<void>`): Re-read every host.
- `removeMany` (`(sessionIds: readonly S['id'][]) => Promise<{ kept: number; reason?: string }>`): Delete sessions, then re-read; resolves to how many kept their environment.
- `rename` (`(sessionId: S['id'], title: string) => Promise<void>`): Renames a session, then re-reads.
- `select` (`(sessionId: S['id'] | null) => void`): Open a session (or none) and clear its notification and the host notice.
- `setActive` (`(sessionId: S['id'] | ((current: S['id'] | null) => S['id'] | null) | null) => void`): Set the open session without clearing anything (window routing, deletes).
- `setActiveSpace` (`(spaceId: string) => void`): Shows another space and reopens the conversation last open there, when it is still listed in it;
  else the open session closes when it belongs elsewhere.
- `setArchive` (`(archive: SessionArchiveFilter) => void`): The list's archive filter changed (re-reads when it did).
- `setArchived` (`(sessionId: S['id'], archived: boolean) => Promise<void>`): Archives or restores a session, then re-reads.
- `setFavorite` (`(sessionId: S['id'], favorite: boolean) => Promise<void>`): Stars or unstars a session at once; a failed write puts it back.
- `setProjectSpace` (`(project: ProjectInSpace, spaceId: string) => Promise<number>`): Move a project's sessions to another space; resolves to how many moved.
- `setSessionSpace` (`(sessionId: S['id'], spaceId: string) => Promise<void>`): Moves a session to a space, then re-reads.
- `setSpaceHidden` (`(spaceId: string, hidden: boolean) => void`): Hides a space from the switcher or shows it again; hiding the shown space shows the default one.
- `start` (`() => () => void`): Start following hosts, signals and settings; returns the stop.
- `stepSpace` (`(delta: -1 | 1) => boolean`): Step to the next or previous space, wrapping at either end; false with spaces off or only one space.

Source: [ui/src/chat/headless/sidebar/directory.ts:226](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L226)

### `SessionDirectoryOptions`

Interface.

Options of [`createSessionDirectory`](https://zidane.si/docs/reference/ui-chat-headless.md#createSessionDirectory): the ports it reads and acts through.

```ts
interface SessionDirectoryOptions<S extends SidebarListSession, P, C = unknown>
```

**Type parameters**

- `S` (`extends SidebarListSession`)
- `P`
- `C` (default `unknown`)

**Properties**

- `archive?` (`SessionArchiveFilter`): The archive filter the list shows (the shown space's view).
- `changedDebounceMs?` (`number`): Debounce of change signals. Defaults to 300 ms.
- `contributions?` (`Readable<SidebarContributions>`): What the extensions contribute to the sidebar (`sidebarContributionsOf(host.items)`). An app whose
  extensions host comes later attaches it then (`attachContributions`).
- `idle?` (`{ cancel(handle: number): void; request(run: () => void): number }`): Schedules prewarm reads; defaults to `requestIdleCallback` with a timer fallback.
- `pinned?` (`() => Iterable<S['id']>`): Session keys kept in the transcript cache besides the prewarmed ones (`pinnedSessions`).
- `pinnedSession?` (`S['id'] | null`): A window that only ever shows this session (its other sessions are never opened).
- `servers` (`Readable<readonly DirectoryServer[]>`): The remote hosts listed next to this machine.
- `sessions` (`SessionDirectorySource<S, C>`): The sessions transport (`ChatHost.sessions`).
- `settings` (`Readable<DirectorySettings>`): Spaces and orchestration settings.
- `signals?` (`{ onHostRemoved?(listener: (removed: { hostId: string; notice: string | null; sessionIds: readonly S['id'][] }) => void): () => void; onRunEnd?(listener: (sessionId: S['id'], ok: boolean) => void): () => void; onRuntime?(listener: (connected: boolean) => void): () => void }`): Live signals; each one left out is not followed.
- `streams` (`SessionDirectoryStreams<S['id'], P>`): The stream store it keeps in step.
- `views` (`SidebarViews`): The views and the shown space.
- `isRunning` (`(sessionId: S['id']) => Promise<boolean | null | undefined>`): Ask whether a session runs; `false` only when the host is sure it doesn't.
- `loadEvents` (`(sessionId: S['id'], options?: { prewarm?: boolean }) => Promise<P>`): Load a session's latest transcript page.
- `onError?` (`(error: unknown) => void`): A refresh failed.
- `onListed?` (`(rows: readonly S[]) => void`): A refresh is about to list these rows (an app's per-row bookkeeping, before they render).
- `onRemoved?` (`(sessionId: S['id']) => void`): A session was deleted: drop what the app keeps for it (panels, layouts).
- `saveSpace?` (`(space: SidebarSpace) => Promise<void>`): Adds a space to the user's list (the settings' `spaceList`). Absent: a view can't be saved as a space.
- `serverOf` (`(sessionId: S['id']) => string | null`): The remote host a session lives on, `null` on this machine.

Source: [ui/src/chat/headless/sidebar/directory.ts:144](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L144)

### `SessionDirectorySource`

Interface.

The sessions transport the directory reads and acts through (`ChatHost.sessions`).

```ts
interface SessionDirectorySource<S extends SidebarListSession, C = unknown>
```

**Type parameters**

- `S` (`extends SidebarListSession`)
- `C` (default `unknown`)

**Properties**

- `create?` (`(input: C) => Promise<S>`): Creates a session and resolves with its row.
- `onChanged?` (`(listener: (sessionId: S['id']) => void) => () => void`): Fires (possibly in bursts) with a session whose row changed.
- `onFacets?` (`(listener: (sessionId: S['id'], facets: Readonly<Record<string, unknown>>) => void) => () => void`): Fires with a session's facets when the extensions computed new ones (`sessions:facets`): every
  value, keyed `<extensionId>.<key>`. Absent: facets change only with a re-read.
- `query` (`(filter: { archive: SessionArchiveFilter; hostId?: string }) => Promise<readonly S[]>`): One host's sessions under the archive filter; `hostId` absent = this machine.
- `remove?` (`(sessionId: S['id']) => Promise<void | SessionRemoval>`): Resolves to `{ kept: true }` when the session's environment stayed on disk.
- `rename?` (`(sessionId: S['id'], title: string) => Promise<void>`): Sets a session's title.
- `setArchived?` (`(sessionId: S['id'], archived: boolean) => Promise<void>`): Archives or restores a session.
- `setFavorite?` (`(sessionId: S['id'], favorite: boolean) => Promise<void>`): Stars or unstars a session.
- `setSpace?` (`(sessionId: S['id'], spaceId: string) => Promise<void>`): Moves a session to a space.

Source: [ui/src/chat/headless/sidebar/directory.ts:77](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L77)

### `SessionDirectoryState`

Interface.

The directory's state as one snapshot: a new object whenever any field changes.

```ts
interface SessionDirectoryState<S extends SidebarListSession>
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Properties**

- `activeSessionId` (`S['id'] | null`): The open session.
- `activeSpace` (`SidebarSpace`): The space shown (the default one while spaces are off).
- `allSessions` (`readonly S[]`): Every listed session, unfiltered (the archive filter is the host's).
- `contributions` (`SidebarContributions`): What the extensions contribute to the sidebar.
- `hiddenSpaces` (`readonly SidebarSpace[]`): The spaces the user hid from the switcher on this device (`setSpaceHidden`), in `spaces` order:
  what the switcher's Hidden spaces menu offers to show again. A space hidden in the settings'
  space list (`hidden: true`) is not in it: the settings show it again.
- `hostNotice` (`string | null`): Why the open session closed (its host was removed), until dismissed or another opens.
- `spaces` (`readonly SidebarSpace[]`): Every space, the default one always present: the user's in order, then the extensions'.
- `spaceSlide` (`{ direction: 'next' | 'prev'; spaceId: string } | null`): The last space switch, for the list's slide.
- `spacesOn` (`boolean`): Spaces are on.
- `switcherSpaces` (`readonly SidebarSpace[]`): The spaces the switcher shows, in its order (the user's arrangement on top of `spaces`).

Source: [ui/src/chat/headless/sidebar/directory.ts:198](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L198)

### `SessionDirectoryStreams`

Interface.

The slice of the session stream store the directory keeps in step.

```ts
interface SessionDirectoryStreams<K extends string, P>
```

**Type parameters**

- `K` (`extends string`)
- `P`

**Properties**

- `captureRunState` (`() => () => boolean`): A snapshot of the run state; the returned check says whether it still holds.
- `confirmIdle` (`(sessionId: K) => void`): The host confirmed the session is idle: end a run whose end was missed.
- `dropAll` (`() => void`): Drop every stream (a runtime switch).
- `evictExcept` (`(keep: ReadonlySet<K>) => void`): Drop every cached transcript except these.
- `hasEvents` (`(sessionId: K) => boolean`): The session's transcript is cached.
- `markRunning` (`(sessionId: K) => void`): A row says the session runs: show it running.
- `peekRunning` (`(sessionId: K | null) => boolean`): Whether a run streams for the session here.
- `peekRunSeq` (`(sessionId: K | null) => number`): The session's run counter (bumps on every run start).
- `reset` (`(sessionId: K) => void`): Drop one session's stream (deleted).
- `setEventsPage` (`(sessionId: K, page: P) => void`): Cache a loaded transcript page.

Source: [ui/src/chat/headless/sidebar/directory.ts:102](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L102)

### `SessionFallbackModel`

Interface.

The model serving a run after it fell back from the one picked.

```ts
interface SessionFallbackModel
```

**Properties**

- `model` (`string`): The model id.
- `provider` (`string`): The provider key.

Source: [ui/src/chat/headless/streams/types.ts:7](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L7)

### `SessionHistory`

Interface.

The window's page history, outside React.

```ts
interface SessionHistory<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `state` (`Readable<SessionHistoryState<K>>`): The pages and the cursor.
- `back` (`(canOpen?: (id: K) => boolean) => SessionHistoryPage<K> | undefined`): Moves the cursor back to the page `peek` finds and returns it (`undefined`: nowhere to go).
- `forget` (`(id: K) => void`): Removes a session from every entry (deleted).
- `forward` (`(canOpen?: (id: K) => boolean) => SessionHistoryPage<K> | undefined`): Moves the cursor forward to the page `peek` finds and returns it (`undefined`: nowhere to go).
- `load` (`() => Promise<void>`): Reads the store once and merges it in (resolves at once without a store).
- `peek` (`(direction: SessionHistoryDirection, canOpen?: (id: K) => boolean) => SessionHistoryPage<K> | undefined`): The page one step back or forward, or `undefined` when there is none. Reads only.
- `replace` (`(page: SessionHistoryPage<K>) => void`): The entry on show becomes `page` (no-op with no entry).
- `visit` (`(page: SessionHistoryPage<K>) => void`): Records a page shown other than by `back` / `forward`.

Source: [ui/src/chat/headless/sidebar/history.ts:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L48)

### `SessionHistoryOptions`

Interface.

Options of [`createSessionHistory`](https://zidane.si/docs/reference/ui-chat-headless.md#createSessionHistory).

```ts
interface SessionHistoryOptions
```

**Properties**

- `limit?` (`number`): The most entries kept (default [`SESSION_HISTORY_LIMIT`](https://zidane.si/docs/reference/ui-chat-headless.md#SESSION_HISTORY_LIMIT)).
- `onError?` (`(what: 'save' | 'load', error: unknown) => void`): A store read or write failed.
- `store?` (`SessionHistoryStore`): Where the history persists; absent, it lasts as long as the window.

Source: [ui/src/chat/headless/sidebar/history.ts:73](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L73)

### `SessionHistoryState`

Interface.

The history as it is kept: its pages, oldest first, and the cursor.

```ts
interface SessionHistoryState<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `entries` (`readonly SessionHistoryPage<K>[]`): The pages, oldest first.
- `index` (`number`): The cursor: the entry on show (`-1` while there is none).

Source: [ui/src/chat/headless/sidebar/history.ts:29](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L29)

### `SessionHistoryStore`

Interface.

Where the history persists (the desktop app: main's database).

```ts
interface SessionHistoryStore
```

**Properties**

- `load` (`() => Promise<unknown>`): The saved history, as stored (checked by [`parseSessionHistory`](https://zidane.si/docs/reference/ui-chat-headless.md#parseSessionHistory)).
- `save` (`(state: SessionHistoryState) => Promise<unknown>`): Saves the history.

Source: [ui/src/chat/headless/sidebar/history.ts:37](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L37)

### `SessionListOptions`

Interface.

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

```ts
interface SessionListOptions<S>
```

**Type parameters**

- `S`

**Properties**

- `calendar?` (`CalendarOptions`): Pin the zone and locale of date buckets (pages rendered on a server and in browsers).
- `collapsedGroups?` (`ReadonlySet<string>`): Header ids whose sessions are hidden.
- `compare?` (`(a: S, b: S) => number`): Orders sessions in place of `sortBy` (a query sort an extension or a space defines).
- `groupBy?` (`SessionGroupBy`, default `'none'`): How to group sessions.
- `idPrefix?` (`string`): Prefix for row ids, when several lists share one id space (one per host).
- `isFavorite?` (`(session: S) => boolean`): Favorited sessions: shown first, under their own header.
- `isGitRepo?` (`(session: S) => boolean`): The session's folder is a git repository.
- `labels?` (`Pick<{ 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 }, 'today' | 'yesterday' | 'months' | 'chats' | 'favorites' | 'stateRunning' | 'stateCompleted' | 'stateError' | 'stateIdle'>`): Strings for group headings and date buckets. Missing keys fall back to the default chat labels.
- `now?` (`number`): Clock, for date buckets (tests pin it).
- `pinnedProjects?` (`readonly string[]`): Project grouping: folders whose groups lead the list (under Favorites,
  above Chats) in this order, whatever their activity.
- `project?` (`(session: S) => string | null | undefined`): A session's folder for project grouping; none puts it in the "Chats" bucket.
- `projectCap?` (`number`): Sessions shown per project group before "show more" (default 5).
- `showMoreExpanded?` (`ReadonlySet<string>`): Header ids whose capped group shows every session.
- `sortBy?` (`SessionSortBy`, default `'recency'`): How to order sessions inside a group.

Source: [ui/src/chat/headless/session-list.ts:63](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L63)

### `SessionNotificationStore`

Interface.

The notifications by session, subscribed to per session.

```ts
interface SessionNotificationStore
```

**Properties**

- `clear` (`(sessionId: string) => void`): Clears the session's notification (it was opened).
- `get` (`(sessionId: string | null) => SessionNotification | null`): The session's notification, `null` for none.
- `set` (`(sessionId: string, value: SessionNotification) => void`): Leaves a notification on the session.
- `subscribe` (`(sessionId: string | null, listener: () => void) => () => void`): Fires when the session's notification changes.

Source: [ui/src/chat/headless/sidebar/notifications.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/notifications.ts#L11)

### `SessionPageState`

Interface.

Lazy-scrollback bookkeeping for one session: where the hydrated window
starts (`firstSeq` — the `beforeSeq` for the previous page), whether
older turns exist, and an in-flight guard so wheel spam near the top
can't stack duplicate page fetches.

```ts
interface SessionPageState
```

**Properties**

- `firstSeq` (`number`): The sequence number the hydrated window starts at: the `beforeSeq` of the page before it.
- `hasMore` (`boolean`): Whether older turns exist before the window.
- `loadingEarlier` (`boolean`): Whether a fetch of the previous page is in flight.

Source: [ui/src/chat/headless/streams/types.ts:30](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L30)

### `SessionRef`

Interface.

How a reference names a session: its title, and its folder's name when it has one.

```ts
interface SessionRef
```

**Properties**

- `dir?` (`string`): Directory basename — the sidebar's project label. Absent for a directory-less session.
- `title` (`string`): The session's title.

Source: [ui/src/chat/headless/sidebar/directory.ts:999](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L999)

### `SessionRetryState`

Interface.

A provider stream being retried.

```ts
interface SessionRetryState
```

**Properties**

- `attempt` (`number`): The attempt in progress, from 1.
- `max` (`number`): The attempts allowed.
- `source` (`string`): Whose stream stalled: `'parent'` or a subagent's child id.

Source: [ui/src/chat/headless/streams/types.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L15)

### `SessionSearchHit`

Interface.

A conversation whose content matched a search.

```ts
interface SessionSearchHit
```

**Properties**

- `excerpt` (`string`): The matching text around the first hit.
- `matchCount` (`number`): How many turns matched.
- `sessionId` (`string`): The session that matched.
- `title` (`string`): Its title.
- `updatedAt` (`number`): The session's last activity, epoch ms.

Source: [ui/src/chat/headless/host.ts:193](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L193)

### `SessionStreamActions`

Interface.

The bound writes of a [`SessionStreams`](https://zidane.si/docs/reference/ui-chat-headless.md#SessionStreams), from [`createSessionStreamActions`](https://zidane.si/docs/reference/ui-chat-headless.md#createSessionStreamActions).

```ts
interface SessionStreamActions<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `appendErrorEvent` (`(sessionId: K, text: string) => void`): Adds an error row to the session's transcript.
- `appendUserPrompt` (`(sessionId: K, text: string, refs?: readonly PromptSegmentRef[], attachments?: readonly ChatAttachment[]) => void`): Shows a sent prompt at once; the host's echo of it is then dropped.
- `confirmIdle` (`(sessionId: K) => void`): Confirms the session is idle (a run that ended while nobody listened).
- `drop` (`(sessionId: K) => void`): Forgets the session (a deleted one).
- `dropAll` (`() => void`): Forgets every session.
- `dropPendingEcho` (`(sessionId: K, text: string) => void`): Unwinds one pending echo after a failed send.
- `dropPromptPreviews` (`(sessionId: K, text: string) => void`): Unwinds a queued prompt's previews after a failed enqueue.
- `evictExcept` (`(keep: ReadonlySet<K>) => void`): Evicts hydrated windows outside `keep`; running and mid-scrollback sessions stay.
- `hasEvents` (`(sessionId: K) => boolean`): Whether the store holds any record for the session (no subscription).
- `loadEarlier` (`(sessionId: K, options?: LoadEarlierOptions) => boolean`): Fetches and splices the page before the window. `false` when no fetch started.
- `markRunning` (`(sessionId: K) => void`): Seeds a run seen only through the session list.
- `noteActiveSession` (`(sessionId: K | null) => void`): Names the session the user reads: its run-end compaction waits until it is backgrounded.
- `rememberPromptPreviews` (`(sessionId: K, text: string, attachments: readonly ChatAttachment[]) => void`): Keeps a queued prompt's previews until the host sends it.
- `renamePromptPreviews` (`(sessionId: K, from: string, to: string) => void`): Re-keys a queued prompt's previews after its text is edited.
- `reset` (`(sessionId: K) => void`): Clears the session's transcript and run state, keeping its record.
- `seedSystemMd` (`(sessionId: K, file: SystemMdFile | null) => void`): Seeds the session's `SYSTEM.md` override.
- `setEventsPage` (`(sessionId: K, page: SessionStreamPage) => void`): Hydrates a tail page (events and scrollback bookkeeping, one notify).

Source: [ui/src/chat/headless/streams/actions.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/actions.ts#L15)

### `SessionStreamPage`

Interface.

One page of a session's persisted transcript (the tail, or the page before a sequence number).

```ts
interface SessionStreamPage
```

**Properties**

- `events` (`readonly ChatEvent[]`): The page's events, oldest first.
- `firstSeq` (`number`): The sequence number of the page's first turn.
- `hasMore` (`boolean`): Whether older turns exist before the page.

Source: [ui/src/chat/headless/streams/types.ts:40](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L40)

### `SessionStreams`

Interface.

The session stream store with pacing, scrollback and compaction. Created by [`createSessionStreams`](https://zidane.si/docs/reference/ui-chat-headless.md#createSessionStreams).

```ts
interface SessionStreams<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `store` (`SessionStreamStore<K>`, readonly): The store: per-session snapshots (`get…Snapshot`), per-session subscriptions and the direct writes.
- `apply` (`(signal: SessionStreamSignal<K> | OtherStreamSignal) => void`): Feeds one live signal in. With smoothing on, streamed markdown waits in its
  (session, owner) bucket and any other signal first drains the buckets it
  follows, so the transcript stays in causal order.
- `confirmIdle` (`(sessionId: K) => void`): Ends a session's run without a host signal (the host says it is idle): drains its buckets, then applies `run:end`.
- `dispose` (`() => void`): Stops the ticker and delivers held notifications.
- `drainSmoothing` (`() => void`): Reveals every waiting smoothed delta at once and stops the ticker (smoothing was turned off).
- `drop` (`(sessionId: K) => void`): Forgets a session entirely (a deleted session).
- `dropAll` (`() => void`): Forgets every session (the runtime behind them changed).
- `evictExcept` (`(keep: ReadonlySet<K>) => void`): Evicts hydrated windows outside `keep`; running and mid-scrollback sessions stay.
- `loadEarlier` (`(sessionId: K, options?: LoadEarlierOptions) => boolean`): Fetches and splices the page before the session's window. Returns whether
  a fetch started (false while one is in flight, when history is complete,
  or without `loadBefore`). A page that lands after the window changed
  (reset, re-hydration) is dropped and reported as `onSettled(false)`.
- `noteActiveSession` (`(sessionId: K | null) => void`): The session the user is looking at: run-end compaction skips it and catches up once it is backgrounded.
- `reset` (`(sessionId: K) => void`): Empties a session's window and run state (and its smoothing bucket).
- `transcript` (`(sessionId: K) => Transcript`): A session's transcript as a [`ChatHost`](https://zidane.si/docs/reference/ui-chat-headless.md#ChatHost) hands it to the components (cached per session).

Source: [ui/src/chat/headless/streams/session-streams.ts:58](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/session-streams.ts#L58)

### `SessionStreamsOptions`

Interface.

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

```ts
interface SessionStreamsOptions<K extends string = string>
```

**Type parameters**

- `K` (`extends string`, default `string`)

**Properties**

- `compactAbove?` (`number`): Event count past which a background window is compacted at run end. Default: 2000.
- `markdown?` (`MarkdownDeltaOptions`): How streamed markdown merges. Default: one event per message.
- `scheduler?` (`FrameScheduler`): Frames and timers for pacing and batched notifications. Default: [`defaultFrameScheduler`](https://zidane.si/docs/reference/ui-chat-headless.md#defaultFrameScheduler).
- `smooth?` (`boolean | (() => boolean)`): Pace streamed markdown at a steady speed. A function is read on every signal, so a setting can flip it live (call `SessionStreams.drainSmoothing` when it turns off). Default: `false`.
- `loadBefore?` (`(sessionId: K, beforeSeq: number) => Promise<SessionStreamPage>`): Loads the page before `beforeSeq`. `SessionStreams.loadEarlier` needs it.
- `loadTail?` (`(sessionId: K) => Promise<SessionStreamPage>`): Loads a session's persisted tail page. Run-end compaction needs it; without it windows are never compacted.

Source: [ui/src/chat/headless/streams/session-streams.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/session-streams.ts#L36)

### `SessionStreamStoreOptions`

Interface.

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

```ts
interface SessionStreamStoreOptions
```

**Properties**

- `batch?` (`boolean`): Deliver transcript-event notifications once per frame (`true`, the default) or at once (`false`). The state is current at once either way.
- `markdown?` (`MarkdownDeltaOptions`): How streamed markdown merges. Default: one event per message (`segmentChars: Infinity`).
- `scheduler?` (`FrameScheduler`): Frames and timers for batched notifications. Default: [`defaultFrameScheduler`](https://zidane.si/docs/reference/ui-chat-headless.md#defaultFrameScheduler).

Source: [ui/src/chat/headless/streams/store.ts:65](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/store.ts#L65)

### `SessionStreamWrite`

Interface.

One write to a session's window, see `SessionStreamStore.write`.

```ts
interface SessionStreamWrite
```

**Properties**

- `events?` (`readonly ChatEvent[]`): Replaces the events.
- `page?` (`SessionPageState | null`): Sets the page state (and so marks the window hydrated); `null` drops it.
- `running?` (`boolean`): Sets the run flag.

Source: [ui/src/chat/headless/streams/store.ts:75](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/store.ts#L75)

### `SharedDraft`

Interface.

A session's shared draft, as another window left it.

```ts
interface SharedDraft
```

**Properties**

- `attachments?` (`PromptAttachment[]`): The files staged with the draft.
- `search?` (`{ active: boolean; query: string }`): The transcript search the draft drives, when it is in search mode.
- `shell?` (`boolean`): True when the draft is a shell command.
- `text` (`string`): The draft's text (shell mode's `!` not included).

Source: [ui/src/chat/headless/composer/host.ts:50](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L50)

### `SharedDraftAttachmentsChange`

Interface.

The staged files of a draft written in another window.

```ts
interface SharedDraftAttachmentsChange
```

**Properties**

- `attachments` (`PromptAttachment[]`): The staged files now.
- `sessionId` (`string`): The session whose draft changed.

Source: [ui/src/chat/headless/composer/host.ts:72](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host.ts#L72)

### `SharedDraftChange`

Interface.

A draft written in another window.

```ts
interface SharedDraftChange
```

**Properties**

- `sessionId` (`string`): The session whose draft changed.
- `shell?` (`boolean`): True when the new draft is a shell command.
- `text` (`string`): The new text.

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

### `SidebarContributions`

Interface.

What the extensions contribute to the sidebar, per token.

```ts
interface SidebarContributions
```

**Properties**

- `decorations` (`readonly ExtensionItem<'sidebar-decoration'>[]`): Extra data on session rows.
- `filters` (`readonly ExtensionItem<'sidebar-filter'>[]`): Filters for the filter menu.
- `groups` (`readonly ExtensionItem<'sidebar-group'>[]`): Groupings for the filter menu.
- `items` (`readonly ExtensionItem<'sidebar-row'>[]`): Rows among the sessions.
- `sorts` (`readonly ExtensionItem<'sidebar-sort'>[]`): Sorts for the filter menu.
- `spaces` (`readonly ExtensionItem<'space'>[]`): Spaces for the switcher.

Source: [ui/src/chat/headless/sidebar/query.ts:67](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L67)

### `SidebarEnvironmentHost`

Interface.

The commands of the environment a session runs in (push the branch, open a pull request).

```ts
interface SidebarEnvironmentHost
```

**Properties**

- `actions` (`(sessionId: string) => Promise<readonly EnvironmentActionSummary[]>`): The commands the session's environment offers right now. Rejects when they can't be read.
- `retry` (`(sessionId: string) => Promise<void>`): Sets a failed environment up again; progress arrives as the session's row changing.
- `run` (`(sessionId: string, actionId: string) => Promise<EnvironmentActionResult>`): Runs one of them; resolves with what to tell the user and, maybe, something to open.

Source: [ui/src/chat/headless/sidebar/host.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/host.ts#L20)

### `SidebarExtensionView`

Interface.

The user's layer over what extensions contribute to the filter menu, kept per space with the rest
of the view. Ids are the published ones (`<extension>/<id>`); an id no extension offers now is ignored.

```ts
interface SidebarExtensionView
```

**Properties**

- `filters` (`Readonly<Record<string, boolean | string | readonly string[]>>`): Each contributed filter's value: `true` for an active toggle, an option id (select), option ids (multi).
- `group?` (`string`): A contributed grouping, or [`VIEW_CHOICE`](https://zidane.si/docs/reference/ui-chat-headless.md#VIEW_CHOICE). Absent: the space's grouping when it has one, else `groupBy`.
- `sort?` (`string`): A contributed sort, or [`VIEW_CHOICE`](https://zidane.si/docs/reference/ui-chat-headless.md#VIEW_CHOICE). Absent: the space's sort when it has one, else `sortBy`.

Source: [ui/src/chat/headless/sidebar/types.ts:71](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L71)

### `SidebarHost`

Interface.

The sidebar's platform capabilities. Every member is optional.

```ts
interface SidebarHost
```

**Properties**

- `badges?` (`SessionBadgesSource`): The rows' badges and when they change, for `createSessionBadges`. Absent: the app reads them its own way, or rows show none.
- `environment?` (`SidebarEnvironmentHost`): A session's environment commands. Absent: no retry, no environment commands.
- `openHostSettings?` (`(hostId: string) => Promise<void>`): Opens a saved host's page in the app's settings. Absent: a server folder's host badge is not a button.
- `openWindow?` (`(sessionId: string, mode: SessionWindowMode) => Promise<void>`): Opens a session in a window of its own. Absent: no window rows.
- `revealPath?` (`(path: string) => Promise<void>`): Shows a folder of this machine in the file manager. Absent: no "Open in Finder".

Source: [ui/src/chat/headless/sidebar/host.ts:30](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/host.ts#L30)

### `SidebarItemEntry`

Interface.

Extension items grouped with their child sessions, as the rows place them.

```ts
interface SidebarItemEntry<S extends SidebarListSession>
```

**Type parameters**

- `S` (`extends SidebarListSession`)

**Properties**

- `children` (`readonly S[]`): The listed sessions its `children` query matches, in list order.
- `entry` (`ExtensionItem<'sidebar-row'>`): The item.

Source: [ui/src/chat/headless/sidebar/query.ts:545](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L545)

### `SidebarListSession`

Interface.

One session as the sidebar lists it: the chat session plus where it runs
(folder, host, space). An app's own row type extends it.

```ts
interface SidebarListSession
```

**Properties**

- `agentId?` (`string`): The agent profile it runs (`AgentProfile.id`): the agent grouping and filter read it.
- `archived?` (`boolean`): Archived: listed only under the archived filter.
- `createdAt` (`number`): Epoch ms.
- `cwd` (`string`): The folder its tools run in.
- `facets?` (`Readonly<Record<string, unknown>>`): What extensions computed for it, keyed `<extensionId>.<key>` (a query reads one as
  `facet.<extensionId>.<key>`). Absent: none, or a host that sends none.
- `favorite?` (`boolean`): Starred: listed under Favorites.
- `hostId?` (`string`): The remote host it lives on; undefined on this machine.
- `id` (`string`): The session's key.
- `isGitRepo?` (`boolean`): Its folder is a git repository.
- `isMain?` (`boolean`): The orchestration main session.
- `projectRoot?` (`string`): The repository or project folder it belongs to, when known.
- `repoKey?` (`string`): The repository its folder is a checkout of (`github.com/owner/repo`). Sessions of one
  repository on several machines are listed under one project.
- `scheduleId?` (`string`): The reminder that started it (zidane's `SessionMeta.scheduleId`): the clock mark and the Origin filter read it.
- `spaceId?` (`string`): The space it belongs to; undefined in the default space.
- `status` (`ChatSessionStatus`): Whether a run is going, and how the last one ended.
- `title` (`string`): What the row shows.
- `updatedAt` (`number`): Epoch ms of the last activity.

Source: [ui/src/chat/headless/sidebar/types.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L11)

### `SidebarQueryLayer`

Interface.

The query layer of the space shown, as the sidebar's parts read it: the space, the view, the
grouping and sort that apply, and what the extensions contribute to this space.

```ts
interface SidebarQueryLayer
```

**Properties**

- `agents` (`readonly string[]`): The agents the space's sessions run, sorted (before the agent filter).
- `decorations` (`readonly ExtensionItem<'sidebar-decoration'>[]`): The row decorations.
- `filters` (`readonly ExtensionItem<'sidebar-filter'>[]`): The contributed filters this space offers.
- `grouping` (`SidebarGrouping`): The grouping that applies ([`resolveGrouping`](https://zidane.si/docs/reference/ui-chat-headless.md#resolveGrouping)).
- `groups` (`readonly ExtensionItem<'sidebar-group'>[]`): The contributed groupings.
- `items` (`readonly ExtensionItem<'sidebar-row'>[]`): The items listed in this space.
- `sort` (`readonly SessionSort[] | null`): The sort that applies ([`resolveSort`](https://zidane.si/docs/reference/ui-chat-headless.md#resolveSort)); `null`: the view's `sortBy`.
- `sorts` (`readonly ExtensionItem<'sidebar-sort'>[]`): The contributed sorts.
- `space` (`SidebarSpace`): The space shown.
- `view` (`SidebarView`): Its view.

Source: [ui/src/chat/headless/sidebar/query.ts:392](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L392)

### `SidebarRowChip`

Interface.

A chip a decoration puts on a row, its template rendered.

```ts
interface SidebarRowChip
```

**Properties**

- `icon?` (`string`): Its icon class.
- `text` (`string`): What it says.
- `tone?` (`ExtensionBadgeTone`): Its tint.

Source: [ui/src/chat/headless/sidebar/query.ts:416](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L416)

### `SidebarRowDecoration`

Interface.

What the decorations matching one session put on its row.

```ts
interface SidebarRowDecoration
```

**Properties**

- `chips` (`readonly SidebarRowChip[]`): Chips, at most [`MAX_ROW_CHIPS`](https://zidane.si/docs/reference/ui-chat-headless.md#MAX_ROW_CHIPS).
- `component?` (`{ chips: readonly SidebarRowChip[]; component: ComponentWire; extension: string; icon?: string }`): A component drawn where the app can, in place of the icon and chips of the decoration that
  names it (`icon`, `chips`: its fallback). The other decorations' chips draw beside it.
- `icon?` (`string`): An icon class beside the title (the first decoration's that has one).
- `subtitle?` (`string`): A line under the title.
- `tone?` (`ExtensionBadgeTone`): The tint of that icon and of chips without their own.

Source: [ui/src/chat/headless/sidebar/query.ts:426](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L426)

### `SidebarSpace`

Interface.

A space as the sidebar lists it: a user space, or an extension's (`extensionId`, read-only), with
the base query, grouping and sort a query space carries.

```ts
interface SidebarSpace extends Space
```

**Properties**

- `account?` (`string`, from `Space`): The stored account of `providerKey` the default runs on (credential id); absent = its active account.
- `agentId?` (`string`, from `Space`): Agent new sessions in this space start on (`AgentProfile.id`); absent = the global default (`Settings.defaultAgent`).
- `effort?` (`'off' | 'max' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'adaptive'`, from `Space`): Effort new sessions in this space start with, whatever their model; absent = Settings' (`defaultEffort`).
- `extensionId?` (`string`): The extension that adds it. Absent: the user's.
- `fallbacks?` (`{ modelId: string; providerKey: string }[]`, from `Space`): Fallback chain seeded with the default model (`provider`/`model` pairs).
- `glyph?` (`string`): An icon class (an extension's `icon.gui`), drawn in place of `icon`.
- `groupBy?` (`SessionGroupBy`): Its own grouping, the default of its view.
- `hidden?` (`boolean`): Left out of the switcher (its sessions stay in it).
- `icon?` (`SpaceIcon`, from `Space`): Icon shown in the switcher.
- `id` (`string`, from `Space`): Stable id. `DEFAULT_SPACE_ID` for the Default space.
- `items?` (`boolean`): Extension items may list in it.
- `modelId?` (`string`, from `Space`): Default model id for new sessions. Used together with `providerKey`.
- `modelOptions?` (`Record<string, boolean>`, from `Space`): Model options (`fast`…) new sessions in this space start with, where their model offers them; absent = Settings' (`defaultModelOptions`).
- `name` (`string`, from `Space`): Display name.
- `providerKey?` (`string`, from `Space`): Default provider for new sessions in this space; set together with `modelId`.
- `query?` (`SessionQuery`): The sessions it lists besides those tagged with it. Absent: only those.
- `readonly?` (`boolean`): Its base (name, query, defaults) can't be edited here: an extension's.
- `sortBy?` (`SessionSort[]`): Its own sort, the default of its view.

Source: [ui/src/chat/headless/sidebar/query.ts:47](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L47)

### `SidebarView`

Interface.

The filter axes, kept per space.

```ts
interface SidebarView
```

**Properties**

- `activity` (`SessionActivityFilter`): Only sessions touched recently.
- `agent?` (`string | null`): Only this agent's sessions (`AgentProfile.id`), or null for every agent.
- `archive` (`SessionArchiveFilter`): Active, archived or every session.
- `extension?` (`SidebarExtensionView`): What the user picked of the extensions' filters, sorts and groupings. Absent: nothing.
- `groupBy` (`SidebarGroupBy`): How the rows group.
- `origin?` (`SidebarOrigin | null`): Only the sessions a reminder started, or only the others. Absent or null: every session.
- `project` (`string | null`): A project's folder name, or null for every project.
- `sortBy` (`SidebarSortBy`): How the rows sort inside a group.

Source: [ui/src/chat/headless/sidebar/types.ts:86](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L86)

### `SidebarViews`

Interface.

The sidebar's views and shown space, outside React.

```ts
interface SidebarViews
```

**Properties**

- `space` (`Readable<string>`): The space the sidebar shows.
- `switcher` (`Readable<SpaceSwitcherPrefs>`): The switcher's order and hidden spaces, on this device.
- `views` (`Readable<SidebarViewMap>`): Every space's view.
- `forgetSession` (`(sessionId: string, exceptSpaceId?: string) => void`): Forget a conversation in every space that remembers it (deleted, moved away).
- `lastSessionOf` (`(spaceId: string) => string | null`): The conversation last open in a space, if one was.
- `patch` (`(spaceId: string, patch: Partial<SidebarView>) => void`): Change some axes of a space's view; persisted at once.
- `rememberSession` (`(spaceId: string, sessionId: string) => void`): Remember the conversation open in a space; persisted at once (no-op when unchanged).
- `setSpace` (`(spaceId: string) => void`): Show another space; persisted at once.
- `setSwitcher` (`(prefs: SpaceSwitcherPrefs) => void`): Replaces the switcher's prefs; persisted at once.
- `sync` (`() => void`): Read the host's copies once (no-op without a host). Call after creation.
- `viewOf` (`(spaceId: string) => SidebarView`): The space's view (the default when it has none).

Source: [ui/src/chat/headless/sidebar/view.ts:208](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L208)

### `SidebarViewsHost`

Interface.

The views the host keeps for this user, next to the device's Storage.

```ts
interface SidebarViewsHost
```

**Properties**

- `getSpace` (`() => Promise<unknown>`): The space last shown, if any.
- `getViews` (`() => Promise<unknown>`): Every saved view, keyed by space id (anything malformed is dropped).
- `setSpace` (`(spaceId: string) => Promise<unknown>`): Saves the space shown.
- `setView` (`(spaceId: string, view: SidebarViewRecord) => Promise<unknown>`): Saves a space's record (its view and last open conversation).

Source: [ui/src/chat/headless/sidebar/view.ts:42](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L42)

### `SidebarViewsOptions`

Interface.

Options of [`createSidebarViews`](https://zidane.si/docs/reference/ui-chat-headless.md#createSidebarViews).

```ts
interface SidebarViewsOptions
```

**Properties**

- `fallbackSpace?` (`string`): The space shown when none was saved.
- `host?` (`SidebarViewsHost`): The host's copy (`ChatHost.sessions.views`).
- `onError?` (`(what: 'view' | 'space' | 'views', error: unknown) => void`): A host read or write failed.
- `storage?` (`SidebarViewsStorage`): Where the views persist on this device.

Source: [ui/src/chat/headless/sidebar/view.ts:234](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L234)

### `SkillConfig`

Interface.

A parsed skill: its frontmatter fields, instructions and origin.

```ts
interface SkillConfig
```

**Properties**

- `allowedTools?` (`string[]`): Pre-approved tool names (experimental per spec)
- `baseDir?` (`string`): Skill directory path for resolving relative references
- `compatibility?` (`string`): Environment requirements
- `description` (`string`): What the skill does and when to use it (1-1024 chars)
- `diagnostics?` (`SkillDiagnostic[]`): Lenient-load warnings recorded during parsing. Host SDKs can surface these
  as inline UI hints. Absent when no issues were found.
- `instructions` (`string`): The SKILL.md body content (after YAML frontmatter)
- `license?` (`string`): License identifier or reference
- `location?` (`string`): Absolute path to SKILL.md (undefined for inline skills)
- `metadata?` (`Record<string, string>`): Flat key-value metadata bag per the spec. For Zidane-specific hints,
  use the `zidane.` key prefix (e.g. `metadata['zidane.paths']`).
- `name` (`string`): Skill name: 1-64 chars, lowercase alphanumeric + hyphens
- `resources?` (`SkillResource[]`): Bundled resource files discovered in the skill directory
- `source?` (`SkillSource`): Where this skill was loaded from. Drives collision precedence and the
  `trustProjectSkills` gate. Optional — `parseSkillFile` stamps it; raw
  fixtures that omit it are treated as `'project'` by downstream readers.

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

### `SpaceSwitcherPrefs`

Interface.

The user's arrangement of the space switcher, over the spaces' own order: extension spaces
included, which Settings › Spaces doesn't list.

```ts
interface SpaceSwitcherPrefs
```

**Properties**

- `hidden` (`readonly string[]`): Space ids the switcher leaves out (their sessions stay where they are).
- `order` (`readonly string[]`): Space ids in the order the user put them; a space not named keeps its place after them.

Source: [ui/src/chat/headless/sidebar/view.ts:113](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L113)

### `ToolPairing`

Interface.

The result paired with one tool call.

```ts
interface ToolPairing
```

**Properties**

- `resultIndex` (`number`): Index in the events array of the paired `tool-result` or `error` event.
- `resultKind` (`'error' | 'tool-result'`): Kind of the paired event. A `tool-result` flagged `isError` counts as `error`.

Source: [ui/src/chat/headless/transcript/pairing.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/pairing.ts#L15)

### `Transcript`

Interface.

A readable store of one session's [`TranscriptState`](https://zidane.si/docs/reference/ui-chat-headless.md#TranscriptState).

```ts
interface Transcript extends Readable<TranscriptState>
```

**Properties**

- `get` (`() => TranscriptState`, from `Readable`): Returns the current value.
- `loadEarlier?` (`() => void`): Fetches older events and prepends them to `events`. Absent: the Earlier messages control is hidden.
- `subscribe` (`(onChange: () => void) => () => void`, from `Readable`): Registers a listener called after the value changes. Returns a function that removes the listener.

Source: [ui/src/chat/headless/host.ts:122](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L122)

### `TranscriptState`

Interface.

The state a [`Transcript`](https://zidane.si/docs/reference/ui-chat-headless.md#Transcript) store holds for one session.

```ts
interface TranscriptState
```

**Properties**

- `events` (`readonly ChatEvent[]`): The events loaded so far, oldest first.
- `hasEarlier?` (`boolean`): Older events exist before `events[0]` (`loadEarlier` fetches them).
- `hydrated` (`boolean`): History has arrived (until then the transcript shows its loading state).
- `loadingEarlier?` (`boolean`): An earlier page of events is being fetched.
- `running` (`boolean`): A run is in flight: the last reply may still be streaming.

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

### `TurnPromptDraft`

Interface.

A sent prompt as a draft: its text and attachments.

```ts
interface TurnPromptDraft
```

**Properties**

- `attachments` (`ChatAttachment[]`): Its attachments.
- `text` (`string`): The prompt text.

Source: [ui/src/chat/headless/turn-prompt.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/turn-prompt.ts#L8)

### `Writable`

Interface.

A [`Readable`](https://zidane.si/docs/reference/ui-chat-headless.md#Readable) you can also write to.

```ts
interface Writable<T> extends Readable<T>
```

**Type parameters**

- `T`

**Properties**

- `get` (`() => T`, from `Readable`): Returns the current value.
- `set` (`(next: T | ((prev: T) => T)) => void`): Replaces the value, or computes the next one from the previous. Listeners run only when the value changes by `Object.is`.
- `subscribe` (`(onChange: () => void) => () => void`, from `Readable`): Registers a listener called after the value changes. Returns a function that removes the listener.

Source: [ui/src/chat/headless/store.ts:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/store.ts#L18)

## Types

### `BuildSidebarRowsOptions`

Type.

The list options [`buildSidebarRows`](https://zidane.si/docs/reference/ui-chat-headless.md#buildSidebarRows) passes through.

```ts
type BuildSidebarRowsOptions = Pick<SessionListOptions<SidebarListSession>, 'collapsedGroups' | 'showMoreExpanded' | 'idPrefix' | 'pinnedProjects' | 'compare'>
```

Source: [ui/src/chat/headless/sidebar/rows.ts:68](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L68)

### `ChatEvent`

Type.

zidane's canonical transcript event, plus what a live client knows and a
replay does not: attachment previews, arrival times, clipped outputs and
thinking durations. Every extra is optional; a replayed `StreamEvent`
list is a valid `ChatEvent` list.

```ts
type ChatEvent = Omit<StreamEvent, 'attachments'> & { attachments?: readonly ChatAttachment[]; clipped?: true; receivedAt?: number; thinkingMs?: number; thinkingStartedAt?: number }
```

Source: [ui/src/chat/headless/host.ts:63](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L63)

### `ChatLabels`

Type.

The shape of the chat label dictionary: every key of [`DEFAULT_CHAT_LABELS`](https://zidane.si/docs/reference/ui-chat-headless.md#DEFAULT_CHAT_LABELS). Some values are functions that build a string.

```ts
type ChatLabels = typeof DEFAULT_CHAT_LABELS
```

Source: [ui/src/chat/headless/labels.ts:507](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/labels.ts#L507)

### `ChatReferencesChange`

Type.

What made the host's references change.

```ts
type ChatReferencesChange =
  | { kind: 'all' }
  | { key: string; kind: 'reference'; providerId: string }
```

Source: [ui/src/chat/headless/transcript-host.ts:38](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L38)

### `ChatResolvedPath`

Type.

What a name in prose points at: a file or folder on disk, a git branch of the repo, or nothing. `candidates`:
everything a bare name matched when it matched several, best first (`path` is the first's).

```ts
type ChatResolvedPath =
  | { candidates?: { kind: 'file' | 'dir'; path: string }[]; kind: 'file' | 'dir'; path: string }
  | { kind: 'branch'; name: string; remote?: string }
  | { kind: 'missing' }
```

Source: [ui/src/chat/headless/transcript-host.ts:66](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript-host.ts#L66)

### `ChatSessionStatus`

Type.

Run state of a session: `idle`, `running`, `completed`, or `error`.

```ts
type ChatSessionStatus = 'idle' | 'running' | 'completed' | 'error'
```

Source: [ui/src/chat/headless/host.ts:79](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/host.ts#L79)

### `ChipResolution`

Type.

`null`: not known yet, or the folder can't be checked (sandboxes).

```ts
type ChipResolution = ChatResolvedPath | null
```

Source: [ui/src/chat/headless/path-resolver.ts:14](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/path-resolver.ts#L14)

### `ChipViewLabels`

Type.

The labels the views read.

```ts
type ChipViewLabels = Pick<ChatLabels, 'chipFactChanges' | 'chipFactDate' | 'chipFactModel' | 'chipFactContext' | 'chipFactPrompts' | 'chipFactTurns' | 'chipFactBranch' | 'chipFactUpdated' | 'chipFactAliases' | 'chipFactSize' | 'chipTokens' | 'chipSessionRunning' | 'chipSessionError' | 'chipUntitledChat' | 'justNow' | 'months'>
```

Source: [ui/src/chat/headless/chip-views.ts:21](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/chip-views.ts#L21)

### `Cluster`

Type.

A transcript row, or a subagent block. A block's `rows` are the worker's
OWN rows (its header reads its lifecycle off them); `body` is what the
block paints in order — those rows as singles, plus the blocks of the
workers it started, nested where they ran.

```ts
type Cluster =
  | { kind: 'single'; row: Row }
  | { body: Cluster[]; childId: string; depth: number; kind: 'group'; rows: Row[] }
```

Source: [ui/src/chat/headless/transcript/rows.ts:299](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L299)

### `CompactionSignal`

Type.

The stream signals a compaction's progress follows; any other kind is ignored.

```ts
type CompactionSignal =
  | { kind: 'compacting:start'; sessionId: string }
  | { estOutputTokens: number | null; kind: 'compacting:progress'; sessionId: string }
  | { kind: 'compacting:end'; sessionId: string }
```

Source: [ui/src/chat/headless/sidebar/compaction.ts:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/compaction.ts#L18)

### `ComposerCacheImpact`

Type.

What a switch would cost the session's prompt cache.

```ts
type ComposerCacheImpact = NonNullable<IpcResult<'sessions.cacheImpact'>>
```

Source: [ui/src/chat/headless/composer/host-chrome.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L26)

### `ComposerCacheImpactChange`

Type.

A switch a picker would make: what its cache estimate is asked for.

```ts
type ComposerCacheImpactChange = IpcParams<'sessions.cacheImpact'>['change']
```

Source: [ui/src/chat/headless/composer/host-chrome.ts:23](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L23)

### `ComposerChromeLabels`

Type.

The chrome's strings.

```ts
type ComposerChromeLabels = typeof DEFAULT_COMPOSER_CHROME_LABELS
```

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

### `ComposerContextBreakdown`

Type.

What `ContextBreakdown` renders.

```ts
type ComposerContextBreakdown = ContextBreakdown
```

Source: [ui/src/chat/headless/composer/host-chrome.ts:161](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/host-chrome.ts#L161)

### `ComposerDraftAttachmentsListener`

Type.

Hears another window's staged files for a draft.

```ts
type ComposerDraftAttachmentsListener = (change: SharedDraftAttachmentsChange) => void
```

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

### `ComposerEffort`

Type.

A reasoning effort level.

```ts
type ComposerEffort = ThinkingLevel
```

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

### `ComposerLabels`

Type.

Every composer string.

```ts
type ComposerLabels = typeof DEFAULT_COMPOSER_EDITOR_LABELS & typeof DEFAULT_COMPOSER_CHROME_LABELS
```

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

### `ComposerMode`

Type.

Composer prompt modes — pure state-machine helpers for the `!` (shell)
and `?` (transcript search) sentinels, mirroring the TUI's grammar
(src/tui/prompt/ `useSyncBuffer` / `usePromptKeyDown`):

- Entry: the sentinel must be TYPED as the first character of an
  empty composer (exactly-one-char transition — pasted/recalled
  `!cmd` stays literal text). The sentinel is consumed; it never
  enters the buffer.
- Exit: Backspace with the caret at offset 0 leaves the mode
  (search also exits on Delete-at-0 and on Esc; shell does NOT
  exit on Esc — TUI parity).
- Submit (shell): the bang is re-attached (`!cmd`) so the host
  routing and prompt history keep the TUI's on-disk grammar; a
  blank command is a no-op.
- History: `!`-prefixed entries recall INTO shell mode with the
  bang stripped; stashing a shell-mode draft re-encodes the bang.

Kept free of TipTap/React so the grammar is unit-testable.

```ts
type ComposerMode = 'normal' | 'shell' | 'search'
```

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

### `DotVariant`

Type.

The status dot a row shows, chosen by [`dotVariantFor`](https://zidane.si/docs/reference/ui-chat-headless.md#dotVariantFor): a row kind, a tool state, or a session event status.

```ts
type DotVariant =
  | 'user'
  | 'thinking'
  | 'text'
  | 'tool-running'
  | 'tool-ok'
  | 'tool-err'
  | 'info'
  | 'note'
  | 'error'
  | 'stopped'
  | 'spawn-start'
  | 'spawn-end'
  | 'compact'
  | 'messages'
  | `session-${SessionEventStatus}`
```

Source: [ui/src/chat/headless/transcript/rows.ts:368](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L368)

### `FileChipKind`

Type.

What a path in prose names: a folder or a file.

```ts
type FileChipKind = 'dir' | 'file'
```

Source: [ui/src/chat/headless/file-chip.ts:20](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/file-chip.ts#L20)

### `FoldActionState`

Type.

`waiting`: a `spawn` call that has not started yet, every slot being taken.

```ts
type FoldActionState = 'waiting' | 'running' | 'ok' | 'err'
```

Source: [ui/src/chat/headless/transcript/fold-actions.ts:22](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/fold-actions.ts#L22)

### `GroupCluster`

Type.

A subagent block: the `group` member of [`Cluster`](https://zidane.si/docs/reference/ui-chat-headless.md#Cluster).

```ts
type GroupCluster = Extract<Cluster, { kind: 'group' }>
```

Source: [ui/src/chat/headless/transcript/rows.ts:303](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L303)

### `HostStatus`

Type.

A host's connection. `local`: This computer, always reachable. The rest
mirror the TUI's statuses (`identity`: a different server answers at the
saved URL; `version-mismatch`: it speaks another protocol version).

```ts
type HostStatus =
  | 'local'
  | 'connecting'
  | 'connected'
  | 'reconnecting'
  | 'offline'
  | 'auth-refused'
  | 'identity'
  | 'version-mismatch'
```

Source: [ui/src/chat/headless/hosts.ts:13](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/hosts.ts#L13)

### `ModelPickerPrefsStorage`

Type.

Where the preferences are stored.

```ts
type ModelPickerPrefsStorage = Pick<Storage, 'getItem' | 'setItem'>
```

Source: [ui/src/chat/headless/composer/model-picker-prefs.ts:48](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/model-picker-prefs.ts#L48)

### `PinsBySpace`

Type.

Pinned folder paths per space id, in pin order.

```ts
type PinsBySpace = Record<string, string[]>
```

Source: [ui/src/chat/headless/sidebar/pinned-projects.ts:12](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/pinned-projects.ts#L12)

### `ProjectIcon`

Type.

A folder's icon: an emoji, or a small image as a data URL.

```ts
type ProjectIcon = { kind: 'emoji'; value: string } | { kind: 'image'; value: string }
```

Source: [ui/src/chat/headless/sidebar/project-icons.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L11)

### `ProjectIconMap`

Type.

Icons by folder path.

```ts
type ProjectIconMap = Record<string, ProjectIcon>
```

Source: [ui/src/chat/headless/sidebar/project-icons.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/project-icons.ts#L15)

### `Row`

Type.

One row of the transcript model. The `kind` field says what it is: a prompt, assistant markdown, thinking, a tool call, a notice, a worker marker, or a synthetic group such as `tool-batch` or `exchange-fold`.

```ts
type Row =
  | (Owned & { attachments?: readonly ChatAttachment[]; id: string; kind: 'user-prompt'; origin?: PromptOrigin; refs?: readonly PromptSegmentRef[]; synthetic?: true; text: string })
  | (Owned & { custom?: { data?: unknown; renderer: string }; id: string; kind: 'markdown'; streaming: boolean; text: string })
  | (Owned & { id: string; kind: 'thinking'; live?: boolean; text: string; thinkingMs?: number })
  | (Owned & { id: string; kind: 'thinking-batch'; thoughts: ReadonlyArray<Extract<Row, { kind: 'thinking' }>>; totalMs?: number })
  | (Owned & { id: string; kind: 'info'; notice?: StreamEvent['notice']; text: string })
  | (Owned & { callId?: string; detail?: StreamEvent['detail']; failure?: { cause: 'error' | 'aborted'; prompt?: string; resume: 'continue' | 'retry' }; id: string; kind: 'error'; notice?: StreamEvent['notice']; text: string; tool?: string })
  | (Owned & { id: string; kind: 'session-event'; sessionEvent?: StreamEvent['sessionEvent']; text: string })
  | (Owned & { id: string; kind: 'run-summary'; runSummary?: StreamEvent['runSummary']; text: string })
  | (Owned & { id: string; kind: 'command-detail'; label?: string; syntax?: 'diff'; text: string })
  | (Owned & { id: string; kind: 'command-note'; text: string })
  | { id: string; kind: 'separator' }
  | (Owned & { id: string; kind: 'spawn-start'; model?: string; spawn?: SpawnMeta; text: string })
  | (Owned & { id: string; kind: 'spawn-end'; model?: string; spawn?: SpawnMeta; text: string })
  | (Owned & { callId?: string; command: string; errored?: boolean; exit: BashExitMeta | null; id: string; kind: 'user-bash'; result: string | null; resultClipped?: boolean; running: boolean })
  | (Owned & { approval?: StreamEvent['approval']; callId?: string; children?: ReadonlyArray<Extract<Row, { kind: 'tool' }>>; displayName: string; durationMs?: number; edit?: StreamEvent['edit']; formatted: ToolFormatLine | null; id: string; kind: 'tool'; name: string; ok: boolean | null; parentId?: string; rawInput?: Record<string, unknown>; result: string | null; resultClipped?: boolean; resuming?: true; scriptProgress?: ScriptProgress; startedAt?: number; waitingFor?: { active: number; max: number } })
  | (Owned & { id: string; kind: 'tool-batch'; summary: string; tools: ReadonlyArray<Extract<Row, { kind: 'tool' }>> })
  | { compact: NonNullable<StreamEvent['compact']>; id: string; kind: 'compact-summary'; text: string }
  | (Owned & { id: string; kind: 'exchange-fold'; live: boolean; rows: Row[]; stats: ExchangeFoldStats; summary: string })
  | (Owned & { current: Row; id: string; kind: 'message-group'; live: boolean; messages: Row[] })
```

Source: [ui/src/chat/headless/transcript/rows.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L26)

### `RunEstimatesSignal`

Type.

The stream signals the store follows; any other kind is ignored.

```ts
type RunEstimatesSignal =
  | { estimate: RunEstimateView; kind: 'run:estimate'; sessionId: string }
  | { kind: 'run:start'; sessionId: string }
  | { kind: 'run:end'; sessionId: string }
```

Source: [ui/src/chat/headless/sidebar/estimates.ts:15](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/estimates.ts#L15)

### `RunFailure`

Type.

How a run ended early and how to pick it back up: `cause` (`error` or `aborted`), `resume` (`continue` or `retry`), and the `prompt` to resend on retry.

```ts
type RunFailure = NonNullable<ErrorRow['failure']>
```

Source: [ui/src/chat/headless/transcript/run-failures.ts:18](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/run-failures.ts#L18)

### `RunMeterSignal`

Type.

The stream signals the meter follows (the host's `HostSignal` variants, structurally).

```ts
type RunMeterSignal =
  | { kind: 'run:start'; sessionId: string; startedAt?: number }
  | { elapsedMs: number; estCostUsd?: number; estimated: boolean; kind: 'stream:progress'; outputTokens: number; sessionId: string; turnId: string }
  | { childId?: string; kind: 'turn:end'; runOutputTokens?: number; sessionId: string; usage?: { cost?: number; output?: number } }
  | { kind: 'run:end'; sessionId: string }
```

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

### `SecretTimeLeft`

Type.

How long a saved secret has left.

```ts
type SecretTimeLeft =
  | { count: number; kind: 'left'; unit: 'minute' | 'hour' | 'day' }
  | { kind: 'expired' }
  | { kind: 'never' }
```

Source: [ui/src/chat/headless/secrets.ts:6](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/secrets.ts#L6)

### `SessionActivityFilter`

Type.

Only sessions touched within the last day, 3, 7 or 30 days.

```ts
type SessionActivityFilter = 'all' | '1d' | '3d' | '7d' | '30d'
```

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

### `SessionActivitySignal`

Type.

The stream signals the activity follows; any other kind is ignored.

```ts
type SessionActivitySignal =
  | { kind: 'run:start'; runId?: string; sessionId: string; startedAt?: number }
  | { kind: 'run:end'; ok?: boolean; runId?: string; sessionId: string }
  | { kind: 'compacting:start'; sessionId: string }
  | { kind: 'compacting:end'; ok?: boolean; sessionId: string }
  | { attempt?: number; kind: 'stream:retry'; max?: number; sessionId: string; source: string }
  | { kind: 'stream:retry:cleared'; sessionId: string; source: string }
  | { event: Pick<StreamEvent, 'kind' | 'childId' | 'streaming' | 'tool' | 'callId' | 'input'>; kind: 'event'; sessionId: string }
```

Source: [ui/src/chat/headless/sidebar/activity.ts:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/activity.ts#L17)

### `SessionArchiveFilter`

Type.

Which sessions the list reads: the archive axis is the one the host filters.

```ts
type SessionArchiveFilter = 'active' | 'archived' | 'all'
```

Source: [ui/src/chat/headless/sidebar/types.ts:55](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L55)

### `SessionGroupBy`

Type.

How the list groups sessions: `none` (flat), `date`, `state`, or `project`.

```ts
type SessionGroupBy = 'none' | 'date' | 'state' | 'project'
```

Source: [ui/src/chat/headless/session-list.ts:31](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L31)

### `SessionHistoryDirection`

Type.

Which way to move.

```ts
type SessionHistoryDirection = 'back' | 'forward'
```

Source: [ui/src/chat/headless/sidebar/history.ts:45](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L45)

### `SessionHistoryPage`

Type.

A page of the history: a session, or `null` for the new-chat draft.

```ts
type SessionHistoryPage<K extends string = string> = K | null
```

**Type parameters**

- `K` (`extends string`, default `string`)

Source: [ui/src/chat/headless/sidebar/history.ts:26](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/history.ts#L26)

### `SessionListRow`

Type.

One row of the flat list [`buildSessionRows`](https://zidane.si/docs/reference/ui-chat-headless.md#buildSessionRows) returns: a group `header`, a `session`, or a `showMore` row that ends a capped group.

```ts
type SessionListRow<S> =
  | { chats?: boolean; collapsed: boolean; favorites?: boolean; fullPath?: string; id: string; isGitRepo?: boolean; kind: 'header'; label: string; pinned?: boolean }
  | { favorites?: boolean; id: string; kind: 'session'; session: S }
  | { groupId: string; hiddenCount: number; id: string; kind: 'showMore' }
```

**Type parameters**

- `S`

Source: [ui/src/chat/headless/session-list.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L36)

### `SessionNotification`

Type.

What a finished run left on a session the user wasn't watching.

```ts
type SessionNotification = 'completed' | 'error'
```

Source: [ui/src/chat/headless/sidebar/notifications.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/notifications.ts#L8)

### `SessionRemoval`

Type.

What deleting a session did with its environment.

```ts
type SessionRemoval = { kept: false } | { kept: true; reason?: string }
```

Source: [ui/src/chat/headless/sidebar/directory.ts:74](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/directory.ts#L74)

### `SessionSortBy`

Type.

How sessions are ordered inside a group: `recency` (last activity, newest first), `createdTime` (newest first), or `alphabetical` by title.

```ts
type SessionSortBy = 'recency' | 'createdTime' | 'alphabetical'
```

Source: [ui/src/chat/headless/session-list.ts:33](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/session-list.ts#L33)

### `SessionStreamSignal`

Type.

The live signals the session stream store reduces: zidane's host signals
for one session (the desktop app's `chat:stream` channel, zidane-server's
signals). Any other signal kind is ignored.

```ts
type SessionStreamSignal<K extends string = string> =
  | { kind: 'run:start'; runId?: string; sessionId: K; startedAt?: number }
  | { detail?: StreamEvent['detail']; error?: string; kind: 'run:end'; ok: boolean; runId?: string; sessionId: K }
  | { childId?: string; depth?: number; kind: 'turn:end'; sessionId: K; turnId?: string }
  | { echo?: boolean; event: ChatEvent | StreamEvent; kind: 'event'; sessionId: K }
  | { discardTurnId?: string; from?: SessionFallbackModel; kind: 'model:fallback'; sessionId: K; to: SessionFallbackModel }
  | { attempt: number; discardTurnId?: string; kind: 'stream:retry'; max: number; sessionId: K; source: string }
  | { kind: 'stream:retry:cleared'; sessionId: K; source: string }
  | { kind: 'prompt-turns'; refs: readonly PromptTurnRef[]; sessionId: K }
  | { file: SystemMdFile | null; kind: 'system-md'; sessionId: K; shadowed?: readonly SystemMdFile[] }
```

**Type parameters**

- `K` (`extends string`, default `string`)

Source: [ui/src/chat/headless/streams/types.ts:54](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/streams/types.ts#L54)

### `SessionWindowMode`

Type.

What a standalone window shows: the conversation with its panels, the conversation alone, or the panels alone.

```ts
type SessionWindowMode = 'chat+panels' | 'chat' | 'panels'
```

Source: [ui/src/chat/headless/sidebar/host.ts:17](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/host.ts#L17)

### `SetDefaultModel`

Type.

Sets the app's default model (the next new chat's); `persist: false` holds it for this window only.

```ts
type SetDefaultModel = (pick: ModelPickRef, opts?: { persist?: boolean }) => void
```

Source: [ui/src/chat/headless/composer/remember-model-pick.ts:98](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/composer/remember-model-pick.ts#L98)

### `SidebarContributionStores`

Type.

The token stores [`sidebarContributionsOf`](https://zidane.si/docs/reference/ui-chat-headless.md#sidebarContributionsOf) reads.

```ts
type SidebarContributionStores = Pick<ExtensionItemStores, typeof TOKENS[keyof typeof TOKENS]>
```

Source: [ui/src/chat/headless/sidebar/query.ts:102](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L102)

### `SidebarDotState`

Type.

What a session's dot says (`StatusDot` draws it).

```ts
type SidebarDotState =
  | 'idle'
  | 'running'
  | 'pending'
  | 'completed'
  | 'error'
  | 'attention'
  | 'attached'
```

Source: [ui/src/chat/headless/sidebar/dot-state.ts:8](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/dot-state.ts#L8)

### `SidebarGroupBy`

Type.

How the sidebar groups its rows: the session list's groupings, one section per host, or one group per agent.

```ts
type SidebarGroupBy = 'none' | 'date' | 'state' | 'project' | 'host' | 'agent'
```

Source: [ui/src/chat/headless/sidebar/types.ts:59](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L59)

### `SidebarGrouping`

Type.

How the rows group: one of the built-in groupings, or a query grouping (a space's, an extension's, the agents').

```ts
type SidebarGrouping =
  | { groupBy: Exclude<SidebarGroupBy, 'agent'>; kind: 'builtin' }
  | { groupBy: SessionGroupBy; id?: string; kind: 'query'; source: 'space' | 'extension' | 'agent' }
```

Source: [ui/src/chat/headless/sidebar/query.ts:338](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/query.ts#L338)

### `SidebarLabels`

Type.

The sidebar's strings, as [`DEFAULT_SIDEBAR_LABELS`](https://zidane.si/docs/reference/ui-chat-headless.md#DEFAULT_SIDEBAR_LABELS) has them.

```ts
type SidebarLabels = typeof DEFAULT_SIDEBAR_LABELS
```

Source: [ui/src/chat/headless/sidebar/labels.ts:163](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/labels.ts#L163)

### `SidebarLastSessions`

Type.

The conversation last open per space id.

```ts
type SidebarLastSessions = Record<string, string>
```

Source: [ui/src/chat/headless/sidebar/view.ts:145](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L145)

### `SidebarListRow`

Type.

One row of the sidebar: a session-list row (a header may name its host) or a host's section header.

```ts
type SidebarListRow<S extends SidebarListSession = SidebarListSession> = 
  | Extract<SessionListRow<S>, { kind: 'showMore' }>
  | (Extract<SessionListRow<S>, { kind: 'session' }> & { itemId?: string })
  | { childCount: number; collapsed: boolean; entry: ExtensionItem<'sidebar-row'>; id: string; kind: 'item' }
  | (Extract<SessionListRow<S>, { kind: 'header' }> & { hostId?: string; repoKey?: string })
  | { collapsed: boolean; count: number; host: HostView; id: string; kind: 'host' }
```

**Type parameters**

- `S` (`extends SidebarListSession`, default `SidebarListSession`)

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

### `SidebarNode`

Type.

What the sidebar list renders: a session or "show more" row, or a section,
a header and the rows under it, drawn as its own `<ul>` so the header
sticks while they scroll by and the next section pushes it out.

```ts
type SidebarNode<S extends SidebarListSession = SidebarListSession> = 
  | Extract<SidebarListRow<S>, { kind: 'session' } | { kind: 'showMore' }>
  | { children: SidebarNode<S>[]; header: SectionHeader<S>; id: string; kind: 'section' }
  | { children: SidebarNode<S>[]; id: string; kind: 'item'; row: Extract<SidebarListRow<S>, { kind: 'item' }> }
```

**Type parameters**

- `S` (`extends SidebarListSession`, default `SidebarListSession`)

Source: [ui/src/chat/headless/sidebar/rows.ts:376](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/rows.ts#L376)

### `SidebarOrigin`

Type.

The Origin filter: the sessions a reminder started (`scheduleId` set), or the others.

```ts
type SidebarOrigin = 'scheduled' | 'unscheduled'
```

Source: [ui/src/chat/headless/sidebar/types.ts:80](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L80)

### `SidebarSortBy`

Type.

How the sidebar orders sessions inside a group.

```ts
type SidebarSortBy = 'recency' | 'createdTime' | 'alphabetical'
```

Source: [ui/src/chat/headless/sidebar/types.ts:83](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/types.ts#L83)

### `SidebarViewMap`

Type.

Views per space id.

```ts
type SidebarViewMap = Record<string, SidebarView>
```

Source: [ui/src/chat/headless/sidebar/view.ts:137](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L137)

### `SidebarViewRecord`

Type.

A space's record as stored: its view, plus the conversation last open in it (`session`, when one was).

```ts
type SidebarViewRecord = SidebarView & { session?: string }
```

Source: [ui/src/chat/headless/sidebar/view.ts:39](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L39)

### `SidebarViewsStorage`

Type.

The Storage the views persist in (`localStorage` in a browser).

```ts
type SidebarViewsStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>
```

Source: [ui/src/chat/headless/sidebar/view.ts:176](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/sidebar/view.ts#L176)

### `SpawnMeta`

Type.

Structured subagent lifecycle metadata, as carried on `StreamEvent.spawn`.

```ts
type SpawnMeta = NonNullable<StreamEvent['spawn']>
```

Source: [ui/src/chat/headless/transcript/rows.ts:288](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L288)

### `ToolRowModel`

Type.

A paired tool call's row: what `ToolRow`, `ToolDetails` and the `ToolBody` slot read.

```ts
type ToolRowModel = Extract<Row, { kind: 'tool' }>
```

Source: [ui/src/chat/headless/transcript/rows.ts:291](https://github.com/Tahul/zidane/blob/main/ui/src/chat/headless/transcript/rows.ts#L291)

## Re-exports

These names are documented on the entry point that owns them.

- [zidane-ui/session/headless](https://zidane.si/docs/reference/ui-session-headless.md): [`PromptAttachment`](https://zidane.si/docs/reference/ui-session-headless.md#PromptAttachment)
- [zidane-ui/app/headless](https://zidane.si/docs/reference/ui-app-headless.md): [`ResourceSnapshot`](https://zidane.si/docs/reference/ui-app-headless.md#ResourceSnapshot)
