fix(state,cli,tui-gateway): keep reasoning fields intact across forks and branches (#57240) - #82109
Merged
Merged
Conversation
… and branches
get_messages() only deserializes content and tool_calls; the structured
reasoning columns (reasoning_details, codex_reasoning_items,
codex_message_items) come back as the raw TEXT they were stored as.
Feeding those rows straight back into a write, which is exactly what
the POST /api/sessions/{id}/fork handler does by piping get_messages()
into replace_messages(), hit an unguarded json.dumps() and stored the
already-serialized string encoded a second time. On replay of the fork,
json.loads() then yields the inner string instead of a list, and every
consumer's isinstance(..., list) gate silently drops it: preserved
Anthropic thinking blocks, Codex encrypted-reasoning/message-item
replay, and OpenRouter multi-turn reasoning context are all lost after
a fork, with one more encoding layer added per fork.
The /branch copy loop had the same defect from the other side: it
forwarded reasoning but none of the structured columns, and both TUI
branch writers persisted role/content alone, dropping reasoning and
reasoning_content along with them.
Route the six dumps sites in append_message and _insert_message_rows
through a shared guard that keeps already-serialized strings as-is;
structured values from the live runtime are dumped exactly as before.
Forward the reasoning fields in all three branch writers, matching the
set gateway/slash_commands.py already forwards on its own /branch path.
teknium1
force-pushed
the
fix/57240-reasoning-roundtrip
branch
from
August 9, 2026 00:24
971e915 to
6229f48
Compare
Contributor
૮ >ﻌ< ა ci reviewran on 6229f48
|
This was referenced Aug 9, 2026
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
Session forks and branches now preserve all structured reasoning fields — previously every fork double-encoded
reasoning_details/codex_reasoning_items/codex_message_itemsinto JSON strings that all replay consumers silently dropped, and the CLI/TUI/branchwriters didn't copy them at all (#57240).Root cause:
get_messages()returns those columns as raw stored TEXT, and both DB writers ran unguardedjson.dumps()on whatever they received — so the fork endpoint'sget_messages() → replace_messages()round-trip wrapped one extra quote layer per fork.Salvaged from PR #57248 by @cryptoyasenka (commit intact with authorship); it was the more complete of the two contributor fixes for #57240 (covers the branch-writer gaps in
hermes_cli+ both TUI paths, not just the DB layer).Changes
hermes_state.py:_reasoning_json_text()— strings that are already valid column TEXT are stored as-is; structures are dumped. Applied to both writers (append_message,_insert_message_rows).hermes_cli/cli_commands_mixin.py,tui_gateway/methods_session.py,tui_gateway/server.py:/branchcopy loops now forward the full reasoning field set (previously each surface copied a different subset).tests/hermes_state/test_reasoning_roundtrip.py(fork round-trip regression incl. double-fork), branch-command and TUI-branch coverage.Why this matters more since #81747
codex_reasoning_itemsnow also carries native server-side compaction checkpoints — a forked gpt-5.6 session was silently losing its checkpoint, ballooning the fork's first request back to full history cost on top of the reasoning-continuity loss originally reported.Validation
get_messages()→replace_messages()codex_reasoning_items/reasoning_detailsstay lists; compaction checkpoint byte-intact at every depthInfographic