rightkit_memory_client/backend/
contract.rs1use crate::backend::error::MemoryBackendError;
4use crate::backend::types::{
5 BackendBinding, FullMemoryRecord, JsonValue, MemoryEntry, MemoryId, MemoryListRow, MemoryTier,
6 Score,
7};
8use async_trait::async_trait;
9use std::time::{Duration, Instant};
10use tokio_util::sync::CancellationToken;
11
12#[derive(Clone, Debug)]
14pub struct CallContext {
15 deadline: Option<Instant>,
16 cancellation: CancellationToken,
17}
18
19impl CallContext {
20 pub fn unbounded() -> Self {
21 Self {
22 deadline: None,
23 cancellation: CancellationToken::new(),
24 }
25 }
26
27 pub fn after(duration: Duration) -> Self {
28 Self {
29 deadline: Some(Instant::now() + duration),
30 cancellation: CancellationToken::new(),
31 }
32 }
33
34 pub fn with_cancellation(mut self, cancellation: CancellationToken) -> Self {
35 self.cancellation = cancellation;
36 self
37 }
38
39 pub fn cancellation(&self) -> CancellationToken {
40 self.cancellation.clone()
41 }
42
43 pub fn deadline(&self) -> Option<Instant> {
44 self.deadline
45 }
46
47 pub fn check(&self) -> Result<(), MemoryBackendError> {
48 if self.cancellation.is_cancelled() {
49 return Err(MemoryBackendError::cancelled("memory operation cancelled"));
50 }
51 if self
52 .deadline
53 .is_some_and(|deadline| Instant::now() >= deadline)
54 {
55 return Err(MemoryBackendError::timeout(
56 "memory operation deadline elapsed",
57 ));
58 }
59 Ok(())
60 }
61}
62
63#[async_trait]
68pub trait MemoryBackend: Send + Sync {
69 fn binding(&self) -> &BackendBinding;
70
71 async fn activity_json(
72 &self,
73 context: &CallContext,
74 limit: usize,
75 ) -> Result<JsonValue, MemoryBackendError>;
76 async fn delete(&self, context: &CallContext, id: &str) -> Result<bool, MemoryBackendError>;
77 async fn embedder_dim(&self, context: &CallContext) -> Result<usize, MemoryBackendError>;
78 async fn entries(
79 &self,
80 context: &CallContext,
81 limit: usize,
82 ) -> Result<Vec<MemoryEntry>, MemoryBackendError>;
83 async fn get_full(
84 &self,
85 context: &CallContext,
86 id: &str,
87 ) -> Result<FullMemoryRecord, MemoryBackendError>;
88 #[allow(clippy::too_many_arguments)]
89 async fn log_recall_with_replay(
90 &self,
91 context: &CallContext,
92 timestamp: &str,
93 scope: Option<&str>,
94 query_chars: usize,
95 hit_count: usize,
96 full_chars: usize,
97 injected_chars: usize,
98 source: &str,
99 query_excerpt: Option<&str>,
100 client: Option<&str>,
101 model: Option<&str>,
102 session: Option<&str>,
103 turn: Option<&str>,
104 task: Option<&str>,
105 actor: Option<&str>,
106 mode: &str,
107 replay_hits: &str,
108 replay_context: &str,
109 ) -> Result<(), MemoryBackendError>;
110 async fn metrics_json(&self, context: &CallContext) -> Result<JsonValue, MemoryBackendError>;
111 async fn put(
112 &self,
113 context: &CallContext,
114 name: &str,
115 content: &str,
116 scope: &str,
117 tier: MemoryTier,
118 ) -> Result<MemoryId, MemoryBackendError>;
119 async fn recall_scored(
120 &self,
121 context: &CallContext,
122 query: &str,
123 limit: usize,
124 scopes: &[String],
125 ) -> Result<Vec<(MemoryEntry, Score)>, MemoryBackendError>;
126 async fn record_injections(
127 &self,
128 context: &CallContext,
129 ids: &[String],
130 ) -> Result<(), MemoryBackendError>;
131 async fn remember(
132 &self,
133 context: &CallContext,
134 content: &str,
135 keywords: Vec<String>,
136 ) -> Result<MemoryEntry, MemoryBackendError>;
137 async fn scopes(&self, context: &CallContext) -> Result<Vec<String>, MemoryBackendError>;
138 async fn search(
139 &self,
140 context: &CallContext,
141 query: &str,
142 limit: usize,
143 ) -> Result<Vec<MemoryEntry>, MemoryBackendError>;
144 async fn try_put(
145 &self,
146 context: &CallContext,
147 name: &str,
148 content: &str,
149 scope: &str,
150 tier: MemoryTier,
151 ) -> Result<MemoryId, MemoryBackendError>;
152
153 async fn list(
155 &self,
156 context: &CallContext,
157 scope: Option<&str>,
158 ) -> Result<Vec<MemoryListRow>, MemoryBackendError>;
159
160 async fn remember_consolidated(
162 &self,
163 context: &CallContext,
164 name: &str,
165 content: &str,
166 keywords: Vec<String>,
167 threshold: Score,
168 ) -> Result<Option<MemoryEntry>, MemoryBackendError>;
169}