ruby_llm 1.16.0 → 2.0.0.rc2

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 (475) hide show
  1. checksums.yaml +4 -4
  2. data/.rdoc_options +25 -0
  3. data/README.md +85 -32
  4. data/exe/ruby_llm +8 -0
  5. data/lib/generators/ruby_llm/agent/templates/agent.rb.tt +0 -1
  6. data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +3 -43
  7. data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +11 -3
  8. data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +8 -0
  9. data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +4 -4
  10. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +1 -1
  11. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +1 -1
  12. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +1 -1
  13. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +2 -2
  14. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +1 -1
  15. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +1 -1
  16. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +1 -1
  17. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +6 -4
  18. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +1 -1
  19. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +2 -2
  20. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +5 -6
  21. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +2 -2
  22. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +5 -5
  23. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +1 -1
  24. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +1 -1
  25. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +1 -1
  26. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +2 -2
  27. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +1 -1
  28. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_system.html.erb.tt +1 -1
  29. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +1 -1
  30. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +6 -4
  31. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_user.html.erb.tt +1 -1
  32. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +4 -6
  33. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +2 -2
  34. data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +5 -6
  35. data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +2 -2
  36. data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +3 -3
  37. data/lib/generators/ruby_llm/generator_helpers.rb +106 -62
  38. data/lib/generators/ruby_llm/install/install_generator.rb +3 -11
  39. data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +2 -0
  40. data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +14 -8
  41. data/lib/generators/ruby_llm/install/templates/create_ruby_llm_records_migration.rb.tt +117 -0
  42. data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +0 -8
  43. data/lib/generators/ruby_llm/provider/cli.rb +175 -0
  44. data/lib/generators/ruby_llm/provider/scaffold.rb +323 -0
  45. data/lib/generators/ruby_llm/provider/templates/core/provider.rb.erb +37 -0
  46. data/lib/generators/ruby_llm/provider/templates/core/provider_spec.rb.erb +34 -0
  47. data/lib/generators/ruby_llm/provider/templates/gem/archspec.rb.erb +14 -0
  48. data/lib/generators/ruby_llm/provider/templates/gem/bin/console.erb +15 -0
  49. data/lib/generators/ruby_llm/provider/templates/gem/bin/setup.erb +5 -0
  50. data/lib/generators/ruby_llm/provider/templates/gem/chat_schema_spec.rb.erb +30 -0
  51. data/lib/generators/ruby_llm/provider/templates/gem/chat_spec.rb.erb +35 -0
  52. data/lib/generators/ruby_llm/provider/templates/gem/chat_streaming_spec.rb.erb +22 -0
  53. data/lib/generators/ruby_llm/provider/templates/gem/chat_tools_spec.rb.erb +30 -0
  54. data/lib/generators/ruby_llm/provider/templates/gem/ci.yml.erb +32 -0
  55. data/lib/generators/ruby_llm/provider/templates/gem/embedding_spec.rb.erb +49 -0
  56. data/lib/generators/ruby_llm/provider/templates/gem/env.erb +2 -0
  57. data/lib/generators/ruby_llm/provider/templates/gem/fixtures_gitkeep.erb +1 -0
  58. data/lib/generators/ruby_llm/provider/templates/gem/flayignore.erb +1 -0
  59. data/lib/generators/ruby_llm/provider/templates/gem/gemfile.erb +23 -0
  60. data/lib/generators/ruby_llm/provider/templates/gem/gemspec.erb +28 -0
  61. data/lib/generators/ruby_llm/provider/templates/gem/gitignore.erb +7 -0
  62. data/lib/generators/ruby_llm/provider/templates/gem/gitleaks.yml.erb +22 -0
  63. data/lib/generators/ruby_llm/provider/templates/gem/image_spec.rb.erb +23 -0
  64. data/lib/generators/ruby_llm/provider/templates/gem/license.erb +21 -0
  65. data/lib/generators/ruby_llm/provider/templates/gem/models.rb.erb +19 -0
  66. data/lib/generators/ruby_llm/provider/templates/gem/models_spec.rb.erb +17 -0
  67. data/lib/generators/ruby_llm/provider/templates/gem/moderation_spec.rb.erb +22 -0
  68. data/lib/generators/ruby_llm/provider/templates/gem/overcommit.yml.erb +31 -0
  69. data/lib/generators/ruby_llm/provider/templates/gem/provider.rb.erb +52 -0
  70. data/lib/generators/ruby_llm/provider/templates/gem/provider_spec.rb.erb +38 -0
  71. data/lib/generators/ruby_llm/provider/templates/gem/rakefile.erb +38 -0
  72. data/lib/generators/ruby_llm/provider/templates/gem/readme.md.erb +50 -0
  73. data/lib/generators/ruby_llm/provider/templates/gem/release.yml.erb +36 -0
  74. data/lib/generators/ruby_llm/provider/templates/gem/rerank_spec.rb.erb +23 -0
  75. data/lib/generators/ruby_llm/provider/templates/gem/rspec.erb +2 -0
  76. data/lib/generators/ruby_llm/provider/templates/gem/rubocop.yml.erb +29 -0
  77. data/lib/generators/ruby_llm/provider/templates/gem/rubyllm_configuration.rb.erb +14 -0
  78. data/lib/generators/ruby_llm/provider/templates/gem/spec_helper.rb.erb +26 -0
  79. data/lib/generators/ruby_llm/provider/templates/gem/speech_spec.rb.erb +25 -0
  80. data/lib/generators/ruby_llm/provider/templates/gem/vcr_configuration.rb.erb +16 -0
  81. data/lib/generators/ruby_llm/provider/templates/gem/video_spec.rb.erb +27 -0
  82. data/lib/generators/ruby_llm/schema/schema_generator.rb +5 -1
  83. data/lib/generators/ruby_llm/schema/templates/schema.rb.tt +1 -1
  84. data/lib/generators/ruby_llm/tool/templates/tailwind/tool_call.html.erb.tt +13 -0
  85. data/lib/generators/ruby_llm/tool/templates/tailwind/tool_result.html.erb.tt +21 -0
  86. data/lib/generators/ruby_llm/tool/templates/tool.rb.tt +3 -3
  87. data/lib/generators/ruby_llm/tool/templates/tool_call.html.erb.tt +7 -12
  88. data/lib/generators/ruby_llm/tool/templates/tool_result.html.erb.tt +5 -2
  89. data/lib/generators/ruby_llm/tool/tool_generator.rb +25 -59
  90. data/lib/generators/ruby_llm/upgrade/templates/backfill_v2_data.rb.tt +461 -0
  91. data/lib/generators/ruby_llm/upgrade/templates/cleanup_v2_upgrade.rb.tt +101 -0
  92. data/lib/generators/ruby_llm/upgrade/templates/finish_v2_upgrade.rb.tt +215 -0
  93. data/lib/generators/ruby_llm/upgrade/templates/prepare_v2_upgrade.rb.tt +660 -0
  94. data/lib/generators/ruby_llm/upgrade/templates/ruby_llm_upgrade.rb.tt +222 -0
  95. data/lib/generators/ruby_llm/upgrade/templates/upgrade_initializer.rb.tt +13 -0
  96. data/lib/generators/ruby_llm/upgrade/upgrade_generator.rb +167 -0
  97. data/lib/generators/ruby_llm/upgrade/upgrade_migration.rb +344 -0
  98. data/lib/ruby_llm/accounting/usage.rb +245 -0
  99. data/lib/ruby_llm/active_record/acts_as.rb +94 -111
  100. data/lib/ruby_llm/active_record/attachment_helpers.rb +186 -0
  101. data/lib/ruby_llm/active_record/batch.rb +97 -0
  102. data/lib/ruby_llm/active_record/chat_methods.rb +828 -305
  103. data/lib/ruby_llm/active_record/message_methods.rb +113 -136
  104. data/lib/ruby_llm/active_record/model.rb +135 -0
  105. data/lib/ruby_llm/active_record/payload_helpers.rb +1 -2
  106. data/lib/ruby_llm/active_record/tool_call.rb +33 -0
  107. data/lib/ruby_llm/active_record/usage.rb +61 -0
  108. data/lib/ruby_llm/agent.rb +1065 -151
  109. data/lib/ruby_llm/aliases.json +268 -100
  110. data/lib/ruby_llm/attachment.rb +187 -48
  111. data/lib/ruby_llm/batch.rb +432 -0
  112. data/lib/ruby_llm/cached_content.rb +112 -0
  113. data/lib/ruby_llm/chat/tool_concurrency.rb +111 -0
  114. data/lib/ruby_llm/chat.rb +1127 -198
  115. data/lib/ruby_llm/chunk.rb +10 -0
  116. data/lib/ruby_llm/citation.rb +105 -0
  117. data/lib/ruby_llm/configuration.rb +261 -24
  118. data/lib/ruby_llm/context.rb +128 -6
  119. data/lib/ruby_llm/cost.rb +217 -80
  120. data/lib/ruby_llm/downloaded_file.rb +33 -0
  121. data/lib/ruby_llm/embedding.rb +121 -17
  122. data/lib/ruby_llm/embedding_request.rb +53 -0
  123. data/lib/ruby_llm/error.rb +159 -23
  124. data/lib/ruby_llm/fallback.rb +133 -0
  125. data/lib/ruby_llm/files/mime_type.rb +97 -0
  126. data/lib/ruby_llm/image.rb +153 -32
  127. data/lib/ruby_llm/message.rb +233 -54
  128. data/lib/ruby_llm/model/modalities.rb +17 -4
  129. data/lib/ruby_llm/model/pricing.rb +24 -5
  130. data/lib/ruby_llm/model/pricing_category.rb +103 -14
  131. data/lib/ruby_llm/model/pricing_tier.rb +55 -15
  132. data/lib/ruby_llm/model.rb +244 -2
  133. data/lib/ruby_llm/models/aliases.rb +41 -0
  134. data/lib/ruby_llm/models/registry.rb +165 -0
  135. data/lib/ruby_llm/models/schema.rb +99 -0
  136. data/lib/ruby_llm/models.json +73261 -33733
  137. data/lib/ruby_llm/models.rb +477 -215
  138. data/lib/ruby_llm/moderation.rb +139 -26
  139. data/lib/ruby_llm/ocr.rb +112 -0
  140. data/lib/ruby_llm/prompt.rb +79 -0
  141. data/lib/ruby_llm/protocol/binary_streaming.rb +65 -0
  142. data/lib/ruby_llm/protocol/stream_accumulator.rb +214 -0
  143. data/lib/ruby_llm/protocol/streaming.rb +230 -0
  144. data/lib/ruby_llm/protocol.rb +662 -0
  145. data/lib/ruby_llm/protocols/anthropic/batches.rb +73 -0
  146. data/lib/ruby_llm/protocols/anthropic/chat.rb +548 -0
  147. data/lib/ruby_llm/protocols/anthropic/embeddings.rb +14 -0
  148. data/lib/ruby_llm/protocols/anthropic/files.rb +38 -0
  149. data/lib/ruby_llm/protocols/anthropic/media.rb +141 -0
  150. data/lib/ruby_llm/protocols/anthropic/models.rb +129 -0
  151. data/lib/ruby_llm/protocols/anthropic/streaming.rb +167 -0
  152. data/lib/ruby_llm/{providers → protocols}/anthropic/tools.rb +24 -41
  153. data/lib/ruby_llm/protocols/anthropic.rb +101 -0
  154. data/lib/ruby_llm/protocols/azure/files.rb +16 -0
  155. data/lib/ruby_llm/protocols/bedrock/async_videos.rb +109 -0
  156. data/lib/ruby_llm/protocols/bedrock/batches.rb +129 -0
  157. data/lib/ruby_llm/protocols/bedrock/files.rb +110 -0
  158. data/lib/ruby_llm/protocols/bedrock/guardrails.rb +122 -0
  159. data/lib/ruby_llm/protocols/bedrock/rerank.rb +95 -0
  160. data/lib/ruby_llm/protocols/chat_completions/batches.rb +32 -0
  161. data/lib/ruby_llm/protocols/chat_completions/chat.rb +493 -0
  162. data/lib/ruby_llm/protocols/chat_completions/embedding_batches.rb +35 -0
  163. data/lib/ruby_llm/protocols/chat_completions/embeddings.rb +60 -0
  164. data/lib/ruby_llm/protocols/chat_completions/images.rb +127 -0
  165. data/lib/ruby_llm/{providers/openai → protocols/chat_completions}/media.rb +30 -17
  166. data/lib/ruby_llm/protocols/chat_completions/models.rb +39 -0
  167. data/lib/ruby_llm/protocols/chat_completions/moderation.rb +52 -0
  168. data/lib/ruby_llm/protocols/chat_completions/rerank.rb +56 -0
  169. data/lib/ruby_llm/protocols/chat_completions/speech.rb +40 -0
  170. data/lib/ruby_llm/protocols/chat_completions/streaming.rb +69 -0
  171. data/lib/ruby_llm/{providers/openai → protocols/chat_completions}/tools.rb +15 -17
  172. data/lib/ruby_llm/protocols/chat_completions/transcription.rb +150 -0
  173. data/lib/ruby_llm/protocols/chat_completions.rb +21 -0
  174. data/lib/ruby_llm/protocols/cohere/batch_requests.rb +75 -0
  175. data/lib/ruby_llm/protocols/cohere/batches.rb +98 -0
  176. data/lib/ruby_llm/protocols/cohere/chat.rb +227 -0
  177. data/lib/ruby_llm/protocols/cohere/datasets.rb +102 -0
  178. data/lib/ruby_llm/protocols/cohere/embeddings.rb +68 -0
  179. data/lib/ruby_llm/protocols/cohere/media.rb +77 -0
  180. data/lib/ruby_llm/protocols/cohere/models.rb +92 -0
  181. data/lib/ruby_llm/protocols/cohere/ocr.rb +63 -0
  182. data/lib/ruby_llm/protocols/cohere/rerank.rb +52 -0
  183. data/lib/ruby_llm/protocols/cohere/streaming.rb +105 -0
  184. data/lib/ruby_llm/protocols/cohere/tokenization.rb +22 -0
  185. data/lib/ruby_llm/protocols/cohere/tools.rb +132 -0
  186. data/lib/ruby_llm/protocols/cohere/transcription.rb +41 -0
  187. data/lib/ruby_llm/protocols/cohere.rb +21 -0
  188. data/lib/ruby_llm/protocols/converse/batches.rb +55 -0
  189. data/lib/ruby_llm/protocols/converse/chat.rb +695 -0
  190. data/lib/ruby_llm/protocols/converse/media.rb +178 -0
  191. data/lib/ruby_llm/protocols/converse/streaming.rb +432 -0
  192. data/lib/ruby_llm/protocols/converse/thinking_stream.rb +56 -0
  193. data/lib/ruby_llm/protocols/converse.rb +54 -0
  194. data/lib/ruby_llm/protocols/deepgram/models.rb +74 -0
  195. data/lib/ruby_llm/protocols/deepgram/speech.rb +93 -0
  196. data/lib/ruby_llm/protocols/deepgram/streaming_transcription.rb +89 -0
  197. data/lib/ruby_llm/protocols/deepgram/transcription.rb +96 -0
  198. data/lib/ruby_llm/protocols/deepgram.rb +19 -0
  199. data/lib/ruby_llm/protocols/deepseek/files.rb +31 -0
  200. data/lib/ruby_llm/protocols/elevenlabs/assets.rb +36 -0
  201. data/lib/ruby_llm/protocols/elevenlabs/flows/images.rb +74 -0
  202. data/lib/ruby_llm/protocols/elevenlabs/flows/media.rb +42 -0
  203. data/lib/ruby_llm/protocols/elevenlabs/flows/videos.rb +93 -0
  204. data/lib/ruby_llm/protocols/elevenlabs/flows.rb +14 -0
  205. data/lib/ruby_llm/protocols/elevenlabs/models.rb +64 -0
  206. data/lib/ruby_llm/protocols/elevenlabs/speech.rb +67 -0
  207. data/lib/ruby_llm/protocols/elevenlabs/streaming_transcription.rb +127 -0
  208. data/lib/ruby_llm/protocols/elevenlabs/transcription.rb +61 -0
  209. data/lib/ruby_llm/protocols/elevenlabs.rb +15 -0
  210. data/lib/ruby_llm/protocols/files.rb +119 -0
  211. data/lib/ruby_llm/protocols/gemini/batches.rb +162 -0
  212. data/lib/ruby_llm/protocols/gemini/caches.rb +59 -0
  213. data/lib/ruby_llm/protocols/gemini/chat.rb +453 -0
  214. data/lib/ruby_llm/protocols/gemini/embedding_batches.rb +86 -0
  215. data/lib/ruby_llm/protocols/gemini/embeddings.rb +70 -0
  216. data/lib/ruby_llm/protocols/gemini/file_transcription.rb +32 -0
  217. data/lib/ruby_llm/protocols/gemini/files.rb +115 -0
  218. data/lib/ruby_llm/protocols/gemini/images.rb +183 -0
  219. data/lib/ruby_llm/protocols/gemini/live_transcription.rb +140 -0
  220. data/lib/ruby_llm/{providers → protocols}/gemini/media.rb +17 -11
  221. data/lib/ruby_llm/protocols/gemini/models.rb +71 -0
  222. data/lib/ruby_llm/protocols/gemini/speech.rb +56 -0
  223. data/lib/ruby_llm/protocols/gemini/streaming.rb +96 -0
  224. data/lib/ruby_llm/protocols/gemini/tools.rb +157 -0
  225. data/lib/ruby_llm/{providers → protocols}/gemini/transcription.rb +22 -22
  226. data/lib/ruby_llm/protocols/gemini/videos.rb +103 -0
  227. data/lib/ruby_llm/protocols/gemini.rb +35 -0
  228. data/lib/ruby_llm/protocols/gpustack/responses.rb +111 -0
  229. data/lib/ruby_llm/protocols/gpustack/tokenization.rb +22 -0
  230. data/lib/ruby_llm/protocols/gpustack/videos.rb +96 -0
  231. data/lib/ruby_llm/protocols/interactions/chat.rb +145 -0
  232. data/lib/ruby_llm/protocols/interactions/content.rb +90 -0
  233. data/lib/ruby_llm/protocols/interactions/streaming.rb +91 -0
  234. data/lib/ruby_llm/protocols/interactions/tools.rb +51 -0
  235. data/lib/ruby_llm/protocols/interactions/transcription.rb +58 -0
  236. data/lib/ruby_llm/protocols/interactions.rb +29 -0
  237. data/lib/ruby_llm/protocols/invoke_model/cohere_embeddings.rb +51 -0
  238. data/lib/ruby_llm/protocols/invoke_model/embedding_batches.rb +111 -0
  239. data/lib/ruby_llm/protocols/invoke_model/nova_embeddings.rb +50 -0
  240. data/lib/ruby_llm/protocols/invoke_model/stability_images.rb +103 -0
  241. data/lib/ruby_llm/protocols/invoke_model/titan_multimodal_embeddings.rb +33 -0
  242. data/lib/ruby_llm/protocols/invoke_model/titan_text_embeddings.rb +44 -0
  243. data/lib/ruby_llm/protocols/invoke_model.rb +57 -0
  244. data/lib/ruby_llm/protocols/mistral/content.rb +49 -0
  245. data/lib/ruby_llm/protocols/mistral/conversations/chat.rb +160 -0
  246. data/lib/ruby_llm/protocols/mistral/conversations/images.rb +43 -0
  247. data/lib/ruby_llm/protocols/mistral/conversations/streaming.rb +83 -0
  248. data/lib/ruby_llm/protocols/mistral/conversations.rb +30 -0
  249. data/lib/ruby_llm/protocols/mistral/files.rb +36 -0
  250. data/lib/ruby_llm/protocols/mistral/multi_completion.rb +160 -0
  251. data/lib/ruby_llm/protocols/openai/batches.rb +126 -0
  252. data/lib/ruby_llm/protocols/openai/files.rb +42 -0
  253. data/lib/ruby_llm/protocols/openrouter/batches.rb +147 -0
  254. data/lib/ruby_llm/protocols/openrouter/files.rb +24 -0
  255. data/lib/ruby_llm/protocols/openrouter/responses.rb +53 -0
  256. data/lib/ruby_llm/protocols/openrouter/transcription.rb +51 -0
  257. data/lib/ruby_llm/protocols/perplexity/files.rb +48 -0
  258. data/lib/ruby_llm/protocols/perplexity/router.rb +59 -0
  259. data/lib/ruby_llm/protocols/responses/approvals.rb +32 -0
  260. data/lib/ruby_llm/protocols/responses/batches.rb +32 -0
  261. data/lib/ruby_llm/protocols/responses/chat.rb +476 -0
  262. data/lib/ruby_llm/protocols/responses/compaction.rb +29 -0
  263. data/lib/ruby_llm/protocols/responses/media.rb +61 -0
  264. data/lib/ruby_llm/protocols/responses/streaming.rb +117 -0
  265. data/lib/ruby_llm/protocols/responses/token_counting.rb +26 -0
  266. data/lib/ruby_llm/protocols/responses/tools.rb +39 -0
  267. data/lib/ruby_llm/protocols/responses.rb +35 -0
  268. data/lib/ruby_llm/protocols/vertexai/batch_prediction.rb +155 -0
  269. data/lib/ruby_llm/protocols/vertexai/embedding_prediction/requests.rb +85 -0
  270. data/lib/ruby_llm/protocols/vertexai/embedding_prediction/results.rb +74 -0
  271. data/lib/ruby_llm/protocols/vertexai/embedding_prediction.rb +56 -0
  272. data/lib/ruby_llm/protocols/vertexai/files.rb +101 -0
  273. data/lib/ruby_llm/protocols/vertexai/ranking.rb +69 -0
  274. data/lib/ruby_llm/protocols/vertexai/research.rb +193 -0
  275. data/lib/ruby_llm/protocols/xai/files.rb +30 -0
  276. data/lib/ruby_llm/protocols/xai/streaming_transcription.rb +120 -0
  277. data/lib/ruby_llm/protocols/xai/tokenization.rb +23 -0
  278. data/lib/ruby_llm/provider.rb +560 -128
  279. data/lib/ruby_llm/providers/anthropic/capabilities.rb +5 -7
  280. data/lib/ruby_llm/providers/anthropic.rb +4 -6
  281. data/lib/ruby_llm/providers/azure/audio.rb +18 -0
  282. data/lib/ruby_llm/providers/azure/capabilities.rb +16 -0
  283. data/lib/ruby_llm/providers/azure/chat.rb +2 -9
  284. data/lib/ruby_llm/providers/azure/chat_completions/batches.rb +29 -0
  285. data/lib/ruby_llm/providers/azure/chat_completions.rb +80 -0
  286. data/lib/ruby_llm/providers/azure/cohere.rb +33 -0
  287. data/lib/ruby_llm/providers/azure/embeddings.rb +3 -2
  288. data/lib/ruby_llm/providers/azure/images.rb +22 -0
  289. data/lib/ruby_llm/providers/azure/media.rb +5 -14
  290. data/lib/ruby_llm/providers/azure/models.rb +35 -0
  291. data/lib/ruby_llm/providers/azure/responses.rb +26 -0
  292. data/lib/ruby_llm/providers/azure/videos.rb +64 -0
  293. data/lib/ruby_llm/providers/azure.rb +77 -78
  294. data/lib/ruby_llm/providers/bedrock/auth.rb +60 -41
  295. data/lib/ruby_llm/providers/bedrock/capabilities.rb +18 -0
  296. data/lib/ruby_llm/providers/bedrock/mantle/anthropic.rb +39 -0
  297. data/lib/ruby_llm/providers/bedrock/mantle/chat_completions.rb +23 -0
  298. data/lib/ruby_llm/providers/bedrock/mantle/responses.rb +24 -0
  299. data/lib/ruby_llm/providers/bedrock/mantle/voxtral.rb +96 -0
  300. data/lib/ruby_llm/providers/bedrock/mantle.rb +57 -0
  301. data/lib/ruby_llm/providers/bedrock/models.rb +193 -41
  302. data/lib/ruby_llm/providers/bedrock.rb +216 -45
  303. data/lib/ruby_llm/providers/cohere.rb +31 -0
  304. data/lib/ruby_llm/providers/deepgram.rb +37 -0
  305. data/lib/ruby_llm/providers/deepseek/capabilities.rb +4 -51
  306. data/lib/ruby_llm/providers/deepseek/chat.rb +49 -2
  307. data/lib/ruby_llm/providers/deepseek/responses.rb +68 -0
  308. data/lib/ruby_llm/providers/deepseek.rb +9 -2
  309. data/lib/ruby_llm/providers/elevenlabs.rb +35 -0
  310. data/lib/ruby_llm/providers/gemini/capabilities.rb +8 -107
  311. data/lib/ruby_llm/providers/gemini.rb +15 -8
  312. data/lib/ruby_llm/providers/gpustack/chat.rb +2 -16
  313. data/lib/ruby_llm/providers/gpustack/embeddings.rb +28 -0
  314. data/lib/ruby_llm/providers/gpustack/media.rb +17 -16
  315. data/lib/ruby_llm/providers/gpustack/models.rb +72 -62
  316. data/lib/ruby_llm/providers/gpustack/speech.rb +15 -0
  317. data/lib/ruby_llm/providers/gpustack/transcription.rb +29 -0
  318. data/lib/ruby_llm/providers/gpustack.rb +35 -11
  319. data/lib/ruby_llm/providers/mistral/capabilities.rb +7 -155
  320. data/lib/ruby_llm/providers/mistral/chat.rb +37 -61
  321. data/lib/ruby_llm/providers/mistral/chat_completions/batches.rb +120 -0
  322. data/lib/ruby_llm/providers/mistral/chat_completions.rb +21 -0
  323. data/lib/ruby_llm/providers/mistral/conversations.rb +12 -0
  324. data/lib/ruby_llm/providers/mistral/embeddings.rb +6 -4
  325. data/lib/ruby_llm/providers/mistral/media.rb +6 -18
  326. data/lib/ruby_llm/providers/mistral/models.rb +57 -23
  327. data/lib/ruby_llm/providers/mistral/ocr.rb +47 -0
  328. data/lib/ruby_llm/providers/mistral/speech.rb +51 -0
  329. data/lib/ruby_llm/providers/mistral/transcription.rb +62 -0
  330. data/lib/ruby_llm/providers/mistral.rb +16 -4
  331. data/lib/ruby_llm/providers/ollama/chat.rb +7 -13
  332. data/lib/ruby_llm/providers/ollama/media.rb +6 -15
  333. data/lib/ruby_llm/providers/ollama/models.rb +50 -9
  334. data/lib/ruby_llm/providers/ollama.rb +9 -8
  335. data/lib/ruby_llm/providers/ollama_cloud/models.rb +14 -0
  336. data/lib/ruby_llm/providers/ollama_cloud.rb +40 -0
  337. data/lib/ruby_llm/providers/openai/capabilities.rb +54 -259
  338. data/lib/ruby_llm/providers/openai/models.rb +23 -23
  339. data/lib/ruby_llm/providers/openai/responses.rb +13 -0
  340. data/lib/ruby_llm/providers/openai.rb +92 -11
  341. data/lib/ruby_llm/providers/openrouter/chat.rb +130 -108
  342. data/lib/ruby_llm/providers/openrouter/embeddings.rb +51 -0
  343. data/lib/ruby_llm/providers/openrouter/images.rb +44 -43
  344. data/lib/ruby_llm/providers/openrouter/media.rb +34 -0
  345. data/lib/ruby_llm/providers/openrouter/models.rb +50 -11
  346. data/lib/ruby_llm/providers/openrouter/speech.rb +32 -0
  347. data/lib/ruby_llm/providers/openrouter/streaming.rb +31 -38
  348. data/lib/ruby_llm/providers/openrouter/videos.rb +81 -0
  349. data/lib/ruby_llm/providers/openrouter.rb +78 -20
  350. data/lib/ruby_llm/providers/perplexity/chat.rb +2 -9
  351. data/lib/ruby_llm/providers/perplexity/embeddings.rb +32 -0
  352. data/lib/ruby_llm/providers/perplexity/media.rb +5 -21
  353. data/lib/ruby_llm/providers/perplexity/models.rb +80 -13
  354. data/lib/ruby_llm/providers/perplexity.rb +28 -20
  355. data/lib/ruby_llm/providers/vertexai/anthropic/batches.rb +52 -0
  356. data/lib/ruby_llm/providers/vertexai/anthropic.rb +34 -0
  357. data/lib/ruby_llm/providers/vertexai/capabilities.rb +19 -0
  358. data/lib/ruby_llm/providers/vertexai/chat_completions/batches.rb +54 -0
  359. data/lib/ruby_llm/providers/vertexai/chat_completions.rb +15 -0
  360. data/lib/ruby_llm/providers/vertexai/embed_content.rb +42 -0
  361. data/lib/ruby_llm/providers/vertexai/embeddings.rb +22 -7
  362. data/lib/ruby_llm/providers/vertexai/gemini/batches.rb +42 -0
  363. data/lib/ruby_llm/providers/vertexai/gemini.rb +69 -0
  364. data/lib/ruby_llm/providers/vertexai/live_transcription.rb +24 -0
  365. data/lib/ruby_llm/providers/vertexai/mistral.rb +28 -0
  366. data/lib/ruby_llm/providers/vertexai/models.rb +145 -43
  367. data/lib/ruby_llm/providers/vertexai/transcription.rb +49 -4
  368. data/lib/ruby_llm/providers/vertexai/videos.rb +61 -0
  369. data/lib/ruby_llm/providers/vertexai.rb +160 -17
  370. data/lib/ruby_llm/providers/xai/capabilities.rb +18 -0
  371. data/lib/ruby_llm/providers/xai/chat.rb +3 -2
  372. data/lib/ruby_llm/providers/xai/chat_completions/batches.rb +108 -0
  373. data/lib/ruby_llm/providers/xai/chat_completions.rb +19 -0
  374. data/lib/ruby_llm/providers/xai/images.rb +91 -0
  375. data/lib/ruby_llm/providers/xai/models.rb +32 -36
  376. data/lib/ruby_llm/providers/xai/reported_cost.rb +18 -0
  377. data/lib/ruby_llm/providers/xai/responses.rb +52 -0
  378. data/lib/ruby_llm/providers/xai/speech.rb +45 -0
  379. data/lib/ruby_llm/providers/xai/transcription.rb +48 -0
  380. data/lib/ruby_llm/providers/xai/videos.rb +87 -0
  381. data/lib/ruby_llm/providers/xai.rb +15 -5
  382. data/lib/ruby_llm/railtie.rb +7 -16
  383. data/lib/ruby_llm/rerank.rb +105 -0
  384. data/lib/ruby_llm/research_job.rb +241 -0
  385. data/lib/ruby_llm/search_results.rb +68 -0
  386. data/lib/ruby_llm/server_tool_call.rb +73 -0
  387. data/lib/ruby_llm/speech.rb +159 -0
  388. data/lib/ruby_llm/speech_chunk.rb +33 -0
  389. data/lib/ruby_llm/support/deprecator.rb +22 -0
  390. data/lib/ruby_llm/support/inspectable.rb +49 -0
  391. data/lib/ruby_llm/support/instrumentation.rb +41 -0
  392. data/lib/ruby_llm/support/utils.rb +147 -0
  393. data/lib/ruby_llm/thinking.rb +127 -20
  394. data/lib/ruby_llm/tokenization.rb +59 -0
  395. data/lib/ruby_llm/tokens.rb +103 -33
  396. data/lib/ruby_llm/tool.rb +266 -91
  397. data/lib/ruby_llm/tool_call.rb +36 -3
  398. data/lib/ruby_llm/tools/server_tools.rb +109 -0
  399. data/lib/ruby_llm/transcription/wav_audio.rb +62 -0
  400. data/lib/ruby_llm/transcription.rb +138 -13
  401. data/lib/ruby_llm/transcription_chunk.rb +68 -0
  402. data/lib/ruby_llm/transport/connection.rb +193 -0
  403. data/lib/ruby_llm/transport/error_middleware.rb +131 -0
  404. data/lib/ruby_llm/transport/usage_middleware.rb +28 -0
  405. data/lib/ruby_llm/transport/websocket_connection.rb +220 -0
  406. data/lib/ruby_llm/uploaded_file.rb +144 -0
  407. data/lib/ruby_llm/version.rb +2 -1
  408. data/lib/ruby_llm/video.rb +136 -0
  409. data/lib/ruby_llm/video_job.rb +150 -0
  410. data/lib/ruby_llm/workflow.rb +91 -0
  411. data/lib/ruby_llm.rb +380 -6
  412. data/lib/tasks/ruby_llm.rake +21 -16
  413. data/skills/rubyllm/SKILL.md +81 -0
  414. data/skills/rubyllm/agents/openai.yaml +4 -0
  415. metadata +339 -97
  416. data/lib/generators/ruby_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt +0 -9
  417. data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +0 -39
  418. data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +0 -21
  419. data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +0 -3
  420. data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +0 -3
  421. data/lib/generators/ruby_llm/upgrade_to_v1_10/templates/add_v1_10_message_columns.rb.tt +0 -19
  422. data/lib/generators/ruby_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +0 -50
  423. data/lib/generators/ruby_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +0 -7
  424. data/lib/generators/ruby_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +0 -49
  425. data/lib/generators/ruby_llm/upgrade_to_v1_7/templates/migration.rb.tt +0 -145
  426. data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +0 -122
  427. data/lib/generators/ruby_llm/upgrade_to_v1_9/templates/add_v1_9_message_columns.rb.tt +0 -15
  428. data/lib/generators/ruby_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +0 -49
  429. data/lib/ruby_llm/active_record/acts_as_legacy.rb +0 -597
  430. data/lib/ruby_llm/active_record/model_methods.rb +0 -82
  431. data/lib/ruby_llm/active_record/tool_call_methods.rb +0 -18
  432. data/lib/ruby_llm/aliases.rb +0 -41
  433. data/lib/ruby_llm/connection.rb +0 -159
  434. data/lib/ruby_llm/content.rb +0 -91
  435. data/lib/ruby_llm/deprecator.rb +0 -24
  436. data/lib/ruby_llm/error_middleware.rb +0 -81
  437. data/lib/ruby_llm/instrumentation.rb +0 -36
  438. data/lib/ruby_llm/mime_type.rb +0 -96
  439. data/lib/ruby_llm/model/info.rb +0 -164
  440. data/lib/ruby_llm/model_registry.rb +0 -39
  441. data/lib/ruby_llm/models_schema.json +0 -171
  442. data/lib/ruby_llm/providers/anthropic/chat.rb +0 -291
  443. data/lib/ruby_llm/providers/anthropic/content.rb +0 -44
  444. data/lib/ruby_llm/providers/anthropic/embeddings.rb +0 -20
  445. data/lib/ruby_llm/providers/anthropic/media.rb +0 -92
  446. data/lib/ruby_llm/providers/anthropic/models.rb +0 -59
  447. data/lib/ruby_llm/providers/anthropic/streaming.rb +0 -71
  448. data/lib/ruby_llm/providers/bedrock/chat.rb +0 -405
  449. data/lib/ruby_llm/providers/bedrock/media.rb +0 -108
  450. data/lib/ruby_llm/providers/bedrock/streaming.rb +0 -328
  451. data/lib/ruby_llm/providers/gemini/chat.rb +0 -542
  452. data/lib/ruby_llm/providers/gemini/embeddings.rb +0 -37
  453. data/lib/ruby_llm/providers/gemini/images.rb +0 -47
  454. data/lib/ruby_llm/providers/gemini/models.rb +0 -38
  455. data/lib/ruby_llm/providers/gemini/streaming.rb +0 -98
  456. data/lib/ruby_llm/providers/gemini/tools.rb +0 -234
  457. data/lib/ruby_llm/providers/gpustack/capabilities.rb +0 -20
  458. data/lib/ruby_llm/providers/ollama/capabilities.rb +0 -20
  459. data/lib/ruby_llm/providers/openai/chat.rb +0 -236
  460. data/lib/ruby_llm/providers/openai/embeddings.rb +0 -33
  461. data/lib/ruby_llm/providers/openai/images.rb +0 -90
  462. data/lib/ruby_llm/providers/openai/moderation.rb +0 -34
  463. data/lib/ruby_llm/providers/openai/streaming.rb +0 -55
  464. data/lib/ruby_llm/providers/openai/temperature.rb +0 -28
  465. data/lib/ruby_llm/providers/openai/transcription.rb +0 -71
  466. data/lib/ruby_llm/providers/perplexity/capabilities.rb +0 -72
  467. data/lib/ruby_llm/providers/vertexai/chat.rb +0 -14
  468. data/lib/ruby_llm/providers/vertexai/streaming.rb +0 -14
  469. data/lib/ruby_llm/stream_accumulator.rb +0 -218
  470. data/lib/ruby_llm/streaming.rb +0 -179
  471. data/lib/ruby_llm/tool_concurrency.rb +0 -105
  472. data/lib/ruby_llm/utils.rb +0 -130
  473. data/lib/tasks/models.rake +0 -593
  474. data/lib/tasks/release.rake +0 -94
  475. data/lib/tasks/vcr.rake +0 -124
