1use serde::{Deserialize, Serialize};
2use serde_json::{Map, Value};
3use std::fmt;
4
5pub type Metadata = Map<String, Value>;
6pub fn default_namespace() -> String { "default".into() }
7pub fn public_scope() -> String { "public".into() }
8pub fn default_limit() -> usize { 50 }
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum RecordKind { Memory, Entity, Relation, Event, Note, Chunk }
13
14impl RecordKind {
15 pub fn as_str(self) -> &'static str {
16 match self {
17 Self::Memory => "memory", Self::Entity => "entity", Self::Relation => "relation",
18 Self::Event => "event", Self::Note => "note", Self::Chunk => "chunk",
19 }
20 }
21 pub fn code(self) -> i64 {
23 match self {
24 Self::Memory => 0, Self::Entity => 1, Self::Relation => 2,
25 Self::Event => 3, Self::Note => 4, Self::Chunk => 5,
26 }
27 }
28 pub fn from_code(code: i64) -> Option<Self> {
29 Some(match code {
30 0 => Self::Memory, 1 => Self::Entity, 2 => Self::Relation,
31 3 => Self::Event, 4 => Self::Note, 5 => Self::Chunk, _ => return None,
32 })
33 }
34}
35
36impl fmt::Display for RecordKind {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
42pub struct RecordKey {
43 pub id: i64,
44}
45
46impl RecordKey {
47 pub fn new(id: i64) -> Self { Self { id } }
48 pub(crate) fn index_key(&self) -> String { self.id.to_string() }
49}
50
51#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
53pub struct Evidence {
54 pub source: String,
55 #[serde(default)]
56 pub source_revision: Option<String>,
57 #[serde(default)]
58 pub chunk_id: Option<i64>,
59 #[serde(default)]
61 pub offset: Option<usize>,
62 #[serde(default)]
63 pub limit: Option<usize>,
64 #[serde(default)]
65 pub quote: String,
66 #[serde(default)]
67 pub metadata: Metadata,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct RecordInput {
72 #[serde(default)]
74 pub id: Option<i64>,
75 #[serde(default = "default_namespace")]
76 pub namespace: String,
77 #[serde(default = "public_scope")]
78 pub scope: String,
79 #[serde(default)]
80 pub tags: Vec<String>,
81 #[serde(default)]
82 pub evidence: Vec<Evidence>,
83 #[serde(default)]
84 pub metadata: Metadata,
85 #[serde(default)]
86 pub created_at_us: Option<i64>,
87 #[serde(default)]
88 pub updated_at_us: Option<i64>,
89 #[serde(default)]
90 pub expected_revision: Option<i64>,
91}
92
93impl Default for RecordInput {
94 fn default() -> Self {
95 Self { id: None, namespace: default_namespace(), scope: public_scope(), tags: vec![],
96 evidence: vec![], metadata: Metadata::new(), created_at_us: None,
97 updated_at_us: None, expected_revision: None }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct RecordHeader {
103 pub id: i64,
104 pub namespace: String,
105 pub kind: RecordKind,
106 pub scope: String,
107 pub tags: Vec<String>,
108 pub evidence: Vec<Evidence>,
109 pub metadata: Metadata,
110 pub created_at_us: i64,
111 pub updated_at_us: i64,
112 pub revision: i64,
113}
114
115impl RecordHeader {
116 pub fn key(&self) -> RecordKey { RecordKey { id: self.id } }
117 pub fn as_input(&self) -> RecordInput {
118 RecordInput { id: Some(self.id), namespace: self.namespace.clone(), scope: self.scope.clone(), tags: self.tags.clone(),
119 evidence: self.evidence.clone(), metadata: self.metadata.clone(), created_at_us: Some(self.created_at_us),
120 updated_at_us: None, expected_revision: Some(self.revision) }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct ReadFilter {
126 #[serde(default = "default_namespace")]
127 pub namespace: String,
128 #[serde(default = "default_scopes")]
129 pub scopes: Vec<String>,
130 #[serde(default)]
132 pub tags: Vec<String>,
133 #[serde(default)]
138 pub note_ids: Vec<i64>,
139}
140
141fn default_scopes() -> Vec<String> { vec![public_scope()] }
142impl Default for ReadFilter {
143 fn default() -> Self { Self { namespace: default_namespace(), scopes: default_scopes(), tags: vec![], note_ids: vec![] } }
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct PageRequest {
148 #[serde(default)]
149 pub filter: ReadFilter,
150 #[serde(default = "default_limit")]
151 pub limit: usize,
152 #[serde(default)]
153 pub after: Option<String>,
154}
155
156impl Default for PageRequest {
157 fn default() -> Self { Self { filter: ReadFilter::default(), limit: default_limit(), after: None } }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct Page<T> { pub items: Vec<T>, pub next_cursor: Option<String> }
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct WriteReceipt<T> {
167 pub value: T,
168 pub revision: i64,
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
173#[serde(rename_all = "snake_case")]
174pub enum Degrade {
175 NamespaceDisabled,
177 NoEmbedder,
179 EmbedFailed,
181 VectorNotReady,
183 RerankFailed,
185 TextIndexUnavailable,
187}
188
189#[derive(Debug, Clone, Default, Serialize, Deserialize)]
191pub struct SearchDiagnostics {
192 pub text_used: bool,
193 pub vector_used: bool,
194 pub reranked: bool,
195 pub rerank_candidates: usize,
197 pub rerank_truncated: usize,
199 #[serde(default)]
200 pub degraded: Vec<Degrade>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct HealthReport {
205 pub schema_version: i64,
206 pub revision: i64,
207 pub indexed_revision: i64,
208 pub record_count: usize,
209 pub index_document_count: usize,
210 pub pending_index_updates: usize,
211 pub sqlite_integrity: String,
212 pub foreign_key_errors: usize,
213 pub counts: std::collections::BTreeMap<String, usize>,
214 pub embedder_spaces: Vec<String>,
216 pub reranker_registered: bool,
217 pub last_degraded: Vec<Degrade>,
219}
220
221#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
224#[serde(rename_all = "snake_case")]
225pub enum MatchField {
226 #[default]
228 All,
229 Text,
231 Name,
233 Path,
235}
236
237#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
240pub struct RebuildProgressReport {
241 pub active: bool,
242 pub processed: u64,
243 pub total: u64,
244}