x-ai 0.1.0

✨ A cli, tui, and sdk for interacting with the 𝕏-AI API
Documentation
// Copyright 2026 Mahmoud Harmouch.
//
// Licensed under the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Reference: [docs/api-reference#deferred-completion](https://docs.x.ai/docs/api-reference#deferred-completion)
//!
//! Implements `GET /v1/chat/deferred-completion/{request_id}`.
//! Returns `200 OK` with the completion when ready, or `202 Accepted` while still processing.

use crate::chat_compl::ChatCompletionResponse;
use crate::error::XaiError;
use crate::error::check_for_model_error;
use crate::traits::{ClientConfig, DeferredCompletionFetcher};
use reqwest::Method;

#[derive(Debug, Clone)]
pub struct DeferredCompletionRequestBuilder<T: ClientConfig + Clone + Send + Sync> {
    client: T,
    request_id: String,
}

impl<T> DeferredCompletionRequestBuilder<T>
where
    T: ClientConfig + Clone + Send + Sync,
{
    pub fn new(client: T, request_id: impl Into<String>) -> Self {
        Self {
            client,
            request_id: request_id.into(),
        }
    }

    pub fn build(self) -> Result<String, XaiError> {
        if self.request_id.trim().is_empty() {
            return Err(XaiError::Validation(
                "request_id cannot be empty".to_string(),
            ));
        }
        Ok(self.request_id)
    }
}

impl<T> DeferredCompletionFetcher for DeferredCompletionRequestBuilder<T>
where
    T: ClientConfig + Clone + Send + Sync,
{
    async fn fetch_deferred_completion(
        &self,
        request_id: &str,
    ) -> Result<Option<ChatCompletionResponse>, XaiError> {
        let url = format!("chat/deferred-completion/{}", request_id);
        let response = self.client.request(Method::GET, &url)?.send().await?;

        match response.status().as_u16() {
            200 => {
                let completion = response.json::<ChatCompletionResponse>().await?;
                Ok(Some(completion))
            }
            202 => Ok(None),
            _ => {
                let error_body = response.text().await.unwrap_or_else(|_| "".to_string());
                if let Some(model_error) = check_for_model_error(&error_body) {
                    return Err(model_error);
                }
                Err(XaiError::Http(error_body))
            }
        }
    }
}
// Copyright 2026 Mahmoud Harmouch.
//
// Licensed under the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.