openai 0.18.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +1 -1
  4. data/lib/openai/client.rb +4 -0
  5. data/lib/openai/helpers/structured_output/boolean.rb +1 -0
  6. data/lib/openai/internal/conversation_cursor_page.rb +92 -0
  7. data/lib/openai/internal/transport/base_client.rb +1 -4
  8. data/lib/openai/internal/transport/pooled_net_requester.rb +1 -9
  9. data/lib/openai/internal/util.rb +1 -1
  10. data/lib/openai/models/audio/transcription.rb +1 -4
  11. data/lib/openai/models/audio/transcription_create_params.rb +2 -7
  12. data/lib/openai/models/audio/transcription_text_done_event.rb +1 -4
  13. data/lib/openai/models/beta/assistant_create_params.rb +6 -19
  14. data/lib/openai/models/beta/assistant_stream_event.rb +6 -24
  15. data/lib/openai/models/beta/assistant_update_params.rb +1 -4
  16. data/lib/openai/models/beta/message_stream_event.rb +1 -4
  17. data/lib/openai/models/beta/run_step_stream_event.rb +1 -4
  18. data/lib/openai/models/beta/thread_create_and_run_params.rb +10 -32
  19. data/lib/openai/models/beta/thread_create_params.rb +7 -22
  20. data/lib/openai/models/beta/threads/message.rb +3 -10
  21. data/lib/openai/models/beta/threads/message_create_params.rb +2 -7
  22. data/lib/openai/models/beta/threads/run.rb +2 -7
  23. data/lib/openai/models/beta/threads/run_create_params.rb +3 -10
  24. data/lib/openai/models/beta/threads/run_submit_tool_outputs_params.rb +1 -3
  25. data/lib/openai/models/beta/threads/runs/code_interpreter_tool_call.rb +5 -17
  26. data/lib/openai/models/beta/threads/runs/code_interpreter_tool_call_delta.rb +1 -3
  27. data/lib/openai/models/beta/threads/runs/file_search_tool_call.rb +4 -12
  28. data/lib/openai/models/beta/threads/runs/run_step_delta_message_delta.rb +1 -4
  29. data/lib/openai/models/beta/threads/runs/tool_calls_step_details.rb +1 -4
  30. data/lib/openai/models/beta/threads/text.rb +1 -4
  31. data/lib/openai/models/chat/chat_completion_chunk.rb +1 -3
  32. data/lib/openai/models/chat/chat_completion_custom_tool.rb +2 -7
  33. data/lib/openai/models/chat/chat_completion_message.rb +7 -5
  34. data/lib/openai/models/chat/chat_completion_message_function_tool_call.rb +7 -5
  35. data/lib/openai/models/conversations/computer_screenshot_content.rb +38 -0
  36. data/lib/openai/models/conversations/container_file_citation_body.rb +58 -0
  37. data/lib/openai/models/conversations/conversation.rb +51 -0
  38. data/lib/openai/models/conversations/conversation_create_params.rb +39 -0
  39. data/lib/openai/models/conversations/conversation_delete_params.rb +16 -0
  40. data/lib/openai/models/conversations/conversation_deleted.rb +29 -0
  41. data/lib/openai/models/conversations/conversation_deleted_resource.rb +30 -0
  42. data/lib/openai/models/conversations/conversation_item.rb +568 -0
  43. data/lib/openai/models/conversations/conversation_item_list.rb +55 -0
  44. data/lib/openai/models/conversations/conversation_retrieve_params.rb +16 -0
  45. data/lib/openai/models/conversations/conversation_update_params.rb +31 -0
  46. data/lib/openai/models/conversations/file_citation_body.rb +42 -0
  47. data/lib/openai/models/conversations/input_file_content.rb +42 -0
  48. data/lib/openai/models/conversations/input_image_content.rb +62 -0
  49. data/lib/openai/models/conversations/input_text_content.rb +26 -0
  50. data/lib/openai/models/conversations/item_create_params.rb +37 -0
  51. data/lib/openai/models/conversations/item_delete_params.rb +22 -0
  52. data/lib/openai/models/conversations/item_list_params.rb +86 -0
  53. data/lib/openai/models/conversations/item_retrieve_params.rb +36 -0
  54. data/lib/openai/models/conversations/lob_prob.rb +35 -0
  55. data/lib/openai/models/conversations/message.rb +115 -0
  56. data/lib/openai/models/conversations/output_text_content.rb +57 -0
  57. data/lib/openai/models/conversations/refusal_content.rb +26 -0
  58. data/lib/openai/models/conversations/summary_text_content.rb +23 -0
  59. data/lib/openai/models/conversations/text_content.rb +23 -0
  60. data/lib/openai/models/conversations/top_log_prob.rb +29 -0
  61. data/lib/openai/models/conversations/url_citation_body.rb +50 -0
  62. data/lib/openai/models/eval_create_params.rb +6 -20
  63. data/lib/openai/models/evals/create_eval_completions_run_data_source.rb +29 -53
  64. data/lib/openai/models/evals/create_eval_jsonl_run_data_source.rb +1 -3
  65. data/lib/openai/models/evals/run_cancel_response.rb +2 -2
  66. data/lib/openai/models/evals/run_create_params.rb +20 -56
  67. data/lib/openai/models/evals/run_create_response.rb +2 -2
  68. data/lib/openai/models/evals/run_list_response.rb +2 -2
  69. data/lib/openai/models/evals/run_retrieve_response.rb +2 -2
  70. data/lib/openai/models/fine_tuning/reinforcement_hyperparameters.rb +1 -4
  71. data/lib/openai/models/moderation.rb +5 -15
  72. data/lib/openai/models/responses/input_item_list_params.rb +1 -9
  73. data/lib/openai/models/responses/response.rb +28 -3
  74. data/lib/openai/models/responses/response_computer_tool_call.rb +2 -6
  75. data/lib/openai/models/responses/response_computer_tool_call_output_item.rb +1 -3
  76. data/lib/openai/models/responses/response_conversation_param.rb +20 -0
  77. data/lib/openai/models/responses/response_create_params.rb +38 -3
  78. data/lib/openai/models/responses/response_function_tool_call.rb +7 -5
  79. data/lib/openai/models/responses/response_function_web_search.rb +35 -1
  80. data/lib/openai/models/responses/response_includable.rb +2 -0
  81. data/lib/openai/models/responses/response_input_item.rb +2 -7
  82. data/lib/openai/models/responses/response_input_message_item.rb +1 -4
  83. data/lib/openai/models/responses/response_output_item.rb +1 -3
  84. data/lib/openai/models/responses/response_output_message.rb +1 -3
  85. data/lib/openai/models/responses/response_output_text.rb +10 -15
  86. data/lib/openai/models/responses/response_stream_event.rb +4 -16
  87. data/lib/openai/models/responses/response_text_delta_event.rb +1 -3
  88. data/lib/openai/models/responses/response_text_done_event.rb +1 -3
  89. data/lib/openai/models/responses/tool.rb +303 -35
  90. data/lib/openai/models.rb +2 -0
  91. data/lib/openai/resources/conversations/items.rb +141 -0
  92. data/lib/openai/resources/conversations.rb +112 -0
  93. data/lib/openai/resources/responses/input_items.rb +1 -3
  94. data/lib/openai/resources/responses.rb +8 -4
  95. data/lib/openai/version.rb +1 -1
  96. data/lib/openai.rb +31 -0
  97. data/rbi/openai/client.rbi +3 -0
  98. data/rbi/openai/errors.rbi +5 -5
  99. data/rbi/openai/internal/conversation_cursor_page.rbi +25 -0
  100. data/rbi/openai/models/conversations/computer_screenshot_content.rbi +60 -0
  101. data/rbi/openai/models/conversations/container_file_citation_body.rbi +82 -0
  102. data/rbi/openai/models/conversations/conversation.rbi +76 -0
  103. data/rbi/openai/models/conversations/conversation_create_params.rbi +144 -0
  104. data/rbi/openai/models/conversations/conversation_delete_params.rbi +32 -0
  105. data/rbi/openai/models/conversations/conversation_deleted.rbi +40 -0
  106. data/rbi/openai/models/conversations/conversation_deleted_resource.rbi +40 -0
  107. data/rbi/openai/models/conversations/conversation_item.rbi +835 -0
  108. data/rbi/openai/models/conversations/conversation_item_list.rbi +101 -0
  109. data/rbi/openai/models/conversations/conversation_retrieve_params.rbi +32 -0
  110. data/rbi/openai/models/conversations/conversation_update_params.rbi +56 -0
  111. data/rbi/openai/models/conversations/file_citation_body.rbi +61 -0
  112. data/rbi/openai/models/conversations/input_file_content.rbi +72 -0
  113. data/rbi/openai/models/conversations/input_image_content.rbi +113 -0
  114. data/rbi/openai/models/conversations/input_text_content.rbi +38 -0
  115. data/rbi/openai/models/conversations/item_create_params.rbi +150 -0
  116. data/rbi/openai/models/conversations/item_delete_params.rbi +40 -0
  117. data/rbi/openai/models/conversations/item_list_params.rbi +178 -0
  118. data/rbi/openai/models/conversations/item_retrieve_params.rbi +70 -0
  119. data/rbi/openai/models/conversations/lob_prob.rbi +50 -0
  120. data/rbi/openai/models/conversations/message.rbi +196 -0
  121. data/rbi/openai/models/conversations/output_text_content.rbi +110 -0
  122. data/rbi/openai/models/conversations/refusal_content.rbi +38 -0
  123. data/rbi/openai/models/conversations/summary_text_content.rbi +31 -0
  124. data/rbi/openai/models/conversations/text_content.rbi +28 -0
  125. data/rbi/openai/models/conversations/top_log_prob.rbi +41 -0
  126. data/rbi/openai/models/conversations/url_citation_body.rbi +74 -0
  127. data/rbi/openai/models/evals/create_eval_completions_run_data_source.rbi +33 -33
  128. data/rbi/openai/models/evals/run_cancel_response.rbi +2 -0
  129. data/rbi/openai/models/evals/run_create_params.rbi +4 -0
  130. data/rbi/openai/models/evals/run_create_response.rbi +2 -0
  131. data/rbi/openai/models/evals/run_list_response.rbi +2 -0
  132. data/rbi/openai/models/evals/run_retrieve_response.rbi +2 -0
  133. data/rbi/openai/models/responses/input_item_list_params.rbi +0 -11
  134. data/rbi/openai/models/responses/response.rbi +50 -0
  135. data/rbi/openai/models/responses/response_conversation_param.rbi +33 -0
  136. data/rbi/openai/models/responses/response_create_params.rbi +62 -0
  137. data/rbi/openai/models/responses/response_function_web_search.rbi +78 -2
  138. data/rbi/openai/models/responses/response_includable.rbi +2 -0
  139. data/rbi/openai/models/responses/tool.rbi +590 -31
  140. data/rbi/openai/models.rbi +2 -0
  141. data/rbi/openai/resources/conversations/items.rbi +154 -0
  142. data/rbi/openai/resources/conversations.rbi +110 -0
  143. data/rbi/openai/resources/responses/input_items.rbi +0 -3
  144. data/rbi/openai/resources/responses.rbi +32 -0
  145. data/sig/openai/client.rbs +2 -0
  146. data/sig/openai/internal/conversation_cursor_page.rbs +15 -0
  147. data/sig/openai/models/conversations/computer_screenshot_content.rbs +28 -0
  148. data/sig/openai/models/conversations/container_file_citation_body.rbs +47 -0
  149. data/sig/openai/models/conversations/conversation.rbs +37 -0
  150. data/sig/openai/models/conversations/conversation_create_params.rbs +33 -0
  151. data/sig/openai/models/conversations/conversation_delete_params.rbs +17 -0
  152. data/sig/openai/models/conversations/conversation_deleted.rbs +28 -0
  153. data/sig/openai/models/conversations/conversation_deleted_resource.rbs +28 -0
  154. data/sig/openai/models/conversations/conversation_item.rbs +403 -0
  155. data/sig/openai/models/conversations/conversation_item_list.rbs +44 -0
  156. data/sig/openai/models/conversations/conversation_retrieve_params.rbs +17 -0
  157. data/sig/openai/models/conversations/conversation_update_params.rbs +26 -0
  158. data/sig/openai/models/conversations/file_citation_body.rbs +37 -0
  159. data/sig/openai/models/conversations/input_file_content.rbs +41 -0
  160. data/sig/openai/models/conversations/input_image_content.rbs +49 -0
  161. data/sig/openai/models/conversations/input_text_content.rbs +17 -0
  162. data/sig/openai/models/conversations/item_create_params.rbs +37 -0
  163. data/sig/openai/models/conversations/item_delete_params.rbs +25 -0
  164. data/sig/openai/models/conversations/item_list_params.rbs +66 -0
  165. data/sig/openai/models/conversations/item_retrieve_params.rbs +37 -0
  166. data/sig/openai/models/conversations/lob_prob.rbs +37 -0
  167. data/sig/openai/models/conversations/message.rbs +95 -0
  168. data/sig/openai/models/conversations/output_text_content.rbs +52 -0
  169. data/sig/openai/models/conversations/refusal_content.rbs +17 -0
  170. data/sig/openai/models/conversations/summary_text_content.rbs +17 -0
  171. data/sig/openai/models/conversations/text_content.rbs +17 -0
  172. data/sig/openai/models/conversations/top_log_prob.rbs +28 -0
  173. data/sig/openai/models/conversations/url_citation_body.rbs +42 -0
  174. data/sig/openai/models/evals/create_eval_completions_run_data_source.rbs +22 -22
  175. data/sig/openai/models/responses/input_item_list_params.rbs +0 -7
  176. data/sig/openai/models/responses/response.rbs +15 -0
  177. data/sig/openai/models/responses/response_conversation_param.rbs +15 -0
  178. data/sig/openai/models/responses/response_create_params.rbs +14 -0
  179. data/sig/openai/models/responses/response_function_web_search.rbs +34 -3
  180. data/sig/openai/models/responses/tool.rbs +204 -18
  181. data/sig/openai/models.rbs +2 -0
  182. data/sig/openai/resources/conversations/items.rbs +38 -0
  183. data/sig/openai/resources/conversations.rbs +31 -0
  184. data/sig/openai/resources/responses/input_items.rbs +0 -1
  185. data/sig/openai/resources/responses.rbs +2 -0
  186. metadata +95 -2
