import type { AgentHooks } from "./agent-hooks.js";
import { type Json, type Target } from "./protocol.js";
/** An agent's permission mode as its own footer names it, and the route that
 * changes it by pressing Shift+Tab through the harness's cycle. The phone's
 * mode picker reads `agentStatus.permissionMode` / `permissionModes` off the
 * chat status stream and posts one back here. Only Claude Code draws the mode
 * in its footer; Codex and OpenCode keep theirs in config, so they offer none. */
/** Claude Code's `permissionMode` values in Shift+Tab cycle order. "default" is
 * the footer's "manual mode on"; "auto" is "auto mode on". */
export declare const PERMISSION_CYCLE: readonly ["default", "acceptEdits", "plan", "auto"];
/** `bypassPermissions` is in the cycle only for a session launched allowing
 * bypass, so it is a valid mode but not part of the standard list. */
export declare const PERMISSION_MODE_VALUES: readonly ["default", "acceptEdits", "plan", "auto", "bypassPermissions"];
export type PermissionModeName = (typeof PERMISSION_MODE_VALUES)[number];
/** The modes a Claude pane offers, in Shift+Tab cycle order. `bypass` adds the
 * one only a session launched with --allow-dangerously-skip-permissions has. */
export declare function permissionModes(bypass: boolean): PermissionModeName[];
/** Claude's permission mode from the footer line its TUI draws under the
 * composer. The transcript lags it: a `permission-mode` row is written only
 * when a prompt is submitted, and a fresh session has no file yet. The line may
 * trail hints ("(shift+tab to cycle) · 1 agent"), so only its start counts. A
 * mode the footer does not mark is `undefined`: "manual mode on" is default. */
export declare function claudeFooterMode(screen: string): PermissionModeName | undefined;
/** Only the owner changes a session's permission mode, from the phone. An
 * agent's call names its own pane (`origin`), and none is accepted: an agent
 * could otherwise lift itself or another pane past the per-grant
 * `maxPermissionMode` ceiling, up to bypassPermissions. Same rule as
 * `/v1/sudo/answer`. */
export declare function refuseAgentOrigin(actor: unknown): void;
/** One Shift+Tab transaction per pane owns its terminal input until it ends,
 * like the settings switcher, so a mode change and a settings change never
 * press into the same composer at once. */
export declare class PermissionModeSwitcher {
    private readonly hooks;
    private readonly wait;
    private active;
    constructor(hooks: AgentHooks, wait?: number);
    private key;
    assertAvailable(target: Target): void;
    /** Steps the pane to `mode`, or refuses. Only Claude offers the cycle; the
     * machine's authority policy never caps an owner's own choice. */
    set(target: Target, mode: PermissionModeName, actor?: unknown): Promise<Json>;
    private cycle;
    /** The mode after a press: polled from the screen until it differs from
     * `from`, because the TUI redraws the footer asynchronously. */
    private changed;
    private assertLive;
}
