activeagent 1.0.0.rc1 → 1.0.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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/lib/active_agent/providers/_base_provider.rb +92 -82
  4. data/lib/active_agent/providers/anthropic/_types.rb +2 -2
  5. data/lib/active_agent/providers/anthropic/request.rb +135 -81
  6. data/lib/active_agent/providers/anthropic/transforms.rb +353 -0
  7. data/lib/active_agent/providers/anthropic_provider.rb +96 -53
  8. data/lib/active_agent/providers/common/messages/_types.rb +37 -1
  9. data/lib/active_agent/providers/common/responses/base.rb +118 -70
  10. data/lib/active_agent/providers/common/usage.rb +385 -0
  11. data/lib/active_agent/providers/concerns/instrumentation.rb +263 -0
  12. data/lib/active_agent/providers/log_subscriber.rb +64 -246
  13. data/lib/active_agent/providers/mock_provider.rb +23 -23
  14. data/lib/active_agent/providers/ollama/chat/request.rb +214 -35
  15. data/lib/active_agent/providers/ollama/chat/transforms.rb +135 -0
  16. data/lib/active_agent/providers/ollama/embedding/request.rb +160 -47
  17. data/lib/active_agent/providers/ollama/embedding/transforms.rb +160 -0
  18. data/lib/active_agent/providers/ollama_provider.rb +0 -1
  19. data/lib/active_agent/providers/open_ai/_base.rb +3 -2
  20. data/lib/active_agent/providers/open_ai/chat/_types.rb +13 -1
  21. data/lib/active_agent/providers/open_ai/chat/request.rb +132 -186
  22. data/lib/active_agent/providers/open_ai/chat/transforms.rb +364 -0
  23. data/lib/active_agent/providers/open_ai/chat_provider.rb +57 -36
  24. data/lib/active_agent/providers/open_ai/embedding/_types.rb +13 -2
  25. data/lib/active_agent/providers/open_ai/embedding/request.rb +38 -70
  26. data/lib/active_agent/providers/open_ai/embedding/transforms.rb +88 -0
  27. data/lib/active_agent/providers/open_ai/responses/_types.rb +1 -7
  28. data/lib/active_agent/providers/open_ai/responses/request.rb +100 -134
  29. data/lib/active_agent/providers/open_ai/responses/transforms.rb +228 -0
  30. data/lib/active_agent/providers/open_ai/responses_provider.rb +77 -30
  31. data/lib/active_agent/providers/open_ai_provider.rb +0 -3
  32. data/lib/active_agent/providers/open_router/_types.rb +27 -1
  33. data/lib/active_agent/providers/open_router/options.rb +49 -1
  34. data/lib/active_agent/providers/open_router/request.rb +232 -66
  35. data/lib/active_agent/providers/open_router/requests/_types.rb +0 -1
  36. data/lib/active_agent/providers/open_router/requests/messages/_types.rb +37 -40
  37. data/lib/active_agent/providers/open_router/requests/messages/content/file.rb +19 -3
  38. data/lib/active_agent/providers/open_router/requests/messages/content/files/details.rb +15 -4
  39. data/lib/active_agent/providers/open_router/requests/plugin.rb +19 -3
  40. data/lib/active_agent/providers/open_router/requests/plugins/pdf_config.rb +30 -8
  41. data/lib/active_agent/providers/open_router/requests/prediction.rb +17 -0
  42. data/lib/active_agent/providers/open_router/requests/provider_preferences/max_price.rb +41 -7
  43. data/lib/active_agent/providers/open_router/requests/provider_preferences.rb +60 -19
  44. data/lib/active_agent/providers/open_router/requests/response_format.rb +30 -2
  45. data/lib/active_agent/providers/open_router/transforms.rb +134 -0
  46. data/lib/active_agent/providers/open_router_provider.rb +9 -0
  47. data/lib/active_agent/version.rb +1 -1
  48. metadata +15 -159
  49. data/lib/active_agent/generation_provider/open_router/types.rb +0 -505
  50. data/lib/active_agent/generation_provider/xai_provider.rb +0 -144
  51. data/lib/active_agent/providers/anthropic/requests/_types.rb +0 -190
  52. data/lib/active_agent/providers/anthropic/requests/container_params.rb +0 -19
  53. data/lib/active_agent/providers/anthropic/requests/content/base.rb +0 -21
  54. data/lib/active_agent/providers/anthropic/requests/content/sources/base.rb +0 -22
  55. data/lib/active_agent/providers/anthropic/requests/context_management_config.rb +0 -18
  56. data/lib/active_agent/providers/anthropic/requests/messages/_types.rb +0 -189
  57. data/lib/active_agent/providers/anthropic/requests/messages/assistant.rb +0 -23
  58. data/lib/active_agent/providers/anthropic/requests/messages/base.rb +0 -63
  59. data/lib/active_agent/providers/anthropic/requests/messages/content/_types.rb +0 -143
  60. data/lib/active_agent/providers/anthropic/requests/messages/content/base.rb +0 -21
  61. data/lib/active_agent/providers/anthropic/requests/messages/content/document.rb +0 -26
  62. data/lib/active_agent/providers/anthropic/requests/messages/content/image.rb +0 -23
  63. data/lib/active_agent/providers/anthropic/requests/messages/content/redacted_thinking.rb +0 -21
  64. data/lib/active_agent/providers/anthropic/requests/messages/content/search_result.rb +0 -27
  65. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/_types.rb +0 -171
  66. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/base.rb +0 -22
  67. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_base64.rb +0 -25
  68. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_file.rb +0 -23
  69. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_text.rb +0 -25
  70. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_url.rb +0 -23
  71. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_base64.rb +0 -27
  72. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_file.rb +0 -23
  73. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_url.rb +0 -23
  74. data/lib/active_agent/providers/anthropic/requests/messages/content/text.rb +0 -22
  75. data/lib/active_agent/providers/anthropic/requests/messages/content/thinking.rb +0 -23
  76. data/lib/active_agent/providers/anthropic/requests/messages/content/tool_result.rb +0 -24
  77. data/lib/active_agent/providers/anthropic/requests/messages/content/tool_use.rb +0 -28
  78. data/lib/active_agent/providers/anthropic/requests/messages/user.rb +0 -21
  79. data/lib/active_agent/providers/anthropic/requests/metadata.rb +0 -18
  80. data/lib/active_agent/providers/anthropic/requests/response_format.rb +0 -22
  81. data/lib/active_agent/providers/anthropic/requests/thinking_config/_types.rb +0 -60
  82. data/lib/active_agent/providers/anthropic/requests/thinking_config/base.rb +0 -20
  83. data/lib/active_agent/providers/anthropic/requests/thinking_config/disabled.rb +0 -16
  84. data/lib/active_agent/providers/anthropic/requests/thinking_config/enabled.rb +0 -20
  85. data/lib/active_agent/providers/anthropic/requests/tool_choice/_types.rb +0 -78
  86. data/lib/active_agent/providers/anthropic/requests/tool_choice/any.rb +0 -17
  87. data/lib/active_agent/providers/anthropic/requests/tool_choice/auto.rb +0 -17
  88. data/lib/active_agent/providers/anthropic/requests/tool_choice/base.rb +0 -20
  89. data/lib/active_agent/providers/anthropic/requests/tool_choice/none.rb +0 -16
  90. data/lib/active_agent/providers/anthropic/requests/tool_choice/tool.rb +0 -20
  91. data/lib/active_agent/providers/ollama/chat/requests/_types.rb +0 -3
  92. data/lib/active_agent/providers/ollama/chat/requests/messages/_types.rb +0 -116
  93. data/lib/active_agent/providers/ollama/chat/requests/messages/assistant.rb +0 -19
  94. data/lib/active_agent/providers/ollama/chat/requests/messages/user.rb +0 -19
  95. data/lib/active_agent/providers/ollama/embedding/requests/_types.rb +0 -83
  96. data/lib/active_agent/providers/ollama/embedding/requests/options.rb +0 -104
  97. data/lib/active_agent/providers/open_ai/chat/requests/_types.rb +0 -229
  98. data/lib/active_agent/providers/open_ai/chat/requests/audio.rb +0 -24
  99. data/lib/active_agent/providers/open_ai/chat/requests/messages/_types.rb +0 -123
  100. data/lib/active_agent/providers/open_ai/chat/requests/messages/assistant.rb +0 -42
  101. data/lib/active_agent/providers/open_ai/chat/requests/messages/base.rb +0 -78
  102. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/_types.rb +0 -133
  103. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/audio.rb +0 -35
  104. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/base.rb +0 -24
  105. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/file.rb +0 -26
  106. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/_types.rb +0 -60
  107. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/details.rb +0 -41
  108. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/image.rb +0 -37
  109. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/refusal.rb +0 -25
  110. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/text.rb +0 -25
  111. data/lib/active_agent/providers/open_ai/chat/requests/messages/developer.rb +0 -25
  112. data/lib/active_agent/providers/open_ai/chat/requests/messages/function.rb +0 -25
  113. data/lib/active_agent/providers/open_ai/chat/requests/messages/system.rb +0 -25
  114. data/lib/active_agent/providers/open_ai/chat/requests/messages/tool.rb +0 -26
  115. data/lib/active_agent/providers/open_ai/chat/requests/messages/user.rb +0 -32
  116. data/lib/active_agent/providers/open_ai/chat/requests/prediction.rb +0 -46
  117. data/lib/active_agent/providers/open_ai/chat/requests/response_format.rb +0 -53
  118. data/lib/active_agent/providers/open_ai/chat/requests/stream_options.rb +0 -24
  119. data/lib/active_agent/providers/open_ai/chat/requests/tool_choice.rb +0 -26
  120. data/lib/active_agent/providers/open_ai/chat/requests/tools/_types.rb +0 -5
  121. data/lib/active_agent/providers/open_ai/chat/requests/tools/base.rb +0 -22
  122. data/lib/active_agent/providers/open_ai/chat/requests/tools/custom_tool.rb +0 -41
  123. data/lib/active_agent/providers/open_ai/chat/requests/tools/function_tool.rb +0 -51
  124. data/lib/active_agent/providers/open_ai/chat/requests/web_search_options.rb +0 -45
  125. data/lib/active_agent/providers/open_ai/embedding/requests/_types.rb +0 -49
  126. data/lib/active_agent/providers/open_ai/responses/requests/_types.rb +0 -231
  127. data/lib/active_agent/providers/open_ai/responses/requests/conversation.rb +0 -23
  128. data/lib/active_agent/providers/open_ai/responses/requests/inputs/_types.rb +0 -264
  129. data/lib/active_agent/providers/open_ai/responses/requests/inputs/assistant_message.rb +0 -22
  130. data/lib/active_agent/providers/open_ai/responses/requests/inputs/base.rb +0 -89
  131. data/lib/active_agent/providers/open_ai/responses/requests/inputs/code_interpreter_tool_call.rb +0 -30
  132. data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call.rb +0 -28
  133. data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call_output.rb +0 -33
  134. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/_types.rb +0 -207
  135. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/base.rb +0 -22
  136. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_audio.rb +0 -26
  137. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_file.rb +0 -28
  138. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_image.rb +0 -28
  139. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_text.rb +0 -25
  140. data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call.rb +0 -28
  141. data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call_output.rb +0 -27
  142. data/lib/active_agent/providers/open_ai/responses/requests/inputs/developer_message.rb +0 -20
  143. data/lib/active_agent/providers/open_ai/responses/requests/inputs/file_search_tool_call.rb +0 -25
  144. data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_call_output.rb +0 -32
  145. data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_tool_call.rb +0 -28
  146. data/lib/active_agent/providers/open_ai/responses/requests/inputs/image_gen_tool_call.rb +0 -27
  147. data/lib/active_agent/providers/open_ai/responses/requests/inputs/input_message.rb +0 -31
  148. data/lib/active_agent/providers/open_ai/responses/requests/inputs/item_reference.rb +0 -23
  149. data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call.rb +0 -26
  150. data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call_output.rb +0 -33
  151. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_request.rb +0 -30
  152. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_response.rb +0 -28
  153. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_list_tools.rb +0 -29
  154. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_tool_call.rb +0 -35
  155. data/lib/active_agent/providers/open_ai/responses/requests/inputs/output_message.rb +0 -35
  156. data/lib/active_agent/providers/open_ai/responses/requests/inputs/reasoning.rb +0 -33
  157. data/lib/active_agent/providers/open_ai/responses/requests/inputs/system_message.rb +0 -20
  158. data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_call_base.rb +0 -27
  159. data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_message.rb +0 -23
  160. data/lib/active_agent/providers/open_ai/responses/requests/inputs/user_message.rb +0 -20
  161. data/lib/active_agent/providers/open_ai/responses/requests/inputs/web_search_tool_call.rb +0 -24
  162. data/lib/active_agent/providers/open_ai/responses/requests/prompt_reference.rb +0 -23
  163. data/lib/active_agent/providers/open_ai/responses/requests/reasoning.rb +0 -23
  164. data/lib/active_agent/providers/open_ai/responses/requests/stream_options.rb +0 -20
  165. data/lib/active_agent/providers/open_ai/responses/requests/text/_types.rb +0 -89
  166. data/lib/active_agent/providers/open_ai/responses/requests/text/base.rb +0 -22
  167. data/lib/active_agent/providers/open_ai/responses/requests/text/json_object.rb +0 -20
  168. data/lib/active_agent/providers/open_ai/responses/requests/text/json_schema.rb +0 -48
  169. data/lib/active_agent/providers/open_ai/responses/requests/text/plain.rb +0 -20
  170. data/lib/active_agent/providers/open_ai/responses/requests/text.rb +0 -41
  171. data/lib/active_agent/providers/open_ai/responses/requests/tool_choice.rb +0 -26
  172. data/lib/active_agent/providers/open_ai/responses/requests/tools/_types.rb +0 -112
  173. data/lib/active_agent/providers/open_ai/responses/requests/tools/base.rb +0 -25
  174. data/lib/active_agent/providers/open_ai/responses/requests/tools/code_interpreter_tool.rb +0 -23
  175. data/lib/active_agent/providers/open_ai/responses/requests/tools/computer_tool.rb +0 -27
  176. data/lib/active_agent/providers/open_ai/responses/requests/tools/custom_tool.rb +0 -28
  177. data/lib/active_agent/providers/open_ai/responses/requests/tools/file_search_tool.rb +0 -27
  178. data/lib/active_agent/providers/open_ai/responses/requests/tools/function_tool.rb +0 -29
  179. data/lib/active_agent/providers/open_ai/responses/requests/tools/image_generation_tool.rb +0 -37
  180. data/lib/active_agent/providers/open_ai/responses/requests/tools/local_shell_tool.rb +0 -21
  181. data/lib/active_agent/providers/open_ai/responses/requests/tools/mcp_tool.rb +0 -41
  182. data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_preview_tool.rb +0 -24
  183. data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_tool.rb +0 -25
  184. data/lib/active_agent/providers/open_ai/schema.yml +0 -65937
  185. data/lib/active_agent/providers/open_router/requests/message.rb +0 -1
  186. data/lib/active_agent/providers/open_router/requests/messages/assistant.rb +0 -20
  187. data/lib/active_agent/providers/open_router/requests/messages/user.rb +0 -30
