import { type JSX } from "react"; /** * Permission payload emitted by the extension when a tool call needs user * approval (write_file, run_command, etc). The webview extracts this from a * `bandit-permission` fenced block in the assistant message and renders the * interactive card in-place. Once the user picks, we post back and flip the * card into a resolved state — so the card is authoritative UI rather than * the extension's chat-message text copy (which is for history). */ export interface BanditPermissionPayload { type: "bandit:permission"; id: string; tool: string; primary: string; description: string; /** Short risk summary from the host permission gate. */ risk?: string; bodyPreview?: string; /** * Optional advisory the extension surfaces on the card BEFORE the user * decides. Used for the "creating a new file at X — did you mean to * edit an existing one?" warning when write_file targets a path that * doesn't yet exist and the user's prompt implied editing. */ warning?: string; /** * +/- line counts extracted from bodyPreview so we can show a compact * "Modified · +12 -3" summary instead of the full diff. When omitted, * the card falls back to rendering bodyPreview expanded (back-compat). */ diffStats?: { added: number; removed: number; }; /** * Raw command text for run_command prompts — the full shell string the * agent wants to execute (e.g. `grep -rE "pattern" ~/path | head -40`). * Shown in a monospace block above the buttons so the user can audit * the command verbatim before approving. Claude Code shows the whole * command; we were only showing the tool name + first param, which hid * pipes / flags / second args. Undefined for non-command tools. */ command?: string; /** * Formatted key=value param dump for non-command tools. When present * and `bodyPreview` is empty, we render this in the same position as * `command` so the user can see exactly what'll be invoked * (apply_edit find/replace, git_checkout branch name, etc). */ paramsPreview?: string; /** * Risk tier from the shared classifier: `routine` | `elevated` | `critical`. * Drives the card's visual weight — users approve dozens of these a session, * and if a delete renders identically to a file read the card stops being * read at all. */ tier?: string; /** * What each grant scope would actually authorize, keyed by choice. Rendered * as the button's hint so the user reads the blast radius before clicking. * Generated host-side by `grantRuleFor` — the same call that computes the * rule that gets stored, so the card cannot promise one scope and save * another. Falls back to the static hints below when absent. */ scopeHints?: Record; /** * True when a saved allow rule already covered this call but the * critical-tier floor overrode it. Without saying so, the user sees a prompt * for something they believe they already approved and concludes the grant * is broken. */ flooredByRisk?: boolean; } export type PermissionChoice = "once" | "session" | "save" | "deny"; export interface PermissionCardProps { payload: BanditPermissionPayload; /** * Fires once per card. `notes` is populated only when the user picked * "Deny with notes" and typed follow-up guidance — the extension pipes * that back to the model as part of the denial reason so the agent * adjusts its plan rather than just seeing "blocked." */ onChoice: (id: string, choice: PermissionChoice, notes?: string) => void; /** * Host-owned decision state. Omit it and the card resolves itself the * moment the user picks (the original behaviour). Pass it and the card * only reports what the host says: `submitting` while the decision is in * flight, `resolved` once the host has applied it, `error` to let the user * retry, `expired` when the agent is no longer waiting. */ status?: PermissionCardStatus; /** * Focus the card while it is pending so the 1/2/3 shortcuts work without a * click (default `true`). The focus never scrolls the page. */ autoFocus?: boolean; } export type PermissionCardStatus = { state: "pending"; } | { state: "submitting"; choice: PermissionChoice; } | { state: "resolved"; choice: PermissionChoice; notes?: string; /** Where the host stored an "Always allow" rule. The card never claims * a rule was saved unless the host says where. */ savedTo?: string; } | { state: "error"; message: string; } | { state: "expired"; reason?: string; }; export declare const PermissionCard: ({ payload, onChoice, status, autoFocus }: PermissionCardProps) => JSX.Element; /** Status line for a card that is no longer waiting on the user. */ export declare function describeOutcome(view: PermissionCardStatus, hostConfirmed: boolean): string; //# sourceMappingURL=PermissionCard.d.ts.map