use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::fmt;
pub type Metadata = Map<String, Value>;
pub fn default_namespace() -> String { "default".into() }
pub fn public_scope() -> String { "public".into() }
pub fn default_limit() -> usize { 50 }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RecordKind { Memory, Entity, Relation, Event, Note, Chunk }
impl RecordKind {
pub fn as_str(self) -> &'static str {
match self {
Self::Memory => "memory", Self::Entity => "entity", Self::Relation => "relation",
Self::Event => "event", Self::Note => "note", Self::Chunk => "chunk",
}
}
pub fn code(self) -> i64 {
match self {
Self::Memory => 0, Self::Entity => 1, Self::Relation => 2,
Self::Event => 3, Self::Note => 4, Self::Chunk => 5,
}
}
pub fn from_code(code: i64) -> Option<Self> {
Some(match code {
0 => Self::Memory, 1 => Self::Entity, 2 => Self::Relation,
3 => Self::Event, 4 => Self::Note, 5 => Self::Chunk, _ => return None,
})
}
}
impl fmt::Display for RecordKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct RecordKey {
pub id: i64,
}
impl RecordKey {
pub fn new(id: i64) -> Self { Self { id } }
pub(crate) fn index_key(&self) -> String { self.id.to_string() }
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct Evidence {
pub source: String,
#[serde(default)]
pub source_revision: Option<String>,
#[serde(default)]
pub chunk_id: Option<i64>,
#[serde(default)]
pub offset: Option<usize>,
#[serde(default)]
pub limit: Option<usize>,
#[serde(default)]
pub quote: String,
#[serde(default)]
pub metadata: Metadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecordInput {
#[serde(default)]
pub id: Option<i64>,
#[serde(default = "default_namespace")]
pub namespace: String,
#[serde(default = "public_scope")]
pub scope: String,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub evidence: Vec<Evidence>,
#[serde(default)]
pub metadata: Metadata,
#[serde(default)]
pub created_at_us: Option<i64>,
#[serde(default)]
pub updated_at_us: Option<i64>,
#[serde(default)]
pub expected_revision: Option<i64>,
}
impl Default for RecordInput {
fn default() -> Self {
Self { id: None, namespace: default_namespace(), scope: public_scope(), tags: vec![],
evidence: vec![], metadata: Metadata::new(), created_at_us: None,
updated_at_us: None, expected_revision: None }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecordHeader {
pub id: i64,
pub namespace: String,
pub kind: RecordKind,
pub scope: String,
pub tags: Vec<String>,
pub evidence: Vec<Evidence>,
pub metadata: Metadata,
pub created_at_us: i64,
pub updated_at_us: i64,
pub revision: i64,
}
impl RecordHeader {
pub fn key(&self) -> RecordKey { RecordKey { id: self.id } }
pub fn as_input(&self) -> RecordInput {
RecordInput { id: Some(self.id), namespace: self.namespace.clone(), scope: self.scope.clone(), tags: self.tags.clone(),
evidence: self.evidence.clone(), metadata: self.metadata.clone(), created_at_us: Some(self.created_at_us),
updated_at_us: None, expected_revision: Some(self.revision) }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReadFilter {
#[serde(default = "default_namespace")]
pub namespace: String,
#[serde(default = "default_scopes")]
pub scopes: Vec<String>,
#[serde(default)]
pub tags: Vec<String>,
}
fn default_scopes() -> Vec<String> { vec![public_scope()] }
impl Default for ReadFilter {
fn default() -> Self { Self { namespace: default_namespace(), scopes: default_scopes(), tags: vec![] } }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PageRequest {
#[serde(default)]
pub filter: ReadFilter,
#[serde(default = "default_limit")]
pub limit: usize,
#[serde(default)]
pub after: Option<String>,
}
impl Default for PageRequest {
fn default() -> Self { Self { filter: ReadFilter::default(), limit: default_limit(), after: None } }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Page<T> { pub items: Vec<T>, pub next_cursor: Option<String> }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WriteReceipt<T> {
pub value: T,
pub revision: i64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Degrade {
NamespaceDisabled,
NoEmbedder,
EmbedFailed,
VectorNotReady,
RerankFailed,
TextIndexUnavailable,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SearchDiagnostics {
pub text_used: bool,
pub vector_used: bool,
pub reranked: bool,
pub rerank_candidates: usize,
pub rerank_truncated: usize,
#[serde(default)]
pub degraded: Vec<Degrade>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthReport {
pub schema_version: i64,
pub revision: i64,
pub indexed_revision: i64,
pub record_count: usize,
pub index_document_count: usize,
pub pending_index_updates: usize,
pub sqlite_integrity: String,
pub foreign_key_errors: usize,
pub counts: std::collections::BTreeMap<String, usize>,
pub embedder_spaces: Vec<String>,
pub reranker_registered: bool,
pub last_degraded: Vec<Degrade>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MatchField {
#[default]
All,
Text,
Name,
Path,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct RebuildProgressReport {
pub active: bool,
pub processed: u64,
pub total: u64,
}