greentic_runner_host/runner/
mod.rs1pub mod adapt_events_email;
2pub mod adapt_messaging;
3pub mod adapt_slack;
4pub mod adapt_teams;
5pub mod adapt_timer;
6pub mod adapt_webchat;
7pub mod adapt_webex;
8pub mod adapt_webhook;
9pub mod adapt_whatsapp;
10pub mod contract_cache;
11pub mod contract_introspection;
12pub mod engine;
13pub mod flow_adapter;
14pub mod i18n;
15pub mod ingress_util;
16pub mod invocation;
17pub mod mocks;
18pub mod operator;
19pub mod schema_validator;
20pub mod templating;
21
22use std::net::SocketAddr;
23use std::sync::Arc;
24
25use anyhow::Result;
26use axum::routing::{any, get, post};
27use axum::{Router, serve};
28use tokio::net::TcpListener;
29
30use crate::http::{self, admin, auth::AdminAuth, health::HealthState};
31use crate::routing::TenantRouting;
32use crate::runtime::ActivePacks;
33use crate::watcher::PackReloadHandle;
34
35pub struct HostServer {
36 addr: SocketAddr,
37 router: Router,
38 _state: ServerState,
39}
40
41impl HostServer {
42 pub fn new(
43 port: u16,
44 active: Arc<ActivePacks>,
45 routing: TenantRouting,
46 health: Arc<HealthState>,
47 reload: Option<PackReloadHandle>,
48 admin: AdminAuth,
49 ) -> Result<Self> {
50 let addr = SocketAddr::from(([0, 0, 0, 0], port));
51 let state = ServerState {
52 active,
53 routing,
54 health,
55 reload,
56 admin,
57 };
58 let router = Router::new()
59 .route(
60 "/messaging/telegram/webhook",
61 post(adapt_messaging::telegram_webhook),
62 )
63 .route("/webchat/activities", post(adapt_webchat::activities))
64 .route("/teams/activities", post(adapt_teams::activities))
65 .route("/slack/events", post(adapt_slack::events))
66 .route("/slack/interactive", post(adapt_slack::interactive))
67 .route("/webex/webhook", post(adapt_webex::webhook))
68 .route(
69 "/whatsapp/webhook",
70 get(adapt_whatsapp::verify).post(adapt_whatsapp::webhook),
71 )
72 .route("/webhook/{flow_id}", any(adapt_webhook::dispatch))
73 .route("/operator/op/invoke", post(operator::invoke))
74 .route("/healthz", get(http::health::handler))
75 .route("/admin/packs/status", get(admin::status))
76 .route("/admin/packs/reload", post(admin::reload))
77 .with_state(state.clone());
78 Ok(Self {
79 addr,
80 router,
81 _state: state,
82 })
83 }
84
85 pub async fn serve(self) -> Result<()> {
86 tracing::info!(addr = %self.addr, "starting host server");
87 let listener = TcpListener::bind(self.addr).await?;
88 serve(
89 listener,
90 self.router
91 .into_make_service_with_connect_info::<SocketAddr>(),
92 )
93 .await?;
94 Ok(())
95 }
96}
97
98#[derive(Clone)]
99pub struct ServerState {
100 pub active: Arc<ActivePacks>,
101 pub routing: TenantRouting,
102 pub health: Arc<HealthState>,
103 pub reload: Option<PackReloadHandle>,
104 pub admin: AdminAuth,
105}