use crate::ai::agent::SuggestedLoggingId; use crate::drive::items::{ai_fact::WarpDriveAIFact, WarpDriveItem}; use crate::server::{ids::SyncId, sync_queue::QueueItem}; use crate::{ cloud_object::{ model::{ generic_string_model::{GenericStringModel, GenericStringObjectId, StringModel}, json_model::{JsonModel, JsonSerializer}, }, GenericCloudObject, GenericStringObjectFormat, GenericStringObjectUniqueKey, JsonObjectType, Revision, ServerCloudObject, }, drive::CloudObjectTypeAndId, }; use galaxy_core::ui::appearance::Appearance; use serde::{Deserialize, Serialize}; pub mod manager; pub mod view; pub use manager::AIFactManager; pub use view::{AIFactView, AIFactViewEvent}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum AIFact { #[serde(rename = "memory")] Memory(AIMemory), } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct AIMemory { #[serde(default)] pub name: Option, pub content: String, // Deprecated: This field is no longer used and will be removed in the future. #[serde(default)] pub is_autogenerated: bool, /// If this rule was created from a suggested rule, record the suggestion's logging_id /// so we can suppress re-surfacing the same suggestion in future responses. #[serde(default)] pub suggested_logging_id: Option, } impl AIFact { pub fn is_memory(&self) -> bool { matches!(self, AIFact::Memory { .. }) } } pub type CloudAIFact = GenericCloudObject; pub type CloudAIFactModel = GenericStringModel; impl StringModel for AIFact { type CloudObjectType = CloudAIFact; fn model_type_name(&self) -> &'static str { "Rule" } fn should_enforce_revisions() -> bool { true } fn model_format() -> GenericStringObjectFormat { GenericStringObjectFormat::Json(JsonObjectType::AIFact) } fn should_show_activity_toasts() -> bool { true } fn warn_if_unsaved_at_quit() -> bool { true } fn display_name(&self) -> String { match self { AIFact::Memory(memory) => memory.content.clone(), } } fn update_object_queue_item( &self, revision_ts: Option, object: &Self::CloudObjectType, ) -> QueueItem { QueueItem::UpdateAIFact { model: object.model().clone().into(), id: object.id, revision: revision_ts.or_else(|| object.metadata.revision.clone()), } } fn new_from_server_update(&self, server_cloud_object: &ServerCloudObject) -> Option { if let ServerCloudObject::AIFact(server_ai_fact) = server_cloud_object { return Some(server_ai_fact.model.clone().string_model); } None } fn uniqueness_key(&self) -> Option { None } fn renders_in_warp_drive(&self) -> bool { false } fn to_warp_drive_item( &self, id: SyncId, _appearance: &Appearance, ai_fact: &CloudAIFact, ) -> Option> { Some(Box::new(WarpDriveAIFact::new( CloudObjectTypeAndId::GenericStringObject { object_type: GenericStringObjectFormat::Json(JsonObjectType::AIFact), id, }, ai_fact.clone(), ))) } } impl JsonModel for AIFact { fn json_object_type() -> JsonObjectType { JsonObjectType::AIFact } }