@phren/cli
Version:
Knowledge layer for AI agents - CLI, MCP server, and data layer
49 lines (48 loc) • 3.06 kB
TypeScript
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;
}