use std::cell::RefCell;
use std::collections::HashMap;
use std::error::Error;
use std::rc::Rc;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::resource::{APIResource};
use crate::core::{self, APIClient, FinalRequestOptions, Headers, RequestOptions};
use crate::resources::beta::assistants as assistants_api;
use crate::pagination::{CursorPage, CursorPageResponse, Page};
use crate::resources::chat::ChatCompletionContentPart;
#[derive(Debug, Clone)]
pub struct Messages {
pub client: Option<APIResource>,
}
impl Messages {
pub fn new() -> Self {
Messages {
client: None,
}
}
pub async fn create(
&self,
thread_id: &str,
body: MessageCreateParams,
options: Option<RequestOptions<MessageCreateParams>>,
) -> Result<Message, Box<dyn Error>> {
let mut headers: Headers = HashMap::new();
headers.insert("OpenAI-Beta".to_string(), Some("assistants=v2".to_string()));
if let Some(opts) = &options {
if let Some(hdrs) = &opts.headers {
for (key, value) in hdrs {
headers.insert(key.to_owned(), value.to_owned());
}
}
}
self.client.as_ref().unwrap().borrow().post(
&format!("/threads/{thread_id}/messages"),
Some(RequestOptions {
body: Some(body),
headers: Some(headers),
..options.unwrap_or_default()
}),
).await
}
pub async fn retrieve(
&self,
thread_id: &str,
message_id: &str,
_options: Option<core::RequestOptions<()>>,
) -> Result<Message, Box<dyn Error>> {
self.client.as_ref().unwrap().borrow().post(
&format!("/threads/{thread_id}/messages/{message_id}"),
Some(core::RequestOptions::<()> {
..Default::default()
}),
).await
}
pub async fn update(
&self,
thread_id: &str,
message_id: &str,
body: MessageUpdateParams,
_options: Option<core::RequestOptions<MessageUpdateParams>>,
) -> Result<Message, Box<dyn Error>> {
self.client.as_ref().unwrap().borrow().post(
&format!("/threads/{thread_id}/messages/{message_id}"),
Some(core::RequestOptions {
body: Some(body),
..Default::default()
}),
).await
}
pub async fn list(
&self,
thread_id: &str,
query: Option<MessageListParams>,
_options: Option<RequestOptions<MessageListParams>>,
) -> Result<CursorPage<MessageListParams, Message>, Box<dyn Error>> {
let mut headers: Headers = HashMap::new();
headers.insert("OpenAI-Beta".to_string(), Some("assistants=v2".to_string()));
let page_constructor = |
client: Rc<RefCell<APIClient>>,
body: CursorPageResponse<Message>,
options: FinalRequestOptions<MessageListParams>,
| {
CursorPage::new(client, body, options)
};
self.client.as_ref().unwrap().borrow().get_api_list(
&format!("/threads/{thread_id}/messages"),
page_constructor,
Some(RequestOptions {
query: query,
headers: Some(headers),
..Default::default()
}),
).await
}
pub async fn del(
&self,
thread_id: &str,
message_id: &str,
options: Option<core::RequestOptions>,
) -> Result<MessageDeleted, Box<dyn Error>> {
let mut headers: Headers = HashMap::new();
headers.insert("OpenAI-Beta".to_string(), Some("assistants=v2".to_string()));
if let Some(opts) = options {
if let Some(hdrs) = opts.headers {
for (key, value) in hdrs {
headers.insert(key, value);
}
}
}
self.client.as_ref().unwrap().borrow().delete(
&format!("/threads/{thread_id}/messages/{message_id}"),
Some(core::RequestOptions::<()> {
headers: Some(headers),
..Default::default()
}),
).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Annotation {
FileCitationAnnotation(FileCitationAnnotation),
FilePathAnnotation(FilePathAnnotation),
}
impl Default for Annotation {
fn default() -> Self {
Annotation::FilePathAnnotation(FilePathAnnotation::default())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum AnnotationDelta {
FileCitationDeltaAnnotation(FileCitationDeltaAnnotation),
FilePathDeltaAnnotation(FilePathDeltaAnnotation),
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FileCitationAnnotation {
pub end_index: u32,
pub file_citation: file_citation_annotation::FileCitation,
pub start_index: u32,
pub text: String,
#[serde(rename = "type")]
pub file_citation_annotation_type: file_citation_annotation::Type,
}
pub mod file_citation_annotation {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FileCitation {
pub file_id: String,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FileCitation,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FileCitationDeltaAnnotation {
pub index: u32,
#[serde(rename = "type")]
pub kind: file_citation_delta_annotation::Type,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_index: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_citation: Option<file_citation_delta_annotation::FileCitation>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_index: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
}
pub mod file_citation_delta_annotation {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FileCitation {
#[serde(skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quote: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FileCitation,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FilePathAnnotation {
pub end_index: u32,
pub file_path: file_path_annotation::FilePath,
pub start_index: u32,
pub text: String,
#[serde(rename = "type")]
pub kind: file_path_annotation::Type,
}
pub mod file_path_annotation {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FilePath {
pub file_id: String,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FilePath,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FilePathDeltaAnnotation {
pub index: u32,
#[serde(rename = "type")]
pub kind: file_path_delta_annotation::Type,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_index: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_path: Option<file_path_delta_annotation::FilePath>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_index: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
}
pub mod file_path_delta_annotation {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FilePath {
#[serde(skip_serializing_if = "Option::is_none")]
file_id: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FilePath,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageFile {
pub file_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<Detail>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageFileDelta {
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<Detail>,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageFileDeltaBlock {
pub index: u32,
#[serde(rename = "type")]
pub kind: image_file_delta_block::Type,
#[serde(skip_serializing_if = "Option::is_none")]
pub image_file: Option<ImageFileDelta>,
}
pub mod image_file_delta_block {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
ImageFile,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageURL {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<Detail>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageURLDelta {
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<Detail>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ImageURLDeltaBlock {
pub index: u32,
#[serde(rename = "type")]
pub kind: image_url_delta_block::Type,
#[serde(skip_serializing_if = "Option::is_none")]
pub image_url: Option<ImageURLDelta>,
}
pub mod image_url_delta_block {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
ImageUrl,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub id: String,
pub assistant_id: Option<String>,
pub attachments: Option<Vec<message::Attachment>>,
pub completed_at: Option<u64>,
pub content: Vec<MessageContent>,
pub created_at: u64,
pub incomplete_at: Option<u64>,
pub incomplete_details: Option<message::IncompleteDetails>,
pub metadata: Option<Value>,
pub object: message::Object,
pub role: message::Role,
pub run_id: Option<String>,
pub status: Option<message::Status>,
pub thread_id: String,
}
pub mod message {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Attachment {
#[serde(skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<attachment::Tool>>,
}
pub mod attachment {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct AssistantToolsFileSearchTypeOnly {
#[serde(rename = "type")]
pub kind: assistant_tools_file_search_type_only::Type,
}
pub mod assistant_tools_file_search_type_only {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FileSearch,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Tool {
CodeInterpreterTool(assistants_api::CodeInterpreterTool),
AssistantToolsFileSearchTypeOnly(AssistantToolsFileSearchTypeOnly),
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct IncompleteDetails {
pub reason: incomplete_details::Reason,
}
pub mod incomplete_details {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Reason {
#[default]
ContentFilter,
MaxTokens,
RunCancelled,
RunExpired,
RunFailed,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Role {
#[default]
User,
Assistant,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub enum Object {
#[default]
#[serde(rename = "thread.message")]
ThreadMessage,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Status {
#[default]
InProgress,
Incomplete,
Complete,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MessageContent {
ImageFile(ImageFile),
ImageURL(ImageURL),
Text{ text: Text },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ChatCompletionContent {
Text(String),
Multiple(Vec<ChatCompletionContentPart>),
}
impl Default for MessageContent {
fn default() -> Self {
MessageContent::Text{ text: Text::default() }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum MessageContentDelta {
ImageFileDeltaBlock(ImageFileDeltaBlock),
TextDeltaBlock(TextDeltaBlock),
ImageURLDeltaBlock(ImageURLDeltaBlock),
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageDeleted {
pub id: String,
pub deleted: bool,
pub object: message_deleted::Object,
}
pub mod message_deleted {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Object {
#[serde(rename = "thread.message.deleted")]
#[default]
ThreadMessageDeleted
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageDelta {
#[serde(skip_serializing_if = "Option::is_none")]
content: Option<Vec<MessageContentDelta>>,
#[serde(skip_serializing_if = "Option::is_none")]
role: Option<message_deleted::Object>,
}
pub mod message_delta {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Role {
#[default]
User,
Assistant,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageDeltaEvent {
pub id: String,
pub delta: MessageDelta,
pub object: message_delta_event::Object,
}
pub mod message_delta_event {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Object {
#[serde(rename = "thread.message.delta")]
#[default]
ThreadMessageDelta
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Text {
pub annotations: Vec<Annotation>,
pub value: String,
}
pub mod text_content_block {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
Text,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct TextContentBlockParam {
pub text: String,
#[serde(rename = "type")]
pub kind: text_content_block_param::Type,
}
pub mod text_content_block_param {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
Text,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct TextDelta {
#[serde(skip_serializing_if = "Option::is_none")]
annotations: Option<Vec<AnnotationDelta>>,
#[serde(skip_serializing_if = "Option::is_none")]
value: Option<String>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct TextDeltaBlock {
pub index: u32,
#[serde(rename = "type")]
pub kind: text_delta_block::Type,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<TextDelta>,
}
pub mod text_delta_block {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
Text,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageCreateParams {
pub content: message_create_params::Content,
pub role: message_create_params::Role,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachments: Option<Vec<message_create_params::Attachment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Value>,
}
pub mod message_create_params {
use super::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Content {
Text(String),
Multiple(Vec<MessageContent>),
}
impl Default for Content {
fn default() -> Self {
Content::Text(String::default())
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Role {
#[default]
User,
Assistant,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Attachment {
#[serde(skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<attachment::Tool>>,
}
pub mod attachment {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FileSearch {
#[serde(rename = "type")]
pub kind: file_search::Type,
}
pub mod file_search {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
#[default]
FileSearch,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Tool {
CodeInterpreterTool(assistants_api::CodeInterpreterTool),
FileSearch(FileSearch),
}
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageUpdateParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Value>,
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MessageListParams { #[serde(skip_serializing_if = "Option::is_none")]
pub before: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub order: Option<message_list_params::Order>,
#[serde(skip_serializing_if = "Option::is_none")]
pub run_id: Option<String>,
}
pub mod message_list_params {
use super::*;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Order {
#[default]
Asc,
Desc,
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[serde(untagged, rename_all = "snake_case")]
pub enum Detail {
#[default]
Auto,
Low,
High,
}