mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 18:15:34 +00:00
fix(agent): loop improvements, history compaction, config tweaks
This commit is contained in:
1 parent
001fe2721c
commit
0cffbf5bfa
8 files changed
+46
-20
No files matched your search
+37
-15
@@ -1333,11 +1333,46 @@ func (l *Loop) runLoop(ctx context.Context, req RunRequest) (*RunResult, error)
|
||||
finalContent += req.ContentSuffix
|
||||
}
|
||||
|
||||
pendingMsgs = append(pendingMsgs, providers.Message{
|
||||
// Collect forwarded media + dedup + populate sizes BEFORE saving to session,
|
||||
// so we can attach output MediaRefs to the assistant message for history reload.
|
||||
for _, mf := range req.ForwardMedia {
|
||||
ct := mf.MimeType
|
||||
if ct == "" {
|
||||
ct = mimeFromExt(filepath.Ext(mf.Path))
|
||||
}
|
||||
mediaResults = append(mediaResults, MediaResult{Path: mf.Path, ContentType: ct})
|
||||
}
|
||||
mediaResults = deduplicateMedia(mediaResults)
|
||||
for i := range mediaResults {
|
||||
if mediaResults[i].Size == 0 {
|
||||
if info, err := os.Stat(mediaResults[i].Path); err == nil {
|
||||
mediaResults[i].Size = info.Size()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build final assistant message with output media refs for history persistence.
|
||||
assistantMsg := providers.Message{
|
||||
Role: "assistant",
|
||||
Content: finalContent,
|
||||
Thinking: finalThinking,
|
||||
})
|
||||
}
|
||||
for _, mr := range mediaResults {
|
||||
kind := "document"
|
||||
if strings.HasPrefix(mr.ContentType, "image/") {
|
||||
kind = "image"
|
||||
} else if strings.HasPrefix(mr.ContentType, "audio/") {
|
||||
kind = "audio"
|
||||
} else if strings.HasPrefix(mr.ContentType, "video/") {
|
||||
kind = "video"
|
||||
}
|
||||
assistantMsg.MediaRefs = append(assistantMsg.MediaRefs, providers.MediaRef{
|
||||
ID: filepath.Base(mr.Path),
|
||||
MimeType: mr.ContentType,
|
||||
Kind: kind,
|
||||
})
|
||||
}
|
||||
pendingMsgs = append(pendingMsgs, assistantMsg)
|
||||
|
||||
// Bootstrap nudge: if model didn't call write_file on turn 2+, inject reminder
|
||||
// into session history so the next turn sees it. Appended to pendingMsgs so it's
|
||||
@@ -1414,19 +1449,6 @@ func (l *Loop) runLoop(ctx context.Context, req RunRequest) (*RunResult, error)
|
||||
// 5. Maybe summarize
|
||||
l.maybeSummarize(ctx, req.SessionKey)
|
||||
|
||||
// Include forwarded media from delegation results (not cleaned up like req.Media)
|
||||
for _, mf := range req.ForwardMedia {
|
||||
ct := mf.MimeType
|
||||
if ct == "" {
|
||||
ct = mimeFromExt(filepath.Ext(mf.Path))
|
||||
}
|
||||
mediaResults = append(mediaResults, MediaResult{Path: mf.Path, ContentType: ct})
|
||||
}
|
||||
|
||||
// Deduplicate media by path — prevents the same image being sent twice
|
||||
// (e.g. once via ForwardMedia and again when the LLM reads the file).
|
||||
mediaResults = deduplicateMedia(mediaResults)
|
||||
|
||||
return &RunResult{
|
||||
Content: finalContent,
|
||||
RunID: req.RunID,
|
||||
|
||||
@@ -482,7 +482,7 @@ func (l *Loop) maybeSummarize(ctx context.Context, sessionKey string) {
|
||||
if l.compactionCfg != nil && l.compactionCfg.MaxHistoryShare > 0 {
|
||||
historyShare = l.compactionCfg.MaxHistoryShare
|
||||
}
|
||||
minMessages := 50
|
||||
minMessages := 200
|
||||
if l.compactionCfg != nil && l.compactionCfg.MinMessages > 0 {
|
||||
minMessages = l.compactionCfg.MinMessages
|
||||
}
|
||||
|
||||
@@ -178,6 +178,9 @@ func (l *Loop) Run(ctx context.Context, req RunRequest) (*RunResult, error) {
|
||||
"cache_read_tokens": result.Usage.CacheReadTokens,
|
||||
}
|
||||
}
|
||||
if len(result.Media) > 0 {
|
||||
completedPayload["media"] = result.Media
|
||||
}
|
||||
emitRun(AgentEvent{
|
||||
Type: protocol.AgentEventRunCompleted,
|
||||
AgentID: l.id,
|
||||
|
||||
@@ -413,5 +413,6 @@ type RunResult struct {
|
||||
type MediaResult struct {
|
||||
Path string `json:"path"` // local file path
|
||||
ContentType string `json:"content_type,omitempty"` // MIME type
|
||||
Size int64 `json:"size,omitempty"` // file size in bytes
|
||||
AsVoice bool `json:"as_voice,omitempty"` // send as voice message (Telegram OGG)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/nextlevelbuilder/goclaw/internal/providers"
|
||||
)
|
||||
|
||||
const titleGenerateTimeout = 10 * time.Second
|
||||
const titleGenerateTimeout = 30 * time.Second
|
||||
|
||||
const titleSystemPrompt = `Generate a short title (max 15 words) for this conversation based on the user's message. Reply with only the title, no quotes or punctuation wrapping.`
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
const maxHistoryKeys = 1000
|
||||
|
||||
// DefaultGroupHistoryLimit is the default pending message limit per group.
|
||||
const DefaultGroupHistoryLimit = 50
|
||||
const DefaultGroupHistoryLimit = 100
|
||||
|
||||
const (
|
||||
flushInterval = 3 * time.Second // periodic flush interval
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
// CompactionConfig configures LLM-based history compaction.
|
||||
type CompactionConfig struct {
|
||||
Threshold int // trigger compaction when entries exceed this (default 50)
|
||||
Threshold int // trigger compaction when entries exceed this (default 100)
|
||||
KeepRecent int // keep this many recent raw messages (default 15)
|
||||
MaxTokens int // max output tokens for summarization (default 4096)
|
||||
Provider providers.Provider // LLM provider for summarization
|
||||
|
||||
@@ -132,7 +132,7 @@ type AgentDefaults struct {
|
||||
type CompactionConfig struct {
|
||||
ReserveTokensFloor int `json:"reserveTokensFloor,omitempty"` // min reserve tokens (default 20000)
|
||||
MaxHistoryShare float64 `json:"maxHistoryShare,omitempty"` // max share of context for history (default 0.75)
|
||||
MinMessages int `json:"minMessages,omitempty"` // min messages before compaction triggers (default 50)
|
||||
MinMessages int `json:"minMessages,omitempty"` // min messages before compaction triggers (default 200)
|
||||
KeepLastMessages int `json:"keepLastMessages,omitempty"` // messages to keep after compaction (default 4)
|
||||
MemoryFlush *MemoryFlushConfig `json:"memoryFlush,omitempty"` // pre-compaction flush
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user