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,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "options"
4
+ require_relative "request"
5
+ require_relative "embedding_request"
6
+
7
+ module ActiveAgent
8
+ module Providers
9
+ module Mock
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
+
43
+ # Type for EmbeddingRequest model
44
+ class EmbeddingRequestType < ActiveModel::Type::Value
45
+ def cast(value)
46
+ case value
47
+ when EmbeddingRequest
48
+ value
49
+ when Hash
50
+ EmbeddingRequest.new(**value.deep_symbolize_keys)
51
+ when nil
52
+ nil
53
+ else
54
+ raise ArgumentError, "Cannot cast #{value.class} to EmbeddingRequest"
55
+ end
56
+ end
57
+
58
+ def serialize(value)
59
+ case value
60
+ when EmbeddingRequest
61
+ value.serialize
62
+ when Hash
63
+ value
64
+ when nil
65
+ nil
66
+ else
67
+ raise ArgumentError, "Cannot serialize #{value.class}"
68
+ end
69
+ end
70
+
71
+ def deserialize(value)
72
+ cast(value)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Mock
8
+ # Embedding request model for Mock provider.
9
+ class EmbeddingRequest < Common::BaseModel
10
+ attribute :model, :string, default: "mock-embedding-model"
11
+ attribute :input # String or array of strings to embed
12
+ attribute :encoding_format, :string
13
+ attribute :dimensions, :integer
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load all message classes
4
+ require_relative "base"
5
+ require_relative "user"
6
+ require_relative "assistant"
7
+
8
+ module ActiveAgent
9
+ module Providers
10
+ module Mock
11
+ module Messages
12
+ # Type for Messages array
13
+ class MessagesType < ActiveModel::Type::Value
14
+ def initialize
15
+ super
16
+ @message_type = MessageType.new
17
+ end
18
+
19
+ def cast(value)
20
+ case value
21
+ when Array
22
+ value.map { |v| @message_type.cast(v) }
23
+ when nil
24
+ nil
25
+ else
26
+ raise ArgumentError, "Cannot cast #{value.class} to Messages array"
27
+ end
28
+ end
29
+
30
+ def serialize(value)
31
+ case value
32
+ when Array
33
+ grouped = []
34
+
35
+ value.each do |message|
36
+ if grouped.empty? || grouped.last.role != message.role
37
+ grouped << message.deep_dup
38
+ else
39
+ grouped.last.content += message.content.deep_dup
40
+ end
41
+ end
42
+
43
+ grouped.map { |v| @message_type.serialize(v) }
44
+ when nil
45
+ nil
46
+ else
47
+ raise ArgumentError, "Cannot serialize #{value.class}"
48
+ end
49
+ end
50
+
51
+ def deserialize(value)
52
+ cast(value)
53
+ end
54
+ end
55
+
56
+ # Type for individual Message
57
+ class MessageType < ActiveModel::Type::Value
58
+ def cast(value)
59
+ case value
60
+ when Base
61
+ value
62
+ when String
63
+ User.new(content: value)
64
+ when Hash
65
+ hash = value.deep_symbolize_keys
66
+ role = hash[:role]&.to_sym
67
+
68
+ case role
69
+ when :user, nil
70
+ User.new(**hash)
71
+ when :assistant
72
+ Assistant.new(**hash)
73
+ else
74
+ raise ArgumentError, "Unknown message role: #{role}"
75
+ end
76
+ when nil
77
+ nil
78
+ else
79
+ raise ArgumentError, "Cannot cast #{value.class} to Message"
80
+ end
81
+ end
82
+
83
+ def serialize(value)
84
+ case value
85
+ when Base
86
+ value.serialize
87
+ when Hash
88
+ value
89
+ when nil
90
+ nil
91
+ else
92
+ raise ArgumentError, "Cannot serialize #{value.class}"
93
+ end
94
+ end
95
+
96
+ def deserialize(value)
97
+ cast(value)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Mock
8
+ module Messages
9
+ # Assistant message for Mock provider.
10
+ #
11
+ # Drops extra fields that are part of the API response but not
12
+ # part of the message structure (usage, id, model, stop_reason, type, etc).
13
+ class Assistant < Base
14
+ attribute :role, :string, as: "assistant"
15
+ attribute :content # Can be string or array of content blocks
16
+ attribute :name, :string
17
+
18
+ validates :content, presence: true
19
+
20
+ # Drop API response fields that aren't part of the message
21
+ drop_attributes :usage, :id, :model, :stop_reason, :stop_sequence, :type
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Mock
8
+ module Messages
9
+ # Base class for Mock messages.
10
+ class Base < Common::BaseModel
11
+ attribute :role, :string
12
+ attribute :content
13
+
14
+ validates :role, presence: true
15
+
16
+ # Define content setter methods for different content types
17
+ %i[text image document].each do |content_type|
18
+ define_method(:"#{content_type}=") do |value|
19
+ # For mock provider, we keep content simple
20
+ # If it's text, just set content to the text value
21
+ if content_type == :text
22
+ self.content = value
23
+ else
24
+ # For image/document, MockProvider doesn't support these, so ignore
25
+ # (or could raise an error)
26
+ end
27
+ end
28
+ end
29
+
30
+ # Converts to common format.
31
+ #
32
+ # @return [Hash] message in canonical format with role and text content
33
+ def to_common
34
+ {
35
+ role: role,
36
+ content: extract_text_content,
37
+ name: nil
38
+ }
39
+ end
40
+
41
+ private
42
+
43
+ # Extracts text content from the content structure.
44
+ #
45
+ # @return [String] extracted text content
46
+ def extract_text_content
47
+ case content
48
+ when String
49
+ content
50
+ when Array
51
+ # Join all text blocks
52
+ content.select { |block| block.is_a?(Hash) && block[:type] == "text" }
53
+ .map { |block| block[:text] }
54
+ .join("\n")
55
+ else
56
+ content.to_s
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Mock
8
+ module Messages
9
+ # User message for Mock provider.
10
+ class User < Base
11
+ attribute :role, :string, as: "user"
12
+
13
+ validates :content, presence: true
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ module ActiveAgent
6
+ module Providers
7
+ module Mock
8
+ # Configuration options for the Mock provider.
9
+ #
10
+ # This provider doesn't make real API calls, so most options are unused.
11
+ # Included for consistency with other providers.
12
+ class Options < Common::BaseModel
13
+ attribute :base_url, :string, default: "https://mock.example.com"
14
+ attribute :api_key, :string, default: "mock-api-key"
15
+
16
+ # Common Interface Compatibility
17
+ alias_attribute :access_token, :api_key
18
+
19
+ def initialize(kwargs = {})
20
+ kwargs = kwargs.deep_symbolize_keys if kwargs.respond_to?(:deep_symbolize_keys)
21
+ super(**deep_compact(kwargs))
22
+ end
23
+
24
+ def extra_headers
25
+ {}
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_agent/providers/common/model"
4
+
5
+ require_relative "messages/_types"
6
+
7
+ module ActiveAgent
8
+ module Providers
9
+ module Mock
10
+ # Request model for Mock provider.
11
+ #
12
+ # Simplified request model that accepts messages and basic parameters.
13
+ class Request < Common::BaseModel
14
+ # Required parameters
15
+ attribute :model, :string, default: "mock-model"
16
+ attribute :messages, Messages::MessagesType.new
17
+
18
+ # Optional parameters
19
+ attribute :instructions # System instructions
20
+ attribute :temperature, :float
21
+ attribute :max_tokens, :integer
22
+ attribute :stream, :boolean, default: false
23
+ attribute :tools # Array of tool definitions
24
+ attribute :tool_choice # Tool choice configuration
25
+
26
+ # Common Format Compatibility
27
+ def message=(value)
28
+ self.messages ||= []
29
+ self.messages << value
30
+ end
31
+
32
+ def response_format
33
+ { type: "text" }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,311 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "_base_provider"
4
+ require_relative "mock/_types"
5
+
6
+ module ActiveAgent
7
+ module Providers
8
+ # Mock provider for testing purposes.
9
+ #
10
+ # This provider doesn't make real API calls. Instead, it returns the last
11
+ # message content converted to pig latin for prompts, and random data for embeddings.
12
+ # Useful for testing without incurring API costs or requiring network access.
13
+ #
14
+ # @example Basic usage
15
+ # provider = ActiveAgent::Providers::MockProvider.new(...)
16
+ # result = provider.prompt
17
+ #
18
+ # @see BaseProvider
19
+ class MockProvider < BaseProvider
20
+ # Returns the embedding request type for Mock.
21
+ #
22
+ # @return [ActiveModel::Type::Value] The Mock embedding request type
23
+ def self.embed_request_type
24
+ Mock::EmbeddingRequestType.new
25
+ end
26
+
27
+ # Returns a mock client (just returns self since we don't need a real client).
28
+ #
29
+ # @return [MockProvider] Returns self
30
+ def client
31
+ self
32
+ end
33
+
34
+ protected
35
+
36
+ # Executes a mock prompt request.
37
+ #
38
+ # Extracts the last user message, converts it to pig latin, and returns
39
+ # a mock response structure. Handles both streaming and non-streaming.
40
+ #
41
+ # @param parameters [Hash] The prompt request parameters
42
+ # @return [Hash] A mock API response structure
43
+ def api_prompt_execute(parameters)
44
+ # Extract the last message content
45
+ last_message = [ request.instructions, parameters[:messages]&.last&.dig(:content) ].compact.join(" ")
46
+ content = extract_message_content(last_message)
47
+
48
+ # Convert to pig latin
49
+ pig_latin_content = to_pig_latin(content)
50
+
51
+ if parameters[:stream]
52
+ # For streaming, call the stream proc with chunks
53
+ stream_proc = parameters[:stream]
54
+ simulate_streaming(pig_latin_content, stream_proc)
55
+ nil
56
+ else
57
+ # Return a complete response
58
+ {
59
+ id: "mock-#{SecureRandom.hex(8)}",
60
+ type: "message",
61
+ role: "assistant",
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: pig_latin_content
66
+ }
67
+ ],
68
+ model: parameters[:model] || "mock-model",
69
+ stop_reason: "end_turn",
70
+ usage: {
71
+ input_tokens: content.length,
72
+ output_tokens: pig_latin_content.length
73
+ }
74
+ }
75
+ end
76
+ end
77
+
78
+ # Executes a mock embedding request.
79
+ #
80
+ # Returns random embedding vectors for testing purposes.
81
+ #
82
+ # @param parameters [Hash] The embedding request parameters
83
+ # @return [Hash] A mock embedding response structure
84
+ def api_embed_execute(parameters)
85
+ input = parameters[:input]
86
+ inputs = input.is_a?(Array) ? input : [ input ]
87
+ dimensions = parameters[:dimensions] || 1536
88
+
89
+ {
90
+ object: "list",
91
+ data: inputs.map.with_index do |text, index|
92
+ {
93
+ object: "embedding",
94
+ index: index,
95
+ embedding: generate_random_embedding(dimensions)
96
+ }
97
+ end,
98
+ model: parameters[:model] || "mock-embedding-model",
99
+ usage: {
100
+ prompt_tokens: inputs.sum { |text| text.to_s.length },
101
+ total_tokens: inputs.sum { |text| text.to_s.length }
102
+ }
103
+ }
104
+ end
105
+
106
+ # Processes streaming response chunks.
107
+ #
108
+ # Handles mock streaming chunks, similar to real provider implementations.
109
+ #
110
+ # @param api_response_chunk [Hash] The streaming response chunk
111
+ # @return [void]
112
+ def process_stream_chunk(api_response_chunk)
113
+ chunk_type = api_response_chunk[:type]&.to_sym
114
+
115
+ instrument("stream_chunk_processing.provider.active_agent", chunk_type: chunk_type)
116
+
117
+ broadcast_stream_open
118
+
119
+ case chunk_type
120
+ when :message_start
121
+ api_message = api_response_chunk[:message]
122
+ message_stack.push(api_message)
123
+ broadcast_stream_update(message_stack.last)
124
+
125
+ when :content_block_start
126
+ api_content = api_response_chunk[:content_block]
127
+ message_stack.last[:content] ||= []
128
+ message_stack.last[:content].push(api_content)
129
+ broadcast_stream_update(message_stack.last, api_content[:text])
130
+
131
+ when :content_block_delta
132
+ index = api_response_chunk[:index]
133
+ content = message_stack.last[:content][index]
134
+ delta = api_response_chunk[:delta]
135
+
136
+ if delta[:type] == "text_delta"
137
+ content[:text] ||= ""
138
+ content[:text] += delta[:text]
139
+ broadcast_stream_update(message_stack.last, delta[:text])
140
+ end
141
+
142
+ when :message_delta
143
+ delta = api_response_chunk[:delta]
144
+ message_stack.last[:stop_reason] = delta[:stop_reason] if delta[:stop_reason]
145
+
146
+ when :message_stop
147
+ # Stream complete
148
+ end
149
+ end
150
+
151
+ # Extracts messages from API response.
152
+ #
153
+ # @param api_response [Hash] The API response
154
+ # @return [Array<Hash>] Array of message hashes
155
+ def process_prompt_finished_extract_messages(api_response)
156
+ return nil if api_response.nil? # Streaming case
157
+ [ api_response ]
158
+ end
159
+
160
+ # Extracts function calls from API response.
161
+ #
162
+ # Mock provider doesn't support tool calling by default.
163
+ #
164
+ # @return [nil]
165
+ def process_prompt_finished_extract_function_calls
166
+ nil
167
+ end
168
+
169
+ private
170
+
171
+ # Extracts text content from a message.
172
+ #
173
+ # @param message [Hash, String, nil] The message to extract from
174
+ # @return [String] The extracted text content
175
+ def extract_message_content(message)
176
+ return "" if message.nil?
177
+
178
+ case message
179
+ when String
180
+ message
181
+ when Hash
182
+ if message[:content].is_a?(String)
183
+ message[:content]
184
+ elsif message[:content].is_a?(Array)
185
+ message[:content]
186
+ .select { |block| block.is_a?(Hash) && block[:type] == "text" }
187
+ .map { |block| block[:text] }
188
+ .join(" ")
189
+ else
190
+ message[:content].to_s
191
+ end
192
+ else
193
+ message.to_s
194
+ end
195
+ end
196
+
197
+ # Converts text to pig latin.
198
+ #
199
+ # Simple pig latin conversion:
200
+ # - Words starting with vowels: add "way" to the end
201
+ # - Words starting with consonants: move consonants to end and add "ay"
202
+ # - Preserves punctuation and capitalization
203
+ #
204
+ # @param text [String] The text to convert
205
+ # @return [String] The text in pig latin
206
+ def to_pig_latin(text)
207
+ return "" if text.nil? || text.empty?
208
+
209
+ words = text.split(/\b/)
210
+
211
+ words.map do |word|
212
+ # Skip non-word characters (spaces, punctuation, etc.)
213
+ next word unless word.match?(/\w/)
214
+
215
+ # Check if word starts with a vowel
216
+ if word.match?(/^[aeiouAEIOU]/)
217
+ "#{word}way"
218
+ else
219
+ # Find the first vowel
220
+ match = word.match(/^([^aeiouAEIOU]+)(.*)/)
221
+ if match
222
+ consonants = match[1]
223
+ rest = match[2]
224
+
225
+ # Preserve capitalization
226
+ if word[0] == word[0].upcase && rest.length > 0
227
+ "#{rest[0].upcase}#{rest[1..-1]}#{consonants.downcase}ay"
228
+ else
229
+ "#{rest}#{consonants}ay"
230
+ end
231
+ else
232
+ # No vowels found, just add "ay"
233
+ "#{word}ay"
234
+ end
235
+ end
236
+ end.join
237
+ end
238
+
239
+ # Simulates streaming by sending chunks.
240
+ #
241
+ # @param content [String] The full content to stream
242
+ # @param stream_proc [Proc] The streaming callback
243
+ # @return [void]
244
+ def simulate_streaming(content, stream_proc)
245
+ message_id = "mock-#{SecureRandom.hex(8)}"
246
+
247
+ # Send message_start
248
+ stream_proc.call({
249
+ type: :message_start,
250
+ message: {
251
+ id: message_id,
252
+ type: "message",
253
+ role: "assistant",
254
+ content: [],
255
+ model: "mock-model"
256
+ }
257
+ })
258
+
259
+ # Send content_block_start
260
+ stream_proc.call({
261
+ type: :content_block_start,
262
+ index: 0,
263
+ content_block: {
264
+ type: "text",
265
+ text: ""
266
+ }
267
+ })
268
+
269
+ # Send content in chunks (simulate word-by-word streaming)
270
+ words = content.split(" ")
271
+ words.each_with_index do |word, i|
272
+ text_chunk = i == 0 ? word : " #{word}"
273
+ stream_proc.call({
274
+ type: :content_block_delta,
275
+ index: 0,
276
+ delta: {
277
+ type: "text_delta",
278
+ text: text_chunk
279
+ }
280
+ })
281
+ end
282
+
283
+ # Send message_delta with stop_reason
284
+ stream_proc.call({
285
+ type: :message_delta,
286
+ delta: {
287
+ stop_reason: "end_turn"
288
+ }
289
+ })
290
+
291
+ # Send message_stop
292
+ stream_proc.call({
293
+ type: :message_stop
294
+ })
295
+ end
296
+
297
+ # Generates a random embedding vector.
298
+ #
299
+ # @param dimensions [Integer] The number of dimensions for the embedding
300
+ # @return [Array<Float>] A random normalized vector
301
+ def generate_random_embedding(dimensions)
302
+ # Generate random values between -1 and 1
303
+ vector = Array.new(dimensions) { rand * 2 - 1 }
304
+
305
+ # Normalize the vector to unit length (common for embeddings)
306
+ magnitude = Math.sqrt(vector.sum { |v| v ** 2 })
307
+ vector.map { |v| v / magnitude }
308
+ end
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "options"
4
+ require_relative "chat/_types"
5
+ require_relative "embedding/_types"