Repository navigation
feat(chat): versions: regenerate, edit and switch in a conversation tree - #467
Merged
Merged
Conversation
A conversation is now a tree: chat_message.parent and chat.head. Regenerate
writes a new answer beside the old one, edit makes a new version of a question
beside it instead of deleting what followed, and parent goes on from any
message. GET /chats/{cid} adds tree, head and each message's versions; PUT
/chats/{cid}/head switches. The model reads only the version showing; a
summary written on another version is ignored and rewritten for this one.
Upgrade step chat-tree lines existing conversations up, safe to run twice.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
19 of 22 tasks
This was referenced Oct 17, 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.
Requested by Adeel · project thread
Description
Before: a conversation was one line. Editing a question deleted it and everything after it, and "Ask again with" added the same question again at the end.
After: a conversation is a tree, and nothing in it is deleted. Through the API:
POST /api/v1/chats/{cid}/messageswithregenerate: <answer id>writes a new answer to the same question beside the old one, with the same model or another (model).edit: <question id>makes a new version of that question beside it and answers it. The old question keeps what followed it.parent: <message id>goes on from any message instead of the version showing.GET /api/v1/chats/{cid}gives the version showing asmessages(same shape as before). Each message now carriesparentandversions(indexfrom 1,count,ids). The response also addstree(every message of every version) andhead.PUT /api/v1/chats/{cid}/head {"message": id}switches to the version that message is in, down to its newest message.branchfirst when a new version is made.The model reads only the version showing. A running summary covers the version it was written on. On another version the summary is ignored, and the next compaction writes one for that version.
/clearand/compactact on the version they're typed on. Chat rooms and automations carry on from the head as before.In the web app, Edit still looks the same: the new version shows in place of the old question. The switcher (
‹ 2 / 3 ›) and the Regenerate button come in the next PR, and the docs label them as in progress.How:
chat_message.parentandchat.headhold the tree.chat.pathwalks the parents in Python after one query for the conversation's ids.chat.addsaves under the head by default and moves the head. The upgrade stepchat-treeturns existing conversations into one line each: every message gets the one before it as its parent, and the last becomes the head. It only touches conversations without a head, so it is safe to run twice. Until it has run, a conversation without a head is still read as one line.Motivation and Context
Part of the chat gaps Adeel listed: regenerate, a response tree, and carrying on from any version. This is module C2 of the plan, backend part.
Screenshots (if appropriate):
n/a (API only; the web app's switcher is the next PR)
Steps to reproduce (if appropriate):
POST /api/v1/chats/{cid}/messages {"regenerate": <first answer id>, "model": "<another model>"}. You get abranchevent and then the new answer.GET /api/v1/chats/{cid}. The first answer now showsversions: {index: 2, count: 2}, andtreeholds all 5 messages.PUT /api/v1/chats/{cid}/head {"message": <first answer id>}shows the first version again, down to its last answer.Types of changes
!in the title)Checklist:
make hookschecks it on commit).docs/accordingly.## UnreleasedinCHANGELOG.md.Done questions (AGENTS.md)
regenerate,edit,parent,PUT /chats/{cid}/head,treeandversionsin GET). C3'sread_chatMCP tool will return the tree.parent,regenerate,editand the head must be messages of that conversation, otherwise 404. There is no new attack surface, so the threat model is unchanged.chat-treeis safe to run twice and tested twice. Reads stay right before it runs (docs/database.md› Upgrades).test_chat_versions.py, plus updates to the compaction, chats and migrations tests.docs/assistant.md› Versions anddocs/database.md› Upgrades are updated, and the client was regenerated with tooling.Generated by Claude Code