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,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ module Messages
11
+ # Function message - result from a function call (deprecated)
12
+ class Function < Base
13
+ attribute :role, :string, as: "function"
14
+ attribute :content, :string # Result of the function call
15
+ attribute :name, :string # Name of the function that was called
16
+
17
+ validates :content, presence: true
18
+ validates :name, presence: true
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "content/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Chat
10
+ module Requests
11
+ module Messages
12
+ # System message - instructions that the model should follow (older models)
13
+ class System < Base
14
+ attribute :role, :string, as: "system"
15
+ attribute :content, Content::ContentsType.new # String or array of content parts
16
+ attribute :name, :string # Optional name for the participant
17
+
18
+ validates :content, presence: true
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "content/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Chat
10
+ module Requests
11
+ module Messages
12
+ # Tool message - result from a tool call
13
+ class Tool < Base
14
+ attribute :role, :string, as: "tool"
15
+ attribute :content, Content::ContentsType.new # String or array of content parts
16
+ attribute :tool_call_id, :string # ID of the tool call this is a response to
17
+
18
+ validates :content, presence: true
19
+ validates :tool_call_id, presence: true
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "content/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Chat
10
+ module Requests
11
+ module Messages
12
+ # User message - messages sent by an end user
13
+ class User < Base
14
+ attribute :role, :string, as: "user"
15
+ attribute :content, Content::ContentsType.new # String or array of content parts
16
+ attribute :name, :string # Optional name for the participant
17
+
18
+ validates :content, presence: true
19
+
20
+ %i[text image document].each do |content_type|
21
+ define_method(:"#{content_type}=") do |value|
22
+ self.content ||= []
23
+ self.content += [ { content_type => value } ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
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 Prediction < Common::BaseModel
11
+ # Type of predicted content (always "content")
12
+ attribute :type, :string, default: "content"
13
+
14
+ # Content that should be matched (string or array of content parts)
15
+ attribute :content
16
+
17
+ validates :type, inclusion: { in: %w[content] }, allow_nil: true
18
+
19
+ # Validate content is present and in correct format
20
+ validate :validate_content_format
21
+
22
+ private
23
+
24
+ def validate_content_format
25
+ if content.blank?
26
+ errors.add(:content, "must be present")
27
+ return
28
+ end
29
+
30
+ # Content can be a string or an array of content parts
31
+ if content.is_a?(Array)
32
+ content.each do |part|
33
+ unless part.is_a?(Hash) && part[:type].present?
34
+ errors.add(:content, "array elements must be hashes with a 'type' field")
35
+ end
36
+ end
37
+ elsif !content.is_a?(String)
38
+ errors.add(:content, "must be a string or array of content parts")
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
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 ResponseFormat < Common::BaseModel
11
+ # Type of response format (text, json_schema, json_object)
12
+ attribute :type, :string
13
+
14
+ # JSON schema configuration (only for json_schema type)
15
+ attribute :json_schema # Hash with name, description, schema, strict
16
+
17
+ validates :type, inclusion: { in: %w[text json_schema json_object] }, allow_nil: true
18
+
19
+ # Validate that json_schema is present when type is json_schema
20
+ validate :validate_json_schema_presence
21
+
22
+ private
23
+
24
+ def validate_json_schema_presence
25
+ if type == "json_schema" && json_schema.blank?
26
+ errors.add(:json_schema, "must be present when type is 'json_schema'")
27
+ end
28
+
29
+ if json_schema.present? && json_schema.is_a?(Hash)
30
+ validate_json_schema_structure
31
+ end
32
+ end
33
+
34
+ def validate_json_schema_structure
35
+ unless json_schema[:name].present?
36
+ errors.add(:json_schema, "must include 'name' field")
37
+ end
38
+
39
+ if json_schema[:name].present? && json_schema[:name].length > 64
40
+ errors.add(:json_schema, "name must be 64 characters or less")
41
+ end
42
+
43
+ # Name must match pattern: a-z, A-Z, 0-9, underscores and dashes
44
+ if json_schema[:name].present? && json_schema[:name] !~ /^[a-zA-Z0-9_-]+$/
45
+ errors.add(:json_schema, "name must contain only a-z, A-Z, 0-9, underscores and dashes")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ 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 StreamOptions < Common::BaseModel
11
+ # Include usage information in the stream
12
+ attribute :include_usage, :boolean
13
+
14
+ # Include obfuscation in the stream
15
+ attribute :include_obfuscation, :boolean
16
+
17
+ validates :include_usage, inclusion: { in: [ true, false ] }, allow_nil: true
18
+ validates :include_obfuscation, inclusion: { in: [ true, false ] }, allow_nil: true
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
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
+ # Tool choice configuration
11
+ class ToolChoice < Common::BaseModel
12
+ # Can be string ("none", "auto", "required") or object
13
+ attribute :mode, :string
14
+ attribute :type, :string
15
+ attribute :function # Hash with name
16
+ attribute :custom # Hash with name
17
+ attribute :allowed_tools # Hash with mode and tools array
18
+
19
+ validates :mode, inclusion: { in: %w[none auto required] }, allow_nil: true
20
+ validates :type, inclusion: { in: %w[function custom allowed_tools] }, allow_nil: true
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "custom_tool"
5
+ require_relative "function_tool"
@@ -0,0 +1,22 @@
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
+ module Tools
11
+ # Base class for tools
12
+ class Base < Common::BaseModel
13
+ attribute :type, :string
14
+
15
+ validates :type, inclusion: { in: %w[function custom] }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ module Tools
11
+ # Custom tool
12
+ class CustomTool < Base
13
+ attribute :type, :string, as: "custom"
14
+ attribute :custom # Hash with name, description, format
15
+
16
+ validate :validate_custom_structure
17
+
18
+ private
19
+
20
+ def validate_custom_structure
21
+ if custom.blank?
22
+ errors.add(:custom, "must be present")
23
+ return
24
+ end
25
+
26
+ unless custom.is_a?(Hash)
27
+ errors.add(:custom, "must be a hash")
28
+ return
29
+ end
30
+
31
+ unless custom[:name].present?
32
+ errors.add(:custom, "must include 'name' field")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ module Tools
11
+ # Function tool
12
+ class FunctionTool < Base
13
+ attribute :type, :string, as: "function"
14
+ attribute :function # Hash with name, description, parameters, strict
15
+
16
+ validate :validate_function_structure
17
+
18
+ private
19
+
20
+ def validate_function_structure
21
+ if function.blank?
22
+ errors.add(:function, "must be present")
23
+ return
24
+ end
25
+
26
+ unless function.is_a?(Hash)
27
+ errors.add(:function, "must be a hash")
28
+ return
29
+ end
30
+
31
+ unless function[:name].present?
32
+ errors.add(:function, "must include 'name' field")
33
+ end
34
+
35
+ if function[:name].present?
36
+ if function[:name].length > 64
37
+ errors.add(:function, "name must be 64 characters or less")
38
+ end
39
+
40
+ unless function[:name] =~ /^[a-zA-Z0-9_-]+$/
41
+ errors.add(:function, "name must contain only a-z, A-Z, 0-9, underscores and dashes")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,45 @@
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 WebSearchOptions < Common::BaseModel
11
+ # Search context size (low, medium, high)
12
+ attribute :search_context_size, :string
13
+
14
+ # User location for search
15
+ attribute :user_location # Hash with type and approximate
16
+
17
+ validates :search_context_size, inclusion: { in: %w[low medium high] }, allow_nil: true
18
+
19
+ # Validate user_location format
20
+ validate :validate_user_location_format
21
+
22
+ private
23
+
24
+ def validate_user_location_format
25
+ return if user_location.nil?
26
+
27
+ unless user_location.is_a?(Hash)
28
+ errors.add(:user_location, "must be a hash")
29
+ return
30
+ end
31
+
32
+ unless user_location[:type] == "approximate"
33
+ errors.add(:user_location, "type must be 'approximate'")
34
+ end
35
+
36
+ unless user_location[:approximate].is_a?(Hash)
37
+ errors.add(:user_location, "must include 'approximate' hash")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,198 @@
1
+ require_relative "_base"
2
+ require_relative "chat/_types"
3
+
4
+ module ActiveAgent
5
+ module Providers
6
+ module OpenAI
7
+ # Provider implementation for OpenAI's Chat Completion API.
8
+ #
9
+ # Handles chat-based interactions including streaming responses,
10
+ # function/tool calling, and message management. Uses OpenAI's
11
+ # chat completions endpoint for generating responses.
12
+ #
13
+ # @see Base
14
+ # @see https://platform.openai.com/docs/api-reference/chat
15
+ class ChatProvider < Base
16
+ # @return [Class] the options class for this provider
17
+ def self.options_klass
18
+ Options
19
+ end
20
+
21
+ # @return [Chat::RequestType] request type instance for chat completions
22
+ def self.prompt_request_type
23
+ Chat::RequestType.new
24
+ end
25
+
26
+ protected
27
+
28
+ # @return [OpenAI::Client::Completions] the API client for chat completions
29
+ # @see Base#api_prompt_executer
30
+ def api_prompt_executer
31
+ client.chat.completions
32
+ end
33
+
34
+ # Processes streaming response chunks from OpenAI's chat API.
35
+ #
36
+ # Handles message deltas, content updates, and completion detection.
37
+ # Manages the message stack and broadcasts streaming updates.
38
+ #
39
+ # Handles multiple event types:
40
+ # - `:chunk` - Message content and tool call deltas
41
+ # - `:"content.delta"` - Incremental content updates
42
+ # - `:"content.done"` - Complete content delivery
43
+ # - `:"tool_calls.function.arguments.delta"` - Tool argument deltas
44
+ # - `:"tool_calls.function.arguments.done"` - Complete tool arguments
45
+ #
46
+ # @param api_response_event [OpenAI::Helpers::Streaming::ChatChunkEvent]
47
+ # @return [void]
48
+ # @see Base#process_stream_chunk
49
+ def process_stream_chunk(api_response_event)
50
+ instrument("stream_chunk_processing.provider.active_agent")
51
+
52
+ # Called Multiple Times: [Chunk<T>, T]<Content, ToolsCall>
53
+ case api_response_event.type
54
+ when :chunk
55
+ api_message = api_response_event.chunk.choices.first
56
+
57
+ # If we have a delta, we need to update a message in the stack
58
+ message = find_or_create_message(api_message.index)
59
+ message = message_merge_delta(message, api_message.delta.as_json.deep_symbolize_keys)
60
+
61
+ # Stream back content changes as they come in
62
+ if api_message.delta.content
63
+ broadcast_stream_update(message_stack.last, api_message.delta.content)
64
+ end
65
+
66
+ # If this is the last api_chunk to be processed
67
+ return unless api_message.finish_reason
68
+
69
+ instrument("stream_finished.provider.active_agent", finish_reason: api_message.finish_reason)
70
+ when :"content.delta"
71
+ # Returns the deltas, without context
72
+ # => {type: :"content.delta", delta: "", snapshot: "", parsed: nil}
73
+ # => {type: :"content.delta", delta: "Hi", snapshot: "Hi", parsed: nil}
74
+ when :"content.done"
75
+ # Returns the full content when complete
76
+ # => {type: :"content.done", content: "Hi there! How can I help you today?", parsed: nil}
77
+
78
+ # Once we are finished, close out and run tooling callbacks (Recursive)
79
+ process_prompt_finished
80
+ when :"tool_calls.function.arguments.delta"
81
+ # => {type: :"tool_calls.function.arguments.delta", name: "get_current_weather", index: 0, arguments: "", parsed: nil, arguments_delta: ""}
82
+ when :"tool_calls.function.arguments.done"
83
+ # => => {type: :"tool_calls.function.arguments.done", index: 0, name: "get_current_weather", arguments: "{\"location\":\"Boston, MA\"}", parsed: nil}
84
+ else
85
+ fail "Unexpected Response Event Type: #{api_response_event.type}"
86
+ end
87
+ end
88
+
89
+ # Processes function/tool calls from the API response.
90
+ #
91
+ # Executes each tool call and creates tool response messages
92
+ # for the next iteration of the conversation.
93
+ #
94
+ # @param api_function_calls [Array<Hash>] function call objects with :type, :id, and :function keys
95
+ # @return [void]
96
+ # @see Base#process_function_calls
97
+ def process_function_calls(api_function_calls)
98
+ api_function_calls.each do |api_function_call|
99
+ content = case api_function_call[:type]
100
+ when "function"
101
+ instrument("tool_execution.provider.active_agent", tool_name: api_function_call.dig(:function, :name))
102
+ process_tool_call_function(api_function_call[:function])
103
+ else
104
+ fail "Unexpected Tool Call Type: #{api_function_call[:type]}"
105
+ end
106
+
107
+ message = Chat::Requests::Messages::Tool.new(
108
+ tool_call_id: api_function_call[:id],
109
+ content: content.to_json
110
+ )
111
+
112
+ message_stack.push(message.serialize)
113
+ end
114
+ end
115
+
116
+ # Extracts messages from the completed API response.
117
+ #
118
+ # @param api_response [Hash]
119
+ # @return [Array<Hash>, nil] single-element array with message or nil if no message
120
+ # @see Base#process_prompt_finished_extract_messages
121
+ def process_prompt_finished_extract_messages(api_response)
122
+ api_message = api_response&.dig(:choices, 0, :message)
123
+
124
+ [ api_message ] if api_message
125
+ end
126
+
127
+ # Extracts function calls from the last message in the stack.
128
+ #
129
+ # @return [Array<Hash>, nil] tool call objects or nil if no tool calls
130
+ # @see Base#process_prompt_finished_extract_function_calls
131
+ def process_prompt_finished_extract_function_calls
132
+ message_stack.last[:tool_calls]
133
+ end
134
+
135
+ # Merges streaming delta into a message.
136
+ #
137
+ # Separated from hash_merge_delta to allow Ollama to override role handling.
138
+ #
139
+ # @param message [Hash]
140
+ # @param delta [Hash]
141
+ # @return [Hash] the merged message
142
+ def message_merge_delta(message, delta)
143
+ hash_merge_delta(message, delta)
144
+ end
145
+
146
+ private
147
+
148
+ # Finds an existing message by ID or creates a new one.
149
+ #
150
+ # @param id [Integer]
151
+ # @return [Hash] found or newly created message
152
+ def find_or_create_message(id)
153
+ message = message_stack.find { _1[:index] == id }
154
+ return message if message
155
+
156
+ message_stack << { index: id }
157
+ message_stack.last
158
+ end
159
+
160
+ # Recursively merges delta changes into a hash structure.
161
+ #
162
+ # Handles the complex delta merging needed for OpenAI's streaming API,
163
+ # including arrays with indexed items and string concatenation.
164
+ #
165
+ # @param hash [Hash] target hash to merge into
166
+ # @param delta [Hash] delta changes to apply
167
+ # @return [Hash] the merged hash
168
+ def hash_merge_delta(hash, delta)
169
+ delta.each do |key, value|
170
+ case hash[key]
171
+ when Hash
172
+ hash[key] = hash_merge_delta(hash[key], value)
173
+ when Array
174
+ value.each do |delta_item|
175
+ if delta_item.is_a?(Hash) && delta_item[:index]
176
+ hash_item = hash[key].find { _1[:index] == delta_item[:index] }
177
+ if hash_item
178
+ hash_merge_delta(hash_item, delta_item)
179
+ else
180
+ hash[key] << delta_item
181
+ end
182
+ else
183
+ hash[key] << delta_item
184
+ end
185
+ end
186
+ when String
187
+ hash[key] += value
188
+ else
189
+ hash[key] = value
190
+ end
191
+ end
192
+
193
+ hash
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "requests/_types"
4
+ require_relative "request"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Embedding
10
+ # Type for Request model
11
+ class RequestType < ActiveModel::Type::Value
12
+ def cast(value)
13
+ case value
14
+ when Request
15
+ value
16
+ when Hash
17
+ Request.new(**value.deep_symbolize_keys)
18
+ when nil
19
+ nil
20
+ else
21
+ raise ArgumentError, "Cannot cast #{value.class} to Request"
22
+ end
23
+ end
24
+
25
+ def serialize(value)
26
+ case value
27
+ when Request
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