diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index c2ff998..e4e6dc9 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -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)) diff --git a/pkg/tools/memory.go b/pkg/tools/memory.go index a6c2151..bc9b2b9 100644 --- a/pkg/tools/memory.go +++ b/pkg/tools/memory.go @@ -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))