diff --git a/internal/agent/memoryflush.go b/internal/agent/memoryflush.go index 00c38456..8f4caad2 100644 --- a/internal/agent/memoryflush.go +++ b/internal/agent/memoryflush.go @@ -21,16 +21,13 @@ const ( DefaultMemoryFlushSystemPrompt = "Pre-compaction memory flush turn. " + "The session is near auto-compaction; capture durable memories to disk. " + "You may reply, but usually NO_REPLY is correct." - - DefaultSoftThresholdTokens = 4000 ) // MemoryFlushSettings holds resolved flush config with defaults applied. type MemoryFlushSettings struct { - Enabled bool - SoftThresholdTokens int - Prompt string - SystemPrompt string + Enabled bool + Prompt string + SystemPrompt string } // ResolveMemoryFlushSettings resolves flush settings from config, applying defaults. @@ -39,10 +36,9 @@ func ResolveMemoryFlushSettings(compaction *config.CompactionConfig) *MemoryFlus if compaction == nil || compaction.MemoryFlush == nil { // Default: enabled return &MemoryFlushSettings{ - Enabled: true, - SoftThresholdTokens: DefaultSoftThresholdTokens, - Prompt: DefaultMemoryFlushPrompt, - SystemPrompt: DefaultMemoryFlushSystemPrompt, + Enabled: true, + Prompt: DefaultMemoryFlushPrompt, + SystemPrompt: DefaultMemoryFlushSystemPrompt, } } @@ -52,15 +48,11 @@ func ResolveMemoryFlushSettings(compaction *config.CompactionConfig) *MemoryFlus } settings := &MemoryFlushSettings{ - Enabled: true, - SoftThresholdTokens: DefaultSoftThresholdTokens, - Prompt: DefaultMemoryFlushPrompt, - SystemPrompt: DefaultMemoryFlushSystemPrompt, + Enabled: true, + Prompt: DefaultMemoryFlushPrompt, + SystemPrompt: DefaultMemoryFlushSystemPrompt, } - if mf.SoftThresholdTokens > 0 { - settings.SoftThresholdTokens = mf.SoftThresholdTokens - } if mf.Prompt != "" { settings.Prompt = mf.Prompt } @@ -72,7 +64,8 @@ func ResolveMemoryFlushSettings(compaction *config.CompactionConfig) *MemoryFlus } // shouldRunMemoryFlush checks whether a memory flush should run before compaction. -// Matching TS memory-flush.ts:shouldRunMemoryFlush. +// Flush always runs when compaction triggers (called inside maybeSummarize), +// gated only by enabled/memory checks and a dedup guard per compaction cycle. func (l *Loop) shouldRunMemoryFlush(sessionKey string, totalTokens int, settings *MemoryFlushSettings) bool { if settings == nil || !settings.Enabled || !l.hasMemory { return false @@ -82,23 +75,7 @@ func (l *Loop) shouldRunMemoryFlush(sessionKey string, totalTokens int, settings return false } - // Threshold = contextWindow - reserveTokensFloor - softThresholdTokens - // When totalTokens >= threshold → flush - reserveFloor := 20000 // default - if l.compactionCfg != nil && l.compactionCfg.ReserveTokensFloor > 0 { - reserveFloor = l.compactionCfg.ReserveTokensFloor - } - - threshold := l.contextWindow - reserveFloor - settings.SoftThresholdTokens - if threshold <= 0 { - return false - } - - if totalTokens < threshold { - return false - } - - // Deduplication: skip if already flushed in this compaction cycle + // Deduplication: skip if already flushed in this compaction cycle. compactionCount := l.sessions.GetCompactionCount(sessionKey) lastFlushAt := l.sessions.GetMemoryFlushCompactionCount(sessionKey) if lastFlushAt >= 0 && lastFlushAt == compactionCount { diff --git a/ui/web/src/i18n/locales/en/agents.json b/ui/web/src/i18n/locales/en/agents.json index 4b45fc04..43029297 100644 --- a/ui/web/src/i18n/locales/en/agents.json +++ b/ui/web/src/i18n/locales/en/agents.json @@ -271,12 +271,14 @@ "compaction": { "title": "Compaction", "description": "Context window compaction and memory flush settings", - "reserveTokensFloor": "Reserve Tokens Floor", "maxHistoryShare": "Max History Share (0-1)", + "maxHistoryShareTip": "Maximum fraction of context window for conversation history (e.g. 0.75 = 75%). Compaction triggers when exceeded.", "minMessages": "Min Messages", + "minMessagesTip": "Minimum messages before compaction can trigger, regardless of token count.", "keepLastMessages": "Keep Last Messages", + "keepLastMessagesTip": "Recent messages kept after compaction. Older messages are replaced by a summary.", "memoryFlush": "Memory Flush", - "softThreshold": "Soft Threshold (tokens)" + "memoryFlushTip": "Before compaction, the agent gets a turn to save important context to memory files. Also triggers Knowledge Graph extraction." }, "contextPruning": { "title": "Context Pruning", diff --git a/ui/web/src/i18n/locales/vi/agents.json b/ui/web/src/i18n/locales/vi/agents.json index ca59d989..1048ebdb 100644 --- a/ui/web/src/i18n/locales/vi/agents.json +++ b/ui/web/src/i18n/locales/vi/agents.json @@ -270,13 +270,15 @@ }, "compaction": { "title": "Nén ngữ cảnh", - "description": "Cài đặt nén cửa sổ ngữ cảnh và xả bộ nhớ", - "reserveTokensFloor": "Sàn token dự trữ", + "description": "Cài đặt nén cửa sổ ngữ cảnh và ghi nhớ trước nén", "maxHistoryShare": "Phần lịch sử tối đa (0-1)", + "maxHistoryShareTip": "Tỷ lệ tối đa của cửa sổ ngữ cảnh dành cho lịch sử hội thoại (vd: 0.75 = 75%). Nén kích hoạt khi vượt quá.", "minMessages": "Tin nhắn tối thiểu", + "minMessagesTip": "Số tin nhắn tối thiểu trước khi nén có thể kích hoạt, bất kể số token.", "keepLastMessages": "Giữ tin nhắn cuối", - "memoryFlush": "Xả bộ nhớ", - "softThreshold": "Ngưỡng mềm (token)" + "keepLastMessagesTip": "Số tin nhắn gần nhất giữ lại sau khi nén. Các tin nhắn cũ hơn được thay thế bằng bản tóm tắt.", + "memoryFlush": "Ghi nhớ trước nén", + "memoryFlushTip": "Trước khi nén, agent được một lượt để lưu ngữ cảnh quan trọng vào file bộ nhớ. Cũng kích hoạt trích xuất Knowledge Graph." }, "contextPruning": { "title": "Cắt bớt ngữ cảnh", diff --git a/ui/web/src/i18n/locales/zh/agents.json b/ui/web/src/i18n/locales/zh/agents.json index 61b232c7..22a520f7 100644 --- a/ui/web/src/i18n/locales/zh/agents.json +++ b/ui/web/src/i18n/locales/zh/agents.json @@ -270,13 +270,15 @@ }, "compaction": { "title": "压缩", - "description": "上下文窗口压缩和内存刷新设置", - "reserveTokensFloor": "保留令牌下限", + "description": "上下文窗口压缩和压缩前记忆设置", "maxHistoryShare": "最大历史份额 (0-1)", + "maxHistoryShareTip": "上下文窗口用于对话历史的最大比例(如0.75 = 75%)。超过时触发压缩。", "minMessages": "最小消息数", + "minMessagesTip": "压缩触发前所需的最少消息数,与令牌数无关。", "keepLastMessages": "保留最后消息数", - "memoryFlush": "内存刷新", - "softThreshold": "软阈值(令牌)" + "keepLastMessagesTip": "压缩后保留的最近消息数。旧消息被摘要替换。", + "memoryFlush": "压缩前记忆", + "memoryFlushTip": "压缩前,Agent可以将重要上下文保存到记忆文件。同时触发知识图谱提取。" }, "contextPruning": { "title": "上下文裁剪", diff --git a/ui/web/src/pages/agents/agent-detail/config-sections/compaction-section.tsx b/ui/web/src/pages/agents/agent-detail/config-sections/compaction-section.tsx index 51e0f106..300882b2 100644 --- a/ui/web/src/pages/agents/agent-detail/config-sections/compaction-section.tsx +++ b/ui/web/src/pages/agents/agent-detail/config-sections/compaction-section.tsx @@ -23,16 +23,7 @@ export function CompactionSection({ enabled, value, onToggle, onChange }: Compac >
- {t(`${s}.reserveTokensFloor`)} - onChange({ ...value, reserveTokensFloor: numOrUndef(e.target.value) })} - /> -
-
- {t(`${s}.maxHistoryShare`)} + {t(`${s}.maxHistoryShare`)} onChange({ ...value, maxHistoryShare: numOrUndef(e.target.value) })} />
-
-
- {t(`${s}.minMessages`)} + {t(`${s}.minMessages`)} onChange({ ...value, minMessages: numOrUndef(e.target.value) })} />
+
+
- {t(`${s}.keepLastMessages`)} + {t(`${s}.keepLastMessages`)}
-
-
- - onChange({ ...value, memoryFlush: { ...value.memoryFlush, enabled: v } }) - } - /> - {t(`${s}.memoryFlush`)} -
- {(value.memoryFlush?.enabled ?? true) && ( -
- {t(`${s}.softThreshold`)} - - onChange({ - ...value, - memoryFlush: { - ...value.memoryFlush, - enabled: true, - softThresholdTokens: numOrUndef(e.target.value), - }, - }) - } - /> -
- )} +
+ + onChange({ ...value, memoryFlush: { ...value.memoryFlush, enabled: v } }) + } + /> + {t(`${s}.memoryFlush`)}
);