@@ -37,9 +37,166 @@ module OpenAI
37
37
  # [custom tools](https://platform.openai.com/docs/guides/function-calling#custom-tools).
38
38
  variant :custom, -> { OpenAI::Responses::CustomTool }
39
39
 
40
+ # Search the Internet for sources related to the prompt. Learn more about the
41
+ # [web search tool](https://platform.openai.com/docs/guides/tools-web-search).
42
+ variant -> { OpenAI::Responses::Tool::WebSearchTool }
43
+
40
44
  # This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search).
41
45
  variant -> { OpenAI::Responses::WebSearchTool }
42
46
 
47
+ class WebSearchTool < OpenAI::Internal::Type::BaseModel
48
+ # @!attribute type
49
+ # The type of the web search tool. One of `web_search` or `web_search_2025_08_26`.
50
+ #
51
+ # @return [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::Type]
52
+ required :type, enum: -> { OpenAI::Responses::Tool::WebSearchTool::Type }
53
+
54
+ # @!attribute filters
55
+ # Filters for the search.
56
+ #
57
+ # @return [OpenAI::Models::Responses::Tool::WebSearchTool::Filters, nil]
58
+ optional :filters, -> { OpenAI::Responses::Tool::WebSearchTool::Filters }, nil?: true
59
+
60
+ # @!attribute search_context_size
61
+ # High level guidance for the amount of context window space to use for the
62
+ # search. One of `low`, `medium`, or `high`. `medium` is the default.
63
+ #
64
+ # @return [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::SearchContextSize, nil]
65
+ optional :search_context_size, enum: -> { OpenAI::Responses::Tool::WebSearchTool::SearchContextSize }
66
+
67
+ # @!attribute user_location
68
+ # The approximate location of the user.
69
+ #
70
+ # @return [OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation, nil]
71
+ optional :user_location, -> { OpenAI::Responses::Tool::WebSearchTool::UserLocation }, nil?: true
72
+
73
+ # @!method initialize(type:, filters: nil, search_context_size: nil, user_location: nil)
74
+ # Some parameter documentations has been truncated, see
75
+ # {OpenAI::Models::Responses::Tool::WebSearchTool} for more details.
76
+ #
77
+ # Search the Internet for sources related to the prompt. Learn more about the
78
+ # [web search tool](https://platform.openai.com/docs/guides/tools-web-search).
79
+ #
80
+ # @param type [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::Type] The type of the web search tool. One of `web_search` or `web_search_2025_08_26`.
81
+ #
82
+ # @param filters [OpenAI::Models::Responses::Tool::WebSearchTool::Filters, nil] Filters for the search.
83
+ #
84
+ # @param search_context_size [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::SearchContextSize] High level guidance for the amount of context window space to use for the search
85
+ #
86
+ # @param user_location [OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation, nil] The approximate location of the user.
87
+
88
+ # The type of the web search tool. One of `web_search` or `web_search_2025_08_26`.
89
+ #
90
+ # @see OpenAI::Models::Responses::Tool::WebSearchTool#type
91
+ module Type
92
+ extend OpenAI::Internal::Type::Enum
93
+
94
+ WEB_SEARCH = :web_search
95
+ WEB_SEARCH_2025_08_26 = :web_search_2025_08_26
96
+
97
+ # @!method self.values
98
+ # @return [Array<Symbol>]
99
+ end
100
+
101
+ # @see OpenAI::Models::Responses::Tool::WebSearchTool#filters
102
+ class Filters < OpenAI::Internal::Type::BaseModel
103
+ # @!attribute allowed_domains
104
+ # Allowed domains for the search. If not provided, all domains are allowed.
105
+ # Subdomains of the provided domains are allowed as well.
106
+ #
107
+ # Example: `["pubmed.ncbi.nlm.nih.gov"]`
108
+ #
109
+ # @return [Array<String>, nil]
110
+ optional :allowed_domains, OpenAI::Internal::Type::ArrayOf[String], nil?: true
111
+
112
+ # @!method initialize(allowed_domains: nil)
113
+ # Some parameter documentations has been truncated, see
114
+ # {OpenAI::Models::Responses::Tool::WebSearchTool::Filters} for more details.
115
+ #
116
+ # Filters for the search.
117
+ #
118
+ # @param allowed_domains [Array<String>, nil] Allowed domains for the search. If not provided, all domains are allowed.
119
+ end
120
+
121
+ # High level guidance for the amount of context window space to use for the
122
+ # search. One of `low`, `medium`, or `high`. `medium` is the default.
123
+ #
124
+ # @see OpenAI::Models::Responses::Tool::WebSearchTool#search_context_size
125
+ module SearchContextSize
126
+ extend OpenAI::Internal::Type::Enum
127
+
128
+ LOW = :low
129
+ MEDIUM = :medium
130
+ HIGH = :high
131
+
132
+ # @!method self.values
133
+ # @return [Array<Symbol>]
134
+ end
135
+
136
+ # @see OpenAI::Models::Responses::Tool::WebSearchTool#user_location
137
+ class UserLocation < OpenAI::Internal::Type::BaseModel
138
+ # @!attribute city
139
+ # Free text input for the city of the user, e.g. `San Francisco`.
140
+ #
141
+ # @return [String, nil]
142
+ optional :city, String, nil?: true
143
+
144
+ # @!attribute country
145
+ # The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of
146
+ # the user, e.g. `US`.
147
+ #
148
+ # @return [String, nil]
149
+ optional :country, String, nil?: true
150
+
151
+ # @!attribute region
152
+ # Free text input for the region of the user, e.g. `California`.
153
+ #
154
+ # @return [String, nil]
155
+ optional :region, String, nil?: true
156
+
157
+ # @!attribute timezone
158
+ # The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the
159
+ # user, e.g. `America/Los_Angeles`.
160
+ #
161
+ # @return [String, nil]
162
+ optional :timezone, String, nil?: true
163
+
164
+ # @!attribute type
165
+ # The type of location approximation. Always `approximate`.
166
+ #
167
+ # @return [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation::Type, nil]
168
+ optional :type, enum: -> { OpenAI::Responses::Tool::WebSearchTool::UserLocation::Type }
169
+
170
+ # @!method initialize(city: nil, country: nil, region: nil, timezone: nil, type: nil)
171
+ # Some parameter documentations has been truncated, see
172
+ # {OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation} for more details.
173
+ #
174
+ # The approximate location of the user.
175
+ #
176
+ # @param city [String, nil] Free text input for the city of the user, e.g. `San Francisco`.
177
+ #
178
+ # @param country [String, nil] The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of t
179
+ #
180
+ # @param region [String, nil] Free text input for the region of the user, e.g. `California`.
181
+ #
182
+ # @param timezone [String, nil] The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user
183
+ #
184
+ # @param type [Symbol, OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation::Type] The type of location approximation. Always `approximate`.
185
+
186
+ # The type of location approximation. Always `approximate`.
187
+ #
188
+ # @see OpenAI::Models::Responses::Tool::WebSearchTool::UserLocation#type
189
+ module Type
190
+ extend OpenAI::Internal::Type::Enum
191
+
192
+ APPROXIMATE = :approximate
193
+
194
+ # @!method self.values
195
+ # @return [Array<Symbol>]
196
+ end
197
+ end
198
+ end
199
+
43
200
  class Mcp < OpenAI::Internal::Type::BaseModel
