khive_pack_session/
pack.rs1use 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}