Skip to main content

async_openai/types/responses/
impls.rs

1use crate::types::mcp::MCPTool;
2use crate::types::responses::{
3    ApplyPatchCallOutputStatus, ApplyPatchCallOutputStatusParam, ApplyPatchCallStatus,
4    ApplyPatchCallStatusParam, ApplyPatchCreateFileOperation, ApplyPatchCreateFileOperationParam,
5    ApplyPatchDeleteFileOperation, ApplyPatchDeleteFileOperationParam, ApplyPatchOperation,
6    ApplyPatchOperationParam, ApplyPatchToolCall, ApplyPatchToolCallItemParam,
7    ApplyPatchToolCallOutput, ApplyPatchToolCallOutputItemParam, ApplyPatchUpdateFileOperation,
8    ApplyPatchUpdateFileOperationParam, CodeInterpreterContainerAuto, CodeInterpreterTool,
9    CodeInterpreterToolCall, CodeInterpreterToolContainer, CompactionBody,
10    CompactionSummaryItemParam, ComputerCallOutputItemParam, ComputerTool, ComputerToolCall,
11    ComputerToolCallOutputResource, ComputerUsePreviewTool, ContainerReferenceParam,
12    ContainerReferenceResource, ConversationParam, CustomToolCall, CustomToolCallOutput,
13    CustomToolCallOutputResource, CustomToolParam, EasyInputContent, EasyInputMessage,
14    FileSearchTool, FileSearchToolCall, FunctionCallOutput, FunctionCallOutputItemParam,
15    FunctionCallOutputStatusEnum, FunctionCallStatus, FunctionShellAction,
16    FunctionShellActionParam, FunctionShellCall, FunctionShellCallEnvironment,
17    FunctionShellCallItemEnvironment, FunctionShellCallItemParam, FunctionShellCallItemStatus,
18    FunctionShellCallOutput, FunctionShellCallOutputContent, FunctionShellCallOutputContentParam,
19    FunctionShellCallOutputExitOutcome, FunctionShellCallOutputExitOutcomeParam,
20    FunctionShellCallOutputItemParam, FunctionShellCallOutputOutcome,
21    FunctionShellCallOutputOutcomeParam, FunctionTool, FunctionToolCall,
22    FunctionToolCallOutputResource, ImageGenTool, ImageGenToolCall, InputContent, InputFileContent,
23    InputImageContent, InputItem, InputMessage, InputParam, InputTextContent, Item, ItemReference,
24    ItemReferenceType, LocalEnvironmentParam, LocalShellCallStatus, LocalShellToolCall,
25    LocalShellToolCallOutput, MCPApprovalRequest, MCPApprovalResponse, MCPListTools, MCPToolCall,
26    MessageItem, MessageType, NamespaceToolParam, OutputItem, OutputMessage, OutputMessageContent,
27    OutputStatus, OutputTextContent, Prompt, Reasoning, ReasoningEffort, ReasoningItem,
28    ReasoningSummary, RefusalContent, ResponseFormatJsonSchema, ResponsePromptVariables,
29    ResponseStreamOptions, ResponseTextParam, Role, TextResponseFormatConfiguration, Tool,
30    ToolChoiceCustom, ToolChoiceFunction, ToolChoiceMCP, ToolChoiceOptions, ToolChoiceParam,
31    ToolChoiceTypes, ToolSearchCall, ToolSearchCallItemParam, ToolSearchOutput,
32    ToolSearchOutputItemParam, ToolSearchToolParam, WebSearchTool, WebSearchToolCall,
33};
34
35impl<S: Into<String>> From<S> for EasyInputMessage {
36    fn from(value: S) -> Self {
37        EasyInputMessage {
38            r#type: MessageType::Message,
39            role: Role::User,
40            content: EasyInputContent::Text(value.into()),
41            phase: None,
42        }
43    }
44}
45
46impl From<EasyInputMessage> for InputItem {
47    fn from(msg: EasyInputMessage) -> Self {
48        InputItem::EasyMessage(msg)
49    }
50}
51
52// InputItem ergonomics
53
54impl From<InputMessage> for InputItem {
55    fn from(msg: InputMessage) -> Self {
56        InputItem::Item(Item::Message(MessageItem::Input(msg)))
57    }
58}
59
60impl From<Item> for InputItem {
61    fn from(item: Item) -> Self {
62        InputItem::Item(item)
63    }
64}
65
66impl From<ItemReference> for InputItem {
67    fn from(item: ItemReference) -> Self {
68        InputItem::ItemReference(item)
69    }
70}
71
72// InputParam ergonomics: from InputItem
73
74impl From<InputItem> for InputParam {
75    fn from(item: InputItem) -> Self {
76        InputParam::Items(vec![item])
77    }
78}
79
80impl From<Item> for InputParam {
81    fn from(item: Item) -> Self {
82        InputParam::Items(vec![InputItem::Item(item)])
83    }
84}
85
86impl From<MessageItem> for InputParam {
87    fn from(item: MessageItem) -> Self {
88        InputParam::Items(vec![InputItem::Item(Item::Message(item))])
89    }
90}
91
92impl From<InputMessage> for InputParam {
93    fn from(msg: InputMessage) -> Self {
94        InputParam::Items(vec![InputItem::Item(Item::Message(MessageItem::Input(
95            msg,
96        )))])
97    }
98}
99
100impl<I: Into<InputItem>> From<Vec<I>> for InputParam {
101    fn from(items: Vec<I>) -> Self {
102        InputParam::Items(items.into_iter().map(|item| item.into()).collect())
103    }
104}
105
106impl<I: Into<InputItem>, const N: usize> From<[I; N]> for InputParam {
107    fn from(items: [I; N]) -> Self {
108        InputParam::Items(items.into_iter().map(|item| item.into()).collect())
109    }
110}
111
112// InputParam ergonomics: from string "family"
113
114impl From<&str> for InputParam {
115    fn from(value: &str) -> Self {
116        InputParam::Text(value.into())
117    }
118}
119
120impl From<String> for InputParam {
121    fn from(value: String) -> Self {
122        InputParam::Text(value)
123    }
124}
125
126impl From<&String> for InputParam {
127    fn from(value: &String) -> Self {
128        InputParam::Text(value.clone())
129    }
130}
131
132// InputParam ergonomics: from vector family
133
134macro_rules! impl_inputparam_easy_from_collection {
135    // Vec<T>
136    ($t:ty, $map:expr, $clone:expr) => {
137        impl From<Vec<$t>> for InputParam {
138            fn from(values: Vec<$t>) -> Self {
139                InputParam::Items(
140                    values
141                        .into_iter()
142                        .map(|value| {
143                            InputItem::EasyMessage(EasyInputMessage {
144                                r#type: MessageType::Message,
145                                role: Role::User,
146                                content: EasyInputContent::Text($map(value)),
147                                phase: None,
148                            })
149                        })
150                        .collect(),
151                )
152            }
153        }
154        // &[T; N]
155        impl<const N: usize> From<[$t; N]> for InputParam {
156            fn from(values: [$t; N]) -> Self {
157                InputParam::Items(
158                    values
159                        .into_iter()
160                        .map(|value| {
161                            InputItem::EasyMessage(EasyInputMessage {
162                                r#type: MessageType::Message,
163                                role: Role::User,
164                                content: EasyInputContent::Text($map(value)),
165                                phase: None,
166                            })
167                        })
168                        .collect(),
169                )
170            }
171        }
172        // &Vec<T>
173        impl From<&Vec<$t>> for InputParam {
174            fn from(values: &Vec<$t>) -> Self {
175                InputParam::Items(
176                    values
177                        .iter()
178                        .map(|value| {
179                            InputItem::EasyMessage(EasyInputMessage {
180                                r#type: MessageType::Message,
181                                role: Role::User,
182                                content: EasyInputContent::Text($clone(value)),
183                                phase: None,
184                            })
185                        })
186                        .collect(),
187                )
188            }
189        }
190    };
191}
192
193// Apply for &str
194impl_inputparam_easy_from_collection!(&str, |v: &str| v.to_string(), |v: &str| v.to_string());
195// Apply for String
196impl_inputparam_easy_from_collection!(String, |v: String| v, |v: &String| v.clone());
197// Apply for &String
198impl_inputparam_easy_from_collection!(&String, |v: &String| v.clone(), |v: &String| v.clone());
199
200// ConversationParam ergonomics
201
202impl<S: Into<String>> From<S> for ConversationParam {
203    fn from(id: S) -> Self {
204        ConversationParam::ConversationID(id.into())
205    }
206}
207
208// ToolChoiceParam ergonomics
209
210impl From<ToolChoiceOptions> for ToolChoiceParam {
211    fn from(mode: ToolChoiceOptions) -> Self {
212        ToolChoiceParam::Mode(mode)
213    }
214}
215
216impl From<ToolChoiceTypes> for ToolChoiceParam {
217    fn from(tool_type: ToolChoiceTypes) -> Self {
218        ToolChoiceParam::Hosted(tool_type)
219    }
220}
221
222impl<S: Into<String>> From<S> for ToolChoiceParam {
223    fn from(name: S) -> Self {
224        ToolChoiceParam::Function(ToolChoiceFunction { name: name.into() })
225    }
226}
227
228impl From<ToolChoiceFunction> for ToolChoiceParam {
229    fn from(function: ToolChoiceFunction) -> Self {
230        ToolChoiceParam::Function(function)
231    }
232}
233
234impl From<ToolChoiceMCP> for ToolChoiceParam {
235    fn from(mcp: ToolChoiceMCP) -> Self {
236        ToolChoiceParam::Mcp(mcp)
237    }
238}
239
240impl From<ToolChoiceCustom> for ToolChoiceParam {
241    fn from(custom: ToolChoiceCustom) -> Self {
242        ToolChoiceParam::Custom(custom)
243    }
244}
245
246// ResponseTextParam ergonomics
247
248impl From<TextResponseFormatConfiguration> for ResponseTextParam {
249    fn from(format: TextResponseFormatConfiguration) -> Self {
250        ResponseTextParam {
251            format,
252            verbosity: None,
253        }
254    }
255}
256
257impl From<ResponseFormatJsonSchema> for ResponseTextParam {
258    fn from(schema: ResponseFormatJsonSchema) -> Self {
259        ResponseTextParam {
260            format: TextResponseFormatConfiguration::JsonSchema(schema),
261            verbosity: None,
262        }
263    }
264}
265
266// ResponseStreamOptions ergonomics
267
268impl From<bool> for ResponseStreamOptions {
269    fn from(include_obfuscation: bool) -> Self {
270        ResponseStreamOptions {
271            include_obfuscation: Some(include_obfuscation),
272        }
273    }
274}
275
276// Reasoning ergonomics
277
278impl From<ReasoningEffort> for Reasoning {
279    fn from(effort: ReasoningEffort) -> Self {
280        Reasoning {
281            effort: Some(effort),
282            summary: None,
283        }
284    }
285}
286
287impl From<ReasoningSummary> for Reasoning {
288    fn from(summary: ReasoningSummary) -> Self {
289        Reasoning {
290            effort: None,
291            summary: Some(summary),
292        }
293    }
294}
295
296// Prompt ergonomics
297
298impl<S: Into<String>> From<S> for Prompt {
299    fn from(id: S) -> Self {
300        Prompt {
301            id: id.into(),
302            version: None,
303            variables: None,
304        }
305    }
306}
307
308// InputTextContent ergonomics
309
310impl<S: Into<String>> From<S> for InputTextContent {
311    fn from(text: S) -> Self {
312        InputTextContent { text: text.into() }
313    }
314}
315
316// InputContent ergonomics
317
318impl From<InputTextContent> for InputContent {
319    fn from(content: InputTextContent) -> Self {
320        InputContent::InputText(content)
321    }
322}
323
324impl From<InputImageContent> for InputContent {
325    fn from(content: InputImageContent) -> Self {
326        InputContent::InputImage(content)
327    }
328}
329
330impl From<InputFileContent> for InputContent {
331    fn from(content: InputFileContent) -> Self {
332        InputContent::InputFile(content)
333    }
334}
335
336impl<S: Into<String>> From<S> for InputContent {
337    fn from(text: S) -> Self {
338        InputContent::InputText(InputTextContent { text: text.into() })
339    }
340}
341
342// ResponsePromptVariables ergonomics
343
344impl From<InputContent> for ResponsePromptVariables {
345    fn from(content: InputContent) -> Self {
346        ResponsePromptVariables::Content(content)
347    }
348}
349
350impl<S: Into<String>> From<S> for ResponsePromptVariables {
351    fn from(text: S) -> Self {
352        ResponsePromptVariables::String(text.into())
353    }
354}
355
356// MessageItem ergonomics
357
358impl From<InputMessage> for MessageItem {
359    fn from(msg: InputMessage) -> Self {
360        MessageItem::Input(msg)
361    }
362}
363
364impl From<OutputMessage> for MessageItem {
365    fn from(msg: OutputMessage) -> Self {
366        MessageItem::Output(msg)
367    }
368}
369
370// FunctionCallOutput ergonomics
371
372impl From<&str> for FunctionCallOutput {
373    fn from(text: &str) -> Self {
374        FunctionCallOutput::Text(text.to_string())
375    }
376}
377
378impl From<String> for FunctionCallOutput {
379    fn from(text: String) -> Self {
380        FunctionCallOutput::Text(text)
381    }
382}
383
384impl From<Vec<InputContent>> for FunctionCallOutput {
385    fn from(content: Vec<InputContent>) -> Self {
386        FunctionCallOutput::Content(content)
387    }
388}
389
390// RefusalContent ergonomics
391
392impl<S: Into<String>> From<S> for RefusalContent {
393    fn from(refusal: S) -> Self {
394        RefusalContent {
395            refusal: refusal.into(),
396        }
397    }
398}
399
400// OutputMessageContent ergonomics
401
402impl From<OutputTextContent> for OutputMessageContent {
403    fn from(content: OutputTextContent) -> Self {
404        OutputMessageContent::OutputText(content)
405    }
406}
407
408impl From<RefusalContent> for OutputMessageContent {
409    fn from(content: RefusalContent) -> Self {
410        OutputMessageContent::Refusal(content)
411    }
412}
413
414// Item ergonomics
415
416impl From<MessageItem> for Item {
417    fn from(item: MessageItem) -> Self {
418        Item::Message(item)
419    }
420}
421
422impl From<FileSearchToolCall> for Item {
423    fn from(call: FileSearchToolCall) -> Self {
424        Item::FileSearchCall(call)
425    }
426}
427
428impl From<ComputerToolCall> for Item {
429    fn from(call: ComputerToolCall) -> Self {
430        Item::ComputerCall(call)
431    }
432}
433
434impl From<ComputerCallOutputItemParam> for Item {
435    fn from(output: ComputerCallOutputItemParam) -> Self {
436        Item::ComputerCallOutput(output)
437    }
438}
439
440impl From<WebSearchToolCall> for Item {
441    fn from(call: WebSearchToolCall) -> Self {
442        Item::WebSearchCall(call)
443    }
444}
445
446impl From<FunctionToolCall> for Item {
447    fn from(call: FunctionToolCall) -> Self {
448        Item::FunctionCall(call)
449    }
450}
451
452impl From<FunctionCallOutputItemParam> for Item {
453    fn from(output: FunctionCallOutputItemParam) -> Self {
454        Item::FunctionCallOutput(output)
455    }
456}
457
458impl From<ReasoningItem> for Item {
459    fn from(item: ReasoningItem) -> Self {
460        Item::Reasoning(item)
461    }
462}
463
464impl From<ImageGenToolCall> for Item {
465    fn from(call: ImageGenToolCall) -> Self {
466        Item::ImageGenerationCall(call)
467    }
468}
469
470impl From<CodeInterpreterToolCall> for Item {
471    fn from(call: CodeInterpreterToolCall) -> Self {
472        Item::CodeInterpreterCall(call)
473    }
474}
475
476impl From<LocalShellToolCall> for Item {
477    fn from(call: LocalShellToolCall) -> Self {
478        Item::LocalShellCall(call)
479    }
480}
481
482impl From<LocalShellToolCallOutput> for Item {
483    fn from(output: LocalShellToolCallOutput) -> Self {
484        Item::LocalShellCallOutput(output)
485    }
486}
487
488impl From<FunctionShellCallItemParam> for Item {
489    fn from(call: FunctionShellCallItemParam) -> Self {
490        Item::ShellCall(call)
491    }
492}
493
494impl From<FunctionShellCallOutputItemParam> for Item {
495    fn from(output: FunctionShellCallOutputItemParam) -> Self {
496        Item::ShellCallOutput(output)
497    }
498}
499
500impl From<ApplyPatchToolCallItemParam> for Item {
501    fn from(call: ApplyPatchToolCallItemParam) -> Self {
502        Item::ApplyPatchCall(call)
503    }
504}
505
506impl From<ApplyPatchToolCallOutputItemParam> for Item {
507    fn from(output: ApplyPatchToolCallOutputItemParam) -> Self {
508        Item::ApplyPatchCallOutput(output)
509    }
510}
511
512impl From<MCPListTools> for Item {
513    fn from(tools: MCPListTools) -> Self {
514        Item::McpListTools(tools)
515    }
516}
517
518impl From<MCPApprovalRequest> for Item {
519    fn from(request: MCPApprovalRequest) -> Self {
520        Item::McpApprovalRequest(request)
521    }
522}
523
524impl From<MCPApprovalResponse> for Item {
525    fn from(response: MCPApprovalResponse) -> Self {
526        Item::McpApprovalResponse(response)
527    }
528}
529
530impl From<MCPToolCall> for Item {
531    fn from(call: MCPToolCall) -> Self {
532        Item::McpCall(call)
533    }
534}
535
536impl From<CustomToolCallOutput> for Item {
537    fn from(output: CustomToolCallOutput) -> Self {
538        Item::CustomToolCallOutput(output)
539    }
540}
541
542impl From<CustomToolCall> for Item {
543    fn from(call: CustomToolCall) -> Self {
544        Item::CustomToolCall(call)
545    }
546}
547
548impl From<ToolSearchCallItemParam> for Item {
549    fn from(call: ToolSearchCallItemParam) -> Self {
550        Item::ToolSearchCall(call)
551    }
552}
553
554impl From<ToolSearchOutputItemParam> for Item {
555    fn from(output: ToolSearchOutputItemParam) -> Self {
556        Item::ToolSearchOutput(output)
557    }
558}
559
560// Tool ergonomics
561
562impl From<FunctionTool> for Tool {
563    fn from(tool: FunctionTool) -> Self {
564        Tool::Function(tool)
565    }
566}
567
568impl From<FileSearchTool> for Tool {
569    fn from(tool: FileSearchTool) -> Self {
570        Tool::FileSearch(tool)
571    }
572}
573
574impl From<ComputerUsePreviewTool> for Tool {
575    fn from(tool: ComputerUsePreviewTool) -> Self {
576        Tool::ComputerUsePreview(tool)
577    }
578}
579
580impl From<WebSearchTool> for Tool {
581    fn from(tool: WebSearchTool) -> Self {
582        Tool::WebSearch(tool)
583    }
584}
585
586impl From<MCPTool> for Tool {
587    fn from(tool: MCPTool) -> Self {
588        Tool::Mcp(tool)
589    }
590}
591
592impl From<CodeInterpreterTool> for Tool {
593    fn from(tool: CodeInterpreterTool) -> Self {
594        Tool::CodeInterpreter(tool)
595    }
596}
597
598impl From<ImageGenTool> for Tool {
599    fn from(tool: ImageGenTool) -> Self {
600        Tool::ImageGeneration(tool)
601    }
602}
603
604impl From<CustomToolParam> for Tool {
605    fn from(tool: CustomToolParam) -> Self {
606        Tool::Custom(tool)
607    }
608}
609
610impl From<ComputerTool> for Tool {
611    fn from(tool: ComputerTool) -> Self {
612        Tool::Computer(tool)
613    }
614}
615
616impl From<NamespaceToolParam> for Tool {
617    fn from(tool: NamespaceToolParam) -> Self {
618        Tool::Namespace(tool)
619    }
620}
621
622impl From<ToolSearchToolParam> for Tool {
623    fn from(tool: ToolSearchToolParam) -> Self {
624        Tool::ToolSearch(tool)
625    }
626}
627
628// Vec<Tool> ergonomics
629
630impl From<Tool> for Vec<Tool> {
631    fn from(tool: Tool) -> Self {
632        vec![tool]
633    }
634}
635
636impl From<FunctionTool> for Vec<Tool> {
637    fn from(tool: FunctionTool) -> Self {
638        vec![Tool::Function(tool)]
639    }
640}
641
642impl From<FileSearchTool> for Vec<Tool> {
643    fn from(tool: FileSearchTool) -> Self {
644        vec![Tool::FileSearch(tool)]
645    }
646}
647
648impl From<ComputerUsePreviewTool> for Vec<Tool> {
649    fn from(tool: ComputerUsePreviewTool) -> Self {
650        vec![Tool::ComputerUsePreview(tool)]
651    }
652}
653
654impl From<WebSearchTool> for Vec<Tool> {
655    fn from(tool: WebSearchTool) -> Self {
656        vec![Tool::WebSearch(tool)]
657    }
658}
659
660impl From<MCPTool> for Vec<Tool> {
661    fn from(tool: MCPTool) -> Self {
662        vec![Tool::Mcp(tool)]
663    }
664}
665
666impl From<CodeInterpreterTool> for Vec<Tool> {
667    fn from(tool: CodeInterpreterTool) -> Self {
668        vec![Tool::CodeInterpreter(tool)]
669    }
670}
671
672impl From<ImageGenTool> for Vec<Tool> {
673    fn from(tool: ImageGenTool) -> Self {
674        vec![Tool::ImageGeneration(tool)]
675    }
676}
677
678impl From<CustomToolParam> for Vec<Tool> {
679    fn from(tool: CustomToolParam) -> Self {
680        vec![Tool::Custom(tool)]
681    }
682}
683
684// EasyInputContent ergonomics
685
686impl Default for EasyInputContent {
687    fn default() -> Self {
688        Self::Text("".to_string())
689    }
690}
691
692impl From<String> for EasyInputContent {
693    fn from(value: String) -> Self {
694        Self::Text(value)
695    }
696}
697
698impl From<&str> for EasyInputContent {
699    fn from(value: &str) -> Self {
700        Self::Text(value.to_owned())
701    }
702}
703
704// Defaults
705
706impl Default for CodeInterpreterToolContainer {
707    fn default() -> Self {
708        Self::Auto(CodeInterpreterContainerAuto::default())
709    }
710}
711
712impl Default for InputParam {
713    fn default() -> Self {
714        Self::Text(String::new())
715    }
716}
717
718impl ItemReference {
719    /// Create a new item reference with the given ID.
720    pub fn new(id: impl Into<String>) -> Self {
721        Self {
722            r#type: Some(ItemReferenceType::ItemReference),
723            id: id.into(),
724        }
725    }
726}
727
728// ──────────────────────────────────────────────────────────────────────────
729// OutputItem -> Item / InputItem (multi-turn responses helpers)
730//
731// The Responses API requires reasoning items to be echoed back into the
732// next request's `input` alongside the function-call items they preceded —
733// otherwise the server rejects the request with
734// `Item 'fc_...' was provided without its required 'reasoning' item: ...`.
735// In the official Python and Node SDKs the canonical pattern is just
736// `input_list += response.output`, since their input/output item types
737// are the same. In Rust the OpenAPI-derived schemas split into Item (input
738// side) and OutputItem (output side), so an explicit conversion is needed.
739//
740// The conversions below give that "just append the output" ergonomic via
741// `From<OutputItem> for Item` (and through it, `From<OutputItem> for
742// InputItem`). For variants where input and output already share a struct
743// the conversion is a one-liner; for the handful of variants where the
744// schemas differ (resource types carry required `id`/`status`, while their
745// input-side `*ItemParam` counterparts have those optional), per-pair
746// `From` impls map the fields so callers don't have to write boilerplate
747// per use site.
748//
749// References:
750//   - https://github.com/64bit/async-openai/issues/492
751//   - https://platform.openai.com/docs/guides/conversation-state
752// ──────────────────────────────────────────────────────────────────────────
753
754// Status enum mappings (resource side → param side).
755
756impl From<FunctionCallOutputStatusEnum> for OutputStatus {
757    fn from(status: FunctionCallOutputStatusEnum) -> Self {
758        match status {
759            FunctionCallOutputStatusEnum::InProgress => OutputStatus::InProgress,
760            FunctionCallOutputStatusEnum::Completed => OutputStatus::Completed,
761            FunctionCallOutputStatusEnum::Incomplete => OutputStatus::Incomplete,
762        }
763    }
764}
765
766impl From<FunctionCallStatus> for OutputStatus {
767    fn from(status: FunctionCallStatus) -> Self {
768        match status {
769            FunctionCallStatus::InProgress => OutputStatus::InProgress,
770            FunctionCallStatus::Completed => OutputStatus::Completed,
771            FunctionCallStatus::Incomplete => OutputStatus::Incomplete,
772        }
773    }
774}
775
776impl From<LocalShellCallStatus> for FunctionShellCallItemStatus {
777    fn from(status: LocalShellCallStatus) -> Self {
778        match status {
779            LocalShellCallStatus::InProgress => FunctionShellCallItemStatus::InProgress,
780            LocalShellCallStatus::Completed => FunctionShellCallItemStatus::Completed,
781            LocalShellCallStatus::Incomplete => FunctionShellCallItemStatus::Incomplete,
782        }
783    }
784}
785
786impl From<ApplyPatchCallStatus> for ApplyPatchCallStatusParam {
787    fn from(status: ApplyPatchCallStatus) -> Self {
788        match status {
789            ApplyPatchCallStatus::InProgress => ApplyPatchCallStatusParam::InProgress,
790            ApplyPatchCallStatus::Completed => ApplyPatchCallStatusParam::Completed,
791        }
792    }
793}
794
795impl From<ApplyPatchCallOutputStatus> for ApplyPatchCallOutputStatusParam {
796    fn from(status: ApplyPatchCallOutputStatus) -> Self {
797        match status {
798            ApplyPatchCallOutputStatus::Completed => ApplyPatchCallOutputStatusParam::Completed,
799            ApplyPatchCallOutputStatus::Failed => ApplyPatchCallOutputStatusParam::Failed,
800        }
801    }
802}
803
804// Shell environment / outcome mappings.
805
806impl From<ContainerReferenceResource> for ContainerReferenceParam {
807    fn from(r: ContainerReferenceResource) -> Self {
808        ContainerReferenceParam {
809            container_id: r.container_id,
810        }
811    }
812}
813
814impl From<FunctionShellCallEnvironment> for FunctionShellCallItemEnvironment {
815    fn from(env: FunctionShellCallEnvironment) -> Self {
816        match env {
817            // The response side carries no payload for `Local`; the param
818            // side accepts an optional `skills` list which we leave None
819            // (it's a request-only knob).
820            FunctionShellCallEnvironment::Local => {
821                FunctionShellCallItemEnvironment::Local(LocalEnvironmentParam { skills: None })
822            }
823            FunctionShellCallEnvironment::ContainerReference(r) => {
824                FunctionShellCallItemEnvironment::ContainerReference(r.into())
825            }
826        }
827    }
828}
829
830impl From<FunctionShellCallOutputExitOutcome> for FunctionShellCallOutputExitOutcomeParam {
831    fn from(o: FunctionShellCallOutputExitOutcome) -> Self {
832        FunctionShellCallOutputExitOutcomeParam {
833            exit_code: o.exit_code,
834        }
835    }
836}
837
838impl From<FunctionShellCallOutputOutcome> for FunctionShellCallOutputOutcomeParam {
839    fn from(o: FunctionShellCallOutputOutcome) -> Self {
840        match o {
841            FunctionShellCallOutputOutcome::Timeout => FunctionShellCallOutputOutcomeParam::Timeout,
842            FunctionShellCallOutputOutcome::Exit(e) => {
843                FunctionShellCallOutputOutcomeParam::Exit(e.into())
844            }
845        }
846    }
847}
848
849impl From<FunctionShellCallOutputContent> for FunctionShellCallOutputContentParam {
850    fn from(c: FunctionShellCallOutputContent) -> Self {
851        FunctionShellCallOutputContentParam {
852            stdout: c.stdout,
853            stderr: c.stderr,
854            outcome: c.outcome.into(),
855        }
856    }
857}
858
859impl From<FunctionShellAction> for FunctionShellActionParam {
860    fn from(a: FunctionShellAction) -> Self {
861        FunctionShellActionParam {
862            commands: a.commands,
863            timeout_ms: a.timeout_ms,
864            max_output_length: a.max_output_length,
865        }
866    }
867}
868
869// ApplyPatch operation mappings.
870
871impl From<ApplyPatchCreateFileOperation> for ApplyPatchCreateFileOperationParam {
872    fn from(op: ApplyPatchCreateFileOperation) -> Self {
873        ApplyPatchCreateFileOperationParam {
874            path: op.path,
875            diff: op.diff,
876        }
877    }
878}
879
880impl From<ApplyPatchDeleteFileOperation> for ApplyPatchDeleteFileOperationParam {
881    fn from(op: ApplyPatchDeleteFileOperation) -> Self {
882        ApplyPatchDeleteFileOperationParam { path: op.path }
883    }
884}
885
886impl From<ApplyPatchUpdateFileOperation> for ApplyPatchUpdateFileOperationParam {
887    fn from(op: ApplyPatchUpdateFileOperation) -> Self {
888        ApplyPatchUpdateFileOperationParam {
889            path: op.path,
890            diff: op.diff,
891        }
892    }
893}
894
895impl From<ApplyPatchOperation> for ApplyPatchOperationParam {
896    fn from(op: ApplyPatchOperation) -> Self {
897        match op {
898            ApplyPatchOperation::CreateFile(o) => ApplyPatchOperationParam::CreateFile(o.into()),
899            ApplyPatchOperation::DeleteFile(o) => ApplyPatchOperationParam::DeleteFile(o.into()),
900            ApplyPatchOperation::UpdateFile(o) => ApplyPatchOperationParam::UpdateFile(o.into()),
901        }
902    }
903}
904
905// Per-resource-output → input-param conversions. Required `id` / `status`
906// fields on the resource side become wrapped in `Some(...)` on the input
907// side; status enums fold through the `From` impls above. The `created_by`
908// field exists only on the resource side and is dropped on the way in —
909// it's a server-assigned annotation that the input schema doesn't accept.
910
911impl From<FunctionToolCallOutputResource> for FunctionCallOutputItemParam {
912    fn from(r: FunctionToolCallOutputResource) -> Self {
913        FunctionCallOutputItemParam {
914            call_id: r.call_id,
915            output: r.output,
916            id: Some(r.id),
917            status: Some(r.status.into()),
918        }
919    }
920}
921
922impl From<ComputerToolCallOutputResource> for ComputerCallOutputItemParam {
923    fn from(r: ComputerToolCallOutputResource) -> Self {
924        ComputerCallOutputItemParam {
925            call_id: r.call_id,
926            output: r.output,
927            acknowledged_safety_checks: r.acknowledged_safety_checks,
928            id: Some(r.id),
929            // ComputerCallOutputStatus has a `Failed` variant that
930            // OutputStatus doesn't model. The Responses API silently
931            // accepts a missing status here, so collapse `Failed` to None
932            // rather than fabricate a value the schema can't represent.
933            status: match r.status {
934                crate::types::responses::ComputerCallOutputStatus::InProgress => {
935                    Some(OutputStatus::InProgress)
936                }
937                crate::types::responses::ComputerCallOutputStatus::Completed => {
938                    Some(OutputStatus::Completed)
939                }
940                crate::types::responses::ComputerCallOutputStatus::Incomplete => {
941                    Some(OutputStatus::Incomplete)
942                }
943                crate::types::responses::ComputerCallOutputStatus::Failed => None,
944            },
945        }
946    }
947}
948
949impl From<CustomToolCallOutputResource> for CustomToolCallOutput {
950    fn from(r: CustomToolCallOutputResource) -> Self {
951        CustomToolCallOutput {
952            call_id: r.call_id,
953            output: r.output,
954            id: Some(r.id),
955        }
956    }
957}
958
959impl From<FunctionShellCall> for FunctionShellCallItemParam {
960    fn from(c: FunctionShellCall) -> Self {
961        FunctionShellCallItemParam {
962            id: Some(c.id),
963            call_id: c.call_id,
964            action: c.action.into(),
965            status: Some(c.status.into()),
966            environment: c.environment.map(Into::into),
967        }
968    }
969}
970
971impl From<FunctionShellCallOutput> for FunctionShellCallOutputItemParam {
972    fn from(o: FunctionShellCallOutput) -> Self {
973        FunctionShellCallOutputItemParam {
974            id: Some(o.id),
975            call_id: o.call_id,
976            output: o.output.into_iter().map(Into::into).collect(),
977            max_output_length: o.max_output_length,
978        }
979    }
980}
981
982impl From<ApplyPatchToolCall> for ApplyPatchToolCallItemParam {
983    fn from(c: ApplyPatchToolCall) -> Self {
984        ApplyPatchToolCallItemParam {
985            id: Some(c.id),
986            call_id: c.call_id,
987            status: c.status.into(),
988            operation: c.operation.into(),
989        }
990    }
991}
992
993impl From<ApplyPatchToolCallOutput> for ApplyPatchToolCallOutputItemParam {
994    fn from(o: ApplyPatchToolCallOutput) -> Self {
995        ApplyPatchToolCallOutputItemParam {
996            id: Some(o.id),
997            call_id: o.call_id,
998            status: o.status.into(),
999            output: o.output,
1000        }
1001    }
1002}
1003
1004impl From<CompactionBody> for CompactionSummaryItemParam {
1005    fn from(b: CompactionBody) -> Self {
1006        CompactionSummaryItemParam {
1007            id: Some(b.id),
1008            encrypted_content: b.encrypted_content,
1009        }
1010    }
1011}
1012
1013impl From<ToolSearchCall> for ToolSearchCallItemParam {
1014    fn from(c: ToolSearchCall) -> Self {
1015        ToolSearchCallItemParam {
1016            id: Some(c.id),
1017            call_id: c.call_id,
1018            execution: Some(c.execution),
1019            arguments: c.arguments,
1020            status: Some(c.status.into()),
1021        }
1022    }
1023}
1024
1025impl From<ToolSearchOutput> for ToolSearchOutputItemParam {
1026    fn from(o: ToolSearchOutput) -> Self {
1027        ToolSearchOutputItemParam {
1028            id: Some(o.id),
1029            call_id: o.call_id,
1030            execution: Some(o.execution),
1031            tools: o.tools,
1032            status: Some(o.status.into()),
1033        }
1034    }
1035}
1036
1037// Top-level: any output item rolls into an Item, and through the existing
1038// `From<Item> for InputItem` impl, into an InputItem too. This is the entry
1039// point callers actually want — see the `responses-multi-turn-reasoning`
1040// example for the round-trip pattern.
1041
1042impl From<OutputItem> for Item {
1043    fn from(item: OutputItem) -> Self {
1044        match item {
1045            OutputItem::Message(m) => Item::Message(m.into()),
1046            OutputItem::FileSearchCall(c) => c.into(),
1047            OutputItem::FunctionCall(c) => c.into(),
1048            OutputItem::FunctionCallOutput(o) => Item::FunctionCallOutput(o.into()),
1049            OutputItem::WebSearchCall(c) => c.into(),
1050            OutputItem::ComputerCall(c) => c.into(),
1051            OutputItem::ComputerCallOutput(o) => Item::ComputerCallOutput(o.into()),
1052            OutputItem::Reasoning(r) => r.into(),
1053            OutputItem::Compaction(c) => Item::Compaction(c.into()),
1054            OutputItem::ImageGenerationCall(c) => c.into(),
1055            OutputItem::CodeInterpreterCall(c) => c.into(),
1056            OutputItem::LocalShellCall(c) => c.into(),
1057            OutputItem::ShellCall(c) => Item::ShellCall(c.into()),
1058            OutputItem::ShellCallOutput(o) => Item::ShellCallOutput(o.into()),
1059            OutputItem::ApplyPatchCall(c) => Item::ApplyPatchCall(c.into()),
1060            OutputItem::ApplyPatchCallOutput(o) => Item::ApplyPatchCallOutput(o.into()),
1061            OutputItem::McpCall(c) => c.into(),
1062            OutputItem::McpListTools(c) => c.into(),
1063            OutputItem::McpApprovalRequest(c) => c.into(),
1064            OutputItem::CustomToolCall(c) => c.into(),
1065            OutputItem::CustomToolCallOutput(o) => Item::CustomToolCallOutput(o.into()),
1066            OutputItem::ToolSearchCall(c) => Item::ToolSearchCall(c.into()),
1067            OutputItem::ToolSearchOutput(o) => Item::ToolSearchOutput(o.into()),
1068        }
1069    }
1070}
1071
1072impl From<OutputItem> for InputItem {
1073    fn from(item: OutputItem) -> Self {
1074        Item::from(item).into()
1075    }
1076}