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