@@ -1,39 +0,0 @@
1
- class <%= create_migration_class_name(model_table_name) %> < ActiveRecord::Migration<%= migration_version %>
2
- def change
3
- create_table :<%= model_table_name %> do |t|
4
- t.string :model_id, null: false
5
- t.string :name, null: false
6
- t.string :provider, null: false
7
- t.string :family
8
- t.datetime :model_created_at
9
- t.integer :context_window
10
- t.integer :max_output_tokens
11
- t.date :knowledge_cutoff
12
- <% if postgresql? %>
13
- t.jsonb :modalities, default: {}
14
- t.jsonb :capabilities, default: []
15
- t.jsonb :pricing, default: {}
16
- t.jsonb :metadata, default: {}
17
- <% elsif mysql? %>
18
- t.json :modalities
19
- t.json :capabilities
20
- t.json :pricing
21
- t.json :metadata
22
- <% else %>
23
- t.json :modalities, default: {}
24
- t.json :capabilities, default: []
25
- t.json :pricing, default: {}
26
- t.json :metadata, default: {}
27
- <% end %>
28
- t.timestamps
29
-
30
- t.index [ :provider, :model_id ], unique: true
31
- t.index :provider
32
- t.index :family
33
- <% if postgresql? -%>
34
- t.index :capabilities, using: :gin
35
- t.index :modalities, using: :gin
36
- <% end -%>
37
- end
38
- end
39
- end
@@ -1,21 +0,0 @@
1
- <%#- # Migration for creating tool_calls table with database-specific JSON handling -%>
2
- class <%= create_migration_class_name(tool_call_table_name) %> < ActiveRecord::Migration<%= migration_version %>
3
- def change
4
- create_table :<%= tool_call_table_name %> do |t|
5
- t.string :tool_call_id, null: false
6
- t.string :name, null: false
7
- t.text :thought_signature
8
- <% if postgresql? %>
9
- t.jsonb :arguments, default: {}
10
- <% elsif mysql? %>
11
- t.json :arguments
12
- <% else %>
13
- t.json :arguments, default: {}
14
- <% end %>
15
- t.timestamps
16
- end
17
-
18
- add_index :<%= tool_call_table_name %>, :tool_call_id, unique: true
19
- add_index :<%= tool_call_table_name %>, :name
20
- end
21
- end
@@ -1,3 +0,0 @@
1
- class <%= model_model_name %> < ApplicationRecord
2
- <%= acts_as_model_declaration %>
3
- end
@@ -1,3 +0,0 @@
1
- class <%= tool_call_model_name %> < ApplicationRecord
2
- <%= acts_as_tool_call_declaration %>
3
- end
@@ -1,19 +0,0 @@
1
- class AddRubyLlmV110Columns < ActiveRecord::Migration<%= migration_version %>
2
- def change
3
- unless column_exists?(:<%= message_table_name %>, :thinking_text)
4
- add_column :<%= message_table_name %>, :thinking_text, :text
5
- end
6
-
7
- unless column_exists?(:<%= message_table_name %>, :thinking_signature)
8
- add_column :<%= message_table_name %>, :thinking_signature, :text
9
- end
10
-
11
- unless column_exists?(:<%= message_table_name %>, :thinking_tokens)
12
- add_column :<%= message_table_name %>, :thinking_tokens, :integer
13
- end
14
-
15
- unless column_exists?(:<%= tool_call_table_name %>, :thought_signature)
16
- add_column :<%= tool_call_table_name %>, :thought_signature, :string
17
- end
18
- end
19
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
5
- require_relative '../generator_helpers'
6
-
7
- module RubyLLM
8
- module Generators
9
- # Generator to add v1.10 columns (thinking output + thinking tokens) to existing apps.
10
- class UpgradeToV110Generator < Rails::Generators::Base
11
- include Rails::Generators::Migration
12
- include RubyLLM::Generators::GeneratorHelpers
13
-
14
- namespace 'ruby_llm:upgrade_to_v1_10'
15
- source_root File.expand_path('templates', __dir__)
16
-
17
- argument :model_mappings, type: :array, default: [], banner: 'message:MessageName'
18
-
19
- desc 'Adds thinking output columns and thinking token tracking introduced in v1.10.0'
20
-
21
- def self.next_migration_number(dirname)
22
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
23
- end
24
-
25
- def create_migration_file
26
- parse_model_mappings
27
-
28
- migration_template 'add_v1_10_message_columns.rb.tt',
29
- 'db/migrate/add_ruby_llm_v1_10_columns.rb',
30
- migration_version: migration_version,
31
- message_table_name: message_table_name,
32
- tool_call_table_name: tool_call_table_name
33
- end
34
-
35
- def show_next_steps
36
- say_status :success, 'Upgrade prepared!', :green
37
- say <<~INSTRUCTIONS
38
-
39
- Next steps:
40
- 1. Review the generated migration
41
- 2. Run: bin/rails db:migrate
42
- 3. Restart your application server
43
-
44
- 📚 See the v1.10.0 release notes for details on extended thinking support.
45
-
46
- INSTRUCTIONS
47
- end
48
- end
49
- end
50
- end
@@ -1,7 +0,0 @@
1
- class AddRubyLlmV114Columns < ActiveRecord::Migration<%= migration_version %>
2
- def change
3
- if column_exists?(:<%= tool_call_table_name %>, :thought_signature, :string)
4
- change_column :<%= tool_call_table_name %>, :thought_signature, :text
5
- end
6
- end
7
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
5
- require_relative '../generator_helpers'
6
-
7
- module RubyLLM
8
- module Generators
9
- # Generator to fix tool call thought signature column type for MySQL safety.
10
- class UpgradeToV114Generator < Rails::Generators::Base
11
- include Rails::Generators::Migration
12
- include RubyLLM::Generators::GeneratorHelpers
13
-
14
- namespace 'ruby_llm:upgrade_to_v1_14'
15
- source_root File.expand_path('templates', __dir__)
16
-
17
- argument :model_mappings, type: :array, default: [], banner: 'tool_call:ToolCallName'
18
-
19
- desc 'Updates tool call thought_signature column to text introduced in v1.14.0'
20
-
21
- def self.next_migration_number(dirname)
22
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
23
- end
24
-
25
- def create_migration_file
26
- parse_model_mappings
27
-
28
- migration_template 'add_v1_14_tool_call_columns.rb.tt',
29
- 'db/migrate/add_ruby_llm_v1_14_columns.rb',
30
- migration_version: migration_version,
31
- tool_call_table_name: tool_call_table_name
32
- end
33
-
34
- def show_next_steps
35
- say_status :success, 'Upgrade prepared!', :green
36
- say <<~INSTRUCTIONS
37
-
38
- Next steps:
39
- 1. Review the generated migration
40
- 2. Run: bin/rails db:migrate
41
- 3. Restart your application server
42
-
43
- 📚 See the v1.14.0 release notes for details on thought signature persistence.
44
-
45
- INSTRUCTIONS
46
- end
47
- end
48
- end
49
- end
@@ -1,145 +0,0 @@
1
- class MigrateToRubyLlmModelReferences < ActiveRecord::Migration<%= migration_version %>
2
- def up
3
- model_class = <%= model_model_name %>
4
- chat_class = <%= chat_model_name %>
5
- message_class = <%= message_model_name %>
6
- <% if @model_table_already_existed %>
7
- # Load models from models.json if Model table already existed
8
- say_with_time "Loading models from models.json" do
9
- RubyLLM.models.load_from_json!
10
- model_class.save_to_database
11
- "Loaded #{model_class.count} models"
12
- end
13
- <% end %>
14
-
15
- # Then check for any models in existing data that aren't in models.json
16
- say_with_time "Checking for additional models in existing data" do
17
- collect_and_create_models(chat_class, :<%= chat_table_name %>, model_class)
18
- collect_and_create_models(message_class, :<%= message_table_name %>, model_class)
19
- model_class.count
20
- end
21
-
22
- # Migrate foreign keys
23
- migrate_foreign_key(:<%= chat_table_name %>, chat_class, model_class, :<%= model_table_name.singularize %>)
24
- migrate_foreign_key(:<%= message_table_name %>, message_class, model_class, :<%= model_table_name.singularize %>)
25
- end
26
-
27
- def down
28
- # Remove foreign key references
29
- if column_exists?(:<%= message_table_name %>, :<%= model_table_name.singularize %>_id)
30
- remove_reference :<%= message_table_name %>, :<%= model_table_name.singularize %>, foreign_key: true
31
- end
32
-
33
- if column_exists?(:<%= chat_table_name %>, :<%= model_table_name.singularize %>_id)
34
- remove_reference :<%= chat_table_name %>, :<%= model_table_name.singularize %>, foreign_key: true
35
- end
36
-
37
- # Restore original model_id string columns
38
- if column_exists?(:<%= message_table_name %>, :model_id_string)
39
- rename_column :<%= message_table_name %>, :model_id_string, :model_id
40
- end
41
-
42
- if column_exists?(:<%= chat_table_name %>, :model_id_string)
43
- rename_column :<%= chat_table_name %>, :model_id_string, :model_id
44
- end
45
- end
46
-
47
- private
48
-
49
- def collect_and_create_models(record_class, table_name, model_class)
50
- return unless column_exists?(table_name, :model_id)
51
-
52
- has_provider = column_exists?(table_name, :provider)
53
-
54
- # Collect unique model/provider combinations using read_attribute to bypass overrides
55
- models_set = Set.new
56
-
57
- record_class.find_each do |record|
58
- model_id = record.read_attribute(:model_id)
59
- next if model_id.blank?
60
-
61
- provider = has_provider ? record.read_attribute(:provider) : nil
62
- models_set.add([ model_id, provider ])
63
- end
64
-
65
- models_set.each do |model_id, provider|
66
- find_or_create_model(model_id, provider, model_class)
67
- end
68
- end
69
-
70
- def find_or_create_model(model_id, provider, model_class)
71
- return if model_id.blank?
72
-
73
- begin
74
- model_info, _provider = RubyLLM.models.resolve(model_id, provider: provider)
75
-
76
- model_class.find_or_create_by!(
77
- model_id: model_info.id,
78
- provider: model_info.provider
79
- ) do |m|
80
- m.name = model_info.name || model_info.id
81
- m.family = model_info.family
82
- m.model_created_at = model_info.created_at
83
- m.context_window = model_info.context_window
84
- m.max_output_tokens = model_info.max_output_tokens
85
- m.knowledge_cutoff = model_info.knowledge_cutoff
86
- m.modalities = model_info.modalities.to_h
87
- m.capabilities = model_info.capabilities
88
- m.pricing = model_info.pricing.to_h
89
- m.metadata = model_info.metadata
90
- end
91
- rescue => e
92
- # Skip models that can't be resolved - they'll need manual fixing
93
- Rails.logger.warn "Skipping unresolvable model: #{model_id} - will need manual update"
94
- nil
95
- end
96
- end
97
-
98
-
99
- def migrate_foreign_key(table_name, record_class, model_class, foreign_key_name)
100
- return unless column_exists?(table_name, :model_id)
101
-
102
- # Check if we need to rename the string column to avoid collision
103
- if column_exists?(table_name, :model_id) && !foreign_key_exists?(table_name, :models)
104
- # Temporarily rename the string column
105
- rename_column table_name, :model_id, :model_id_string
106
- end
107
-
108
- # Add the foreign key reference
109
- unless column_exists?(table_name, "#{foreign_key_name}_id")
110
- add_reference table_name, foreign_key_name, foreign_key: true
111
- end
112
-
113
- say_with_time "Migrating #{table_name} model references" do
114
- record_class.reset_column_information
115
- has_provider = column_exists?(table_name, :provider)
116
-
117
- # Determine which column to read from (renamed or original)
118
- model_id_column = column_exists?(table_name, :model_id_string) ? :model_id_string : :model_id
119
-
120
- record_class.find_each do |record|
121
- model_id = record.read_attribute(model_id_column)
122
- next if model_id.blank?
123
-
124
- provider = has_provider ? record.read_attribute(:provider) : nil
125
-
126
- model = if has_provider && provider.present?
127
- model_class.find_by(model_id: model_id, provider: provider)
128
- else
129
- find_model_for_record(model_id, model_class)
130
- end
131
-
132
- record.update_column("#{foreign_key_name}_id", model.id) if model
133
- end
134
- end
135
- end
136
-
137
- def find_model_for_record(model_id, model_class)
138
- begin
139
- model_info, _provider = RubyLLM.models.resolve(model_id)
140
- model_class.find_by(model_id: model_info.id, provider: model_info.provider)
141
- rescue => e
142
- model_class.find_by(model_id: model_id)
143
- end
144
- end
145
- end
@@ -1,122 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
5
- require_relative '../generator_helpers'
6
-
7
- module RubyLLM
8
- module Generators
9
- # Generator to upgrade existing RubyLLM apps to v1.7 with association-based Rails API
10
- class UpgradeToV17Generator < Rails::Generators::Base
11
- include Rails::Generators::Migration
12
- include RubyLLM::Generators::GeneratorHelpers
13
-
14
- namespace 'ruby_llm:upgrade_to_v1_7'
15
- source_root File.expand_path('templates', __dir__)
16
-
17
- # Override source_paths to include install templates
18
- def self.source_paths
19
- [
20
- File.expand_path('templates', __dir__),
21
- File.expand_path('../install/templates', __dir__)
22
- ]
23
- end
24
-
25
- argument :model_mappings, type: :array, default: [], banner: 'chat:ChatName message:MessageName ...'
26
-
27
- desc 'Upgrades existing RubyLLM apps to v1.7 with association-based Rails API\n' \
28
- 'Usage: bin/rails g ruby_llm:upgrade_to_v1_7 [chat:ChatName] [message:MessageName] ...'
29
-
30
- def self.next_migration_number(dirname)
31
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
32
- end
33
-
34
- def create_migration_file
35
- @model_table_already_existed = table_exists?(table_name_for(model_model_name))
36
-
37
- # First check if models table exists, if not create it
38
- unless @model_table_already_existed
39
- migration_template 'create_models_migration.rb.tt',
40
- "db/migrate/create_#{table_name_for(model_model_name)}.rb",
41
- migration_version: migration_version,
42
- model_model_name: model_model_name
43
- end
44
-
45
- migration_template 'migration.rb.tt',
46
- 'db/migrate/migrate_to_ruby_llm_model_references.rb',
47
- migration_version: migration_version,
48
- chat_model_name: chat_model_name,
49
- message_model_name: message_model_name,
50
- tool_call_model_name: tool_call_model_name,
51
- model_model_name: model_model_name,
52
- model_table_already_existed: @model_table_already_existed
53
- end
54
-
55
- def create_model_file
56
- create_namespace_modules
57
-
58
- template 'model_model.rb.tt', "app/models/#{model_model_name.underscore}.rb"
59
- end
60
-
61
- def update_existing_models
62
- update_model_acts_as(chat_model_name, 'acts_as_chat', acts_as_chat_declaration)
63
- update_model_acts_as(message_model_name, 'acts_as_message', acts_as_message_declaration)
64
- update_model_acts_as(tool_call_model_name, 'acts_as_tool_call', acts_as_tool_call_declaration)
65
- end
66
-
67
- def update_initializer
68
- initializer_path = 'config/initializers/ruby_llm.rb'
69
-
70
- unless File.exist?(initializer_path)
71
- say_status :warning, 'No initializer found. Creating one...', :yellow
72
- template 'initializer.rb.tt', initializer_path
73
- return
74
- end
75
-
76
- initializer_content = File.read(initializer_path)
77
-
78
- return if initializer_content.include?('config.use_new_acts_as')
79
-
80
- inject_into_file initializer_path, before: /^end/ do
81
- lines = ["\n # Enable the association-based Rails API", ' config.use_new_acts_as = true']
82
- lines << " config.model_registry_class = \"#{model_model_name}\"" if model_model_name != 'Model'
83
- lines << "\n"
84
- lines.join("\n")
85
- end
86
- end
87
-
88
- def show_next_steps
89
- say_status :success, 'Upgrade prepared!', :green
90
- say <<~INSTRUCTIONS
91
-
92
- Next steps:
93
- 1. Review the generated migrations
94
- 2. Run: bin/rails db:migrate
95
- 3. Update your code to use the new API: #{chat_model_name}.create! now has the same signature as RubyLLM.chat
96
-
97
- ⚠️ If you get "undefined method 'acts_as_model'" during migration:
98
- Add this to config/application.rb BEFORE your Application class:
99
-
100
- RubyLLM.configure do |config|
101
- config.use_new_acts_as = true
102
- end
103
-
104
- 📚 See the full migration guide: https://rubyllm.com/upgrading-to-1-7/
105
-
106
- INSTRUCTIONS
107
- end
108
-
109
- private
110
-
111
- def update_model_acts_as(model_name, old_acts_as, new_acts_as)
112
- model_path = "app/models/#{model_name.underscore}.rb"
113
- return unless File.exist?(Rails.root.join(model_path))
114
-
115
- content = File.read(Rails.root.join(model_path))
116
- return unless content.match?(/^\s*#{old_acts_as}/)
117
-
118
- gsub_file model_path, /^\s*#{old_acts_as}.*$/, " #{new_acts_as}"
119
- end
120
- end
121
- end
122
- end
@@ -1,15 +0,0 @@
1
- class AddRubyLlmV19Columns < ActiveRecord::Migration<%= migration_version %>
2
- def change
3
- unless column_exists?(:<%= message_table_name %>, :cached_tokens)
4
- add_column :<%= message_table_name %>, :cached_tokens, :integer
5
- end
6
-
7
- unless column_exists?(:<%= message_table_name %>, :cache_creation_tokens)
8
- add_column :<%= message_table_name %>, :cache_creation_tokens, :integer
9
- end
10
-
11
- unless column_exists?(:<%= message_table_name %>, :content_raw)
12
- add_column :<%= message_table_name %>, :content_raw, :json
13
- end
14
- end
15
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
5
- require_relative '../generator_helpers'
6
-
7
- module RubyLLM
8
- module Generators
9
- # Generator to add v1.9 columns (cached tokens + raw content support) to existing apps.
10
- class UpgradeToV19Generator < Rails::Generators::Base
11
- include Rails::Generators::Migration
12
- include RubyLLM::Generators::GeneratorHelpers
13
-
14
- namespace 'ruby_llm:upgrade_to_v1_9'
15
- source_root File.expand_path('templates', __dir__)
16
-
17
- argument :model_mappings, type: :array, default: [], banner: 'message:MessageName'
18
-
19
- desc 'Adds cached token columns and raw content storage fields introduced in v1.9.0'
20
-
21
- def self.next_migration_number(dirname)
22
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
23
- end
24
-
25
- def create_migration_file
26
- parse_model_mappings
27
-
28
- migration_template 'add_v1_9_message_columns.rb.tt',
29
- 'db/migrate/add_ruby_llm_v1_9_columns.rb',
30
- migration_version: migration_version,
31
- message_table_name: message_table_name
32
- end
33
-
34
- def show_next_steps
35
- say_status :success, 'Upgrade prepared!', :green
36
- say <<~INSTRUCTIONS
37
-
38
- Next steps:
39
- 1. Review the generated migration
40
- 2. Run: bin/rails db:migrate
41
- 3. Restart your application server
42
-
43
- 📚 See the v1.9.0 release notes for details on cached token tracking and raw content support.
44
-
45
- INSTRUCTIONS
46
- end
47
- end
48
- end
49
- end