ruby_llm-agents 0.5.0 → 1.0.0.beta.1

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +189 -31
  3. data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
  4. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
  5. data/app/controllers/ruby_llm/agents/workflows_controller.rb +355 -0
  6. data/app/helpers/ruby_llm/agents/application_helper.rb +25 -0
  7. data/app/models/ruby_llm/agents/execution.rb +3 -0
  8. data/app/models/ruby_llm/agents/tenant_budget.rb +58 -15
  9. data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
  10. data/app/views/layouts/ruby_llm/agents/application.html.erb +2 -29
  11. data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -1
  12. data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +235 -0
  13. data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +70 -0
  14. data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +152 -0
  15. data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +63 -0
  16. data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +108 -0
  17. data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +91 -0
  18. data/app/views/ruby_llm/agents/agents/_workflow.html.erb +1 -1
  19. data/app/views/ruby_llm/agents/agents/index.html.erb +74 -9
  20. data/app/views/ruby_llm/agents/agents/show.html.erb +18 -378
  21. data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
  22. data/app/views/ruby_llm/agents/executions/show.html.erb +16 -0
  23. data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
  24. data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +236 -0
  25. data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +76 -0
  26. data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +74 -0
  27. data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +108 -0
  28. data/app/views/ruby_llm/agents/workflows/show.html.erb +442 -0
  29. data/config/routes.rb +1 -0
  30. data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
  31. data/lib/generators/ruby_llm_agents/background_remover_generator.rb +110 -0
  32. data/lib/generators/ruby_llm_agents/embedder_generator.rb +107 -0
  33. data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +115 -0
  34. data/lib/generators/ruby_llm_agents/image_editor_generator.rb +108 -0
  35. data/lib/generators/ruby_llm_agents/image_generator_generator.rb +116 -0
  36. data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +178 -0
  37. data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +109 -0
  38. data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +103 -0
  39. data/lib/generators/ruby_llm_agents/image_variator_generator.rb +102 -0
  40. data/lib/generators/ruby_llm_agents/install_generator.rb +76 -4
  41. data/lib/generators/ruby_llm_agents/restructure_generator.rb +292 -0
  42. data/lib/generators/ruby_llm_agents/speaker_generator.rb +121 -0
  43. data/lib/generators/ruby_llm_agents/templates/add_execution_type_migration.rb.tt +8 -0
  44. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +99 -84
  45. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +42 -40
  46. data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +26 -0
  47. data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +50 -0
  48. data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +26 -0
  49. data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +20 -0
  50. data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +38 -0
  51. data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +139 -0
  52. data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +21 -0
  53. data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +20 -0
  54. data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +20 -0
  55. data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +49 -0
  56. data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +53 -0
  57. data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +44 -0
  58. data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +41 -0
  59. data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +45 -0
  60. data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +35 -0
  61. data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +47 -0
  62. data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +50 -0
  63. data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +44 -0
  64. data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +38 -0
  65. data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +33 -0
  66. data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +228 -0
  67. data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +131 -0
  68. data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +255 -0
  69. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +120 -0
  70. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +102 -0
  71. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +282 -0
  72. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +228 -0
  73. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +120 -0
  74. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +110 -0
  75. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +120 -0
  76. data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +212 -0
  77. data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +227 -0
  78. data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +251 -0
  79. data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +300 -0
  80. data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +56 -0
  81. data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +51 -0
  82. data/lib/generators/ruby_llm_agents/transcriber_generator.rb +107 -0
  83. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +152 -1
  84. data/lib/ruby_llm/agents/audio/speaker.rb +553 -0
  85. data/lib/ruby_llm/agents/audio/transcriber.rb +669 -0
  86. data/lib/ruby_llm/agents/base_agent.rb +675 -0
  87. data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +181 -0
  88. data/lib/ruby_llm/agents/core/base/moderation_execution.rb +274 -0
  89. data/lib/ruby_llm/agents/core/base.rb +135 -0
  90. data/lib/ruby_llm/agents/core/configuration.rb +981 -0
  91. data/lib/ruby_llm/agents/core/errors.rb +150 -0
  92. data/lib/ruby_llm/agents/{instrumentation.rb → core/instrumentation.rb} +22 -1
  93. data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
  94. data/lib/ruby_llm/agents/{version.rb → core/version.rb} +1 -1
  95. data/lib/ruby_llm/agents/dsl/base.rb +110 -0
  96. data/lib/ruby_llm/agents/dsl/caching.rb +142 -0
  97. data/lib/ruby_llm/agents/dsl/reliability.rb +307 -0
  98. data/lib/ruby_llm/agents/dsl.rb +41 -0
  99. data/lib/ruby_llm/agents/image/analyzer/dsl.rb +130 -0
  100. data/lib/ruby_llm/agents/image/analyzer/execution.rb +402 -0
  101. data/lib/ruby_llm/agents/image/analyzer.rb +90 -0
  102. data/lib/ruby_llm/agents/image/background_remover/dsl.rb +154 -0
  103. data/lib/ruby_llm/agents/image/background_remover/execution.rb +240 -0
  104. data/lib/ruby_llm/agents/image/background_remover.rb +89 -0
  105. data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +91 -0
  106. data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +165 -0
  107. data/lib/ruby_llm/agents/image/editor/dsl.rb +56 -0
  108. data/lib/ruby_llm/agents/image/editor/execution.rb +207 -0
  109. data/lib/ruby_llm/agents/image/editor.rb +92 -0
  110. data/lib/ruby_llm/agents/image/generator/active_storage_support.rb +127 -0
  111. data/lib/ruby_llm/agents/image/generator/content_policy.rb +95 -0
  112. data/lib/ruby_llm/agents/image/generator/pricing.rb +353 -0
  113. data/lib/ruby_llm/agents/image/generator/templates.rb +124 -0
  114. data/lib/ruby_llm/agents/image/generator.rb +455 -0
  115. data/lib/ruby_llm/agents/image/pipeline/dsl.rb +213 -0
  116. data/lib/ruby_llm/agents/image/pipeline/execution.rb +382 -0
  117. data/lib/ruby_llm/agents/image/pipeline.rb +97 -0
  118. data/lib/ruby_llm/agents/image/transformer/dsl.rb +148 -0
  119. data/lib/ruby_llm/agents/image/transformer/execution.rb +223 -0
  120. data/lib/ruby_llm/agents/image/transformer.rb +95 -0
  121. data/lib/ruby_llm/agents/image/upscaler/dsl.rb +83 -0
  122. data/lib/ruby_llm/agents/image/upscaler/execution.rb +219 -0
  123. data/lib/ruby_llm/agents/image/upscaler.rb +81 -0
  124. data/lib/ruby_llm/agents/image/variator/dsl.rb +62 -0
  125. data/lib/ruby_llm/agents/image/variator/execution.rb +189 -0
  126. data/lib/ruby_llm/agents/image/variator.rb +80 -0
  127. data/lib/ruby_llm/agents/{alert_manager.rb → infrastructure/alert_manager.rb} +17 -22
  128. data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +145 -0
  129. data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +149 -0
  130. data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +68 -0
  131. data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +279 -0
  132. data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +275 -0
  133. data/lib/ruby_llm/agents/{execution_logger_job.rb → infrastructure/execution_logger_job.rb} +17 -1
  134. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/executor.rb +2 -1
  135. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/retry_strategy.rb +9 -3
  136. data/lib/ruby_llm/agents/{reliability.rb → infrastructure/reliability.rb} +11 -21
  137. data/lib/ruby_llm/agents/pipeline/builder.rb +215 -0
  138. data/lib/ruby_llm/agents/pipeline/context.rb +255 -0
  139. data/lib/ruby_llm/agents/pipeline/executor.rb +86 -0
  140. data/lib/ruby_llm/agents/pipeline/middleware/base.rb +124 -0
  141. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +95 -0
  142. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +171 -0
  143. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +415 -0
  144. data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +276 -0
  145. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +196 -0
  146. data/lib/ruby_llm/agents/pipeline.rb +68 -0
  147. data/lib/ruby_llm/agents/{engine.rb → rails/engine.rb} +79 -11
  148. data/lib/ruby_llm/agents/results/background_removal_result.rb +286 -0
  149. data/lib/ruby_llm/agents/{result.rb → results/base.rb} +73 -1
  150. data/lib/ruby_llm/agents/results/embedding_result.rb +243 -0
  151. data/lib/ruby_llm/agents/results/image_analysis_result.rb +314 -0
  152. data/lib/ruby_llm/agents/results/image_edit_result.rb +250 -0
  153. data/lib/ruby_llm/agents/results/image_generation_result.rb +346 -0
  154. data/lib/ruby_llm/agents/results/image_pipeline_result.rb +399 -0
  155. data/lib/ruby_llm/agents/results/image_transform_result.rb +251 -0
  156. data/lib/ruby_llm/agents/results/image_upscale_result.rb +255 -0
  157. data/lib/ruby_llm/agents/results/image_variation_result.rb +237 -0
  158. data/lib/ruby_llm/agents/results/moderation_result.rb +158 -0
  159. data/lib/ruby_llm/agents/results/speech_result.rb +338 -0
  160. data/lib/ruby_llm/agents/results/transcription_result.rb +408 -0
  161. data/lib/ruby_llm/agents/text/embedder.rb +444 -0
  162. data/lib/ruby_llm/agents/text/moderator.rb +237 -0
  163. data/lib/ruby_llm/agents/workflow/async.rb +220 -0
  164. data/lib/ruby_llm/agents/workflow/async_executor.rb +156 -0
  165. data/lib/ruby_llm/agents/{workflow.rb → workflow/orchestrator.rb} +6 -5
  166. data/lib/ruby_llm/agents/workflow/parallel.rb +34 -17
  167. data/lib/ruby_llm/agents/workflow/thread_pool.rb +185 -0
  168. data/lib/ruby_llm/agents.rb +86 -20
  169. metadata +172 -34
  170. data/lib/ruby_llm/agents/base/caching.rb +0 -40
  171. data/lib/ruby_llm/agents/base/cost_calculation.rb +0 -105
  172. data/lib/ruby_llm/agents/base/dsl.rb +0 -324
  173. data/lib/ruby_llm/agents/base/execution.rb +0 -366
  174. data/lib/ruby_llm/agents/base/reliability_dsl.rb +0 -82
  175. data/lib/ruby_llm/agents/base/reliability_execution.rb +0 -136
  176. data/lib/ruby_llm/agents/base/response_building.rb +0 -86
  177. data/lib/ruby_llm/agents/base/tool_tracking.rb +0 -57
  178. data/lib/ruby_llm/agents/base.rb +0 -210
  179. data/lib/ruby_llm/agents/budget_tracker.rb +0 -733
  180. data/lib/ruby_llm/agents/configuration.rb +0 -394
  181. /data/lib/ruby_llm/agents/{deprecations.rb → core/deprecations.rb} +0 -0
  182. /data/lib/ruby_llm/agents/{inflections.rb → core/inflections.rb} +0 -0
  183. /data/lib/ruby_llm/agents/{resolved_config.rb → core/resolved_config.rb} +0 -0
  184. /data/lib/ruby_llm/agents/{attempt_tracker.rb → infrastructure/attempt_tracker.rb} +0 -0
  185. /data/lib/ruby_llm/agents/{cache_helper.rb → infrastructure/cache_helper.rb} +0 -0
  186. /data/lib/ruby_llm/agents/{circuit_breaker.rb → infrastructure/circuit_breaker.rb} +0 -0
  187. /data/lib/ruby_llm/agents/{redactor.rb → infrastructure/redactor.rb} +0 -0
  188. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/breaker_manager.rb +0 -0
  189. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/execution_constraints.rb +0 -0
  190. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/fallback_routing.rb +0 -0
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module RubyLlmAgents
6
+ # ImageTransformer generator for creating new image transformers
7
+ #
8
+ # Usage:
9
+ # rails generate ruby_llm_agents:image_transformer Anime
10
+ # rails generate ruby_llm_agents:image_transformer Watercolor --model sdxl --strength 0.8
11
+ # rails generate ruby_llm_agents:image_transformer Oil --template "oil painting, {prompt}"
12
+ # rails generate ruby_llm_agents:image_transformer Anime --root=ai
13
+ #
14
+ # This will create:
15
+ # - app/{root}/image/transformers/anime_transformer.rb
16
+ #
17
+ class ImageTransformerGenerator < ::Rails::Generators::NamedBase
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ class_option :model, type: :string, default: "sdxl",
21
+ desc: "The image model to use"
22
+ class_option :size, type: :string, default: "1024x1024",
23
+ desc: "Output image size (e.g., 1024x1024)"
24
+ class_option :strength, type: :string, default: "0.75",
25
+ desc: "Transformation strength (0.0-1.0)"
26
+ class_option :template, type: :string, default: nil,
27
+ desc: "Prompt template (use {prompt} as placeholder)"
28
+ class_option :content_policy, type: :string, default: "standard",
29
+ desc: "Content policy level (none, standard, moderate, strict)"
30
+ class_option :cache, type: :string, default: nil,
31
+ desc: "Cache TTL (e.g., '1.hour', '1.day')"
32
+ class_option :root,
33
+ type: :string,
34
+ default: nil,
35
+ desc: "Root directory name (default: uses config or 'llm')"
36
+ class_option :namespace,
37
+ type: :string,
38
+ default: nil,
39
+ desc: "Root namespace (default: camelized root or config)"
40
+
41
+ def ensure_base_class_and_skill_file
42
+ @root_namespace = root_namespace
43
+ @image_namespace = "#{root_namespace}::Image"
44
+ transformers_dir = "app/#{root_directory}/image/transformers"
45
+
46
+ # Create directory if needed
47
+ empty_directory transformers_dir
48
+
49
+ # Create base class if it doesn't exist
50
+ base_class_path = "#{transformers_dir}/application_image_transformer.rb"
51
+ unless File.exist?(File.join(destination_root, base_class_path))
52
+ template "application_image_transformer.rb.tt", base_class_path
53
+ end
54
+
55
+ # Create skill file if it doesn't exist
56
+ skill_file_path = "#{transformers_dir}/IMAGE_TRANSFORMERS.md"
57
+ unless File.exist?(File.join(destination_root, skill_file_path))
58
+ template "skills/IMAGE_TRANSFORMERS.md.tt", skill_file_path
59
+ end
60
+ end
61
+
62
+ def create_image_transformer_file
63
+ @root_namespace = root_namespace
64
+ @image_namespace = "#{root_namespace}::Image"
65
+ transformer_path = name.underscore
66
+ template "image_transformer.rb.tt", "app/#{root_directory}/image/transformers/#{transformer_path}_transformer.rb"
67
+ end
68
+
69
+ def show_usage
70
+ transformer_class_name = name.split("/").map(&:camelize).join("::")
71
+ full_class_name = "#{root_namespace}::Image::#{transformer_class_name}Transformer"
72
+ say ""
73
+ say "Image transformer #{full_class_name} created!", :green
74
+ say ""
75
+ say "Usage:"
76
+ say " # Transform an image with a style"
77
+ say " result = #{full_class_name}.call("
78
+ say " image: 'photo.jpg',"
79
+ say " prompt: 'portrait of a person'"
80
+ say " )"
81
+ say " result.url # => 'https://...'"
82
+ say ""
83
+ say " # Override strength at runtime"
84
+ say " result = #{full_class_name}.call("
85
+ say " image: 'photo.jpg',"
86
+ say " prompt: 'detailed portrait',"
87
+ say " strength: 0.9"
88
+ say " )"
89
+ say ""
90
+ end
91
+
92
+ private
93
+
94
+ def root_directory
95
+ @root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
96
+ end
97
+
98
+ def root_namespace
99
+ @root_namespace ||= options[:namespace] || camelize(root_directory)
100
+ end
101
+
102
+ def camelize(str)
103
+ return "AI" if str.downcase == "ai"
104
+ return "ML" if str.downcase == "ml"
105
+ return "LLM" if str.downcase == "llm"
106
+ str.split(/[-_]/).map(&:capitalize).join
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module RubyLlmAgents
6
+ # ImageUpscaler generator for creating new image upscalers
7
+ #
8
+ # Usage:
9
+ # rails generate ruby_llm_agents:image_upscaler Photo
10
+ # rails generate ruby_llm_agents:image_upscaler Portrait --model real-esrgan --scale 4
11
+ # rails generate ruby_llm_agents:image_upscaler Face --face_enhance
12
+ # rails generate ruby_llm_agents:image_upscaler Photo --root=ai
13
+ #
14
+ # This will create:
15
+ # - app/{root}/image/upscalers/photo_upscaler.rb
16
+ #
17
+ class ImageUpscalerGenerator < ::Rails::Generators::NamedBase
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ class_option :model, type: :string, default: "real-esrgan",
21
+ desc: "The upscaling model to use"
22
+ class_option :scale, type: :string, default: "4",
23
+ desc: "Upscale factor (2, 4, or 8)"
24
+ class_option :face_enhance, type: :boolean, default: false,
25
+ desc: "Enable face enhancement"
26
+ class_option :cache, type: :string, default: nil,
27
+ desc: "Cache TTL (e.g., '1.hour', '1.day')"
28
+ class_option :root,
29
+ type: :string,
30
+ default: nil,
31
+ desc: "Root directory name (default: uses config or 'llm')"
32
+ class_option :namespace,
33
+ type: :string,
34
+ default: nil,
35
+ desc: "Root namespace (default: camelized root or config)"
36
+
37
+ def ensure_base_class_and_skill_file
38
+ @root_namespace = root_namespace
39
+ @image_namespace = "#{root_namespace}::Image"
40
+ upscalers_dir = "app/#{root_directory}/image/upscalers"
41
+
42
+ # Create directory if needed
43
+ empty_directory upscalers_dir
44
+
45
+ # Create base class if it doesn't exist
46
+ base_class_path = "#{upscalers_dir}/application_image_upscaler.rb"
47
+ unless File.exist?(File.join(destination_root, base_class_path))
48
+ template "application_image_upscaler.rb.tt", base_class_path
49
+ end
50
+
51
+ # Create skill file if it doesn't exist
52
+ skill_file_path = "#{upscalers_dir}/IMAGE_UPSCALERS.md"
53
+ unless File.exist?(File.join(destination_root, skill_file_path))
54
+ template "skills/IMAGE_UPSCALERS.md.tt", skill_file_path
55
+ end
56
+ end
57
+
58
+ def create_image_upscaler_file
59
+ @root_namespace = root_namespace
60
+ @image_namespace = "#{root_namespace}::Image"
61
+ upscaler_path = name.underscore
62
+ template "image_upscaler.rb.tt", "app/#{root_directory}/image/upscalers/#{upscaler_path}_upscaler.rb"
63
+ end
64
+
65
+ def show_usage
66
+ upscaler_class_name = name.split("/").map(&:camelize).join("::")
67
+ full_class_name = "#{root_namespace}::Image::#{upscaler_class_name}Upscaler"
68
+ say ""
69
+ say "Image upscaler #{full_class_name} created!", :green
70
+ say ""
71
+ say "Usage:"
72
+ say " # Upscale an image"
73
+ say " result = #{full_class_name}.call(image: 'low_res.jpg')"
74
+ say " result.url # => 'https://...'"
75
+ say " result.output_size # => '4096x4096'"
76
+ say ""
77
+ say " # Override settings at runtime"
78
+ say " result = #{full_class_name}.call("
79
+ say " image: 'photo.jpg',"
80
+ say " scale: 8,"
81
+ say " face_enhance: true"
82
+ say " )"
83
+ say ""
84
+ end
85
+
86
+ private
87
+
88
+ def root_directory
89
+ @root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
90
+ end
91
+
92
+ def root_namespace
93
+ @root_namespace ||= options[:namespace] || camelize(root_directory)
94
+ end
95
+
96
+ def camelize(str)
97
+ return "AI" if str.downcase == "ai"
98
+ return "ML" if str.downcase == "ml"
99
+ return "LLM" if str.downcase == "llm"
100
+ str.split(/[-_]/).map(&:capitalize).join
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module RubyLlmAgents
6
+ # ImageVariator generator for creating new image variators
7
+ #
8
+ # Usage:
9
+ # rails generate ruby_llm_agents:image_variator Logo
10
+ # rails generate ruby_llm_agents:image_variator Product --model gpt-image-1 --size 1024x1024
11
+ # rails generate ruby_llm_agents:image_variator Avatar --variation_strength 0.3
12
+ # rails generate ruby_llm_agents:image_variator Logo --root=ai
13
+ #
14
+ # This will create:
15
+ # - app/{root}/image/variators/logo_variator.rb
16
+ #
17
+ class ImageVariatorGenerator < ::Rails::Generators::NamedBase
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ class_option :model, type: :string, default: "gpt-image-1",
21
+ desc: "The image model to use"
22
+ class_option :size, type: :string, default: "1024x1024",
23
+ desc: "Output image size (e.g., 1024x1024)"
24
+ class_option :variation_strength, type: :string, default: "0.5",
25
+ desc: "Variation strength (0.0-1.0)"
26
+ class_option :cache, type: :string, default: nil,
27
+ desc: "Cache TTL (e.g., '1.hour', '1.day')"
28
+ class_option :root,
29
+ type: :string,
30
+ default: nil,
31
+ desc: "Root directory name (default: uses config or 'llm')"
32
+ class_option :namespace,
33
+ type: :string,
34
+ default: nil,
35
+ desc: "Root namespace (default: camelized root or config)"
36
+
37
+ def ensure_base_class_and_skill_file
38
+ @root_namespace = root_namespace
39
+ @image_namespace = "#{root_namespace}::Image"
40
+ variators_dir = "app/#{root_directory}/image/variators"
41
+
42
+ # Create directory if needed
43
+ empty_directory variators_dir
44
+
45
+ # Create base class if it doesn't exist
46
+ base_class_path = "#{variators_dir}/application_image_variator.rb"
47
+ unless File.exist?(File.join(destination_root, base_class_path))
48
+ template "application_image_variator.rb.tt", base_class_path
49
+ end
50
+
51
+ # Create skill file if it doesn't exist
52
+ skill_file_path = "#{variators_dir}/IMAGE_VARIATORS.md"
53
+ unless File.exist?(File.join(destination_root, skill_file_path))
54
+ template "skills/IMAGE_VARIATORS.md.tt", skill_file_path
55
+ end
56
+ end
57
+
58
+ def create_image_variator_file
59
+ @root_namespace = root_namespace
60
+ @image_namespace = "#{root_namespace}::Image"
61
+ variator_path = name.underscore
62
+ template "image_variator.rb.tt", "app/#{root_directory}/image/variators/#{variator_path}_variator.rb"
63
+ end
64
+
65
+ def show_usage
66
+ variator_class_name = name.split("/").map(&:camelize).join("::")
67
+ full_class_name = "#{root_namespace}::Image::#{variator_class_name}Variator"
68
+ say ""
69
+ say "Image variator #{full_class_name} created!", :green
70
+ say ""
71
+ say "Usage:"
72
+ say " # Generate variations of an image"
73
+ say " result = #{full_class_name}.call(image: 'logo.png', count: 4)"
74
+ say " result.urls # => ['https://...', ...]"
75
+ say ""
76
+ say " # Override settings at runtime"
77
+ say " result = #{full_class_name}.call("
78
+ say " image: 'logo.png',"
79
+ say " variation_strength: 0.7,"
80
+ say " count: 3"
81
+ say " )"
82
+ say ""
83
+ end
84
+
85
+ private
86
+
87
+ def root_directory
88
+ @root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
89
+ end
90
+
91
+ def root_namespace
92
+ @root_namespace ||= options[:namespace] || camelize(root_directory)
93
+ end
94
+
95
+ def camelize(str)
96
+ return "AI" if str.downcase == "ai"
97
+ return "ML" if str.downcase == "ml"
98
+ return "LLM" if str.downcase == "llm"
99
+ str.split(/[-_]/).map(&:capitalize).join
100
+ end
101
+ end
102
+ end
@@ -8,11 +8,13 @@ module RubyLlmAgents
8
8
  #