@@ -4,100 +4,88 @@ require "active_support/log_subscriber"
4
4
 
5
5
  module ActiveAgent
6
6
  module Providers
7
- # Log subscriber for ActiveAgent provider operations.
7
+ # Logs provider operations via ActiveSupport::Notifications events.
8
8
  #
9
- # This subscriber listens to ActiveSupport::Notifications events published
10
- # during provider operations and logs them in a consistent, configurable format.
11
- #
12
- # Events are automatically instrumented in the providers and can be customized
13
- # or disabled through log level configuration.
9
+ # Subscribes to instrumented provider events and formats them consistently.
10
+ # Customize by subclassing and attaching your subscriber, or adjust log levels.
14
11
  #
15
12
  # @example Custom log formatting
16
- # class MyLogSubscriber < ActiveAgent::LogSubscriber
17
- # def prompt_start(event)
18
- # info "🚀 Starting prompt: #{event.payload[:provider]}"
13
+ # class MyLogSubscriber < ActiveAgent::Providers::LogSubscriber
14
+ # def prompt(event)
15
+ # info "🚀 #{event.payload[:provider_module]}: #{event.duration}ms"
19
16
  # end
20
17
  # end
21
18
  #
22
- # ActiveAgent::LogSubscriber.detach_from :active_agent_provider
23
- # MyLogSubscriber.attach_to :active_agent_provider
19
+ # ActiveAgent::Providers::LogSubscriber.detach_from :active_agent
20
+ # MyLogSubscriber.attach_to :active_agent
24
21
  class LogSubscriber < ActiveSupport::LogSubscriber