44
201
  # @!attribute server_label
45
202
  # A label for this MCP server, used to identify it in tool calls.
@@ -47,12 +204,6 @@ module OpenAI
47
204
  # @return [String]
48
205
  required :server_label, String
49
206
 
50
- # @!attribute server_url
51
- # The URL for the MCP server.
52
- #
53
- # @return [String]
54
- required :server_url, String
55
-
56
207
  # @!attribute type
57
208
  # The type of the MCP tool. Always `mcp`.
58
209
  #
@@ -62,9 +213,37 @@ module OpenAI
62
213
  # @!attribute allowed_tools
63
214
  # List of allowed tool names or a filter object.
64
215
  #
65
- # @return [Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpAllowedToolsFilter, nil]
216
+ # @return [Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpToolFilter, nil]
66
217
  optional :allowed_tools, union: -> { OpenAI::Responses::Tool::Mcp::AllowedTools }, nil?: true
67
218
 
219
+ # @!attribute authorization
220
+ # An OAuth access token that can be used with a remote MCP server, either with a
221
+ # custom MCP server URL or a service connector. Your application must handle the
222
+ # OAuth authorization flow and provide the token here.
223
+ #
224
+ # @return [String, nil]
225
+ optional :authorization, String
226
+
227
+ # @!attribute connector_id
228
+ # Identifier for service connectors, like those available in ChatGPT. One of
229
+ # `server_url` or `connector_id` must be provided. Learn more about service
230
+ # connectors
231
+ # [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors).
232
+ #
233
+ # Currently supported `connector_id` values are:
234
+ #
235
+ # - Dropbox: `connector_dropbox`
236
+ # - Gmail: `connector_gmail`
237
+ # - Google Calendar: `connector_googlecalendar`
238
+ # - Google Drive: `connector_googledrive`
239
+ # - Microsoft Teams: `connector_microsoftteams`
240
+ # - Outlook Calendar: `connector_outlookcalendar`
241
+ # - Outlook Email: `connector_outlookemail`
242
+ # - SharePoint: `connector_sharepoint`
243
+ #
244
+ # @return [Symbol, OpenAI::Models::Responses::Tool::Mcp::ConnectorID, nil]
245
+ optional :connector_id, enum: -> { OpenAI::Responses::Tool::Mcp::ConnectorID }
246
+
68
247
  # @!attribute headers
