/** Accessible HUX-05 UI. Parent callbacks own every request and side effect. */ import { Ban, Hand, Octagon, ShieldCheck } from "lucide-react"; import { useMemo, useState } from "react"; import { AUTONOMY_LEVELS, BUDGET_MAX, CAPABILITIES, GRANT_DECISIONS, autonomyControlsEnabled, buildApprovalDecision, buildPolicyUpdate, buildStopIntent, normalizeAutonomyPage, normalizeStopReceipt, } from "./model.ts"; import type { ActiveRun, ApprovalChoice, ApprovalDecisionIntent, ApprovalView, AutonomyLevel, BudgetDraft, Capability, GrantDecision, HuxIdentity, PolicyUpdateIntent, RawAutonomyEnvelope, StopIntent, } from "./types.ts"; interface AutonomyControlsProps { flags?: Iterable; identity: HuxIdentity; conversationId: string; page: RawAutonomyEnvelope; activeRun?: ActiveRun | null; stopReceipt?: Record | null; now?: number; busy?: boolean; onUpdatePolicy?: (intent: PolicyUpdateIntent) => void; onDecideApproval?: (intent: ApprovalDecisionIntent) => void; onStop?: (intent: StopIntent) => void; } const LABELS: Readonly> = { read_files: "Read files", write_files: "Write files", shell: "Run commands", network: "Use network", web_search: "Search the web", send_message: "Send messages", memory_write: "Save memory", artifact_write: "Change artifacts", spend_tokens: "Spend model tokens", delegate: "Delegate to agents", deploy: "Deploy changes", }; const MODES: Readonly> = { ask_first: {label: "Ask First", help: "Pause before actions until you approve."}, safe: {label: "Safe Actions", help: "Read-only work may proceed; external effects still pause."}, autonomous: {label: "Autonomous", help: "Explicitly allowed capabilities may proceed within every budget."}, }; function startingBudget(page: ReturnType): BudgetDraft { return {...page!.policy.budgets, spendCentsPerRun: 0, scopeLimit: "current_task"}; } function CapabilityMatrix({grants, setGrant, busy}: { grants: Readonly>; setGrant: (capability: Capability, decision: GrantDecision) => void; busy: boolean; }) { return
Capability matrix

Missing or invalid grants are denied.

{CAPABILITIES.map((capability) => )}
CapabilityDecision
{LABELS[capability]}
; } function BudgetControls({budget, setBudget, busy}: { budget: BudgetDraft; setBudget: (next: BudgetDraft) => void; busy: boolean; }) { const number = (field: keyof typeof BUDGET_MAX, label: string, step = 1) => ; return
Per-run budgets

Zero blocks that resource. Limits are enforced together.

{number("wallClockSeconds", "Time (seconds)")} {number("spendCentsPerRun", "Spend (cents)")} {number("tokensPerRun", "Tokens", 1000)} {number("toolCallsPerRun", "Tool calls")} {number("delegationsPerRun", "Subagents")}
; } function ApprovalQueue({items, busy, decide}: { items: readonly ApprovalView[]; busy: boolean; decide: (approval: ApprovalView, choice: ApprovalChoice) => void; }) { return

Review external side effects

{items.length ?
    {items.map((approval) =>
  1. {LABELS[approval.capability]}

    {approval.summary}

    Risk: {approval.risk}. Expires .
  2. )}
:

No actions are waiting for approval.

}
; } /** Render nothing unless foundation, timeline, and autonomy are negotiated. */ export function AutonomyControls(props: AutonomyControlsProps) { const enabled = autonomyControlsEnabled(props.flags); const page = useMemo(() => enabled ? normalizeAutonomyPage(props.page, props.identity, props.conversationId, props.now) : null, [enabled, props.page, props.identity, props.conversationId, props.now]); const [autonomy, setAutonomy] = useState("ask_first"); const [grants, setGrants] = useState> | null>(null); const [budget, setBudget] = useState(null); if (!enabled) return null; if (!page) return
Autonomy controls are unavailable because identity or policy scope could not be verified.
; const selectedAutonomy = grants ? autonomy : page.policy.autonomy; const selectedGrants = grants || page.policy.grants; const selectedBudget = budget || startingBudget(page); const receipt = props.stopReceipt && props.activeRun ? normalizeStopReceipt(props.stopReceipt, props.activeRun, props.identity) : null; function decide(approval: ApprovalView, choice: ApprovalChoice) { try { props.onDecideApproval?.(buildApprovalDecision(approval, choice, props.identity, approval.requestedAt, props.now)); } catch { /* a stale approval remains denied */ } } function stop() { if (!props.activeRun) return; try { props.onStop?.(buildStopIntent(props.activeRun, props.identity, props.activeRun.runId)); } catch { /* an unowned run is never stopped */ } } return

Autonomy

Control what Hermes may do, how far it may go, and what always pauses.

{ event.preventDefault(); try { props.onUpdatePolicy?.(buildPolicyUpdate(page.policy, props.identity, selectedAutonomy, selectedGrants, selectedBudget)); } catch { /* invalid budgets fail closed */ } }}>
Autonomy level {AUTONOMY_LEVELS.map((level) => )}
setGrants({...selectedGrants, [capability]: decision})} /> {page.rejectedApprovals > 0 &&

Some approval requests were withheld because they were stale or out of scope.

} {receipt &&

Stop receipt

Outcome: {receipt.outcome}.

{receipt.stopped} effects reverted; {receipt.remaining} remain.

    {receipt.effects.map((effect, index) =>
  • {effect.description} — {effect.reverted ? "reverted" : "remaining"}
  • )}
{receipt.omittedEffects > 0 &&

{receipt.omittedEffects} additional effects omitted.

}
}

{props.busy ? "Updating autonomy controls" : `${page.approvals.length} approvals waiting`}

; }