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,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "content/_types"
4
+
5
+ # Load all message classes
6
+ require_relative "base"
7
+ require_relative "developer"
8
+ require_relative "system"
9
+ require_relative "user"
10
+ require_relative "assistant"
11
+ require_relative "tool"
12
+ require_relative "function"
13
+
14
+ module ActiveAgent
15
+ module Providers
16
+ module OpenAI
17
+ module Chat
18
+ module Requests
19
+ module Messages
20
+ # Type for Messages array
21
+ class MessagesType < ActiveModel::Type::Value
22
+ def initialize
23
+ super
24
+ @message_type = MessageType.new
25
+ end
26
+
27
+ def cast(value)
28
+ case value
29
+ when Array
30
+ value.map { |v| @message_type.cast(v) }
31
+ when nil
32
+ nil
33
+ else
34
+ raise ArgumentError, "Cannot cast #{value.class} to Messages array"
35
+ end
36
+ end
37
+
38
+ def serialize(value)
39
+ case value
40
+ when Array
41
+ grouped = []
42
+
43
+ value.each do |message|
44
+ if grouped.empty? || grouped.last.role != message.role
45
+ grouped << message.deep_dup
46
+ else
47
+ grouped.last.content += message.content.deep_dup
48
+ end
49
+ end
50
+
51
+ grouped.map { |v| @message_type.serialize(v) }
52
+ when nil
53
+ nil
54
+ else
55
+ raise ArgumentError, "Cannot serialize #{value.class}"
56
+ end
57
+ end
58
+
59
+ def deserialize(value)
60
+ cast(value)
61
+ end
62
+ end
63
+
64
+ # Type for individual Message
65
+ class MessageType < ActiveModel::Type::Value
66
+ def cast(value)
67
+ case value
68
+ when ::OpenAI::Models::Chat::ChatCompletionMessage
69
+ cast(value.to_h)
70
+ when Base
71
+ value
72
+ when String
73
+ User.new(content: value)
74
+ when Hash
75
+ hash = value.deep_symbolize_keys
76
+ role = hash[:role]&.to_sym
77
+
78
+ case role
79
+ when :developer
80
+ Developer.new(**hash)
81
+ when :system
82
+ System.new(**hash)
83
+ when :user, nil
84
+ User.new(**hash)
85
+ when :assistant
86
+ Assistant.new(**hash)
87
+ when :tool
88
+ Tool.new(**hash)
89
+ when :function
90
+ Function.new(**hash)
91
+ else
92
+ raise ArgumentError, "Unknown message role: #{role.inspect}"
93
+ end
94
+ when nil
95
+ nil
96
+ else
97
+ raise ArgumentError, "Cannot cast #{value.class} to Message (expected Base, String, Hash, or nil)"
98
+ end
99
+ end
100
+
101
+ def serialize(value)
102
+ case value
103
+ when Base
104
+ value.serialize
105
+ when Hash
106
+ value
107
+ when nil
108
+ nil
109
+ else
110
+ raise ArgumentError, "Cannot serialize #{value.class} as Message"
111
+ end
112
+ end
113
+
114
+ def deserialize(value)
115
+ cast(value)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,42 @@
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
+ # Assistant message - messages sent by the model
13
+ class Assistant < Base
14
+ attribute :role, :string, as: "assistant"
15
+ attribute :content # String, null, or array of content parts
16
+ attribute :name, :string # Optional name for the participant
17
+ attribute :audio # Audio response from the model
18
+ attribute :refusal, :string # Refusal message if the model refused to respond
19
+ attribute :tool_calls # Array of tool calls the model wants to make
20
+ attribute :function_call # Deprecated: function call (use tool_calls instead)
21
+
22
+ # Assistant messages need content, tool_calls, function_call, or refusal
23
+ validate :validate_has_response_content
24
+
25
+ drop_attributes :annotations, :index
26
+
27
+ alias_attribute :text, :content
28
+
29
+ private
30
+
31
+ def validate_has_response_content
32
+ if content.nil? && tool_calls.nil? && function_call.nil? && refusal.nil?
33
+ errors.add(:base, "must have content, tool_calls, function_call, or refusal")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,78 @@
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 Messages
11
+ # Base class for all OpenAI message types.
12
+ #
13
+ # Provides common message structure and conversion utilities for
14
+ # OpenAI's message format, including role mapping and content extraction.
15
+ class Base < Common::BaseModel
16
+ attribute :role, :string
17
+
18
+ validates :role, presence: true
19
+
20
+ # Converts to common format.
21
+ #
22
+ # @return [Hash] message in canonical format
23
+ def to_common
24
+ {
25
+ role: map_role_to_common,
26
+ content: extract_text_content,
27
+ name: respond_to?(:name) ? name : nil,
28
+ tool_call_id: respond_to?(:tool_call_id) ? tool_call_id : nil
29
+ }.compact
30
+ end
31
+
32
+ private
33
+
34
+ # Maps OpenAI roles to canonical roles.
35
+ #
36
+ # @return [String] canonical role name
37
+ def map_role_to_common
38
+ case role
39
+ when "developer", "system"
40
+ "system"
41
+ when "user"
42
+ "user"
43
+ when "assistant"
44
+ "assistant"
45
+ when "tool", "function"
46
+ "tool"
47
+ else
48
+ role
49
+ end
50
+ end
51
+
52
+ # Extracts text content from OpenAI's content structure.
53
+ #
54
+ # @return [String, nil] extracted text content
55
+ def extract_text_content
56
+ return nil unless respond_to?(:content)
57
+
58
+ case content
59
+ when String
60
+ content
61
+ when Array
62
+ # Join all text parts
63
+ content.select { |part| part.is_a?(Hash) && part["type"] == "text" }
64
+ .map { |part| part["text"] }
65
+ .join("\n")
66
+ when nil
67
+ nil
68
+ else
69
+ content.to_s
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "text"
5
+ require_relative "image"
6
+ require_relative "audio"
7
+ require_relative "file"
8
+ require_relative "refusal"
9
+
10
+ module ActiveAgent
11
+ module Providers
12
+ module OpenAI
13
+ module Chat
14
+ module Requests
15
+ module Messages
16
+ module Content
17
+ # Type for handling content (string or array of content parts)
18
+ class ContentsType < ActiveModel::Type::Value
19
+ def initialize
20
+ super
21
+ @content_type = ContentType.new
22
+ end
23
+
24
+ def cast(value)
25
+ case value
26
+ when String
27
+ # Plain text string - convert to array with single text content
28
+ [ Text.new(text: value) ]
29
+ when Array
30
+ # Array of content parts - cast each part
31
+ value.map { |part| @content_type.cast(part) }
32
+ when nil
33
+ nil
34
+ else
35
+ raise ArgumentError, "Cannot cast #{value.class} to Contents (expected String, Array, or nil)"
36
+ end
37
+ end
38
+
39
+ def serialize(value)
40
+ case value
41
+ when String
42
+ value
43
+ when Array
44
+ array = value.map { |part| @content_type.serialize(part) }
45
+
46
+ if array in [ { type: "text", text: String } ]
47
+ array.first[:text]
48
+ else
49
+ array
50
+ end
51
+ when nil
52
+ nil
53
+ else
54
+ raise ArgumentError, "Cannot serialize #{value.class} as Contents"
55
+ end
56
+ end
57
+
58
+ def deserialize(value)
59
+ cast(value)
60
+ end
61
+ end
62
+
63
+ # Type for individual content items
64
+ class ContentType < ActiveModel::Type::Value
65
+ def cast(value)
66
+ case value
67
+ when Base
68
+ value
69
+ when Hash
70
+ hash = value.deep_symbolize_keys
71
+ type = hash[:type]&.to_sym
72
+
73
+ case type
74
+ when :text
75
+ Text.new(**hash)
76
+ when :image_url
77
+ Image.new(**hash)
78
+ when :input_audio
79
+ Audio.new(**hash)
80
+ when :file
81
+ File.new(**hash)
82
+ when :refusal
83
+ Refusal.new(**hash)
84
+ when nil
85
+ # When type is nil, check for specific content keys to infer type
86
+ if hash.key?(:text)
87
+ Text.new(**hash)
88
+ elsif hash.key?(:image)
89
+ Image.new(**hash.merge(image_url: hash.delete(:image)))
90
+ elsif hash.key?(:document)
91
+ File.new(**hash.merge(file: hash.delete(:document)))
92
+ else
93
+ raise ArgumentError, "Cannot determine content type from hash keys: #{hash.keys.inspect}"
94
+ end
95
+ else
96
+ raise ArgumentError, "Unknown content type: #{type.inspect}"
97
+ end
98
+ when String
99
+ # Plain text string becomes text content
100
+ Text.new(text: value)
101
+ when nil
102
+ nil
103
+ else
104
+ raise ArgumentError, "Cannot cast #{value.class} to Content (expected Base, Hash, String, or nil)"
105
+ end
106
+ end
107
+
108
+ def serialize(value)
109
+ case value
110
+ when Base
111
+ value.serialize
112
+ when Hash
113
+ value
114
+ when String
115
+ { type: "text", text: value }
116
+ when nil
117
+ nil
118
+ else
119
+ raise ArgumentError, "Cannot serialize #{value.class} as Content"
120
+ end
121
+ end
122
+
123
+ def deserialize(value)
124
+ cast(value)
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,35 @@
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
+ module Content
12
+ # Audio content part
13
+ class Audio < Base
14
+ attribute :type, :string, as: "input_audio"
15
+ attribute :input_audio, default: -> { {} }
16
+
17
+ validates :input_audio, presence: true
18
+
19
+ # Nested input_audio object
20
+ def input_audio=(value)
21
+ case value
22
+ when Hash
23
+ super(value.symbolize_keys)
24
+ else
25
+ super(value)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ 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
+ module Messages
11
+ module Content
12
+ # Base class for content parts
13
+ class Base < Common::BaseModel
14
+ attribute :type, :string
15
+
16
+ validates :type, presence: true
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "files/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ module OpenAI
9
+ module Chat
10
+ module Requests
11
+ module Messages
12
+ module Content
13
+ # File content part
14
+ class File < Base
15
+ attribute :type, :string, as: "file"
16
+ attribute :file, Files::DetailsType.new
17
+
18
+ validates :file, presence: true
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "details"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ module Messages
11
+ module Content
12
+ module Files
13
+ # Type for the nested file object
14
+ class DetailsType < ActiveModel::Type::Value
15
+ def cast(value)
16
+ case value
17
+ when Details
18
+ value
19
+ when Hash
20
+ Details.new(**value.deep_symbolize_keys)
21
+ when String
22
+ if value.start_with?("data:")
23
+ Details.new(file_data: value)
24
+ elsif value.match?(%r{\Ahttps?://})
25
+ raise ArgumentError, "HTTP/S URLs are not supported. Use a base64 data instead"
26
+ else
27
+ Details.new(file_data: value)
28
+ end
29
+ when nil
30
+ nil
31
+ else
32
+ raise ArgumentError, "Cannot cast #{value.class} to File::Details"
33
+ end
34
+ end
35
+
36
+ def serialize(value)
37
+ case value
38
+ when Details
39
+ value.serialize
40
+ when Hash
41
+ value
42
+ when nil
43
+ nil
44
+ else
45
+ raise ArgumentError, "Cannot serialize #{value.class}"
46
+ end
47
+ end
48
+
49
+ def deserialize(value)
50
+ cast(value)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,41 @@
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 Messages
11
+ module Content
12
+ module Files
13
+ # Represents the nested file object within File content part
14
+ class Details < Common::BaseModel
15
+ # The base64 encoded file data, used when passing the file to the model as a string
16
+ attribute :file_data, :string
17
+
18
+ # The ID of an uploaded file to use as input
19
+ attribute :file_id, :string
20
+
21
+ # The name of the file, used when passing the file to the model as a string
22
+ attribute :filename, :string
23
+
24
+ # Override serialize to strip data URI prefix from file_data
25
+ def file_data=(value)
26
+ # Strip data URI prefix from file_data if present
27
+ if value&.match?(/\Adata:[^;]+;base64,/)
28
+ value = value.sub(/\Adata:[^;]+;base64,/, "")
29
+ end
30
+
31
+ super(value)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
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
+ module Content
12
+ # Image content part
13
+ class Image < Base
14
+ attribute :type, :string, as: "image_url"
15
+ attribute :image_url, default: -> { {} }
16
+
17
+ validates :image_url, presence: true
18
+
19
+ # Nested image_url object
20
+ def image_url=(value)
21
+ case value
22
+ when Hash
23
+ super(value.symbolize_keys)
24
+ when String
25
+ super({ url: value })
26
+ else
27
+ super(value)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -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
+ module Content
12
+ # Refusal content part (used in assistant messages)
13
+ class Refusal < Base
14
+ attribute :type, :string, as: "refusal"
15
+ attribute :refusal, :string
16
+
17
+ validates :refusal, presence: true
18
+ end
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
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module OpenAI
8
+ module Chat
9
+ module Requests
10
+ module Messages
11
+ module Content
12
+ # Text content part
13
+ class Text < Base
14
+ attribute :type, :string, as: "text"
15
+ attribute :text, :string
16
+
17
+ validates :text, presence: true
18
+ end
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
+ # Developer message - instructions that the model should follow (o1 models and newer)
13
+ class Developer < Base
14
+ attribute :role, :string, as: "developer"
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