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
@@ -1,36 +1,458 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/object/duplicable"
4
+ require "active_support/core_ext/hash/indifferent_access"
5
+ require "erb"
6
+ require "socket"
7
+ require "timeout"
8
+ require "yaml"
9
+
3
10
  module ActiveAgent
11
+ # Configuration class for ActiveAgent global settings.
12
+ #
13
+ # Provides configuration options for generation behavior, error handling,
14
+ # and logging. Configuration can be set globally using the
15
+ # {ActiveAgent.configure} method or loaded from a YAML file for
16
+ # provider-specific settings.
17
+ #
18
+ # = Global Configuration
19
+ #
20
+ # Use {ActiveAgent.configure} for framework-level settings like logging.
21
+ #
22
+ # @example Basic configuration
23
+ # ActiveAgent.configure do |config|
24
+ # config.logger = Logger.new(STDOUT)
25
+ # end
26
+ #
27
+ # = Provider Configuration
28
+ #
29
+ # Use YAML configuration files to define provider-specific settings like
30
+ # API keys, models, and parameters. This is the recommended approach for
31
+ # managing multiple generation providers across different environments.
32
+ #
33
+ # @example YAML configuration file (config/activeagent.yml)
34
+ # # Define reusable anchors for common settings
35
+ # openai: &openai
36
+ # service: "OpenAI"
37
+ # access_token: <%= Rails.application.credentials.dig(:openai, :access_token) %>
38
+ #
39
+ # anthropic: &anthropic
40
+ # service: "Anthropic"
41
+ # access_token: <%= Rails.application.credentials.dig(:anthropic, :access_token) %>
42
+ #
43
+ # development:
44
+ # openai:
45
+ # <<: *openai
46
+ # model: "gpt-4o-mini"
47
+ # temperature: 0.7
48
+ # anthropic:
49
+ # <<: *anthropic
50
+ # model: "claude-3-5-sonnet-20241022"
51
+ #
52
+ # production:
53
+ # openai:
54
+ # <<: *openai
55
+ # model: "gpt-4o"
56
+ # temperature: 0.5
57
+ #
58
+ # @example Loading provider configuration
59
+ # # In config/initializers/activeagent.rb
60
+ # ActiveAgent.configuration_load(Rails.root.join("config/activeagent.yml"))
61
+ #
62
+ # @example Using configured providers in agents
63
+ # class MyAgent < ActiveAgent::Base
64
+ # generate_with :openai # Uses settings from config/activeagent.yml
65
+ # end
66
+ #
67
+ # @see ActiveAgent.configure
68
+ # @see ActiveAgent.configuration_load
4
69
  class Configuration
5
- attr_accessor :verbose_generation_errors
6
- attr_accessor :generation_retry_errors
7
- attr_accessor :generation_max_retries
8
- attr_accessor :generation_provider_logger
70
+ # Default configuration values.
71
+ #
72
+ # @return [Hash] Hash of default configuration values
73
+ DEFAULTS = {}.freeze
9
74
 
10
- def initialize
11
- @verbose_generation_errors = false
12
- @generation_retry_errors = []
13
- @generation_max_retries = 3
14
- @generation_provider_logger = nil
75
+ # Gets the logger used by ActiveAgent.
76
+ #
77
+ # @return [Logger] The logger instance
78
+ # @see ActiveAgent::Base.logger
79
+ def logger
80
+ ActiveAgent::Base.logger
15
81
  end
16
82
 