25
22
  # self.namespace = "active_agent" # Rails 8.1
26
23
 
27
- # Logs the start of a prompt request
24
+ # Logs completed prompt with model, message count, token usage, and duration.
28
25
  #
29
26
  # @param event [ActiveSupport::Notifications::Event]
30
- def prompt_start(event)
27
+ # @return [void]
28
+ def prompt(event)
31
29
  trace_id = event.payload[:trace_id]
32
30
  provider_module = event.payload[:provider_module]
31
+ model = event.payload[:model]
32
+ message_count = event.payload[:message_count]
33
+ stream = event.payload[:stream]
34
+ usage = event.payload[:usage]
35
+ finish_reason = event.payload[:finish_reason]
36
+ duration = event.duration.round(1)
33
37
 
34
38
  debug do
35
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Starting prompt request"
36
- end
37
- end
38
- # event_log_level :prompt_start, :debug # Rails 8.1
39
+ parts = [ "[#{trace_id}]", "[ActiveAgent]", "[#{provider_module}]" ]
40
+ parts << "Prompt completed:"
41
+ parts << "model=#{model}" if model
42
+ parts << "messages=#{message_count}"
43
+ parts << "stream=#{stream}"
39
44
 
40
- # Logs the start of an embedding request
41
- #
42
- # @param event [ActiveSupport::Notifications::Event]
43
- def embed_start(event)
44
- trace_id = event.payload[:trace_id]
45
- provider_module = event.payload[:provider_module]
46
-
47
- debug do
48
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Starting embed request"
49
- end
50
- end
51
- # event_log_level :embed_start, :debug # Rails 8.1
45
+ if usage
46
+ tokens = "tokens=#{usage[:input_tokens]}/#{usage[:output_tokens]}"
47
+ tokens += " (cached: #{usage[:cached_tokens]})" if usage[:cached_tokens]&.positive?
48
+ tokens += " (reasoning: #{usage[:reasoning_tokens]})" if usage[:reasoning_tokens]&.positive?
49
+ parts << tokens
50
+ end
52
51
 
