1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
4pub enum EmbeddingProviderKind {
5 #[default]
6 Disabled,
7 DeterministicLocal,
8}
9
10#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
11pub enum RecallScoringProfile {
12 #[default]
13 Balanced,
14 LexicalFirst,
15 ImportanceFirst,
16}
17
18#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
19pub enum RecallScorerKind {
20 #[default]
21 Profile,
22 Curated,
23}
24
25#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
26pub enum RecallPlanningProfile {
27 #[default]
28 FastPath,
29 ContinuityAware,
30}
31
32#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
33pub enum RecallPolicyProfile {
34 #[default]
35 General,
36 Support,
37 Research,
38 Assistant,
39 AutonomousAgent,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
43pub struct EngineTuningInfo {
44 pub recall_scorer_kind: RecallScorerKind,
45 pub recall_scoring_profile: RecallScoringProfile,
46 pub recall_planning_profile: RecallPlanningProfile,
47 pub recall_policy_profile: RecallPolicyProfile,
48 pub embedding_provider_kind: EmbeddingProviderKind,
49 pub embedding_dimensions: usize,
50 pub graph_expansion_max_hops: u8,
51 pub compaction_summarize_after_record_count: usize,
52 pub compaction_cold_archive_after_days: u32,
53 pub compaction_cold_archive_importance_threshold_per_mille: u16,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
57pub struct EngineConfig {
58 pub node_id: String,
59 pub default_tenant: String,
60 pub max_batch_size: usize,
61 pub retention: RetentionPolicy,
62 pub compaction: CompactionPolicy,
63 pub ingestion: IngestionPolicy,
64 pub recall_scorer_kind: RecallScorerKind,
65 pub recall_scoring_profile: RecallScoringProfile,
66 pub recall_planning_profile: RecallPlanningProfile,
67 pub recall_policy_profile: RecallPolicyProfile,
68 pub embedding_provider_kind: EmbeddingProviderKind,
69 pub embedding_dimensions: usize,
70 pub graph_expansion_max_hops: u8,
71 pub explain_recall: bool,
72}
73
74impl Default for EngineConfig {
75 fn default() -> Self {
76 Self {
77 node_id: "local-node".to_string(),
78 default_tenant: "default".to_string(),
79 max_batch_size: 256,
80 retention: RetentionPolicy::default(),
81 compaction: CompactionPolicy::default(),
82 ingestion: IngestionPolicy::default(),
83 recall_scorer_kind: RecallScorerKind::default(),
84 recall_scoring_profile: RecallScoringProfile::default(),
85 recall_planning_profile: RecallPlanningProfile::default(),
86 recall_policy_profile: RecallPolicyProfile::default(),
87 embedding_provider_kind: EmbeddingProviderKind::default(),
88 embedding_dimensions: 64,
89 graph_expansion_max_hops: 1,
90 explain_recall: true,
91 }
92 }
93}
94
95impl EngineConfig {
96 pub fn tuning_info(&self) -> EngineTuningInfo {
97 EngineTuningInfo {
98 recall_scorer_kind: self.recall_scorer_kind,
99 recall_scoring_profile: self.recall_scoring_profile,
100 recall_planning_profile: self.recall_planning_profile,
101 recall_policy_profile: self.recall_policy_profile,
102 embedding_provider_kind: self.embedding_provider_kind,
103 embedding_dimensions: self.embedding_dimensions,
104 graph_expansion_max_hops: self.graph_expansion_max_hops,
105 compaction_summarize_after_record_count: self.compaction.summarize_after_record_count,
106 compaction_cold_archive_after_days: self.compaction.cold_archive_after_days,
107 compaction_cold_archive_importance_threshold_per_mille: self
108 .compaction
109 .cold_archive_importance_threshold_per_mille,
110 }
111 }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
115pub struct RetentionPolicy {
116 pub ttl_days: u32,
117 pub archive_after_days: u32,
118 pub max_records_per_namespace: usize,
119 pub pinned_records_exempt: bool,
120}
121
122impl Default for RetentionPolicy {
123 fn default() -> Self {
124 Self {
125 ttl_days: 0,
126 archive_after_days: 0,
127 max_records_per_namespace: 5_000,
128 pinned_records_exempt: true,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134pub struct CompactionPolicy {
135 pub deduplicate_similar_records: bool,
136 pub summarize_after_record_count: usize,
137 pub prune_stale_graph_edges: bool,
138 pub cold_archive_after_days: u32,
139 pub cold_archive_importance_threshold_per_mille: u16,
140 pub maintenance_interval_operations: u32,
141 pub dry_run_supported: bool,
142}
143
144impl Default for CompactionPolicy {
145 fn default() -> Self {
146 Self {
147 deduplicate_similar_records: true,
148 summarize_after_record_count: 50,
149 prune_stale_graph_edges: true,
150 cold_archive_after_days: 0,
151 cold_archive_importance_threshold_per_mille: 250,
152 maintenance_interval_operations: 32,
153 dry_run_supported: true,
154 }
155 }
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
159pub struct IngestionPolicy {
160 pub idempotent_writes_required: bool,
161 pub deduplication_window_hours: u32,
162 pub allow_model_derived_memories: bool,
163 pub require_source_labels: bool,
164}
165
166impl Default for IngestionPolicy {
167 fn default() -> Self {
168 Self {
169 idempotent_writes_required: true,
170 deduplication_window_hours: 24,
171 allow_model_derived_memories: true,
172 require_source_labels: false,
173 }
174 }
175}