Skip to main content

async_openai/types/responses/
impls.rs

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