/** * PermissionPrompt - Render permission request * Renders via ANSI terminal output. Callbacks route through parent * which enforces INV-3 via ToolRegistry/PermissionEngine. * * @module packages/tui/src/components/PermissionPrompt */ /** Command channel interface for INV-3 compliance. */ export interface UiCommandChannel { allow_tool(tool_name: string): void deny_tool(tool_name: string): void always_allow_tool(tool_name: string): void } export interface PermissionPromptProps { tool_name: string reason: string risk_score: number channel?: UiCommandChannel on_allow: () => void on_deny: () => void on_always_allow?: () => void } export function PermissionPrompt({ tool_name, reason, risk_score, channel, on_allow, on_deny, on_always_allow }: PermissionPromptProps): string { const risk_bar = '█'.repeat(Math.min(10, Math.ceil(risk_score / 10))) + '░'.repeat(Math.max(0, 10 - Math.ceil(risk_score / 10))) // Callbacks are explicitly allowed: the parent routes them through ToolRegistry (INV-3) const allowFn = () => { if (channel) channel.allow_tool(tool_name); else on_allow() } const denyFn = () => { if (channel) channel.deny_tool(tool_name); else on_deny() } const alwaysFn = () => { if (channel) channel.always_allow_tool(tool_name); else on_always_allow?.() } return [ '═══ Permission Required ═══', `Tool: ${tool_name}`, `Reason: ${reason}`, `Risk: [${risk_bar}] ${risk_score}/100`, '', '[A] Allow [D] Deny [S] Allow Always', '═══════════════════════════' ].join('\n') }