From 8458bd2121ffcb25d5be2b8aaec303210498f9e0 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Mon, 2 Sep 2024 23:56:27 -0400 Subject: [PATCH 1/9] Implement `invites` --- async-openai/src/invites.rs | 48 +++++++++++++++++++++++ async-openai/src/lib.rs | 2 + async-openai/src/types/invites.rs | 63 +++++++++++++++++++++++++++++++ async-openai/src/types/mod.rs | 2 + 4 files changed, 115 insertions(+) create mode 100644 async-openai/src/invites.rs create mode 100644 async-openai/src/types/invites.rs diff --git a/async-openai/src/invites.rs b/async-openai/src/invites.rs new file mode 100644 index 00000000..0a94dfc5 --- /dev/null +++ b/async-openai/src/invites.rs @@ -0,0 +1,48 @@ +use serde::Serialize; + +use crate::{ + config::Config, + error::OpenAIError, + types::{Invite, InviteDeleteResponse, InviteListResponse, InviteRequest}, + Client, +}; + +/// Invite and manage invitations for an organization. Invited users are automatically added to the Default project. +pub struct Invites<'c, C: Config> { + client: &'c Client, +} + +impl<'c, C: Config> Invites<'c, C> { + pub fn new(client: &'c Client) -> Self { + Self { client } + } + + /// Returns a list of runs belonging to a thread. + pub async fn list(&self, query: &Q) -> Result + where + Q: Serialize + ?Sized, + { + self.client + .get_with_query("/organization/invites", query) + .await + } + + /// Retrieves an invite. + pub async fn retrieve(&self, invite_id: &str) -> Result { + self.client + .get(format!("/organization/invites/{}", invite_id).as_str()) + .await + } + + /// Create an invite for a user to the organization. The invite must be accepted by the user before they have access to the organization. + pub async fn create(&self, request: InviteRequest) -> Result { + self.client.post("/organization/invites", request).await + } + + /// Delete an invite. If the invite has already been accepted, it cannot be deleted. + pub async fn delete(&self, invite_id: &str) -> Result { + self.client + .delete(format!("/organization/invites/{invite_id}").as_str()) + .await + } +} diff --git a/async-openai/src/lib.rs b/async-openai/src/lib.rs index 7218ac45..2b5e1293 100644 --- a/async-openai/src/lib.rs +++ b/async-openai/src/lib.rs @@ -90,6 +90,7 @@ pub mod error; mod file; mod fine_tuning; mod image; +mod invites; mod message_files; mod messages; mod model; @@ -114,6 +115,7 @@ pub use embedding::Embeddings; pub use file::Files; pub use fine_tuning::FineTuning; pub use image::Images; +pub use invites::Invites; pub use message_files::MessageFiles; pub use messages::Messages; pub use model::Models; diff --git a/async-openai/src/types/invites.rs b/async-openai/src/types/invites.rs new file mode 100644 index 00000000..29d519c5 --- /dev/null +++ b/async-openai/src/types/invites.rs @@ -0,0 +1,63 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum InviteRole { + Owner, + Reader, +} +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum InviteStatus { + Accepted, + Expired, + Pending, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct InviteRequest { + email: String, + role: InviteRole, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct InviteListResponse { + object: String, + data: Vec, + first_id: Option, + last_id: Option, + has_more: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct InviteDeleteResponse { + /// The object type, which is always `organization.invite.deleted` + object: String, + id: String, + deleted: bool, +} + +/// Represents an individual `invite` to the organization. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct Invite { + /// The object type, which is always `organization.invite` + object: String, + /// The identifier, which can be referenced in API endpoints + id: String, + /// The email address of the individual to whom the invite was sent + email: String, + /// `owner` or `reader` + role: InviteRole, + /// `accepted`, `expired`, or `pending` + status: InviteStatus, + /// The Unix timestamp (in seconds) of when the invite was sent. + invited_at: u32, + /// The Unix timestamp (in seconds) of when the invite expires. + expires_at: u32, + /// The Unix timestamp (in seconds) of when the invite was accepted. + accepted_at: u32, +} diff --git a/async-openai/src/types/mod.rs b/async-openai/src/types/mod.rs index d3b89963..8ea222c6 100644 --- a/async-openai/src/types/mod.rs +++ b/async-openai/src/types/mod.rs @@ -13,6 +13,7 @@ mod embedding; mod file; mod fine_tuning; mod image; +mod invites; mod message; mod message_file; mod model; @@ -34,6 +35,7 @@ pub use embedding::*; pub use file::*; pub use fine_tuning::*; pub use image::*; +pub use invites::*; pub use message::*; pub use message_file::*; pub use model::*; From 99daf009d38cf0b9e6e03ff149fee7235558d581 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Tue, 3 Sep 2024 00:26:11 -0400 Subject: [PATCH 2/9] Consistently inline format --- async-openai/src/invites.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/async-openai/src/invites.rs b/async-openai/src/invites.rs index 0a94dfc5..ebfd7fba 100644 --- a/async-openai/src/invites.rs +++ b/async-openai/src/invites.rs @@ -30,7 +30,7 @@ impl<'c, C: Config> Invites<'c, C> { /// Retrieves an invite. pub async fn retrieve(&self, invite_id: &str) -> Result { self.client - .get(format!("/organization/invites/{}", invite_id).as_str()) + .get(format!("/organization/invites/{invite_id}").as_str()) .await } From 575af4ea24af87e0dbe9c3fd9af4c550856c81b3 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Tue, 3 Sep 2024 13:46:19 -0400 Subject: [PATCH 3/9] Implement `users` --- async-openai/src/lib.rs | 2 ++ async-openai/src/types/common.rs | 8 +++++ async-openai/src/types/mod.rs | 2 ++ async-openai/src/types/users.rs | 48 ++++++++++++++++++++++++++++ async-openai/src/users.rs | 54 ++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 async-openai/src/types/users.rs create mode 100644 async-openai/src/users.rs diff --git a/async-openai/src/lib.rs b/async-openai/src/lib.rs index 2b5e1293..9761508e 100644 --- a/async-openai/src/lib.rs +++ b/async-openai/src/lib.rs @@ -99,6 +99,7 @@ mod runs; mod steps; mod threads; pub mod types; +mod users; mod util; mod vector_store_file_batches; mod vector_store_files; @@ -123,6 +124,7 @@ pub use moderation::Moderations; pub use runs::Runs; pub use steps::Steps; pub use threads::Threads; +pub use users::Users; pub use vector_store_file_batches::VectorStoreFileBatches; pub use vector_store_files::VectorStoreFiles; pub use vector_stores::VectorStores; diff --git a/async-openai/src/types/common.rs b/async-openai/src/types/common.rs index ee7f9d95..be149902 100644 --- a/async-openai/src/types/common.rs +++ b/async-openai/src/types/common.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use bytes::Bytes; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq)] pub enum InputSource { @@ -8,3 +9,10 @@ pub enum InputSource { Bytes { filename: String, bytes: Bytes }, VecU8 { filename: String, vec: Vec }, } + +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum OrganizationRole { + Owner, + Reader, +} diff --git a/async-openai/src/types/mod.rs b/async-openai/src/types/mod.rs index 8ea222c6..ce20fa62 100644 --- a/async-openai/src/types/mod.rs +++ b/async-openai/src/types/mod.rs @@ -21,6 +21,7 @@ mod moderation; mod run; mod step; mod thread; +mod users; mod vector_store; pub use assistant::*; @@ -43,6 +44,7 @@ pub use moderation::*; pub use run::*; pub use step::*; pub use thread::*; +pub use users::*; pub use vector_store::*; mod impls; diff --git a/async-openai/src/types/users.rs b/async-openai/src/types/users.rs new file mode 100644 index 00000000..fc6c2864 --- /dev/null +++ b/async-openai/src/types/users.rs @@ -0,0 +1,48 @@ +use serde::{Deserialize, Serialize}; + +use super::OrganizationRole; + +/// Represents an individual `user` within an organization. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct User { + /// The object type, which is always `organization.user` + object: String, + /// The identifier, which can be referenced in API endpoints + id: String, + /// The name of the user + name: String, + /// The email address of the user + email: String, + /// `owner` or `reader` + role: OrganizationRole, + /// The Unix timestamp (in seconds) of when the users was added. + added_at: u32, +} + +/// A list of `User` objects. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct UserListResponse { + object: String, + data: Vec, + first_id: String, + last_id: String, + has_more: bool, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct UserRoleUpdateRequest { + /// `owner` or `reader` + role: OrganizationRole, +} + +/// Confirmation of the deleted user +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct UserDeleteResponse { + object: String, + id: String, + deleted: bool, +} diff --git a/async-openai/src/users.rs b/async-openai/src/users.rs new file mode 100644 index 00000000..ebda27a8 --- /dev/null +++ b/async-openai/src/users.rs @@ -0,0 +1,54 @@ +use serde::Serialize; + +use crate::{ + config::Config, + error::OpenAIError, + types::{User, UserDeleteResponse, UserListResponse, UserRoleUpdateRequest}, + Client, +}; + +/// Manage users and their role in an organization. Users will be automatically added to the Default project. +pub struct Users<'c, C: Config> { + client: &'c Client, +} + +impl<'c, C: Config> Users<'c, C> { + pub fn new(client: &'c Client) -> Self { + Self { client } + } + + /// Lists all of the users in the organization. + pub async fn list(&self, query: &Q) -> Result + where + Q: Serialize + ?Sized, + { + self.client + .get_with_query("/organization/users", query) + .await + } + + /// Modifies a user's role in the organization. + pub async fn modify( + &self, + user_id: &str, + request: UserRoleUpdateRequest, + ) -> Result { + self.client + .post(format!("/organization/users/{user_id}").as_str(), request) + .await + } + + /// Retrieve a user by their identifier + pub async fn retrieve(&self, user_id: &str) -> Result { + self.client + .get(format!("/organization/users/{user_id}").as_str()) + .await + } + + /// Deletes a user from the organization. + pub async fn delete(&self, user_id: &str) -> Result { + self.client + .delete(format!("/organizations/users/{user_id}").as_str()) + .await + } +} From 386fc2d178fd9d0e7a9cb9c494efdf5ea30d72b5 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Tue, 3 Sep 2024 13:48:55 -0400 Subject: [PATCH 4/9] Replace `InviteRole` with generic `OrganizationRole` --- async-openai/src/types/invites.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/async-openai/src/types/invites.rs b/async-openai/src/types/invites.rs index 29d519c5..f85c1ca2 100644 --- a/async-openai/src/types/invites.rs +++ b/async-openai/src/types/invites.rs @@ -1,11 +1,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] -#[serde(rename_all = "snake_case")] -pub enum InviteRole { - Owner, - Reader, -} +use super::OrganizationRole; + #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] #[serde(rename_all = "snake_case")] pub enum InviteStatus { @@ -18,7 +14,7 @@ pub enum InviteStatus { #[serde(rename_all = "snake_case")] pub struct InviteRequest { email: String, - role: InviteRole, + role: OrganizationRole, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] @@ -51,7 +47,7 @@ pub struct Invite { /// The email address of the individual to whom the invite was sent email: String, /// `owner` or `reader` - role: InviteRole, + role: OrganizationRole, /// `accepted`, `expired`, or `pending` status: InviteStatus, /// The Unix timestamp (in seconds) of when the invite was sent. From 883d6c656ba9c250f4c4918c8cebdd201dd84693 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Sat, 7 Sep 2024 20:16:54 -0400 Subject: [PATCH 5/9] Implement `projects` --- async-openai/src/lib.rs | 2 + async-openai/src/projects.rs | 63 ++++++++++++++++++++++++++++ async-openai/src/types/mod.rs | 2 + async-openai/src/types/projects.rs | 66 ++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 async-openai/src/projects.rs create mode 100644 async-openai/src/types/projects.rs diff --git a/async-openai/src/lib.rs b/async-openai/src/lib.rs index 9761508e..816cfb6d 100644 --- a/async-openai/src/lib.rs +++ b/async-openai/src/lib.rs @@ -95,6 +95,7 @@ mod message_files; mod messages; mod model; mod moderation; +mod projects; mod runs; mod steps; mod threads; @@ -121,6 +122,7 @@ pub use message_files::MessageFiles; pub use messages::Messages; pub use model::Models; pub use moderation::Moderations; +pub use projects::Projects; pub use runs::Runs; pub use steps::Steps; pub use threads::Threads; diff --git a/async-openai/src/projects.rs b/async-openai/src/projects.rs new file mode 100644 index 00000000..077c1d79 --- /dev/null +++ b/async-openai/src/projects.rs @@ -0,0 +1,63 @@ +use serde::Serialize; + +use crate::{ + config::Config, + error::OpenAIError, + types::{Project, ProjectCreateRequest, ProjectListResponse, ProjectUpdateRequest}, + Client, +}; + +/// Manage the projects within an organization includes creation, updating, and archiving or projects. +/// The Default project cannot be modified or archived. +pub struct Projects<'c, C: Config> { + client: &'c Client, +} + +impl<'c, C: Config> Projects<'c, C> { + pub fn new(client: &'c Client) -> Self { + Self { client } + } + + /// Returns a list of projects. + pub async fn list(&self, query: &Q) -> Result + where + Q: Serialize + ?Sized, + { + self.client + .get_with_query("/organization/projects", query) + .await + } + + /// Create a new project in the organization. Projects can be created and archived, but cannot be deleted. + pub async fn create(&self, request: ProjectCreateRequest) -> Result { + self.client.post("/organization/projects", request).await + } + + /// Retrieves a project. + pub async fn retrieve(&self, project_id: String) -> Result { + self.client + .get(format!("/organization/projects/{project_id}").as_str()) + .await + } + + /// Modifies a project in the organization. + pub async fn modify( + &self, + project_id: String, + request: ProjectUpdateRequest, + ) -> Result { + self.client + .post( + format!("/organization/projects/{project_id}").as_str(), + request, + ) + .await + } + + /// Archives a project in the organization. Archived projects cannot be used or updated. + pub async fn archive(&self, project_id: String) -> Result { + self.client + .post(format!("/organization/projects/{project_id}").as_str(), ()) + .await + } +} diff --git a/async-openai/src/types/mod.rs b/async-openai/src/types/mod.rs index ce20fa62..551c8ddc 100644 --- a/async-openai/src/types/mod.rs +++ b/async-openai/src/types/mod.rs @@ -18,6 +18,7 @@ mod message; mod message_file; mod model; mod moderation; +mod projects; mod run; mod step; mod thread; @@ -41,6 +42,7 @@ pub use message::*; pub use message_file::*; pub use model::*; pub use moderation::*; +pub use projects::*; pub use run::*; pub use step::*; pub use thread::*; diff --git a/async-openai/src/types/projects.rs b/async-openai/src/types/projects.rs new file mode 100644 index 00000000..5b22f524 --- /dev/null +++ b/async-openai/src/types/projects.rs @@ -0,0 +1,66 @@ +use crate::types::OpenAIError; +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +/// `active` or `archived` +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum ProjectStatus { + Active, + Archived, +} + +/// Represents an individual project. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct Project { + /// The identifier, which can be referenced in API endpoints + id: String, + /// The object type, which is always `organization.project` + object: String, + /// The name of the project. This appears in reporting. + name: String, + /// The Unix timestamp (in seconds) of when the project was created. + created_at: u32, + /// The Unix timestamp (in seconds) of when the project was archived or `null`. + archived_at: Option, + /// `active` or `archived` + status: ProjectStatus, +} + +/// A list of Project objects. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct ProjectListResponse { + object: String, + data: Vec, + first_id: String, + last_id: String, + has_more: String, +} + +/// The project create request payload. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder, Default)] +#[builder(name = "ProjectCreateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option), default)] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] +#[serde(rename_all = "snake_case")] +pub struct ProjectCreateRequest { + /// The friendly name of the project, this name appears in reports. + name: String, +} + +/// The project update request payload. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder, Default)] +#[builder(name = "ProjectUpdateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option), default)] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] +#[serde(rename_all = "snake_case")] +pub struct ProjectUpdateRequest { + /// The updated name of the project, this name appears in reports. + name: String, +} From 9757043fff2692d22d1f3e571b02cee08ba04fe8 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Sat, 7 Sep 2024 20:21:32 -0400 Subject: [PATCH 6/9] Update requests to use builder --- async-openai/src/types/invites.rs | 9 ++++++++- async-openai/src/types/users.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/async-openai/src/types/invites.rs b/async-openai/src/types/invites.rs index f85c1ca2..cb60a301 100644 --- a/async-openai/src/types/invites.rs +++ b/async-openai/src/types/invites.rs @@ -1,3 +1,5 @@ +use crate::types::OpenAIError; +use derive_builder::Builder; use serde::{Deserialize, Serialize}; use super::OrganizationRole; @@ -10,7 +12,12 @@ pub enum InviteStatus { Pending, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] +#[builder(name = "ProjectCreateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option))] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] #[serde(rename_all = "snake_case")] pub struct InviteRequest { email: String, diff --git a/async-openai/src/types/users.rs b/async-openai/src/types/users.rs index fc6c2864..ad06a4c9 100644 --- a/async-openai/src/types/users.rs +++ b/async-openai/src/types/users.rs @@ -1,3 +1,5 @@ +use crate::types::OpenAIError; +use derive_builder::Builder; use serde::{Deserialize, Serialize}; use super::OrganizationRole; @@ -31,7 +33,12 @@ pub struct UserListResponse { has_more: bool, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] +#[builder(name = "ProjectCreateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option))] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] #[serde(rename_all = "snake_case")] pub struct UserRoleUpdateRequest { /// `owner` or `reader` From cd57b371e3b9c42b16837441fcb6b7ee9db92941 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Sat, 7 Sep 2024 20:21:56 -0400 Subject: [PATCH 7/9] Remove `default` from builder --- async-openai/src/types/projects.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/async-openai/src/types/projects.rs b/async-openai/src/types/projects.rs index 5b22f524..1dd545e2 100644 --- a/async-openai/src/types/projects.rs +++ b/async-openai/src/types/projects.rs @@ -40,10 +40,10 @@ pub struct ProjectListResponse { } /// The project create request payload. -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] #[builder(name = "ProjectCreateRequestArgs")] #[builder(pattern = "mutable")] -#[builder(setter(into, strip_option), default)] +#[builder(setter(into, strip_option))] #[builder(derive(Debug))] #[builder(build_fn(error = "OpenAIError"))] #[serde(rename_all = "snake_case")] @@ -53,10 +53,10 @@ pub struct ProjectCreateRequest { } /// The project update request payload. -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] #[builder(name = "ProjectUpdateRequestArgs")] #[builder(pattern = "mutable")] -#[builder(setter(into, strip_option), default)] +#[builder(setter(into, strip_option))] #[builder(derive(Debug))] #[builder(build_fn(error = "OpenAIError"))] #[serde(rename_all = "snake_case")] From 77b7f0a3e9185a915e0843f531d33204af9559d8 Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Mon, 16 Sep 2024 19:23:01 -0400 Subject: [PATCH 8/9] Update `projects` to include verification information (https://help.openai.com/en/articles/9824607-api-platform-verifications) --- async-openai/src/types/projects.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/async-openai/src/types/projects.rs b/async-openai/src/types/projects.rs index 1dd545e2..a7e5af87 100644 --- a/async-openai/src/types/projects.rs +++ b/async-openai/src/types/projects.rs @@ -26,6 +26,10 @@ pub struct Project { archived_at: Option, /// `active` or `archived` status: ProjectStatus, + /// A description of your business, project, or use case. + app_use_case: String, + /// Your business URL, or if you don't have one yet, a URL to your LinkedIn or other social media. + business_website: String, } /// A list of Project objects. @@ -50,6 +54,10 @@ pub struct ProjectListResponse { pub struct ProjectCreateRequest { /// The friendly name of the project, this name appears in reports. name: String, + /// A description of your business, project, or use case. + app_use_case: Option, + /// Your business URL, or if you don't have one yet, a URL to your LinkedIn or other social media. + business_website: Option, } /// The project update request payload. @@ -63,4 +71,8 @@ pub struct ProjectCreateRequest { pub struct ProjectUpdateRequest { /// The updated name of the project, this name appears in reports. name: String, + /// A description of your business, project, or use case. + app_use_case: Option, + /// Your business URL, or if you don't have one yet, a URL to your LinkedIn or other social media. + business_website: Option, } From f204abaf8fc858481f4ade70a19e9580d695a12b Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Mon, 16 Sep 2024 20:35:54 -0400 Subject: [PATCH 9/9] Implement `project_users` --- async-openai/src/lib.rs | 2 + async-openai/src/project_users.rs | 89 +++++++++++++++++++++++++ async-openai/src/types/mod.rs | 2 + async-openai/src/types/project_users.rs | 74 ++++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 async-openai/src/project_users.rs create mode 100644 async-openai/src/types/project_users.rs diff --git a/async-openai/src/lib.rs b/async-openai/src/lib.rs index 816cfb6d..4ab3dc96 100644 --- a/async-openai/src/lib.rs +++ b/async-openai/src/lib.rs @@ -95,6 +95,7 @@ mod message_files; mod messages; mod model; mod moderation; +mod project_users; mod projects; mod runs; mod steps; @@ -122,6 +123,7 @@ pub use message_files::MessageFiles; pub use messages::Messages; pub use model::Models; pub use moderation::Moderations; +pub use project_users::ProjectUsers; pub use projects::Projects; pub use runs::Runs; pub use steps::Steps; diff --git a/async-openai/src/project_users.rs b/async-openai/src/project_users.rs new file mode 100644 index 00000000..b3f4752f --- /dev/null +++ b/async-openai/src/project_users.rs @@ -0,0 +1,89 @@ +use serde::Serialize; + +use crate::{ + config::Config, + error::OpenAIError, + types::{ + ProjectUser, ProjectUserCreateRequest, ProjectUserListResponse, ProjectUserUpdateRequest, + }, + Client, +}; + +/// Manage users within a project, including adding, updating roles, and removing users. +/// Users cannot be removed from the Default project, unless they are being removed from the organization. +pub struct ProjectUsers<'c, C: Config> { + client: &'c Client, +} + +impl<'c, C: Config> ProjectUsers<'c, C> { + pub fn new(client: &'c Client) -> Self { + Self { client } + } + + /// Returns a list of users in the project. + pub async fn list( + &self, + project_id: String, + query: &Q, + ) -> Result + where + Q: Serialize + ?Sized, + { + self.client + .get_with_query( + format!("/organization/projects/{project_id}/users").as_str(), + query, + ) + .await + } + + /// Adds a user to the project. Users must already be members of the organization to be added to a project. + pub async fn create( + &self, + project_id: String, + request: ProjectUserCreateRequest, + ) -> Result { + self.client + .post( + format!("/organization/projects/{project_id}/users").as_str(), + request, + ) + .await + } + + /// Retrieves a user in the project. + pub async fn retrieve( + &self, + project_id: String, + user_id: String, + ) -> Result { + self.client + .get(format!("/organization/projects/{project_id}/users/{user_id}").as_str()) + .await + } + + /// Modifies a user's role in the project. + pub async fn modify( + &self, + project_id: String, + request: ProjectUserUpdateRequest, + ) -> Result { + self.client + .post( + format!("/organization/projects/{project_id}").as_str(), + request, + ) + .await + } + + /// Deletes a user from the project. + pub async fn delete( + &self, + project_id: String, + user_id: String, + ) -> Result { + self.client + .delete(format!("/organization/projects/{project_id}/users/{user_id}").as_str()) + .await + } +} diff --git a/async-openai/src/types/mod.rs b/async-openai/src/types/mod.rs index 551c8ddc..73616174 100644 --- a/async-openai/src/types/mod.rs +++ b/async-openai/src/types/mod.rs @@ -18,6 +18,7 @@ mod message; mod message_file; mod model; mod moderation; +mod project_users; mod projects; mod run; mod step; @@ -42,6 +43,7 @@ pub use message::*; pub use message_file::*; pub use model::*; pub use moderation::*; +pub use project_users::*; pub use projects::*; pub use run::*; pub use step::*; diff --git a/async-openai/src/types/project_users.rs b/async-openai/src/types/project_users.rs new file mode 100644 index 00000000..5a415d68 --- /dev/null +++ b/async-openai/src/types/project_users.rs @@ -0,0 +1,74 @@ +use crate::types::OpenAIError; +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +/// Represents an individual user in a project. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct ProjectUser { + /// The object type, which is always `organization.project.user` + object: String, + /// The identifier, which can be referenced in API endpoints + id: String, + /// The name of the project + name: String, + /// The email address of the user + email: String, + /// `owner` or `member` + role: ProjectUserRole, + /// The Unix timestamp (in seconds) of when the project was added. + added_at: u32, +} + +/// `owner` or `member` +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum ProjectUserRole { + Owner, + Member, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct ProjectUserListResponse { + object: String, + data: Vec, + first_id: String, + last_id: String, + has_more: String, +} + +/// The project user create request payload. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] +#[builder(name = "ProjectUserCreateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option))] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] +#[serde(rename_all = "snake_case")] +pub struct ProjectUserCreateRequest { + /// The ID of the user. + user_id: String, + /// `owner` or `member` + role: ProjectUserRole, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)] +#[builder(name = "ProjectUserUpdateRequestArgs")] +#[builder(pattern = "mutable")] +#[builder(setter(into, strip_option))] +#[builder(derive(Debug))] +#[builder(build_fn(error = "OpenAIError"))] +#[serde(rename_all = "snake_case")] +pub struct ProjectUserUpdateRequest { + /// `owner` or `member` + role: ProjectUserRole, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct ProjectUserDeleteResponse { + object: String, + id: String, + deleted: bool, +}