use std::time::SystemTime;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Signal(pub String);
impl Signal {
pub fn new(s: impl Into<String>) -> Self {
Self(s.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Evidence {
pub source_skill: String,
pub label: String,
pub detail: Value,
pub recorded_at: SystemTime,
}
impl Evidence {
pub fn new(source_skill: impl Into<String>, label: impl Into<String>) -> Self {
Self {
source_skill: source_skill.into(),
label: label.into(),
detail: Value::Null,
recorded_at: SystemTime::now(),
}
}
pub fn with_detail(mut self, detail: Value) -> Self {
self.detail = detail;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NextAction {
RunSkill(String),
InvokeTool { tool: String, args: Value },
Conclude,
Discard,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InvestigationContext {
pub entity_id: String,
pub block_id: Option<Uuid>,
pub partition: String,
pub signals: Vec<Signal>,
pub evidence: Vec<Evidence>,
pub confidence: f32,
pub pending_actions: Vec<NextAction>,
}
impl InvestigationContext {
pub fn new(entity_id: impl Into<String>, partition: impl Into<String>) -> Self {
Self {
entity_id: entity_id.into(),
block_id: None,
partition: partition.into(),
signals: Vec::new(),
evidence: Vec::new(),
confidence: 0.0,
pending_actions: Vec::new(),
}
}
pub fn with_block<I: Into<Uuid>>(mut self, id: I) -> Self {
self.block_id = Some(id.into());
self
}
pub fn with_signal(mut self, s: impl Into<String>) -> Self {
self.signals.push(Signal::new(s));
self
}
pub fn has_signal(&self, name: &str) -> bool {
self.signals.iter().any(|s| s.as_str() == name)
}
}