Skip to main content

khive_pack_template/
pack.rs

1//! Pack registration, handler table, and PackRuntime dispatch for the template pack.
2//!
3//! Non-kg packs must prefix all verb names with the pack name: `<pack>.<verb>`.
4
5use async_trait::async_trait;
6use serde_json::Value;
7
8use khive_runtime::pack::PackRuntime;
9use khive_runtime::{KhiveRuntime, NamespaceToken, RuntimeError, VerbRegistry};
10use khive_types::{HandlerDef, Visibility};
11
12use crate::{handlers, TemplatePack, PACK_NAME};
13
14/// Handler table. Add one `HandlerDef` per verb.
15///
16/// `Visibility::Verb`       = exposed on the MCP `request` tool (agent-facing).
17/// `Visibility::Subhandler` = CLI-only / internal; not on the MCP wire.
18pub(crate) static TEMPLATE_HANDLERS: [HandlerDef; 1] = [HandlerDef {
19    name: "template.my_verb",
20    description: "Example pack-prefixed verb. Non-kg packs must use pack.verb naming.",
21    visibility: Visibility::Verb,
22    category: khive_types::VerbCategory::Directive,
23    params: &[],
24}];
25
26// ── Inventory self-registration ───────────────────────────────────────────────
27//
28// Registers the pack factory so the linker includes it in the binary's
29// inventory at startup. One `inventory::submit!` per pack crate.
30
31struct TemplatePackFactory;
32
33impl khive_runtime::PackFactory for TemplatePackFactory {
34    fn name(&self) -> &'static str {
35        PACK_NAME
36    }
37    fn requires(&self) -> &'static [&'static str] {
38        &["kg"]
39    }
40    fn create(&self, runtime: KhiveRuntime) -> Box<dyn khive_runtime::PackRuntime> {
41        Box::new(TemplatePack::new(runtime))
42    }
43}
44
45inventory::submit! { khive_runtime::PackRegistration(&TemplatePackFactory) }
46
47// ── PackRuntime impl ──────────────────────────────────────────────────────────
48
49#[async_trait]
50impl PackRuntime for TemplatePack {
51    fn name(&self) -> &str {
52        <TemplatePack as khive_types::Pack>::NAME
53    }
54    fn note_kinds(&self) -> &'static [&'static str] {
55        <TemplatePack as khive_types::Pack>::NOTE_KINDS
56    }
57    fn entity_kinds(&self) -> &'static [&'static str] {
58        <TemplatePack as khive_types::Pack>::ENTITY_KINDS
59    }
60    fn handlers(&self) -> &'static [HandlerDef] {
61        &TEMPLATE_HANDLERS
62    }
63    fn requires(&self) -> &'static [&'static str] {
64        <TemplatePack as khive_types::Pack>::REQUIRES
65    }
66
67    /// Dispatch a verb call. Add a match arm for each entry in `TEMPLATE_HANDLERS`.
68    async fn dispatch(
69        &self,
70        verb: &str,
71        params: Value,
72        _registry: &VerbRegistry,
73        token: &NamespaceToken,
74    ) -> Result<Value, RuntimeError> {
75        match verb {
76            "template.my_verb" => handlers::handle_my_verb(self.runtime(), token, params).await,
77            _ => Err(RuntimeError::InvalidInput(format!(
78                "{PACK_NAME} pack does not handle verb {verb:?}"
79            ))),
80        }
81    }
82}