fix(cli): keep session alive when a destructive slash confirm is cancelled - #40733
fix(cli): keep session alive when a destructive slash confirm is cancelled#40733entropy-0x wants to merge 1 commit into
Conversation
…elled
process_command() is contracted to return bool ("True to continue, False to
exit"), and the REPL loop exits the session when the call is falsy:
`if not self.process_command(user_input): self._should_exit = True; app.exit()`.
The cancel branches of the destructive session commands (/clear, /new, /reset,
/undo) did a bare `return` (None) when _confirm_destructive_slash() returned
None. Since `not None` is True, picking "Cancel — keep current conversation"
exited the entire interactive session and dropped the live agent state — the
opposite of the user's intent. The /undo invalid-count branch had the same
bare return. The falsy path also reaches the inline dispatch site.
Return True from those branches so cancelling keeps the REPL running.
## What does this PR do?
Fixes a bug where cancelling the confirmation prompt for a destructive session
slash command (/clear, /new, /reset, /undo) exited the whole CLI session
instead of returning to the prompt with the conversation intact. The cancel
branches returned None, which the REPL loop treats as a request to exit.
## Related Issue
N/A
## Type of Change
- [x] 🐛 Bug fix (non-breaking change that fixes an issue)
- [ ] ✨ New feature (non-breaking change that adds functionality)
- [ ] 🔒 Security fix
- [ ] 📝 Documentation update
- [ ] ✅ Tests (adding or improving test coverage)
- [ ] ♻️ Refactor (no behavior change)
- [ ] 🎯 New skill (bundled or hub)
## Changes Made
- `cli.py`: changed the bare `return` to `return True` in the cancel branches
of `/clear`, `/new`, and `/undo`, and in the `/undo` invalid-count branch
inside `process_command()`, honoring its `-> bool` contract.
- `tests/cli/test_destructive_slash_cancel_keeps_session.py`: added a
regression test asserting `process_command()` returns True (and does not run
new_session/undo_last) when the destructive-confirm prompt is cancelled.
## How to Test
1. Run `hermes` to enter the interactive CLI.
2. Type `/clear` (or `/new`, `/reset`, `/undo`) and select
"Cancel — keep current conversation" at the prompt.
3. Before the fix the session exits; after the fix the prompt returns with the
conversation intact.
4. Automated: `pytest tests/cli/test_destructive_slash_cancel_keeps_session.py -q`.
## Checklist
### Code
- [x] I've read the [Contributing Guide](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md)
- [x] My commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) (`fix(scope):`, `feat(scope):`, etc.)
- [x] I searched for [existing PRs](https://github.com/NousResearch/hermes-agent/pulls) to make sure this isn't a duplicate
- [x] My PR contains **only** changes related to this fix/feature (no unrelated commits)
- [x] I've run `pytest tests/ -q` and all tests pass
- [x] I've added tests for my changes (required for bug fixes, strongly encouraged for features)
- [x] I've tested on my platform: macOS 15.5
### Documentation & Housekeeping
- [x] I've updated relevant documentation (README, `docs/`, docstrings) — or N/A
- [x] I've updated `cli-config.yaml.example` if I added/changed config keys — or N/A
- [x] I've updated `CONTRIBUTING.md` or `AGENTS.md` if I changed architecture or workflows — or N/A
- [x] I've considered cross-platform impact (Windows, macOS) per the [compatibility guide](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md#cross-platform-compatibility) — or N/A
- [x] I've updated tool descriptions/schemas if I changed tool behavior — or N/A
|
Thanks for identifying the Problems
Suggested changes
Automated hermes-sweeper review. |
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Summary
Two PRs address the same falsy-return defect in process_command(): both change destructive-confirm cancellation and invalid /undo count paths from None to True, with regression coverage. Current main already contains the cancellation fixes via #40583, leaving only the invalid-count branch as the production defect to salvage.
Related pull requests
- #40733
related— (+52/-4) — salvage and merge: The diff fixes all four bare returns and adds fixture-based coverage for cancellation plus invalid/undocounts; as the contributor review notes, the three cancellation production hunks overlap current main, so #40733 should be rebased to retain only the invalid-count fix while preserving useful regression tests. - #41019
duplicate— (+97/-4) — duplicate of #40733: Its production diff is identical, while its tests cover the same behavior through aSimpleNamespacestand-in. Despite the keep_open review on #41019, the complete diff shows no distinct production fix beyond #40733, and the review itself requires the same reduction to the remaining invalid-count branch.
Duplicates
#40733 and #41019 contain identical production changes and substantially duplicate regression coverage for the same process_command() return-value defect.
Suggested consolidation
Merge #40733 after reconciling it with current main: retain the /undo invalid-count return True fix and adapt the regression coverage, while dropping the three production hunks already implemented by #40583. Close #41019 as a duplicate of #40733; this does not disregard its keep_open review, because that review identifies the same salvageable invalid-count fix but the diff provides no independent implementation to preserve.
Complex graph
flowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
subgraph Dup40733 ["PRs duplicating each other"]
P40733["PR #40733 (open)"]
P41019["PR #41019 (open)"]
end
class P40733 open
class P41019 open
class P40733 target
click P40733 "https://github.com/NousResearch/hermes-agent/pull/40733"
click P41019 "https://github.com/NousResearch/hermes-agent/pull/41019"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).
Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 9 kB of PR diffs, 7 kB of issue/PR text, 2 kB of discussion (2 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
process_command() is contracted to return bool ("True to continue, False to
exit"), and the REPL loop exits the session when the call is falsy:
if not self.process_command(user_input): self._should_exit = True; app.exit().The cancel branches of the destructive session commands (/clear, /new, /reset,
/undo) did a bare
return(None) when _confirm_destructive_slash() returnedNone. Since
not Noneis True, picking "Cancel — keep current conversation"exited the entire interactive session and dropped the live agent state — the
opposite of the user's intent. The /undo invalid-count branch had the same
bare return. The falsy path also reaches the inline dispatch site.
Return True from those branches so cancelling keeps the REPL running.
What does this PR do?
Fixes a bug where cancelling the confirmation prompt for a destructive session
slash command (/clear, /new, /reset, /undo) exited the whole CLI session
instead of returning to the prompt with the conversation intact. The cancel
branches returned None, which the REPL loop treats as a request to exit.
Related Issue
N/A
Type of Change
Changes Made
cli.py: changed the barereturntoreturn Truein the cancel branchesof
/clear,/new, and/undo, and in the/undoinvalid-count branchinside
process_command(), honoring its-> boolcontract.tests/cli/test_destructive_slash_cancel_keeps_session.py: added aregression test asserting
process_command()returns True (and does not runnew_session/undo_last) when the destructive-confirm prompt is cancelled.
How to Test
hermesto enter the interactive CLI./clear(or/new,/reset,/undo) and select"Cancel — keep current conversation" at the prompt.
conversation intact.
pytest tests/cli/test_destructive_slash_cancel_keeps_session.py -q.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A