Skip to main content

khive_pack_session/
pack.rs

1//! `SessionPack` self-registration factory and `PackRuntime` dispatch impl.
2
3use async_trait::async_trait;
4use serde_json::Value;
5
6use khive_runtime::pack::PackRuntime;
7use khive_runtime::{KhiveRuntime, NamespaceToken, RuntimeError, SchemaPlan, VerbRegistry};
8use khive_types::{EdgeEndpointRule, HandlerDef, Pack, PackSchemaPlan};
9
10use crate::{handlers, vocab::SESSION_HANDLERS};
11
12pub struct SessionPack {
13    runtime: KhiveRuntime,
14}
15
16impl SessionPack {
17    pub fn new(runtime: KhiveRuntime) -> Self {
18        Self { runtime }
19    }
20
21    pub(crate) fn runtime(&self) -> &KhiveRuntime {
22        &self.runtime
23    }
24}
25
26impl Pack for SessionPack {
27    const NAME: &'static str = "session";
28    const NOTE_KINDS: &'static [&'static str] = &["session"];
29    const ENTITY_KINDS: &'static [&'static str] = &[];
30    const HANDLERS: &'static [HandlerDef] = &SESSION_HANDLERS;
31    const REQUIRES: &'static [&'static str] = &["kg"];
32    const SCHEMA_PLAN: Option<PackSchemaPlan> = Some(PackSchemaPlan {
33        pack: "session",
34        statements: &crate::vocab::SESSION_SCHEMA_PLAN_STMTS,
35    });
36}
37
38struct SessionPackFactory;
39
40impl khive_runtime::PackFactory for SessionPackFactory {
41    fn name(&self) -> &'static str {
42        "session"
43    }
44
45    fn requires(&self) -> &'static [&'static str] {
46        &["kg"]
47    }
48
49    fn create(&self, runtime: KhiveRuntime) -> Box<dyn khive_runtime::PackRuntime> {
50        Box::new(SessionPack::new(runtime))
51    }
52}
53
54inventory::submit! { khive_runtime::PackRegistration(&SessionPackFactory) }
55
56#[async_trait]
57impl PackRuntime for SessionPack {
58    fn name(&self) -> &str {
59        <SessionPack as Pack>::NAME
60    }
61
62    fn note_kinds(&self) -> &'static [&'static str] {
63        <SessionPack as Pack>::NOTE_KINDS
64    }
65
66    fn entity_kinds(&self) -> &'static [&'static str] {
67        <SessionPack as Pack>::ENTITY_KINDS
68    }
69
70    fn handlers(&self) -> &'static [HandlerDef] {
71        <SessionPack as Pack>::HANDLERS
72    }
73
74    fn edge_rules(&self) -> &'static [EdgeEndpointRule] {
75        &[]
76    }
77
78    fn requires(&self) -> &'static [&'static str] {
79        <SessionPack as Pack>::REQUIRES
80    }
81
82    fn schema_plan(&self) -> SchemaPlan {
83        SchemaPlan {
84            pack: "session",
85            statements: &crate::vocab::SESSION_SCHEMA_PLAN_STMTS,
86        }
87    }
88
89    async fn warm(&self) {
90        let config = crate::mirror::MirrorConfig::from_env();
91        if !config.enabled && !config.codex_enabled && !config.chatgpt_enabled {
92            return;
93        }
94        let runtime = self.runtime().clone();
95        tokio::spawn(async move {
96            crate::mirror::run_mirror_service(runtime, config).await;
97        });
98    }
99
100    async fn dispatch(
101        &self,
102        verb: &str,
103        params: Value,
104        _registry: &VerbRegistry,
105        token: &NamespaceToken,
106    ) -> Result<Value, RuntimeError> {
107        let runtime = self.runtime();
108        match verb {
109            "session.store" => handlers::store::handle_store(runtime, token, params).await,
110            "session.list" => handlers::list::handle_list(runtime, token, params).await,
111            "session.resume" => handlers::resume::handle_resume(runtime, token, params).await,
112            "session.export" => handlers::export::handle_export(runtime, token, params).await,
113            _ => Err(RuntimeError::InvalidInput(format!(
114                "session pack does not handle verb {verb:?}; valid verbs: \
115                 session.store, session.list, session.resume, session.export"
116            ))),
117        }
118    }
119}