nexgenomics 0.2.8

The official Rust crate for NexGenomics
Documentation

// src/threads.rs

use crate::utils;
use reqwest::{Client,Error};
use reqwest::header::{AUTHORIZATION, HeaderValue};
use chrono::{DateTime,Utc};
use serde::Deserialize;
use serde_json::{json};


/**
A Thread is a conversation. The participants may be humans, AI agents, or AI assistants.
*/
#[derive(Debug,Deserialize)]
#[allow(dead_code)]
pub struct Thread {
    pub id: String,
    pub title: String,
    pub creator: String,
    pub created_at: DateTime<Utc>,
}


/**
This struct contains a message from a thread.
*/
#[derive(Debug,Deserialize)]
#[allow(dead_code)]
pub struct Message {
    pub creator: String,
    pub message: String,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug,Deserialize)]
struct AssistantResponse {
    pub message: String,
}


/**
create_thread creates a new conversation thread with the supplied title.
*/
pub async fn create_thread(title:&str) -> Result<Thread,Error> {
    //Ok(Thread{id:"A".to_string(),title:"B".to_string(),creator:"C".to_string(),created_at:Utc::now()})
    let auth_token = utils::get_api_auth_token().unwrap();
    let url_stem = utils::get_api_url_stem().unwrap();
    let token = format!("Bearer {}", auth_token);
    let url = format!("{}/api/v0/thread",url_stem);


    let body = json!({
        "title": title.to_string(),
        "metadata": {},
    });

    let client = Client::new();
    let response = client
        .put(url)
        .header (AUTHORIZATION, HeaderValue::from_str(&token).unwrap())
        .json(&body)
        .send()
        .await?
        .error_for_status()?
        .json::<Thread>()
        .await?;

    Ok(response)
}



    /*
impl Thread {
    pub async fn new(title:&str) -> Result<Self,Box<dyn std::error::Error>> {
        let auth_token = utils::get_api_auth_token().unwrap();
        let url_stem = utils::get_api_url_stem().unwrap();
        let token = format!("Bearer {}", auth_token);
        let url = format!("{}/api/v0/thread",url_stem);


        let body = json!({
            "title": title.to_string(),
            "metadata": {},
        });

        let client = Client::new();
        let response = client
            .put(url)
            .header (AUTHORIZATION, HeaderValue::from_str(&token).unwrap())
            .json(&body)
            .send()
            .await?
            .error_for_status()?
            .json::<Thread>()
            .await?;

        Ok(response)

        /*
        let tid = response.get("thread_id").ok_or("no thread id".to_string())?;
        let t2 = if let Value::String(s) = tid {
            Some(s)
        } else {
            None
        };

        Ok(Self {
            id: t2.unwrap().to_string(),
            creator: "".to_string(),
            title: title.to_string(),
            created_at: Utc::now(),
        })
        */
    }
    */



impl Thread {
    pub async fn get_messages(&self) -> Result<Vec<Message>,Box<dyn std::error::Error>> {
        let auth_token = format! ("Bearer {}", utils::get_api_auth_token().unwrap());
        let url = format! ("{}/api/v0/thread/{}/messages", utils::get_api_url_stem().unwrap(), self.id);

        let client = Client::new();
        let response = client
            .get(url)
            .header (AUTHORIZATION, HeaderValue::from_str(&auth_token).unwrap())
            .send()
            .await?
            .error_for_status()?
            .json::<Vec<Message>>()
            .await?;

        Ok(response)
    }
}


impl Thread {
    pub async fn post_message(&self, msg:&str) -> Result<(), Box<dyn std::error::Error>> {
        let auth_token = format! ("Bearer {}", utils::get_api_auth_token().unwrap());
        let url = format! ("{}/api/v0/thread/{}/message", utils::get_api_url_stem().unwrap(), self.id);

        let body = json!({
            "msg": msg.to_string(),
        });

        let client = Client::new();
        let _ = client
            .post(url)
            .header (AUTHORIZATION, HeaderValue::from_str(&auth_token).unwrap())
            .json(&body)
            .send()
            .await?
            .error_for_status()?;

        Ok(())
    }
}



impl Thread {
    pub async fn ask_assistant(&self, optional_msg:&str) -> Result<String, Box<dyn std::error::Error>> {
        let auth_token = format! ("Bearer {}", utils::get_api_auth_token().unwrap());
        let url = format! ("{}/api/v0/thread/{}/assistant", utils::get_api_url_stem().unwrap(), self.id);

        let body = json!({
            "msg": optional_msg.to_string(),
        });

        let client = Client::new();
        let response = client
            .post(url)
            .header (AUTHORIZATION, HeaderValue::from_str(&auth_token).unwrap())
            .json(&body)
            .send()
            .await?
            .error_for_status()?
            .json::<AssistantResponse>()
            .await?;

        Ok(response.message.to_string())
    }

}







async fn inner_get_threads() -> Result<Vec<Thread>, Error> {
    let auth_token = utils::get_api_auth_token().unwrap();
    let url_stem = utils::get_api_url_stem().unwrap();
    let token = format!("Bearer {}", auth_token);
    let url = format!("{}/api/v0/threads/list",url_stem);

    let client = Client::new();
    let response = client
        .post(url)
        .header (AUTHORIZATION, HeaderValue::from_str(&token).unwrap())
        .send()
        .await?
        .error_for_status()?;

    let p = response.json::<Vec<Thread>>().await?;
    Ok(p)
    
}

#[cfg(feature = "async")]
pub async fn get_threads() -> Result<Vec<Thread>,Error> {
    inner_get_threads().await
}


#[cfg(feature = "blocking")]
pub fn get_threads() -> Result<Vec<Thread>,Error> {
    let rt = tokio::runtime::Runtime::new()
        .expect("Failed to create Tokio runtime");
    rt.block_on(inner_get_threads())
}