Skip to main content

dynamo_protocols/types/
impls.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Convenience trait implementations for locally-defined types.
5// Types re-exported from upstream async-openai already have their own impls.
6
7use std::fmt::Display;
8
9use super::{
10    AudioUrl, ChatCompletionNamedToolChoice, ChatCompletionRequestAssistantMessage,
11    ChatCompletionRequestAssistantMessageContent, ChatCompletionRequestMessage,
12    ChatCompletionRequestMessageContentPartAudio, ChatCompletionRequestMessageContentPartAudioUrl,
13    ChatCompletionRequestMessageContentPartImage, ChatCompletionRequestMessageContentPartText,
14    ChatCompletionRequestMessageContentPartVideo, ChatCompletionRequestSystemMessage,
15    ChatCompletionRequestSystemMessageContent, ChatCompletionRequestToolMessage,
16    ChatCompletionRequestToolMessageContent, ChatCompletionRequestToolMessageContentPart,
17    ChatCompletionRequestUserMessageContentPart, ChatCompletionToolChoiceOption,
18    ChatCompletionToolType, FunctionName, ImageUrl, VideoUrl,
19};
20
21use crate::error::OpenAIError;
22
23// --- From impls for locally-defined types ---
24
25impl From<&str> for FunctionName {
26    fn from(value: &str) -> Self {
27        Self { name: value.into() }
28    }
29}
30
31impl From<String> for FunctionName {
32    fn from(value: String) -> Self {
33        Self { name: value }
34    }
35}
36
37impl From<&str> for ChatCompletionNamedToolChoice {
38    fn from(value: &str) -> Self {
39        Self {
40            r#type: ChatCompletionToolType::Function,
41            function: value.into(),
42        }
43    }
44}
45
46impl From<String> for ChatCompletionNamedToolChoice {
47    fn from(value: String) -> Self {
48        Self {
49            r#type: ChatCompletionToolType::Function,
50            function: value.into(),
51        }
52    }
53}
54
55impl From<&str> for ChatCompletionToolChoiceOption {
56    fn from(value: &str) -> Self {
57        match value {
58            "auto" => Self::Auto,
59            "none" => Self::None,
60            _ => Self::Named(value.into()),
61        }
62    }
63}
64
65impl From<String> for ChatCompletionToolChoiceOption {
66    fn from(value: String) -> Self {
67        match value.as_str() {
68            "auto" => Self::Auto,
69            "none" => Self::None,
70            _ => Self::Named(value.into()),
71        }
72    }
73}
74
75// From message types into ChatCompletionRequestMessage enum
76// Note: types from upstream (SystemMessage, ToolMessage, etc.) need From impls
77// on our local ChatCompletionRequestMessage enum.
78
79impl From<super::ChatCompletionRequestUserMessage> for ChatCompletionRequestMessage {
80    fn from(value: super::ChatCompletionRequestUserMessage) -> Self {
81        Self::User(value)
82    }
83}
84
85impl From<ChatCompletionRequestSystemMessageContent> for ChatCompletionRequestSystemMessage {
86    fn from(value: ChatCompletionRequestSystemMessageContent) -> Self {
87        Self {
88            content: value,
89            name: None,
90            tools: None,
91        }
92    }
93}
94
95impl From<&str> for ChatCompletionRequestSystemMessage {
96    fn from(value: &str) -> Self {
97        ChatCompletionRequestSystemMessageContent::Text(value.into()).into()
98    }
99}
100
101impl From<String> for ChatCompletionRequestSystemMessage {
102    fn from(value: String) -> Self {
103        ChatCompletionRequestSystemMessageContent::Text(value).into()
104    }
105}
106
107impl From<async_openai::types::chat::ChatCompletionRequestSystemMessage>
108    for ChatCompletionRequestSystemMessage
109{
110    fn from(value: async_openai::types::chat::ChatCompletionRequestSystemMessage) -> Self {
111        Self {
112            content: value.content,
113            name: value.name,
114            tools: None,
115        }
116    }
117}
118
119impl From<async_openai::types::chat::ChatCompletionRequestSystemMessage>
120    for ChatCompletionRequestMessage
121{
122    fn from(value: async_openai::types::chat::ChatCompletionRequestSystemMessage) -> Self {
123        Self::System(value.into())
124    }
125}
126
127impl From<ChatCompletionRequestSystemMessage> for ChatCompletionRequestMessage {
128    fn from(value: ChatCompletionRequestSystemMessage) -> Self {
129        Self::System(value)
130    }
131}
132
133impl From<async_openai::types::chat::ChatCompletionRequestDeveloperMessage>
134    for ChatCompletionRequestMessage
135{
136    fn from(value: async_openai::types::chat::ChatCompletionRequestDeveloperMessage) -> Self {
137        Self::Developer(value)
138    }
139}
140
141impl From<async_openai::types::chat::ChatCompletionRequestToolMessage>
142    for ChatCompletionRequestMessage
143{
144    fn from(value: async_openai::types::chat::ChatCompletionRequestToolMessage) -> Self {
145        Self::Tool(value.into())
146    }
147}
148
149impl From<async_openai::types::chat::ChatCompletionRequestToolMessage>
150    for ChatCompletionRequestToolMessage
151{
152    fn from(value: async_openai::types::chat::ChatCompletionRequestToolMessage) -> Self {
153        let content = match value.content {
154            async_openai::types::chat::ChatCompletionRequestToolMessageContent::Text(text) => {
155                ChatCompletionRequestToolMessageContent::Text(text)
156            }
157            async_openai::types::chat::ChatCompletionRequestToolMessageContent::Array(parts) => {
158                ChatCompletionRequestToolMessageContent::Array(
159                    parts
160                        .into_iter()
161                        .map(|part| match part {
162                            async_openai::types::chat::ChatCompletionRequestToolMessageContentPart::Text(
163                                text,
164                            ) => ChatCompletionRequestToolMessageContentPart::Text(text),
165                        })
166                        .collect(),
167                )
168            }
169        };
170        Self {
171            content,
172            tool_call_id: value.tool_call_id,
173        }
174    }
175}
176
177impl From<ChatCompletionRequestToolMessage> for ChatCompletionRequestMessage {
178    fn from(value: ChatCompletionRequestToolMessage) -> Self {
179        Self::Tool(value)
180    }
181}
182
183impl From<async_openai::types::chat::ChatCompletionRequestFunctionMessage>
184    for ChatCompletionRequestMessage
185{
186    fn from(value: async_openai::types::chat::ChatCompletionRequestFunctionMessage) -> Self {
187        Self::Function(value)
188    }
189}
190
191impl From<ChatCompletionRequestAssistantMessage> for ChatCompletionRequestMessage {
192    fn from(value: ChatCompletionRequestAssistantMessage) -> Self {
193        Self::Assistant(value)
194    }
195}
196
197impl From<ChatCompletionRequestAssistantMessageContent> for ChatCompletionRequestAssistantMessage {
198    fn from(value: ChatCompletionRequestAssistantMessageContent) -> Self {
199        Self {
200            content: Some(value),
201            ..Default::default()
202        }
203    }
204}
205
206impl From<&str> for ChatCompletionRequestAssistantMessage {
207    fn from(value: &str) -> Self {
208        ChatCompletionRequestAssistantMessageContent::Text(value.into()).into()
209    }
210}
211
212impl From<String> for ChatCompletionRequestAssistantMessage {
213    fn from(value: String) -> Self {
214        value.as_str().into()
215    }
216}
217
218// From content parts into UserMessageContentPart enum
219
220impl From<ChatCompletionRequestMessageContentPartText>
221    for ChatCompletionRequestUserMessageContentPart
222{
223    fn from(value: ChatCompletionRequestMessageContentPartText) -> Self {
224        ChatCompletionRequestUserMessageContentPart::Text(value)
225    }
226}
227
228impl From<ChatCompletionRequestMessageContentPartImage>
229    for ChatCompletionRequestUserMessageContentPart
230{
231    fn from(value: ChatCompletionRequestMessageContentPartImage) -> Self {
232        ChatCompletionRequestUserMessageContentPart::ImageUrl(value)
233    }
234}
235
236impl From<ChatCompletionRequestMessageContentPartAudio>
237    for ChatCompletionRequestUserMessageContentPart
238{
239    fn from(value: ChatCompletionRequestMessageContentPartAudio) -> Self {
240        ChatCompletionRequestUserMessageContentPart::InputAudio(value)
241    }
242}
243
244impl From<ChatCompletionRequestMessageContentPartVideo>
245    for ChatCompletionRequestUserMessageContentPart
246{
247    fn from(value: ChatCompletionRequestMessageContentPartVideo) -> Self {
248        ChatCompletionRequestUserMessageContentPart::VideoUrl(value)
249    }
250}
251
252impl From<ChatCompletionRequestMessageContentPartAudioUrl>
253    for ChatCompletionRequestUserMessageContentPart
254{
255    fn from(value: ChatCompletionRequestMessageContentPartAudioUrl) -> Self {
256        ChatCompletionRequestUserMessageContentPart::AudioUrl(value)
257    }
258}
259
260// URL type conversions
261
262impl From<&str> for ImageUrl {
263    fn from(value: &str) -> Self {
264        Self {
265            url: value.parse().expect("Invalid URL"),
266            detail: Default::default(),
267            uuid: None,
268        }
269    }
270}
271
272impl From<String> for ImageUrl {
273    fn from(value: String) -> Self {
274        Self {
275            url: value.parse().expect("Invalid URL"),
276            detail: Default::default(),
277            uuid: None,
278        }
279    }
280}
281
282impl From<&str> for VideoUrl {
283    fn from(value: &str) -> Self {
284        Self {
285            url: value.parse().expect("Invalid URL"),
286            detail: Default::default(),
287            uuid: None,
288        }
289    }
290}
291
292impl From<String> for VideoUrl {
293    fn from(value: String) -> Self {
294        Self {
295            url: value.parse().expect("Invalid URL"),
296            detail: Default::default(),
297            uuid: None,
298        }
299    }
300}
301
302impl From<&str> for AudioUrl {
303    fn from(value: &str) -> Self {
304        Self {
305            url: value.parse().expect("Invalid URL"),
306            uuid: None,
307        }
308    }
309}
310
311impl From<String> for AudioUrl {
312    fn from(value: String) -> Self {
313        Self {
314            url: value.parse().expect("Invalid URL"),
315            uuid: None,
316        }
317    }
318}