Skip to main content

librefang/
lib.rs

1//! LibreFang Rust SDK
2//!
3//! Official Rust client for the LibreFang Agent OS REST API.
4//!
5//! # Usage
6//!
7//! ```rust,no_run
8//! use librefang::LibreFang;
9//!
10//! #[tokio::main]
11//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
12//!     let client = LibreFang::new("http://localhost:4545");
13//!
14//!     // List skills
15//!     let skills = client.skills().list().await?;
16//!     println!("Skills: {}", skills.skills.len());
17//!
18//!     // List models
19//!     let models = client.models().list().await?;
20//!     println!("Models: {}", models.models.len());
21//!
22//!     Ok(())
23//! }
24//! ```
25
26use reqwest::Client;
27use serde::{Deserialize, Serialize};
28use std::sync::Arc;
29use thiserror::Error;
30
31pub mod agents;
32pub mod models;
33pub mod providers;
34pub mod skills;
35
36pub use agents::Agents;
37pub use models::Models;
38pub use providers::Providers;
39pub use skills::Skills;
40
41#[derive(Error, Debug)]
42pub enum Error {
43    #[error("HTTP error: {0}")]
44    Http(#[from] reqwest::Error),
45    #[error("API error: {0}")]
46    Api(String),
47    #[error("JSON error: {0}")]
48    Json(#[from] serde_json::Error),
49}
50
51pub type Result<T> = std::result::Result<T, Error>;
52
53#[derive(Debug, Clone)]
54pub struct LibreFang {
55    base_url: String,
56    #[allow(dead_code)]
57    client: Client,
58    agents: Arc<Agents>,
59    skills: Arc<Skills>,
60    models: Arc<Models>,
61    providers: Arc<Providers>,
62}
63
64impl LibreFang {
65    pub fn new(base_url: impl Into<String>) -> Self {
66        let base_url = base_url.into();
67        let client = Client::new();
68
69        let agents = Arc::new(Agents::new(base_url.clone(), client.clone()));
70        let skills = Arc::new(Skills::new(base_url.clone(), client.clone()));
71        let models = Arc::new(Models::new(base_url.clone(), client.clone()));
72        let providers = Arc::new(Providers::new(base_url.clone(), client.clone()));
73
74        Self {
75            base_url,
76            client,
77            agents,
78            skills,
79            models,
80            providers,
81        }
82    }
83
84    pub fn agents(&self) -> &Arc<Agents> {
85        &self.agents
86    }
87
88    pub fn skills(&self) -> &Arc<Skills> {
89        &self.skills
90    }
91
92    pub fn models(&self) -> &Arc<Models> {
93        &self.models
94    }
95
96    pub fn providers(&self) -> &Arc<Providers> {
97        &self.providers
98    }
99
100    pub fn base_url(&self) -> &str {
101        &self.base_url
102    }
103}
104
105// Common response types
106#[derive(Debug, Deserialize, Serialize)]
107pub struct ApiResponse<T> {
108    pub data: Option<T>,
109    pub error: Option<String>,
110}
111
112#[derive(Debug, Deserialize, Serialize)]
113pub struct ApiError {
114    pub error: String,
115}
116
117pub fn extract_error(
118    status: reqwest::StatusCode,
119    body: &str,
120) -> Error {
121    if let Ok(api_err) = serde_json::from_str::<ApiError>(body) {
122        Error::Api(api_err.error)
123    } else {
124        Error::Api(format!("HTTP {}", status))
125    }
126}