use std::any::Any;
use std::sync::Arc;
use async_trait::async_trait;
use khive_storage::EventView;
use serde_json::Value;
use crate::operations::LinkSpec;
use crate::runtime::NamespaceToken;
use crate::validation::ValidationRule;
use crate::{KhiveRuntime, RuntimeError};
use super::{
ChannelIngestCapability, EdgeEndpointRule, EntityTypeDef, HandlerDef, NoteEmbeddingPolicySpec,
NoteKindSpec, PackColumnAddition, VerbRegistry,
};
#[cfg(doc)]
use super::{PackFactory, PackRegistry};
#[derive(Debug, Default, Clone)]
pub struct SchemaPlan {
pub pack: &'static str,
pub statements: &'static [&'static str],
}
impl SchemaPlan {
pub const fn empty() -> Self {
Self {
pack: "",
statements: &[],
}
}
pub fn is_empty(&self) -> bool {
self.statements.is_empty()
}
}
#[async_trait]
pub trait DispatchHook: Send + Sync {
async fn on_dispatch(&self, view: &EventView);
}
#[async_trait]
pub trait PackRuntime: Send + Sync {
fn name(&self) -> &str;
fn host_state(&self) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn validate_config(&self) -> Result<(), RuntimeError> {
Ok(())
}
fn note_kinds(&self) -> &'static [&'static str];
fn entity_kinds(&self) -> &'static [&'static str];
fn brain_consumer_kinds(&self) -> &'static [&'static str] {
&[]
}
async fn apply_profile_section_feedback(
&self,
_token: &NamespaceToken,
_profile_id: &str,
_section_signals: Value,
_target_attribution: Option<String>,
) -> Result<Value, RuntimeError> {
Err(RuntimeError::InvalidInput(format!(
"pack {:?} does not support profile section feedback",
self.name()
)))
}
fn handlers(&self) -> &'static [HandlerDef];
fn input_schema(&self, _verb: &str) -> Option<Value> {
None
}
fn edge_rules(&self) -> &'static [EdgeEndpointRule] {
&[]
}
fn entity_types(&self) -> &'static [EntityTypeDef] {
&[]
}
fn requires(&self) -> &'static [&'static str] {
&[]
}
fn note_kind_specs(&self) -> &'static [NoteKindSpec] {
&[]
}
fn note_embedding_policies(&self) -> &'static [NoteEmbeddingPolicySpec] {
&[]
}
fn kind_hook(&self, _kind: &str) -> Option<Arc<dyn KindHook>> {
None
}
fn accept_channel_ingest_capability(&self, _capability: ChannelIngestCapability) {}
fn schema_plan(&self) -> SchemaPlan {
SchemaPlan::empty()
}
fn schema_column_additions(&self) -> &'static [PackColumnAddition] {
&[]
}
fn validation_rules(&self) -> &'static [ValidationRule] {
&[]
}
fn register_embedders(&self, _runtime: &KhiveRuntime) {}
fn register_entity_type_validator(&self, _runtime: &KhiveRuntime) {}
fn register_entity_type_validator_with_types(
&self,
runtime: &KhiveRuntime,
_pack_entity_types: &[EntityTypeDef],
) {
self.register_entity_type_validator(runtime);
}
fn register_note_mutation_hook(&self, _runtime: &KhiveRuntime) {}
fn register_note_search_ann_provider(&self, _runtime: &KhiveRuntime) {}
fn register_note_write_validator(&self, _runtime: &KhiveRuntime) {}
async fn warm(&self) {}
fn registered_embedding_model_names(&self) -> Vec<String> {
Vec::new()
}
fn mounted_namespace(&self) -> Option<&str> {
None
}
fn mounted_catalog_snapshot(&self) -> Vec<crate::mounted_verb::MountedVerb> {
Vec::new()
}
async fn mounted_catalog(&self) -> Result<Vec<crate::mounted_verb::MountedVerb>, RuntimeError> {
Ok(Vec::new())
}
async fn dispatch_mounted(
&self,
_definition: &crate::mounted_verb::MountedVerb,
verb: &str,
params: Value,
registry: &VerbRegistry,
token: &NamespaceToken,
) -> Result<Value, RuntimeError> {
self.dispatch(verb, params, registry, token).await
}
async fn dispatch(
&self,
verb: &str,
params: Value,
registry: &VerbRegistry,
token: &NamespaceToken,
) -> Result<Value, RuntimeError>;
}
#[async_trait]
pub trait KindHook: Send + Sync + std::fmt::Debug {
async fn prepare_create(
&self,
runtime: &KhiveRuntime,
args: &mut Value,
) -> Result<(), RuntimeError>;
async fn after_create(
&self,
_runtime: &KhiveRuntime,
_id: uuid::Uuid,
_args: &Value,
) -> Result<(), RuntimeError> {
Ok(())
}
fn validate_proposal_entity(
&self,
_entity: &khive_types::EntityDraft,
) -> Result<(), RuntimeError> {
Ok(())
}
fn validate_proposal_note(&self, _note: &khive_types::NoteDraft) -> Result<(), RuntimeError> {
Ok(())
}
async fn normalize_note_update(
&self,
_runtime: &KhiveRuntime,
_token: &NamespaceToken,
_note: &khive_storage::Note,
_args: &mut Value,
) -> Result<(), RuntimeError> {
Ok(())
}
async fn validate_note_update(
&self,
_runtime: &KhiveRuntime,
_token: &NamespaceToken,
_note: &khive_storage::Note,
_properties: Option<&Value>,
) -> Result<(), RuntimeError> {
Ok(())
}
async fn note_update_effects(
&self,
_runtime: &KhiveRuntime,
_token: &NamespaceToken,
_note: &khive_storage::Note,
_patch: &crate::curation::NotePatch,
) -> Result<Vec<NoteUpdateEffect>, RuntimeError> {
Ok(Vec::new())
}
fn note_update_null_clearing_properties(&self) -> &'static [&'static str] {
&[]
}
async fn validate_entity_update(
&self,
_runtime: &KhiveRuntime,
_token: &NamespaceToken,
_entity: &khive_storage::Entity,
_properties: Option<&Value>,
) -> Result<(), RuntimeError> {
Ok(())
}
async fn validate_links(
&self,
_runtime: &KhiveRuntime,
_token: &NamespaceToken,
_links: &[crate::LinkSpec],
) -> Result<(), RuntimeError> {
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum NoteUpdateEffect {
Link(LinkSpec),
DeleteEdge(khive_storage::types::Edge),
AssertLink(khive_storage::types::Edge),
}
#[async_trait]
pub trait PackByIdResolver: Send + Sync {
async fn resolve_by_id(
&self,
id: uuid::Uuid,
) -> Result<Option<crate::Resolved>, crate::RuntimeError>;
async fn resolve_by_id_including_deleted(
&self,
id: uuid::Uuid,
) -> Result<Option<crate::Resolved>, crate::RuntimeError> {
self.resolve_by_id(id).await
}
async fn delete_by_id(
&self,
id: uuid::Uuid,
hard: bool,
) -> Result<serde_json::Value, crate::RuntimeError>;
fn private_record_verbs(&self) -> &'static [&'static str] {
&[]
}
}