17
- def verbose_generation_errors?
18
- @verbose_generation_errors
83
+ # Sets the logger used by ActiveAgent.
84
+ #
85
+ # @param value [Logger] The logger instance to use
86
+ # @return [Logger] The logger that was set
87
+ #
88
+ # @example
89
+ # config.logger = Logger.new(STDOUT)
90
+ # config.logger.level = Logger::DEBUG
91
+ #
92
+ # @see ActiveAgent::Base.logger=
93
+ def logger=(value)
94
+ ActiveAgent::Base.logger = value
95
+ end
96
+
97
+ # Loads configuration from a YAML file.
98
+ #
99
+ # Reads a YAML configuration file, evaluates any ERB templates, and extracts
100
+ # environment-specific settings based on RAILS_ENV or ENV environment variables.
101
+ # Falls back to the root level settings if no environment key is found.
102
+ #
103
+ # The YAML file contains provider-specific configurations (API keys, models,
104
+ # parameters, retry settings). Provider configurations are stored as nested hashes
105
+ # and can be accessed via the [] operator.
106
+ #
107
+ # @param filename [String] Path to the YAML configuration file
108
+ # @return [Configuration] A new Configuration instance with loaded settings
109
+ #
110
+ # @example Provider-specific configuration with YAML anchors
111
+ # # config/activeagent.yml
112
+ # openai: &openai
113
+ # service: "OpenAI"
114
+ # access_token: <%= Rails.application.credentials.dig(:openai, :access_token) %>
115
+ # max_retries: 3
116
+ #
117
+ # anthropic: &anthropic
118
+ # service: "Anthropic"
119
+ # access_token: <%= Rails.application.credentials.dig(:anthropic, :access_token) %>
120
+ # max_retries: 5
121
+ #
122
+ # open_router: &open_router
123
+ # service: "OpenRouter"
124
+ # access_token: <%= Rails.application.credentials.dig(:open_router, :access_token) %>
125
+ #
126
+ # development:
127
+ # openai:
128
+ # <<: *openai
129
+ # model: "gpt-4o-mini"
130
+ # temperature: 0.7
131
+ # anthropic:
132
+ # <<: *anthropic
133
+ # model: "claude-3-5-sonnet-20241022"
134
+ # open_router:
135
+ # <<: *open_router
136
+ # model: "qwen/qwen3-30b-a3b:free"
137
+ #
138
+ # test:
139
+ # openai:
140
+ # <<: *openai
141
+ # model: "gpt-4o-mini"
142
+ # anthropic:
143
+ # <<: *anthropic
144
+ #
145
+ # production:
146
+ # openai:
147
+ # <<: *openai
148
+ # model: "gpt-4o"
149
+ # temperature: 0.5
150
+ # anthropic:
151
+ # <<: *anthropic
152
+ # model: "claude-3-5-sonnet-20241022"
153
+ #
154
+ # @example Loading and accessing provider configuration
155
+ # config = ActiveAgent::Configuration.load("config/activeagent.yml")
156
+ # config[:openai] # => { "service" => "OpenAI", "model" => "gpt-4o-mini", ... }
157
+ #
158
+ # @note ERB templates are evaluated, allowing you to use Rails credentials,
159
+ # environment variables, or any Ruby code within <%= %> tags.
160
+ def self.load(filename)
161
+ settings = {}
162
+
163
+ if File.exist?(filename)
164
+ config_file = YAML.load(ERB.new(File.read(filename)).result, aliases: true)
165
+ env = ENV["RAILS_ENV"] || ENV["ENV"] || "development"
166
+ settings = config_file[env] || config_file
167
+ end
168
+
169
+ Configuration.new(settings)
170
+ end
171
+
172
+ # Initializes a new Configuration instance with default values.
173
+ #
174
+ # Sets all configuration attributes to their default values as defined
175
+ # in {DEFAULTS}. Duplicates values where possible to prevent shared state.
176
+ # Custom settings can be passed to override defaults.
177
+ #
178
+ # When loading from a YAML file via {Configuration.load}, all settings from
179
+ # the environment-specific section are passed as the settings hash, including
180
+ # Initializes a new Configuration instance with optional settings.
181
+ #
182
+ # Settings typically come from a YAML configuration file loaded via {.load}.
183
+ # The configuration object stores provider-specific settings as nested hashes.
184
+ #
185
+ # @param settings [Hash] Optional settings to load
186
+ #
187
+ # @example With default settings
188
+ # config = ActiveAgent::Configuration.new
189
+ #
190
+ # @example With provider configurations (typically from YAML)
191
+ # config = ActiveAgent::Configuration.new(
192
+ # openai: { service: "OpenAI", model: "gpt-4o" },
193
+ # anthropic: { service: "Anthropic", model: "claude-3-5-sonnet-20241022" }
194
+ # )
195
+ def initialize(settings = {})
196
+ (DEFAULTS.merge(settings)).each do |key, value|
197
+ self[key] = value
198
+ end
19
199
  end
20
- end
21
200
 
22
- class << self
23
- def configuration
24
- @configuration ||= Configuration.new
201
+ # Retrieves a configuration value by key.
202
+ #
203
+ # This method provides hash-like access to provider configurations.
204
+ # Provider configurations are stored as nested hashes.
205
+ #
206
+ # @param key [String, Symbol] Configuration key to retrieve
207
+ # @return [Object, nil] The configuration value or nil if not found
208
+ #
209
+ # @example Accessing provider configurations
210
+ # config[:openai] # => { "service" => "OpenAI", "model" => "gpt-4o", ... }
211
+ # config[:anthropic] # => { "service" => "Anthropic", "model" => "claude-3-5-sonnet-20241022", ... }
212
+ def [](key)
213
+ instance_variable_get("@#{key}")
25
214
  end
26
215
 
