@@ -9,7 +9,33 @@ import { GenerationOptions } from "./generation"
99import { HTMLEscape } from "./html"
1010import { prettifyMarkdown } from "./markdown"
1111import { TraceOptions } from "./trace"
12- import { logVerbose } from "./util"
12+ import { ellipse } from "./util"
13+ import debug from "debug"
14+ const dbg = debug ( "agent:memory" )
15+
16+ export type AgentMemoryCacheKey = { agent : string ; query : string }
17+ export type AgentMemoryCacheValue = AgentMemoryCacheKey & {
18+ answer : string
19+ createdAt : number
20+ }
21+ export type AgentMemoryCache = WorkspaceFileCache <
22+ AgentMemoryCacheKey ,
23+ AgentMemoryCacheValue
24+ >
25+
26+ export function agentCreateCache (
27+ options : Pick < GenerationOptions , "userState" > & { lookupOnly ?: boolean }
28+ ) : AgentMemoryCache {
29+ const cache = createCache < AgentMemoryCacheKey , AgentMemoryCacheValue > (
30+ AGENT_MEMORY_CACHE_NAME ,
31+ {
32+ type : "memory" ,
33+ userState : options . userState ,
34+ lookupOnly : options . lookupOnly ,
35+ }
36+ )
37+ return cache
38+ }
1339
1440/**
1541 * Queries the agent's memory to retrieve contextual information relevant to a given query.
@@ -26,17 +52,19 @@ import { logVerbose } from "./util"
2652 * @returns Memory answer or undefined if no relevant memories are retrieved.
2753 */
2854export async function agentQueryMemory (
55+ cache : AgentMemoryCache ,
2956 ctx : ChatGenerationContext ,
3057 query : string ,
31- options : Pick < GenerationOptions , "userState" > & Required < TraceOptions >
58+ options : Required < TraceOptions >
3259) {
3360 if ( ! query ) return undefined
3461
35- const memories = await loadMemories ( options )
62+ const memories = await loadMemories ( cache )
3663 if ( ! memories ?. length ) return undefined
3764
3865 let memoryAnswer : string | undefined
3966 // always pre-query memory with cheap model
67+ dbg ( `query: ${ query } ` )
4068 const res = await ctx . runPrompt (
4169 async ( _ ) => {
4270 _ . $ `Return the contextual information useful to answer <QUERY> from the content in <MEMORY>.
@@ -47,18 +75,21 @@ export async function agentQueryMemory(
4775 "system"
4876 )
4977 _ . def ( "QUERY" , query )
50- await defMemory ( _ )
78+ await defMemory ( cache , _ )
5179 } ,
5280 {
5381 model : "memory" ,
5482 system : [ ] ,
5583 flexTokens : AGENT_MEMORY_FLEX_TOKENS ,
5684 label : "agent memory query" ,
85+ cache : "agent_memory" ,
5786 }
5887 )
5988 if ( ! res . error )
6089 memoryAnswer = res . text . includes ( TOKEN_NO_ANSWER ) ? "" : res . text
61- else logVerbose ( `agent memory query error: ${ errorMessage ( res . error ) } ` )
90+ else dbg ( `error: ${ errorMessage ( res . error ) } ` )
91+
92+ dbg ( `answer: ${ ellipse ( memoryAnswer , 128 ) } ` )
6293 return memoryAnswer
6394}
6495
@@ -73,25 +104,20 @@ export async function agentQueryMemory(
73104 * @param options - Configuration options, including user state and tracing details.
74105 */
75106export async function agentAddMemory (
107+ cache : AgentMemoryCache ,
76108 agent : string ,
77109 query : string ,
78110 text : string ,
79- options : Pick < GenerationOptions , "userState" > & Required < TraceOptions >
111+ options : Required < TraceOptions >
80112) {
81113 const { trace } = options || { }
82- const cache = createCache <
83- { agent : string ; query : string } ,
84- {
85- agent : string
86- query : string
87- answer : string
88- }
89- > ( AGENT_MEMORY_CACHE_NAME )
90- const cacheKey = { agent, query }
91- const cachedValue = {
114+ const cacheKey : AgentMemoryCacheKey = { agent, query }
115+ const cachedValue : AgentMemoryCacheValue = {
92116 ...cacheKey ,
93117 answer : text ,
118+ createdAt : Date . now ( ) ,
94119 }
120+ dbg ( `add ${ agent } : ${ ellipse ( query , 80 ) } -> ${ ellipse ( text , 128 ) } ` )
95121 await cache . set ( cacheKey , cachedValue )
96122 trace . detailsFenced (
97123 `🧠 agent memory: ${ HTMLEscape ( query ) } ` ,
@@ -100,19 +126,9 @@ export async function agentAddMemory(
100126 )
101127}
102128
103- async function loadMemories ( options : Pick < GenerationOptions , "userState" > ) {
104- const cache = createCache <
105- { agent : string ; query : string } ,
106- {
107- agent : string
108- query : string
109- answer : string
110- }
111- > ( AGENT_MEMORY_CACHE_NAME , {
112- lookupOnly : true ,
113- userState : options . userState ,
114- } )
129+ async function loadMemories ( cache : AgentMemoryCache ) {
115130 const memories = await cache ?. values ( )
131+ memories ?. sort ( ( l , r ) => l . createdAt - r . createdAt )
116132 return memories
117133}
118134
@@ -131,7 +147,11 @@ export async function traceAgentMemory(
131147 options : Pick < GenerationOptions , "userState" > & Required < TraceOptions >
132148) {
133149 const { trace } = options || { }
134- const memories = await loadMemories ( options )
150+ const cache = agentCreateCache ( {
151+ userState : options . userState ,
152+ lookupOnly : true ,
153+ } )
154+ const memories = await loadMemories ( cache )
135155 if ( memories ) {
136156 try {
137157 trace . startDetails ( "🧠 agent memory" )
@@ -150,15 +170,10 @@ export async function traceAgentMemory(
150170 }
151171}
152172
153- async function defMemory ( ctx : ChatTurnGenerationContext ) {
154- const cache = createCache <
155- { agent : string ; query : string } ,
156- {
157- agent : string
158- query : string
159- answer : string
160- }
161- > ( AGENT_MEMORY_CACHE_NAME )
173+ async function defMemory (
174+ cache : AgentMemoryCache ,
175+ ctx : ChatTurnGenerationContext
176+ ) {
162177 const memories = await cache . values ( )
163178 memories . reverse ( ) . forEach ( ( { agent, query, answer } , index ) =>
164179 ctx . def (
0 commit comments