Skip to content

ui: export full message tree instead of active path only#25501

Merged
allozaur merged 1 commit into
ggml-org:masterfrom
ServeurpersoCom:ui/export-full-message-tree
Jul 10, 2026
Merged

ui: export full message tree instead of active path only#25501
allozaur merged 1 commit into
ggml-org:masterfrom
ServeurpersoCom:ui/export-full-message-tree

Conversation

@ServeurpersoCom

Copy link
Copy Markdown
Contributor

Overview

When you export a single conversation from the sidebar (the "..." menu -> Export), you now get every version of your messages, not just the one currently displayed.

Before, if you had edited or regenerated a message, the exported file only contained the version you were looking at. The other versions were silently left out, so re-importing the file gave you back a trimmed conversation with your alternate takes gone.

Now the export contains the complete message tree of that conversation, so importing it restores everything exactly as it was, with all your edited and regenerated versions still navigable ("<" and ">" under messages).

Forks are untouched: a fork is its own conversation, so it keeps its own separate export.

Additional information

Before :

{"type":"session","harness":"llama.app","id":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","name":"Hello","lastModified":1783620763176,"currNode":"81cab215-ca15-4b37-91fd-f6e196059e86","thinkingEnabled":false}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","role":"user","content":"Hello","type":"text","timestamp":1783619815561,"children":["235b8431-e2fd-4199-9bbd-4d5d0e803a56"],"extra":[],"id":"48bbf4f9-3885-449a-8c92-f957222b2d5e","parent":"32c264eb-f5f2-4acd-ab6c-d24800de3298"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","role":"assistant","content":"Hello! How can I help you today?","timestamp":1783619815579,"children":["28dcb160-10e1-42d4-97da-707c8c9141bd","3c0444bd-0468-4a76-bcba-4f6a9551be9a","005bc344-aac6-43b8-a29e-c16e3293c6a1"],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"235b8431-e2fd-4199-9bbd-4d5d0e803a56","parent":"48bbf4f9-3885-449a-8c92-f957222b2d5e","completionId":"chatcmpl-R4xxYJgsj3tzzi7FeXE2B6hb0UrKhufl","timings":{"cache_n":0,"prompt_n":1584,"prompt_ms":258.951,"prompt_per_token_ms":0.16347916666666668,"prompt_per_second":6116.98738371352,"predicted_n":10,"predicted_ms":40.03,"predicted_per_token_ms":4.003,"predicted_per_second":249.81264051961028}}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620313399,"role":"user","content":"Test. Edit2","children":["81cab215-ca15-4b37-91fd-f6e196059e86"],"extra":[],"id":"005bc344-aac6-43b8-a29e-c16e3293c6a1","parent":"235b8431-e2fd-4199-9bbd-4d5d0e803a56"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620313429,"role":"assistant","content":"Understood! How can I assist you with Test. Edit2?","children":[],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"81cab215-ca15-4b37-91fd-f6e196059e86","parent":"005bc344-aac6-43b8-a29e-c16e3293c6a1","completionId":"chatcmpl-pMlcB0JyvXn6E2vo0r3zvSkL6tWygrAG","timings":{"cache_n":0,"prompt_n":1265,"prompt_ms":292.836,"prompt_per_token_ms":0.2314909090909091,"prompt_per_second":4319.824065347157,"predicted_n":15,"predicted_ms":64.548,"predicted_per_token_ms":4.3032,"predicted_per_second":232.3852017103551}}}

After :

{"type":"session","harness":"llama.app","id":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","name":"Hello","lastModified":1783622113057,"currNode":"81cab215-ca15-4b37-91fd-f6e196059e86","thinkingEnabled":false}
{"type":"message","message":{"id":"32c264eb-f5f2-4acd-ab6c-d24800de3298","convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"root","timestamp":1783619815553,"role":"system","content":"","parent":null,"children":["48bbf4f9-3885-449a-8c92-f957222b2d5e"]}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","role":"user","content":"Hello","type":"text","timestamp":1783619815561,"children":["235b8431-e2fd-4199-9bbd-4d5d0e803a56"],"extra":[],"id":"48bbf4f9-3885-449a-8c92-f957222b2d5e","parent":"32c264eb-f5f2-4acd-ab6c-d24800de3298"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","role":"assistant","content":"Hello! How can I help you today?","timestamp":1783619815579,"children":["28dcb160-10e1-42d4-97da-707c8c9141bd","3c0444bd-0468-4a76-bcba-4f6a9551be9a","005bc344-aac6-43b8-a29e-c16e3293c6a1"],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"235b8431-e2fd-4199-9bbd-4d5d0e803a56","parent":"48bbf4f9-3885-449a-8c92-f957222b2d5e","completionId":"chatcmpl-R4xxYJgsj3tzzi7FeXE2B6hb0UrKhufl","timings":{"cache_n":0,"prompt_n":1584,"prompt_ms":258.951,"prompt_per_token_ms":0.16347916666666668,"prompt_per_second":6116.98738371352,"predicted_n":10,"predicted_ms":40.03,"predicted_per_token_ms":4.003,"predicted_per_second":249.81264051961028}}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","role":"user","content":"Test","type":"text","timestamp":1783619904269,"children":["2f7974a3-f658-46f6-af5f-88585a1627b1"],"extra":[],"id":"28dcb160-10e1-42d4-97da-707c8c9141bd","parent":"235b8431-e2fd-4199-9bbd-4d5d0e803a56"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","role":"assistant","content":"Test received! What would you like me to help you with? ","timestamp":1783619904301,"children":[],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"2f7974a3-f658-46f6-af5f-88585a1627b1","parent":"28dcb160-10e1-42d4-97da-707c8c9141bd","completionId":"chatcmpl-y7wNAA7IVO9b9EpVRxOKv4uUbziS8byk","timings":{"cache_n":3034,"prompt_n":13,"prompt_ms":31.439,"prompt_per_token_ms":2.4183846153846154,"prompt_per_second":413.49915709787206,"predicted_n":14,"predicted_ms":58.084,"predicted_per_token_ms":4.1488571428571435,"predicted_per_second":241.0302320776806}}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620305392,"role":"user","content":"Test. Edit1","children":["d2d6108c-f958-4315-8f0f-5ba218d990dd"],"extra":[],"id":"3c0444bd-0468-4a76-bcba-4f6a9551be9a","parent":"235b8431-e2fd-4199-9bbd-4d5d0e803a56"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620305425,"role":"assistant","content":"Understood. How would you like me to proceed with \"Test. Edit1\"?","children":[],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"d2d6108c-f958-4315-8f0f-5ba218d990dd","parent":"3c0444bd-0468-4a76-bcba-4f6a9551be9a","completionId":"chatcmpl-zpe6goBYdKU7v86INq9uIbJXGn7kU7cd","timings":{"cache_n":0,"prompt_n":1265,"prompt_ms":234.599,"prompt_per_token_ms":0.18545375494071145,"prompt_per_second":5392.179847313927,"predicted_n":18,"predicted_ms":78.973,"predicted_per_token_ms":4.387388888888889,"predicted_per_second":227.9260000253251}}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620313399,"role":"user","content":"Test. Edit2","children":["81cab215-ca15-4b37-91fd-f6e196059e86"],"extra":[],"id":"005bc344-aac6-43b8-a29e-c16e3293c6a1","parent":"235b8431-e2fd-4199-9bbd-4d5d0e803a56"}}
{"type":"message","message":{"convId":"0e3fa8ec-6cb6-4c40-a13a-0e70daf73d83","type":"text","timestamp":1783620313429,"role":"assistant","content":"Understood! How can I assist you with Test. Edit2?","children":[],"model":"MoE-Vision-Qwen3.6-35B-A3B","id":"81cab215-ca15-4b37-91fd-f6e196059e86","parent":"005bc344-aac6-43b8-a29e-c16e3293c6a1","completionId":"chatcmpl-pMlcB0JyvXn6E2vo0r3zvSkL6tWygrAG","timings":{"cache_n":0,"prompt_n":1265,"prompt_ms":292.836,"prompt_per_token_ms":0.2314909090909091,"prompt_per_second":4319.824065347157,"predicted_n":15,"predicted_ms":64.548,"predicted_per_token_ms":4.3032,"predicted_per_second":232.3852017103551}}}

Fixes #25451

Requirements

downloadConversation serialized activeMessages, the root -> currNode
path, so exporting a conversation with edited or regenerated messages
dropped every alternate version and kept only the selected one.

Fetch the whole message tree via getConversationMessages so the export
carries all message versions, matching the multi-conversation export
path which already did this. Keep the active conversation as the header
source to preserve an up-to-date currNode.

Forks are separate conversations, each with its own convId, and are
exported on their own.
@ServeurpersoCom ServeurpersoCom requested a review from a team as a code owner July 9, 2026 18:52
@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

Import test OK. Untouched.

@pnb

pnb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Nice! I will give it a try. The output in your example looks more like what I was expecting when I tried exporting; for example, 28dcb160-10e1-42d4-97da-707c8c9141bd appears in the children of one node in the "Before" version but then no message with that UUID is ever saved, whereas in the "After" version it is.

@ServeurpersoCom

Copy link
Copy Markdown
Contributor Author

You can test it, the code was actually designed for this all along; it must be a minor regression or something that was overlooked during a refactor.

Each conversation is a tree structure, and the conversation ID remains the same.
All versions of all edited messages remain available.

@pnb

pnb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

EDIT: Never mind, it is working.

For some reason, probably user error, I cannot get it to work. I haven't tried modifying the UI since the pre-Svelte days, but I followed the instructions in the UI README, got it running on localhost:5173, and tried a simple conversation. But after a chat sequence like:
A → B
Edited A → C → D

I still only see the currently selected version (from the < > options) in the JSONL export. Is there something special needed to test changes to the UI?

I also used a private browser window, and double checked that I had the code from your branch.

@pnb

pnb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Works great! I tried many different combinations of editing messages (including the first message) and everything seems preserved in the exports. Thanks for doing this!

@allozaur allozaur merged commit d46786f into ggml-org:master Jul 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misc. bug: Web UI export doesn't export full conversation tree, only currently selected branch

4 participants