53
- # Logs request preparation details
54
- #
55
- # @param event [ActiveSupport::Notifications::Event]
56
- def request_prepared(event)
57
- trace_id = event.payload[:trace_id]
58
- provider_module = event.payload[:provider_module]
59
- message_count = event.payload[:message_count]
52
+ parts << "finish=#{finish_reason}" if finish_reason
53
+ parts << "#{duration}ms"
60
54
 
61
- debug do
62
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Prepared request with #{message_count} message(s)"
55
+ parts.join(" ")
63
56
  end
64
57
  end
65
- # event_log_level :request_prepared, :debug # Rails 8.1
58
+ # event_log_level :prompt, :debug # Rails 8.1
66
59
 
67
- # Logs API call execution
60
+ # Logs completed embedding with model, input size, and token usage.
68
61
  #
69
62
  # @param event [ActiveSupport::Notifications::Event]
70
- def api_call(event)
71
- return unless logger.debug?
72
-
63
+ # @return [void]
64
+ def embed(event)
73
65
  trace_id = event.payload[:trace_id]
74
66
  provider_module = event.payload[:provider_module]
75
- streaming = event.payload[:streaming]
67
+ model = event.payload[:model]
68
+ input_size = event.payload[:input_size]
69
+ embedding_count = event.payload[:embedding_count]
70
+ usage = event.payload[:usage]
76
71
  duration = event.duration.round(1)
