portkey_sdk/service/
responses.rs

1use std::future::Future;
2
3#[cfg(feature = "tracing")]
4use crate::TRACING_TARGET_SERVICE;
5use crate::client::PortkeyClient;
6use crate::error::Result;
7use crate::model::{CreateResponseRequest, ListInputItemsParams, ListInputItemsResponse, Response};
8
9/// Service trait for managing responses in Portkey.
10///
11/// This trait provides methods for creating, retrieving, listing, and deleting
12/// responses, as well as managing input items associated with responses.
13///
14/// # Example
15///
16/// ```rust,no_run
17/// use portkey_sdk::{PortkeyConfig, Result};
18/// use portkey_sdk::service::ResponsesService;
19/// use portkey_sdk::builder::AuthMethod;
20/// use portkey_sdk::model::CreateResponseRequest;
21///
22/// #[tokio::main]
23/// async fn main() -> Result<()> {
24///     let client = PortkeyConfig::builder()
25///         .with_api_key("your-portkey-api-key")
26///         .with_auth_method(AuthMethod::virtual_key("your-virtual-key"))
27///         .build_client()?;
28///
29///     // Create a new response
30///     let request = CreateResponseRequest {
31///         trace_id: Some("trace-123".to_string()),
32///         model: Some("gpt-4".to_string()),
33///         provider: Some("openai".to_string()),
34///         status: Some("success".to_string()),
35///         total_tokens: Some(150),
36///         prompt_tokens: Some(100),
37///         completion_tokens: Some(50),
38///         latency_ms: Some(1500),
39///         cost: Some(0.003),
40///         metadata: None,
41///         request: None,
42///         response: None,
43///     };
44///
45///     let response = client.create_response(request).await?;
46///     println!("Created response: {}", response.id);
47///
48///     // Get the response
49///     let fetched = client.get_response(&response.id).await?;
50///     println!("Fetched response: {:?}", fetched);
51///
52///     // List input items for the response
53///     let params = portkey_sdk::model::ListInputItemsParams {
54///         limit: Some(50),
55///         offset: Some(0),
56///     };
57///     let input_items = client.list_input_items(&response.id, params).await?;
58///     println!("Found {} input items", input_items.data.len());
59///
60///     // Delete the response
61///     client.delete_response(&response.id).await?;
62///     println!("Deleted response");
63///
64///     Ok(())
65/// }
66/// ```
67pub trait ResponsesService {
68    /// Creates a new response.
69    ///
70    /// # Arguments
71    ///
72    /// * `request` - The response data to create
73    ///
74    /// # Returns
75    ///
76    /// Returns the created `Response` object with its assigned ID and metadata.
77    ///
78    /// # Errors
79    ///
80    /// Returns an error if the API request fails or the response cannot be parsed.
81    fn create_response(
82        &self,
83        request: CreateResponseRequest,
84    ) -> impl Future<Output = Result<Response>>;
85
86    /// Retrieves a specific response by ID.
87    ///
88    /// # Arguments
89    ///
90    /// * `response_id` - The unique identifier of the response to retrieve
91    ///
92    /// # Returns
93    ///
94    /// Returns the `Response` object if found.
95    ///
96    /// # Errors
97    ///
98    /// Returns an error if the response is not found or the API request fails.
99    fn get_response(&self, response_id: &str) -> impl Future<Output = Result<Response>>;
100
101    /// Deletes a response.
102    ///
103    /// # Arguments
104    ///
105    /// * `response_id` - The unique identifier of the response to delete
106    ///
107    /// # Returns
108    ///
109    /// Returns `Ok(())` if the response was successfully deleted.
110    ///
111    /// # Errors
112    ///
113    /// Returns an error if the response is not found or the deletion fails.
114    fn delete_response(&self, response_id: &str) -> impl Future<Output = Result<()>>;
115
116    /// Lists input items for a specific response.
117    ///
118    /// # Arguments
119    ///
120    /// * `response_id` - The unique identifier of the response
121    /// * `params` - Pagination parameters (limit and offset)
122    ///
123    /// # Returns
124    ///
125    /// Returns a `ListInputItemsResponse` containing the input items and pagination info.
126    ///
127    /// # Errors
128    ///
129    /// Returns an error if the response is not found or the API request fails.
130    fn list_input_items(
131        &self,
132        response_id: &str,
133        params: ListInputItemsParams,
134    ) -> impl Future<Output = Result<ListInputItemsResponse>>;
135}
136
137impl ResponsesService for PortkeyClient {
138    async fn create_response(&self, request: CreateResponseRequest) -> Result<Response> {
139        #[cfg(feature = "tracing")]
140        tracing::debug!(
141            target: TRACING_TARGET_SERVICE,
142            trace_id = ?request.trace_id,
143            model = ?request.model,
144            "Creating response"
145        );
146
147        let response = self
148            .send_json(reqwest::Method::POST, "/responses", &request)
149            .await?;
150        let response = response.error_for_status()?;
151        let response_data: Response = response.json().await?;
152
153        Ok(response_data)
154    }
155
156    async fn get_response(&self, response_id: &str) -> Result<Response> {
157        #[cfg(feature = "tracing")]
158        tracing::debug!(
159            target: TRACING_TARGET_SERVICE,
160            response_id = %response_id,
161            "Getting response"
162        );
163
164        let path = format!("/responses/{}", response_id);
165        let response = self.send(reqwest::Method::GET, &path).await?;
166        let response = response.error_for_status()?;
167        let response_data: Response = response.json().await?;
168
169        Ok(response_data)
170    }
171
172    async fn delete_response(&self, response_id: &str) -> Result<()> {
173        #[cfg(feature = "tracing")]
174        tracing::debug!(
175            target: TRACING_TARGET_SERVICE,
176            response_id = %response_id,
177            "Deleting response"
178        );
179
180        let path = format!("/responses/{}", response_id);
181        let response = self.send(reqwest::Method::DELETE, &path).await?;
182        response.error_for_status()?;
183
184        Ok(())
185    }
186
187    async fn list_input_items(
188        &self,
189        response_id: &str,
190        params: ListInputItemsParams,
191    ) -> Result<ListInputItemsResponse> {
192        #[cfg(feature = "tracing")]
193        tracing::debug!(
194            target: TRACING_TARGET_SERVICE,
195            response_id = %response_id,
196            limit = ?params.limit,
197            offset = ?params.offset,
198            "Listing input items"
199        );
200
201        let path = format!("/responses/{}/input_items", response_id);
202        let mut request = self.request_builder(reqwest::Method::GET, &path)?;
203
204        // Add query parameters if specified
205        if let Some(limit) = params.limit {
206            request = request.query(&[("limit", limit.to_string())]);
207        }
208        if let Some(offset) = params.offset {
209            request = request.query(&[("offset", offset.to_string())]);
210        }
211
212        let response = request.send().await?;
213        let response = response.error_for_status()?;
214        let input_items: ListInputItemsResponse = response.json().await?;
215
216        Ok(input_items)
217    }
218}