9
9
  # Usage:
10
10
  # rails generate ruby_llm_agents:install
11
+ # rails generate ruby_llm_agents:install --root=ai
11
12
  #
12
13
  # This will:
13
14
  # - Create the migration for ruby_llm_agents_executions table
14
15
  # - Create the initializer at config/initializers/ruby_llm_agents.rb
15
- # - Create app/agents/application_agent.rb base class
16
+ # - Create app/{root}/agents/application_agent.rb base class
17
+ # - Create app/{root}/text/embedders/application_embedder.rb base class
16
18
  # - Optionally mount the dashboard engine in routes
17
19
  #
18
20
  class InstallGenerator < ::Rails::Generators::Base
@@ -26,6 +28,14 @@ module RubyLlmAgents
26
28
  desc: "Skip generating the initializer file"
27
29
  class_option :mount_dashboard, type: :boolean, default: true,
28
30
  desc: "Mount the dashboard engine in routes"
31
+ class_option :root,
32
+ type: :string,
33
+ default: nil,
34
+ desc: "Root directory name (default: uses config or 'llm')"
35
+ class_option :namespace,
36
+ type: :string,
37
+ default: nil,
38
+ desc: "Root namespace (default: camelized root or config)"
29
39
 
30
40
  def create_migration_file
31
41
  return if options[:skip_migration]
