77module  ActiveAgent 
88  module  Providers 
99    module  OpenAI 
10+       # Base provider implementation for OpenAI API integration. 
11+       # 
12+       # This class serves as the foundation for OpenAI-based providers, handling 
13+       # message management, streaming responses, and function/tool callbacks. 
14+       # 
15+       # @abstract Subclass and override {#client_request_create} to implement specific provider behavior 
16+       # 
17+       # @example Basic usage 
18+       #   provider = BaseProvider.new( 
19+       #     stream_callback: ->(chunk) { puts chunk }, 
20+       #     function_callback: ->(name, **kwargs) { execute_function(name, kwargs) } 
21+       #   ) 
22+       #   response = provider.call 
23+       # 
24+       # @attr_internal request [ActiveAgent::Request] The current request being processed 
25+       # @attr_internal message_stack [Array] Stack of messages to be applied to the request 
26+       # @attr_internal stream_callback [Proc] Callback invoked for each streaming chunk 
27+       # @attr_internal stream_finished [Boolean] Flag indicating if streaming has completed 
28+       # @attr_internal function_callback [Proc] Callback for handling function/tool calls 
29+       # 
30+       # @see ActiveAgent::Providers::BaseProvider 
1031      class  BaseProvider  < ActiveAgent ::Providers ::BaseProvider 
11-         attr_internal  :stream_callback ,  :function_callback 
32+         attr_internal  :request ,  :message_stack , 
33+                       :stream_callback ,  :stream_finished , 
34+                       :function_callback 
1235
1336        def  initialize ( kwargs  =  { } ) 
1437          self . stream_callback    =  kwargs . delete ( :stream_callback ) 
1538          self . function_callback  =  kwargs . delete ( :function_callback ) 
39+           self . message_stack      =  [ ] 
1640
1741          super ( kwargs ) 
1842        end 
1943
20-         # @return [OpenAI::Client] 
21-         def  client 
22-           ::OpenAI ::Client . new ( options . to_hc ) 
23-         end 
24- 
44+         # Main entry point for executing the provider call. 
45+         # 
46+         # This method orchestrates the provider execution by wrapping the prompt 
47+         # resolution in error handling logic. It serves as the primary interface 
48+         # for initiating provider operations. 
49+         # 
50+         # @return [ActiveAgent::Providers::Response] The result of the prompt resolution 
51+         # @raise [StandardError] Any errors that occur during execution will be 
52+         #   handled by the error handling wrapper 
53+         # 
54+         # @example Execute the provider call 
55+         #   provider.call 
56+         #   # => <result of prompt resolution> 
2557        def  call 
2658          with_error_handling  do 
2759            resolve_prompt 
2860          end 
2961        end 
3062
63+         # @return [OpenAI::Client] a configured OpenAI client instance 
64+         def  client 
65+           ::OpenAI ::Client . new ( options . to_hc ) 
66+         end 
67+ 
3168        # @return [String] Name of service, e.g., Anthropic 
3269        def  service_name  =  "OpenAI" 
3370
@@ -36,11 +73,62 @@ def service_name = "OpenAI"
3673        # @return [Class] The Options class for the specific provider, e.g., Anthropic::Options 
3774        def  options_type  =  OpenAI ::Options 
3875
76+         # @return response [ActiveAgent::Providers::Response] 
77+         def  resolve_prompt 
78+           # Apply Tool/Function Messages and Reset Processing Buffer 
79+           self . request . messages  =  [  *request . messages ,  *message_stack  ] 
80+           self . message_stack     =  [ ] 
81+           # @todo Validate Request 
82+ 
83+           ## Prepare Executation Environment 
84+           parameters  =  request . to_hc 
85+           if  request . stream 
86+             parameters [ :stream ]   =  process_stream 
87+             self . stream_finished  =  false 
88+           end 
89+ 
90+           ## Execute 
91+           api_response  =  client_request_create ( parameters :) 
92+           process_finished ( api_response . presence &.deep_symbolize_keys ) 
93+         end 
94+ 
95+         def  client_request_create ( parameters :) 
96+           fail ( NotImplementedError ) 
97+         end 
98+ 
99+         # @return [Proc] a Proc that accepts an API response chunk and processes it 
100+         # @see #process_stream_chunk 
101+         # 
102+         # @example 
103+         #   stream_processor = process_stream 
104+         #   api_client.stream(params, &stream_processor) 
39105        def  process_stream 
40106          proc  do  |api_response_chunk |
41107            process_stream_chunk ( api_response_chunk . deep_symbolize_keys ) 
42108          end 
43109        end 
110+ 
111+         # Processes a tool call function from the API response. 
112+         # 
113+         # This method extracts the function name and arguments from an API function call, 
114+         # parses the arguments as JSON, and invokes the function callback with the parsed parameters. 
115+         # 
116+         # @param api_function_call [Hash] The function call data from the API response 
117+         # @option api_function_call [String] :name The name of the function to call 
118+         # @option api_function_call [String] :arguments JSON string containing the function arguments 
119+         # 
120+         # @return [Object] The result of the function callback invocation 
121+         # 
122+         # @example Processing a tool call 
123+         #   api_call = { name: "get_weather", arguments: '{"location":"NYC"}' } 
124+         #   process_tool_call_function(api_call) 
125+         #   # => calls function_callback.call("get_weather", location: "NYC") 
126+         def  process_tool_call_function ( api_function_call ) 
127+           name    =  api_function_call [ :name ] 
128+           kwargs  =  JSON . parse ( api_function_call [ :arguments ] ,  symbolize_names : true )  if  api_function_call [ :arguments ] 
129+ 
130+           function_callback . call ( name ,  **kwargs ) 
131+         end 
44132      end 
45133    end 
46134  end 
0 commit comments