Skip to main content

llmrix_rust_sdk/
client.rs

1use std::{sync::Arc, time::Duration};
2
3use crate::{
4    error::Result,
5    resources::{agents::AgentsResource, chat::ChatResource, conversations::ConversationsResource, cron::CronResource},
6    transport::Transport,
7};
8
9/// Main entry point for the Llmrix Rust SDK.
10///
11/// `LlmrixClient` is cheap to clone — all instances share the same underlying
12/// connection pool via `Arc<Transport>`.
13///
14/// # Example
15/// ```rust,no_run
16/// # use llmrix_rust_sdk::{LlmrixClient, model::ConversationCreateRequest};
17/// # #[tokio::main] async fn main() -> llmrix_rust_sdk::error::Result<()> {
18/// let client = LlmrixClient::builder()
19///     .base_url("http://localhost:8899")
20///     .api_key("sk-xxx")
21///     .build()?;
22///
23/// let conv = client.conversations()
24///     .create(ConversationCreateRequest { title: "My chat".into(), agent_id: None })
25///     .await?;
26///
27/// client.chat(&conv.id).send("Hello!", |event| {
28///     use llmrix_rust_sdk::streaming::event::StreamEvent;
29///     if let StreamEvent::MessageChunk(e) = event {
30///         print!("{}", e.content);
31///     }
32///     Ok(())
33/// }).await?;
34/// # Ok(()) }
35/// ```
36#[derive(Clone)]
37pub struct LlmrixClient {
38    transport: Arc<Transport>,
39}
40
41impl LlmrixClient {
42    /// Returns a builder for configuring and constructing a [`LlmrixClient`].
43    pub fn builder() -> ClientBuilder {
44        ClientBuilder::default()
45    }
46
47    /// Returns the resource for managing conversations and message history.
48    pub fn conversations(&self) -> ConversationsResource {
49        ConversationsResource { t: Arc::clone(&self.transport) }
50    }
51
52    /// Returns the resource for managing scheduled cron tasks.
53    pub fn cron(&self) -> CronResource {
54        CronResource { t: Arc::clone(&self.transport) }
55    }
56
57    /// Returns the resource for managing agents and their mates.
58    /// Returns HTTP 503 in native/standalone server mode.
59    pub fn agents(&self) -> AgentsResource {
60        AgentsResource { t: Arc::clone(&self.transport) }
61    }
62
63    /// Returns a [`ChatResource`] scoped to the given conversation ID.
64    pub fn chat(&self, conv_id: impl Into<String>) -> ChatResource {
65        ChatResource { t: Arc::clone(&self.transport), conv_id: conv_id.into() }
66    }
67}
68
69// ---------------------------------------------------------------------------
70// Builder
71// ---------------------------------------------------------------------------
72
73/// Builder for [`LlmrixClient`].
74#[derive(Default)]
75pub struct ClientBuilder {
76    base_url:   Option<String>,
77    api_key:    String,
78    timeout:    Option<Duration>,
79}
80
81impl ClientBuilder {
82    /// Base URL of the Llmrix server, e.g. `"http://localhost:8899"`. **Required.**
83    pub fn base_url(mut self, url: impl Into<String>) -> Self {
84        self.base_url = Some(url.into().trim_end_matches('/').to_string());
85        self
86    }
87
88    /// API key sent in the `Authorization: Bearer` header.
89    /// Omit if the server has no auth configured.
90    pub fn api_key(mut self, key: impl Into<String>) -> Self {
91        self.api_key = key.into();
92        self
93    }
94
95    /// HTTP request timeout for non-streaming requests (default: 60 s).
96    /// SSE streaming calls use no overall timeout.
97    pub fn timeout(mut self, d: Duration) -> Self {
98        self.timeout = Some(d);
99        self
100    }
101
102    /// Construct the [`LlmrixClient`].
103    ///
104    /// # Errors
105    /// Returns an error if `base_url` was not set or if the HTTP client could
106    /// not be built (e.g. invalid TLS configuration).
107    pub fn build(self) -> Result<LlmrixClient> {
108        let base_url = self.base_url
109            .expect("LlmrixClient: base_url is required — call .base_url(\"http://...\")");
110        let timeout = self.timeout.unwrap_or(Duration::from_secs(60));
111        let transport = Transport::new(base_url, self.api_key, timeout)?;
112        Ok(LlmrixClient { transport: Arc::new(transport) })
113    }
114}