activeagent 0.6.3 → 1.0.0.rc1

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 (282) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +210 -2
  3. data/README.md +15 -24
  4. data/lib/active_agent/base.rb +389 -39
  5. data/lib/active_agent/concerns/callbacks.rb +251 -0
  6. data/lib/active_agent/concerns/observers.rb +147 -0
  7. data/lib/active_agent/concerns/parameterized.rb +292 -0
  8. data/lib/active_agent/concerns/provider.rb +120 -0
  9. data/lib/active_agent/concerns/queueing.rb +36 -0
  10. data/lib/active_agent/concerns/rescue.rb +64 -0
  11. data/lib/active_agent/concerns/streaming.rb +282 -0
  12. data/lib/active_agent/concerns/tooling.rb +23 -0
  13. data/lib/active_agent/concerns/view.rb +150 -0
  14. data/lib/active_agent/configuration.rb +442 -20
  15. data/lib/active_agent/generation.rb +141 -47
  16. data/lib/active_agent/generation_provider/open_router/types.rb +505 -0
  17. data/lib/active_agent/generation_provider/xai_provider.rb +144 -0
  18. data/lib/active_agent/providers/_base_provider.rb +410 -0
  19. data/lib/active_agent/providers/anthropic/_types.rb +63 -0
  20. data/lib/active_agent/providers/anthropic/options.rb +53 -0
  21. data/lib/active_agent/providers/anthropic/request.rb +109 -0
  22. data/lib/active_agent/providers/anthropic/requests/_types.rb +190 -0
  23. data/lib/active_agent/providers/anthropic/requests/container_params.rb +19 -0
  24. data/lib/active_agent/providers/anthropic/requests/content/base.rb +21 -0
  25. data/lib/active_agent/providers/anthropic/requests/content/sources/base.rb +22 -0
  26. data/lib/active_agent/providers/anthropic/requests/context_management_config.rb +18 -0
  27. data/lib/active_agent/providers/anthropic/requests/messages/_types.rb +189 -0
  28. data/lib/active_agent/providers/anthropic/requests/messages/assistant.rb +23 -0
  29. data/lib/active_agent/providers/anthropic/requests/messages/base.rb +63 -0
  30. data/lib/active_agent/providers/anthropic/requests/messages/content/_types.rb +143 -0
  31. data/lib/active_agent/providers/anthropic/requests/messages/content/base.rb +21 -0
  32. data/lib/active_agent/providers/anthropic/requests/messages/content/document.rb +26 -0
  33. data/lib/active_agent/providers/anthropic/requests/messages/content/image.rb +23 -0
  34. data/lib/active_agent/providers/anthropic/requests/messages/content/redacted_thinking.rb +21 -0
  35. data/lib/active_agent/providers/anthropic/requests/messages/content/search_result.rb +27 -0
  36. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/_types.rb +171 -0
  37. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/base.rb +22 -0
  38. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_base64.rb +25 -0
  39. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_file.rb +23 -0
  40. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_text.rb +25 -0
  41. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_url.rb +23 -0
  42. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_base64.rb +27 -0
  43. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_file.rb +23 -0
  44. data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_url.rb +23 -0
  45. data/lib/active_agent/providers/anthropic/requests/messages/content/text.rb +22 -0
  46. data/lib/active_agent/providers/anthropic/requests/messages/content/thinking.rb +23 -0
  47. data/lib/active_agent/providers/anthropic/requests/messages/content/tool_result.rb +24 -0
  48. data/lib/active_agent/providers/anthropic/requests/messages/content/tool_use.rb +28 -0
  49. data/lib/active_agent/providers/anthropic/requests/messages/user.rb +21 -0
  50. data/lib/active_agent/providers/anthropic/requests/metadata.rb +18 -0
  51. data/lib/active_agent/providers/anthropic/requests/response_format.rb +22 -0
  52. data/lib/active_agent/providers/anthropic/requests/thinking_config/_types.rb +60 -0
  53. data/lib/active_agent/providers/anthropic/requests/thinking_config/base.rb +20 -0
  54. data/lib/active_agent/providers/anthropic/requests/thinking_config/disabled.rb +16 -0
  55. data/lib/active_agent/providers/anthropic/requests/thinking_config/enabled.rb +20 -0
  56. data/lib/active_agent/providers/anthropic/requests/tool_choice/_types.rb +78 -0
  57. data/lib/active_agent/providers/anthropic/requests/tool_choice/any.rb +17 -0
  58. data/lib/active_agent/providers/anthropic/requests/tool_choice/auto.rb +17 -0
  59. data/lib/active_agent/providers/anthropic/requests/tool_choice/base.rb +20 -0
  60. data/lib/active_agent/providers/anthropic/requests/tool_choice/none.rb +16 -0
  61. data/lib/active_agent/providers/anthropic/requests/tool_choice/tool.rb +20 -0
  62. data/lib/active_agent/providers/anthropic_provider.rb +211 -0
  63. data/lib/active_agent/providers/common/messages/_types.rb +124 -0
  64. data/lib/active_agent/providers/common/messages/assistant.rb +57 -0
  65. data/lib/active_agent/providers/common/messages/base.rb +17 -0
  66. data/lib/active_agent/providers/common/messages/system.rb +20 -0
  67. data/lib/active_agent/providers/common/messages/tool.rb +21 -0
  68. data/lib/active_agent/providers/common/messages/user.rb +20 -0
  69. data/lib/active_agent/providers/common/model.rb +361 -0
  70. data/lib/active_agent/providers/common/response.rb +13 -0
  71. data/lib/active_agent/providers/common/responses/_types.rb +51 -0
  72. data/lib/active_agent/providers/common/responses/base.rb +151 -0
  73. data/lib/active_agent/providers/common/responses/embed.rb +33 -0
  74. data/lib/active_agent/providers/common/responses/format.rb +31 -0
  75. data/lib/active_agent/providers/common/responses/message.rb +3 -0
  76. data/lib/active_agent/providers/common/responses/prompt.rb +42 -0
  77. data/lib/active_agent/providers/concerns/exception_handler.rb +72 -0
  78. data/lib/active_agent/providers/concerns/previewable.rb +150 -0
  79. data/lib/active_agent/providers/log_subscriber.rb +360 -0
  80. data/lib/active_agent/providers/mock/_types.rb +77 -0
  81. data/lib/active_agent/providers/mock/embedding_request.rb +17 -0
  82. data/lib/active_agent/providers/mock/messages/_types.rb +103 -0
  83. data/lib/active_agent/providers/mock/messages/assistant.rb +26 -0
  84. data/lib/active_agent/providers/mock/messages/base.rb +63 -0
  85. data/lib/active_agent/providers/mock/messages/user.rb +18 -0
  86. data/lib/active_agent/providers/mock/options.rb +30 -0
  87. data/lib/active_agent/providers/mock/request.rb +38 -0
  88. data/lib/active_agent/providers/mock_provider.rb +311 -0
  89. data/lib/active_agent/providers/ollama/_types.rb +5 -0
  90. data/lib/active_agent/providers/ollama/chat/_types.rb +44 -0
  91. data/lib/active_agent/providers/ollama/chat/request.rb +70 -0
  92. data/lib/active_agent/providers/ollama/chat/requests/_types.rb +3 -0
  93. data/lib/active_agent/providers/ollama/chat/requests/messages/_types.rb +116 -0
  94. data/lib/active_agent/providers/ollama/chat/requests/messages/assistant.rb +19 -0
  95. data/lib/active_agent/providers/ollama/chat/requests/messages/user.rb +19 -0
  96. data/lib/active_agent/providers/ollama/embedding/_types.rb +44 -0
  97. data/lib/active_agent/providers/ollama/embedding/request.rb +77 -0
  98. data/lib/active_agent/providers/ollama/embedding/requests/_types.rb +83 -0
  99. data/lib/active_agent/providers/ollama/embedding/requests/options.rb +104 -0
  100. data/lib/active_agent/providers/ollama/options.rb +27 -0
  101. data/lib/active_agent/providers/ollama_provider.rb +95 -0
  102. data/lib/active_agent/providers/open_ai/_base.rb +58 -0
  103. data/lib/active_agent/providers/open_ai/_types.rb +5 -0
  104. data/lib/active_agent/providers/open_ai/chat/_types.rb +44 -0
  105. data/lib/active_agent/providers/open_ai/chat/request.rb +215 -0
  106. data/lib/active_agent/providers/open_ai/chat/requests/_types.rb +229 -0
  107. data/lib/active_agent/providers/open_ai/chat/requests/audio.rb +24 -0
  108. data/lib/active_agent/providers/open_ai/chat/requests/messages/_types.rb +123 -0
  109. data/lib/active_agent/providers/open_ai/chat/requests/messages/assistant.rb +42 -0
  110. data/lib/active_agent/providers/open_ai/chat/requests/messages/base.rb +78 -0
  111. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/_types.rb +133 -0
  112. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/audio.rb +35 -0
  113. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/base.rb +24 -0
  114. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/file.rb +26 -0
  115. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/_types.rb +60 -0
  116. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/details.rb +41 -0
  117. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/image.rb +37 -0
  118. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/refusal.rb +25 -0
  119. data/lib/active_agent/providers/open_ai/chat/requests/messages/content/text.rb +25 -0
  120. data/lib/active_agent/providers/open_ai/chat/requests/messages/developer.rb +25 -0
  121. data/lib/active_agent/providers/open_ai/chat/requests/messages/function.rb +25 -0
  122. data/lib/active_agent/providers/open_ai/chat/requests/messages/system.rb +25 -0
  123. data/lib/active_agent/providers/open_ai/chat/requests/messages/tool.rb +26 -0
  124. data/lib/active_agent/providers/open_ai/chat/requests/messages/user.rb +32 -0
  125. data/lib/active_agent/providers/open_ai/chat/requests/prediction.rb +46 -0
  126. data/lib/active_agent/providers/open_ai/chat/requests/response_format.rb +53 -0
  127. data/lib/active_agent/providers/open_ai/chat/requests/stream_options.rb +24 -0
  128. data/lib/active_agent/providers/open_ai/chat/requests/tool_choice.rb +26 -0
  129. data/lib/active_agent/providers/open_ai/chat/requests/tools/_types.rb +5 -0
  130. data/lib/active_agent/providers/open_ai/chat/requests/tools/base.rb +22 -0
  131. data/lib/active_agent/providers/open_ai/chat/requests/tools/custom_tool.rb +41 -0
  132. data/lib/active_agent/providers/open_ai/chat/requests/tools/function_tool.rb +51 -0
  133. data/lib/active_agent/providers/open_ai/chat/requests/web_search_options.rb +45 -0
  134. data/lib/active_agent/providers/open_ai/chat_provider.rb +198 -0
  135. data/lib/active_agent/providers/open_ai/embedding/_types.rb +45 -0
  136. data/lib/active_agent/providers/open_ai/embedding/request.rb +85 -0
  137. data/lib/active_agent/providers/open_ai/embedding/requests/_types.rb +49 -0
  138. data/lib/active_agent/providers/open_ai/options.rb +74 -0
  139. data/lib/active_agent/providers/open_ai/responses/_types.rb +50 -0
  140. data/lib/active_agent/providers/open_ai/responses/request.rb +163 -0
  141. data/lib/active_agent/providers/open_ai/responses/requests/_types.rb +231 -0
  142. data/lib/active_agent/providers/open_ai/responses/requests/conversation.rb +23 -0
  143. data/lib/active_agent/providers/open_ai/responses/requests/inputs/_types.rb +264 -0
  144. data/lib/active_agent/providers/open_ai/responses/requests/inputs/assistant_message.rb +22 -0
  145. data/lib/active_agent/providers/open_ai/responses/requests/inputs/base.rb +89 -0
  146. data/lib/active_agent/providers/open_ai/responses/requests/inputs/code_interpreter_tool_call.rb +30 -0
  147. data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call.rb +28 -0
  148. data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call_output.rb +33 -0
  149. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/_types.rb +207 -0
  150. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/base.rb +22 -0
  151. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_audio.rb +26 -0
  152. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_file.rb +28 -0
  153. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_image.rb +28 -0
  154. data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_text.rb +25 -0
  155. data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call.rb +28 -0
  156. data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call_output.rb +27 -0
  157. data/lib/active_agent/providers/open_ai/responses/requests/inputs/developer_message.rb +20 -0
  158. data/lib/active_agent/providers/open_ai/responses/requests/inputs/file_search_tool_call.rb +25 -0
  159. data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_call_output.rb +32 -0
  160. data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_tool_call.rb +28 -0
  161. data/lib/active_agent/providers/open_ai/responses/requests/inputs/image_gen_tool_call.rb +27 -0
  162. data/lib/active_agent/providers/open_ai/responses/requests/inputs/input_message.rb +31 -0
  163. data/lib/active_agent/providers/open_ai/responses/requests/inputs/item_reference.rb +23 -0
  164. data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call.rb +26 -0
  165. data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call_output.rb +33 -0
  166. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_request.rb +30 -0
  167. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_response.rb +28 -0
  168. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_list_tools.rb +29 -0
  169. data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_tool_call.rb +35 -0
  170. data/lib/active_agent/providers/open_ai/responses/requests/inputs/output_message.rb +35 -0
  171. data/lib/active_agent/providers/open_ai/responses/requests/inputs/reasoning.rb +33 -0
  172. data/lib/active_agent/providers/open_ai/responses/requests/inputs/system_message.rb +20 -0
  173. data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_call_base.rb +27 -0
  174. data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_message.rb +23 -0
  175. data/lib/active_agent/providers/open_ai/responses/requests/inputs/user_message.rb +20 -0
  176. data/lib/active_agent/providers/open_ai/responses/requests/inputs/web_search_tool_call.rb +24 -0
  177. data/lib/active_agent/providers/open_ai/responses/requests/prompt_reference.rb +23 -0
  178. data/lib/active_agent/providers/open_ai/responses/requests/reasoning.rb +23 -0
  179. data/lib/active_agent/providers/open_ai/responses/requests/stream_options.rb +20 -0
  180. data/lib/active_agent/providers/open_ai/responses/requests/text/_types.rb +89 -0
  181. data/lib/active_agent/providers/open_ai/responses/requests/text/base.rb +22 -0
  182. data/lib/active_agent/providers/open_ai/responses/requests/text/json_object.rb +20 -0
  183. data/lib/active_agent/providers/open_ai/responses/requests/text/json_schema.rb +48 -0
  184. data/lib/active_agent/providers/open_ai/responses/requests/text/plain.rb +20 -0
  185. data/lib/active_agent/providers/open_ai/responses/requests/text.rb +41 -0
  186. data/lib/active_agent/providers/open_ai/responses/requests/tool_choice.rb +26 -0
  187. data/lib/active_agent/providers/open_ai/responses/requests/tools/_types.rb +112 -0
  188. data/lib/active_agent/providers/open_ai/responses/requests/tools/base.rb +25 -0
  189. data/lib/active_agent/providers/open_ai/responses/requests/tools/code_interpreter_tool.rb +23 -0
  190. data/lib/active_agent/providers/open_ai/responses/requests/tools/computer_tool.rb +27 -0
  191. data/lib/active_agent/providers/open_ai/responses/requests/tools/custom_tool.rb +28 -0
  192. data/lib/active_agent/providers/open_ai/responses/requests/tools/file_search_tool.rb +27 -0
  193. data/lib/active_agent/providers/open_ai/responses/requests/tools/function_tool.rb +29 -0
  194. data/lib/active_agent/providers/open_ai/responses/requests/tools/image_generation_tool.rb +37 -0
  195. data/lib/active_agent/providers/open_ai/responses/requests/tools/local_shell_tool.rb +21 -0
  196. data/lib/active_agent/providers/open_ai/responses/requests/tools/mcp_tool.rb +41 -0
  197. data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_preview_tool.rb +24 -0
  198. data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_tool.rb +25 -0
  199. data/lib/active_agent/providers/open_ai/responses_provider.rb +153 -0
  200. data/lib/active_agent/providers/open_ai/schema.yml +65937 -0
  201. data/lib/active_agent/providers/open_ai_provider.rb +97 -0
  202. data/lib/active_agent/providers/open_router/_types.rb +45 -0
  203. data/lib/active_agent/providers/open_router/options.rb +93 -0
  204. data/lib/active_agent/providers/open_router/request.rb +83 -0
  205. data/lib/active_agent/providers/open_router/requests/_types.rb +198 -0
  206. data/lib/active_agent/providers/open_router/requests/message.rb +1 -0
  207. data/lib/active_agent/providers/open_router/requests/messages/_types.rb +59 -0
  208. data/lib/active_agent/providers/open_router/requests/messages/assistant.rb +20 -0
  209. data/lib/active_agent/providers/open_router/requests/messages/content/_types.rb +97 -0
  210. data/lib/active_agent/providers/open_router/requests/messages/content/file.rb +27 -0
  211. data/lib/active_agent/providers/open_router/requests/messages/content/files/_types.rb +61 -0
  212. data/lib/active_agent/providers/open_router/requests/messages/content/files/details.rb +26 -0
  213. data/lib/active_agent/providers/open_router/requests/messages/user.rb +30 -0
  214. data/lib/active_agent/providers/open_router/requests/plugin.rb +25 -0
  215. data/lib/active_agent/providers/open_router/requests/plugins/_types.rb +46 -0
  216. data/lib/active_agent/providers/open_router/requests/plugins/pdf_config.rb +29 -0
  217. data/lib/active_agent/providers/open_router/requests/prediction.rb +17 -0
  218. data/lib/active_agent/providers/open_router/requests/provider_preferences/_types.rb +44 -0
  219. data/lib/active_agent/providers/open_router/requests/provider_preferences/max_price.rb +30 -0
  220. data/lib/active_agent/providers/open_router/requests/provider_preferences.rb +64 -0
  221. data/lib/active_agent/providers/open_router/requests/response_format.rb +49 -0
  222. data/lib/active_agent/providers/open_router_provider.rb +53 -0
  223. data/lib/active_agent/providers/openai_provider.rb +2 -0
  224. data/lib/active_agent/providers/openrouter_provider.rb +2 -0
  225. data/lib/active_agent/railtie.rb +8 -6
  226. data/lib/active_agent/schema_generator.rb +333 -166
  227. data/lib/active_agent/version.rb +1 -1
  228. data/lib/active_agent.rb +112 -36
  229. data/lib/generators/active_agent/agent/USAGE +78 -0
  230. data/lib/generators/active_agent/{agent_generator.rb → agent/agent_generator.rb} +14 -4
  231. data/lib/generators/active_agent/install/USAGE +25 -0
  232. data/lib/generators/active_agent/{install_generator.rb → install/install_generator.rb} +1 -19
  233. data/lib/generators/active_agent/templates/agent.rb.tt +7 -3
  234. data/lib/generators/active_agent/templates/application_agent.rb.tt +0 -2
  235. data/lib/generators/erb/agent_generator.rb +31 -16
  236. data/lib/generators/erb/templates/instructions.md.erb.tt +3 -0
  237. data/lib/generators/erb/templates/instructions.md.tt +3 -0
  238. data/lib/generators/erb/templates/instructions.text.tt +1 -0
  239. data/lib/generators/erb/templates/message.md.erb.tt +5 -0
  240. data/lib/generators/erb/templates/schema.json.tt +10 -0
  241. data/lib/generators/test_unit/agent_generator.rb +1 -1
  242. data/lib/generators/test_unit/templates/functional_test.rb.tt +4 -2
  243. metadata +320 -65
  244. data/lib/active_agent/action_prompt/action.rb +0 -13
  245. data/lib/active_agent/action_prompt/base.rb +0 -623
  246. data/lib/active_agent/action_prompt/message.rb +0 -126
  247. data/lib/active_agent/action_prompt/prompt.rb +0 -136
  248. data/lib/active_agent/action_prompt.rb +0 -19
  249. data/lib/active_agent/callbacks.rb +0 -33
  250. data/lib/active_agent/generation_provider/anthropic_provider.rb +0 -163
  251. data/lib/active_agent/generation_provider/base.rb +0 -55
  252. data/lib/active_agent/generation_provider/base_adapter.rb +0 -19
  253. data/lib/active_agent/generation_provider/error_handling.rb +0 -167
  254. data/lib/active_agent/generation_provider/log_subscriber.rb +0 -92
  255. data/lib/active_agent/generation_provider/message_formatting.rb +0 -107
  256. data/lib/active_agent/generation_provider/ollama_provider.rb +0 -66
  257. data/lib/active_agent/generation_provider/open_ai_provider.rb +0 -279
  258. data/lib/active_agent/generation_provider/open_router_provider.rb +0 -385
  259. data/lib/active_agent/generation_provider/parameter_builder.rb +0 -119
  260. data/lib/active_agent/generation_provider/response.rb +0 -75
  261. data/lib/active_agent/generation_provider/responses_adapter.rb +0 -44
  262. data/lib/active_agent/generation_provider/stream_processing.rb +0 -58
  263. data/lib/active_agent/generation_provider/tool_management.rb +0 -142
  264. data/lib/active_agent/generation_provider.rb +0 -67
  265. data/lib/active_agent/log_subscriber.rb +0 -44
  266. data/lib/active_agent/parameterized.rb +0 -75
  267. data/lib/active_agent/prompt_helper.rb +0 -19
  268. data/lib/active_agent/queued_generation.rb +0 -12
  269. data/lib/active_agent/rescuable.rb +0 -34
  270. data/lib/active_agent/sanitizers.rb +0 -40
  271. data/lib/active_agent/streaming.rb +0 -34
  272. data/lib/active_agent/test_case.rb +0 -125
  273. data/lib/generators/USAGE +0 -47
  274. data/lib/generators/active_agent/USAGE +0 -56
  275. data/lib/generators/erb/install_generator.rb +0 -44
  276. data/lib/generators/erb/templates/layout.html.erb.tt +0 -1
  277. data/lib/generators/erb/templates/layout.json.erb.tt +0 -1
  278. data/lib/generators/erb/templates/layout.text.erb.tt +0 -1
  279. data/lib/generators/erb/templates/view.html.erb.tt +0 -5
  280. data/lib/generators/erb/templates/view.json.erb.tt +0 -16
  281. /data/lib/active_agent/{preview.rb → concerns/preview.rb} +0 -0
  282. /data/lib/generators/erb/templates/{view.text.erb.tt → message.text.erb.tt} +0 -0
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Common
8
+ module Responses
9
+ class Format < Common::BaseModel
10
+ # Type of response format (text, json_object, json_schema)
11
+ attribute :type, :string, default: "text"
12
+ attribute :name, :string
13
+ attribute :schema
14
+
15
+ validates :type, inclusion: { in: %w[text json_object json_object] }, allow_nil: true
16
+
17
+ # OpenAI's Responses => Common Format
18
+ def format=(value)
19
+ self.type = value[:type]
20
+ end
21
+
22
+ # OpenAI's Chat => Common Format
23
+ def json_schema=(value)
24
+ self.name = value[:name] if value[:name]
25
+ self.schema = value[:schema] if value[:schema]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../messages/base"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "_types"
5
+ require_relative "message"
6
+
7
+ module ActiveAgent
8
+ module Providers
9
+ module Common
10
+ module Responses
11
+ # Response model for prompt/completion responses
12
+ #
13
+ # This class represents responses from conversational/completion endpoints.
14
+ # It includes the generated messages, the original context, raw API data,
15
+ # and usage statistics.
16
+ #
17
+ # == Example
18
+ #
19
+ # response = PromptResponse.new(
20
+ # context: context_hash,
21
+ # messages: [message_object],
22
+ # raw_response: { "usage" => { "prompt_tokens" => 10 } }
23
+ # )
24
+ #
25
+ # response.message #=> <Message>
26
+ # response.prompt_tokens #=> 10
27
+ # response.usage #=> { "prompt_tokens" => 10, ... }
28
+ class Prompt < Base
29
+ # The list of messages from this conversation
30
+ attribute :messages, Types::MessagesType.new, writable: false
31
+
32
+ attribute :format, Types::FormatType.new, writable: false, default: {}
33
+
34
+ # The most recent message in the conversational stack
35
+ def message
36
+ messages.last
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ # Provides exception handling for provider operations.
6
+ #
7
+ # This concern implements basic exception handling that allows agents to
8
+ # define custom error handling logic via rescue_from callbacks. The actual
9
+ # retry logic is now handled by the underlying provider gems (ruby-openai,
10
+ # anthropic-rb, etc.) which provide their own retry mechanisms.
11
+ #
12
+ # @example Using exception handler
13
+ # class MyProvider
14
+ # include ActiveAgent::Providers::ExceptionHandler
15
+ #
16
+ # def call
17
+ # with_exception_handling do
18
+ # # API call that may fail
19
+ # end
20
+ # end
21
+ # end
22
+ #
23
+ # @example Agent-level error handling
24
+ # class MyAgent < ActiveAgent::Base
25
+ # rescue_from SomeError do |exception|
26
+ # # Handle the error
27
+ # end
28
+ # end
29
+ module ExceptionHandler
30
+ extend ActiveSupport::Concern
31
+
32
+ included do
33
+ # @!attribute [rw] exception_handler
34
+ # @return [Proc, nil] Callback for handling exceptions
35
+ attr_internal :exception_handler
36
+ end
37
+
38
+ # Configures instance-level exception handling.
39
+ #
40
+ # @param exception_handler [Proc, nil] callback for handling exceptions
41
+ # @return [void]
42
+ def configure_exception_handler(exception_handler: nil)
43
+ self.exception_handler = exception_handler
44
+ end
45
+
46
+ # Executes a block with exception handling.
47
+ #
48
+ # @yield Block to execute with exception protection
49
+ # @return [Object] The result of the block execution
50
+ # @raise [StandardError] Any unhandled exception from the block
51
+ #
52
+ # @example Basic usage
53
+ # with_exception_handling { api_call }
54
+ def with_exception_handling(&block)
55
+ yield
56
+ rescue => exception
57
+ rescue_with_handler(exception) || raise
58
+ end
59
+
60
+ # Bubbles up exceptions to the Agent's rescue_from if a handler is defined.
61
+ #
62
+ # This method delegates exception handling to the configured exception handler,
63
+ # allowing agents to define custom error handling logic.
64
+ #
65
+ # @param exception [StandardError] The exception to handle
66
+ # @return [Object, nil] Result from the exception handler, or nil if no handler
67
+ def rescue_with_handler(exception)
68
+ exception_handler&.call(exception)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ # Generates markdown previews of prompts for debugging and inspection.
6
+ #
7
+ # Renders request parameters, instructions, messages, and tools in a
8
+ # human-readable format without executing the actual API call.
9
+ module Previewable
10
+ extend ActiveSupport::Concern
11
+
12
+ # Generates a markdown preview of the prompt request.
13
+ #
14
+ # @return [String] markdown-formatted preview
15
+ def preview_prompt
16
+ request = prepare_prompt_request
17
+
18
+ # @todo Validate Request
19
+ api_parameters = api_request_build(request, prompt_request_type)
20
+
21
+ render_markdown_preview(api_parameters)
22
+ end
23
+
24
+ private
25
+
26
+ # Renders markdown preview with YAML metadata, instructions, messages, and tools.
27
+ #
28
+ # Sections are separated by `---` dividers for readability.
29
+ #
30
+ # @param parameters [Hash]
31
+ # @return [String]
32
+ def render_markdown_preview(parameters)
33
+ sections = []
34
+
35
+ # Instructions section
36
+ if (instructions = parameters.delete(:instructions)).present?
37
+ sections << render_instructions_section(instructions)
38
+ end
39
+
40
+ # Messages section
41
+ if (messages = parameters.delete(:messages) || parameters.delete(:input)).present?
42
+ sections << render_messages_section(messages)
43
+ end
44
+
45
+ # Tools section
46
+ if (tools = parameters.delete(:tools)).present?
47
+ sections << render_tools_section(tools)
48
+ end
49
+
50
+ # Prepend YAML section with request details
51
+ sections = [ render_yaml_section(parameters), "---" ] + sections
52
+
53
+ sections.compact.join("\n")
54
+ end
55
+
56
+ # @param instructions [String]
57
+ # @return [String]
58
+ def render_instructions_section(instructions)
59
+ "## Instructions\n#{instructions}"
60
+ end
61
+
62
+ # Renders conversation messages with role labels.
63
+ #
64
+ # @param messages [Array<Hash>]
65
+ # @return [String]
66
+ def render_messages_section(messages)
67
+ return "" if messages.nil? || messages.empty?
68
+
69
+ content = +"## Messages\n\n"
70
+
71
+ Array(messages).each_with_index do |message, index|
72
+ content << render_single_message(message, index + 1)
73
+ content << "\n\n" unless index == messages.size - 1
74
+ end
75
+
76
+ content
77
+ end
78
+
79
+ # @param message [Hash]
80
+ # @param index [Integer] 1-based message number
81
+ # @return [String]
82
+ def render_single_message(message, index)
83
+ role = (message.is_a?(Hash) && message[:role]) || "user"
84
+ content = extract_message_content(message)
85
+
86
+ "### Message #{index} (#{role.capitalize})\n#{content}"
87
+ end
88
+
89
+ # Renders available tools with descriptions and parameter schemas.
90
+ #
91
+ # @param tools [Array<Hash>]
92
+ # @return [String]
93
+ def render_tools_section(tools)
94
+ return "" if tools.nil? || tools.empty?
95
+
96
+ content = +"## Tools\n\n"
97
+
98
+ tools.each_with_index do |tool, index|
99
+ content << "### #{tool[:name] || "Tool #{index + 1}"}\n"
100
+ content << "**Description:** #{tool[:description] || 'No description'}\n\n"
101
+
102
+ if tool[:parameters]
103
+ content << "**Parameters:**\n```json\n#{JSON.pretty_generate(tool[:parameters])}\n```\n\n"
104
+ end
105
+ end
106
+
107
+ content.chomp
108
+ end
109
+
110
+ # Extracts text content from various message formats.
111
+ #
112
+ # Handles string messages, hash messages with :content key, and
113
+ # array content blocks (extracting only text-type blocks).
114
+ #
115
+ # @param message [Hash, String, nil]
116
+ # @return [String]
117
+ def extract_message_content(message)
118
+ return "" if message.nil?
119
+
120
+ case message
121
+ when String
122
+ message
123
+ when Hash
124
+ content = message[:content]
125
+ case content
126
+ when String
127
+ content
128
+ when Array
129
+ content
130
+ .select { |block| block.is_a?(Hash) && block[:type] == "text" }
131
+ .map { |block| block[:text] }
132
+ .join(" ")
133
+ else
134
+ content.to_s
135
+ end
136
+ else
137
+ message.to_s
138
+ end
139
+ end
140
+
141
+ # Renders request metadata as YAML.
142
+ #
143
+ # @param parameters [Hash]
144
+ # @return [String]
145
+ def render_yaml_section(parameters)
146
+ parameters.to_yaml.chomp
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,360 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/log_subscriber"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ # Log subscriber for ActiveAgent provider operations.
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.
14
+ #
15
+ # @example Custom log formatting
16
+ # class MyLogSubscriber < ActiveAgent::LogSubscriber
17
+ # def prompt_start(event)
18
+ # info "🚀 Starting prompt: #{event.payload[:provider]}"
19
+ # end
20
+ # end
21
+ #
22
+ # ActiveAgent::LogSubscriber.detach_from :active_agent_provider
23
+ # MyLogSubscriber.attach_to :active_agent_provider
24
+ class LogSubscriber < ActiveSupport::LogSubscriber
25
+ # self.namespace = "active_agent" # Rails 8.1
26
+
27
+ # Logs the start of a prompt request
28
+ #
29
+ # @param event [ActiveSupport::Notifications::Event]
30
+ def prompt_start(event)
31
+ trace_id = event.payload[:trace_id]
32
+ provider_module = event.payload[:provider_module]
33
+
34
+ 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
+
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
52
+
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]
60
+
61
+ debug do
62
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Prepared request with #{message_count} message(s)"
63
+ end
64
+ end
65
+ # event_log_level :request_prepared, :debug # Rails 8.1
66
+
67
+ # Logs API call execution
68
+ #
69
+ # @param event [ActiveSupport::Notifications::Event]
70
+ def api_call(event)
71
+ return unless logger.debug?
72
+
73
+ trace_id = event.payload[:trace_id]
74
+ provider_module = event.payload[:provider_module]
75
+ streaming = event.payload[:streaming]
76
+ duration = event.duration.round(1)
77
+
78
+ 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
83
+
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"
94
+ end
95
+ end
96
+ # event_log_level :embed_call, :debug # Rails 8.1
97
+
98
+ # Logs stream opening
99
+ #
100
+ # @param event [ActiveSupport::Notifications::Event]
101
+ def stream_open(event)
102
+ trace_id = event.payload[:trace_id]
103
+ provider_module = event.payload[:provider_module]
104
+
105
+ debug do
106
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Opening stream"
107
+ end
108
+ end
109
+ # event_log_level :stream_open, :debug # Rails 8.1
110
+
111
+ # Logs stream closing
112
+ #
113
+ # @param event [ActiveSupport::Notifications::Event]
114
+ def stream_close(event)
115
+ trace_id = event.payload[:trace_id]
116
+ provider_module = event.payload[:provider_module]
117
+
118
+ debug do
119
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Closing stream"
120
+ end
121
+ end
122
+ # event_log_level :stream_close, :debug # Rails 8.1
123
+
124
+ # Logs message extraction from API response
125
+ #
126
+ # @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)
216
+ trace_id = event.payload[:trace_id]
217
+ provider_module = event.payload[:provider_module]
218
+ tool_name = event.payload[:tool_name]
219
+
220
+ 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
256
+ end
257
+ end
258
+ # event_log_level :api_request, :debug # Rails 8.1
259
+
260
+ # Logs stream chunk processing
261
+ #
262
+ # @param event [ActiveSupport::Notifications::Event]
263
+ def stream_chunk_processing(event)
264
+ trace_id = event.payload[:trace_id]
265
+ provider_module = event.payload[:provider_module]
266
+ chunk_type = event.payload[:chunk_type]
267
+
268
+ debug do
269
+ if chunk_type
270
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Processing stream chunk: #{chunk_type}"
271
+ else
272
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Processing stream chunk"
273
+ end
274
+ end
275
+ end
276
+ # event_log_level :stream_chunk_processing, :debug # Rails 8.1
277
+
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
326
+ #
327
+ # @param event [ActiveSupport::Notifications::Event]
328
+ def connection_error(event)
329
+ trace_id = event.payload[:trace_id]
330
+ provider_module = event.payload[:provider_module]
331
+ uri_base = event.payload[:uri_base]
332
+ exception = event.payload[:exception]
333
+ message = event.payload[:message]
334
+
335
+ debug do
336
+ "[#{trace_id}] [ActiveAgent] [#{provider_module}] Unable to connect to #{uri_base}. Please ensure the service is running. Error: #{exception} - #{message}"
337
+ end
338
+ end
339
+ # event_log_level :connection_error, :debug # Rails 8.1
340
+
341
+ private
342
+
343
+ # Use the logger configured for ActiveAgent::Base
344
+ #
345
+ # @return [Logger]
346
+ def logger
347
+ ActiveAgent::Base.logger
348
+ end
349
+ end
350
+ end
351
+ end
352
+
353
+ # region log_subscriber_attach
354
+ ActiveAgent::Providers::LogSubscriber.attach_to :"provider.active_agent"
355
+ # endregion log_subscriber_attach
356
+
357
+ # Rails 8.1
358
+ # ActiveSupport.event_reporter.subscribe(
359
+ # ActiveAgent::LogSubscriber.new, &ActiveAgent::LogSubscriber.subscription_filter
360
+ # )