@@ -42,12 +52,44 @@ module RubyLlmAgents
42
52
  template "initializer.rb.tt", "config/initializers/ruby_llm_agents.rb"
43
53
  end
44
54
 
45
- def create_agents_directory
46
- empty_directory "app/agents"
55
+ def create_directory_structure
56
+ say_status :create, "#{root_directory}/ directory structure", :green
57
+
58
+ # Create agents directory
59
+ empty_directory "app/#{root_directory}/agents"
60
+
61
+ # Create text/embedders directory
62
+ empty_directory "app/#{root_directory}/text/embedders"
47
63
  end
48
64
 
49
65
  def create_application_agent
50
- template "application_agent.rb.tt", "app/agents/application_agent.rb"
66
+ @root_namespace = root_namespace
67
+ template "application_agent.rb.tt", "app/#{root_directory}/agents/application_agent.rb"
68
+ end
69
+
70
+ def create_application_embedder
71
+ @root_namespace = root_namespace
72
+ @text_namespace = "#{root_namespace}::Text"
73
+ template "application_embedder.rb.tt", "app/#{root_directory}/text/embedders/application_embedder.rb"
74
+ end
75
+
76
+ def create_skill_files
77
+ @root_namespace = root_namespace
78
+ say_status :create, "skill documentation files", :green
79
+
80
+ # Create agents skill file
81
+ template "skills/AGENTS.md.tt", "app/#{root_directory}/agents/AGENTS.md"
82
+
83
+ # Create embedders skill file
84
+ template "skills/EMBEDDERS.md.tt", "app/#{root_directory}/text/embedders/EMBEDDERS.md"
85
+
86
+ # Create tools directory and skill file
87
+ empty_directory "app/#{root_directory}/tools"
88
+ template "skills/TOOLS.md.tt", "app/#{root_directory}/tools/TOOLS.md"
89
+
90
+ # Create workflows directory and skill file
91
+ empty_directory "app/#{root_directory}/workflows"
92
+ template "skills/WORKFLOWS.md.tt", "app/#{root_directory}/workflows/WORKFLOWS.md"
51
93
  end
