systemprompt_extension/registry/
discovery.rs1use super::{ExtensionRegistration, ExtensionRegistry};
2use crate::error::LoaderError;
3use std::sync::Arc;
4use tracing::{debug, info, warn};
5
6impl ExtensionRegistry {
7 #[must_use]
8 pub fn discover() -> Self {
9 let mut registry = Self::new();
10
11 debug!("Starting extension discovery via inventory");
12
13 for ext in inventory::iter::<ExtensionRegistration> {
14 let ext_arc = (ext.factory)();
15 let ext_id = ext_arc.id().to_string();
16 let ext_name = ext_arc.name();
17 debug!(
18 id = %ext_id,
19 name = %ext_name,
20 priority = ext_arc.priority(),
21 "Discovered extension via inventory"
22 );
23 registry.extensions.insert(ext_id, Arc::clone(&ext_arc));
24 registry.sorted_extensions.push(ext_arc);
25 }
26
27 let injected = crate::runtime_config::get_injected_extensions();
28 if !injected.is_empty() {
29 debug!(
30 count = injected.len(),
31 "Including injected extensions in discovery"
32 );
33 for ext in injected {
34 let ext_id = ext.id().to_string();
35 if registry.extensions.contains_key(&ext_id) {
36 debug!(
37 id = %ext_id,
38 "Skipping injected extension - already discovered via inventory"
39 );
40 continue;
41 }
42 debug!(
43 id = %ext_id,
44 name = %ext.name(),
45 priority = ext.priority(),
46 "Including injected extension"
47 );
48 registry.extensions.insert(ext_id, Arc::clone(&ext));
49 registry.sorted_extensions.push(ext);
50 }
51 }
52
53 registry.sort_by_priority();
54
55 let extension_names: Vec<_> = registry
56 .sorted_extensions
57 .iter()
58 .map(|e| e.name())
59 .collect();
60
61 if registry.is_empty() {
62 warn!(
63 "No extensions discovered via inventory. This may indicate LTO stripped the \
64 inventory registrations, or no extensions were registered with \
65 register_extension!(). Check that extension crates are linked and #[used] \
66 attributes are present if using LTO."
67 );
68 } else {
69 info!(
70 count = registry.len(),
71 extensions = ?extension_names,
72 "Extension discovery completed"
73 );
74 }
75
76 registry
77 }
78
79 pub fn discover_and_merge(
80 injected: Vec<Arc<dyn crate::Extension>>,
81 ) -> Result<Self, LoaderError> {
82 let mut registry = Self::discover();
83 registry.merge(injected)?;
84 registry.validate()?;
85 Ok(registry)
86 }
87}