54 lines
2.0 KiB
Go
54 lines
2.0 KiB
Go
// This file holds PersistTurn, the session-tree persistence step shared by the
|
|
// REPL loop and the /goal autonomous loop. It reads and advances a session's
|
|
// mutable cursor state through the Host contract, so a command need not import
|
|
// the concrete replDeps aggregate to persist the tail of a turn.
|
|
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// PersistTurn appends the messages produced since the last persist as a new
|
|
// branch descending from the host's current leaf, advancing the leaf and the
|
|
// persisted-message cursor. Growing the tree with AppendBranch (rather than a
|
|
// full linear Save) is what lets a later /tree leaf-switch fork the on-disk
|
|
// history instead of clobbering it. If nothing new was produced it is a no-op:
|
|
// rewriting the file would regenerate entry ids and flatten the tree.
|
|
func PersistTurn(out io.Writer, h Host) {
|
|
agentCtx := h.AgentCtx()
|
|
// Automatic compaction during a turn rewrites Messages into a summary + recent
|
|
// tail, shrinking the slice below the persisted cursor. The append-a-tail
|
|
// branch model no longer holds (the prefix changed and Messages[persisted:]
|
|
// would be out of range), so re-save the flattened context linearly and reset
|
|
// the branch cursor to the new leaf, mirroring the /compact handler.
|
|
if h.Persisted() > len(agentCtx.Messages) {
|
|
header := h.Header()
|
|
header.UpdatedAt = time.Now().UTC()
|
|
if err := h.Store().Save(header, agentCtx.Messages); err != nil {
|
|
fmt.Fprintf(out, "pigo: session save failed: %v\n", err)
|
|
return
|
|
}
|
|
h.SetPersisted(len(agentCtx.Messages))
|
|
h.SetCurLeaf("")
|
|
if _, entries, err := h.Store().LoadEntries(header.ID); err == nil && len(entries) > 0 {
|
|
h.SetCurLeaf(entries[len(entries)-1].ID)
|
|
}
|
|
return
|
|
}
|
|
tail := agentCtx.Messages[h.Persisted():]
|
|
if len(tail) == 0 {
|
|
return
|
|
}
|
|
header := h.Header()
|
|
header.UpdatedAt = time.Now().UTC()
|
|
leaf, err := h.Store().AppendBranch(header, h.CurLeaf(), tail)
|
|
if err != nil {
|
|
fmt.Fprintf(out, "pigo: session save failed: %v\n", err)
|
|
return
|
|
}
|
|
h.SetCurLeaf(leaf)
|
|
h.SetPersisted(len(agentCtx.Messages))
|
|
}
|