# zidane-ui/approvals/headless

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

## Functions

### `allowDecision`

Function.

The decision an "allow" makes with a hunk selection: a `partial` decision when only some hunks
of a multi-hunk edit are checked, else `accept-once`.

```ts
function allowDecision(mask: readonly boolean[]): ApprovalDecision
```

**Parameters**

- `mask` (`readonly boolean[]`): One entry per hunk, `true` to apply it.

**Returns** `ApprovalDecision`

Source: [ui/src/approvals/headless/preview.ts:92](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L92)

### `approvalPath`

Function.

The file a file-edit request writes: its edit payload's path, else a loose read of the input
(`file_path`, `path`, `filePath`) for requests that came without a payload.

```ts
function approvalPath(request: Pick<ApprovalRequest, 'edit' | 'input'>): string | null
```

**Parameters**

- `request` (`Pick<ApprovalRequest, 'edit' | 'input'>`): The pending approval.

**Returns** `string | null`

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

### `approvalPreview`

Function.

Returns what an approval card shows for a tool call's input: a non-empty `command` as bash
with its `cwd` and `timeout`, anything else as indented JSON.

```ts
function approvalPreview(
  input: Record<string, unknown>,
  labels?: Pick<ApprovalsLabels, 'approvalCwd' | 'approvalTimeout'>,
): ApprovalPreview
```

**Parameters**

- `input` (`Record<string, unknown>`): The tool call's input.
- `labels?` (`Pick<ApprovalsLabels, 'approvalCwd' | 'approvalTimeout'>`, default `DEFAULT_APPROVALS_LABELS`): The wording of the facts under a command.

**Returns** `ApprovalPreview`

Source: [ui/src/approvals/headless/preview.ts:32](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L32)

### `createApprovalHeads`

Function.

Indexes a pending queue by session: the first request of each session (first arrival wins).
It listens to the queue only while a session has a subscriber; a read without one indexes the
queue as it is.

```ts
function createApprovalHeads(
  pending: Readable<readonly WireApprovalRequest[]>,
): ApprovalHeads
```

**Parameters**

- `pending` (`Readable<readonly WireApprovalRequest[]>`): The pending approvals, oldest first.

**Returns** `ApprovalHeads`

