Skip to main content

stasis/ports/outbound/memory/
memory_models.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5#[derive(Clone, Debug, Default)]
6pub struct MemoryScope {
7    pub tenant_id: Option<String>,
8    pub session_ids: Option<Vec<String>>,
9    pub tiers: Option<Vec<String>>,
10    pub from_utc: Option<DateTime<Utc>>,
11    pub to_utc: Option<DateTime<Utc>>,
12}
13
14#[derive(Clone, Copy, Debug, Default)]
15pub struct MemoryAvecState {
16    pub stability: f32,
17    pub friction: f32,
18    pub logic: f32,
19    pub autonomy: f32,
20}
21
22#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
23pub enum MemoryFallbackPolicy {
24    Never,
25    #[default]
26    OnEmpty,
27    Always,
28}
29
30#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
31pub enum MemoryStrictnessMode {
32    Precision,
33    #[default]
34    Balanced,
35    Recall,
36}
37
38#[derive(Clone, Debug, Default)]
39pub struct MemoryMetricRange {
40    pub min: Option<f32>,
41    pub max: Option<f32>,
42}
43
44#[derive(Clone, Debug, Default)]
45pub struct MemoryFilter {
46    pub has_embedding: Option<bool>,
47    pub embedding_model: Option<String>,
48    pub psi: Option<MemoryMetricRange>,
49    pub rho: Option<MemoryMetricRange>,
50    pub kappa: Option<MemoryMetricRange>,
51    pub text_contains: Option<String>,
52    pub tags_contains: Option<Vec<String>>,
53    pub has_tag: Option<String>,
54    pub indexed_tags: Option<Vec<String>>,
55    pub tag_prefix: Option<String>,
56    pub has_semantic_links: Option<bool>,
57    pub link_rel: Option<String>,
58    pub link_target: Option<String>,
59    pub links_to_ref: Option<String>,
60}
61
62#[derive(Clone, Debug, Default, Serialize, Deserialize)]
63pub struct MemorySemanticLink {
64    pub rel: String,
65    pub target: String,
66    pub confidence: Option<f32>,
67}
68
69#[derive(Clone, Debug)]
70pub struct MemoryRecallRequest {
71    pub scope: MemoryScope,
72    pub filter: MemoryFilter,
73    pub current_avec: Option<MemoryAvecState>,
74    pub query_text: Option<String>,
75    pub limit: usize,
76    pub alpha: f32,
77    pub beta: f32,
78    pub gamma: f32,
79    pub fallback_policy: MemoryFallbackPolicy,
80    pub strictness: MemoryStrictnessMode,
81    pub include_explain: bool,
82}
83
84impl Default for MemoryRecallRequest {
85    fn default() -> Self {
86        Self {
87            scope: MemoryScope::default(),
88            filter: MemoryFilter::default(),
89            current_avec: None,
90            query_text: None,
91            limit: 20,
92            alpha: 0.7,
93            beta: 0.3,
94            gamma: 0.0,
95            fallback_policy: MemoryFallbackPolicy::OnEmpty,
96            strictness: MemoryStrictnessMode::Balanced,
97            include_explain: false,
98        }
99    }
100}
101
102#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
103pub enum MemorySortField {
104    #[default]
105    Timestamp,
106    UpdatedAt,
107    Psi,
108    Rho,
109    Kappa,
110}
111
112#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
113pub enum MemorySortDirection {
114    Asc,
115    #[default]
116    Desc,
117}
118
119#[derive(Clone, Debug)]
120pub struct MemoryFindRequest {
121    pub scope: MemoryScope,
122    pub filter: MemoryFilter,
123    pub limit: usize,
124    pub cursor: Option<String>,
125    pub sort_field: MemorySortField,
126    pub sort_direction: MemorySortDirection,
127}
128
129impl Default for MemoryFindRequest {
130    fn default() -> Self {
131        Self {
132            scope: MemoryScope::default(),
133            filter: MemoryFilter::default(),
134            limit: 50,
135            cursor: None,
136            sort_field: MemorySortField::Timestamp,
137            sort_direction: MemorySortDirection::Desc,
138        }
139    }
140}
141
142#[derive(Clone, Debug, Default)]
143pub struct MemoryNode {
144    pub raw: String,
145    pub session_id: String,
146    pub tier: String,
147    pub timestamp: DateTime<Utc>,
148    pub compression_depth: i32,
149    pub parent_node_id: Option<String>,
150    pub sync_key: String,
151    pub context_summary: Option<String>,
152    pub semantic_tags: Option<Vec<String>>,
153    pub semantic_links: Option<Vec<MemorySemanticLink>>,
154    pub embedding_model: Option<String>,
155    pub embedding_dimensions: Option<usize>,
156    pub embedded_at: Option<DateTime<Utc>>,
157    pub rho: f32,
158    pub kappa: f32,
159    pub psi: f32,
160    pub user_avec: MemoryAvecState,
161    pub model_avec: MemoryAvecState,
162    pub compression_avec: Option<MemoryAvecState>,
163    pub updated_at: DateTime<Utc>,
164}
165
166#[derive(Clone, Debug, Default)]
167pub struct MemoryFindResponse {
168    pub retrieved: usize,
169    pub has_more: bool,
170    pub next_cursor: Option<String>,
171    pub nodes: Vec<MemoryNode>,
172    pub node_sync_keys: Vec<String>,
173}
174
175#[derive(Clone, Debug, Default)]
176pub struct MemoryRecallResponse {
177    pub retrieved: usize,
178    pub next_cursor: Option<String>,
179    pub has_more: bool,
180    pub retrieval_path: Option<String>,
181    pub fallback_triggered: bool,
182    pub fallback_reason: Option<String>,
183    pub nodes: Vec<MemoryNode>,
184    pub node_sync_keys: Vec<String>,
185}
186
187#[derive(Clone, Debug)]
188pub struct MemoryStoreRequest {
189    pub session_id: String,
190    pub raw_node: String,
191}
192
193#[derive(Clone, Debug, Default)]
194pub struct MemoryStoreResponse {
195    pub node_id: String,
196    pub psi: f32,
197    pub valid: bool,
198    pub validation_error: Option<String>,
199}
200
201#[derive(Clone, Debug, Default)]
202pub struct MemoryAggregateRequest {
203    pub scope: MemoryScope,
204    pub max_groups: usize,
205    pub max_nodes: usize,
206}
207
208#[derive(Clone, Debug, Default)]
209pub struct MemoryAggregateResponse {
210    pub total_groups: usize,
211    pub scanned_nodes: usize,
212}
213
214#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
215pub enum MemoryTransformOperation {
216    #[default]
217    EmbedBackfill,
218    ReindexEmbeddings,
219    EmbedTagBackfill,
220    ReindexTagEmbeddings,
221}
222
223#[derive(Clone, Debug)]
224pub struct MemoryTransformRequest {
225    pub scope: MemoryScope,
226    pub filter: MemoryFilter,
227    pub operation: MemoryTransformOperation,
228    pub dry_run: bool,
229    pub batch_size: usize,
230    pub max_nodes: usize,
231    pub provider_id: Option<String>,
232    pub model: Option<String>,
233}
234
235impl Default for MemoryTransformRequest {
236    fn default() -> Self {
237        Self {
238            scope: MemoryScope::default(),
239            filter: MemoryFilter::default(),
240            operation: MemoryTransformOperation::EmbedBackfill,
241            dry_run: true,
242            batch_size: 100,
243            max_nodes: 5000,
244            provider_id: None,
245            model: None,
246        }
247    }
248}
249
250#[derive(Clone, Debug, Default)]
251pub struct MemoryTransformResponse {
252    pub scanned: usize,
253    pub selected: usize,
254    pub updated: usize,
255    pub skipped: usize,
256    pub failed: usize,
257    pub duplicate: usize,
258    pub failures: Vec<String>,
259}
260
261#[derive(Clone, Debug, Default)]
262pub struct MemoryRollupRequest {
263    pub scope: MemoryScope,
264    pub max_days: usize,
265    pub max_nodes: usize,
266}
267
268#[derive(Clone, Debug, Default)]
269pub struct MemoryRollupResponse {
270    pub total_groups: usize,
271    pub scanned_nodes: usize,
272}
273
274#[derive(Clone, Debug, Default)]
275pub struct MemorySchemaResponse {
276    pub schema_version: String,
277    pub sort_fields: Vec<String>,
278    pub filter_fields: Vec<String>,
279    pub group_by_fields: Vec<String>,
280    pub fallback_policies: Vec<String>,
281    pub strictness_modes: Vec<String>,
282    pub transform_operations: Vec<String>,
283    pub evict_operations: Vec<String>,
284}
285
286#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
287pub enum MemoryEvictMode {
288    #[default]
289    BySyncKeys,
290    ByNodeIds,
291    ByFilter,
292    PurgeSession,
293}
294
295#[derive(Clone, Debug, Default, Serialize, Deserialize)]
296pub struct MemoryInboundReferencesPreview {
297    pub child_parent_links: Vec<String>,
298    pub incoming_semantic_refs: Vec<String>,
299}
300
301#[derive(Clone, Debug, Default, Serialize, Deserialize)]
302pub struct MemoryEvictRecord {
303    pub node_id: String,
304    pub sync_key: String,
305    pub status: String,
306    pub reason: Option<String>,
307    pub inbound_references: Option<MemoryInboundReferencesPreview>,
308}
309
310#[derive(Clone, Debug)]
311pub struct MemoryEvictRequest {
312    pub mode: MemoryEvictMode,
313    pub scope: MemoryScope,
314    pub filter: MemoryFilter,
315    pub sync_keys: Option<Vec<String>>,
316    pub node_ids: Option<Vec<String>>,
317    pub dry_run: bool,
318    pub force: bool,
319    pub max_nodes: usize,
320    pub include_calibration: bool,
321    pub include_checkpoints: bool,
322}
323
324impl Default for MemoryEvictRequest {
325    fn default() -> Self {
326        Self {
327            mode: MemoryEvictMode::BySyncKeys,
328            scope: MemoryScope::default(),
329            filter: MemoryFilter::default(),
330            sync_keys: None,
331            node_ids: None,
332            dry_run: true,
333            force: false,
334            max_nodes: 5000,
335            include_calibration: false,
336            include_checkpoints: false,
337        }
338    }
339}
340
341#[derive(Clone, Debug, Default)]
342pub struct MemoryEvictResponse {
343    pub dry_run: bool,
344    pub deleted: usize,
345    pub blocked: usize,
346    pub not_found: usize,
347    pub skipped: usize,
348    pub would_delete: Vec<String>,
349    pub calibrations_deleted: usize,
350    pub checkpoints_deleted: usize,
351    pub records: Vec<MemoryEvictRecord>,
352}
353
354#[derive(Clone, Debug)]
355pub struct MemoryGraphRequest {
356    pub scope: MemoryScope,
357    pub filter: MemoryFilter,
358    pub include_lineage: bool,
359    pub include_semantic: bool,
360    pub include_session_topology: bool,
361    pub rel: Option<String>,
362    pub target_prefix: Option<String>,
363    pub limit: usize,
364}
365
366impl Default for MemoryGraphRequest {
367    fn default() -> Self {
368        Self {
369            scope: MemoryScope::default(),
370            filter: MemoryFilter::default(),
371            include_lineage: true,
372            include_semantic: true,
373            include_session_topology: true,
374            rel: None,
375            target_prefix: None,
376            limit: 200,
377        }
378    }
379}
380
381#[derive(Clone, Debug, Default)]
382pub struct MemoryGraphResponse {
383    pub sessions: Vec<Value>,
384    pub nodes: Vec<Value>,
385    pub edges: Vec<Value>,
386    pub retrieved: usize,
387}