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, ParamDef, 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: &[ParamDef {
24        name: "name",
25        param_type: "string",
26        required: true,
27        description: "Non-empty string field to echo in the template response.",
28    }],
29}];
30
31// ── Inventory self-registration ───────────────────────────────────────────────
32//
33// Registers the pack factory so the linker includes it in the binary's
34// inventory at startup. One `inventory::submit!` per pack crate.
35
36struct TemplatePackFactory;
37
38impl khive_runtime::PackFactory for TemplatePackFactory {
39    fn name(&self) -> &'static str {
40        PACK_NAME
41    }
42    fn requires(&self) -> &'static [&'static str] {
43        &["kg"]
44    }
45    fn create(&self, runtime: KhiveRuntime) -> Box<dyn khive_runtime::PackRuntime> {
46        Box::new(TemplatePack::new(runtime))
47    }
48}
49
50inventory::submit! { khive_runtime::PackRegistration(&TemplatePackFactory) }
51
52// ── PackRuntime impl ──────────────────────────────────────────────────────────
53
54#[async_trait]
55impl PackRuntime for TemplatePack {
56    fn name(&self) -> &str {
57        <TemplatePack as khive_types::Pack>::NAME
58    }
59    fn note_kinds(&self) -> &'static [&'static str] {
60        <TemplatePack as khive_types::Pack>::NOTE_KINDS
61    }
62    fn entity_kinds(&self) -> &'static [&'static str] {
63        <TemplatePack as khive_types::Pack>::ENTITY_KINDS
64    }
65    fn handlers(&self) -> &'static [HandlerDef] {
66        &TEMPLATE_HANDLERS
67    }
68    fn requires(&self) -> &'static [&'static str] {
69        <TemplatePack as khive_types::Pack>::REQUIRES
70    }
71
72    /// Dispatch a verb call. Add a match arm for each entry in `TEMPLATE_HANDLERS`.
73    async fn dispatch(
74        &self,
75        verb: &str,
76        params: Value,
77        _registry: &VerbRegistry,
78        token: &NamespaceToken,
79    ) -> Result<Value, RuntimeError> {
80        match verb {
81            "template.my_verb" => handlers::handle_my_verb(self.runtime(), token, params).await,
82            _ => Err(RuntimeError::InvalidInput(format!(
83                "{PACK_NAME} pack does not handle verb {verb:?}"
84            ))),
85        }
86    }
87}