Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions pkg/agent/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
"github.com/sipeed/picoclaw/pkg/utils"
)

// maxHistoryMessagesForContext is the maximum number of history messages to send to the LLM.
// Read-time cap only; session storage keeps full history.
const maxHistoryMessagesForContext = 200

type AgentLoop struct {
bus *bus.MessageBus
cfg *config.Config
Expand Down Expand Up @@ -413,6 +417,10 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
if !opts.NoHistory {
history = agent.Sessions.GetHistory(opts.SessionKey)
summary = agent.Sessions.GetSummary(opts.SessionKey)
// Read-time cap: only the last N messages go to the LLM; session storage is unchanged.
if len(history) > maxHistoryMessagesForContext {
history = history[len(history)-maxHistoryMessagesForContext:]
}
}
messages := agent.ContextBuilder.BuildMessages(
history,
Expand Down Expand Up @@ -573,11 +581,10 @@ func (al *AgentLoop) runLLMIteration(
})
}

al.forceCompression(agent, opts.SessionKey)
newHistory := agent.Sessions.GetHistory(opts.SessionKey)
compressed := al.forceCompression(agent, opts.SessionKey)
newSummary := agent.Sessions.GetSummary(opts.SessionKey)
messages = agent.ContextBuilder.BuildMessages(
newHistory, newSummary, "",
compressed, newSummary, "",
nil, opts.Channel, opts.ChatID,
)
continue
Expand Down Expand Up @@ -775,18 +782,19 @@ func (al *AgentLoop) maybeSummarize(agent *AgentInstance, sessionKey, channel, c

// forceCompression aggressively reduces context when the limit is hit.
// It drops the oldest 50% of messages (keeping system prompt and last user message).
func (al *AgentLoop) forceCompression(agent *AgentInstance, sessionKey string) {
// Returns the compressed history for use in the current request only; does not persist to session.
func (al *AgentLoop) forceCompression(agent *AgentInstance, sessionKey string) []providers.Message {
history := agent.Sessions.GetHistory(sessionKey)
if len(history) <= 4 {
return
return history
}

// Keep system prompt (usually [0]) and the very last message (user's trigger)
// We want to drop the oldest half of the *conversation*
// Assuming [0] is system, [1:] is conversation
conversation := history[1 : len(history)-1]
if len(conversation) == 0 {
return
return history
}

// Helper to find the mid-point of the conversation
Expand Down Expand Up @@ -815,15 +823,12 @@ func (al *AgentLoop) forceCompression(agent *AgentInstance, sessionKey string) {
newHistory = append(newHistory, keptConversation...)
newHistory = append(newHistory, history[len(history)-1]) // Last message

// Update session
agent.Sessions.SetHistory(sessionKey, newHistory)
agent.Sessions.Save(sessionKey)

logger.WarnCF("agent", "Forced compression executed", map[string]any{
logger.WarnCF("agent", "Forced compression executed (in-memory only, not persisted)", map[string]any{
"session_key": sessionKey,
"dropped_msgs": droppedCount,
"new_count": len(newHistory),
})
return newHistory
}

// GetStartupInfo returns information about loaded tools and skills for logging.
Expand Down Expand Up @@ -981,7 +986,6 @@ func (al *AgentLoop) summarizeSession(agent *AgentInstance, sessionKey string) {

if finalSummary != "" {
agent.Sessions.SetSummary(sessionKey, finalSummary)
agent.Sessions.TruncateHistory(sessionKey, 4)
agent.Sessions.Save(sessionKey)
}
}
Expand Down
12 changes: 10 additions & 2 deletions pkg/session/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
"github.com/sipeed/picoclaw/pkg/providers"
)

// maxStoredMessages is the maximum number of messages to persist per session (safety cap to limit file size).
// Older messages are dropped only at write time; in-memory session may hold more until next Save.
const maxStoredMessages = 500

type Session struct {
Key string `json:"key"`
Messages []providers.Message `json:"messages"`
Expand Down Expand Up @@ -184,8 +188,12 @@ func (sm *SessionManager) Save(key string) error {
Updated: stored.Updated,
}
if len(stored.Messages) > 0 {
snapshot.Messages = make([]providers.Message, len(stored.Messages))
copy(snapshot.Messages, stored.Messages)
toStore := stored.Messages
if len(toStore) > maxStoredMessages {
toStore = toStore[len(toStore)-maxStoredMessages:]
}
snapshot.Messages = make([]providers.Message, len(toStore))
copy(snapshot.Messages, toStore)
} else {
snapshot.Messages = []providers.Message{}
}
Expand Down