rcrewai-rails 0.3.1 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +96 -0
- data/app/jobs/rcrewai/rails/crew_execution_job.rb +3 -2
- data/app/models/rcrewai/rails/active_record_state_store.rb +24 -0
- data/app/models/rcrewai/rails/agent.rb +21 -1
- data/app/models/rcrewai/rails/crew.rb +67 -1
- data/app/models/rcrewai/rails/flow_run.rb +41 -0
- data/app/models/rcrewai/rails/flow_state.rb +11 -0
- data/app/models/rcrewai/rails/knowledge_source.rb +27 -0
- data/app/models/rcrewai/rails/task.rb +39 -1
- data/db/migrate/002_add_config_to_rcrewai_agents.rb +9 -0
- data/db/migrate/003_add_output_processing_to_rcrewai_tasks.rb +13 -0
- data/db/migrate/004_add_lifecycle_to_rcrewai_crews.rb +10 -0
- data/db/migrate/005_add_batch_id_to_rcrewai_executions.rb +6 -0
- data/db/migrate/006_create_rcrewai_knowledge_sources.rb +11 -0
- data/db/migrate/007_create_rcrewai_flows.rb +24 -0
- data/lib/generators/rcrewai/rails/install/templates/create_rcrewai_tables.rb +50 -0
- data/lib/rcrewai/rails/version.rb +1 -1
- data/rcrewai-rails.gemspec +3 -3
- metadata +15 -5
- data/docs/superpowers/specs/2026-06-16-github-pages-landing-design.md +0 -61
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3002ce8deaeb0a940a8d3636d3e88e7c3209a7198682f8210b2f93e46998c2c6
|
|
4
|
+
data.tar.gz: b37ea3a73e1d4a9d040293cf017d2790fd200745971c487a23c353cf1269c513
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e085f8cb656d8ff666a5796801268371ffcbbf9c80348b42ce82586e4d43cd91c419e1d32eae570eee3b75e757030a94732a584b88ccd2e51cef136c4f5f4933
|
|
7
|
+
data.tar.gz: 16fdc1b89c8955bdf57e74e43354965c0ca820ee8b18f254bdf1580e20db4d5fdc5efcaa08d468ed129fb06c777c94c5a4071f883200cfaa47481a5688a1173c
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.5.1] - 2026-07-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Exclude internal `docs/superpowers/` design and plan documents from the packaged
|
|
14
|
+
gem (they were swept in alongside the intended `docs/index.html`). No code
|
|
15
|
+
changes; first published build carrying the 0.4/0.5 parity work.
|
|
16
|
+
|
|
17
|
+
## [0.5.0] - 2026-07-06
|
|
18
|
+
|
|
19
|
+
Adds the second CrewAI pillar — **Flows** — to the Rails engine as a persistence
|
|
20
|
+
layer, completing the rcrewai 0.4/0.5 feature-parity effort. Additive; existing
|
|
21
|
+
crews, agents, and tasks are unaffected.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- Flows persistence: `RcrewAI::Rails::ActiveRecordStateStore` backs rcrewai Flow
|
|
25
|
+
state with a `rcrewai_flow_states` table so flows resume from the DB
|
|
26
|
+
(`flow.restore(state_id)`), and `RcrewAI::Rails::FlowRun` records each kickoff
|
|
27
|
+
(status, state id, inputs, result, timing) via `FlowRun.execute(FlowClass,
|
|
28
|
+
inputs:)`. Flow subclasses are still defined in the host app; the engine adds
|
|
29
|
+
the persistence layer (#13).
|
|
30
|
+
|
|
31
|
+
## [0.4.0] - 2026-07-06
|
|
32
|
+
|
|
33
|
+
Feature-parity release: brings the rcrewai 0.4/0.5 agent, task, and crew
|
|
34
|
+
capabilities to the Rails engine. Requires `rcrewai ~> 0.5`. All additive —
|
|
35
|
+
existing agents, tasks, and crews build unchanged.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
- Forward rcrewai 0.5.0 agent options through `RcrewAI::Rails::Agent#to_rcrew_agent`:
|
|
39
|
+
`reasoning`, `max_reasoning_attempts`, `respect_context_window`, and per-agent
|
|
40
|
+
`llm` (from the `llm_config` column). Also fixes a latent gap where the existing
|
|
41
|
+
`max_rpm` and `llm_config` columns were never passed to the core agent. New
|
|
42
|
+
columns are added via a host migration, the install generator, and the test
|
|
43
|
+
schema; all options are emitted only when set, so existing agents are
|
|
44
|
+
unaffected (#6).
|
|
45
|
+
- Forward rcrewai 0.4/0.5 task output-processing options through
|
|
46
|
+
`RcrewAI::Rails::Task#to_rcrew_task`: `output_schema` (structured output),
|
|
47
|
+
`guardrail` (resolved from `guardrail_class` + `guardrail_method_name`),
|
|
48
|
+
`guardrail_max_retries`, `output_file`, `create_directory`, `markdown`, and
|
|
49
|
+
multimodal `attachments`. Options are emitted only when meaningfully set, so
|
|
50
|
+
existing tasks construct unchanged (#7).
|
|
51
|
+
- Forward rcrewai 0.5.0 crew options through `RcrewAI::Rails::Crew#to_rcrew`:
|
|
52
|
+
`planning` / `planning_llm`, and `before_kickoff` / `after_kickoff` lifecycle
|
|
53
|
+
hooks (resolved from `*_class` + `*_method` columns). Options are emitted and
|
|
54
|
+
hooks registered only when configured, so existing crews build unchanged (#9).
|
|
55
|
+
- Batch crew execution (`kickoff_for_each` parity): `Crew#execute_batch_sync` /
|
|
56
|
+
`#execute_batch_async` run the crew once per input set, creating one `Execution`
|
|
57
|
+
per input grouped by a shared `batch_id` (new nullable column). `#batch_executions`
|
|
58
|
+
returns a batch's runs in order. Existing single-run executions are unaffected (#10).
|
|
59
|
+
- Knowledge (RAG) sources: a polymorphic `RcrewAI::Rails::KnowledgeSource`
|
|
60
|
+
(owned by an Agent or a Crew) persists `{source_type, value}` for string, file,
|
|
61
|
+
PDF, CSV, and URL sources. `Agent#to_rcrew_agent` / `Crew#to_rcrew` forward
|
|
62
|
+
active sources as `knowledge_sources:`; the core embeds them lazily at
|
|
63
|
+
execution. Emitted only when sources exist, so existing agents/crews are
|
|
64
|
+
unaffected (#11).
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
- Require `rcrewai ~> 0.5` (was `~> 0.3`) (#6).
|
|
68
|
+
|
|
69
|
+
## [0.3.1] - 2026-06-16
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
- GitHub Pages landing + documentation site, served from `/docs` at
|
|
73
|
+
https://gkosmo.github.io/rcrewai-rails/ (#3).
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
- Zeitwerk eager-load failure caused by `lib/` being on the autoload paths (#2).
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
- Point the gemspec `documentation_uri` at the new GitHub Pages site (#3).
|
|
80
|
+
|
|
81
|
+
## [0.3.0] - 2026-05-12
|
|
82
|
+
|
|
83
|
+
### Added
|
|
84
|
+
- Adapt the engine to rcrewai 0.3.
|
|
85
|
+
- Test suite (RSpec) covering models, jobs, builders, and tools.
|
|
86
|
+
- GitHub Actions CI workflow.
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
- Rename generators from `rcrew_a_i` to `rcrewai` namespacing.
|
|
90
|
+
|
|
91
|
+
[Unreleased]: https://github.com/gkosmo/rcrewai-rails/compare/v0.5.1...HEAD
|
|
92
|
+
[0.5.1]: https://github.com/gkosmo/rcrewai-rails/compare/v0.5.0...v0.5.1
|
|
93
|
+
[0.5.0]: https://github.com/gkosmo/rcrewai-rails/compare/v0.4.0...v0.5.0
|
|
94
|
+
[0.4.0]: https://github.com/gkosmo/rcrewai-rails/compare/v0.3.1...v0.4.0
|
|
95
|
+
[0.3.1]: https://github.com/gkosmo/rcrewai-rails/compare/v0.3.0...v0.3.1
|
|
96
|
+
[0.3.0]: https://github.com/gkosmo/rcrewai-rails/releases/tag/v0.3.0
|
|
@@ -5,10 +5,11 @@ module RcrewAI
|
|
|
5
5
|
|
|
6
6
|
retry_on StandardError, wait: :exponentially_longer, attempts: 3
|
|
7
7
|
|
|
8
|
-
def perform(crew, inputs = {})
|
|
8
|
+
def perform(crew, inputs = {}, batch_id: nil)
|
|
9
9
|
execution = crew.executions.create!(
|
|
10
10
|
status: "pending",
|
|
11
|
-
inputs: inputs
|
|
11
|
+
inputs: inputs,
|
|
12
|
+
batch_id: batch_id
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
begin
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module RcrewAI
|
|
2
|
+
module Rails
|
|
3
|
+
# Persists rcrewai Flow state to the DB. Implements the core state-store
|
|
4
|
+
# contract: save(id, hash) / load(id) => hash or nil. Pass an instance as
|
|
5
|
+
# +state_store:+ when constructing a Flow.
|
|
6
|
+
#
|
|
7
|
+
# State is stored as JSON (see FlowState), so values must be JSON-native —
|
|
8
|
+
# the same constraint as the core FileStateStore. A single flow run persists
|
|
9
|
+
# from one process, so saves are effectively serial; a genuinely concurrent
|
|
10
|
+
# first-write for the same state_id would hit the unique index and raise
|
|
11
|
+
# ActiveRecord::RecordNotUnique (fail-loud, by design).
|
|
12
|
+
class ActiveRecordStateStore
|
|
13
|
+
def save(id, hash)
|
|
14
|
+
record = FlowState.find_or_initialize_by(state_id: id)
|
|
15
|
+
record.data = hash
|
|
16
|
+
record.save!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def load(id)
|
|
20
|
+
FlowState.find_by(state_id: id)&.data
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -6,6 +6,7 @@ module RcrewAI
|
|
|
6
6
|
belongs_to :crew
|
|
7
7
|
has_many :tasks, dependent: :nullify
|
|
8
8
|
has_many :tools, class_name: 'RcrewAI::Rails::Tool', dependent: :destroy
|
|
9
|
+
has_many :knowledge_sources, as: :owner, class_name: "RcrewAI::Rails::KnowledgeSource", dependent: :destroy
|
|
9
10
|
|
|
10
11
|
validates :name, presence: true
|
|
11
12
|
validates :role, presence: true
|
|
@@ -24,10 +25,29 @@ module RcrewAI
|
|
|
24
25
|
verbose: verbose,
|
|
25
26
|
allow_delegation: allow_delegation,
|
|
26
27
|
tools: instantiated_tools,
|
|
27
|
-
max_iterations: max_iterations
|
|
28
|
+
max_iterations: max_iterations,
|
|
29
|
+
**agent_options
|
|
28
30
|
)
|
|
29
31
|
end
|
|
30
32
|
|
|
33
|
+
# rcrewai 0.5.0 agent options. Only emit a key when it is meaningfully
|
|
34
|
+
# set, so an all-default record constructs exactly as it did pre-0.5.
|
|
35
|
+
def agent_options
|
|
36
|
+
opts = {}
|
|
37
|
+
opts[:max_rpm] = max_rpm if max_rpm.present? && max_rpm.positive?
|
|
38
|
+
opts[:reasoning] = reasoning if reasoning
|
|
39
|
+
opts[:max_reasoning_attempts] = max_reasoning_attempts if reasoning && max_reasoning_attempts
|
|
40
|
+
opts[:respect_context_window] = respect_context_window if respect_context_window
|
|
41
|
+
opts[:llm] = llm_config.symbolize_keys if llm_config.present?
|
|
42
|
+
sources = rcrew_knowledge_sources
|
|
43
|
+
opts[:knowledge_sources] = sources if sources.any?
|
|
44
|
+
opts
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def rcrew_knowledge_sources
|
|
48
|
+
knowledge_sources.active.map(&:to_rcrew_source)
|
|
49
|
+
end
|
|
50
|
+
|
|
31
51
|
def instantiated_tools
|
|
32
52
|
return [] if tools.blank?
|
|
33
53
|
|
|
@@ -6,6 +6,7 @@ module RcrewAI
|
|
|
6
6
|
has_many :agents, dependent: :destroy
|
|
7
7
|
has_many :tasks, dependent: :destroy
|
|
8
8
|
has_many :executions, dependent: :destroy
|
|
9
|
+
has_many :knowledge_sources, as: :owner, class_name: "RcrewAI::Rails::KnowledgeSource", dependent: :destroy
|
|
9
10
|
|
|
10
11
|
validates :name, presence: true
|
|
11
12
|
validates :process_type, inclusion: { in: %w[sequential hierarchical] }
|
|
@@ -20,7 +21,8 @@ module RcrewAI
|
|
|
20
21
|
crew = RCrewAI::Crew.new(
|
|
21
22
|
name,
|
|
22
23
|
process: process_type.to_sym,
|
|
23
|
-
verbose: verbose
|
|
24
|
+
verbose: verbose,
|
|
25
|
+
**crew_planning_options
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
agents.each do |agent|
|
|
@@ -31,9 +33,25 @@ module RcrewAI
|
|
|
31
33
|
crew.add_task(task.to_rcrew_task)
|
|
32
34
|
end
|
|
33
35
|
|
|
36
|
+
register_kickoff_hooks(crew)
|
|
34
37
|
crew
|
|
35
38
|
end
|
|
36
39
|
|
|
40
|
+
# rcrewai 0.5.0 planning options. Emit a key only when meaningfully set, so
|
|
41
|
+
# an all-default crew constructs exactly as it did before.
|
|
42
|
+
def crew_planning_options
|
|
43
|
+
opts = {}
|
|
44
|
+
opts[:planning] = planning if planning
|
|
45
|
+
opts[:planning_llm] = planning_llm.to_sym if planning_llm.present?
|
|
46
|
+
sources = rcrew_knowledge_sources
|
|
47
|
+
opts[:knowledge_sources] = sources if sources.any?
|
|
48
|
+
opts
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def rcrew_knowledge_sources
|
|
52
|
+
knowledge_sources.active.map(&:to_rcrew_source)
|
|
53
|
+
end
|
|
54
|
+
|
|
37
55
|
def execute_async(inputs = {})
|
|
38
56
|
CrewExecutionJob.perform_later(self, inputs)
|
|
39
57
|
end
|
|
@@ -42,6 +60,26 @@ module RcrewAI
|
|
|
42
60
|
CrewExecutionJob.perform_now(self, inputs)
|
|
43
61
|
end
|
|
44
62
|
|
|
63
|
+
def execute_batch_async(inputs_list)
|
|
64
|
+
batch_id = SecureRandom.uuid
|
|
65
|
+
normalize_batch_inputs(inputs_list).each do |inputs|
|
|
66
|
+
CrewExecutionJob.perform_later(self, inputs, batch_id: batch_id)
|
|
67
|
+
end
|
|
68
|
+
batch_id
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def execute_batch_sync(inputs_list)
|
|
72
|
+
batch_id = SecureRandom.uuid
|
|
73
|
+
normalize_batch_inputs(inputs_list).each do |inputs|
|
|
74
|
+
CrewExecutionJob.perform_now(self, inputs, batch_id: batch_id)
|
|
75
|
+
end
|
|
76
|
+
{ batch_id: batch_id, executions: batch_executions(batch_id).to_a }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def batch_executions(batch_id)
|
|
80
|
+
executions.where(batch_id: batch_id).order(:created_at, :id)
|
|
81
|
+
end
|
|
82
|
+
|
|
45
83
|
def last_execution
|
|
46
84
|
executions.order(created_at: :desc).first
|
|
47
85
|
end
|
|
@@ -55,6 +93,34 @@ module RcrewAI
|
|
|
55
93
|
average_duration: executions.successful.average(:duration_seconds)
|
|
56
94
|
}
|
|
57
95
|
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
# Wraps a single inputs hash into a one-element array; leaves an array of
|
|
100
|
+
# hashes as-is. Avoids Array()'s hash-destructuring (Array({a:1}) => [[:a,1]]).
|
|
101
|
+
def normalize_batch_inputs(inputs_list)
|
|
102
|
+
inputs_list.is_a?(Hash) ? [inputs_list] : Array(inputs_list)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Registers before/after kickoff hooks resolved from *_class + *_method
|
|
106
|
+
# columns, mirroring the guardrail/callback pattern. No-op when unconfigured.
|
|
107
|
+
def register_kickoff_hooks(crew)
|
|
108
|
+
if (before = hook_callable(before_kickoff_class, before_kickoff_method))
|
|
109
|
+
crew.before_kickoff { |inputs| before.call(inputs) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if (after = hook_callable(after_kickoff_class, after_kickoff_method))
|
|
113
|
+
crew.after_kickoff { |result| after.call(result) }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Resolves a *_class + *_method pair to a callable; nil when either is blank.
|
|
118
|
+
def hook_callable(class_name, method_name)
|
|
119
|
+
return nil unless class_name.present? && method_name.present?
|
|
120
|
+
|
|
121
|
+
klass = class_name.constantize
|
|
122
|
+
->(arg) { klass.new.send(method_name, arg) }
|
|
123
|
+
end
|
|
58
124
|
end
|
|
59
125
|
end
|
|
60
126
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module RcrewAI
|
|
2
|
+
module Rails
|
|
3
|
+
class FlowRun < ApplicationRecord
|
|
4
|
+
self.table_name = "rcrewai_flow_runs"
|
|
5
|
+
|
|
6
|
+
serialize :inputs, coder: JSON
|
|
7
|
+
serialize :result, coder: JSON
|
|
8
|
+
|
|
9
|
+
validates :flow_class, presence: true
|
|
10
|
+
validates :status, inclusion: { in: %w[pending running completed failed] }
|
|
11
|
+
|
|
12
|
+
scope :successful, -> { where(status: "completed") }
|
|
13
|
+
scope :failed, -> { where(status: "failed") }
|
|
14
|
+
|
|
15
|
+
# Runs a Flow subclass (a Class or its String name) with an AR-backed state
|
|
16
|
+
# store, wrapped in a run record. Returns the run. Re-raises on failure
|
|
17
|
+
# after recording it.
|
|
18
|
+
def self.execute(flow_class, inputs: {})
|
|
19
|
+
klass = flow_class.is_a?(String) ? flow_class.constantize : flow_class
|
|
20
|
+
run = create!(flow_class: klass.name, status: "pending", inputs: inputs)
|
|
21
|
+
run.run!(klass, inputs)
|
|
22
|
+
run
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def run!(klass, inputs)
|
|
26
|
+
update!(status: "running", started_at: Time.current)
|
|
27
|
+
flow = klass.new(state_store: ActiveRecordStateStore.new)
|
|
28
|
+
state = flow.kickoff(inputs: inputs)
|
|
29
|
+
update!(
|
|
30
|
+
status: "completed",
|
|
31
|
+
state_id: state.id,
|
|
32
|
+
result: state.to_h,
|
|
33
|
+
completed_at: Time.current
|
|
34
|
+
)
|
|
35
|
+
rescue => e
|
|
36
|
+
update!(status: "failed", error_message: e.message, completed_at: Time.current)
|
|
37
|
+
raise
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module RcrewAI
|
|
2
|
+
module Rails
|
|
3
|
+
class KnowledgeSource < ApplicationRecord
|
|
4
|
+
self.table_name = "rcrewai_knowledge_sources"
|
|
5
|
+
|
|
6
|
+
TYPE_MAP = {
|
|
7
|
+
"string" => RCrewAI::Knowledge::StringSource,
|
|
8
|
+
"file" => RCrewAI::Knowledge::FileSource,
|
|
9
|
+
"pdf" => RCrewAI::Knowledge::PdfSource,
|
|
10
|
+
"csv" => RCrewAI::Knowledge::CsvSource,
|
|
11
|
+
"url" => RCrewAI::Knowledge::UrlSource,
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
belongs_to :owner, polymorphic: true
|
|
15
|
+
|
|
16
|
+
validates :source_type, inclusion: { in: TYPE_MAP.keys }
|
|
17
|
+
validates :value, presence: true
|
|
18
|
+
|
|
19
|
+
scope :active, -> { where(active: true) }
|
|
20
|
+
|
|
21
|
+
# Maps this row to the matching core Source object.
|
|
22
|
+
def to_rcrew_source
|
|
23
|
+
TYPE_MAP.fetch(source_type).new(value)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -15,6 +15,8 @@ module RcrewAI
|
|
|
15
15
|
serialize :output_json, coder: JSON
|
|
16
16
|
serialize :output_pydantic, coder: JSON
|
|
17
17
|
serialize :tools, coder: JSON, type: Array
|
|
18
|
+
serialize :output_schema, coder: JSON
|
|
19
|
+
serialize :attachments, coder: JSON, type: Array
|
|
18
20
|
|
|
19
21
|
scope :ordered, -> { order(:order_index) }
|
|
20
22
|
|
|
@@ -27,10 +29,28 @@ module RcrewAI
|
|
|
27
29
|
context: context,
|
|
28
30
|
async: async_execution,
|
|
29
31
|
tools: instantiated_tools,
|
|
30
|
-
callback: callback_method
|
|
32
|
+
callback: callback_method,
|
|
33
|
+
**task_output_options
|
|
31
34
|
)
|
|
32
35
|
end
|
|
33
36
|
|
|
37
|
+
# rcrewai 0.4/0.5 task output-processing options. Only emit a key when it
|
|
38
|
+
# is meaningfully set, so an all-default record constructs exactly as it
|
|
39
|
+
# did before these options existed.
|
|
40
|
+
def task_output_options
|
|
41
|
+
opts = {}
|
|
42
|
+
opts[:output_schema] = output_schema.deep_symbolize_keys if output_schema.present?
|
|
43
|
+
opts[:guardrail] = guardrail_callable if guardrail_callable
|
|
44
|
+
opts[:guardrail_max_retries] = guardrail_max_retries if guardrail_callable && guardrail_max_retries
|
|
45
|
+
opts[:output_file] = output_file if output_file.present?
|
|
46
|
+
# Core defaults create_directory to true; only forward when explicitly
|
|
47
|
+
# disabled, so an all-default record still emits nothing.
|
|
48
|
+
opts[:create_directory] = false if create_directory == false
|
|
49
|
+
opts[:markdown] = markdown if markdown
|
|
50
|
+
opts[:attachments] = normalized_attachments if attachments.present?
|
|
51
|
+
opts
|
|
52
|
+
end
|
|
53
|
+
|
|
34
54
|
|
|
35
55
|
def instantiated_tools
|
|
36
56
|
return [] if tools.blank?
|
|
@@ -65,6 +85,24 @@ module RcrewAI
|
|
|
65
85
|
klass = callback_class.constantize
|
|
66
86
|
->(output) { klass.new.send(callback_method_name, output) }
|
|
67
87
|
end
|
|
88
|
+
|
|
89
|
+
# Resolves guardrail_class + guardrail_method_name to a callable returning
|
|
90
|
+
# the core [ok, value_or_error] contract. Mirrors callback_method. nil when
|
|
91
|
+
# not configured.
|
|
92
|
+
def guardrail_callable
|
|
93
|
+
return nil unless guardrail_class.present? && guardrail_method_name.present?
|
|
94
|
+
|
|
95
|
+
klass = guardrail_class.constantize
|
|
96
|
+
->(output) { klass.new.send(guardrail_method_name, output) }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Symbolizes each attachment hash so { "type" => "image", "url" => ... }
|
|
100
|
+
# becomes { type: :image, url: ... } as the core Multimodal builder expects.
|
|
101
|
+
def normalized_attachments
|
|
102
|
+
attachments.map do |att|
|
|
103
|
+
att.symbolize_keys.tap { |h| h[:type] = h[:type].to_sym if h[:type] }
|
|
104
|
+
end
|
|
105
|
+
end
|
|
68
106
|
end
|
|
69
107
|
end
|
|
70
108
|
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class AddConfigToRcrewaiAgents < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
# max_rpm and llm_config already exist on rcrewai_agents from the
|
|
4
|
+
# original create table; only the 0.5.0 additions are new.
|
|
5
|
+
add_column :rcrewai_agents, :reasoning, :boolean, default: false, null: false
|
|
6
|
+
add_column :rcrewai_agents, :max_reasoning_attempts, :integer, default: 3
|
|
7
|
+
add_column :rcrewai_agents, :respect_context_window, :boolean, default: false, null: false
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddOutputProcessingToRcrewaiTasks < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
# output_file already exists on rcrewai_tasks from the original create
|
|
4
|
+
# table; only the new 0.4/0.5 output-processing options are added here.
|
|
5
|
+
add_column :rcrewai_tasks, :output_schema, :text
|
|
6
|
+
add_column :rcrewai_tasks, :guardrail_class, :string
|
|
7
|
+
add_column :rcrewai_tasks, :guardrail_method_name, :string
|
|
8
|
+
add_column :rcrewai_tasks, :guardrail_max_retries, :integer, default: 3
|
|
9
|
+
add_column :rcrewai_tasks, :create_directory, :boolean, default: true
|
|
10
|
+
add_column :rcrewai_tasks, :markdown, :boolean, default: false
|
|
11
|
+
add_column :rcrewai_tasks, :attachments, :text
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class AddLifecycleToRcrewaiCrews < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :rcrewai_crews, :planning, :boolean, default: false, null: false
|
|
4
|
+
add_column :rcrewai_crews, :planning_llm, :string
|
|
5
|
+
add_column :rcrewai_crews, :before_kickoff_class, :string
|
|
6
|
+
add_column :rcrewai_crews, :before_kickoff_method, :string
|
|
7
|
+
add_column :rcrewai_crews, :after_kickoff_class, :string
|
|
8
|
+
add_column :rcrewai_crews, :after_kickoff_method, :string
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class CreateRcrewaiKnowledgeSources < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :rcrewai_knowledge_sources do |t|
|
|
4
|
+
t.references :owner, polymorphic: true, null: false
|
|
5
|
+
t.string :source_type, null: false
|
|
6
|
+
t.text :value, null: false
|
|
7
|
+
t.boolean :active, default: true, null: false
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class CreateRcrewaiFlows < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :rcrewai_flow_states do |t|
|
|
4
|
+
t.string :state_id, null: false
|
|
5
|
+
t.text :data, null: false
|
|
6
|
+
t.timestamps
|
|
7
|
+
end
|
|
8
|
+
add_index :rcrewai_flow_states, :state_id, unique: true
|
|
9
|
+
|
|
10
|
+
create_table :rcrewai_flow_runs do |t|
|
|
11
|
+
t.string :flow_class, null: false
|
|
12
|
+
t.string :state_id
|
|
13
|
+
t.string :status, null: false
|
|
14
|
+
t.text :inputs
|
|
15
|
+
t.text :result
|
|
16
|
+
t.string :error_message
|
|
17
|
+
t.datetime :started_at
|
|
18
|
+
t.datetime :completed_at
|
|
19
|
+
t.timestamps
|
|
20
|
+
end
|
|
21
|
+
add_index :rcrewai_flow_runs, :status
|
|
22
|
+
add_index :rcrewai_flow_runs, :state_id
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -9,6 +9,12 @@ class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
|
|
|
9
9
|
t.boolean :cache_enabled, default: false
|
|
10
10
|
t.integer :max_rpm
|
|
11
11
|
t.string :manager_llm
|
|
12
|
+
t.boolean :planning, default: false, null: false
|
|
13
|
+
t.string :planning_llm
|
|
14
|
+
t.string :before_kickoff_class
|
|
15
|
+
t.string :before_kickoff_method
|
|
16
|
+
t.string :after_kickoff_class
|
|
17
|
+
t.string :after_kickoff_method
|
|
12
18
|
t.text :config
|
|
13
19
|
t.text :memory
|
|
14
20
|
t.boolean :active, default: true
|
|
@@ -31,6 +37,9 @@ class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
|
|
|
31
37
|
t.text :tools
|
|
32
38
|
t.integer :max_iterations, default: 25
|
|
33
39
|
t.integer :max_rpm
|
|
40
|
+
t.boolean :reasoning, default: false, null: false
|
|
41
|
+
t.integer :max_reasoning_attempts, default: 3
|
|
42
|
+
t.boolean :respect_context_window, default: false, null: false
|
|
34
43
|
t.text :llm_config
|
|
35
44
|
t.boolean :active, default: true
|
|
36
45
|
|
|
@@ -48,6 +57,13 @@ class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
|
|
|
48
57
|
t.text :output_json
|
|
49
58
|
t.text :output_pydantic
|
|
50
59
|
t.string :output_file
|
|
60
|
+
t.text :output_schema
|
|
61
|
+
t.string :guardrail_class
|
|
62
|
+
t.string :guardrail_method_name
|
|
63
|
+
t.integer :guardrail_max_retries, default: 3
|
|
64
|
+
t.boolean :create_directory, default: true
|
|
65
|
+
t.boolean :markdown, default: false
|
|
66
|
+
t.text :attachments
|
|
51
67
|
t.text :tools
|
|
52
68
|
t.string :callback_class
|
|
53
69
|
t.string :callback_method_name
|
|
@@ -86,12 +102,14 @@ class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
|
|
|
86
102
|
t.datetime :started_at
|
|
87
103
|
t.datetime :completed_at
|
|
88
104
|
t.integer :duration_seconds
|
|
105
|
+
t.string :batch_id
|
|
89
106
|
|
|
90
107
|
t.timestamps
|
|
91
108
|
end
|
|
92
109
|
|
|
93
110
|
add_index :rcrewai_executions, :status
|
|
94
111
|
add_index :rcrewai_executions, :created_at
|
|
112
|
+
add_index :rcrewai_executions, :batch_id
|
|
95
113
|
|
|
96
114
|
create_table :rcrewai_execution_logs do |t|
|
|
97
115
|
t.references :execution, null: false, foreign_key: { to_table: :rcrewai_executions }
|
|
@@ -105,5 +123,37 @@ class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
|
|
|
105
123
|
|
|
106
124
|
add_index :rcrewai_execution_logs, :level
|
|
107
125
|
add_index :rcrewai_execution_logs, :timestamp
|
|
126
|
+
|
|
127
|
+
create_table :rcrewai_knowledge_sources do |t|
|
|
128
|
+
t.references :owner, polymorphic: true, null: false
|
|
129
|
+
t.string :source_type, null: false
|
|
130
|
+
t.text :value, null: false
|
|
131
|
+
t.boolean :active, default: true, null: false
|
|
132
|
+
|
|
133
|
+
t.timestamps
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
create_table :rcrewai_flow_states do |t|
|
|
137
|
+
t.string :state_id, null: false
|
|
138
|
+
t.text :data, null: false
|
|
139
|
+
|
|
140
|
+
t.timestamps
|
|
141
|
+
end
|
|
142
|
+
add_index :rcrewai_flow_states, :state_id, unique: true
|
|
143
|
+
|
|
144
|
+
create_table :rcrewai_flow_runs do |t|
|
|
145
|
+
t.string :flow_class, null: false
|
|
146
|
+
t.string :state_id
|
|
147
|
+
t.string :status, null: false
|
|
148
|
+
t.text :inputs
|
|
149
|
+
t.text :result
|
|
150
|
+
t.string :error_message
|
|
151
|
+
t.datetime :started_at
|
|
152
|
+
t.datetime :completed_at
|
|
153
|
+
|
|
154
|
+
t.timestamps
|
|
155
|
+
end
|
|
156
|
+
add_index :rcrewai_flow_runs, :status
|
|
157
|
+
add_index :rcrewai_flow_runs, :state_id
|
|
108
158
|
end
|
|
109
159
|
end
|
data/rcrewai-rails.gemspec
CHANGED
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
|
|
29
29
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
30
30
|
spec.metadata["source_code_uri"] = spec.homepage
|
|
31
|
-
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/
|
|
31
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
|
|
32
32
|
spec.metadata["documentation_uri"] = "https://gkosmo.github.io/rcrewai-rails/"
|
|
33
33
|
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
|
34
34
|
spec.metadata["wiki_uri"] = "#{spec.homepage}/wiki"
|
|
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
|
37
37
|
spec.files = Dir.chdir(__dir__) do
|
|
38
38
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
39
39
|
(File.expand_path(f) == __FILE__) ||
|
|
40
|
-
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
|
40
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ docs/superpowers/ .git .github appveyor Gemfile])
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
spec.bindir = "exe"
|
|
@@ -45,7 +45,7 @@ Gem::Specification.new do |spec|
|
|
|
45
45
|
spec.require_paths = ["lib"]
|
|
46
46
|
|
|
47
47
|
# Core dependency
|
|
48
|
-
spec.add_dependency "rcrewai", "~> 0.
|
|
48
|
+
spec.add_dependency "rcrewai", "~> 0.5"
|
|
49
49
|
|
|
50
50
|
# Rails dependencies
|
|
51
51
|
spec.add_dependency "rails", ">= 7.0.0"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rcrewai-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- gkosmo
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.5'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.
|
|
25
|
+
version: '0.5'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: rails
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -195,6 +195,7 @@ extensions: []
|
|
|
195
195
|
extra_rdoc_files: []
|
|
196
196
|
files:
|
|
197
197
|
- ".tool-versions"
|
|
198
|
+
- CHANGELOG.md
|
|
198
199
|
- MIT-LICENSE
|
|
199
200
|
- README.md
|
|
200
201
|
- Rakefile
|
|
@@ -208,11 +209,15 @@ files:
|
|
|
208
209
|
- app/controllers/rcrewai/rails/tools_controller.rb
|
|
209
210
|
- app/jobs/rcrewai/rails/crew_execution_job.rb
|
|
210
211
|
- app/jobs/rcrewai/rails/task_execution_job.rb
|
|
212
|
+
- app/models/rcrewai/rails/active_record_state_store.rb
|
|
211
213
|
- app/models/rcrewai/rails/agent.rb
|
|
212
214
|
- app/models/rcrewai/rails/application_record.rb
|
|
213
215
|
- app/models/rcrewai/rails/crew.rb
|
|
214
216
|
- app/models/rcrewai/rails/execution.rb
|
|
215
217
|
- app/models/rcrewai/rails/execution_log.rb
|
|
218
|
+
- app/models/rcrewai/rails/flow_run.rb
|
|
219
|
+
- app/models/rcrewai/rails/flow_state.rb
|
|
220
|
+
- app/models/rcrewai/rails/knowledge_source.rb
|
|
216
221
|
- app/models/rcrewai/rails/task.rb
|
|
217
222
|
- app/models/rcrewai/rails/task_assignment.rb
|
|
218
223
|
- app/models/rcrewai/rails/task_dependency.rb
|
|
@@ -238,8 +243,13 @@ files:
|
|
|
238
243
|
- app/views/rcrewai/rails/tools/show.html.erb
|
|
239
244
|
- config/routes.rb
|
|
240
245
|
- db/migrate/001_add_agent_to_tasks.rb
|
|
246
|
+
- db/migrate/002_add_config_to_rcrewai_agents.rb
|
|
247
|
+
- db/migrate/003_add_output_processing_to_rcrewai_tasks.rb
|
|
248
|
+
- db/migrate/004_add_lifecycle_to_rcrewai_crews.rb
|
|
249
|
+
- db/migrate/005_add_batch_id_to_rcrewai_executions.rb
|
|
250
|
+
- db/migrate/006_create_rcrewai_knowledge_sources.rb
|
|
251
|
+
- db/migrate/007_create_rcrewai_flows.rb
|
|
241
252
|
- docs/index.html
|
|
242
|
-
- docs/superpowers/specs/2026-06-16-github-pages-landing-design.md
|
|
243
253
|
- lib/generators/rcrewai/rails/crew/crew_generator.rb
|
|
244
254
|
- lib/generators/rcrewai/rails/crew/templates/agent.rb.erb
|
|
245
255
|
- lib/generators/rcrewai/rails/crew/templates/crew.rb.erb
|
|
@@ -265,7 +275,7 @@ licenses:
|
|
|
265
275
|
metadata:
|
|
266
276
|
homepage_uri: https://github.com/gkosmo/rcrewai-rails
|
|
267
277
|
source_code_uri: https://github.com/gkosmo/rcrewai-rails
|
|
268
|
-
changelog_uri: https://github.com/gkosmo/rcrewai-rails/blob/
|
|
278
|
+
changelog_uri: https://github.com/gkosmo/rcrewai-rails/blob/master/CHANGELOG.md
|
|
269
279
|
documentation_uri: https://gkosmo.github.io/rcrewai-rails/
|
|
270
280
|
bug_tracker_uri: https://github.com/gkosmo/rcrewai-rails/issues
|
|
271
281
|
wiki_uri: https://github.com/gkosmo/rcrewai-rails/wiki
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# GitHub Pages Landing Site for `rcrewai-rails`
|
|
2
|
-
|
|
3
|
-
**Date:** 2026-06-16
|
|
4
|
-
**Status:** Approved
|
|
5
|
-
|
|
6
|
-
## Goal
|
|
7
|
-
|
|
8
|
-
Publish a polished landing + documentation page for the `rcrewai-rails` gem,
|
|
9
|
-
served via GitHub Pages from the `/docs` folder on `master`. The page gives a
|
|
10
|
-
strong first impression and doubles as practical usage documentation.
|
|
11
|
-
|
|
12
|
-
## Constraints
|
|
13
|
-
|
|
14
|
-
- **Single self-contained file:** `docs/index.html`. No build step, no
|
|
15
|
-
framework, no JavaScript dependencies, no external network requests.
|
|
16
|
-
- **Styling:** Inline `<style>` in the document. Clean light / Rails-y look —
|
|
17
|
-
off-white background, crimson Rails-style accent, system sans-serif for prose,
|
|
18
|
-
monospace for code. Code blocks styled with CSS only (dark block, monospace,
|
|
19
|
-
soft border) — no syntax-token coloring.
|
|
20
|
-
- **Content accuracy:** All copy drawn from the existing `README.md` and
|
|
21
|
-
`rcrewai-rails.gemspec` so the page stays correct.
|
|
22
|
-
|
|
23
|
-
## Hosting
|
|
24
|
-
|
|
25
|
-
GitHub Pages configured to serve from the `master` branch `/docs` folder. The
|
|
26
|
-
resulting URL is `https://gkosmo.github.io/rcrewai-rails/`. (Enabling Pages in
|
|
27
|
-
the repo settings is a manual GitHub step the user performs; this spec only
|
|
28
|
-
produces the file.)
|
|
29
|
-
|
|
30
|
-
## Page Structure
|
|
31
|
-
|
|
32
|
-
Single scrolling page with a sticky top navigation:
|
|
33
|
-
|
|
34
|
-
1. **Sticky header** — gem name, tagline, anchor links (Features · Install ·
|
|
35
|
-
Usage · Tools · API), GitHub link.
|
|
36
|
-
2. **Hero** — name, one-line pitch, `gem 'rcrewai-rails'` snippet, CTA buttons
|
|
37
|
-
(GitHub repo, RubyGems).
|
|
38
|
-
3. **Features grid** — 6 cards: ActiveRecord persistence, ActiveJob integration,
|
|
39
|
-
Rails generators, Web dashboard, Multi-LLM support, Rails-specific tools.
|
|
40
|
-
4. **Installation** — Gemfile, `bundle install`, install generator, `db:migrate`,
|
|
41
|
-
manual route mounting.
|
|
42
|
-
5. **Configuration** — the initializer example from the README.
|
|
43
|
-
6. **Usage** — generator command, programmatic crew example, async/sync execution.
|
|
44
|
-
7. **Rails Tools** — tool ecosystem (ActiveRecord, ActionMailer, Cache,
|
|
45
|
-
ActiveStorage, Logger) with the `DataAnalystAgent` example.
|
|
46
|
-
8. **Web UI & Models** — what `/rcrewai` provides + the ActiveRecord model list.
|
|
47
|
-
9. **API endpoints** — the JSON API table.
|
|
48
|
-
10. **Footer** — MIT license, links.
|
|
49
|
-
|
|
50
|
-
## Additional Change
|
|
51
|
-
|
|
52
|
-
Update `rcrewai-rails.gemspec`:
|
|
53
|
-
`spec.metadata["documentation_uri"]` from
|
|
54
|
-
`https://gkosmo.github.io/rcrewAI/` to
|
|
55
|
-
`https://gkosmo.github.io/rcrewai-rails/`.
|
|
56
|
-
|
|
57
|
-
## Out of Scope
|
|
58
|
-
|
|
59
|
-
- Multi-page docs / Jekyll.
|
|
60
|
-
- JavaScript-driven syntax highlighting.
|
|
61
|
-
- Automated Pages deployment workflow (GitHub builds static `/docs` directly).
|