1use soma_application::CatalogSnapshot;
5use soma_provider_core::{ProviderSurface, ToolSpec};
6
7use crate::dto::{LauncherCatalogEntry, LauncherCatalogResponse};
8
9#[must_use]
14pub fn palette_entries(snapshot: &CatalogSnapshot) -> Vec<LauncherCatalogEntry> {
15 snapshot
16 .catalogs
17 .iter()
18 .flat_map(|catalog| {
19 catalog
20 .tools
21 .iter()
22 .filter(|tool| tool.exposed_on(ProviderSurface::Palette))
23 .map(|tool| tool_to_entry(&catalog.provider.name, tool))
24 })
25 .collect()
26}
27
28#[must_use]
30pub fn catalog_response(snapshot: &CatalogSnapshot) -> LauncherCatalogResponse {
31 LauncherCatalogResponse {
32 schema_version: 1,
33 fingerprint: snapshot.fingerprint.clone(),
34 entries: palette_entries(snapshot),
35 }
36}
37
38fn tool_to_entry(provider: &str, tool: &ToolSpec) -> LauncherCatalogEntry {
39 let overlay = tool.palette.as_ref();
40 LauncherCatalogEntry {
41 id: tool.name.clone(),
42 provider: provider.to_owned(),
43 title: tool.title.clone().unwrap_or_else(|| tool.name.clone()),
44 description: tool.description.clone(),
45 category: overlay.and_then(|overlay| overlay.category.clone()),
46 icon: overlay.and_then(|overlay| overlay.icon.clone()),
47 tone: overlay.and_then(|overlay| overlay.tone.clone()),
48 arg_mode: overlay.and_then(|overlay| overlay.arg_mode.clone()),
49 result_view: overlay.and_then(|overlay| overlay.result_view.clone()),
50 destructive: tool.destructive,
51 requires_admin: tool.requires_admin,
52 }
53}
54
55#[cfg(test)]
56#[path = "catalog_tests.rs"]
57mod tests;