69
248
  # Optional HTTP headers to send to the MCP server. Use for authentication or other
70
249
  # purposes.
@@ -84,7 +263,14 @@ module OpenAI
84
263
  # @return [String, nil]
85
264
  optional :server_description, String
86
265
 
87
- # @!method initialize(server_label:, server_url:, allowed_tools: nil, headers: nil, require_approval: nil, server_description: nil, type: :mcp)
266
+ # @!attribute server_url
267
+ # The URL for the MCP server. One of `server_url` or `connector_id` must be
268
+ # provided.
269
+ #
270
+ # @return [String, nil]
271
+ optional :server_url, String
272
+
273
+ # @!method initialize(server_label:, allowed_tools: nil, authorization: nil, connector_id: nil, headers: nil, require_approval: nil, server_description: nil, server_url: nil, type: :mcp)
88
274
  # Some parameter documentations has been truncated, see
89
275
  # {OpenAI::Models::Responses::Tool::Mcp} for more details.
90
276
  #
@@ -94,9 +280,11 @@ module OpenAI
94
280
  #
95
281
  # @param server_label [String] A label for this MCP server, used to identify it in tool calls.
96
282
  #
97
- # @param server_url [String] The URL for the MCP server.
283
+ # @param allowed_tools [Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpToolFilter, nil] List of allowed tool names or a filter object.
98
284
  #
