1use chrono::{DateTime, Utc};
2use pgvector::Vector;
3use serde::{Deserialize, Serialize};
4use sqlx::postgres::types::PgInterval;
5use sqlx::FromRow;
6use std::str::FromStr;
7use uuid::Uuid;
8
9use super::math_engine::constants;
10use super::simple_consolidation::{SimpleConsolidationConfig, SimpleConsolidationEngine};
11
12#[derive(Debug, Clone)]
13pub struct SerializableVector(pub Option<Vector>);
14
15impl Serialize for SerializableVector {
16 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17 where
18 S: serde::Serializer,
19 {
20 match &self.0 {
21 Some(v) => v.as_slice().serialize(serializer),
22 None => serializer.serialize_none(),
23 }
24 }
25}
26
27impl<'de> Deserialize<'de> for SerializableVector {
28 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
29 where
30 D: serde::Deserializer<'de>,
31 {
32 let opt_vec: Option<Vec<f32>> = Option::deserialize(deserializer)?;
33 Ok(SerializableVector(opt_vec.map(Vector::from)))
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
38#[sqlx(type_name = "varchar", rename_all = "lowercase")]
39pub enum MemoryTier {
40 Working,
41 Warm,
42 Cold,
43 Frozen,
44}
45
46impl FromStr for MemoryTier {
47 type Err = String;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 match s.to_lowercase().as_str() {
51 "working" => Ok(MemoryTier::Working),
52 "warm" => Ok(MemoryTier::Warm),
53 "cold" => Ok(MemoryTier::Cold),
54 "frozen" => Ok(MemoryTier::Frozen),
55 _ => Err(format!("Invalid memory tier: {s}")),
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
61#[sqlx(type_name = "varchar", rename_all = "lowercase")]
62pub enum MemoryStatus {
63 Active,
64 Migrating,
65 Archived,
66 Deleted,
67}
68
69#[derive(Debug, Clone, FromRow)]
70pub struct Memory {
71 pub id: Uuid,
72 pub content: String,
73 pub content_hash: String,
74 pub embedding: Option<Vector>,
75 pub tier: MemoryTier,
76 pub status: MemoryStatus,
77 pub importance_score: f64,
78 pub access_count: i32,
79 pub last_accessed_at: Option<DateTime<Utc>>,
80 pub metadata: serde_json::Value,
81 pub parent_id: Option<Uuid>,
82 pub created_at: DateTime<Utc>,
83 pub updated_at: DateTime<Utc>,
84 pub expires_at: Option<DateTime<Utc>>,
85 pub consolidation_strength: f64,
87 pub decay_rate: f64,
88 pub recall_probability: Option<f64>,
89 pub last_recall_interval: Option<PgInterval>,
90 pub recency_score: f64,
92 pub relevance_score: f64,
93}
94
95impl Serialize for Memory {
96 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
97 where
98 S: serde::Serializer,
99 {
100 use serde::ser::SerializeStruct;
101 let mut state = serializer.serialize_struct("Memory", 21)?;
102 state.serialize_field("id", &self.id)?;
103 state.serialize_field("content", &self.content)?;
104 state.serialize_field("content_hash", &self.content_hash)?;
105 state.serialize_field("embedding", &self.embedding.as_ref().map(|v| v.as_slice()))?;
106 state.serialize_field("tier", &self.tier)?;
107 state.serialize_field("status", &self.status)?;
108 state.serialize_field("importance_score", &self.importance_score)?;
109 state.serialize_field("access_count", &self.access_count)?;
110 state.serialize_field("last_accessed_at", &self.last_accessed_at)?;
111 state.serialize_field("metadata", &self.metadata)?;
112 state.serialize_field("parent_id", &self.parent_id)?;
113 state.serialize_field("created_at", &self.created_at)?;
114 state.serialize_field("updated_at", &self.updated_at)?;
115 state.serialize_field("expires_at", &self.expires_at)?;
116 state.serialize_field("consolidation_strength", &self.consolidation_strength)?;
117 state.serialize_field("decay_rate", &self.decay_rate)?;
118 state.serialize_field("recall_probability", &self.recall_probability)?;
119 state.serialize_field(
120 "last_recall_interval",
121 &self.last_recall_interval.as_ref().map(|i| i.microseconds),
122 )?;
123 state.serialize_field("recency_score", &self.recency_score)?;
124 state.serialize_field("relevance_score", &self.relevance_score)?;
125 state.end()
126 }
127}
128
129impl<'de> Deserialize<'de> for Memory {
130 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
131 where
132 D: serde::Deserializer<'de>,
133 {
134 Ok(Memory::default())
136 }
137}
138
139#[derive(Debug, Clone, FromRow)]
140pub struct MemorySummary {
141 pub id: Uuid,
142 pub summary_level: String,
143 pub summary_content: String,
144 pub summary_embedding: Option<Vector>,
145 pub start_time: DateTime<Utc>,
146 pub end_time: DateTime<Utc>,
147 pub memory_count: i32,
148 pub metadata: serde_json::Value,
149 pub created_at: DateTime<Utc>,
150 pub updated_at: DateTime<Utc>,
151}
152
153impl Serialize for MemorySummary {
154 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155 where
156 S: serde::Serializer,
157 {
158 use serde::ser::SerializeStruct;
159 let mut state = serializer.serialize_struct("MemorySummary", 10)?;
160 state.serialize_field("id", &self.id)?;
161 state.serialize_field("summary_level", &self.summary_level)?;
162 state.serialize_field("summary_content", &self.summary_content)?;
163 state.serialize_field(
164 "summary_embedding",
165 &self.summary_embedding.as_ref().map(|v| v.as_slice()),
166 )?;
167 state.serialize_field("start_time", &self.start_time)?;
168 state.serialize_field("end_time", &self.end_time)?;
169 state.serialize_field("memory_count", &self.memory_count)?;
170 state.serialize_field("metadata", &self.metadata)?;
171 state.serialize_field("created_at", &self.created_at)?;
172 state.serialize_field("updated_at", &self.updated_at)?;
173 state.end()
174 }
175}
176
177impl<'de> Deserialize<'de> for MemorySummary {
178 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
179 where
180 D: serde::Deserializer<'de>,
181 {
182 unimplemented!("MemorySummary deserialization not needed")
183 }
184}
185
186#[derive(Debug, Clone, FromRow)]
187pub struct MemoryCluster {
188 pub id: Uuid,
189 pub cluster_name: String,
190 pub centroid_embedding: Vector,
191 pub concept_tags: Vec<String>,
192 pub member_count: i32,
193 pub tier: MemoryTier,
194 pub metadata: serde_json::Value,
195 pub created_at: DateTime<Utc>,
196 pub updated_at: DateTime<Utc>,
197}
198
199impl Serialize for MemoryCluster {
200 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
201 where
202 S: serde::Serializer,
203 {
204 use serde::ser::SerializeStruct;
205 let mut state = serializer.serialize_struct("MemoryCluster", 9)?;
206 state.serialize_field("id", &self.id)?;
207 state.serialize_field("cluster_name", &self.cluster_name)?;
208 state.serialize_field("centroid_embedding", &self.centroid_embedding.as_slice())?;
209 state.serialize_field("concept_tags", &self.concept_tags)?;
210 state.serialize_field("member_count", &self.member_count)?;
211 state.serialize_field("tier", &self.tier)?;
212 state.serialize_field("metadata", &self.metadata)?;
213 state.serialize_field("created_at", &self.created_at)?;
214 state.serialize_field("updated_at", &self.updated_at)?;
215 state.end()
216 }
217}
218
219impl<'de> Deserialize<'de> for MemoryCluster {
220 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
221 where
222 D: serde::Deserializer<'de>,
223 {
224 unimplemented!("MemoryCluster deserialization not needed")
225 }
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
229pub struct MigrationHistoryEntry {
230 pub id: Uuid,
231 pub memory_id: Uuid,
232 pub from_tier: MemoryTier,
233 pub to_tier: MemoryTier,
234 pub migration_reason: Option<String>,
235 pub migrated_at: DateTime<Utc>,
236 pub migration_duration_ms: Option<i32>,
237 pub success: bool,
238 pub error_message: Option<String>,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize, Default)]
242pub struct CreateMemoryRequest {
243 pub content: String,
244 pub embedding: Option<Vec<f32>>,
245 pub tier: Option<MemoryTier>,
246 pub importance_score: Option<f64>,
247 pub metadata: Option<serde_json::Value>,
248 pub parent_id: Option<Uuid>,
249 pub expires_at: Option<DateTime<Utc>>,
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct UpdateMemoryRequest {
254 pub content: Option<String>,
255 pub embedding: Option<Vec<f32>>,
256 pub tier: Option<MemoryTier>,
257 pub importance_score: Option<f64>,
258 pub metadata: Option<serde_json::Value>,
259 pub expires_at: Option<DateTime<Utc>>,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize, Default)]
263pub struct SearchRequest {
264 pub query_text: Option<String>,
266 pub query_embedding: Option<Vec<f32>>,
267
268 pub search_type: Option<SearchType>,
270 pub hybrid_weights: Option<HybridWeights>,
271
272 pub tier: Option<MemoryTier>,
274 pub date_range: Option<DateRange>,
275 pub importance_range: Option<RangeFilter<f32>>,
276 pub metadata_filters: Option<serde_json::Value>,
277 pub tags: Option<Vec<String>>,
278
279 pub limit: Option<i32>,
281 pub offset: Option<i64>, pub cursor: Option<String>, pub similarity_threshold: Option<f32>,
284 pub include_metadata: Option<bool>,
285 pub include_facets: Option<bool>,
286
287 pub ranking_boost: Option<RankingBoost>,
289 pub explain_score: Option<bool>,
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize, Hash)]
293pub enum SearchType {
294 Semantic,
295 Temporal,
296 Hybrid,
297 FullText,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct HybridWeights {
302 pub semantic_weight: f32,
303 pub temporal_weight: f32,
304 pub importance_weight: f32,
305 pub access_frequency_weight: f32,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
309pub struct DateRange {
310 pub start: Option<DateTime<Utc>>,
311 pub end: Option<DateTime<Utc>>,
312}
313
314#[derive(Debug, Clone, Serialize, Deserialize)]
315pub struct RangeFilter<T> {
316 pub min: Option<T>,
317 pub max: Option<T>,
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct RankingBoost {
322 pub recency_boost: Option<f32>,
323 pub importance_boost: Option<f32>,
324 pub access_frequency_boost: Option<f32>,
325 pub tier_boost: Option<std::collections::HashMap<MemoryTier, f32>>,
326}
327
328#[derive(Debug, Clone, Serialize, Deserialize)]
329pub struct SearchResult {
330 pub memory: Memory,
331 pub similarity_score: f32,
332 pub temporal_score: Option<f32>,
333 pub importance_score: f64,
334 pub access_frequency_score: Option<f32>,
335 pub combined_score: f32,
336 pub score_explanation: Option<ScoreExplanation>,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct ScoreExplanation {
341 pub semantic_contribution: f32,
342 pub temporal_contribution: f32,
343 pub importance_contribution: f32,
344 pub access_frequency_contribution: f32,
345 pub total_score: f32,
346 pub factors: Vec<String>,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct SearchResponse {
351 pub results: Vec<SearchResult>,
352 pub total_count: Option<i64>,
353 pub facets: Option<SearchFacets>,
354 pub suggestions: Option<Vec<String>>,
355 pub next_cursor: Option<String>,
356 pub execution_time_ms: u64,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct SearchFacets {
361 pub tiers: std::collections::HashMap<MemoryTier, i64>,
362 pub date_histogram: Vec<DateBucket>,
363 pub importance_ranges: Vec<ImportanceRange>,
364 pub tags: std::collections::HashMap<String, i64>,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct DateBucket {
369 pub date: DateTime<Utc>,
370 pub count: i64,
371 pub interval: String, }
373
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct ImportanceRange {
376 pub min: f32,
377 pub max: f32,
378 pub count: i64,
379 pub label: String,
380}
381
382impl Default for Memory {
383 fn default() -> Self {
384 Self {
385 id: Uuid::new_v4(),
386 content: String::new(),
387 content_hash: String::new(),
388 embedding: None,
389 tier: MemoryTier::Working,
390 status: MemoryStatus::Active,
391 importance_score: 0.5,
392 access_count: 0,
393 last_accessed_at: None,
394 metadata: serde_json::json!({}),
395 parent_id: None,
396 created_at: Utc::now(),
397 updated_at: Utc::now(),
398 expires_at: None,
399 consolidation_strength: 1.0,
400 decay_rate: 1.0,
401 recall_probability: None,
402 last_recall_interval: None,
403 recency_score: 0.0,
404 relevance_score: 0.0,
405 }
406 }
407}
408
409impl Memory {
410 pub fn calculate_content_hash(content: &str) -> String {
411 use sha2::{Digest, Sha256};
412 let mut hasher = Sha256::new();
413 hasher.update(content.as_bytes());
414 hex::encode(hasher.finalize())
415 }
416
417 pub fn recall_count(&self) -> i32 {
419 self.access_count
420 }
421
422 pub fn should_migrate(&self) -> bool {
423 if matches!(self.tier, MemoryTier::Frozen) {
425 return false;
426 }
427
428 let config = SimpleConsolidationConfig::default();
429 let engine = SimpleConsolidationEngine::new(config);
430
431 match engine.calculate_recall_probability(self, None) {
433 Ok(recall_prob) => recall_prob < constants::COLD_MIGRATION_THRESHOLD,
434 Err(_) => {
435 match self.tier {
437 MemoryTier::Working => {
438 self.importance_score < 0.3
439 || (self.last_accessed_at.is_some()
440 && Utc::now()
441 .signed_duration_since(self.last_accessed_at.unwrap())
442 .num_hours()
443 > 24)
444 }
445 MemoryTier::Warm => {
446 self.importance_score < 0.1
447 && Utc::now().signed_duration_since(self.updated_at).num_days() > 7
448 }
449 MemoryTier::Cold => {
450 Utc::now().signed_duration_since(self.updated_at).num_days() > 30
451 }
452 MemoryTier::Frozen => false,
453 }
454 }
455 }
456 }
457
458 pub fn next_tier(&self) -> Option<MemoryTier> {
459 match self.tier {
460 MemoryTier::Working => Some(MemoryTier::Warm),
461 MemoryTier::Warm => Some(MemoryTier::Cold),
462 MemoryTier::Cold => Some(MemoryTier::Frozen),
463 MemoryTier::Frozen => None,
464 }
465 }
466
467 pub fn calculate_recall_probability(&self) -> Option<f64> {
471 use crate::memory::math_engine::{MathEngine, MemoryParameters};
472
473 let engine = MathEngine::new();
474 let params = MemoryParameters {
475 consolidation_strength: self.consolidation_strength,
476 decay_rate: self.decay_rate,
477 last_accessed_at: self.last_accessed_at,
478 created_at: self.created_at,
479 access_count: self.access_count,
480 importance_score: self.importance_score,
481 };
482
483 match engine.calculate_recall_probability(¶ms) {
484 Ok(result) => Some(result.recall_probability),
485 Err(e) => {
486 tracing::warn!(
487 "Recall probability calculation failed for memory {}: {}. Using fallback.",
488 self.id,
489 e
490 );
491 let fallback = (self.importance_score * self.consolidation_strength / 10.0)
493 .min(1.0)
494 .max(0.0);
495 Some(fallback)
496 }
497 }
498 }
499
500 pub fn update_consolidation_strength(&mut self, recall_interval: PgInterval) {
504 use crate::memory::math_engine::MathEngine;
505
506 let engine = MathEngine::new();
507
508 match engine.update_consolidation_strength(self.consolidation_strength, recall_interval) {
509 Ok(result) => {
510 self.consolidation_strength = result.new_consolidation_strength;
511 }
512 Err(_) => {
513 let time_hours = recall_interval.microseconds as f64 / 3_600_000_000.0;
515 let increment = time_hours.min(1.0) * 0.1; self.consolidation_strength = (self.consolidation_strength + increment).min(10.0);
517 }
518 }
519 }
520}
521
522#[derive(Debug, Clone, FromRow)]
525pub struct MemoryConsolidationLog {
526 pub id: Uuid,
527 pub memory_id: Uuid,
528 pub event_type: String,
529 pub previous_consolidation_strength: f64,
530 pub new_consolidation_strength: f64,
531 pub previous_recall_probability: Option<f64>,
532 pub new_recall_probability: Option<f64>,
533 pub recall_interval: Option<PgInterval>,
534 pub access_context: serde_json::Value,
535 pub created_at: DateTime<Utc>,
536}
537
538impl Serialize for MemoryConsolidationLog {
539 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
540 where
541 S: serde::Serializer,
542 {
543 use serde::ser::SerializeStruct;
544 let mut state = serializer.serialize_struct("MemoryConsolidationLog", 10)?;
545 state.serialize_field("id", &self.id)?;
546 state.serialize_field("memory_id", &self.memory_id)?;
547 state.serialize_field("event_type", &self.event_type)?;
548 state.serialize_field(
549 "previous_consolidation_strength",
550 &self.previous_consolidation_strength,
551 )?;
552 state.serialize_field(
553 "new_consolidation_strength",
554 &self.new_consolidation_strength,
555 )?;
556 state.serialize_field(
557 "previous_recall_probability",
558 &self.previous_recall_probability,
559 )?;
560 state.serialize_field("new_recall_probability", &self.new_recall_probability)?;
561 state.serialize_field(
562 "recall_interval_microseconds",
563 &self.recall_interval.as_ref().map(|i| i.microseconds),
564 )?;
565 state.serialize_field("access_context", &self.access_context)?;
566 state.serialize_field("created_at", &self.created_at)?;
567 state.end()
568 }
569}
570
571#[derive(Debug, Clone, FromRow)]
572pub struct FrozenMemory {
573 pub id: Uuid,
574 pub original_memory_id: Uuid,
575 pub compressed_content: serde_json::Value, pub original_metadata: Option<serde_json::Value>, pub original_content_hash: String,
578 pub original_embedding: Option<Vector>,
579 pub original_tier: MemoryTier,
580 pub freeze_reason: Option<String>,
581 pub frozen_at: DateTime<Utc>,
582 pub unfreeze_count: Option<i32>, pub last_unfrozen_at: Option<DateTime<Utc>>, pub compression_ratio: Option<f64>,
585 pub original_size_bytes: Option<i32>,
586 pub compressed_size_bytes: Option<i32>,
587}
588
589impl Serialize for FrozenMemory {
590 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
591 where
592 S: serde::Serializer,
593 {
594 use serde::ser::SerializeStruct;
595 let mut state = serializer.serialize_struct("FrozenMemory", 13)?;
596 state.serialize_field("id", &self.id)?;
597 state.serialize_field("original_memory_id", &self.original_memory_id)?;
598 state.serialize_field("compressed_content", &self.compressed_content)?;
599 state.serialize_field("original_metadata", &self.original_metadata)?;
600 state.serialize_field("original_content_hash", &self.original_content_hash)?;
601 state.serialize_field(
602 "original_embedding",
603 &self.original_embedding.as_ref().map(|v| v.as_slice()),
604 )?;
605 state.serialize_field("original_tier", &self.original_tier)?;
606 state.serialize_field("freeze_reason", &self.freeze_reason)?;
607 state.serialize_field("frozen_at", &self.frozen_at)?;
608 state.serialize_field("unfreeze_count", &self.unfreeze_count)?;
609 state.serialize_field("last_unfrozen_at", &self.last_unfrozen_at)?;
610 state.serialize_field("compression_ratio", &self.compression_ratio)?;
611 state.serialize_field("original_size_bytes", &self.original_size_bytes)?;
612 state.serialize_field("compressed_size_bytes", &self.compressed_size_bytes)?;
613 state.end()
614 }
615}
616
617#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
618pub struct MemoryTierStatistics {
619 pub id: Uuid,
620 pub tier: MemoryTier,
621 pub total_memories: i64,
622 pub average_consolidation_strength: Option<f64>,
623 pub average_recall_probability: Option<f64>,
624 pub average_age_days: Option<f64>,
625 pub total_storage_bytes: i64,
626 pub snapshot_timestamp: DateTime<Utc>,
627}
628
629#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
630pub struct ConsolidationAnalytics {
631 pub tier: MemoryTier,
632 pub total_memories: i64,
633 pub avg_consolidation_strength: Option<f64>,
634 pub avg_recall_probability: Option<f64>,
635 pub avg_decay_rate: Option<f64>,
636 pub avg_age_days: Option<f64>,
637 pub migration_candidates: i64,
638 pub never_accessed: i64,
639 pub accessed_recently: i64,
640}
641
642#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
643pub struct ConsolidationEventSummary {
644 pub event_type: String,
645 pub event_count: i64,
646 pub avg_strength_change: Option<f64>,
647 pub avg_probability_change: Option<f64>,
648 pub avg_recall_interval_hours: Option<f64>,
649}
650
651#[derive(Debug, Clone, Serialize, Deserialize)]
654pub struct FreezeMemoryRequest {
655 pub memory_id: Uuid,
656 pub reason: Option<String>,
657}
658
659#[derive(Debug, Clone, Serialize, Deserialize)]
660pub struct FreezeMemoryResponse {
661 pub frozen_id: Uuid,
662 pub compression_ratio: Option<f64>,
663 pub original_tier: MemoryTier,
664 pub frozen_at: DateTime<Utc>,
665}
666
667#[derive(Debug, Clone, Serialize, Deserialize)]
668pub struct UnfreezeMemoryRequest {
669 pub frozen_id: Uuid,
670 pub target_tier: Option<MemoryTier>,
671}
672
673#[derive(Debug, Clone, Serialize, Deserialize)]
674pub struct UnfreezeMemoryResponse {
675 pub memory_id: Uuid,
676 pub retrieval_delay_seconds: i32,
677 pub restoration_tier: MemoryTier,
678 pub unfrozen_at: DateTime<Utc>,
679}
680
681#[derive(Debug, Clone, Serialize, Deserialize)]
684pub struct ConsolidationSearchRequest {
685 pub min_consolidation_strength: Option<f64>,
686 pub max_consolidation_strength: Option<f64>,
687 pub min_recall_probability: Option<f64>,
688 pub max_recall_probability: Option<f64>,
689 pub include_frozen: Option<bool>,
690 pub tier: Option<MemoryTier>,
691 pub limit: Option<i32>,
692 pub offset: Option<i64>,
693}
694
695#[derive(Debug, Clone, Serialize, Deserialize)]
698pub struct BatchFreezeResult {
699 pub memories_frozen: u32,
700 pub total_space_saved_bytes: u64,
701 pub average_compression_ratio: f32,
702 pub processing_time_ms: u64,
703 pub frozen_memory_ids: Vec<Uuid>,
704}
705
706#[derive(Debug, Clone, Serialize, Deserialize)]
707pub struct BatchUnfreezeResult {
708 pub memories_unfrozen: u32,
709 pub total_processing_time_ms: u64,
710 pub average_delay_seconds: f32,
711 pub unfrozen_memory_ids: Vec<Uuid>,
712}
713
714#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
718#[sqlx(type_name = "varchar", rename_all = "lowercase")]
719pub enum HarvestSessionType {
720 Silent,
721 Manual,
722 Scheduled,
723 Forced,
724}
725
726#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
728#[sqlx(type_name = "varchar", rename_all = "lowercase")]
729pub enum HarvestSessionStatus {
730 InProgress,
731 Completed,
732 Failed,
733 Cancelled,
734}
735
736#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
738pub struct HarvestSession {
739 pub id: Uuid,
740 pub session_type: HarvestSessionType,
741 pub trigger_reason: String,
742 pub started_at: DateTime<Utc>,
743 pub completed_at: Option<DateTime<Utc>>,
744 pub status: HarvestSessionStatus,
745
746 pub messages_processed: i32,
748 pub patterns_extracted: i32,
749 pub patterns_stored: i32,
750 pub duplicates_filtered: i32,
751 pub processing_time_ms: i64,
752
753 pub config_snapshot: serde_json::Value,
755
756 pub error_message: Option<String>,
758 pub retry_count: i32,
759
760 pub extraction_time_ms: i64,
762 pub deduplication_time_ms: i64,
763 pub storage_time_ms: i64,
764
765 pub memory_usage_mb: Option<f64>,
767 pub cpu_usage_percent: Option<f64>,
768
769 pub created_at: DateTime<Utc>,
770}
771
772#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
774#[sqlx(type_name = "varchar", rename_all = "lowercase")]
775pub enum HarvestPatternType {
776 Preference,
777 Fact,
778 Decision,
779 Correction,
780 Emotion,
781 Goal,
782 Relationship,
783 Skill,
784}
785
786#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
788#[sqlx(type_name = "varchar", rename_all = "lowercase")]
789pub enum HarvestPatternStatus {
790 Extracted,
791 Stored,
792 Duplicate,
793 Rejected,
794}
795
796#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
798pub struct HarvestPattern {
799 pub id: Uuid,
800 pub harvest_session_id: Uuid,
801 pub pattern_type: HarvestPatternType,
802 pub content: String,
803 pub confidence_score: f64,
804 pub source_message_id: Option<String>,
805 pub context: Option<String>,
806 pub metadata: serde_json::Value,
807
808 pub status: HarvestPatternStatus,
810 pub memory_id: Option<Uuid>, pub rejection_reason: Option<String>,
812
813 pub extraction_confidence: Option<f64>,
815 pub similarity_to_existing: Option<f64>,
816
817 pub extracted_at: DateTime<Utc>,
818}
819
820#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
822#[sqlx(type_name = "varchar", rename_all = "lowercase")]
823pub enum ConsolidationEventType {
824 TierMigration,
825 ImportanceUpdate,
826 AccessDecay,
827 BatchConsolidation,
828 ManualOverride,
829}
830
831#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
833pub struct ConsolidationEvent {
834 pub id: Uuid,
835 pub event_type: ConsolidationEventType,
836 pub memory_id: Uuid,
837
838 pub source_tier: Option<String>,
840 pub target_tier: Option<String>,
841 pub migration_reason: Option<String>,
842
843 pub old_consolidation_strength: Option<f64>,
845 pub new_consolidation_strength: Option<f64>,
846 pub strength_delta: Option<f64>,
847
848 pub old_recall_probability: Option<f64>,
850 pub new_recall_probability: Option<f64>,
851 pub probability_delta: Option<f64>,
852
853 pub processing_time_ms: Option<i32>,
855
856 pub triggered_by: Option<String>, pub context_metadata: serde_json::Value,
859
860 pub created_at: DateTime<Utc>,
861}
862
863#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
865#[sqlx(type_name = "varchar", rename_all = "lowercase")]
866pub enum MemoryAccessType {
867 Search,
868 DirectRetrieval,
869 SimilarityMatch,
870 ReflectionAnalysis,
871 ConsolidationProcess,
872}
873
874#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
876pub struct MemoryAccessLog {
877 pub id: Uuid,
878 pub memory_id: Uuid,
879 pub access_type: MemoryAccessType,
880
881 pub session_id: Option<Uuid>, pub user_context: Option<String>,
884 pub query_context: Option<String>,
885
886 pub retrieval_time_ms: Option<i32>,
888 pub similarity_score: Option<f64>,
889 pub ranking_position: Option<i32>,
890
891 pub importance_boost: f64,
893 pub access_count_increment: i32,
894
895 pub accessed_at: DateTime<Utc>,
896}
897
898#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
900#[sqlx(type_name = "varchar", rename_all = "lowercase")]
901pub enum SystemMetricsSnapshotType {
902 Hourly,
903 Daily,
904 Weekly,
905 OnDemand,
906 Incident,
907}
908
909#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
911pub struct SystemMetricsSnapshot {
912 pub id: Uuid,
913 pub snapshot_type: SystemMetricsSnapshotType,
914
915 pub working_memory_count: i32,
917 pub warm_memory_count: i32,
918 pub cold_memory_count: i32,
919 pub frozen_memory_count: i32,
920
921 pub total_storage_bytes: i64,
923 pub compressed_storage_bytes: i64,
924 pub average_compression_ratio: Option<f64>,
925
926 pub average_query_time_ms: Option<f64>,
928 pub p95_query_time_ms: Option<f64>,
929 pub p99_query_time_ms: Option<f64>,
930 pub slow_query_count: i32,
931
932 pub consolidation_backlog: i32,
934 pub migration_queue_size: i32,
935 pub failed_operations_count: i32,
936
937 pub vector_index_size_mb: Option<f64>,
939 pub vector_search_performance: serde_json::Value,
940
941 pub database_cpu_percent: Option<f64>,
943 pub database_memory_mb: Option<f64>,
944 pub connection_count: Option<i32>,
945 pub active_connections: Option<i32>,
946
947 pub recorded_at: DateTime<Utc>,
948}
949
950#[derive(Debug, Clone, Serialize, Deserialize)]
953pub struct CreateHarvestSessionRequest {
954 pub session_type: HarvestSessionType,
955 pub trigger_reason: String,
956 pub config_snapshot: Option<serde_json::Value>,
957}
958
959#[derive(Debug, Clone, Serialize, Deserialize)]
960pub struct UpdateHarvestSessionRequest {
961 pub status: Option<HarvestSessionStatus>,
962 pub messages_processed: Option<i32>,
963 pub patterns_extracted: Option<i32>,
964 pub patterns_stored: Option<i32>,
965 pub duplicates_filtered: Option<i32>,
966 pub processing_time_ms: Option<i64>,
967 pub error_message: Option<String>,
968 pub extraction_time_ms: Option<i64>,
969 pub deduplication_time_ms: Option<i64>,
970 pub storage_time_ms: Option<i64>,
971 pub memory_usage_mb: Option<f64>,
972 pub cpu_usage_percent: Option<f64>,
973}
974
975#[derive(Debug, Clone, Serialize, Deserialize)]
976pub struct CreateHarvestPatternRequest {
977 pub harvest_session_id: Uuid,
978 pub pattern_type: HarvestPatternType,
979 pub content: String,
980 pub confidence_score: f64,
981 pub source_message_id: Option<String>,
982 pub context: Option<String>,
983 pub metadata: Option<serde_json::Value>,
984}
985
986#[derive(Debug, Clone, Serialize, Deserialize)]
987pub struct CreateConsolidationEventRequest {
988 pub event_type: ConsolidationEventType,
989 pub memory_id: Uuid,
990 pub source_tier: Option<String>,
991 pub target_tier: Option<String>,
992 pub migration_reason: Option<String>,
993 pub old_consolidation_strength: Option<f64>,
994 pub new_consolidation_strength: Option<f64>,
995 pub old_recall_probability: Option<f64>,
996 pub new_recall_probability: Option<f64>,
997 pub triggered_by: Option<String>,
998 pub context_metadata: Option<serde_json::Value>,
999}
1000
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub struct CreateMemoryAccessLogRequest {
1003 pub memory_id: Uuid,
1004 pub access_type: MemoryAccessType,
1005 pub session_id: Option<Uuid>,
1006 pub user_context: Option<String>,
1007 pub query_context: Option<String>,
1008 pub retrieval_time_ms: Option<i32>,
1009 pub similarity_score: Option<f64>,
1010 pub ranking_position: Option<i32>,
1011 pub importance_boost: Option<f64>,
1012 pub access_count_increment: Option<i32>,
1013}
1014
1015#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
1018pub struct HarvestSuccessRate {
1019 pub total_sessions: i32,
1020 pub successful_sessions: i32,
1021 pub failed_sessions: i32,
1022 pub success_rate: f64,
1023 pub average_processing_time_ms: f64,
1024}
1025
1026#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
1027pub struct TierMigrationStats {
1028 pub source_tier: String,
1029 pub target_tier: String,
1030 pub migration_count: i32,
1031 pub avg_processing_time_ms: f64,
1032 pub success_rate: f64,
1033}
1034
1035#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
1036pub struct TopHarvestPattern {
1037 pub pattern_type: HarvestPatternType,
1038 pub total_extracted: i32,
1039 pub total_stored: i32,
1040 pub avg_confidence: f64,
1041 pub success_rate: f64,
1042}