52
94
 
53
95
  def mount_dashboard_engine
@@ -69,6 +111,24 @@ module RubyLlmAgents
69
111
  say ""
70
112
  say "RubyLLM::Agents has been installed!", :green
71
113
  say ""
114
+ say "Directory structure created:"
115
+ say " app/#{root_directory}/"
116
+ say " ├── agents/"
117
+ say " │ ├── application_agent.rb"
118
+ say " │ └── AGENTS.md"
119
+ say " ├── text/"
120
+ say " │ └── embedders/"
121
+ say " │ ├── application_embedder.rb"
122
+ say " │ └── EMBEDDERS.md"
123
+ say " ├── tools/"
124
+ say " │ └── TOOLS.md"
125
+ say " └── workflows/"
126
+ say " └── WORKFLOWS.md"
127
+ say ""
128
+ say "Skill files (*.md) help AI coding assistants understand how to use this gem."
129
+ say ""
130
+ say "Namespace: #{root_namespace}::"
131
+ say ""
72
132
  say "Next steps:"
73
133
  say " 1. Run migrations: rails db:migrate"
74
134
  say " 2. Generate an agent: rails generate ruby_llm_agents:agent MyAgent query:required"
@@ -85,5 +145,17 @@ module RubyLlmAgents
85
145
  def db_migrate_path
86
146
  "db/migrate"
87
147
  end
148
+
149
+ def root_directory
150
+ @root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
151
+ end
152
+
153
+ def root_namespace
154
+ @root_namespace ||= options[:namespace] || camelize(root_directory)
155
+ end
156
+
157
+ def camelize(str)
158
+ str.split(/[-_]/).map(&:capitalize).join
159
+ end
88
160
  end
89
161
  end