rcrewai-rails 0.1.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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +222 -0
  4. data/Rakefile +6 -0
  5. data/app/controllers/rcrewai/rails/application_controller.rb +17 -0
  6. data/app/controllers/rcrewai/rails/crews_controller.rb +67 -0
  7. data/app/controllers/rcrewai/rails/executions_controller.rb +65 -0
  8. data/app/jobs/rcrewai/rails/crew_execution_job.rb +82 -0
  9. data/app/jobs/rcrewai/rails/task_execution_job.rb +63 -0
  10. data/app/models/rcrewai/rails/agent.rb +58 -0
  11. data/app/models/rcrewai/rails/application_record.rb +8 -0
  12. data/app/models/rcrewai/rails/crew.rb +65 -0
  13. data/app/models/rcrewai/rails/execution.rb +98 -0
  14. data/app/models/rcrewai/rails/execution_log.rb +18 -0
  15. data/app/models/rcrewai/rails/task.rb +69 -0
  16. data/app/models/rcrewai/rails/task_assignment.rb +12 -0
  17. data/app/models/rcrewai/rails/task_dependency.rb +42 -0
  18. data/app/views/layouts/rcrewai/rails/application.html.erb +37 -0
  19. data/app/views/rcrewai/rails/crews/index.html.erb +42 -0
  20. data/app/views/rcrewai/rails/crews/show.html.erb +95 -0
  21. data/app/views/rcrewai/rails/executions/show.html.erb +92 -0
  22. data/config/routes.rb +50 -0
  23. data/lib/generators/rcrew_a_i/rails/crew/crew_generator.rb +42 -0
  24. data/lib/generators/rcrew_a_i/rails/crew/templates/agent.rb.erb +45 -0
  25. data/lib/generators/rcrew_a_i/rails/crew/templates/crew.rb.erb +72 -0
  26. data/lib/generators/rcrew_a_i/rails/install/install_generator.rb +40 -0
  27. data/lib/generators/rcrew_a_i/rails/install/templates/create_rcrewai_tables.rb +113 -0
  28. data/lib/generators/rcrew_a_i/rails/install/templates/rcrewai.rb +53 -0
  29. data/lib/generators/rcrewai/rails/crew/crew_generator.rb +42 -0
  30. data/lib/generators/rcrewai/rails/crew/templates/agent.rb.erb +45 -0
  31. data/lib/generators/rcrewai/rails/crew/templates/crew.rb.erb +72 -0
  32. data/lib/generators/rcrewai/rails/install/install_generator.rb +40 -0
  33. data/lib/generators/rcrewai/rails/install/templates/create_rcrewai_tables.rb +113 -0
  34. data/lib/generators/rcrewai/rails/install/templates/rcrewai.rb +53 -0
  35. data/lib/rcrewai/rails/agent_builder.rb +123 -0
  36. data/lib/rcrewai/rails/configuration.rb +22 -0
  37. data/lib/rcrewai/rails/crew_builder.rb +112 -0
  38. data/lib/rcrewai/rails/engine.rb +38 -0
  39. data/lib/rcrewai/rails/tools/action_mailer_tool.rb +60 -0
  40. data/lib/rcrewai/rails/tools/active_record_tool.rb +67 -0
  41. data/lib/rcrewai/rails/tools/active_storage_tool.rb +122 -0
  42. data/lib/rcrewai/rails/tools/rails_cache_tool.rb +69 -0
  43. data/lib/rcrewai/rails/tools/rails_logger_tool.rb +57 -0
  44. data/lib/rcrewai/rails/version.rb +5 -0
  45. data/lib/rcrewai/rails.rb +31 -0
  46. data/lib/rcrewai-rails.rb +1 -0
  47. data/rcrewai-rails.gemspec +48 -0
  48. metadata +261 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d07d3c8b88c4bf9326dc8fc588cc58d0b02112d8c92d4d6eccc25a3da98d58a2
