rcrewai 0.3.0 → 0.4.0
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/.rubocop.yml +20 -0
- data/CHANGELOG.md +40 -1
- data/README.md +168 -0
- data/ROADMAP.md +84 -0
- data/lib/rcrewai/agent.rb +36 -2
- data/lib/rcrewai/configuration.rb +20 -0
- data/lib/rcrewai/crew.rb +79 -1
- data/lib/rcrewai/flow/state.rb +47 -0
- data/lib/rcrewai/flow/state_store.rb +50 -0
- data/lib/rcrewai/flow.rb +243 -0
- data/lib/rcrewai/knowledge/base.rb +52 -0
- data/lib/rcrewai/knowledge/chunker.rb +31 -0
- data/lib/rcrewai/knowledge/embedder.rb +48 -0
- data/lib/rcrewai/knowledge/sources.rb +83 -0
- data/lib/rcrewai/knowledge/store.rb +58 -0
- data/lib/rcrewai/knowledge.rb +13 -0
- data/lib/rcrewai/llm_client.rb +23 -0
- data/lib/rcrewai/output_schema.rb +79 -0
- data/lib/rcrewai/planning.rb +65 -0
- data/lib/rcrewai/task.rb +89 -2
- data/lib/rcrewai/version.rb +1 -1
- data/lib/rcrewai.rb +2 -0
- metadata +13 -1
data/lib/rcrewai/task.rb
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'async_executor'
|
|
4
4
|
require_relative 'human_input'
|
|
5
|
+
require_relative 'output_schema'
|
|
5
6
|
|
|
6
7
|
module RCrewAI
|
|
7
8
|
class Task
|
|
8
9
|
include AsyncExtensions
|
|
9
10
|
include HumanInteractionExtensions
|
|
10
|
-
attr_reader :name, :description, :agent, :context, :expected_output, :tools, :async
|
|
11
|
+
attr_reader :name, :description, :agent, :context, :expected_output, :tools, :async,
|
|
12
|
+
:raw_result, :structured_output
|
|
11
13
|
attr_accessor :result, :status, :start_time, :end_time, :execution_time
|
|
12
14
|
|
|
13
15
|
def initialize(name:, description:, agent: nil, **options)
|
|
@@ -20,6 +22,16 @@ module RCrewAI
|
|
|
20
22
|
@async = options[:async] || false # Whether task can run asynchronously
|
|
21
23
|
@callback = options[:callback] # Callback function after completion
|
|
22
24
|
|
|
25
|
+
# Output processing (0.4.0)
|
|
26
|
+
@output_schema = options[:output_schema] # JSON-schema for structured output
|
|
27
|
+
@guardrail = options[:guardrail] # ->(output) { [ok, value_or_error] }
|
|
28
|
+
@guardrail_max_retries = options.fetch(:guardrail_max_retries, 3)
|
|
29
|
+
@output_file = options[:output_file] # Path to write result to
|
|
30
|
+
@create_directory = options.fetch(:create_directory, true)
|
|
31
|
+
@markdown = options.fetch(:markdown, false)
|
|
32
|
+
@raw_result = nil # Unprocessed string content
|
|
33
|
+
@structured_output = nil # Parsed object when output_schema set
|
|
34
|
+
|
|
23
35
|
# Human interaction options
|
|
24
36
|
@human_input_enabled = options[:human_input] || false
|
|
25
37
|
@require_human_confirmation = options[:require_confirmation] || false
|
|
@@ -62,7 +74,7 @@ module RCrewAI
|
|
|
62
74
|
)
|
|
63
75
|
end
|
|
64
76
|
|
|
65
|
-
@result =
|
|
77
|
+
@result = run_agent_with_output_processing
|
|
66
78
|
|
|
67
79
|
# Post-execution human review if configured
|
|
68
80
|
if @human_input_enabled && @human_review_points.include?(:completion)
|
|
@@ -166,6 +178,12 @@ module RCrewAI
|
|
|
166
178
|
@context << task unless @context.include?(task)
|
|
167
179
|
end
|
|
168
180
|
|
|
181
|
+
# Appends supplementary guidance (e.g. a planning step) to the task's
|
|
182
|
+
# description without discarding the original instructions.
|
|
183
|
+
def enrich_description(text)
|
|
184
|
+
@description = "#{@description}\n\n#{text}"
|
|
185
|
+
end
|
|
186
|
+
|
|
169
187
|
def add_tool(tool)
|
|
170
188
|
@tools << tool unless @tools.include?(tool)
|
|
171
189
|
end
|
|
@@ -190,6 +208,74 @@ module RCrewAI
|
|
|
190
208
|
|
|
191
209
|
private
|
|
192
210
|
|
|
211
|
+
# Runs the agent, then applies guardrail validation and schema coercion.
|
|
212
|
+
# Guardrail/schema failures re-run the agent (up to @guardrail_max_retries)
|
|
213
|
+
# with the failure fed back in, rather than raising immediately.
|
|
214
|
+
def run_agent_with_output_processing
|
|
215
|
+
attempts = 0
|
|
216
|
+
feedback = nil
|
|
217
|
+
|
|
218
|
+
loop do
|
|
219
|
+
attempts += 1
|
|
220
|
+
raw = extract_content(agent.execute_task(self))
|
|
221
|
+
@raw_result = raw
|
|
222
|
+
|
|
223
|
+
begin
|
|
224
|
+
apply_guardrail!(raw)
|
|
225
|
+
@structured_output = OutputSchema.coerce(raw, @output_schema) if @output_schema
|
|
226
|
+
rescue OutputProcessingError, OutputSchemaError => e
|
|
227
|
+
if attempts <= @guardrail_max_retries
|
|
228
|
+
feedback = e.message
|
|
229
|
+
append_feedback_to_description(feedback)
|
|
230
|
+
next
|
|
231
|
+
end
|
|
232
|
+
raise
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
write_output_file(guardrail_value_or(raw)) if @output_file
|
|
236
|
+
return guardrail_value_or(raw)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Accepts either the legacy plain-string return or the 0.3.0 result hash.
|
|
241
|
+
def extract_content(agent_result)
|
|
242
|
+
return agent_result[:content].to_s if agent_result.is_a?(Hash)
|
|
243
|
+
|
|
244
|
+
agent_result.to_s
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def apply_guardrail!(raw)
|
|
248
|
+
return unless @guardrail
|
|
249
|
+
|
|
250
|
+
ok, value = @guardrail.call(raw)
|
|
251
|
+
raise OutputProcessingError, "guardrail rejected output: #{value}" unless ok
|
|
252
|
+
|
|
253
|
+
@guardrail_value = value
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def guardrail_value_or(raw)
|
|
257
|
+
@guardrail ? @guardrail_value : raw
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def append_feedback_to_description(feedback)
|
|
261
|
+
@description = "#{@description}\n\n[Retry] Previous attempt was rejected: #{feedback}. " \
|
|
262
|
+
'Please correct the output.'
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def write_output_file(content)
|
|
266
|
+
dir = File.dirname(@output_file)
|
|
267
|
+
if @create_directory
|
|
268
|
+
require 'fileutils'
|
|
269
|
+
FileUtils.mkdir_p(dir)
|
|
270
|
+
elsif !Dir.exist?(dir)
|
|
271
|
+
raise OutputProcessingError, "output directory does not exist: #{dir}"
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
body = content.to_s
|
|
275
|
+
body = "# #{name}\n\n#{body}" if @markdown && !body.lstrip.start_with?('#')
|
|
276
|
+
File.write(@output_file, body)
|
|
277
|
+
end
|
|
278
|
+
|
|
193
279
|
def confirm_task_execution
|
|
194
280
|
message = "Confirm execution of task: #{name}"
|
|
195
281
|
context = "Description: #{description}\nExpected Output: #{expected_output || 'Not specified'}\nAssigned Agent: #{agent&.name || 'No agent'}"
|
|
@@ -365,4 +451,5 @@ module RCrewAI
|
|
|
365
451
|
|
|
366
452
|
class TaskExecutionError < Error; end
|
|
367
453
|
class TaskDependencyError < TaskExecutionError; end
|
|
454
|
+
class OutputProcessingError < TaskExecutionError; end
|
|
368
455
|
end
|
data/lib/rcrewai/version.rb
CHANGED
data/lib/rcrewai.rb
CHANGED
|
@@ -23,6 +23,7 @@ require_relative 'rcrewai/sse_parser'
|
|
|
23
23
|
require_relative 'rcrewai/pricing'
|
|
24
24
|
require_relative 'rcrewai/llm_client'
|
|
25
25
|
require_relative 'rcrewai/memory'
|
|
26
|
+
require_relative 'rcrewai/knowledge'
|
|
26
27
|
require_relative 'rcrewai/human_input'
|
|
27
28
|
require_relative 'rcrewai/tool_schema'
|
|
28
29
|
require_relative 'rcrewai/provider_schema'
|
|
@@ -41,4 +42,5 @@ require_relative 'rcrewai/async_executor'
|
|
|
41
42
|
require_relative 'rcrewai/agent'
|
|
42
43
|
require_relative 'rcrewai/task'
|
|
43
44
|
require_relative 'rcrewai/crew'
|
|
45
|
+
require_relative 'rcrewai/flow'
|
|
44
46
|
require_relative 'rcrewai/mcp'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rcrewai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- gkosmo
|
|
@@ -302,6 +302,7 @@ files:
|
|
|
302
302
|
- CHANGELOG.md
|
|
303
303
|
- LICENSE
|
|
304
304
|
- README.md
|
|
305
|
+
- ROADMAP.md
|
|
305
306
|
- Rakefile
|
|
306
307
|
- bin/rcrewai
|
|
307
308
|
- docs/_config.yml
|
|
@@ -361,7 +362,16 @@ files:
|
|
|
361
362
|
- lib/rcrewai/configuration.rb
|
|
362
363
|
- lib/rcrewai/crew.rb
|
|
363
364
|
- lib/rcrewai/events.rb
|
|
365
|
+
- lib/rcrewai/flow.rb
|
|
366
|
+
- lib/rcrewai/flow/state.rb
|
|
367
|
+
- lib/rcrewai/flow/state_store.rb
|
|
364
368
|
- lib/rcrewai/human_input.rb
|
|
369
|
+
- lib/rcrewai/knowledge.rb
|
|
370
|
+
- lib/rcrewai/knowledge/base.rb
|
|
371
|
+
- lib/rcrewai/knowledge/chunker.rb
|
|
372
|
+
- lib/rcrewai/knowledge/embedder.rb
|
|
373
|
+
- lib/rcrewai/knowledge/sources.rb
|
|
374
|
+
- lib/rcrewai/knowledge/store.rb
|
|
365
375
|
- lib/rcrewai/legacy_react_runner.rb
|
|
366
376
|
- lib/rcrewai/llm_client.rb
|
|
367
377
|
- lib/rcrewai/llm_clients/anthropic.rb
|
|
@@ -376,6 +386,8 @@ files:
|
|
|
376
386
|
- lib/rcrewai/mcp/transport/http.rb
|
|
377
387
|
- lib/rcrewai/mcp/transport/stdio.rb
|
|
378
388
|
- lib/rcrewai/memory.rb
|
|
389
|
+
- lib/rcrewai/output_schema.rb
|
|
390
|
+
- lib/rcrewai/planning.rb
|
|
379
391
|
- lib/rcrewai/pricing.rb
|
|
380
392
|
- lib/rcrewai/process.rb
|
|
381
393
|
- lib/rcrewai/provider_schema.rb
|