feat: added langflow, langfuse and langgraph integrations (#17)
Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #17
This commit was merged in pull request #17.
This commit is contained in:
+224
-11
@@ -1,26 +1,239 @@
|
||||
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 page placeholder for the LangGraph agent builder.
|
||||
/// Agents informational landing page for LangGraph.
|
||||
///
|
||||
/// Shows a "Coming Soon" card with a disabled launch button.
|
||||
/// Will eventually integrate with the LangGraph framework.
|
||||
/// 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::<Signal<Locale>>();
|
||||
let svc = use_context::<Signal<ServiceUrlsContext>>();
|
||||
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! {
|
||||
section { class: "placeholder-page",
|
||||
div { class: "placeholder-card",
|
||||
div { class: "placeholder-icon", "A" }
|
||||
h2 { "{t(l, \"developer.agents_title\")}" }
|
||||
p { class: "placeholder-desc",
|
||||
"{t(l, \"developer.agents_desc\")}"
|
||||
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")}
|
||||
}
|
||||
}
|
||||
button { class: "btn-primary", disabled: true, "{t(l, \"developer.launch_agents\")}" }
|
||||
span { class: "placeholder-badge", "{t(l, \"common.coming_soon\")}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user