27
- def configure
28
- yield configuration if block_given?
29
- configuration
216
+ # Sets a configuration value by key.
217
+ #
218
+ # @param key [String, Symbol] Configuration key to set
219
+ # @param value [Object] Value to set
220
+ # @return [Object] The value that was set
221
+ #
222
+ # @example
223
+ # config[:retries] = false
224
+ # config["retries_count"] = 5
225
+ def []=(key, value)
226
+ instance_variable_set("@#{key}", convert_to_indifferent_access(value))
227
+ end
228
+
229
+ # Extracts nested values using a sequence of keys.
230
+ #
231
+ # Similar to Hash#dig, traverses nested configuration values safely.
232
+ # Returns nil if any intermediate key doesn't exist.
233
+ #
234
+ # @param keys [Array<String, Symbol>] Keys to traverse
235
+ # @return [Object, nil] The nested value or nil
236
+ #
237
+ # @example
238
+ # config.dig(:openai, :model) # => "gpt-4o"
239
+ # config.dig("test", "anthropic", "service") # => "Anthropic"
240
+ # config.dig(:nonexistent, :key) # => nil
241
+ def dig(*keys)
242
+ keys.reduce(self) do |obj, key|
243
+ break nil unless obj
244
+ if obj.is_a?(Configuration)
245
+ obj[key]
246
+ elsif obj.respond_to?(:dig)
247
+ obj.dig(key)
248
+ elsif obj.respond_to?(:[])
249
+ obj[key]
250
+ else
251
+ nil
252
+ end
253
+ end
254
+ end
255
+
256
+ # Creates a deep duplicate of the configuration.
257
+ #
258
+ # Recursively duplicates all configuration values to avoid shared state.
259
+ #
260
+ # @return [Configuration] A new Configuration instance with duplicated values
261
+ #
262
+ # @example
263
+ # original = ActiveAgent.configuration
264
+ # backup = original.deep_dup
265
+ # backup[:openai] = { service: "OpenAI" } # doesn't affect original
266
+ def deep_dup
267
+ new_config = Configuration.new
268
+ instance_variables.each do |var|
269
+ value = instance_variable_get(var)
270
+ new_config.instance_variable_set(var, deep_dup_value(value))
271
+ end
272
+ new_config
273
+ end
274
+
275
+ # Replaces the current configuration values with those from another configuration.
276
+ #
277
+ # Copies all instance variables from the source configuration to this one,
278
+ # and removes any instance variables that exist in self but not in other.
279
+ # Useful for restoring configuration state in tests.
280
+ #
281
+ # @param other [Configuration] The configuration to copy from
282
+ # @return [Configuration] Self
283
+ #
284
+ # @example
285
+ # backup = config.deep_dup
286
+ # # ... make changes ...
287
+ # config.replace(backup) # restore original state
288
+ def replace(other)
289
+ # Remove variables that exist in self but not in other
290
+ (instance_variables - other.instance_variables).each do |var|
291
+ remove_instance_variable(var)
292
+ end
293
+
294
+ # Copy all variables from other to self
295
+ other.instance_variables.each do |var|
296
+ instance_variable_set(var, other.instance_variable_get(var))
297
+ end
298
+
299
+ self
30
300
  end
31
301
 
32
- def reset_configuration!
33
- @configuration = Configuration.new
302
+ # Delegates method calls to the [] operator for accessing configuration values.
303
+ #
304
+ # Allows accessing configuration values using method syntax instead of
305
+ # hash-like access. Returns nil for undefined configuration keys.
306
+ #
307
+ # @param method [Symbol] The method name (configuration key)
308
+ # @param args [Array] Method arguments (not used)
309
+ # @return [Object, nil] The configuration value or nil
310
+ # @private
311
+ #
312
+ # @example
313
+ # config.retries # => true (same as config[:retries])
314
+ # config.retries_count # => 3 (same as config[:retries_count])
315
+ def method_missing(method, *args)
316
+ self[method]
34
317
  end