4
+ data.tar.gz: 1ce7c0563541bc473d6d1d3a092063d0ec86d7617d314fe733e444d37f761bfc
5
+ SHA512:
6
+ metadata.gz: 267b55d87d5ef72a12560a689459cc82cc93e99e55200b2c6128e492d4736f3911717c07b8616cb623baf8c595398084d9f57c0375e95deaf220b6f695c8c50a
7
+ data.tar.gz: 899ce8199ad7727e3bca13bf07362cf5184ba3ccc1431e35bd2564c57e91597c67db9744d9286c1caa115c9bd54cb2d7fb27fc29859d0b044d6bcd2fd6d6b034
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2024 RcrewAI Rails Contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # RcrewAI Rails
2
+
3
+ Rails engine for integrating RcrewAI into your Rails applications. Provides ActiveRecord persistence, background job integration, generators, and a web UI for managing AI crews and agents.
4
+
5
+ ## Features
6
+
7
+ - **ActiveRecord Integration**: Persist crews, agents, tasks, and executions in your database
8
+ - **Background Job Support**: Works with any ActiveJob adapter (Sidekiq, Resque, Delayed Job, etc.)
9
+ - **Rails Generators**: Quickly scaffold new crews and agents
10
+ - **Web UI**: Monitor and manage crews through a built-in interface
11
+ - **Rails-Specific Tools**: Pre-built tools for ActiveRecord, ActionMailer, Rails cache, and more
12
+ - **Configuration**: Flexible configuration through Rails initializers
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'rcrewai-rails'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ ```bash
25
+ $ bundle install
26
+ ```
27
+
28
+ Run the installation generator:
29
+
30
+ ```bash
31
+ $ rails generate rcrewai:rails:install
32
+ $ rails db:migrate
33
+ ```
34
+
35
+ This will:
36
+ - Create the necessary database migrations
37
+ - Add an initializer file for configuration
38
+ - Mount the engine routes
39
+
40
+ ## Configuration
41
+
42
+ Configure RcrewAI Rails in `config/initializers/rcrewai.rb`:
43
+
44
+ ```ruby
45
+ RcrewAI::Rails.configure do |config|
46
+ # ActiveJob queue for background processing
47
+ config.job_queue_name = "default"
48
+
49
+ # Enable/disable web UI
50
+ config.enable_web_ui = true
51
+
52
+ # Use async execution by default
53
+ config.async_execution = true
54
+
55
+ # Default LLM settings
56
+ config.default_llm_provider = "openai"
57
+ config.default_llm_model = "gpt-4"
58
+
59
+ # Logging
60
+ config.enable_logging = true
61
+ config.log_level = :info
62
+ end
63
+
64
+ # Configure the base RcrewAI gem
65
+ RcrewAI.configure do |config|
66
+ config.openai_api_key = ENV["OPENAI_API_KEY"]
67
+ # Add other LLM provider keys as needed
68
+ end
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ ### Creating a Crew with Generators
74
+
75
+ Generate a new crew with agents:
76
+
77
+ ```bash
78
+ $ rails generate rcrewai:rails:crew research_team sequential \
79
+ --agents researcher analyst writer \
80
+ --description "Research team for market analysis"
81
+ ```
82
+
83
+ This creates a crew class in `app/crews/research_team_crew.rb`.
84
+
85
+ ### Creating a Crew Programmatically
86
+
87
+ ```ruby
88
+ class ResearchCrew
89
+ include RcrewAI::Rails::CrewBuilder
90
+
91
+ crew_name "research_team"
92
+ crew_description "AI-powered research team"
93
+ process_type :sequential
94
+ memory_enabled true
95
+
96
+ def setup_agents
97
+ @researcher = create_agent("researcher",
98
+ role: "Senior Research Analyst",
99
+ goal: "Uncover insights and trends",
100
+ backstory: "Expert researcher with years of experience"
101
+ )
102
+
103
+ @writer = create_agent("writer",
104
+ role: "Content Writer",
105
+ goal: "Create compelling reports",
106
+ backstory: "Skilled writer specializing in technical content"
107
+ )
108
+ end
109
+
110
+ def setup_tasks
111
+ @research_task = create_task("Research latest AI trends",
112
+ expected_output: "Comprehensive research report",
113
+ position: 1
114
+ )
115
+ assign_agent_to_task(@researcher, @research_task)
116
+
117
+ @writing_task = create_task("Write executive summary",
118
+ expected_output: "2-page executive summary",
119
+ position: 2
120
+ )
121
+ assign_agent_to_task(@writer, @writing_task)
122
+ add_task_dependency(@writing_task, @research_task)
123
+ end
124
+ end
125
+
126
+ # Execute the crew
127
+ crew = ResearchCrew.new
128
+ execution = crew.execute(topic: "AI in Healthcare")
129
+ ```
130
+
131
+ ### Using Rails-Specific Tools
132
+
133
+ ```ruby
134
+ class DataAnalystAgent
135
+ include RcrewAI::Rails::AgentBuilder
136
+
137
+ agent_role "Data Analyst"
138
+ agent_goal "Analyze application data"
139
+
140
+ tools [
141
+ RcrewAI::Rails::Tools::ActiveRecordTool.new(
142
+ model_class: User,
143
+ allowed_methods: [:count, :where, :pluck]
144
+ ),
145
+ RcrewAI::Rails::Tools::RailsCacheTool.new,
146
+ RcrewAI::Rails::Tools::ActionMailerTool.new(
147
+ mailer_class: ReportMailer,
148
+ allowed_methods: [:send_report]
149
+ )
150
+ ]
151
+ end
152
+ ```
153
+
154
+ ### Monitoring Executions
155
+
156
+ Access the web UI at `/rcrewai` to:
157
+ - View all crews and their configurations
158
+ - Monitor execution status and logs
159
+ - Start new executions
160
+ - View execution history and results
161
+
162
+ ### Using with ActiveJob
163
+
164
+ Executions run through ActiveJob by default, using whatever adapter your Rails app is configured with:
165
+
166
+ ```ruby
167
+ # Async execution (default)
168
+ crew.execute_async(inputs)
169
+
170
+ # Sync execution
171
+ crew.execute_sync(inputs)
172
+
173
+ # Custom job options
174
+ CrewExecutionJob.set(wait: 5.minutes).perform_later(crew, inputs)
175
+ ```
176
+
177
+ ## Database Models
178
+
179
+ The gem provides these ActiveRecord models:
180
+
181
+ - `RcrewAI::Rails::Crew` - Crew configurations
182
+ - `RcrewAI::Rails::Agent` - Agent definitions
183
+ - `RcrewAI::Rails::Task` - Task definitions
184
+ - `RcrewAI::Rails::Execution` - Execution history
185
+ - `RcrewAI::Rails::ExecutionLog` - Detailed execution logs
186
+
187
+ ## API Endpoints
188
+
189
+ The engine provides JSON API endpoints:
190
+
191
+ ```
192
+ GET /rcrewai/api/v1/crews
193
+ GET /rcrewai/api/v1/crews/:id
194
+ POST /rcrewai/api/v1/crews/:id/execute
195
+ GET /rcrewai/api/v1/executions
196
+ GET /rcrewai/api/v1/executions/:id
197
+ GET /rcrewai/api/v1/executions/:id/status
198
+ GET /rcrewai/api/v1/executions/:id/logs
199
+ ```
200
+
201
+ ## Development
202
+
203
+ After checking out the repo, run:
204
+
205
+ ```bash
206
+ $ bundle install
207
+ $ bundle exec rspec
208
+ ```
209
+
210
+ To install this gem onto your local machine:
211
+
212
+ ```bash
213
+ $ bundle exec rake install
214
+ ```
215
+
216
+ ## Contributing
217
+
218
+ Bug reports and pull requests are welcome on GitHub.
219
+
220
+ ## License
221
+
222
+ The gem is available as open source under the terms of the MIT License.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,17 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class ApplicationController < ActionController::Base
4
+ protect_from_forgery with: :exception
5
+
6
+ before_action :check_web_ui_enabled
7
+
8
+ private
9
+
10
+ def check_web_ui_enabled
11
+ unless RcrewAI::Rails.config.enable_web_ui
12
+ render plain: "RcrewAI Web UI is disabled", status: :forbidden
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class CrewsController < ApplicationController
4
+ before_action :set_crew, only: [:show, :edit, :update, :destroy, :execute]
5
+
6
+ def index
7
+ @crews = Crew.includes(:agents, :tasks).page(params[:page])
8
+ end
9
+
10
+ def show
11
+ @recent_executions = @crew.executions.recent.limit(10)
12
+ @agents = @crew.agents
13
+ @tasks = @crew.tasks.ordered
14
+ end
15
+
16
+ def new
17
+ @crew = Crew.new
18
+ end
19
+
20
+ def create
21
+ @crew = Crew.new(crew_params)
22
+
23
+ if @crew.save
24
+ redirect_to @crew, notice: 'Crew was successfully created.'
25
+ else
26
+ render :new
27
+ end
28
+ end
29
+
30
+ def edit
31
+ end
32
+
33
+ def update
34
+ if @crew.update(crew_params)
35
+ redirect_to @crew, notice: 'Crew was successfully updated.'
36
+ else
37
+ render :edit
38
+ end
39
+ end
40
+
41
+ def destroy
42
+ @crew.destroy
43
+ redirect_to crews_url, notice: 'Crew was successfully destroyed.'
44
+ end
45
+
46
+ def execute
47
+ inputs = params[:inputs] || {}
48
+ execution = @crew.execute_async(inputs)
49
+
50
+ redirect_to execution_path(execution), notice: 'Crew execution started.'
51
+ end
52
+
53
+ private
54
+
55
+ def set_crew
56
+ @crew = Crew.find(params[:id])
57
+ end
58
+
59
+ def crew_params
60
+ params.require(:crew).permit(
61
+ :name, :description, :process_type, :verbose,
62
+ :memory_enabled, :cache_enabled, :max_rpm, :manager_llm, :active
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,65 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class ExecutionsController < ApplicationController
4
+ before_action :set_execution, only: [:show, :cancel, :logs]
5
+
6
+ def index
7
+ @executions = Execution.includes(:crew)
8
+ @executions = @executions.where(crew_id: params[:crew_id]) if params[:crew_id]
9
+ @executions = @executions.where(status: params[:status]) if params[:status]
10
+ @executions = @executions.recent.page(params[:page])
11
+ end
12
+
13
+ def show
14
+ @logs = @execution.execution_logs.recent.page(params[:page])
15
+
16
+ respond_to do |format|
17
+ format.html
18
+ format.json { render json: execution_json }
19
+ format.turbo_stream if request.headers["Turbo-Frame"]
20
+ end
21
+ end
22
+
23
+ def cancel
24
+ if @execution.running?
25
+ @execution.cancel!
26
+ redirect_to @execution, notice: 'Execution was cancelled.'
27
+ else
28
+ redirect_to @execution, alert: 'Execution cannot be cancelled.'
29
+ end
30
+ end
31
+
32
+ def logs
33
+ @logs = @execution.execution_logs
34
+ @logs = @logs.where(level: params[:level]) if params[:level]
35
+ @logs = @logs.recent.limit(params[:limit] || 100)
36
+
37
+ respond_to do |format|
38
+ format.json { render json: @logs }
39
+ format.turbo_stream
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def set_execution
46
+ @execution = Execution.find(params[:id])
47
+ end
48
+
49
+ def execution_json
50
+ {
51
+ id: @execution.id,
52
+ crew_name: @execution.crew.name,
53
+ status: @execution.status,
54
+ started_at: @execution.started_at,
55
+ completed_at: @execution.completed_at,
56
+ duration_seconds: @execution.duration_seconds,
57
+ inputs: @execution.inputs,
58
+ output: @execution.output,
59
+ error_message: @execution.error_message,
60
+ logs_count: @execution.execution_logs.count
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,82 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class CrewExecutionJob < ActiveJob::Base
4
+ queue_as { RcrewAI::Rails.config.job_queue_name }
5
+
6
+ retry_on StandardError, wait: :exponentially_longer, attempts: 3
7
+
8
+ def perform(crew, inputs = {})
9
+ execution = crew.executions.create!(
10
+ status: "pending",
11
+ inputs: inputs
12
+ )
13
+
14
+ begin
15
+ execution.start!
16
+ execution.log("info", "Starting crew execution", { crew_id: crew.id })
17
+
18
+ # Convert Rails models to RcrewAI objects
19
+ rcrew = crew.to_rcrew
20
+
21
+ # Execute the crew with logging
22
+ result = execute_with_logging(rcrew, inputs, execution)
23
+
24
+ execution.complete!(result)
25
+ execution.log("info", "Crew execution completed successfully", { result: result })
26
+
27
+ # Trigger callbacks if configured
28
+ notify_completion(crew, execution, result)
29
+
30
+ result
31
+ rescue => e
32
+ execution.fail!(e)
33
+ execution.log("error", "Crew execution failed", {
34
+ error: e.message,
35
+ backtrace: e.backtrace.first(5)
36
+ })
37
+
38
+ # Re-raise for ActiveJob retry mechanism
39
+ raise
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def execute_with_logging(rcrew, inputs, execution)
46
+ # Set up logging callbacks
47
+ rcrew.before_task do |task|
48
+ execution.log("info", "Starting task: #{task.description}")
49
+ end
50
+
51
+ rcrew.after_task do |task, output|
52
+ execution.log("info", "Completed task: #{task.description}", { output: output })
53
+ end
54
+
55
+ # Execute the crew
56
+ rcrew.kickoff(inputs)
57
+ end
58
+
59
+ def notify_completion(crew, execution, result)
60
+ # Send notifications if configured
61
+ if crew.notification_webhook_url.present?
62
+ NotificationJob.perform_later(
63
+ crew.notification_webhook_url,
64
+ {
65
+ crew_id: crew.id,
66
+ execution_id: execution.id,
67
+ status: "completed",
68
+ result: result
69
+ }
70
+ )
71
+ end
72
+
73
+ # Trigger Rails events
74
+ ActiveSupport::Notifications.instrument("crew_execution.completed", {
75
+ crew: crew,
76
+ execution: execution,
77
+ result: result
78
+ })
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,63 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class TaskExecutionJob < ActiveJob::Base
4
+ queue_as { RcrewAI::Rails.config.job_queue_name }
5
+
6
+ retry_on StandardError, wait: 5.seconds, attempts: 3
7
+
8
+ def perform(task, agent, inputs = {})
9
+ execution_log = {
10
+ task_id: task.id,
11
+ agent_id: agent.id,
12
+ started_at: Time.current
13
+ }
14
+
15
+ begin
16
+ # Convert to RcrewAI objects
17
+ rcrew_task = task.to_rcrew_task
18
+ rcrew_agent = agent.to_rcrew_agent
19
+
20
+ # Execute the task
21
+ result = rcrew_agent.execute_task(rcrew_task, context: inputs)
22
+
23
+ execution_log[:completed_at] = Time.current
24
+ execution_log[:status] = "completed"
25
+ execution_log[:result] = result
26
+
27
+ # Save result if configured
28
+ if task.output_file.present?
29
+ save_output_to_file(task.output_file, result)
30
+ end
31
+
32
+ # Log success
33
+ ::Rails.logger.info "Task #{task.id} completed successfully by agent #{agent.id}"
34
+
35
+ result
36
+ rescue => e
37
+ execution_log[:completed_at] = Time.current
38
+ execution_log[:status] = "failed"
39
+ execution_log[:error] = e.message
40
+
41
+ ::Rails.logger.error "Task #{task.id} failed: #{e.message}"
42
+
43
+ raise
44
+ ensure
45
+ # Could save execution log to database if needed
46
+ log_task_execution(execution_log)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def save_output_to_file(filename, content)
53
+ output_path = ::Rails.root.join("tmp", "rcrewai_outputs", filename)
54
+ FileUtils.mkdir_p(File.dirname(output_path))
55
+ File.write(output_path, content)
56
+ end
57
+
58
+ def log_task_execution(log_data)
59
+ ActiveSupport::Notifications.instrument("task_execution.rcrewai", log_data)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,58 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class Agent < ApplicationRecord
4
+ self.table_name = "rcrewai_agents"
5
+
6
+ belongs_to :crew
7
+ has_many :task_assignments, dependent: :destroy
8
+ has_many :tasks, through: :task_assignments
9
+
10
+ validates :name, presence: true
11
+ validates :role, presence: true
12
+
13
+ serialize :tools, coder: JSON, type: Array
14
+ serialize :llm_config, coder: JSON
15
+
16
+ scope :active, -> { where(active: true) }
17
+
18
+ def to_rcrew_agent
19
+ RCrewAI::Agent.new(
20
+ role: role,
21
+ goal: goal,
22
+ backstory: backstory,
23
+ memory: memory_enabled,
24
+ verbose: verbose,
25
+ allow_delegation: allow_delegation,
26
+ tools: instantiated_tools,
27
+ max_iter: max_iterations,
28
+ max_rpm: max_rpm,
29
+ llm: llm_config
30
+ )
31
+ end
32
+
33
+ def instantiated_tools
34
+ return [] if tools.blank?
35
+
36
+ tools.map do |tool_config|
37
+ tool_class = tool_config["class"].constantize
38
+ tool_params = tool_config["params"] || {}
39
+ tool_class.new(**tool_params.symbolize_keys)
40
+ end
41
+ end
42
+
43
+ def add_tool(tool_class, params = {})
44
+ self.tools ||= []
45
+ self.tools << {
46
+ "class" => tool_class.to_s,
47
+ "params" => params
48
+ }
49
+ save
50
+ end
51
+
52
+ def remove_tool(tool_class)
53
+ self.tools = tools.reject { |t| t["class"] == tool_class.to_s }
54
+ save
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,8 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ self.table_name_prefix = "rcrewai_"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,65 @@
1
+ module RcrewAI
2
+ module Rails
3
+ class Crew < ApplicationRecord
4
+ self.table_name = "rcrewai_crews"
5
+
6
+ has_many :agents, dependent: :destroy
7
+ has_many :tasks, dependent: :destroy
8
+ has_many :executions, dependent: :destroy
9
+
10
+ validates :name, presence: true
11
+ validates :process_type, inclusion: { in: %w[sequential hierarchical] }
12
+
13
+ serialize :config, coder: JSON
14
+ serialize :memory, coder: JSON
15
+
16
+ scope :active, -> { where(active: true) }
17
+ scope :with_agents, -> { includes(:agents) }
18
+
19
+ def to_rcrew
20
+ crew = RCrewAI::Crew.new(
21
+ name: name,
22
+ description: description,
23
+ process: process_type.to_sym,
24
+ verbose: verbose,
25
+ memory: memory_enabled,
26
+ cache: cache_enabled,
27
+ max_rpm: max_rpm,
28
+ manager_llm: manager_llm
29
+ )
30
+
31
+ agents.each do |agent|
32
+ crew.add_agent(agent.to_rcrew_agent)
33
+ end
34
+
35
+ tasks.each do |task|
36
+ crew.add_task(task.to_rcrew_task)
37
+ end
38
+
39
+ crew
40
+ end
41
+
42
+ def execute_async(inputs = {})
43
+ CrewExecutionJob.perform_later(self, inputs)
44
+ end
45
+
46
+ def execute_sync(inputs = {})
47
+ CrewExecutionJob.perform_now(self, inputs)
48
+ end
49
+
50
+ def last_execution
51
+ executions.order(created_at: :desc).first
52
+ end
53
+
54
+ def execution_stats
55
+ {
56
+ total: executions.count,
57
+ successful: executions.successful.count,
58
+ failed: executions.failed.count,
59
+ pending: executions.pending.count,
60
+ average_duration: executions.successful.average(:duration_seconds)
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end