99
- # @param allowed_tools [Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpAllowedToolsFilter, nil] List of allowed tool names or a filter object.
285
+ # @param authorization [String] An OAuth access token that can be used with a remote MCP server, either
286
+ #
287
+ # @param connector_id [Symbol, OpenAI::Models::Responses::Tool::Mcp::ConnectorID] Identifier for service connectors, like those available in ChatGPT. One of
100
288
  #
101
289
  # @param headers [Hash{Symbol=>String}, nil] Optional HTTP headers to send to the MCP server. Use for authentication
102
290
  #
@@ -104,6 +292,8 @@ module OpenAI
104
292
  #
105
293
  # @param server_description [String] Optional description of the MCP server, used to provide more context.
106
294
  #
295
+ # @param server_url [String] The URL for the MCP server. One of `server_url` or `connector_id` must be
296
+ #
107
297
  # @param type [Symbol, :mcp] The type of the MCP tool. Always `mcp`.
108
298
 
109
299
  # List of allowed tool names or a filter object.
@@ -116,34 +306,85 @@ module OpenAI
116
306
  variant -> { OpenAI::Models::Responses::Tool::Mcp::AllowedTools::StringArray }
117
307
 
118
308
  # A filter object to specify which tools are allowed.
119
- variant -> { OpenAI::Responses::Tool::Mcp::AllowedTools::McpAllowedToolsFilter }
309
+ variant -> { OpenAI::Responses::Tool::Mcp::AllowedTools::McpToolFilter }
310
+
311
+ class McpToolFilter < OpenAI::Internal::Type::BaseModel
312
+ # @!attribute read_only
313
+ # Indicates whether or not a tool modifies data or is read-only. If an MCP server
314
+ # is
315
+ # [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),
316
+ # it will match this filter.
317
+ #
318
+ # @return [Boolean, nil]
319
+ optional :read_only, OpenAI::Internal::Type::Boolean
120
320
 
121
- class McpAllowedToolsFilter < OpenAI::Internal::Type::BaseModel
122
321
  # @!attribute tool_names
123
322
  # List of allowed tool names.
124
323
  #
125
324
  # @return [Array<String>, nil]
126
325
  optional :tool_names, OpenAI::Internal::Type::ArrayOf[String]
127
326
 
128
- # @!method initialize(tool_names: nil)
327
+ # @!method initialize(read_only: nil, tool_names: nil)
328
+ # Some parameter documentations has been truncated, see
329
+ # {OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpToolFilter} for more
330
+ # details.
331
+ #
129
332
  # A filter object to specify which tools are allowed.
130
333
  #
334
+ # @param read_only [Boolean] Indicates whether or not a tool modifies data or is read-only. If an
335
+ #
131
336
  # @param tool_names [Array<String>] List of allowed tool names.
132
337
  end
133
338
 
134
339
  # @!method self.variants
135
- # @return [Array(Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpAllowedToolsFilter)]
340
+ # @return [Array(Array<String>, OpenAI::Models::Responses::Tool::Mcp::AllowedTools::McpToolFilter)]
136
341
 
137
342
  # @type [OpenAI::Internal::Type::Converter]
138
343
  StringArray = OpenAI::Internal::Type::ArrayOf[String]
139
344
  end
140
345
 
