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