miyabi_a2a/http/
server.rs1use axum::{
4 http::{header, HeaderValue, Method},
5 routing::{get, post},
6 Router,
7};
8use std::net::SocketAddr;
9use std::sync::Arc;
10use tower_http::cors::CorsLayer;
11
12use super::routes::{
13 cancel_task, get_agents, get_events, get_system_status, get_workflow_dag, health_check,
14 retry_task,
15};
16use super::websocket::{broadcast_updates, ws_handler, WsState};
17use crate::storage::TaskStorage;
18
19#[derive(Clone)]
21pub struct AppState {
22 pub ws_state: Arc<WsState>,
24 pub storage: Arc<dyn TaskStorage>,
26}
27
28#[derive(Debug, Clone)]
30pub struct HttpServerConfig {
31 pub host: String,
33 pub port: u16,
34}
35
36impl Default for HttpServerConfig {
37 fn default() -> Self {
38 Self {
39 host: "127.0.0.1".to_string(),
40 port: 3001,
41 }
42 }
43}
44
45pub async fn start_http_server(
47 config: HttpServerConfig,
48 storage: Arc<dyn TaskStorage>,
49) -> anyhow::Result<()> {
50 let ws_state = Arc::new(WsState::new());
52
53 let app_state = AppState {
55 ws_state: ws_state.clone(),
56 storage,
57 };
58
59 let ws_state_clone = ws_state.clone();
61 tokio::spawn(async move {
62 broadcast_updates(ws_state_clone).await;
63 });
64
65 let cors = CorsLayer::new()
67 .allow_origin("http://localhost:5173".parse::<HeaderValue>()?)
68 .allow_methods([Method::GET, Method::POST])
69 .allow_headers([header::CONTENT_TYPE]);
70
71 let app = Router::new()
73 .route("/health", get(health_check))
74 .route("/api/agents", get(get_agents))
75 .route("/api/system", get(get_system_status))
76 .route("/api/events", get(get_events))
77 .route("/api/workflow/dag", get(get_workflow_dag))
78 .route("/api/tasks/:id/retry", post(retry_task))
80 .route("/api/tasks/:id/cancel", post(cancel_task))
81 .route("/ws", get(ws_handler))
83 .with_state(app_state)
84 .layer(cors);
85
86 let addr = format!("{}:{}", config.host, config.port).parse::<SocketAddr>()?;
88
89 tracing::info!("🚀 Miyabi Dashboard API server listening on http://{}", addr);
90 tracing::info!("📡 WebSocket endpoint available at ws://{}/ws", addr);
91
92 let listener = tokio::net::TcpListener::bind(addr).await?;
94 axum::serve(listener, app).await?;
95
96 Ok(())
97}