mirror of
https://github.com/patriceckhart/zot.git
synced 2026-06-26 21:36:31 +02:00
Branch semantics for conversations: rewind to a past user message
and continue from there in a new session, with a visual tree
picker to switch between branches later.
/session fork
Opens the /jump turn picker in fork mode. Pick any past user
message; zot copies every message from the session start up to
and including that turn into a new session file, records the
parent id + fork point in the new meta, and swaps the running
agent onto the new branch. The parent session file stays on
disk unchanged; you can return to it later via /session tree.
/session tree
Shows every session in the current cwd arranged by parent/child
relationships. Depth-first flatten with two-space indent per
level; the current session is tagged "[current]". Pick any
other entry to switch into it (same semantics as /sessions).
Why both commands:
/sessions remains the "flat list of everything in this
directory" resume picker. /session tree is the fork-aware
variant. /session fork is the equivalent of git branch; /session
tree is the equivalent of checkout.
core additions:
SessionMeta gains two fields:
- Parent string (parent session ID, empty for roots)
- ForkPoint int (0-indexed message position of the cut)
core.BranchSession(parentPath, root, cwd, version, upToIdx)
Reads the parent session, writes a new session file in
SessionsDir(root, cwd) containing the first upToIdx message
rows + any usage rows that came before the cut. The new meta
records Parent=<parent id>, ForkPoint=<upToIdx>, fresh id,
cwd, Started, Version.
core.BuildSessionTree(root, cwd) []*TreeNode
Walks every session file in the cwd dir, reads each one's
meta, links children to parents by ID. Returns the forest
rooted at parentless sessions. Missing-parent sessions (if
the parent file was manually deleted) surface as roots so
they stay discoverable.
core.FindSessionByID(root, cwd, id) string
O(n) lookup used when resolving a tree pick back to a file
path. Files in the dir are small in practice.
readSessionMeta helper (unexported) reads just the first line
of a session file and decodes the meta; avoids loading the
whole transcript when BuildSessionTree only needs the
parent/id pair.
tui additions:
session_tree_dialog.go
Flat list with indent-based nesting to match the other
picker dialogs' shape. Up/down moves; enter switches; esc
cancels. Rows show "<relative-when> <prompt-preview> N msgs"
with a muted "[current]" tag on the current session.
interactive.go
- sessionTreeDialog field + constructor.
- /session fork / /session tree cases in doSessionOp.
- doSessionFork flips pendingFork=true and opens the
jumpDialog over the agent's current messages.
- The jump-dialog key handler checks pendingFork; if set,
routes the selection to applyForkSelection instead of the
normal applyJumpSelection. pendingFork clears on select
OR on dismiss so a later plain /jump isn't hijacked.
- applyForkSelection calls FlushSession (so the branch gets
everything in memory, not just what was lazy-flushed),
then core.BranchSession, then LoadSession to swap.
- doSessionTree calls FlushSession first so the tree shows
the true current message count, then
core.BuildSessionTree, then hands the forest to the tree
dialog.
- applySessionTreeSelection hands the picked path to
LoadSession.
tests:
TestBranchSessionCopiesPrefix
Parent with three messages; branch at upToIdx=2; verify the
child has exactly 2 messages, parent ID matches, fork point
= 2, ID rotated.
TestBuildSessionTree
Parent + 2 branches off it; verify roots=[parent],
roots[0].Children has both branches.
README: /session row expanded to cover all four ops.
|
||
|---|---|---|
| .. | ||
| agent | ||
| assets | ||
| auth | ||
| core | ||
| extproto | ||
| provider | ||
| skills | ||
| tui | ||