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,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/open_ai/chat/requests/messages/content/base"
4
+ require_relative "files/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenRouter
9
+ module Requests
10
+ module Messages
11
+ module Content
12
+ # File content part for OpenRouter.
13
+ #
14
+ # Uses OpenRouter's Files::DetailsType which preserves the data URI prefix
15
+ # instead of stripping it like OpenAI does.
16
+ class File < OpenAI::Chat::Requests::Messages::Content::Base
17
+ attribute :type, :string, as: "file"
18
+ attribute :file, Files::DetailsType.new
19
+
20
+ validates :file, presence: true
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "details"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenRouter
8
+ module Requests
9
+ module Messages
10
+ module Content
11
+ module Files
12
+ # Type for the nested file object in OpenRouter.
13
+ #
14
+ # Uses OpenRouter's Details class which preserves the data URI prefix.
15
+ class DetailsType < ActiveModel::Type::Value
16
+ def cast(value)
17
+ case value
18
+ when Details
19
+ value
20
+ when Hash
21
+ Details.new(**value.deep_symbolize_keys)
22
+ when String
23
+ # Accept both data URIs and plain base64, but preserve the format
24
+ if value.start_with?("data:")
25
+ Details.new(file_data: value)
26
+ elsif value.match?(%r{\Ahttps?://})
27
+ raise ArgumentError, "HTTP/S URLs are not supported. Use a base64 data URI instead"
28
+ else
29
+ Details.new(file_data: value)
30
+ end
31
+ when nil
32
+ nil
33
+ else
34
+ raise ArgumentError, "Cannot cast #{value.class} to File::Details"
35
+ end
36
+ end
37
+
38
+ def serialize(value)
39
+ case value
40
+ when Details
41
+ value.serialize
42
+ when Hash
43
+ value
44
+ when nil
45
+ nil
46
+ else
47
+ raise ArgumentError, "Cannot serialize #{value.class}"
48
+ end
49
+ end
50
+
51
+ def deserialize(value)
52
+ cast(value)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/open_ai/chat/requests/messages/content/files/details"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenRouter
8
+ module Requests
9
+ module Messages
10
+ module Content
11
+ module Files
12
+ # Represents the nested file object within File content part for OpenRouter.
13
+ #
14
+ # Unlike OpenAI which strips the data URI prefix, OpenRouter keeps it intact
15
+ # (e.g., data:application/pdf;base64,) in the file_data field.
16
+ class Details < OpenAI::Chat::Requests::Messages::Content::Files::Details
17
+ # Override the setter to NOT strip the data URI prefix
18
+ attribute :file_data, :string
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/open_ai/chat/requests/messages/user"
4
+ require_relative "content/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenRouter
9
+ module Requests
10
+ module Messages
11
+ # User message for OpenRouter API.
12
+ #
13
+ # Extends OpenAI's user message with OpenRouter-specific content handling.
14
+ # Overrides the content attribute to use OpenRouter's ContentsType which
15
+ # preserves the data URI prefix in file content instead of stripping it.
16
+ class User < OpenAI::Chat::Requests::Messages::User
17
+ attribute :content, Content::ContentsType.new # Override with OpenRouter's content handling
18
+
19
+ %i[text image document].each do |content_type|
20
+ define_method(:"#{content_type}=") do |value|
21
+ self.content ||= []
22
+ self.content += [ { content_type => value } ]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ module OpenRouter
6
+ module Requests
7
+ # Represents a plugin configuration for OpenRouter requests.
8
+ # Currently supports the file-parser plugin for PDF processing.
9
+ #
10
+ # @example
11
+ # plugin = Plugin.new(
12
+ # id: 'file-parser',
13
+ # pdf: { engine: 'pdf-text' }
14
+ # )
15
+ class Plugin < Common::BaseModel
16
+ attribute :id, :string
17
+ attribute :pdf, Plugins::PdfConfigType.new
18
+
19
+ validates :id, presence: true
20
+ validates :id, inclusion: { in: %w[file-parser] }, allow_nil: false
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "pdf_config"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenRouter
8
+ module Requests
9
+ module Plugins
10
+ # Type for PdfConfig
11
+ class PdfConfigType < ActiveModel::Type::Value
12
+ def cast(value)
13
+ case value
14
+ when PdfConfig
15
+ value
16
+ when Hash
17
+ PdfConfig.new(**value.deep_symbolize_keys)
18
+ when nil
19
+ nil
20
+ else
21
+ raise ArgumentError, "Cannot cast #{value.class} to PdfConfig"
22
+ end
23
+ end
24
+
25
+ def serialize(value)
26
+ case value
27
+ when PdfConfig
28
+ value.serialize
29
+ when Hash
30
+ value
31
+ when nil
32
+ nil
33
+ else
34
+ raise ArgumentError, "Cannot serialize #{value.class}"
35
+ end
36
+ end
37
+
38
+ def deserialize(value)
39
+ cast(value)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ module OpenRouter
6
+ module Requests
7
+ module Plugins
8
+ # Configuration for PDF processing in the file-parser plugin.
9
+ #
10
+ # OpenRouter provides several PDF processing engines:
11
+ # - "mistral-ocr": Best for scanned documents or PDFs with images ($2 per 1,000 pages)
12
+ # - "pdf-text": Best for well-structured PDFs with clear text content (Free)
13
+ # - "native": Only available for models that support file input natively (charged as input tokens)
14
+ #
15
+ # If you don't explicitly specify an engine, OpenRouter will default first to the model's
16
+ # native file processing capabilities, and if that's not available, will use the "mistral-ocr" engine.
17
+ #
18
+ # @example
19
+ # pdf_config = PdfConfig.new(engine: 'pdf-text')
20
+ class PdfConfig < Common::BaseModel
21
+ attribute :engine, :string
22
+
23
+ validates :engine, inclusion: { in: %w[mistral-ocr pdf-text native] }, allow_nil: true
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ module OpenRouter
6
+ module Requests
7
+ class Prediction < Common::BaseModel
8
+ attribute :type, :string
9
+ attribute :content, :string
10
+
11
+ validates :type, inclusion: { in: %w[content] }, allow_nil: true
12
+ validates :content, presence: true, if: -> { type.present? }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "max_price"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenRouter
8
+ module Requests
9
+ # Type for MaxPrice
10
+ class MaxPriceType < ActiveModel::Type::Value
11
+ def cast(value)
12
+ case value
13
+ when MaxPrice
14
+ value
15
+ when Hash
16
+ MaxPrice.new(**value.deep_symbolize_keys)
17
+ when nil
18
+ nil
19
+ else
20
+ raise ArgumentError, "Cannot cast #{value.class} to MaxPrice"
21
+ end
22
+ end
23
+
24
+ def serialize(value)
25
+ case value
26
+ when MaxPrice
27
+ value.serialize
28
+ when Hash
29
+ value
30
+ when nil
31
+ nil
32
+ else
33
+ raise ArgumentError, "Cannot serialize #{value.class}"
34
+ end
35
+ end
36
+
37
+ def deserialize(value)
38
+ cast(value)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ module OpenRouter
6
+ module Requests
7
+ # Maximum price configuration for provider routing
8
+ # Specifies USD price per million tokens for different operations
9
+ # See: https://openrouter.ai/docs/provider-routing
10
+ class MaxPrice < Common::BaseModel
11
+ attribute :prompt, :float # Price per million prompt tokens (input)
12
+ attribute :completion, :float # Price per million completion tokens (output)
13
+ attribute :image, :float # Price per image
14
+ attribute :audio, :float # Price per audio unit
15
+ attribute :request, :float # Price per request
16
+
17
+ validates :prompt, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
18
+ validates :completion, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
19
+ validates :image, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
20
+ validates :audio, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
21
+ validates :request, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
22
+
23
+ # Backwards Compatibility
24
+ alias_attribute :prompt_tokens, :prompt
25
+ alias_attribute :completion_tokens, :completion
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "provider_preferences/_types"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenRouter
8
+ module Requests
9
+ # Provider preferences for routing requests to specific providers
10
+ # See: https://openrouter.ai/docs/provider-routing
11
+ class ProviderPreferences < Common::BaseModel
12
+ # Whether to allow backup providers to serve requests
13
+ # - true: (default) when primary provider is unavailable, use next best provider
14
+ # - false: use only primary/custom provider, return upstream error if unavailable
15
+ attribute :allow_fallbacks, :boolean
16
+
17
+ # Whether to filter providers to only those that support provided parameters
18
+ # If false, providers receive only parameters they support and ignore the rest
19
+ attribute :require_parameters, :boolean
20
+
21
+ # Data collection setting
22
+ # - allow: (default) allow providers which store user data and may train on it
23
+ # - deny: use only providers which do not collect user data
24
+ attribute :data_collection, :string
25
+
26
+ # Zero Data Retention - stricter privacy mode
27
+ attribute :zdr, :boolean
28
+
29
+ # Ordered list of provider slugs to try in order
30
+ attribute :order, default: -> { [] }
31
+
32
+ # List of provider slugs to allow (merged with account-wide settings)
33
+ attribute :only, default: -> { [] }
34
+
35
+ # List of provider slugs to ignore (merged with account-wide settings)
36
+ attribute :ignore, default: -> { [] }
37
+
38
+ # List of quantization levels to filter providers by
39
+ # Options: int4, int8, fp4, fp6, fp8, fp16, bf16, fp32, unknown
40
+ attribute :quantizations, default: -> { [] }
41
+
42
+ # Sorting strategy to use if "order" is not specified
43
+ # Options: price, throughput, latency
44
+ # When set, no load balancing is performed
45
+ attribute :sort, :string
46
+
47
+ # Maximum price constraints (USD per million tokens)
48
+ attribute :max_price, MaxPriceType.new
49
+
50
+ # Validations matching the schema
51
+ validates :data_collection, inclusion: { in: %w[deny allow] }, allow_nil: true
52
+ validates :sort, inclusion: { in: %w[price throughput latency] }, allow_nil: true
53
+ validates :quantizations, inclusion: {
54
+ in: [ %w[int4 int8 fp4 fp6 fp8 fp16 bf16 fp32 unknown].freeze ],
55
+ message: "must contain valid quantization levels"
56
+ }, allow_nil: true, if: -> { quantizations.is_a?(Array) && quantizations.any? }
57
+
58
+ # Backwards Compatibility
59
+ alias_attribute :enable_fallbacks, :allow_fallbacks
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Providers
5
+ module OpenRouter
6
+ module Requests
7
+ class ResponseFormat < Common::BaseModel
8
+ # Type of response format (json_object, json_schema)
9
+ attribute :type, :string
10
+
11
+ # JSON schema configuration (only for json_schema type)
12
+ attribute :json_schema # Hash with name, description, schema, strict
13
+
14
+ validates :type, inclusion: { in: %w[json_object json_schema] }, allow_nil: true
15
+
16
+ # Validate that json_schema is present when type is json_schema
17
+ validate :validate_json_schema_presence
18
+
19
+ private
20
+
21
+ def validate_json_schema_presence
22
+ if type == "json_schema" && json_schema.blank?
23
+ errors.add(:json_schema, "must be present when type is 'json_schema'")
24
+ end
25
+
26
+ if json_schema.present? && json_schema.is_a?(Hash)
27
+ validate_json_schema_structure
28
+ end
29
+ end
30
+
31
+ def validate_json_schema_structure
32
+ unless json_schema[:name].present?
33
+ errors.add(:json_schema, "must include 'name' field")
34
+ end
35
+
36
+ if json_schema[:name].present? && json_schema[:name].length > 64
37
+ errors.add(:json_schema, "name must be 64 characters or less")
38
+ end
39
+
40
+ # Name must match pattern: a-z, A-Z, 0-9, underscores and dashes
41
+ if json_schema[:name].present? && json_schema[:name] !~ /^[a-zA-Z0-9_-]+$/
42
+ errors.add(:json_schema, "name must contain only a-z, A-Z, 0-9, underscores and dashes")
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ require_relative "_base_provider"
2
+
3
+ require_gem!(:openai, __FILE__)
4
+
5
+ require_relative "open_ai_provider"
6
+ require_relative "open_router/_types"
7
+
8
+ module ActiveAgent
9
+ module Providers
10
+ # Provides access to OpenRouter's multi-model API.
11
+ #
12
+ # Extends OpenAI provider to work with OpenRouter's OpenAI-compatible API,
13
+ # enabling access to multiple AI models through a single interface with
14
+ # model fallbacks, cost tracking, and provider metadata.
15
+ #
16
+ # @see OpenAI::ChatProvider
17
+ # @see https://openrouter.ai/docs
18
+ class OpenRouterProvider < OpenAI::ChatProvider
19
+ # @return [String]
20
+ def self.service_name
21
+ "OpenRouter"
22
+ end
23
+
24
+ # @return [Class]
25
+ def self.options_klass
26
+ namespace::Options
27
+ end
28
+
29
+ # @return [ActiveModel::Type::Value]
30
+ def self.prompt_request_type
31
+ namespace::RequestType.new
32
+ end
33
+
34
+ protected
35
+
36
+ # Merges streaming delta into the message with role cleanup.
37
+ #
38
+ # Overrides parent to handle OpenRouter's role copying behavior which duplicates
39
+ # the role field in every streaming chunk, requiring manual cleanup to prevent
40
+ # message corruption.
41
+ #
42
+ # @see OpenAI::ChatProvider#message_merge_delta
43
+ # @param message [Hash]
44
+ # @param delta [Hash]
45
+ # @return [Hash]
46
+ def message_merge_delta(message, delta)
47
+ message[:role] = delta.delete(:role) if delta[:role] # Copy a Bad Design (OpenAI's Chat API) Badly, Win Bad Prizes
48
+
49
+ hash_merge_delta(message, delta)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,2 @@
1
+ # OpenAI, "Your tacky and I hate you" - Billy, https://youtu.be/dsheboxJNgQ?si=tzDlJ7sdSxM4RjSD
2
+ require_relative "open_ai_provider"
@@ -0,0 +1,2 @@
1
+ # OpenRouter, just copying OpenAI
2
+ require_relative "open_router_provider"
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails"
3
4
  require "active_job/railtie"
4
5
  require "active_agent"
5
- # require "active_agent/engine"
6
- require "rails"
7
- require "abstract_controller/railties/routes_helpers"
8
6
  require "active_agent/railtie/schema_generator_extension"
7
+ require "abstract_controller/railties/routes_helpers"
9
8
 
10
9
  module ActiveAgent
11
10
  class Railtie < Rails::Railtie # :nodoc:
@@ -22,7 +21,7 @@ module ActiveAgent
22
21
  end
23
22
 
24
23
  initializer "active_agent.set_configs" do |app|
25
- paths = app.config.paths
24
+ paths = app.config.paths
26
25
  options = app.config.active_agent
27
26
 
28
27
  options.assets_dir ||= paths["public"].first
@@ -33,10 +32,13 @@ module ActiveAgent
33
32
  options.preview_paths |= [ "#{Rails.root}/test/agents/previews" ]
34
33
 
35
34
  # make sure readers methods get compiled
36
- options.asset_host ||= app.config.asset_host
35
+ options.asset_host ||= app.config.asset_host
37
36
  options.relative_url_root ||= app.config.relative_url_root
38
37
 
39
- ActiveAgent.load_configuration(Rails.root.join("config", "active_agent.yml"))
38
+ # region configuration_load
39
+ # Loaded automatically via Railtie
40
+ ActiveAgent.configuration_load(Rails.root.join("config", "active_agent.yml"))
41
+ # endregion configuration_load
40
42
 
41
43
  ActiveSupport.on_load(:active_agent) do
42
44
  include AbstractController::UrlFor