77
72
 
78
73
  debug do
79
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] API call completed in #{duration}ms (streaming: #{streaming})"
80
- end
81
- end
82
- # event_log_level :api_call, :debug # Rails 8.1
74
+ parts = [ "[#{trace_id}]", "[ActiveAgent]", "[#{provider_module}]" ]
75
+ parts << "Embed completed:"
76
+ parts << "model=#{model}" if model
77
+ parts << "inputs=#{input_size}" if input_size
78
+ parts << "embeddings=#{embedding_count}" if embedding_count
79
+ parts << "tokens=#{usage[:input_tokens]}" if usage
80
+ parts << "#{duration}ms"
83
81
 
84
- # Logs embed API call execution
85
- #
86
- # @param event [ActiveSupport::Notifications::Event]
87
- def embed_call(event)
88
- trace_id = event.payload[:trace_id]
89
- provider_module = event.payload[:provider_module]
90
- duration = event.duration.round(1)
91
-
92
- debug do
93
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Embed API call completed in #{duration}ms"
82
+ parts.join(" ")
94
83
  end
95
84
  end
96
- # event_log_level :embed_call, :debug # Rails 8.1
85
+ # event_log_level :embed, :debug # Rails 8.1
97
86
 
98
- # Logs stream opening
99
- #
100
87
  # @param event [ActiveSupport::Notifications::Event]