346
+ # Identifier for service connectors, like those available in ChatGPT. One of
347
+ # `server_url` or `connector_id` must be provided. Learn more about service
348
+ # connectors
349
+ # [here](https://platform.openai.com/docs/guides/tools-remote-mcp#connectors).
350
+ #
351
+ # Currently supported `connector_id` values are:
352
+ #
353
+ # - Dropbox: `connector_dropbox`
354
+ # - Gmail: `connector_gmail`
355
+ # - Google Calendar: `connector_googlecalendar`
356
+ # - Google Drive: `connector_googledrive`
357
+ # - Microsoft Teams: `connector_microsoftteams`
358
+ # - Outlook Calendar: `connector_outlookcalendar`
359
+ # - Outlook Email: `connector_outlookemail`
360
+ # - SharePoint: `connector_sharepoint`
361
+ #
362
+ # @see OpenAI::Models::Responses::Tool::Mcp#connector_id
363
+ module ConnectorID
364
+ extend OpenAI::Internal::Type::Enum
365
+
366
+ CONNECTOR_DROPBOX = :connector_dropbox
367
+ CONNECTOR_GMAIL = :connector_gmail
368
+ CONNECTOR_GOOGLECALENDAR = :connector_googlecalendar
369
+ CONNECTOR_GOOGLEDRIVE = :connector_googledrive
370
+ CONNECTOR_MICROSOFTTEAMS = :connector_microsoftteams
371
+ CONNECTOR_OUTLOOKCALENDAR = :connector_outlookcalendar
372
+ CONNECTOR_OUTLOOKEMAIL = :connector_outlookemail
373
+ CONNECTOR_SHAREPOINT = :connector_sharepoint
374
+
375
+ # @!method self.values
376
+ # @return [Array<Symbol>]
377
+ end
378
+
141
379
  # Specify which of the MCP server's tools require approval.
142
380
  #
143
381
  # @see OpenAI::Models::Responses::Tool::Mcp#require_approval
144
382
  module RequireApproval
145
383
  extend OpenAI::Internal::Type::Union
146
384
 
385
+ # Specify which of the MCP server's tools require approval. Can be
386
+ # `always`, `never`, or a filter object associated with tools
387
+ # that require approval.
147
388
  variant -> { OpenAI::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter }
148
389
 
149
390
  # Specify a single approval policy for all tools. One of `always` or
@@ -153,58 +394,85 @@ module OpenAI
153
394
 
154
395
  class McpToolApprovalFilter < OpenAI::Internal::Type::BaseModel
155
396
  # @!attribute always
156
- # A list of tools that always require approval.
397
+ # A filter object to specify which tools are allowed.
157
398
  #
158
399
  # @return [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always, nil]
159
- optional :always,
160
- -> {
161
- OpenAI::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always
162
- }
400
+ optional :always, -> { OpenAI::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always }
163
401
 
164
402
  # @!attribute never
165
- # A list of tools that never require approval.
403
+ # A filter object to specify which tools are allowed.
166
404
  #
167
405
  # @return [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never, nil]
168
- optional :never,
169
- -> {
170
- OpenAI::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never
171
- }
406
+ optional :never, -> { OpenAI::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never }
172
407
 
173
408
  # @!method initialize(always: nil, never: nil)
174
409
  # Some parameter documentations has been truncated, see
175
410
  # {OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter}
176
411
  # for more details.
177
412
  #
178
- # @param always [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always] A list of tools that always require approval.
413
+ # Specify which of the MCP server's tools require approval. Can be `always`,
414
+ # `never`, or a filter object associated with tools that require approval.
415
+ #
416
+ # @param always [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always] A filter object to specify which tools are allowed.
179
417
  #
180
- # @param never [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never] A list of tools that never require approval.
418
+ # @param never [OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never] A filter object to specify which tools are allowed.
181
419
 
182
420
  # @see OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter#always
183
421
  class Always < OpenAI::Internal::Type::BaseModel
422
+ # @!attribute read_only
423
+ # Indicates whether or not a tool modifies data or is read-only. If an MCP server
424
+ # is
425
+ # [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),
426
+ # it will match this filter.
427
+ #
428
+ # @return [Boolean, nil]
429
+ optional :read_only, OpenAI::Internal::Type::Boolean
430
+
184
431
  # @!attribute tool_names
185
- # List of tools that require approval.
432
+ # List of allowed tool names.
186
433
  #
187
434
  # @return [Array<String>, nil]
188
435
  optional :tool_names, OpenAI::Internal::Type::ArrayOf[String]
189
436
 
190
- # @!method initialize(tool_names: nil)
191
- # A list of tools that always require approval.
437
+ # @!method initialize(read_only: nil, tool_names: nil)
438
+ # Some parameter documentations has been truncated, see
439
+ # {OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Always}
440
+ # for more details.
441
+ #
442
+ # A filter object to specify which tools are allowed.
192
443
  #
193
- # @param tool_names [Array<String>] List of tools that require approval.
444
+ # @param read_only [Boolean] Indicates whether or not a tool modifies data or is read-only. If an
445
+ #
446
+ # @param tool_names [Array<String>] List of allowed tool names.
194
447
  end
195
448
 
196
449
  # @see OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter#never
197
450
  class Never < OpenAI::Internal::Type::BaseModel
451
+ # @!attribute read_only
452
+ # Indicates whether or not a tool modifies data or is read-only. If an MCP server
453
+ # is
454
+ # [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),
455
+ # it will match this filter.
456
+ #
457
+ # @return [Boolean, nil]
458
+ optional :read_only, OpenAI::Internal::Type::Boolean
459
+
198
460
  # @!attribute tool_names
199
- # List of tools that do not require approval.
461
+ # List of allowed tool names.
200
462
  #
201
463
  # @return [Array<String>, nil]
202
464
  optional :tool_names, OpenAI::Internal::Type::ArrayOf[String]
203
465
 
204
- # @!method initialize(tool_names: nil)
205
- # A list of tools that never require approval.
466
+ # @!method initialize(read_only: nil, tool_names: nil)
467
+ # Some parameter documentations has been truncated, see
468
+ # {OpenAI::Models::Responses::Tool::Mcp::RequireApproval::McpToolApprovalFilter::Never}
469
+ # for more details.
470
+ #
471
+ # A filter object to specify which tools are allowed.
472
+ #
473
+ # @param read_only [Boolean] Indicates whether or not a tool modifies data or is read-only. If an
206
474
  #
