fix(desktop): skip failed turns in regenerate/edit truncation ordinal - #41275
fix(desktop): skip failed turns in regenerate/edit truncation ordinal#41275vondelomlo wants to merge 1 commit into
Conversation
## What does this PR do?
Regenerate stayed silently broken after any failed turn — this realigns
the client-side truncation ordinal with backend history.
A user turn whose `prompt.submit` fails keeps its optimistic bubble in the
transcript, but that turn is never written to backend history. The desktop
`visibleUserOrdinal` helper still counted those failed turns, so every later
`truncate_before_user_ordinal` overshot the gateway's persisted-history index.
The backend then rejected the request with error 4018 ("target user message is
no longer in session history"). `editMessage` recovers via a plain resend, but
`reloadFromMessage` (regenerate) has no fallback — it just surfaces
"regenerate failed", so the feature is unusable for the rest of the session.
The fix excludes failed/optimistic user turns (a user message immediately
followed by an assistant error) from the count, mirroring the existing
`isFailedTurn` heuristic already used in `editMessage`, so the client and
backend ordinals stay in lockstep.
## 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
- `apps/desktop/src/app/session/hooks/use-prompt-actions.ts` — `visibleUserOrdinal` now skips failed/optimistic user turns so the ordinal matches the gateway's persisted-history count; exported for direct unit testing.
- `apps/desktop/src/app/session/hooks/use-prompt-actions.test.tsx` — added coverage for the counter: normal turns, a failed turn (must be skipped), and hidden branched-away turns.
## How to Test
1. In the desktop app, send a message while a provider is unreachable — an inline assistant error appears and the user bubble stays.
2. Send a second message that succeeds.
3. Hover the successful turn and click Regenerate. Before: it fails with "regenerate failed". After: it regenerates correctly.
4. Unit test: `cd apps/desktop && npx vitest run --environment jsdom src/app/session/hooks/use-prompt-actions.test.tsx` (14 passing).
## 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 added tests for my changes (required for bug fixes, strongly encouraged for features)
- [x] I've tested on my platform: macOS 15 (vitest + tsc + eslint)
### 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
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary (PR #41275)
Verdict: Approved
Looks Good
- Fixes ordinal misalignment between desktop UI and backend when a failed turn (assistant error) is visible to the user but not persisted in gateway history
visibleUserOrdinalnow skips failed assistant turns, preventing error 4018 on regenerate- Tests cover: failed turn skip, hidden (branched) turn skip, normal counting
- Good inline documentation explaining the root cause
Reviewed by Hermes Agent
|
Thanks for identifying the client/backend ordinal mismatch; current main still has the naive counter in Problems
Suggested changes
Automated hermes-sweeper review. |
A user turn whose submit failed keeps its optimistic bubble but never reached the gateway, so counting it makes every later truncate_before_user_ordinal overshoot the backend index (refused 4018, regenerate dead for the rest of the session). Skip failed turns in the one shared visible-user ordinal space (visibleUserMessageIndices) used by truncate ordinals, ordinal->index resolution, and survivor-rowId rebinding. Based on #41275 by @vondelomlo, relocated onto the split use-prompt-actions/ modules and widened from visibleUserOrdinal to the shared index helper.
|
Salvaged into #87294 (merged) — your failed-turn ordinal fix now lives in Thanks for the fix and the clean test coverage — closing since the work has landed. |
What does this PR do?
Regenerate stayed silently broken after any failed turn — this realigns
the client-side truncation ordinal with backend history.
A user turn whose
prompt.submitfails keeps its optimistic bubble in thetranscript, but that turn is never written to backend history. The desktop
visibleUserOrdinalhelper still counted those failed turns, so every latertruncate_before_user_ordinalovershot the gateway's persisted-history index.The backend then rejected the request with error 4018 ("target user message is
no longer in session history").
editMessagerecovers via a plain resend, butreloadFromMessage(regenerate) has no fallback — it just surfaces"regenerate failed", so the feature is unusable for the rest of the session.
The fix excludes failed/optimistic user turns (a user message immediately
followed by an assistant error) from the count, mirroring the existing
isFailedTurnheuristic already used ineditMessage, so the client andbackend ordinals stay in lockstep.
Related Issue
N/A
Type of Change
Changes Made
apps/desktop/src/app/session/hooks/use-prompt-actions.ts—visibleUserOrdinalnow skips failed/optimistic user turns so the ordinal matches the gateway's persisted-history count; exported for direct unit testing.apps/desktop/src/app/session/hooks/use-prompt-actions.test.tsx— added coverage for the counter: normal turns, a failed turn (must be skipped), and hidden branched-away turns.How to Test
cd apps/desktop && npx vitest run --environment jsdom src/app/session/hooks/use-prompt-actions.test.tsx(14 passing).Checklist
Code
fix(scope):,feat(scope):, etc.)Documentation & 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