88
+ # @return [void]
101
89
  def stream_open(event)
102
90
  trace_id = event.payload[:trace_id]
103
91
  provider_module = event.payload[:provider_module]
@@ -108,9 +96,8 @@ module ActiveAgent
108
96
  end
109
97
  # event_log_level :stream_open, :debug # Rails 8.1
110
98
 
111
- # Logs stream closing
112
- #
113
99
  # @param event [ActiveSupport::Notifications::Event]
100
+ # @return [void]
114
101
  def stream_close(event)
115
102
  trace_id = event.payload[:trace_id]
116
103
  provider_module = event.payload[:provider_module]
@@ -121,210 +108,41 @@ module ActiveAgent
121
108
  end
122
109
  # event_log_level :stream_close, :debug # Rails 8.1
123
110
 
124
- # Logs message extraction from API response
125
- #
126
111
  # @param event [ActiveSupport::Notifications::Event]
127
- def messages_extracted(event)
128
- trace_id = event.payload[:trace_id]
129
- provider_module = event.payload[:provider_module]
130
- message_count = event.payload[:message_count]
131
-
132
- debug do
133
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Extracted #{message_count} message(s) from API response"
134
- end
135
- end
136
- # event_log_level :messages_extracted, :debug # Rails 8.1
137
-
138
- # Logs tool/function call processing
139
- #
140
- # @param event [ActiveSupport::Notifications::Event]
141
- def tool_calls_processing(event)
142
- trace_id = event.payload[:trace_id]
143
- provider_module = event.payload[:provider_module]
144
- tool_count = event.payload[:tool_count]
145
-
146
- debug do
147
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Processing #{tool_count} tool call(s)"
148
- end
149
- end
150
- # event_log_level :tool_calls_processing, :debug # Rails 8.1
151
-
152
- # Logs multi-turn conversation continuation
153
- #
154
- # @param event [ActiveSupport::Notifications::Event]
155
- def multi_turn_continue(event)
156
- trace_id = event.payload[:trace_id]
157
- provider_module = event.payload[:provider_module]
158
-
159
- debug do
160
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Continuing multi-turn conversation after tool execution"
161
- end
162
- end
163
- # event_log_level :multi_turn_continue, :debug # Rails 8.1
164
-
165
- # Logs prompt completion
166
- #
167
- # @param event [ActiveSupport::Notifications::Event]
168
- def prompt_complete(event)
169
- trace_id = event.payload[:trace_id]
170
- provider_module = event.payload[:provider_module]
171
- message_count = event.payload[:message_count]
172
- duration = event.duration.round(1)
173
-
174
- debug do
175
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Prompt completed with #{message_count} message(s) in stack (total: #{duration}ms)"
176
- end
177
- end
178
- # event_log_level :prompt_complete, :debug # Rails 8.1
179
-
180
- # Logs retry attempts
181
- #
182
- # @param event [ActiveSupport::Notifications::Event]
183
- def retry_attempt(event)
184
- trace_id = event.payload[:trace_id]
185
- provider_module = event.payload[:provider_module]
186
- attempt = event.payload[:attempt]
187
- max_retries = event.payload[:max_retries]
188
- exception = event.payload[:exception]
189
- backoff_time = event.payload[:backoff_time]
190
-
191
- debug do
192
- "[#{trace_id}] [ActiveAgent] [#{provider_module}:Retries] Attempt #{attempt}/#{max_retries} failed with #{exception}, retrying in #{backoff_time}s"
193
- end
194
- end
195
- # event_log_level :retry_attempt, :debug # Rails 8.1
196
-
197
- # Logs when max retries are exceeded
198
- #
199
- # @param event [ActiveSupport::Notifications::Event]
200
- def retry_exhausted(event)
201
- trace_id = event.payload[:trace_id]
202
- provider_module = event.payload[:provider_module]
203
- max_retries = event.payload[:max_retries]
204
- exception = event.payload[:exception]
205
-
206
- debug do
207
- "[#{trace_id}] [ActiveAgent] [#{provider_module}:Retries] Max retries (#{max_retries}) exceeded for #{exception}"
208
- end
209
- end
210
- # event_log_level :retry_exhausted, :debug # Rails 8.1
211
-
212
- # Logs tool execution
213
- #
214
- # @param event [ActiveSupport::Notifications::Event]
215
- def tool_execution(event)
112
+ # @return [void]
113
+ def tool_call(event)
216
114
  trace_id = event.payload[:trace_id]
