@@ -6,21 +6,28 @@ import (
66 "github.com/daverage/tinymem/internal/cove"
77 "github.com/daverage/tinymem/internal/memory"
88 "github.com/daverage/tinymem/internal/recall"
9+ "go.uber.org/zap"
910 "strconv"
1011 "strings"
1112)
1213
14+ const noMemorySentinel = "[no memory found; continue with user request]"
15+
1316// MemoryInjector handles injecting memories into prompts
1417type MemoryInjector struct {
15- recallEngine recall.Recaller
16- coveVerifier * cove.Verifier
18+ recallEngine recall.Recaller
19+ coveVerifier * cove.Verifier
20+ logger * zap.Logger
21+ alwaysIncludeUserPrompt bool
1722}
1823
1924// NewMemoryInjector creates a new memory injector
20- func NewMemoryInjector (recallEngine recall.Recaller ) * MemoryInjector {
25+ func NewMemoryInjector (recallEngine recall.Recaller , logger * zap. Logger , alwaysIncludeUserPrompt bool ) * MemoryInjector {
2126 return & MemoryInjector {
22- recallEngine : recallEngine ,
23- coveVerifier : nil , // Can be set later via SetCoVeVerifier
27+ recallEngine : recallEngine ,
28+ coveVerifier : nil , // Can be set later via SetCoVeVerifier
29+ logger : logger ,
30+ alwaysIncludeUserPrompt : alwaysIncludeUserPrompt ,
2431 }
2532}
2633
@@ -45,32 +52,57 @@ func (mi *MemoryInjector) FilterRecallResults(ctx context.Context, results []rec
4552
4653// InjectMemoriesIntoPrompt injects relevant memories into a prompt
4754func (mi * MemoryInjector ) InjectMemoriesIntoPrompt (prompt string , projectID string , maxItems int , maxTokens int ) (string , error ) {
55+ basePrompt := prompt
56+
4857 // Perform recall to find relevant memories
4958 results , err := mi .recallEngine .Recall (recall.RecallOptions {
5059 ProjectID : projectID ,
51- Query : prompt ,
60+ Query : basePrompt ,
5261 MaxItems : maxItems ,
5362 MaxTokens : maxTokens ,
5463 })
5564 if err != nil {
5665 return "" , err
5766 }
5867
59- if len (results ) == 0 {
60- // No relevant memories found, return original prompt
61- return prompt , nil
62- }
68+ if ! mi .alwaysIncludeUserPrompt {
69+ if len (results ) == 0 {
70+ return prompt , nil
71+ }
72+
73+ results = mi .FilterRecallResults (context .Background (), results , basePrompt )
74+ if len (results ) == 0 {
75+ return prompt , nil
76+ }
6377
64- // COVE INTEGRATION POINT 2: Optional recall filtering (advisory only )
65- // This can only remove memories, never add new ones.
66- results = mi . FilterRecallResults ( context . Background (), results , prompt )
78+ memorySection := buildMemorySection ( results )
79+ return memorySection + prompt , nil
80+ }
6781
82+ results = mi .FilterRecallResults (context .Background (), results , basePrompt )
6883 if len (results ) == 0 {
69- // All memories filtered out, return original prompt
70- return prompt , nil
84+ mi .logZeroMemoryPath ()
85+ finalBuilder := strings.Builder {}
86+ finalBuilder .WriteString (basePrompt )
87+ finalBuilder .WriteString ("\n \n " )
88+ finalBuilder .WriteString (noMemorySentinel )
89+ finalBuilder .WriteString ("\n " )
90+ return finalBuilder .String (), nil
7191 }
7292
73- // Build memory section
93+ memorySection := buildMemorySection (results )
94+
95+ var finalBuilder strings.Builder
96+ finalBuilder .WriteString (basePrompt )
97+ finalBuilder .WriteString ("\n \n " )
98+ finalBuilder .WriteString (noMemorySentinel )
99+ finalBuilder .WriteString ("\n " )
100+ finalBuilder .WriteString (memorySection )
101+
102+ return finalBuilder .String (), nil
103+ }
104+
105+ func buildMemorySection (results []recall.RecallResult ) string {
74106 var memorySection strings.Builder
75107 memorySection .WriteString ("\n \n === RELEVANT MEMORY ===\n " )
76108
@@ -96,10 +128,14 @@ func (mi *MemoryInjector) InjectMemoriesIntoPrompt(prompt string, projectID stri
96128
97129 memorySection .WriteString ("=== END MEMORY ===\n " )
98130
99- // Prepend memories to the original prompt
100- injectedPrompt := memorySection . String () + prompt
131+ return memorySection . String ()
132+ }
101133
102- return injectedPrompt , nil
134+ func (mi * MemoryInjector ) logZeroMemoryPath () {
135+ if mi .logger == nil {
136+ return
137+ }
138+ mi .logger .Info ("zero-memory prompt path" , zap .String ("layer" , "memory_injector" ))
103139}
104140
105141// FormatMemoriesForSystemMessage formats memories in a structured way for system messages
0 commit comments