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,95 @@
1
+ require_relative "_base_provider"
2
+
3
+ require_gem!(:openai, __FILE__)
4
+
5
+ require_relative "open_ai_provider"
6
+ require_relative "ollama/_types"
7
+
8
+ module ActiveAgent
9
+ module Providers
10
+ # Connects to local Ollama instances via OpenAI-compatible API.
11
+ #
12
+ # Provides chat completion and embedding functionality through locally-hosted
13
+ # Ollama models. Handles connection errors specific to local deployments.
14
+ #
15
+ # @see OpenAI::ChatProvider
16
+ class OllamaProvider < OpenAI::ChatProvider
17
+ # @return [String]
18
+ def self.service_name
19
+ "Ollama"
20
+ end
21
+
22
+ # @return [Class]
23
+ def self.options_klass
24
+ namespace::Options
25
+ end
26
+
27
+ # @return [ActiveModel::Type::Value]
28
+ def self.prompt_request_type
29
+ namespace::Chat::RequestType.new
30
+ end
31
+
32
+ # @return [ActiveModel::Type::Value]
33
+ def self.embed_request_type
34
+ namespace::Embedding::RequestType.new
35
+ end
36
+
37
+ protected
38
+
39
+ # Executes chat completion request with Ollama-specific error handling.
40
+ #
41
+ # @see OpenAI::ChatProvider#api_prompt_execute
42
+ # @param parameters [Hash]
43
+ # @return [Object, nil] response object or nil for streaming
44
+ # @raise [OpenAI::Errors::APIConnectionError] when Ollama server unreachable
45
+ def api_prompt_execute(parameters)
46
+ super
47
+
48
+ rescue ::OpenAI::Errors::APIConnectionError => exception
49
+ log_connection_error(exception)
50
+ raise exception
51
+ end
52
+
53
+ # Executes embedding request with Ollama-specific error handling.
54
+ #
55
+ # @param parameters [Hash]
56
+ # @return [Hash] symbolized API response
57
+ # @raise [OpenAI::Errors::APIConnectionError] when Ollama server unreachable
58
+ def api_embed_execute(parameters)
59
+ instrument("embeddings_request.provider.active_agent")
60
+ client.embeddings.create(**parameters).as_json.deep_symbolize_keys
61
+
62
+ rescue ::OpenAI::Errors::APIConnectionError => exception
63
+ log_connection_error(exception)
64
+ raise exception
65
+ end
66
+
67
+ # Handles role duplication bug in Ollama's OpenAI-compatible streaming.
68
+ #
69
+ # Ollama duplicates role information in streaming deltas, requiring
70
+ # manual cleanup to prevent message corruption. This fixes the
71
+ # "role appears in every chunk" issue when using streaming responses.
72
+ #
73
+ # @see OpenAI::ChatProvider#message_merge_delta
74
+ # @param message [Hash]
75
+ # @param delta [Hash]
76
+ # @return [Hash]
77
+ def message_merge_delta(message, delta)
78
+ message[:role] = delta.delete(:role) if delta[:role] # Copy a Bad Design (OpenAI's Chat API) Badly, Win Bad Prizes
79
+
80
+ hash_merge_delta(message, delta)
81
+ end
82
+
83
+ # Logs connection failures with Ollama server details for debugging.
84
+ #
85
+ # @param error [Exception]
86
+ # @return [void]
87
+ def log_connection_error(error)
88
+ instrument("connection_error.provider.active_agent",
89
+ uri_base: options.uri_base,
90
+ exception: error.class,
91
+ message: error.message)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,58 @@
1
+ require_relative "../_base_provider"
2
+
3
+ require_gem!(:openai, __FILE__)
4
+
5
+ require_relative "options"
6
+
7
+ module ActiveAgent
8
+ module Providers
9
+ module OpenAI
10
+ # Base provider class for OpenAI API implementations.
11
+ #
12
+ # Provides common functionality for OpenAI-based providers including
13
+ # client configuration, service identification, and tool call processing.
14
+ #
15
+ # @see ActiveAgent::Providers::BaseProvider
16
+ class Base < ActiveAgent::Providers::BaseProvider
17
+ # Returns the service name for OpenAI providers.
18
+ #
19
+ # @return [String] Always returns "OpenAI"
20
+ def self.service_name
21
+ "OpenAI"
22
+ end
23
+
24
+ # Returns a configured OpenAI client instance.
25
+ #
26
+ # @return [OpenAI::Client] The configured OpenAI client
27
+ def client
28
+ ::OpenAI::Client.new(**options.serialize)
29
+ end
30
+
31
+ protected
32
+
33
+ # Processes a tool call function from the API response.
34
+ #
35
+ # This method extracts the function name and arguments from an API function call,
36
+ # parses the arguments as JSON, and invokes the function callback with the parsed parameters.
37
+ #
38
+ # @param api_function_call [Hash] The function call data from the API response
39
+ # @option api_function_call [String] :name The name of the function to call
40
+ # @option api_function_call [String] :arguments JSON string containing the function arguments
41
+ #
42
+ # @return [Object] The result of the function callback invocation
43
+ #
44
+ # @example Processing a tool call
45
+ # api_call = { name: "get_weather", arguments: '{"location":"NYC"}' }
46
+ # process_tool_call_function(api_call)
47
+ # # => calls tools_function.call("get_weather", location: "NYC")
48
+ def process_tool_call_function(api_function_call)
49
+ name = api_function_call[:name]
50
+ kwargs = JSON.parse(api_function_call[:arguments], symbolize_names: true) if api_function_call[:arguments]
51
+
52
+ instrument("tool_execution.provider.active_agent", tool_name: name)
53
+ tools_function.call(name, **kwargs)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "chat/_types"
4
+ require_relative "embedding/_types"
5
+ require_relative "responses/_types"
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "request"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ # Type for Request model
10
+ class RequestType < ActiveModel::Type::Value
11
+ def cast(value)
12
+ case value
13
+ when Request
14
+ value
15
+ when Hash
16
+ Request.new(**value.deep_symbolize_keys)
17
+ when nil
18
+ nil
19
+ else
20
+ raise ArgumentError, "Cannot cast #{value.class} to Request"
21
+ end
22
+ end
23
+
24
+ def serialize(value)
25
+ case value
26
+ when Request
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,215 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+ require_relative "requests/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Chat
10
+ class Request < Common::BaseModel
11
+ # Messages array (required)
12
+ attribute :messages, Requests::Messages::MessagesType.new
13
+
14
+ # Model ID (required)
15
+ attribute :model, :string
16
+
17
+ # Audio output parameters
18
+ attribute :audio, Requests::AudioType.new
19
+
20
+ # Frequency penalty
21
+ attribute :frequency_penalty, :float, default: 0
22
+
23
+ # Deprecated: function_call (use tool_choice instead)
24
+ attribute :function_call # String or object
25
+
26
+ # Deprecated: functions (use tools instead)
27
+ attribute :functions # Array of function objects
28
+
29
+ # Logit bias
30
+ attribute :logit_bias # Hash of token_id => bias_value
31
+
32
+ # Log probabilities
33
+ attribute :logprobs, :boolean, default: false
34
+
35
+ # Max completion tokens
36
+ attribute :max_completion_tokens, :integer
37
+
38
+ # Deprecated: max_tokens (use max_completion_tokens)
39
+ attribute :max_tokens, :integer
40
+
41
+ # Metadata
42
+ attribute :metadata # Hash of key-value pairs
43
+
44
+ # Modalities
45
+ attribute :modalities, default: -> { [ "text" ] } # Array of strings
46
+
47
+ # Number of completions
48
+ attribute :n, :integer, default: 1
49
+
50
+ # Parallel tool calls
51
+ attribute :parallel_tool_calls, :boolean, default: true
52
+
53
+ # Prediction configuration
54
+ attribute :prediction, Requests::PredictionType.new
55
+
56
+ # Presence penalty
57
+ attribute :presence_penalty, :float, default: 0
58
+
59
+ # Prompt cache key
60
+ attribute :prompt_cache_key, :string
61
+
62
+ # Reasoning effort (for reasoning models)
63
+ attribute :reasoning_effort, :string
64
+
65
+ # Response format
66
+ attribute :response_format, Requests::ResponseFormatType.new
67
+
68
+ # Safety identifier
69
+ attribute :safety_identifier, :string
70
+
71
+ # Deprecated: seed
72
+ attribute :seed, :integer
73
+
74
+ # Service tier
75
+ attribute :service_tier, :string, default: "auto"
76
+
77
+ # Stop sequences
78
+ attribute :stop # String, array, or null
79
+
80
+ # Storage
81
+ attribute :store, :boolean, default: false
82
+
83
+ # Streaming
84
+ attribute :stream, :boolean, default: false
85
+ attribute :stream_options, Requests::StreamOptionsType.new
86
+
87
+ # Temperature sampling
88
+ attribute :temperature, :float, default: 1
89
+
90
+ # Tool choice
91
+ attribute :tool_choice, Requests::ToolChoiceType.new
92
+
93
+ # Tools array
94
+ attribute :tools # Array of tool objects
95
+
96
+ # Top logprobs
97
+ attribute :top_logprobs, :integer
98
+
99
+ # Top P sampling
100
+ attribute :top_p, :float, default: 1
101
+
102
+ # Deprecated: user (use safety_identifier or prompt_cache_key)
103
+ attribute :user, :string
104
+
105
+ # Verbosity (for reasoning models)
106
+ attribute :verbosity, :string
107
+
108
+ # Web search options
109
+ attribute :web_search_options, Requests::WebSearchOptionsType.new
110
+
111
+ # Validations
112
+ validates :model, :messages, presence: true
113
+
114
+ validates :frequency_penalty, numericality: { greater_than_or_equal_to: -2.0, less_than_or_equal_to: 2.0 }, allow_nil: true
115
+ validates :presence_penalty, numericality: { greater_than_or_equal_to: -2.0, less_than_or_equal_to: 2.0 }, allow_nil: true
116
+ validates :temperature, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 2 }, allow_nil: true
117
+ validates :top_p, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1 }, allow_nil: true
118
+ validates :top_logprobs, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 20 }, allow_nil: true
119
+ validates :n, numericality: { greater_than: 0 }, allow_nil: true
120
+ validates :max_completion_tokens, numericality: { greater_than: 0 }, allow_nil: true
121
+ validates :max_tokens, numericality: { greater_than: 0 }, allow_nil: true
122
+
123
+ validates :service_tier, inclusion: { in: %w[auto default flex priority] }, allow_nil: true
124
+ validates :reasoning_effort, inclusion: { in: %w[minimal low medium high] }, allow_nil: true
125
+ validates :verbosity, inclusion: { in: %w[low medium high] }, allow_nil: true
126
+ validates :modalities, inclusion: { in: %w[text audio] }, allow_nil: true
127
+
128
+ # Custom validations
129
+ validate :validate_metadata_format
130
+ validate :validate_logit_bias_format
131
+ validate :validate_stop_sequences
132
+
133
+ def serialize
134
+ super.tap do |hash|
135
+ # Can be an empty hash, to enable the feature
136
+ hash[:web_search_options] ||= {} if web_search_options
137
+ end
138
+ end
139
+
140
+ # Common Format Compatability
141
+ def instructions=(*values)
142
+ self.messages ||= []
143
+
144
+ values.flatten.reverse.each do |value|
145
+ self.messages.unshift({ role: "developer", content: value })
146
+ end
147
+ end
148
+
149
+ # Common Format Compatability
150
+ alias_attribute :message, :messages
151
+
152
+ # Common Format Compatability
153
+ def messages=(value)
154
+ case value
155
+ when Array
156
+ super((messages || []) | value)
157
+ else
158
+ super((messages || []) | [ value ])
159
+ end
160
+ end
161
+
162
+ private
163
+
164
+ def validate_metadata_format
165
+ return if metadata.nil?
166
+
167
+ unless metadata.is_a?(Hash)
168
+ errors.add(:metadata, "must be a hash")
169
+ return
170
+ end
171
+
172
+ metadata.each do |key, value|
173
+ if key.to_s.length > 64
174
+ errors.add(:metadata, "keys must be 64 characters or less")
175
+ end
176
+ if value.to_s.length > 512
177
+ errors.add(:metadata, "values must be 512 characters or less")
178
+ end
179
+ end
180
+
181
+ if metadata.size > 16
182
+ errors.add(:metadata, "must have 16 key-value pairs or less")
183
+ end
184
+ end
185
+
186
+ def validate_logit_bias_format
187
+ return if logit_bias.nil?
188
+
189
+ unless logit_bias.is_a?(Hash)
190
+ errors.add(:logit_bias, "must be a hash")
191
+ return
192
+ end
193
+
194
+ logit_bias.each do |token_id, bias|
195
+ unless bias.is_a?(Numeric) && bias >= -100 && bias <= 100
196
+ errors.add(:logit_bias, "bias values must be between -100 and 100")
197
+ end
198
+ end
199
+ end
200
+
201
+ def validate_stop_sequences
202
+ return if stop.nil?
203
+ return if stop.is_a?(String)
204
+
205
+ if stop.is_a?(Array)
206
+ errors.add(:stop, "can have at most 4 sequences") if stop.length > 4
207
+ else
208
+ errors.add(:stop, "must be a string, array, or null")
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "messages/_types"
4
+ require_relative "tools/_types"
5
+
6
+ require_relative "audio"
7
+ require_relative "prediction"
8
+ require_relative "response_format"
9
+ require_relative "stream_options"
10
+ require_relative "tool_choice"
11
+ require_relative "web_search_options"
12
+
13
+ module ActiveAgent
14
+ module Providers
15
+ module OpenAI
16
+ module Chat
17
+ module Requests
18
+ # Type for Audio
19
+ class AudioType < ActiveModel::Type::Value
20
+ def cast(value)
21
+ case value
22
+ when Audio
23
+ value
24
+ when Hash
25
+ Audio.new(**value.symbolize_keys)
26
+ when nil
27
+ nil
28
+ else
29
+ raise ArgumentError, "Cannot cast #{value.class} to Audio"
30
+ end
31
+ end
32
+
33
+ def serialize(value)
34
+ case value
35
+ when Audio
36
+ value.serialize
37
+ when Hash
38
+ value
39
+ when nil
40
+ nil
41
+ else
42
+ raise ArgumentError, "Cannot serialize #{value.class}"
43
+ end
44
+ end
45
+
46
+ def deserialize(value)
47
+ cast(value)
48
+ end
49
+ end
50
+
51
+ # Type for Prediction
52
+ class PredictionType < ActiveModel::Type::Value
53
+ def cast(value)
54
+ case value
55
+ when Prediction
56
+ value
57
+ when Hash
58
+ Prediction.new(**value.symbolize_keys)
59
+ when nil
60
+ nil
61
+ else
62
+ raise ArgumentError, "Cannot cast #{value.class} to Prediction"
63
+ end
64
+ end
65
+
66
+ def serialize(value)
67
+ case value
68
+ when Prediction
69
+ value.serialize
70
+ when Hash
71
+ value
72
+ when nil
73
+ nil
74
+ else
75
+ raise ArgumentError, "Cannot serialize #{value.class}"
76
+ end
77
+ end
78
+
79
+ def deserialize(value)
80
+ cast(value)
81
+ end
82
+ end
83
+
84
+ # Type for ResponseFormat
85
+ class ResponseFormatType < ActiveModel::Type::Value
86
+ def cast(value)
87
+ case value
88
+ when ResponseFormat
89
+ value
90
+ when Hash
91
+ ResponseFormat.new(**value.symbolize_keys)
92
+ when nil
93
+ nil
94
+ else
95
+ raise ArgumentError, "Cannot cast #{value.class} to ResponseFormat"
96
+ end
97
+ end
98
+
99
+ def serialize(value)
100
+ case value
101
+ when ResponseFormat
102
+ value.serialize
103
+ when Hash
104
+ value
105
+ when nil
106
+ nil
107
+ else
108
+ raise ArgumentError, "Cannot serialize #{value.class}"
109
+ end
110
+ end
111
+
112
+ def deserialize(value)
113
+ cast(value)
114
+ end
115
+ end
116
+
117
+ # Type for StreamOptions
118
+ class StreamOptionsType < ActiveModel::Type::Value
119
+ def cast(value)
120
+ case value
121
+ when StreamOptions
122
+ value
123
+ when Hash
124
+ StreamOptions.new(**value.symbolize_keys)
125
+ when nil
126
+ nil
127
+ else
128
+ raise ArgumentError, "Cannot cast #{value.class} to StreamOptions"
129
+ end
130
+ end
131
+
132
+ def serialize(value)
133
+ case value
134
+ when StreamOptions
135
+ value.serialize
136
+ when Hash
137
+ value
138
+ when nil
139
+ nil
140
+ else
141
+ raise ArgumentError, "Cannot serialize #{value.class}"
142
+ end
143
+ end
144
+
145
+ def deserialize(value)
146
+ cast(value)
147
+ end
148
+ end
149
+
150
+ # Type for ToolChoice
151
+ class ToolChoiceType < ActiveModel::Type::Value
152
+ def cast(value)
153
+ case value
154
+ when ToolChoice
155
+ value
156
+ when Hash
157
+ ToolChoice.new(**value.symbolize_keys)
158
+ when String
159
+ ToolChoice.new(mode: value)
160
+ when nil
161
+ nil
162
+ else
163
+ raise ArgumentError, "Cannot cast #{value.class} to ToolChoice"
164
+ end
165
+ end
166
+
167
+ def serialize(value)
168
+ case value
169
+ when ToolChoice
170
+ hash = value.serialize
171
+ # If it's just a mode string, return the string
172
+ if hash[:mode].present? && hash[:type].blank? && hash[:function].blank? && hash[:custom].blank? && hash[:allowed_tools].blank?
173
+ hash[:mode]
174
+ else
175
+ hash
176
+ end
177
+ when Hash
178
+ value
179
+ when String
180
+ value
181
+ when nil
182
+ nil
183
+ else
184
+ raise ArgumentError, "Cannot serialize #{value.class}"
185
+ end
186
+ end
187
+
188
+ def deserialize(value)
189
+ cast(value)
190
+ end
191
+ end
192
+
193
+ # Type for WebSearchOptions
194
+ class WebSearchOptionsType < ActiveModel::Type::Value
195
+ def cast(value)
196
+ case value
197
+ when WebSearchOptions
198
+ value
199
+ when Hash
200
+ WebSearchOptions.new(**value.symbolize_keys)
201
+ when nil
202
+ nil
203
+ else
204
+ raise ArgumentError, "Cannot cast #{value.class} to WebSearchOptions"
205
+ end
206
+ end
207
+
208
+ def serialize(value)
209
+ case value
210
+ when WebSearchOptions
211
+ value.serialize
212
+ when Hash
213
+ value
214
+ when nil
215
+ nil
216
+ else
217
+ raise ArgumentError, "Cannot serialize #{value.class}"
218
+ end
219
+ end
220
+
221
+ def deserialize(value)
222
+ cast(value)
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ class Audio < Common::BaseModel
11
+ # Voice to use for audio output
12
+ attribute :voice, :string
13
+
14
+ # Audio format
15
+ attribute :format, :string
16
+
17
+ validates :voice, inclusion: { in: %w[alloy ash ballad coral echo fable nova onyx sage shimmer] }, allow_nil: true
18
+ validates :format, inclusion: { in: %w[wav mp3 flac opus pcm16] }, allow_nil: true
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end