Skip to content

zidane-ui/approvals/headless

import { … } from 'zidane-ui/approvals/headless'ui/src/approvals/headless/index.ts

Functions#

allowDecisionFunction#

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.

TypeScript
function allowDecision(mask: readonly boolean[]): ApprovalDecision
Parameters
NameTypeDescription
maskreadonly boolean[]

One entry per hunk, true to apply it.

ui/src/approvals/headless/preview.ts:92

approvalPathFunction#

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.

TypeScript
function approvalPath(request: Pick<ApprovalRequest, 'edit' | 'input'>): string | null
Parameters
NameTypeDescription
requestPick<ApprovalRequest, 'edit' | 'input'>

The pending approval.

string | null

ui/src/approvals/headless/preview.ts:66

approvalPreviewFunction#

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.

TypeScript
function approvalPreview(
  input: Record<string, unknown>,
  labels?: Pick<ApprovalsLabels, 'approvalCwd' | 'approvalTimeout'>,
): ApprovalPreview
Parameters
NameTypeDefaultDescription
inputRecord<string, unknown>

The tool call's input.

labels?Pick<ApprovalsLabels, 'approvalCwd' | 'approvalTimeout'>DEFAULT_APPROVALS_LABELS

The wording of the facts under a command.

ui/src/approvals/headless/preview.ts:32

createApprovalHeadsFunction#

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.

TypeScript
function createApprovalHeads(
  pending: Readable<readonly WireApprovalRequest[]>,
): ApprovalHeads
Parameters
NameTypeDescription
pendingReadable<readonly WireApprovalRequest[]>

The pending approvals, oldest first.

ui/src/approvals/headless/heads.ts:24

createPendingApprovalsFunction#

Creates a pending-approvals queue.

TypeScript
function createPendingApprovals(
  connect?: (sink: PendingApprovalsSink) => () => void,
): PendingApprovals
Parameters
NameTypeDescription
connect?(sink: PendingApprovalsSink) => () => void

Starts listening to the backend with the queue's sink; returns how to stop. Runs while the queue has subscribers.

ui/src/approvals/headless/pending.ts:36

createSafelistFunction#

Creates an ApprovalsSafelist over a backend's list and remove calls.

TypeScript
function createSafelist(backend: SafelistBackend): ApprovalsSafelist
Parameters
NameTypeDescription
backendSafelistBackend

The calls that read and change the safelist.

ui/src/approvals/headless/safelist.ts:28

initialHunkMaskFunction#

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).

TypeScript
function initialHunkMask(request: Pick<ApprovalRequest, 'edit' | 'preview'>): boolean[]
Parameters
NameTypeDescription
requestPick<ApprovalRequest, 'edit' | 'preview'>

The pending approval.

boolean[]

ui/src/approvals/headless/preview.ts:81

isFileEditApprovalFunction#

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

TypeScript
function isFileEditApproval(request: Pick<ApprovalRequest, 'tool'>): boolean
Parameters
NameTypeDescription
requestPick<ApprovalRequest, 'tool'>

The pending approval.

boolean

ui/src/approvals/headless/preview.ts:56

Constants#

DEFAULT_APPROVALS_LABELSConstant#

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

TypeScript
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 }

ui/src/approvals/headless/labels.ts:12

FILE_EDIT_TOOLSConstant#

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

TypeScript
const FILE_EDIT_TOOLS: ReadonlySet<string>

ui/src/approvals/headless/preview.ts:49

Interfaces#

ApprovalHeadsInterface#

Per-session heads of a pending queue.

TypeScript
interface ApprovalHeads
ApprovalHeads properties
NameTypeDescription
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.

ui/src/approvals/headless/heads.ts:10

ApprovalPreviewInterface#

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

TypeScript
interface ApprovalPreview
ApprovalPreview properties
NameTypeDescription
codestring

The command, or the input as indented JSON.

language'bash' | 'json'

How to highlight code.

metastring[]

Small facts shown under a command (cwd …, timeout 30s).

ui/src/approvals/headless/preview.ts:11

ApprovalsErrorInterface#

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

TypeScript
interface ApprovalsError
ApprovalsError properties
NameTypeDescription
detailstring

The backend's message, shown as is by the default labels.

kind'read' | 'revoke'

read: listing failed. revoke: removing a safelist entry failed.

ui/src/approvals/headless/host.ts:28

ApprovalsHostInterface#

What the approval components read and the decisions they send.

TypeScript
interface ApprovalsHost
ApprovalsHost properties
NameTypeDescription
pendingReadable<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.

ui/src/approvals/headless/host.ts:64

ApprovalsSafelistInterface#

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

TypeScript
interface ApprovalsSafelist
ApprovalsSafelist properties
NameTypeDescription
stateReadable<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. Absent: the list is read-only.

ui/src/approvals/headless/host.ts:54

PendingApprovalsInterface#

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

TypeScript
interface PendingApprovals extends Readable<readonly ApprovalRequest[]>, PendingApprovalsSink
PendingApprovals properties
NameTypeDescription
addfrom PendingApprovalsSink(request: WireApprovalRequest) => void

Appends a request, unless one with its id is already pending.

dropfrom PendingApprovalsSink(requestId: string) => void

Drops a request answered elsewhere. Unknown ids do nothing.

getfrom Readable() => readonly WireApprovalRequest[]

Returns the current value.

mergefrom PendingApprovalsSink(requests: readonly WireApprovalRequest[]) => void

Appends the requests of a re-read that are not pending yet (a re-read never removes).

subscribefrom Readable(onChange: () => void) => () => void

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.

ui/src/approvals/headless/pending.ts:24

PendingApprovalsSinkInterface#

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

TypeScript
interface PendingApprovalsSink
PendingApprovalsSink properties
NameTypeDescription
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).

ui/src/approvals/headless/pending.ts:14

SafelistBackendInterface#

The backend calls createSafelist wraps.

TypeScript
interface SafelistBackend
SafelistBackend properties
NameTypeDescription
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.

ui/src/approvals/headless/safelist.ts:10

SafelistProjectInterface#

The "Always allow" entries of one project.

TypeScript
interface SafelistProject
SafelistProject properties
NameTypeDescription
entriesreadonly string[]

The entries, as zidane stores them (shell:git:*, fetch_url…).

projectstring

The project the entries apply to (its root folder).

ui/src/approvals/headless/host.ts:36

SafelistStateInterface#

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

TypeScript
interface SafelistState
SafelistState properties
NameTypeDescription
errorApprovalsError | null

Why the last read failed, null when it did not.

projectsreadonly 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.

ui/src/approvals/headless/host.ts:44

Types#

ApprovalDecisionType#

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.

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

dist/media-type-BzRZ4FqT.d.ts:1841

ApprovalRequestType#

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.

TypeScript
type ApprovalRequest = WireApprovalRequest

ui/src/approvals/headless/host.ts:25

ApprovalsLabelsType#

The approval components' strings: the shape of DEFAULT_APPROVALS_LABELS.

TypeScript
type ApprovalsLabels = typeof DEFAULT_APPROVALS_LABELS

ui/src/approvals/headless/labels.ts:67