agent_preview.rs

 1use collections::HashMap;
 2use component::ComponentId;
 3use gpui::{App, Entity, WeakEntity};
 4use linkme::distributed_slice;
 5use std::sync::OnceLock;
 6use ui::{AnyElement, Component, Window};
 7use workspace::Workspace;
 8
 9use crate::{ActiveThread, ThreadStore};
10
11/// Function type for creating agent component previews
12pub type PreviewFn = fn(
13    WeakEntity<Workspace>,
14    Entity<ActiveThread>,
15    WeakEntity<ThreadStore>,
16    &mut Window,
17    &mut App,
18) -> Option<AnyElement>;
19
20/// Distributed slice for preview registration functions
21#[distributed_slice]
22pub static __ALL_AGENT_PREVIEWS: [fn() -> (ComponentId, PreviewFn)] = [..];
23
24/// Trait that must be implemented by components that provide agent previews.
25pub trait AgentPreview: Component {
26    /// Get the ID for this component
27    ///
28    /// Eventually this will move to the component trait.
29    fn id() -> ComponentId
30    where
31        Self: Sized,
32    {
33        ComponentId(Self::name())
34    }
35
36    /// Static method to create a preview for this component type
37    fn create_preview(
38        workspace: WeakEntity<Workspace>,
39        active_thread: Entity<ActiveThread>,
40        thread_store: WeakEntity<ThreadStore>,
41        window: &mut Window,
42        cx: &mut App,
43    ) -> Option<AnyElement>
44    where
45        Self: Sized;
46}
47
48/// Register an agent preview for the given component type
49#[macro_export]
50macro_rules! register_agent_preview {
51    ($type:ty) => {
52        #[linkme::distributed_slice($crate::ui::agent_preview::__ALL_AGENT_PREVIEWS)]
53        static __REGISTER_AGENT_PREVIEW: fn() -> (
54            component::ComponentId,
55            $crate::ui::agent_preview::PreviewFn,
56        ) = || {
57            (
58                <$type as $crate::ui::agent_preview::AgentPreview>::id(),
59                <$type as $crate::ui::agent_preview::AgentPreview>::create_preview,
60            )
61        };
62    };
63}
64
65/// Lazy initialized registry of preview functions
66static AGENT_PREVIEW_REGISTRY: OnceLock<HashMap<ComponentId, PreviewFn>> = OnceLock::new();
67
68/// Initialize the agent preview registry if needed
69fn get_or_init_registry() -> &'static HashMap<ComponentId, PreviewFn> {
70    AGENT_PREVIEW_REGISTRY.get_or_init(|| {
71        let mut map = HashMap::default();
72        for register_fn in __ALL_AGENT_PREVIEWS.iter() {
73            let (id, preview_fn) = register_fn();
74            map.insert(id, preview_fn);
75        }
76        map
77    })
78}
79
80/// Get a specific agent preview by component ID.
81pub fn get_agent_preview(
82    id: &ComponentId,
83    workspace: WeakEntity<Workspace>,
84    active_thread: Entity<ActiveThread>,
85    thread_store: WeakEntity<ThreadStore>,
86    window: &mut Window,
87    cx: &mut App,
88) -> Option<AnyElement> {
89    let registry = get_or_init_registry();
90    registry
91        .get(id)
92        .and_then(|preview_fn| preview_fn(workspace, active_thread, thread_store, window, cx))
93}
94
95/// Get all registered agent previews.
96pub fn all_agent_previews() -> Vec<ComponentId> {
97    let registry = get_or_init_registry();
98    registry.keys().cloned().collect()
99}