use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MemoryType {
Identity,
Preference,
Decision,
Fact,
Goal,
}
impl MemoryType {
pub fn all_values() -> &'static [&'static str] {
&["identity", "preference", "decision", "fact", "goal"]
}
pub fn is_profile_alias(s: &str) -> bool {
s.eq_ignore_ascii_case("profile")
}
}
impl std::fmt::Display for MemoryType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Identity => "identity",
Self::Preference => "preference",
Self::Decision => "decision",
Self::Fact => "fact",
Self::Goal => "goal",
};
f.write_str(s)
}
}
impl std::str::FromStr for MemoryType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"identity" => Ok(Self::Identity),
"preference" => Ok(Self::Preference),
"decision" => Ok(Self::Decision),
"fact" => Ok(Self::Fact),
"goal" => Ok(Self::Goal),
"knowledge" => Ok(Self::Fact),
"profile" => Err(
"profile requires sub-classification into identity, preference, or goal -- use classify_memory_type".to_string()
),
"correction" | "custom" | "recap" => Ok(Self::Fact),
_ => Err(format!(
"invalid memory_type '{}', valid values: {}",
s,
Self::all_values().join(", ")
)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StabilityTier {
Protected,
Standard,
Ephemeral,
}
pub fn stability_tier(memory_type: Option<&str>) -> StabilityTier {
match memory_type {
Some("identity") | Some("preference") => StabilityTier::Protected,
Some("fact") | Some("decision") => StabilityTier::Standard,
_ => StabilityTier::Ephemeral,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RawDocument {
pub source: String,
pub source_id: String,
pub title: String,
pub summary: Option<String>,
pub content: String,
pub url: Option<String>,
pub last_modified: i64,
pub metadata: HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub memory_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_agent: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub confidence: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub confirmed: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stability: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub supersedes: Option<String>,
#[serde(default)]
pub pending_revision: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub entity_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quality: Option<String>,
#[serde(default)]
pub is_recap: bool,
#[serde(default = "default_enrichment_status")]
pub enrichment_status: String,
#[serde(default = "default_supersede_mode")]
pub supersede_mode: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub structured_fields: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retrieval_cue: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_text: Option<String>,
}
fn default_enrichment_status() -> String {
"raw".to_string()
}
fn default_supersede_mode() -> String {
"hide".to_string()
}
impl Default for RawDocument {
fn default() -> Self {
Self {
source: String::new(),
source_id: String::new(),
title: String::new(),
summary: None,
content: String::new(),
url: None,
last_modified: 0,
metadata: HashMap::new(),
memory_type: None,
domain: None,
source_agent: None,
confidence: None,
confirmed: None,
stability: None,
supersedes: None,
pending_revision: false,
entity_id: None,
quality: None,
is_recap: false,
enrichment_status: "raw".to_string(),
supersede_mode: "hide".to_string(),
structured_fields: None,
retrieval_cue: None,
source_text: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SourceType {
Obsidian,
Directory,
}
impl SourceType {
pub fn as_str(&self) -> &'static str {
match self {
Self::Obsidian => "obsidian",
Self::Directory => "directory",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SyncStatus {
Active,
Paused,
Error(String),
}