improve memory source citations and auto-attach recall source hints

This commit is contained in:
DBT
2026-02-23 15:49:40 +00:00
parent 15b4d7cccc
commit 8cafd2e66e
2 changed files with 34 additions and 2 deletions

View File

@@ -307,9 +307,13 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
history := al.sessions.GetHistory(msg.SessionKey)
summary := al.sessions.GetSummary(msg.SessionKey)
memoryRecallUsed := false
memoryRecallText := ""
if shouldRecallMemory(msg.Content) {
if recall, err := al.tools.Execute(ctx, "memory_search", map[string]interface{}{"query": msg.Content, "maxResults": 3}); err == nil && strings.TrimSpace(recall) != "" {
summary = strings.TrimSpace(summary + "\n\n[Memory Recall]\n" + recall)
memoryRecallUsed = true
memoryRecallText = strings.TrimSpace(recall)
summary = strings.TrimSpace(summary + "\n\n[Memory Recall]\n" + memoryRecallText)
}
}
if explicitPref := ExtractLanguagePreference(msg.Content); explicitPref != "" {
@@ -472,6 +476,12 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
}
}
if memoryRecallUsed && !strings.Contains(strings.ToLower(userContent), "source:") {
if src := extractFirstSourceLine(memoryRecallText); src != "" {
userContent = strings.TrimSpace(userContent + "\n\n" + src)
}
}
al.sessions.AddMessage(msg.SessionKey, "user", msg.Content)
// 使用 AddMessageFull 存储包含思考过程或工具调用的完整助手消息
@@ -847,6 +857,16 @@ func shouldRecallMemory(text string) bool {
return false
}
func extractFirstSourceLine(text string) string {
for _, line := range strings.Split(text, "\n") {
t := strings.TrimSpace(line)
if strings.HasPrefix(strings.ToLower(t), "source:") {
return t
}
}
return ""
}
func alSessionListForTool(sm *session.SessionManager, limit int) []tools.SessionInfo {
items := sm.List(limit)
out := make([]tools.SessionInfo, 0, len(items))

View File

@@ -118,7 +118,11 @@ func (t *MemorySearchTool) Execute(ctx context.Context, args map[string]interfac
sb.WriteString(fmt.Sprintf("Found %d memories for '%s':\n\n", len(allResults), query))
for _, res := range allResults {
relPath, _ := filepath.Rel(t.workspace, res.file)
sb.WriteString(fmt.Sprintf("--- Source: %s:%d ---\n%s\n\n", relPath, res.lineNum, res.content))
lineEnd := res.lineNum + countLines(res.content) - 1
if lineEnd < res.lineNum {
lineEnd = res.lineNum
}
sb.WriteString(fmt.Sprintf("Source: %s#L%d-L%d\n%s\n\n", relPath, res.lineNum, lineEnd, res.content))
}
return sb.String(), nil
@@ -154,6 +158,14 @@ func (t *MemorySearchTool) getMemoryFiles() []string {
return dedupeStrings(files)
}
func countLines(s string) int {
s = strings.TrimSpace(s)
if s == "" {
return 0
}
return len(strings.Split(s, "\n"))
}
func dedupeStrings(items []string) []string {
seen := make(map[string]struct{}, len(items))
out := make([]string, 0, len(items))