feat: confirm prompt for destructive slash commands (#4069) - #22687
Merged
Conversation
/clear, /new, /reset, and /undo now ask the user to confirm before discarding conversation state — three-option prompt routed through the existing tools.slash_confirm primitive. Native yes/no buttons render on Telegram, Discord, and Slack (their adapters already implement send_slash_confirm); other platforms get a text-fallback prompt and reply with /approve, /always, or /cancel. The classic prompt_toolkit CLI uses the same three-option flow via the established _prompt_text_input pattern (see _confirm_and_reload_mcp). TUI keeps its existing modal overlay (#12312). Gated by new config key approvals.destructive_slash_confirm (default true). Picking 'Always Approve' flips the gate to false so subsequent destructive commands run silently — matches the established mcp_reload_confirm UX. Out of scope: /cron remove (separate domain — scheduled jobs, not session history). Existing TUI overlay env-var (HERMES_TUI_NO_CONFIRM) left unchanged; cosmetic unification can come later. Closes #4069.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
invalid-argument-type |
3 |
unresolved-import |
1 |
not-subscriptable |
1 |
invalid-return-type |
1 |
unresolved-attribute |
1 |
First entries
tests/gateway/test_destructive_slash_confirm.py:16: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/hermes_cli/test_destructive_slash_confirm_gate.py:26: [not-subscriptable] not-subscriptable: Cannot subscript object of type `int` with no `__getitem__` method
cli.py:6909: [invalid-return-type] invalid-return-type: Return type does not match returned value: expected `bool`, found `None`
tests/hermes_cli/test_destructive_slash_confirm_gate.py:26: [invalid-argument-type] invalid-argument-type: Method `__getitem__` of type `Overload[(key: SupportsIndex | slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> LiteralString, (key: SupportsIndex | slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> str]` cannot be called with key of type `Literal["destructive_slash_confirm"]` on object of type `str`
tests/hermes_cli/test_destructive_slash_confirm_gate.py:26: [invalid-argument-type] invalid-argument-type: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> Unknown, (s: slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> list[Unknown]]` cannot be called with key of type `Literal["destructive_slash_confirm"]` on object of type `list[Unknown]`
tests/hermes_cli/test_destructive_slash_confirm_gate.py:26: [invalid-argument-type] invalid-argument-type: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> str, (s: slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> list[str]]` cannot be called with key of type `Literal["destructive_slash_confirm"]` on object of type `list[str]`
tests/hermes_cli/test_destructive_slash_confirm_gate.py:32: [unresolved-attribute] unresolved-attribute: Attribute `get` is not defined on `str`, `list[Unknown]`, `list[str]`, `int` in union `str | dict[Unknown, Unknown] | list[Unknown] | ... omitted 25 union elements`
✅ Fixed issues: none
Unchanged: 4174 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
1 task
5 tasks
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/clear,/new,/reset, and/undonow ask the user to confirm before discarding conversation state — same three-option prompt (Approve Once / Always Approve / Cancel) on every surface, with native yes/no buttons on platforms that support them.Closes #4069.
How it works
Routes through the existing
tools.slash_confirmprimitive (already wired for/reload-mcp):send_slash_confirmoverride/approve,/always, or/cancel_prompt_text_input1/2/3 prompt, mirrors_confirm_and_reload_mcpChanges
hermes_cli/config.py: newapprovals.destructive_slash_confirmkey (defaulttrue)cli.py:_confirm_destructive_slashhelper;/clear,/new,/undodispatch sites gatedgateway/run.py:_maybe_confirm_destructive_slashwraps_handle_reset_commandand_handle_undo_command;_request_slash_confirmmade tolerant of bare-runner test harnessesValidation
/clear,/new,/undoon CLI/new,/undoin messengersapprovals.destructive_slash_confirm: falsefalseto config; subsequent calls silentscripts/run_tests.sh tests/cli/test_destructive_slash_confirm.py tests/gateway/test_destructive_slash_confirm.py tests/hermes_cli/test_destructive_slash_confirm_gate.py— 18/18 passingscripts/run_tests.sh tests/cli/— 647/647 passingscripts/run_tests.sh tests/gateway/— 5114/5118 passing (4 pre-existing flakes unrelated to this change, verified onorigin/main)HERMES_HOME, real config loader, realtools.slash_confirmround-trip — all four resolution paths (initial prompt, once, always→persists→silences, cancel) verifiedOut of scope
/cron remove— separate domain (scheduled jobs, not session history); the issue mentioned it but it's a different command surfaceHERMES_TUI_NO_CONFIRM) left as-is; can be unified with the new config key in a follow-up if desired