mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
* fix(desktop): render approval/sudo/secret prompts so tools stop silently timing out The desktop app's gateway event handler (use-message-stream.ts) handled clarify.request but had no case for approval.request, sudo.request, or secret.request. When a tool needed approval, the gateway emitted approval.request and blocked the agent thread in _await_gateway_decision() for up to 5 min (approvals.gateway_timeout); the desktop dropped the unknown event, never showed a dialog, then the agent returned BLOCKED. No prompt, just a stall then a block. The Ink TUI already handles all three (createGatewayEventHandler.ts); this brings the Electron app to parity. - store/prompts.ts: approval/sudo/secret atoms (+ request-id-guarded clears) - components/prompt-overlays.tsx: Radix dialogs; close/Esc maps to refusal so silence is never mistaken for consent (parity with TUI Esc->deny) - use-message-stream.ts: wire the three *.request cases; clearAllPrompts on message.complete so an overlay can't outlive its turn - chat-messages.ts: GatewayEventPayload gains command/description/env_var/prompt - mount PromptOverlays in the chat shell * feat(desktop): inline tool-call approval bar (Cursor-style "Run") Render dangerous-command / execute_code approval inline on the pending tool row instead of as a modal. Binding is positional: the desktop tool.start payload carries no structured args, but approval.request only fires from the terminal/execute_code guards and the agent blocks on one approval at a time, so the single pending row of those tools is the one that raised it. Command/description text comes from $approvalRequest. Drops ApprovalDialog from PromptOverlays (sudo/secret stay modal). * style(desktop): make inline approval bar match Cursor's command card Drop the amber alert styling for a neutral elevated card: command on a terminal-prefixed row up top, a divided footer with the muted description on the left and right-aligned controls — a ghost "Reject" (Esc) plus a split primary "Run" (⌘⏎) whose chevron opens "Allow this session" / "Always allow" / "Reject". Wire ⌘/Ctrl+Enter → Run and Esc → Reject to match Cursor's accept/skip bindings, guarded against double-send via the $approvalRequest atom. * style(desktop): shrink inline approval to a tiny Cursor-style button strip The running tool row already shows the command, so drop the whole card + command echo + description band. What's left is a compact strip under the row: a small split "Run ⌘⏎" button (chevron → Allow this session / Always allow / Reject) and a ghost "Reject Esc", indented to sit under the row's title text. * style(desktop): drop the loud blue Run button for a quiet outlined control Swap the primary (blue) Run for a subtle outlined split control — neutral border, transparent fill, hover-accent — so the approval strip reads as quiet inline affordance rather than a big CTA. Reject stays ghost. * style(desktop): make Run a soft primary badge Tint the Run split control with the primary color as a badge (bg-primary/10, primary text, primary/25 border, rounded-md, hover primary/15) instead of a solid CTA or a neutral outline. * style(desktop): slim the approval chevron and space out Reject The chevron button had ballooned because dropping the size prop fell back to the big default size (h-9 + has-svg px-3). Pin size=xs everywhere and give the chevron a tight w-5/px-0. Bump the gap between the Run badge and Reject (gap-2.5) and loosen Reject's internal spacing. * feat(desktop): confirm before "Always allow" persists an approval "Always allow" writes the matched pattern to ~/.hermes/config.yaml and suppresses the prompt in every future session — too consequential to fire straight from a menu click. Route it through a confirm dialog that names the pattern + command and the file it touches. The dialog owns the keyboard while open so Esc closes it instead of denying the approval. * fix(gateway): make sudo + secret prompts actually fire in the desktop Tek's PR added the sudo/secret overlays and callback wiring, but neither reached the live path: - Sudo: the sudo password callback is thread-local (terminal_tool _callback_tls), and _wire_callbacks runs on the agent-build thread, not the turn thread that executes tools. At command time the callback was missing, so terminal sudo fell through to /dev/tty and hung the headless gateway. Re-wire callbacks at the top of the prompt-submit turn thread. - Secret: skills_tool short-circuited to the "secret entry unsupported" hint for any gateway surface, before invoking the callback. Interactive surfaces (desktop/TUI) register a secret-capture callback that routes to the secret.request overlay; only short-circuit when no callback exists, so messaging still gets the hint but the desktop prompts. * docs(desktop): drop Cursor references from approval comments * docs(desktop): drop Cursor reference from prompt-overlays comment * fix(skills): gate in-band secret capture on HERMES_INTERACTIVE, not callback presence The desktop/sudo PR switched the gateway secret-capture short-circuit from "any gateway surface" to "gateway surface with no callback registered". That made a messaging gateway (telegram/discord/...) attempt interactive in-band secret capture whenever any callback happened to be registered, instead of returning the safe "setup unsupported" hint — and broke test_gateway_still_loads_skill_but_returns_setup_guidance. Discriminate on HERMES_INTERACTIVE instead: the desktop app / TUI set it in _enable_gateway_prompts (alongside registering the secret.request callback), while messaging platforms never do. This is the same flag tools/approval.py uses to tell an interactive surface from a messaging one, so messaging keeps the hint and desktop/TUI still prompt. --------- Co-authored-by: Brooklyn Nicholson <brooklyn.bb.nicholson@gmail.com> |
||
|---|---|---|
| .. | ||
| bootstrap-installer | ||
| desktop | ||
| shared | ||