add runtime context compaction and track compaction in sessions index

This commit is contained in:
DBT
2026-02-23 15:20:11 +00:00
parent 4985a934a7
commit bb3a710144
2 changed files with 67 additions and 15 deletions

View File

@@ -475,6 +475,7 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
Content: userContent,
})
al.sessions.SetLastLanguage(msg.SessionKey, responseLang)
al.compactSessionIfNeeded(msg.SessionKey)
al.sessions.Save(al.sessions.GetOrCreate(msg.SessionKey))
@@ -653,6 +654,7 @@ func (al *AgentLoop) processSystemMessage(ctx context.Context, msg bus.InboundMe
Content: finalContent,
})
al.sessions.SetLastLanguage(sessionKey, responseLang)
al.compactSessionIfNeeded(sessionKey)
al.sessions.Save(al.sessions.GetOrCreate(sessionKey))
@@ -680,6 +682,32 @@ func truncate(s string, maxLen int) string {
}
// GetStartupInfo returns information about loaded tools and skills for logging.
func (al *AgentLoop) compactSessionIfNeeded(sessionKey string) {
if !al.compactionEnabled {
return
}
trigger := al.compactionTrigger
if trigger <= 0 {
trigger = 60
}
keepRecent := al.compactionKeepRecent
if keepRecent <= 0 || keepRecent >= trigger {
keepRecent = trigger / 2
if keepRecent < 10 {
keepRecent = 10
}
}
h := al.sessions.GetHistory(sessionKey)
if len(h) <= trigger {
return
}
removed := len(h) - keepRecent
note := fmt.Sprintf("[runtime-compaction] removed %d old messages, kept %d recent messages", removed, keepRecent)
if al.sessions.CompactSession(sessionKey, keepRecent, note) {
al.sessions.Save(al.sessions.GetOrCreate(sessionKey))
}
}
// RunStartupSelfCheckAllSessions runs startup compaction checks across loaded sessions.
func (al *AgentLoop) RunStartupSelfCheckAllSessions(ctx context.Context) StartupCompactionReport {
report := StartupCompactionReport{TotalSessions: al.sessions.Count()}
@@ -712,17 +740,11 @@ func (al *AgentLoop) RunStartupSelfCheckAllSessions(ctx context.Context) Startup
}
removed := len(history) - keepRecent
summary := al.sessions.GetSummary(key)
note := fmt.Sprintf("[startup-compaction] removed %d old messages, kept %d recent messages", removed, keepRecent)
if strings.TrimSpace(summary) == "" {
al.sessions.SetSummary(key, note)
} else {
al.sessions.SetSummary(key, summary+"\n"+note)
if al.sessions.CompactSession(key, keepRecent, note) {
al.sessions.Save(al.sessions.GetOrCreate(key))
report.CompactedSessions++
}
al.sessions.TruncateHistory(key, keepRecent)
al.sessions.Save(al.sessions.GetOrCreate(key))
report.CompactedSessions++
}
return report

View File

@@ -20,6 +20,7 @@ type Session struct {
Kind string `json:"kind,omitempty"`
Messages []providers.Message `json:"messages"`
Summary string `json:"summary,omitempty"`
CompactionCount int `json:"compaction_count,omitempty"`
LastLanguage string `json:"last_language,omitempty"`
PreferredLanguage string `json:"preferred_language,omitempty"`
Created time.Time `json:"created"`
@@ -180,6 +181,32 @@ func (sm *SessionManager) SetSummary(key string, summary string) {
}
}
func (sm *SessionManager) CompactSession(key string, keepLast int, note string) bool {
sm.mu.RLock()
session, ok := sm.sessions[key]
sm.mu.RUnlock()
if !ok {
return false
}
session.mu.Lock()
defer session.mu.Unlock()
if keepLast <= 0 || len(session.Messages) <= keepLast {
return false
}
session.Messages = session.Messages[len(session.Messages)-keepLast:]
session.CompactionCount++
if strings.TrimSpace(note) != "" {
if strings.TrimSpace(session.Summary) == "" {
session.Summary = note
} else {
session.Summary += "\n" + note
}
}
session.Updated = time.Now()
return true
}
func (sm *SessionManager) GetLanguagePreferences(key string) (preferred string, last string) {
sm.mu.RLock()
session, ok := sm.sessions[key]
@@ -271,6 +298,7 @@ func (sm *SessionManager) List(limit int) []Session {
SessionID: s.SessionID,
Kind: s.Kind,
Summary: s.Summary,
CompactionCount: s.CompactionCount,
LastLanguage: s.LastLanguage,
PreferredLanguage: s.PreferredLanguage,
Created: s.Created,
@@ -388,7 +416,7 @@ func (sm *SessionManager) writeOpenClawSessionsIndex() error {
"updatedAt": s.Updated.UnixMilli(),
"systemSent": true,
"abortedLastRun": false,
"compactionCount": 0,
"compactionCount": s.CompactionCount,
"chatType": mapKindToChatType(s.Kind),
"sessionFile": sessionFile,
"kind": s.Kind,
@@ -430,11 +458,12 @@ func (sm *SessionManager) loadSessions() error {
indexPath := filepath.Join(sm.storage, "sessions.json")
if data, err := os.ReadFile(indexPath); err == nil {
var index map[string]struct {
SessionID string `json:"sessionId"`
SessionKey string `json:"sessionKey"`
UpdatedAt int64 `json:"updatedAt"`
Kind string `json:"kind"`
ChatType string `json:"chatType"`
SessionID string `json:"sessionId"`
SessionKey string `json:"sessionKey"`
UpdatedAt int64 `json:"updatedAt"`
Kind string `json:"kind"`
ChatType string `json:"chatType"`
CompactionCount int `json:"compactionCount"`
}
if err := json.Unmarshal(data, &index); err == nil {
for key, row := range index {
@@ -451,6 +480,7 @@ func (sm *SessionManager) loadSessions() error {
if row.UpdatedAt > 0 {
session.Updated = time.UnixMilli(row.UpdatedAt)
}
session.CompactionCount = row.CompactionCount
session.mu.Unlock()
}
}