207
- # @param tool_names [Array<String>] List of tools that do not require approval.
475
+ # @param tool_names [Array<String>] List of allowed tool names.
208
476
  end
209
477
  end
210
478
 
@@ -546,7 +814,7 @@ module OpenAI
546
814
  end
547
815
 
548
816
  # @!method self.variants
549
- # @return [Array(OpenAI::Models::Responses::FunctionTool, OpenAI::Models::Responses::FileSearchTool, OpenAI::Models::Responses::ComputerTool, OpenAI::Models::Responses::Tool::Mcp, OpenAI::Models::Responses::Tool::CodeInterpreter, OpenAI::Models::Responses::Tool::ImageGeneration, OpenAI::Models::Responses::Tool::LocalShell, OpenAI::Models::Responses::CustomTool, OpenAI::Models::Responses::WebSearchTool)]
817
+ # @return [Array(OpenAI::Models::Responses::FunctionTool, OpenAI::Models::Responses::FileSearchTool, OpenAI::Models::Responses::ComputerTool, OpenAI::Models::Responses::Tool::Mcp, OpenAI::Models::Responses::Tool::CodeInterpreter, OpenAI::Models::Responses::Tool::ImageGeneration, OpenAI::Models::Responses::Tool::LocalShell, OpenAI::Models::Responses::CustomTool, OpenAI::Models::Responses::Tool::WebSearchTool, OpenAI::Models::Responses::WebSearchTool)]
550
818
  end
551
819
  end
552
820
  end
data/lib/openai/models.rb CHANGED
@@ -91,6 +91,8 @@ module OpenAI
91
91
 
92
92
  Containers = OpenAI::Models::Containers
93
93
 
94
+ Conversations = OpenAI::Models::Conversations
95
+
94
96
  CreateEmbeddingResponse = OpenAI::Models::CreateEmbeddingResponse
95
97
 
