Skip to main content

serve/
serve.rs

1//! Serve the bridge over HTTP with the System One compatible surface.
2//!
3//! ```bash
4//! export JEV_BRIDGE_UPSTREAM_URL=http://127.0.0.1:8080/v1
5//! export JEV_BRIDGE_UPSTREAM_KEY=...      # only if the server requires it
6//! export JEV_BRIDGE_API_KEY=...           # optional, for clients of this service
7//! cargo run --example serve
8//! ```
9//!
10//! Then:
11//!
12//! ```bash
13//! curl http://127.0.0.1:8100/health
14//! curl http://127.0.0.1:8100/v1/systemone \
15//!   -H 'Content-Type: application/json' \
16//!   -d '{"model":"example-bridge","state":"I was charged twice.",
17//!        "questions":{"queue":{"type":"choice","criteria":{"billing":"Refunds","sales":"Pricing"}}}}'
18//! ```
19
20use std::sync::Arc;
21
22use anyhow::{Context, Result};
23use serde_json::json;
24
25use jev_bridge::server::{router, AppState, Bridge, BridgeConfig};
26
27const ADDRESS: &str = "127.0.0.1:8100";
28
29#[tokio::main]
30async fn main() -> Result<()> {
31    let openai_base = std::env::var("JEV_BRIDGE_UPSTREAM_URL")
32        .unwrap_or_else(|_| "http://127.0.0.1:8080/v1".to_string());
33    let native_base = std::env::var("JEV_BRIDGE_NATIVE_URL")
34        .unwrap_or_else(|_| openai_base.trim_end_matches("/v1").to_string());
35    let upstream_model =
36        std::env::var("JEV_BRIDGE_UPSTREAM_MODEL").unwrap_or_else(|_| "local-model".to_string());
37
38    let bridge = Bridge::connect(
39        reqwest::Client::new(),
40        BridgeConfig {
41            openai_base,
42            native_base,
43            upstream_model,
44            upstream_key: std::env::var("JEV_BRIDGE_UPSTREAM_KEY").ok(),
45            served_model: "example-bridge".to_string(),
46            description: "example bridge over a generic inference API".to_string(),
47            release_date: "2026-09-22".to_string(),
48            chat_template_kwargs: json!({"enable_thinking": false}),
49            max_input_tokens: None,
50            local: Default::default(),
51        },
52    )
53    .await
54    .context("connecting to the upstream service failed")?;
55
56    println!("transport: {} via {}", bridge.probe().name(), bridge.probe().endpoint());
57
58    let state = Arc::new(AppState {
59        bridge,
60        api_key: std::env::var("JEV_BRIDGE_API_KEY").ok(),
61    });
62    let listener = tokio::net::TcpListener::bind(ADDRESS)
63        .await
64        .with_context(|| format!("binding {ADDRESS} failed"))?;
65    println!("listening on http://{ADDRESS}");
66    axum::serve(listener, router(state))
67        .with_graceful_shutdown(async {
68            let _ = tokio::signal::ctrl_c().await;
69        })
70        .await
71        .context("the HTTP server stopped unexpectedly")
72}