217
115
  provider_module = event.payload[:provider_module]
218
116
  tool_name = event.payload[:tool_name]
117
+ duration = event.duration.round(1)
219
118
 
220
119
  debug do
221
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Executing tool: #{tool_name}"
222
- end
223
- end
224
- # event_log_level :tool_execution, :debug # Rails 8.1
225
-
226
- # Logs tool choice removal
227
- #
228
- # @param event [ActiveSupport::Notifications::Event]
229
- def tool_choice_removed(event)
230
- trace_id = event.payload[:trace_id]
231
- provider_module = event.payload[:provider_module]
232
-
233
- debug do
234
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Removing tool_choice constraint after tool execution"
235
- end
236
- end
237
- # event_log_level :tool_choice_removed, :debug # Rails 8.1
238
-
239
- # Logs API request
240
- #
241
- # @param event [ActiveSupport::Notifications::Event]
242
- def api_request(event)
243
- trace_id = event.payload[:trace_id]
244
- provider_module = event.payload[:provider_module]
245
- model = event.payload[:model]
246
- streaming = event.payload[:streaming]
247
-
248
-
249
- debug do
250
- if streaming.nil?
251
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Executing request to #{model}"
252
- else
253
- mode = streaming ? "streaming" : "non-streaming"
254
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Executing #{mode} request to #{model}"
255
- end
120
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Tool call: #{tool_name} (#{duration}ms)"
256
121
  end
257
122
  end
258
- # event_log_level :api_request, :debug # Rails 8.1
123
+ # event_log_level :tool_call, :debug # Rails 8.1
259
124
 
260
- # Logs stream chunk processing
261
- #
262
125
  # @param event [ActiveSupport::Notifications::Event]
263
- def stream_chunk_processing(event)
126
+ # @return [void]
127
+ def stream_chunk(event)
264
128
  trace_id = event.payload[:trace_id]
265
129
  provider_module = event.payload[:provider_module]
266
130
  chunk_type = event.payload[:chunk_type]
267
131
 
268
132
  debug do
269
133
  if chunk_type
270
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Processing stream chunk: #{chunk_type}"
134
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Stream chunk: #{chunk_type}"
271
135
  else
272
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Processing stream chunk"
136
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Stream chunk"
273
137
  end
274
138
  end
275
139
  end
276
- # event_log_level :stream_chunk_processing, :debug # Rails 8.1
140
+ # event_log_level :stream_chunk, :debug # Rails 8.1
277
141
 
278
- # Logs stream finished
279
- #
280
- # @param event [ActiveSupport::Notifications::Event]
281
- def stream_finished(event)
282
- trace_id = event.payload[:trace_id]
283
- provider_module = event.payload[:provider_module]
284
- finish_reason = event.payload[:finish_reason]
285
-
286
- debug do
287
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Stream finished with reason: #{finish_reason}"
288
- end
289
- end
290
- # event_log_level :stream_finished, :debug # Rails 8.1
291
-
292
- # Logs API routing decisions
293
- #
294
- # @param event [ActiveSupport::Notifications::Event]
295
- def api_routing(event)
296
- trace_id = event.payload[:trace_id]
297
- provider_module = event.payload[:provider_module]
298
- api_type = event.payload[:api_type]
299
- api_version = event.payload[:api_version]
300
- has_audio = event.payload[:has_audio]
301
-
302
- debug do
303
- if has_audio
304
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Routing to #{api_type.to_s.capitalize} API (api_version: #{api_version}, audio: #{has_audio})"
305
- else
306
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Routing to #{api_type.to_s.capitalize} API (api_version: #{api_version})"
307
- end
308
- end
309
- end
310
- # event_log_level :api_routing, :debug # Rails 8.1
311
-
312
- # Logs embeddings requests
313
- #
314
- # @param event [ActiveSupport::Notifications::Event]
315
- def embeddings_request(event)
316
- trace_id = event.payload[:trace_id]
317
- provider_module = event.payload[:provider_module]
318
-
319
- debug do
320
- "[#{trace_id}] [ActiveAgent] [#{provider_module}] Executing embeddings request"
321
- end
322
- end
323
- # event_log_level :embeddings_request, :debug # Rails 8.1
324
-
325
- # Logs connection errors
142
+ # Logs connection failures with service URI and error details.
326
143
  #
