openai_ergonomic/responses/
mod.rs

1//! Response type wrappers and ergonomic helpers.
2//!
3//! This module provides ergonomic wrappers around `OpenAI` API responses with
4//! convenient methods for common operations. The responses-first approach
5//! makes it easy to work with structured outputs and tool calling.
6//!
7//! # Example
8//!
9//! ```rust,ignore
10//! # use openai_ergonomic::responses::*;
11//! // TODO: Add example once responses are implemented
12//! ```
13
14use serde::{Deserialize, Serialize};
15
16pub mod assistants;
17pub mod audio;
18pub mod batch;
19pub mod chat;
20pub mod embeddings;
21pub mod files;
22pub mod fine_tuning;
23pub mod images;
24pub mod moderations;
25pub mod threads;
26pub mod uploads;
27pub mod vector_stores;
28
29// Re-export response types for convenience
30// NOTE: Re-exports will be enabled as modules are implemented
31// pub use assistants::*;
32// pub use audio::*;
33// pub use batch::*;
34pub use chat::*; // Has implementation
35                 // pub use embeddings::*;
36                 // pub use files::*;
37                 // pub use fine_tuning::*;
38                 // pub use images::*;
39                 // pub use moderations::*;
40                 // pub use threads::*;
41                 // pub use uploads::*;
42                 // pub use vector_stores::*;
43
44// TODO: Import actual types from openai-client-base once available
45// use openai_client_base::responses::*;
46
47/// Common trait for all response types to provide consistent access patterns.
48pub trait Response {
49    /// Get the unique identifier for this response, if available.
50    fn id(&self) -> Option<&str>;
51
52    /// Get the model that generated this response, if available.
53    fn model(&self) -> Option<&str>;
54
55    /// Get any usage information from the response, if available.
56    fn usage(&self) -> Option<&Usage>;
57}
58
59/// Usage information for API calls.
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct Usage {
62    /// Number of tokens in the prompt
63    pub prompt_tokens: u32,
64    /// Number of tokens in the completion (if applicable)
65    pub completion_tokens: Option<u32>,
66    /// Total number of tokens used
67    pub total_tokens: u32,
68}
69
70/// Tool definition for function calling.
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct Tool {
73    /// Type of tool (usually "function")
74    #[serde(rename = "type")]
75    pub tool_type: String,
76    /// Function definition for the tool
77    pub function: ToolFunction,
78}
79
80/// Function definition for tool calling.
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct ToolFunction {
83    /// Name of the function
84    pub name: String,
85    /// Description of what the function does
86    pub description: Option<String>,
87    /// JSON Schema defining the function parameters
88    pub parameters: Option<serde_json::Value>,
89}
90
91/// Tool choice options for responses.
92#[derive(Debug, Clone, Serialize, Deserialize)]
93#[serde(untagged)]
94pub enum ToolChoice {
95    /// Let the model decide whether to call tools
96    Auto,
97    /// Disable tool calling
98    None,
99    /// Force the model to call a tool
100    Required,
101    /// Force the model to call a specific function
102    Function {
103        /// The function to call
104        function: ToolFunction,
105    },
106}
107
108/// Builder for responses-first structured output requests.
109#[derive(Debug, Clone)]
110#[allow(dead_code)]
111pub struct ResponseBuilder {
112    model: String,
113    messages: Vec<crate::builders::ChatMessage>,
114    tools: Vec<Tool>,
115    tool_choice: Option<ToolChoice>,
116    response_format: Option<serde_json::Value>,
117}
118
119impl ResponseBuilder {
120    /// Create a new response builder with the specified model.
121    #[must_use]
122    pub fn new(model: impl Into<String>) -> Self {
123        Self {
124            model: model.into(),
125            messages: Vec::new(),
126            tools: Vec::new(),
127            tool_choice: None,
128            response_format: None,
129        }
130    }
131
132    /// Add a message to the conversation.
133    #[must_use]
134    pub fn message(mut self, role: impl Into<String>, content: impl Into<String>) -> Self {
135        self.messages.push(crate::builders::ChatMessage {
136            role: role.into(),
137            content: content.into(),
138        });
139        self
140    }
141
142    /// Add a tool for function calling.
143    #[must_use]
144    pub fn tool(mut self, tool: Tool) -> Self {
145        self.tools.push(tool);
146        self
147    }
148
149    /// Set the tool choice strategy.
150    #[must_use]
151    pub fn tool_choice(mut self, tool_choice: ToolChoice) -> Self {
152        self.tool_choice = Some(tool_choice);
153        self
154    }
155
156    /// Set the response format for structured outputs.
157    #[must_use]
158    pub fn response_format(mut self, format: serde_json::Value) -> Self {
159        self.response_format = Some(format);
160        self
161    }
162}
163
164// Helper functions for common tool patterns
165
166/// Create a web search tool definition.
167#[must_use]
168pub fn tool_web_search() -> Tool {
169    Tool {
170        tool_type: "function".to_string(),
171        function: ToolFunction {
172            name: "web_search".to_string(),
173            description: Some("Search the web for current information".to_string()),
174            parameters: Some(serde_json::json!({
175                "type": "object",
176                "properties": {
177                    "query": {
178                        "type": "string",
179                        "description": "The search query"
180                    }
181                },
182                "required": ["query"]
183            })),
184        },
185    }
186}
187
188/// Create a function tool definition with JSON schema parameters.
189#[must_use]
190pub fn tool_function(
191    name: impl Into<String>,
192    description: impl Into<String>,
193    parameters: serde_json::Value,
194) -> Tool {
195    Tool {
196        tool_type: "function".to_string(),
197        function: ToolFunction {
198            name: name.into(),
199            description: Some(description.into()),
200            parameters: Some(parameters),
201        },
202    }
203}