@@ -92,9 +92,71 @@ pub struct CorrectByQueryRequest {
9292pub struct PurgeRequest {
9393 pub memory_ids : Option < Vec < String > > ,
9494 pub topic : Option < String > ,
95+ pub session_id : Option < String > ,
96+ pub memory_types : Option < Vec < String > > ,
9597 pub reason : Option < String > ,
9698}
9799
100+ pub enum PurgeSelector {
101+ MemoryIds ( Vec < String > ) ,
102+ Topic ( String ) ,
103+ Session {
104+ session_id : String ,
105+ memory_types : Option < Vec < MemoryType > > ,
106+ } ,
107+ None ,
108+ }
109+
110+ impl PurgeRequest {
111+ pub fn selector ( & self ) -> Result < PurgeSelector , String > {
112+ let memory_ids = self . memory_ids . as_ref ( ) . filter ( |ids| !ids. is_empty ( ) ) ;
113+ let memory_types = self . memory_types . as_ref ( ) . filter ( |types| !types. is_empty ( ) ) ;
114+ let topic = self
115+ . topic
116+ . as_deref ( )
117+ . map ( str:: trim)
118+ . filter ( |s| !s. is_empty ( ) ) ;
119+ let session_id = self
120+ . session_id
121+ . as_deref ( )
122+ . map ( str:: trim)
123+ . filter ( |s| !s. is_empty ( ) ) ;
124+ if memory_types. is_some ( ) && session_id. is_none ( ) {
125+ return Err ( "memory_types requires session_id" . to_string ( ) ) ;
126+ }
127+
128+ let selector_count = usize:: from ( memory_ids. is_some ( ) )
129+ + usize:: from ( topic. is_some ( ) )
130+ + usize:: from ( session_id. is_some ( ) ) ;
131+ if selector_count > 1 {
132+ return Err ( "provide only one of memory_ids, topic, or session_id" . to_string ( ) ) ;
133+ }
134+
135+ if let Some ( ids) = memory_ids {
136+ return Ok ( PurgeSelector :: MemoryIds ( ids. clone ( ) ) ) ;
137+ }
138+ if let Some ( topic) = topic {
139+ return Ok ( PurgeSelector :: Topic ( topic. to_string ( ) ) ) ;
140+ }
141+ if let Some ( session_id) = session_id {
142+ let memory_types = memory_types
143+ . map ( |types| {
144+ types
145+ . iter ( )
146+ . map ( |memory_type| parse_memory_type ( memory_type) )
147+ . collect :: < Result < Vec < _ > , _ > > ( )
148+ } )
149+ . transpose ( ) ?
150+ . filter ( |types| !types. is_empty ( ) ) ;
151+ return Ok ( PurgeSelector :: Session {
152+ session_id : session_id. to_string ( ) ,
153+ memory_types,
154+ } ) ;
155+ }
156+ Ok ( PurgeSelector :: None )
157+ }
158+ }
159+
98160#[ derive( Serialize ) ]
99161pub struct MemoryResponse {
100162 pub memory_id : String ,
@@ -231,3 +293,43 @@ pub fn parse_memory_type(s: &str) -> Result<MemoryType, String> {
231293pub fn parse_trust_tier ( s : & str ) -> Result < TrustTier , String > {
232294 TrustTier :: from_str ( s) . map_err ( |e| e. to_string ( ) )
233295}
296+
297+ #[ cfg( test) ]
298+ mod tests {
299+ use super :: { PurgeRequest , PurgeSelector } ;
300+
301+ #[ test]
302+ fn purge_selector_ignores_empty_arrays ( ) {
303+ let request = PurgeRequest {
304+ memory_ids : Some ( vec ! [ ] ) ,
305+ topic : None ,
306+ session_id : Some ( "sess-1" . to_string ( ) ) ,
307+ memory_types : Some ( vec ! [ ] ) ,
308+ reason : None ,
309+ } ;
310+
311+ match request. selector ( ) . unwrap ( ) {
312+ PurgeSelector :: Session {
313+ session_id,
314+ memory_types,
315+ } => {
316+ assert_eq ! ( session_id, "sess-1" ) ;
317+ assert ! ( memory_types. is_none( ) ) ;
318+ }
319+ _ => panic ! ( "expected session selector" ) ,
320+ }
321+ }
322+
323+ #[ test]
324+ fn purge_selector_empty_memory_types_do_not_require_session ( ) {
325+ let request = PurgeRequest {
326+ memory_ids : None ,
327+ topic : None ,
328+ session_id : None ,
329+ memory_types : Some ( vec ! [ ] ) ,
330+ reason : None ,
331+ } ;
332+
333+ assert ! ( matches!( request. selector( ) . unwrap( ) , PurgeSelector :: None ) ) ;
334+ }
335+ }
0 commit comments