318
+
319
+ # Checks if the configuration responds to a method.
320
+ #
321
+ # Returns true if an instance variable exists for the given method name,
322
+ # allowing proper introspection of dynamically accessible configuration keys.
323
+ #
324
+ # @param method [Symbol] The method name to check
325
+ # @param include_private [Boolean] Whether to include private methods
326
+ # @return [Boolean] True if the configuration has the key
327
+ # @private
328
+ def respond_to_missing?(method, include_private = false)
329
+ instance_variable_defined?("@#{method}") || super
330
+ end
331
+
332
+ private
333
+
334
+ # Recursively converts hashes to HashWithIndifferentAccess.
335
+ #
336
+ # This ensures that all hash values (including nested hashes) can be
337
+ # accessed using both string and symbol keys. Non-hash values are
338
+ # returned unchanged.
339
+ #
340
+ # @param value [Object] The value to convert
341
+ # @return [Object] The converted value
342
+ # @private
343
+ def convert_to_indifferent_access(value)
344
+ case value
345
+ when Hash
346
+ value.with_indifferent_access.transform_values { |v| convert_to_indifferent_access(v) }
347
+ when Array
348
+ value.map { |v| convert_to_indifferent_access(v) }
349
+ else
350
+ value
351
+ end
352
+ end
353
+
354
+ # Recursively duplicates a value.
355
+ #
356
+ # Creates deep copies of hashes and arrays to avoid shared state.
357
+ # Uses dup for duplicable objects, returns non-duplicable objects as-is.
358
+ #
359
+ # @param value [Object] The value to duplicate
360
+ # @return [Object] The duplicated value
361
+ # @private
362
+ def deep_dup_value(value)
363
+ case value
364
+ when Hash
365
+ value.transform_values { |v| deep_dup_value(v) }
366
+ when Array
367
+ value.map { |v| deep_dup_value(v) }
368
+ else
369
+ value.duplicable? ? value.dup : value
370
+ end
371
+ end
372
+ end
373
+
374
+ # Returns the global configuration instance.
375
+ #
376
+ # Creates a new {Configuration} instance if one doesn't exist.
377
+ #
378
+ # @return [Configuration] The global configuration instance
379
+ #
380
+ # @example Access configuration
381
+ # ActiveAgent.configuration.retries # => true
382
+ def self.configuration
383
+ @configuration ||= Configuration.new
384
+ end
385
+
386
+ # Configures ActiveAgent with a block.
387
+ #
388
+ # Yields the global configuration instance to the provided block,
389
+ # allowing settings to be modified. This is the recommended way
390
+ # to configure ActiveAgent.
391
+ #
392
+ # @yield [config] Yields the configuration instance
393
+ # @yieldparam config [Configuration] The configuration to modify
394
+ # @return [Configuration] The modified configuration instance
395
+ #
396
+ # @example Custom logger (non-Rails environments)
397
+ # ActiveAgent.configure do |config|
398
+ # config.logger = Logger.new(STDOUT)
399
+ # config.logger.level = Logger::DEBUG
400
+ # end
401
+ def self.configure
402
+ yield configuration if block_given?
403
+ configuration
404
+ end
405
+
406
+ # Resets the global configuration to default values.
407
+ #
408
+ # Creates a new {Configuration} instance with all defaults restored.
409
+ # Useful for testing or resetting state.
410
+ #
411
+ # @return [Configuration] The new default configuration instance
412
+ #
413
+ # @example
414
+ # ActiveAgent.reset_configuration!
415
+ def self.reset_configuration!
416
+ @configuration = Configuration.new
417
+ end
418
+
419
+ # Loads and sets the global configuration from a YAML file.
420
+ #
421
+ # Reads configuration from the specified file and sets it as the
422
+ # global configuration instance. This is an alternative to using
423
+ # {.configure} with a block and is the recommended approach for
424
+ # managing provider-specific settings.
425
+ #
426
+ # The YAML file supports ERB templating, environment-specific sections,
427
+ # and YAML anchors for reusing common configuration blocks across providers.
428
+ #
429
+ # @param filename [String] Path to the YAML configuration file
430
+ # @return [Configuration] The loaded configuration instance
431
+ #
432
+ # @example Basic usage in Rails initializer
433
+ # # config/initializers/activeagent.rb
434
+ # ActiveAgent.configuration_load(Rails.root.join("config/activeagent.yml"))
435
+ #
436
+ # @example Complete workflow
437
+ # # 1. Create config/activeagent.yml with provider settings
438
+ # # 2. Load in initializer:
439
+ # ActiveAgent.configuration_load("config/activeagent.yml")
440
+ #
441
+ # # 3. Use in your agents:
442
+ # class MyAgent < ActiveAgent::Base
443
+ # generate_with :openai # Automatically uses config from YAML
444
+ # end
445
+ #
446
+ # @example Accessing loaded provider configuration
447
+ # ActiveAgent.configuration[:openai]
448
+ # # => { "service" => "OpenAI", "model" => "gpt-4o-mini", "temperature" => 0.7, ... }
449
+ #
450
+ # @note This method is typically called once during application initialization.
451
+ # Store API keys in Rails credentials rather than directly in the YAML file.
452
+ #
453
+ # @see Configuration.load
454
+ # @see .configure
455
+ def self.configuration_load(filename)
456
+ @configuration = Configuration.load(filename)
35
457
  end
36
458
  end