@@ -200,9 +200,15 @@ extension OpenAIClient {
200200
201201 switch toolChoice {
202202 case . required:
203- try validateRequiredToolChoice ( requestTools)
203+ guard !requestTools. isEmpty else {
204+ throw AgentError . llmError ( . other( " OpenAI Chat toolChoice.required requires at least one tool " ) )
205+ }
204206 case let . function( name) :
205- try validateRequestedFunctionChoice ( name, functions: functions)
207+ guard functions. contains ( name) else {
208+ throw AgentError . llmError ( . other(
209+ " OpenAI Chat toolChoice.function requires tool ' \( name) ' in the request "
210+ ) )
211+ }
206212 case let . custom( name) :
207213 try validateRequestedCustomChoice ( name, customs: customs, capabilities: capabilities)
208214 case let . allowedTools( _, tools) :
@@ -214,6 +220,57 @@ extension OpenAIClient {
214220 return toolChoice
215221 }
216222
223+ private func validateRequestedCustomChoice(
224+ _ name: String ,
225+ customs: Set < String > ,
226+ capabilities: OpenAIChatCapabilities
227+ ) throws {
228+ guard capabilities. supportsCustomTools else {
229+ throw AgentError . llmError ( . featureUnsupported(
230+ provider: " openai-chat- \( capabilities. profile) " ,
231+ feature: " custom tool choice "
232+ ) )
233+ }
234+ guard customs. contains ( name) else {
235+ throw AgentError . llmError ( . other(
236+ " OpenAI Chat toolChoice.custom requires custom tool ' \( name) ' in the request "
237+ ) )
238+ }
239+ }
240+
241+ private func validateAllowedTools(
242+ _ tools: [ OpenAIChatAllowedTool ] ,
243+ functions: Set < String > ,
244+ customs: Set < String > ,
245+ capabilities: OpenAIChatCapabilities
246+ ) throws {
247+ guard capabilities. profile == . firstParty else {
248+ throw AgentError . llmError ( . featureUnsupported(
249+ provider: " openai-chat- \( capabilities. profile) " ,
250+ feature: " allowed tools "
251+ ) )
252+ }
253+ guard !tools. isEmpty else {
254+ throw AgentError . llmError ( . other( " OpenAI Chat allowed tools must not be empty " ) )
255+ }
256+ for tool in tools {
257+ switch tool {
258+ case let . function( name) :
259+ guard functions. contains ( name) else {
260+ throw AgentError . llmError ( . other(
261+ " OpenAI Chat allowed function tool ' \( name) ' is missing from the request "
262+ ) )
263+ }
264+ case let . custom( name) :
265+ guard customs. contains ( name) else {
266+ throw AgentError . llmError ( . other(
267+ " OpenAI Chat allowed custom tool ' \( name) ' is missing from the request "
268+ ) )
269+ }
270+ }
271+ }
272+ }
273+
217274 func buildURLRequest( _ request: ChatCompletionRequest ) throws -> URLRequest {
218275 let url = baseURL. appendingPathComponent ( chatCompletionPath)
219276 var headers : [ ( String , String ) ] = [ ]
0 commit comments