use std::sync::Mutex;
use async_trait::async_trait;
use serde_json::Value;
use khive_brain_core::SectionPosteriorState;
use khive_runtime::pack::PackRuntime;
use khive_runtime::{KhiveRuntime, NamespaceToken, RuntimeError, VerbRegistry};
use khive_types::{HandlerDef, Pack};
use crate::knowledge::vamana;
use crate::knowledge::KnowledgeHandlers;
use crate::vocab::KNOWLEDGE_HANDLERS;
pub struct KnowledgePack {
pub(crate) runtime: KhiveRuntime,
pub(crate) ann: vamana::SharedAnn,
pub(crate) section_posteriors: Mutex<SectionPosteriorState>,
pub(crate) brain_profile: Option<String>,
}
impl Pack for KnowledgePack {
const NAME: &'static str = "knowledge";
const NOTE_KINDS: &'static [&'static str] = &[];
const ENTITY_KINDS: &'static [&'static str] = &[];
const HANDLERS: &'static [HandlerDef] = &KNOWLEDGE_HANDLERS;
const REQUIRES: &'static [&'static str] = &["kg"];
}
impl KnowledgePack {
pub fn new(runtime: KhiveRuntime) -> Self {
let brain_profile = runtime.config().brain_profile.clone();
Self {
runtime,
ann: vamana::new_shared(),
section_posteriors: Mutex::new(SectionPosteriorState::new()),
brain_profile,
}
}
}
struct KnowledgePackFactory;
impl khive_runtime::PackFactory for KnowledgePackFactory {
fn name(&self) -> &'static str {
"knowledge"
}
fn requires(&self) -> &'static [&'static str] {
&["kg"]
}
fn create(&self, runtime: KhiveRuntime) -> Box<dyn khive_runtime::PackRuntime> {
Box::new(KnowledgePack::new(runtime))
}
}
inventory::submit! { khive_runtime::PackRegistration(&KnowledgePackFactory) }
#[async_trait]
impl PackRuntime for KnowledgePack {
fn name(&self) -> &str {
<KnowledgePack as Pack>::NAME
}
fn note_kinds(&self) -> &'static [&'static str] {
<KnowledgePack as Pack>::NOTE_KINDS
}
fn entity_kinds(&self) -> &'static [&'static str] {
<KnowledgePack as Pack>::ENTITY_KINDS
}
fn handlers(&self) -> &'static [HandlerDef] {
&KNOWLEDGE_HANDLERS
}
fn requires(&self) -> &'static [&'static str] {
<KnowledgePack as Pack>::REQUIRES
}
async fn warm(&self) {
crate::knowledge::vamana::warm_known_snapshots(&self.runtime, &self.ann).await;
if !self.runtime.default_embedder_name().is_empty() {
let runtime = self.runtime.clone();
tokio::spawn(async move {
let _ = runtime.embed("__khive_knowledge_warm__").await;
});
}
}
async fn dispatch(
&self,
verb: &str,
params: Value,
registry: &VerbRegistry,
token: &NamespaceToken,
) -> Result<Value, RuntimeError> {
match verb {
"knowledge.upsert_atoms" => {
KnowledgeHandlers::upsert_atoms(&self.runtime, token, params).await
}
"knowledge.upsert_domains" => {
KnowledgeHandlers::upsert_domains(&self.runtime, token, params).await
}
"knowledge.get" => KnowledgeHandlers::get(&self.runtime, token, params).await,
"knowledge.list" => KnowledgeHandlers::list(&self.runtime, token, params).await,
"knowledge.delete_atoms" => {
KnowledgeHandlers::delete_atoms(&self.runtime, token, params).await
}
"knowledge.stats" => KnowledgeHandlers::stats(&self.runtime, token, params).await,
"knowledge.index" => {
KnowledgeHandlers::index(&self.runtime, token, params, &self.ann, None).await
}
"knowledge.fold" => KnowledgeHandlers::fold(&self.runtime, token, params).await,
"knowledge.search" => {
KnowledgeHandlers::search(&self.runtime, token, params, &self.ann).await
}
"knowledge.suggest" => {
KnowledgeHandlers::suggest(&self.runtime, token, params, &self.ann).await
}
"knowledge.compose" => {
KnowledgeHandlers::compose(&self.runtime, token, params, &self.ann).await
}
"knowledge.edit" => KnowledgeHandlers::edit(&self.runtime, token, params).await,
"knowledge.import" => KnowledgeHandlers::import(&self.runtime, token, params).await,
"knowledge.challenge" => {
KnowledgeHandlers::challenge(&self.runtime, token, params).await
}
"knowledge.adjudicate" => {
KnowledgeHandlers::adjudicate(&self.runtime, token, params).await
}
"knowledge.learn" => self.handle_learn(token, params).await,
"knowledge.cite" => self.handle_cite(token, params).await,
"knowledge.topic" => self.handle_topic(token, params).await,
"knowledge.feedback" => self.handle_feedback(token, params, registry).await,
_ => Err(RuntimeError::InvalidInput(format!(
"knowledge pack does not handle verb {verb:?}"
))),
}
}
}