mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat(session): add per-message created_at timestamps
- Persistence layer (jsonl.go addMsg/SetHistory) normalizes CreatedAt when missing so the invariant is guaranteed at the storage boundary - API layer (session.go) exposes created_at on all transcript message types with session.updated fallback for legacy messages - Frontend uses per-message timestamps when available - messagesContentEqual ignores CreatedAt for tail-matching after JSONL roundtrip Fixes #2787
This commit is contained in:
+16
-1
@@ -686,10 +686,25 @@ func (ts *turnState) restoreSession(agent *AgentInstance) error {
|
||||
return agent.Sessions.Save(ts.sessionKey)
|
||||
}
|
||||
|
||||
// messagesContentEqual compares two message slices by content only, ignoring CreatedAt.
|
||||
// JSON roundtrip loses the monotonic clock portion of time.Time, so direct
|
||||
// reflect.DeepEqual would always differ on messages that roundtripped through
|
||||
// the JSONL store.
|
||||
func messagesContentEqual(a, b []providers.Message) bool {
|
||||
for i := range a {
|
||||
aCopy, bCopy := a[i], b[i]
|
||||
aCopy.CreatedAt, bCopy.CreatedAt = nil, nil
|
||||
if !reflect.DeepEqual(aCopy, bCopy) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func matchingTurnMessageTail(history, persisted []providers.Message) int {
|
||||
maxMatch := min(len(history), len(persisted))
|
||||
for size := maxMatch; size > 0; size-- {
|
||||
if reflect.DeepEqual(history[len(history)-size:], persisted[len(persisted)-size:]) {
|
||||
if messagesContentEqual(history[len(history)-size:], persisted[len(persisted)-size:]) {
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user