Source: [ui/src/approvals/headless/heads.ts:24](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/heads.ts#L24)

### `createPendingApprovals`

Function.

Creates a pending-approvals queue.

```ts
function createPendingApprovals(
  connect?: (sink: PendingApprovalsSink) => () => void,
): PendingApprovals
```

**Parameters**

- `connect?` (`(sink: PendingApprovalsSink) => () => void`): Starts listening to the backend with the queue's sink; returns how to stop. Runs while the queue has subscribers.

**Returns** `PendingApprovals`

Source: [ui/src/approvals/headless/pending.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/pending.ts#L36)

### `createSafelist`

Function.

Creates an [`ApprovalsSafelist`](https://zidane.si/docs/reference/ui-approvals-headless.md#ApprovalsSafelist) over a backend's list and remove calls.

```ts
function createSafelist(backend: SafelistBackend): ApprovalsSafelist
```

**Parameters**

- `backend` (`SafelistBackend`): The calls that read and change the safelist.

**Returns** `ApprovalsSafelist`

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

### `initialHunkMask`

Function.

The starting hunk selection of a file-edit request, one entry per hunk: only hunks the resolver
found in the file start checked (an ambiguous or missing hunk would fail if applied).

```ts
function initialHunkMask(request: Pick<ApprovalRequest, 'edit' | 'preview'>): boolean[]
```

**Parameters**

- `request` (`Pick<ApprovalRequest, 'edit' | 'preview'>`): The pending approval.

**Returns** `boolean[]`

Source: [ui/src/approvals/headless/preview.ts:81](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L81)

### `isFileEditApproval`

Function.

Whether a request gets the file-edit review rather than the inline card.

```ts
function isFileEditApproval(request: Pick<ApprovalRequest, 'tool'>): boolean
```

**Parameters**

- `request` (`Pick<ApprovalRequest, 'tool'>`): The pending approval.

**Returns** `boolean`

Source: [ui/src/approvals/headless/preview.ts:56](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L56)

## Constants

### `DEFAULT_APPROVALS_LABELS`

Constant.

The default English strings of the approval components. Override any of them through `ApprovalsProvider` or `LabelsProvider`.

```ts
const DEFAULT_APPROVALS_LABELS: { approvalAllow: string; approvalAllowForSession: string; approvalAllowNoneSelected: string; approvalAllowOnce: string; approvalAlwaysAllow: string; approvalApplySelected: (selected: number, total: number) => string; approvalClose: string; approvalConcern: (concern: ModelApproval) => string; approvalCwd: (cwd: string) => string; approvalDeny: string; approvalFileEditNoPath: string; approvalFileEditReview: string; approvalFileEditTitle: (tool: string, path: string | null) => string; approvalFromSubagent: (label: string) => string; approvalRunAfter: string; approvalRunBefore: string; approvalsError: (error: ApprovalsError) => string; approvalTimeout: (timeout: string) => string; hunkAdded: (count: number) => string; hunkAmbiguous: (matches: number) => string; hunkAmbiguousHint: (matches: number) => string; hunkFile: string; hunkInclude: (index: number, total: number) => string; hunkNewFile: string; hunkNotInFile: string; hunkNotInFileHint: string; hunkRemoved: (count: number) => string; hunkReplaceAll: string; hunksClear: string; hunksOf: string; hunksSelectAll: string; hunksSelected: string; hunksSomeMissing: string; hunkTitle: (index: number, total: number) => string; hunkVia: (via: string) => string; hunkViaHint: (via: string) => string; safelistCount: (count: number) => string; safelistDescription: string; safelistEmpty: string; safelistEmptyHint: string; safelistLoading: string; safelistProject: string; safelistRevoke: string; safelistRevoking: string; safelistTitle: string }
```

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

### `FILE_EDIT_TOOLS`

Constant.

The tools that write files: their approvals get the file-edit review (the diff, per-hunk choices).

```ts
const FILE_EDIT_TOOLS: ReadonlySet<string>
```

Source: [ui/src/approvals/headless/preview.ts:49](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L49)

## Interfaces

### `ApprovalHeads`

Interface.

Per-session heads of a pending queue.

```ts
interface ApprovalHeads
```

**Properties**

- `get` (`(sessionId: string | null) => WireApprovalRequest | null`): The first pending approval of `sessionId` (same reference while it stays the head), or `null`.
- `subscribe` (`(sessionId: string | null, onChange: () => void) => () => void`): Calls `onChange` when the head of `sessionId` changes. Returns the unsubscribe. A `null` session never changes.

Source: [ui/src/approvals/headless/heads.ts:10](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/heads.ts#L10)

### `ApprovalPreview`

Interface.

What an approval card shows for a tool call's input.

```ts
interface ApprovalPreview
```

**Properties**

- `code` (`string`): The command, or the input as indented JSON.
- `language` (`'bash' | 'json'`): How to highlight `code`.
- `meta` (`string[]`): Small facts shown under a command (`cwd …`, `timeout 30s`).

Source: [ui/src/approvals/headless/preview.ts:11](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/preview.ts#L11)

### `ApprovalsError`

Interface.

What went wrong, for the UI to word through its labels. `detail` is the backend's own message.

```ts
interface ApprovalsError
```

**Properties**

- `detail` (`string`): The backend's message, shown as is by the default labels.
- `kind` (`'read' | 'revoke'`): `read`: listing failed. `revoke`: removing a safelist entry failed.

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

### `ApprovalsHost`

Interface.

What the approval components read and the decisions they send.

```ts
interface ApprovalsHost
```

**Properties**

- `pending` (`Readable<readonly WireApprovalRequest[]>`): The approvals waiting for a decision, oldest first. The host keeps it current: new requests,
  requests answered elsewhere (another window, a terminal), and a re-read after a reconnect.
  The host starts listening when the store gets its first subscriber.
- `safelist?` (`ApprovalsSafelist`): The "Always allow" entries. Absent: no safelist panel.
- `denyAll?` (`(sessionId?: string) => Promise<void>`): Denies every pending approval, or only those of `sessionId`. Absent: no bulk deny.
- `resolve?` (`(requestId: string, decision: ApprovalDecision) => Promise<void>`): Answers a pending approval. The request leaves `pending` at once; an id that is not pending
  does nothing. Absent: the host can show approvals but not answer them.

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

### `ApprovalsSafelist`

Interface.

The safelist: what the user allowed with "Always allow", and revoking an entry.

```ts
interface ApprovalsSafelist
```

**Properties**

- `state` (`Readable<SafelistState>`): The safelist as last read.
- `refresh` (`() => Promise<void>`): Reads the safelist again. Never rejects: a failure lands in `state.error`.
- `remove?` (`(project: string, entry: string) => Promise<void>`): Removes one entry, then reads the safelist again. Rejects with an [`ApprovalsError`](https://zidane.si/docs/reference/ui-approvals-headless.md#ApprovalsError). Absent: the list is read-only.

Source: [ui/src/approvals/headless/host.ts:54](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/host.ts#L54)

### `PendingApprovals`

Interface.

The queue: a readable list, what a backend does to it, and taking requests out to answer them.

```ts
interface PendingApprovals extends Readable<readonly ApprovalRequest[]>, PendingApprovalsSink
```

**Properties**

- `add` (`(request: WireApprovalRequest) => void`, from `PendingApprovalsSink`): Appends a request, unless one with its id is already pending.
- `drop` (`(requestId: string) => void`, from `PendingApprovalsSink`): Drops a request answered elsewhere. Unknown ids do nothing.
- `get` (`() => readonly WireApprovalRequest[]`, from `Readable`): Returns the current value.
- `merge` (`(requests: readonly WireApprovalRequest[]) => void`, from `PendingApprovalsSink`): Appends the requests of a re-read that are not pending yet (a re-read never removes).
- `subscribe` (`(onChange: () => void) => () => void`, from `Readable`): Registers a listener called after the value changes. Returns a function that removes the listener.
- `take` (`(requestId: string) => WireApprovalRequest | undefined`): Takes a request out to answer it. `undefined` when it is not pending.
- `takeAll` (`(sessionId?: string) => WireApprovalRequest[]`): Takes out every pending request, or those of `sessionId`, to deny them.

Source: [ui/src/approvals/headless/pending.ts:24](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/pending.ts#L24)

### `PendingApprovalsSink`

Interface.

What a backend does to the queue: what `connect` receives.

```ts
interface PendingApprovalsSink
```

**Properties**

- `add` (`(request: WireApprovalRequest) => void`): Appends a request, unless one with its id is already pending.
- `drop` (`(requestId: string) => void`): Drops a request answered elsewhere. Unknown ids do nothing.
- `merge` (`(requests: readonly WireApprovalRequest[]) => void`): Appends the requests of a re-read that are not pending yet (a re-read never removes).

Source: [ui/src/approvals/headless/pending.ts:14](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/pending.ts#L14)

### `SafelistBackend`

Interface.

The backend calls [`createSafelist`](https://zidane.si/docs/reference/ui-approvals-headless.md#createSafelist) wraps.

```ts
interface SafelistBackend
```

**Properties**

- `describeError?` (`(error: unknown) => string`): The message to show for a failed call. Default: the error's `message`, or its text.
- `list` (`() => Promise<readonly SafelistProject[]>`): Lists every project with at least one entry.
- `remove?` (`(project: string, entry: string) => Promise<void>`): Removes one entry. Absent: the safelist is read-only.

Source: [ui/src/approvals/headless/safelist.ts:10](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/safelist.ts#L10)

### `SafelistProject`

Interface.

The "Always allow" entries of one project.

```ts
interface SafelistProject
```

**Properties**

- `entries` (`readonly string[]`): The entries, as zidane stores them (`shell:git:*`, `fetch_url`…).
- `project` (`string`): The project the entries apply to (its root folder).

Source: [ui/src/approvals/headless/host.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/host.ts#L36)

### `SafelistState`

Interface.

Where the safelist is: not read yet, being read, read, or failed.

```ts
interface SafelistState
```

**Properties**

- `error` (`ApprovalsError | null`): Why the last read failed, `null` when it did not.
- `projects` (`readonly SafelistProject[] | null`): The projects from the last read that succeeded, `null` until one did.
- `status` (`'error' | 'idle' | 'loading' | 'ready'`): `idle` before the first read; `loading` while a read is in flight; `ready` or `error` after.

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

## Types

### `ApprovalDecision`

Type.

Outcome of an approval prompt. Four bulk decisions match the original
single-edit modal contract; `partial` is the multi-edit branch — the
user accepted a subset of an `edit` / `multi_edit` / `write_file` call.

`partial.mask` is 1:1 with the call's hunks (in input order): `true`
means apply, `false` means deny. The gate handler walks the mask to
build per-hunk outcomes; the TUI rebinds `ctx.input.edits` to the
approved subset and the renderer reconstructs the full per-hunk view
from the `<edit-outcomes>` annotation appended to the tool result.

```ts
type ApprovalDecision =
  | 'accept-once'
  | 'accept-session'
  | 'accept-safelist'
  | 'deny'
  | { kind: 'partial'; mask: readonly boolean[] }
```

Source: [dist/media-type-BzRZ4FqT.d.ts:1841](https://github.com/Tahul/zidane/blob/main/dist/media-type-BzRZ4FqT.d.ts#L1841)

### `ApprovalRequest`

Type.

A tool call waiting for the user's decision: the tool and its input, the session that raised
it, the safelist entries "Always allow" adds, and for edit tools the edit and its diff preview.

```ts
type ApprovalRequest = WireApprovalRequest
```

Source: [ui/src/approvals/headless/host.ts:25](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/host.ts#L25)

### `ApprovalsLabels`

Type.

The approval components' strings: the shape of [`DEFAULT_APPROVALS_LABELS`](https://zidane.si/docs/reference/ui-approvals-headless.md#DEFAULT_APPROVALS_LABELS).

```ts
type ApprovalsLabels = typeof DEFAULT_APPROVALS_LABELS
```

Source: [ui/src/approvals/headless/labels.ts:67](https://github.com/Tahul/zidane/blob/main/ui/src/approvals/headless/labels.ts#L67)