96
98
  CustomToolInputFormat = OpenAI::Models::CustomToolInputFormat
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenAI
4
+ module Resources
5
+ class Conversations
6
+ class Items
7
+ # Some parameter documentations has been truncated, see
8
+ # {OpenAI::Models::Conversations::ItemCreateParams} for more details.
9
+ #
10
+ # Create items in a conversation with the given ID.
11
+ #
12
+ # @overload create(conversation_id, items:, include: nil, request_options: {})
13
+ #
14
+ # @param conversation_id [String] Path param: The ID of the conversation to add the item to.
15
+ #
16
+ # @param items [Array<OpenAI::Models::Responses::EasyInputMessage, OpenAI::Models::Responses::ResponseInputItem::Message, OpenAI::Models::Responses::ResponseOutputMessage, OpenAI::Models::Responses::ResponseFileSearchToolCall, OpenAI::Models::Responses::ResponseComputerToolCall, OpenAI::Models::Responses::ResponseInputItem::ComputerCallOutput, OpenAI::Models::Responses::ResponseFunctionWebSearch, OpenAI::Models::Responses::ResponseFunctionToolCall, OpenAI::Models::Responses::ResponseInputItem::FunctionCallOutput, OpenAI::Models::Responses::ResponseReasoningItem, OpenAI::Models::Responses::ResponseInputItem::ImageGenerationCall, OpenAI::Models::Responses::ResponseCodeInterpreterToolCall, OpenAI::Models::Responses::ResponseInputItem::LocalShellCall, OpenAI::Models::Responses::ResponseInputItem::LocalShellCallOutput, OpenAI::Models::Responses::ResponseInputItem::McpListTools, OpenAI::Models::Responses::ResponseInputItem::McpApprovalRequest, OpenAI::Models::Responses::ResponseInputItem::McpApprovalResponse, OpenAI::Models::Responses::ResponseInputItem::McpCall, OpenAI::Models::Responses::ResponseCustomToolCallOutput, OpenAI::Models::Responses::ResponseCustomToolCall, OpenAI::Models::Responses::ResponseInputItem::ItemReference>] Body param: The items to add to the conversation. You may add up to 20 items at
17
+ #
18
+ # @param include [Array<Symbol, OpenAI::Models::Responses::ResponseIncludable>] Query param: Additional fields to include in the response. See the `include`
19
+ #
20
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
21
+ #
22
+ # @return [OpenAI::Models::Conversations::ConversationItemList]
23
+ #
24
+ # @see OpenAI::Models::Conversations::ItemCreateParams
25
+ def create(conversation_id, params)
26
+ parsed, options = OpenAI::Conversations::ItemCreateParams.dump_request(params)
27
+ query_params = [:include]
28
+ @client.request(
29
+ method: :post,
30
+ path: ["conversations/%1$s/items", conversation_id],
31
+ query: parsed.slice(*query_params),
32
+ body: parsed.except(*query_params),
33
+ model: OpenAI::Conversations::ConversationItemList,
34
+ options: options
35
+ )
36
+ end
37
+
38
+ # Some parameter documentations has been truncated, see
39
+ # {OpenAI::Models::Conversations::ItemRetrieveParams} for more details.
40
+ #
41
+ # Get a single item from a conversation with the given IDs.
42
+ #
43
+ # @overload retrieve(item_id, conversation_id:, include: nil, request_options: {})
44
+ #
45
+ # @param item_id [String] Path param: The ID of the item to retrieve.
46
+ #
47
+ # @param conversation_id [String] Path param: The ID of the conversation that contains the item.
48
+ #
49
+ # @param include [Array<Symbol, OpenAI::Models::Responses::ResponseIncludable>] Query param: Additional fields to include in the response. See the `include`
50
+ #
51
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
52
+ #
53
+ # @return [OpenAI::Models::Conversations::Message, OpenAI::Models::Responses::ResponseFunctionToolCallItem, OpenAI::Models::Responses::ResponseFunctionToolCallOutputItem, OpenAI::Models::Responses::ResponseFileSearchToolCall, OpenAI::Models::Responses::ResponseFunctionWebSearch, OpenAI::Models::Conversations::ConversationItem::ImageGenerationCall, OpenAI::Models::Responses::ResponseComputerToolCall, OpenAI::Models::Responses::ResponseComputerToolCallOutputItem, OpenAI::Models::Responses::ResponseReasoningItem, OpenAI::Models::Responses::ResponseCodeInterpreterToolCall, OpenAI::Models::Conversations::ConversationItem::LocalShellCall, OpenAI::Models::Conversations::ConversationItem::LocalShellCallOutput, OpenAI::Models::Conversations::ConversationItem::McpListTools, OpenAI::Models::Conversations::ConversationItem::McpApprovalRequest, OpenAI::Models::Conversations::ConversationItem::McpApprovalResponse, OpenAI::Models::Conversations::ConversationItem::McpCall, OpenAI::Models::Responses::ResponseCustomToolCall, OpenAI::Models::Responses::ResponseCustomToolCallOutput]
54
+ #
55
+ # @see OpenAI::Models::Conversations::ItemRetrieveParams
56
+ def retrieve(item_id, params)
57
+ parsed, options = OpenAI::Conversations::ItemRetrieveParams.dump_request(params)
58
+ conversation_id =
59
+ parsed.delete(:conversation_id) do
60
+ raise ArgumentError.new("missing required path argument #{_1}")
61
+ end
62
+ @client.request(
63
+ method: :get,
64
+ path: ["conversations/%1$s/items/%2$s", conversation_id, item_id],
65
+ query: parsed,
66
+ model: OpenAI::Conversations::ConversationItem,
67
+ options: options
68
+ )
69
+ end
70
+
71
+ # Some parameter documentations has been truncated, see
72
+ # {OpenAI::Models::Conversations::ItemListParams} for more details.
73
+ #
74
+ # List all items for a conversation with the given ID.
75
+ #
76
+ # @overload list(conversation_id, after: nil, include: nil, limit: nil, order: nil, request_options: {})
77
+ #
78
+ # @param conversation_id [String] The ID of the conversation to list items for.
79
+ #
80
+ # @param after [String] An item ID to list items after, used in pagination.
81
+ #
82
+ # @param include [Array<Symbol, OpenAI::Models::Responses::ResponseIncludable>] Specify additional output data to include in the model response. Currently
83
+ #
84
+ # @param limit [Integer] A limit on the number of objects to be returned. Limit can range between
85
+ #
86
+ # @param order [Symbol, OpenAI::Models::Conversations::ItemListParams::Order] The order to return the input items in. Default is `desc`.
87
+ #
88
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
89
+ #
90
+ # @return [OpenAI::Internal::ConversationCursorPage<OpenAI::Models::Conversations::Message, OpenAI::Models::Responses::ResponseFunctionToolCallItem, OpenAI::Models::Responses::ResponseFunctionToolCallOutputItem, OpenAI::Models::Responses::ResponseFileSearchToolCall, OpenAI::Models::Responses::ResponseFunctionWebSearch, OpenAI::Models::Conversations::ConversationItem::ImageGenerationCall, OpenAI::Models::Responses::ResponseComputerToolCall, OpenAI::Models::Responses::ResponseComputerToolCallOutputItem, OpenAI::Models::Responses::ResponseReasoningItem, OpenAI::Models::Responses::ResponseCodeInterpreterToolCall, OpenAI::Models::Conversations::ConversationItem::LocalShellCall, OpenAI::Models::Conversations::ConversationItem::LocalShellCallOutput, OpenAI::Models::Conversations::ConversationItem::McpListTools, OpenAI::Models::Conversations::ConversationItem::McpApprovalRequest, OpenAI::Models::Conversations::ConversationItem::McpApprovalResponse, OpenAI::Models::Conversations::ConversationItem::McpCall, OpenAI::Models::Responses::ResponseCustomToolCall, OpenAI::Models::Responses::ResponseCustomToolCallOutput>]
91
+ #
92
+ # @see OpenAI::Models::Conversations::ItemListParams
93
+ def list(conversation_id, params = {})
94
+ parsed, options = OpenAI::Conversations::ItemListParams.dump_request(params)
95
+ @client.request(
96
+ method: :get,
97
+ path: ["conversations/%1$s/items", conversation_id],
98
+ query: parsed,
99
+ page: OpenAI::Internal::ConversationCursorPage,
100
+ model: OpenAI::Conversations::ConversationItem,
101
+ options: options
102
+ )
103
+ end
104
+
105
+ # Delete an item from a conversation with the given IDs.
106
+ #
107
+ # @overload delete(item_id, conversation_id:, request_options: {})
108
+ #
109
+ # @param item_id [String] The ID of the item to delete.
110
+ #
111
+ # @param conversation_id [String] The ID of the conversation that contains the item.
112
+ #
113
+ # @param request_options [OpenAI::RequestOptions, Hash{Symbol=>Object}, nil]
114
+ #
115
+ # @return [OpenAI::Models::Conversations::Conversation]
116
+ #
117
+ # @see OpenAI::Models::Conversations::ItemDeleteParams
118
+ def delete(item_id, params)
119
+ parsed, options = OpenAI::Conversations::ItemDeleteParams.dump_request(params)
120
+ conversation_id =
121
+ parsed.delete(:conversation_id) do
122
+ raise ArgumentError.new("missing required path argument #{_1}")
123
+ end
124
+ @client.request(
125
+ method: :delete,
126
+ path: ["conversations/%1$s/items/%2$s", conversation_id, item_id],
127
+ model: OpenAI::Conversations::Conversation,
128
+ options: options
129
+ )
130
+ end
131
+
132
+ # @api private
133
+ #
134
+ # @param client [OpenAI::Client]
135
+ def initialize(client:)
136
+ @client = client
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end