use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use crate::domain::memory::{
MemoryAggregateRequest, MemoryFindRequest, MemoryRecallRequest, MemoryScope,
};
pub const SALIENCE_RUBRIC: [&str; 4] = [
"none: memory would not change the outcome",
"background: memory is optional color",
"relevant: memory should be read or written",
"blocking: the next step is wrong if memory is skipped",
];
pub const MEMORY_ESCALATE_TOPIC: &str = "locus.memory.escalate";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MemoryAction {
Ignore,
Recall,
Find,
Persist,
Explain,
Aggregate,
}
impl MemoryAction {
pub fn as_str(self) -> &'static str {
match self {
Self::Ignore => "ignore",
Self::Recall => "recall",
Self::Find => "find",
Self::Persist => "persist",
Self::Explain => "explain",
Self::Aggregate => "aggregate",
}
}
pub fn parse(value: &str) -> Option<Self> {
match value {
"ignore" => Some(Self::Ignore),
"recall" => Some(Self::Recall),
"find" => Some(Self::Find),
"persist" => Some(Self::Persist),
"explain" => Some(Self::Explain),
"aggregate" => Some(Self::Aggregate),
_ => None,
}
}
pub fn topic(self) -> &'static str {
match self {
Self::Ignore => "locus.memory.ignore",
Self::Recall => "locus.memory.recall",
Self::Find => "locus.memory.find",
Self::Persist => "locus.memory.persist",
Self::Explain => "locus.memory.explain",
Self::Aggregate => "locus.memory.aggregate",
}
}
pub fn is_read(self) -> bool {
matches!(
self,
Self::Recall | Self::Find | Self::Explain | Self::Aggregate
)
}
pub fn all() -> &'static [Self] {
&[
Self::Ignore,
Self::Recall,
Self::Find,
Self::Persist,
Self::Explain,
Self::Aggregate,
]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MemoryReflexKind {
Dispatch,
Ignore,
Escalate,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReflexGate {
Accepted,
BlankStimulus,
BelowSalience,
LowConfidence,
PropositionDisagreement,
System2Required,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MemoryPropositions {
pub references_prior: f32,
pub should_persist: f32,
pub needs_system2: f32,
}
impl Default for MemoryPropositions {
fn default() -> Self {
Self {
references_prior: 0.0,
should_persist: 0.0,
needs_system2: 0.0,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MemoryPersistHint {
pub text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MemoryStimulus {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
#[serde(default)]
pub scope: MemoryScope,
#[serde(default)]
pub metadata: Map<String, Value>,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReflexPolicy {
pub min_choice_confidence: f32,
pub min_salience: f32,
pub read_floor: f32,
pub write_floor: f32,
pub escalate_at: f32,
pub page_limit: usize,
}
impl Default for ReflexPolicy {
fn default() -> Self {
Self {
min_choice_confidence: 0.55,
min_salience: 0.34,
read_floor: 0.45,
write_floor: 0.45,
escalate_at: 0.70,
page_limit: 8,
}
}
}
#[derive(Debug, Clone)]
pub struct MemoryReflex {
pub schema_version: String,
pub stimulus_id: String,
pub stimulus_text: String,
pub role: Option<String>,
pub scope: MemoryScope,
pub kind: MemoryReflexKind,
pub action: MemoryAction,
pub topic: String,
pub salience: f32,
pub salience_label: String,
pub salience_confidence: f32,
pub confidence: f32,
pub propositions: MemoryPropositions,
pub gate: ReflexGate,
pub companions: Vec<MemoryAction>,
pub recall: Option<MemoryRecallRequest>,
pub find: Option<MemoryFindRequest>,
pub aggregate: Option<MemoryAggregateRequest>,
pub persist: Option<MemoryPersistHint>,
pub decider_id: String,
pub checkpoint: Option<String>,
pub metadata: Map<String, Value>,
}