327
144
  # @param event [ActiveSupport::Notifications::Event]
145
+ # @return [void]
328
146
  def connection_error(event)
329
147
  trace_id = event.payload[:trace_id]
330
148
  provider_module = event.payload[:provider_module]
@@ -340,8 +158,6 @@ module ActiveAgent
340
158
 
341
159
  private
342
160
 
343
- # Use the logger configured for ActiveAgent::Base
344
- #
345
161
  # @return [Logger]
346
162
  def logger
347
163
  ActiveAgent::Base.logger
@@ -351,6 +167,8 @@ module ActiveAgent
351
167
  end
352
168
 
353
169
  # region log_subscriber_attach
170
+ # Subscribe to both top-level (.active_agent) and provider-level (.provider.active_agent) events
171
+ ActiveAgent::Providers::LogSubscriber.attach_to :active_agent
354
172
  ActiveAgent::Providers::LogSubscriber.attach_to :"provider.active_agent"
355
173
  # endregion log_subscriber_attach
356
174
 
@@ -56,20 +56,20 @@ module ActiveAgent
56
56
  else
57
57
  # Return a complete response
58
58
  {
59
- id: "mock-#{SecureRandom.hex(8)}",
60
- type: "message",
61
- role: "assistant",
62
- content: [
59
+ "id" => "mock-#{SecureRandom.hex(8)}",
60
+ "type" => "message",
61
+ "role" => "assistant",
62
+ "content" => [
63
63
  {
64
- type: "text",
65
- text: pig_latin_content
64
+ "type" => "text",
65
+ "text" => pig_latin_content
66
66
  }
67
67
  ],
68
- model: parameters[:model] || "mock-model",
69
- stop_reason: "end_turn",
70
- usage: {
71
- input_tokens: content.length,
72
- output_tokens: pig_latin_content.length
68
+ "model" => parameters[:model] || "mock-model",
69
+ "stop_reason" => "end_turn",
70
+ "usage" => {
71
+ "input_tokens" => content.length,
72
+ "output_tokens" => pig_latin_content.length
73
73
  }
74
74
  }
75
75
  end
@@ -80,27 +80,27 @@ module ActiveAgent
80
80
  # Returns random embedding vectors for testing purposes.
81
81
  #
82
82
  # @param parameters [Hash] The embedding request parameters
83
- # @return [Hash] A mock embedding response structure
83
+ # @return [Hash] A mock embedding response structure with symbol keys
84
84
  def api_embed_execute(parameters)
85
85
  input = parameters[:input]
86
86
  inputs = input.is_a?(Array) ? input : [ input ]
87
87
  dimensions = parameters[:dimensions] || 1536
88
88
 
89
89
  {
90
- object: "list",
91
- data: inputs.map.with_index do |text, index|
90
+ "object" => "list",
91
+ "data" => inputs.map.with_index do |text, index|
92
92
  {
93
- object: "embedding",
94
- index: index,
95
- embedding: generate_random_embedding(dimensions)
93
+ "object" => "embedding",
94
+ "index" => index,
95
+ "embedding" => generate_random_embedding(dimensions)
96
96
  }
97
97
  end,
98
- model: parameters[:model] || "mock-embedding-model",
99
- usage: {
100
- prompt_tokens: inputs.sum { |text| text.to_s.length },
101
- total_tokens: inputs.sum { |text| text.to_s.length }
98
+ "model" => parameters[:model] || "mock-embedding-model",
99
+ "usage" => {
100
+ "prompt_tokens" => inputs.sum { |text| text.to_s.length },
101
+ "total_tokens" => inputs.sum { |text| text.to_s.length }
102
102
  }
103
- }
103
+ }.deep_symbolize_keys
104
104
  end
105
105
 
106
106
  # Processes streaming response chunks.
@@ -112,7 +112,7 @@ module ActiveAgent
112
112
  def process_stream_chunk(api_response_chunk)
113
113
  chunk_type = api_response_chunk[:type]&.to_sym
114
114
 
115
- instrument("stream_chunk_processing.provider.active_agent", chunk_type: chunk_type)
115
+ instrument("stream_chunk.active_agent", chunk_type: chunk_type)
116
116
 
117
117
  broadcast_stream_open
118
118