use dioxus::prelude::*; use dioxus_free_icons::icons::bs_icons::{ BsBook, BsBoxArrowUpRight, BsCodeSquare, BsCpu, BsGithub, BsLightningCharge, }; use dioxus_free_icons::Icon; use crate::i18n::{t, Locale}; use crate::models::ServiceUrlsContext; /// Agents informational landing page for LangGraph. /// /// Since LangGraph is API-only (no web UI), this page displays a hero section /// explaining its role, a connection status indicator, a card grid linking /// to documentation, and a live table of registered agents fetched from the /// LangGraph assistants API. #[component] pub fn AgentsPage() -> Element { let locale = use_context::>(); let svc = use_context::>(); let l = *locale.read(); let url = svc.read().langgraph_url.clone(); // Derive whether a LangGraph URL is configured let connected = !url.is_empty(); // Build the API reference URL from the configured base, falling back to "#" let api_ref_href = if connected { format!("{}/docs", url) } else { "#".to_string() }; // Fetch agents from LangGraph when connected let agents_resource = use_resource(move || async move { match crate::infrastructure::langgraph::list_langgraph_agents().await { Ok(agents) => agents, Err(e) => { tracing::error!("Failed to fetch agents: {e}"); Vec::new() } } }); rsx! { div { class: "agents-page", // -- Hero section -- div { class: "agents-hero", div { class: "agents-hero-row", div { class: "agents-hero-icon", Icon { icon: BsCpu, width: 24, height: 24 } } h2 { class: "agents-hero-title", {t(l, "developer.agents_title")} } } p { class: "agents-hero-desc", {t(l, "developer.agents_desc")} } // -- Connection status -- if connected { div { class: "agents-status", span { class: "agents-status-dot agents-status-dot--on", } span { {t(l, "developer.agents_status_connected")} } code { class: "agents-status-url", {url.clone()} } } } else { div { class: "agents-status", span { class: "agents-status-dot agents-status-dot--off", } span { {t(l, "developer.agents_status_not_connected")} } span { class: "agents-status-hint", {t(l, "developer.agents_config_hint")} } } } } // -- Running Agents table -- div { class: "agents-table-section", h3 { class: "agents-section-title", {t(l, "developer.agents_running_title")} } match agents_resource.read().as_ref() { None => { rsx! { p { class: "agents-table-loading", {t(l, "common.loading")} } } } Some(agents) if agents.is_empty() => { rsx! { p { class: "agents-table-empty", {t(l, "developer.agents_none")} } } } Some(agents) => { rsx! { div { class: "agents-table-wrap", table { class: "agents-table", thead { tr { th { {t(l, "developer.agents_col_name")} } th { {t(l, "developer.agents_col_id")} } th { {t(l, "developer.agents_col_description")} } th { {t(l, "developer.agents_col_status")} } } } tbody { for agent in agents.iter() { tr { key: "{agent.id}", td { class: "agents-cell-name", {agent.name.clone()} } td { code { class: "agents-cell-id", {agent.id.clone()} } } td { class: "agents-cell-desc", if agent.description.is_empty() { span { class: "agents-cell-none", "--" } } else { {agent.description.clone()} } } td { span { class: "agents-badge agents-badge--active", {agent.status.clone()} } } } } } } } } } } } // -- Quick Start card grid -- h3 { class: "agents-section-title", {t(l, "developer.agents_quick_start")} } div { class: "agents-grid", // Documentation a { class: "agents-card", href: "https://langchain-ai.github.io/langgraph/", target: "_blank", rel: "noopener noreferrer", div { class: "agents-card-icon", Icon { icon: BsBook, width: 18, height: 18 } } div { class: "agents-card-title", {t(l, "developer.agents_docs")} } div { class: "agents-card-desc", {t(l, "developer.agents_docs_desc")} } } // Getting Started a { class: "agents-card", href: "https://langchain-ai.github.io/langgraph/tutorials/introduction/", target: "_blank", rel: "noopener noreferrer", div { class: "agents-card-icon", Icon { icon: BsLightningCharge, width: 18, height: 18 } } div { class: "agents-card-title", {t(l, "developer.agents_getting_started")} } div { class: "agents-card-desc", {t(l, "developer.agents_getting_started_desc")} } } // GitHub a { class: "agents-card", href: "https://github.com/langchain-ai/langgraph", target: "_blank", rel: "noopener noreferrer", div { class: "agents-card-icon", Icon { icon: BsGithub, width: 18, height: 18 } } div { class: "agents-card-title", {t(l, "developer.agents_github")} } div { class: "agents-card-desc", {t(l, "developer.agents_github_desc")} } } // Examples a { class: "agents-card", href: "https://github.com/langchain-ai/langgraph/tree/main/examples", target: "_blank", rel: "noopener noreferrer", div { class: "agents-card-icon", Icon { icon: BsCodeSquare, width: 18, height: 18 } } div { class: "agents-card-title", {t(l, "developer.agents_examples")} } div { class: "agents-card-desc", {t(l, "developer.agents_examples_desc")} } } // API Reference (disabled when URL is empty) a { class: if connected { "agents-card" } else { "agents-card agents-card--disabled" }, href: "{api_ref_href}", target: "_blank", rel: "noopener noreferrer", div { class: "agents-card-icon", Icon { icon: BsBoxArrowUpRight, width: 18, height: 18 } } div { class: "agents-card-title", {t(l, "developer.agents_api_ref")} } div { class: "agents-card-desc", {t(l, "developer.agents_api_ref_desc")} } } } } } }