roast-ai 0.4.9 → 0.5.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/.claude/commands/docs/write-comments.md +36 -0
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/ci.yaml +10 -6
- data/.gitignore +0 -1
- data/.rubocop.yml +7 -1
- data/CLAUDE.md +2 -2
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +18 -18
- data/Gemfile.lock +46 -57
- data/README.md +118 -1432
- data/README_LEGACY.md +1464 -0
- data/Rakefile +39 -4
- data/dev.yml +29 -0
- data/dsl/agent_sessions.rb +20 -0
- data/dsl/async_cogs.rb +49 -0
- data/dsl/async_cogs_complex.rb +67 -0
- data/dsl/call.rb +44 -0
- data/dsl/collect_from.rb +72 -0
- data/dsl/demo/Gemfile +4 -0
- data/dsl/demo/Gemfile.lock +120 -0
- data/dsl/demo/cogs/local.rb +15 -0
- data/dsl/demo/simple_external_cog.rb +17 -0
- data/dsl/json_output.rb +28 -0
- data/dsl/map.rb +55 -0
- data/dsl/map_reduce.rb +37 -0
- data/dsl/map_with_index.rb +49 -0
- data/dsl/next_break.rb +40 -0
- data/dsl/next_break_parallel.rb +44 -0
- data/dsl/outputs.rb +39 -0
- data/dsl/outputs_bang.rb +36 -0
- data/dsl/parallel_map.rb +37 -0
- data/dsl/plugin-gem-example/.gitignore +8 -0
- data/dsl/plugin-gem-example/Gemfile +13 -0
- data/dsl/plugin-gem-example/Gemfile.lock +178 -0
- data/dsl/plugin-gem-example/lib/other.rb +17 -0
- data/dsl/plugin-gem-example/lib/plugin_gem_example.rb +5 -0
- data/dsl/plugin-gem-example/lib/simple.rb +15 -0
- data/dsl/plugin-gem-example/lib/version.rb +10 -0
- data/dsl/plugin-gem-example/plugin-gem-example.gemspec +28 -0
- data/dsl/prompts/simple_prompt.md.erb +3 -0
- data/dsl/prototype.rb +10 -4
- data/dsl/repeat_loop_results.rb +53 -0
- data/dsl/ruby_cog.rb +72 -0
- data/dsl/simple_agent.rb +18 -0
- data/dsl/simple_chat.rb +26 -0
- data/dsl/simple_repeat.rb +29 -0
- data/dsl/skip.rb +36 -0
- data/dsl/step_communication.rb +10 -5
- data/dsl/targets_and_params.rb +57 -0
- data/dsl/temperature.rb +17 -0
- data/dsl/temporary_directory.rb +22 -0
- data/dsl/tutorial/01_your_first_workflow/README.md +179 -0
- data/dsl/tutorial/01_your_first_workflow/configured_chat.rb +33 -0
- data/dsl/tutorial/01_your_first_workflow/hello.rb +23 -0
- data/dsl/tutorial/02_chaining_cogs/README.md +310 -0
- data/dsl/tutorial/02_chaining_cogs/code_review.rb +104 -0
- data/dsl/tutorial/02_chaining_cogs/session_resumption.rb +92 -0
- data/dsl/tutorial/02_chaining_cogs/simple_chain.rb +84 -0
- data/dsl/tutorial/03_targets_and_params/README.md +230 -0
- data/dsl/tutorial/03_targets_and_params/multiple_targets.rb +65 -0
- data/dsl/tutorial/03_targets_and_params/single_target.rb +65 -0
- data/dsl/tutorial/04_configuration_options/README.md +209 -0
- data/dsl/tutorial/04_configuration_options/control_display_and_temperature.rb +104 -0
- data/dsl/tutorial/04_configuration_options/simple_config.rb +68 -0
- data/dsl/tutorial/05_control_flow/README.md +156 -0
- data/dsl/tutorial/05_control_flow/conditional_execution.rb +62 -0
- data/dsl/tutorial/05_control_flow/handling_failures.rb +77 -0
- data/dsl/tutorial/06_reusable_scopes/README.md +172 -0
- data/dsl/tutorial/06_reusable_scopes/accessing_scope_outputs.rb +126 -0
- data/dsl/tutorial/06_reusable_scopes/basic_scope.rb +63 -0
- data/dsl/tutorial/06_reusable_scopes/parameterized_scope.rb +78 -0
- data/dsl/tutorial/07_processing_collections/README.md +152 -0
- data/dsl/tutorial/07_processing_collections/basic_map.rb +70 -0
- data/dsl/tutorial/07_processing_collections/parallel_map.rb +74 -0
- data/dsl/tutorial/08_iterative_workflows/README.md +231 -0
- data/dsl/tutorial/08_iterative_workflows/basic_repeat.rb +57 -0
- data/dsl/tutorial/08_iterative_workflows/conditional_break.rb +57 -0
- data/dsl/tutorial/09_async_cogs/README.md +197 -0
- data/dsl/tutorial/09_async_cogs/basic_async.rb +38 -0
- data/dsl/tutorial/README.md +222 -0
- data/dsl/working_directory.rb +16 -0
- data/exe/roast +1 -1
- data/internal/documentation/architectural-notes.md +115 -0
- data/internal/documentation/doc-comments-external.md +686 -0
- data/internal/documentation/doc-comments-internal.md +342 -0
- data/internal/documentation/doc-comments.md +211 -0
- data/lib/roast/dsl/cog/config.rb +280 -4
- data/lib/roast/dsl/cog/input.rb +73 -0
- data/lib/roast/dsl/cog/output.rb +313 -0
- data/lib/roast/dsl/cog/registry.rb +71 -0
- data/lib/roast/dsl/cog/stack.rb +3 -2
- data/lib/roast/dsl/cog/store.rb +11 -8
- data/lib/roast/dsl/cog.rb +108 -31
- data/lib/roast/dsl/cog_input_context.rb +44 -0
- data/lib/roast/dsl/cog_input_manager.rb +156 -0
- data/lib/roast/dsl/cogs/agent/config.rb +465 -0
- data/lib/roast/dsl/cogs/agent/input.rb +81 -0
- data/lib/roast/dsl/cogs/agent/output.rb +59 -0
- data/lib/roast/dsl/cogs/agent/provider.rb +51 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/claude_invocation.rb +185 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/message.rb +73 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/assistant_message.rb +36 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/result_message.rb +61 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/system_message.rb +47 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/text_message.rb +36 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_result_message.rb +47 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_use_message.rb +46 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/unknown_message.rb +27 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/user_message.rb +37 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/tool_result.rb +51 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/tool_use.rb +48 -0
- data/lib/roast/dsl/cogs/agent/providers/claude.rb +31 -0
- data/lib/roast/dsl/cogs/agent/stats.rb +92 -0
- data/lib/roast/dsl/cogs/agent/usage.rb +62 -0
- data/lib/roast/dsl/cogs/agent.rb +75 -0
- data/lib/roast/dsl/cogs/chat/config.rb +453 -0
- data/lib/roast/dsl/cogs/chat/input.rb +92 -0
- data/lib/roast/dsl/cogs/chat/output.rb +64 -0
- data/lib/roast/dsl/cogs/chat/session.rb +68 -0
- data/lib/roast/dsl/cogs/chat.rb +81 -0
- data/lib/roast/dsl/cogs/cmd.rb +291 -27
- data/lib/roast/dsl/cogs/ruby.rb +171 -0
- data/lib/roast/dsl/command_runner.rb +191 -0
- data/lib/roast/dsl/config_context.rb +2 -47
- data/lib/roast/dsl/config_manager.rb +143 -0
- data/lib/roast/dsl/control_flow.rb +41 -0
- data/lib/roast/dsl/execution_context.rb +9 -0
- data/lib/roast/dsl/execution_manager.rb +267 -0
- data/lib/roast/dsl/nil_assertions.rb +23 -0
- data/lib/roast/dsl/system_cog/params.rb +32 -0
- data/lib/roast/dsl/system_cog.rb +36 -0
- data/lib/roast/dsl/system_cogs/call.rb +162 -0
- data/lib/roast/dsl/system_cogs/map.rb +448 -0
- data/lib/roast/dsl/system_cogs/repeat.rb +242 -0
- data/lib/roast/dsl/workflow.rb +123 -0
- data/lib/roast/dsl/workflow_context.rb +20 -0
- data/lib/roast/dsl/workflow_params.rb +24 -0
- data/lib/roast/sorbet_runtime_stub.rb +154 -0
- data/lib/roast/tools/apply_diff.rb +1 -3
- data/lib/roast/tools/cmd.rb +4 -3
- data/lib/roast/tools/read_file.rb +1 -1
- data/lib/roast/tools/update_files.rb +1 -1
- data/lib/roast/tools/write_file.rb +1 -1
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/base_workflow.rb +4 -0
- data/lib/roast/workflow/step_loader.rb +14 -2
- data/lib/roast-ai.rb +4 -0
- data/lib/roast.rb +60 -22
- data/{roast.gemspec → roast-ai.gemspec} +10 -13
- data/sorbet/config +1 -0
- data/sorbet/rbi/gems/async@2.34.0.rbi +1577 -0
- data/sorbet/rbi/gems/cli-kit@5.2.0.rbi +2063 -0
- data/sorbet/rbi/gems/{cli-ui@2.3.0.rbi → cli-ui@2.7.0-6bdefd1d06305e5d6ae312ac76f9c88f88658dda.rbi} +1418 -1013
- data/sorbet/rbi/gems/console@1.34.2.rbi +1193 -0
- data/sorbet/rbi/gems/fiber-annotation@0.2.0.rbi +50 -0
- data/sorbet/rbi/gems/fiber-local@1.1.0.rbi +35 -0
- data/sorbet/rbi/gems/fiber-storage@1.0.1.rbi +41 -0
- data/sorbet/rbi/gems/io-event@1.14.0.rbi +724 -0
- data/sorbet/rbi/gems/marcel@1.1.0.rbi +239 -0
- data/sorbet/rbi/gems/metrics@0.15.0.rbi +9 -0
- data/sorbet/rbi/gems/ruby_llm@1.8.2.rbi +5703 -0
- data/sorbet/rbi/gems/traces@0.18.2.rbi +9 -0
- data/sorbet/rbi/shims/lib/roast/dsl/cog_input_context.rbi +1197 -0
- data/sorbet/rbi/shims/lib/roast/dsl/config_context.rbi +314 -2
- data/sorbet/rbi/shims/lib/roast/dsl/execution_context.rbi +498 -0
- data/sorbet/tapioca/config.yml +6 -0
- data/sorbet/tapioca/require.rb +2 -0
- metadata +198 -34
- data/dsl/less_simple.rb +0 -112
- data/dsl/simple.rb +0 -8
- data/lib/roast/dsl/cog_execution_context.rb +0 -29
- data/lib/roast/dsl/cogs/graph.rb +0 -53
- data/lib/roast/dsl/cogs.rb +0 -65
- data/lib/roast/dsl/executor.rb +0 -82
- data/lib/roast/dsl/workflow_execution_context.rb +0 -47
- data/sorbet/rbi/gems/cgi@0.5.0.rbi +0 -2961
- data/sorbet/rbi/gems/claude_swarm@0.1.19.rbi +0 -568
- data/sorbet/rbi/gems/cli-kit@5.0.1.rbi +0 -1991
- data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +0 -672
- data/sorbet/rbi/gems/dry-core@1.1.0.rbi +0 -1894
- data/sorbet/rbi/gems/dry-inflector@1.2.0.rbi +0 -659
- data/sorbet/rbi/gems/dry-initializer@3.2.0.rbi +0 -781
- data/sorbet/rbi/gems/dry-logic@1.6.0.rbi +0 -1127
- data/sorbet/rbi/gems/dry-schema@1.14.1.rbi +0 -3727
- data/sorbet/rbi/gems/dry-types@1.8.3.rbi +0 -3969
- data/sorbet/rbi/gems/fast-mcp-annotations@1.5.3.rbi +0 -1588
- data/sorbet/rbi/gems/mime-types-data@3.2025.0617.rbi +0 -136
- data/sorbet/rbi/gems/mime-types@3.7.0.rbi +0 -1342
- data/sorbet/rbi/gems/rack@2.2.18.rbi +0 -5659
- data/sorbet/rbi/gems/rbs-inline@0.12.0.rbi +0 -2170
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +0 -435
- data/sorbet/rbi/gems/yard@0.9.37.rbi +0 -18492
- data/sorbet/rbi/shims/lib/roast/dsl/workflow_execution_context.rbi +0 -11
data/dsl/next_break.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
execute do
|
|
10
|
+
map(:loop, run: :loop_body) { 1..3 }
|
|
11
|
+
|
|
12
|
+
ruby do
|
|
13
|
+
results = collect(map!(:loop)) do
|
|
14
|
+
[ruby?(:one), ruby?(:two), ruby?(:three)]
|
|
15
|
+
end
|
|
16
|
+
results.each_with_index do |iteration_results, index|
|
|
17
|
+
puts "Iteration #{index}: #{iteration_results.presence || "did not run at all"}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
execute(:loop_body) do
|
|
23
|
+
ruby(:one) do |_, _, idx|
|
|
24
|
+
skip! if idx == 0
|
|
25
|
+
s = "[#{idx}] beginning"
|
|
26
|
+
puts s
|
|
27
|
+
s
|
|
28
|
+
end
|
|
29
|
+
ruby(:two) do |_, _, idx|
|
|
30
|
+
break! if idx == 1
|
|
31
|
+
s = "[#{idx}] middle"
|
|
32
|
+
puts s
|
|
33
|
+
s
|
|
34
|
+
end
|
|
35
|
+
ruby(:three) do |_, _, idx|
|
|
36
|
+
s = "[#{idx}] end"
|
|
37
|
+
puts s
|
|
38
|
+
s
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
map { parallel! }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
execute do
|
|
11
|
+
map(:loop, run: :loop_body) { 1..3 }
|
|
12
|
+
|
|
13
|
+
ruby do
|
|
14
|
+
results = collect(map!(:loop)) do
|
|
15
|
+
[ruby?(:one), ruby?(:two), ruby?(:three)]
|
|
16
|
+
end
|
|
17
|
+
results.each_with_index do |iteration_results, index|
|
|
18
|
+
puts "Iteration #{index}: #{iteration_results.presence || "did not run at all"}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
execute(:loop_body) do
|
|
24
|
+
ruby(:one) do |_, _, idx|
|
|
25
|
+
sleep(0.1) if idx == 0
|
|
26
|
+
sleep(0.2) if idx == 1
|
|
27
|
+
skip! if idx == 0
|
|
28
|
+
s = "[#{idx}] beginning"
|
|
29
|
+
puts s
|
|
30
|
+
s
|
|
31
|
+
end
|
|
32
|
+
ruby(:two) do |_, _, idx|
|
|
33
|
+
break! if idx == 1
|
|
34
|
+
s = "[#{idx}] middle"
|
|
35
|
+
puts s
|
|
36
|
+
s
|
|
37
|
+
end
|
|
38
|
+
ruby(:three) do |_, _, idx|
|
|
39
|
+
sleep(0.3) if idx == 2
|
|
40
|
+
s = "[#{idx}] end"
|
|
41
|
+
puts s
|
|
42
|
+
s
|
|
43
|
+
end
|
|
44
|
+
end
|
data/dsl/outputs.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
cmd { display! }
|
|
8
|
+
cmd(/to_/) { no_display! }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
execute(:capitalize_a_word) do
|
|
12
|
+
cmd(:to_original) { |_, word| "echo \"#{word}\"" }
|
|
13
|
+
cmd(:to_upper) do |my, word|
|
|
14
|
+
my.command = "sh"
|
|
15
|
+
my.args << "-c"
|
|
16
|
+
my.args << "echo \"#{word}\" | tr '[:lower:]' '[:upper:]'"
|
|
17
|
+
end
|
|
18
|
+
cmd(:to_lower) do |my, word|
|
|
19
|
+
break! # the `outputs` will always be evaluated even if a cog breaks out of the execution scope
|
|
20
|
+
my.command = "sh"
|
|
21
|
+
my.args << "-c"
|
|
22
|
+
my.args << "echo \"#{word}\" | tr '[:upper:]' '[:lower:]'"
|
|
23
|
+
end
|
|
24
|
+
outputs do |word|
|
|
25
|
+
"Upper: #{cmd!(:to_upper).text} - Original: #{word}"
|
|
26
|
+
# `outputs` can return any kind of value
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
execute do
|
|
31
|
+
# Call a subroutine with `call` or `map`
|
|
32
|
+
call(:hello, run: :capitalize_a_word) { "Hello" }
|
|
33
|
+
|
|
34
|
+
cmd do
|
|
35
|
+
from_outputs = from(call!(:hello))
|
|
36
|
+
explicit_value_access = from(call!(:hello)) { cmd!(:to_upper).text }
|
|
37
|
+
"echo From Outputs: '\"#{from_outputs}\"\nExplicit Value Access: \"#{explicit_value_access}\"'"
|
|
38
|
+
end
|
|
39
|
+
end
|
data/dsl/outputs_bang.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
cmd { display! }
|
|
8
|
+
cmd(/to_/) { no_display! }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
execute(:subroutine1) do
|
|
12
|
+
ruby(:one) { "one" }
|
|
13
|
+
ruby(:two) { skip! }
|
|
14
|
+
# Attempting to access the output of a cog that did not run will not raise an exception inside the `outputs` block
|
|
15
|
+
# Instead, it will just return `nil`
|
|
16
|
+
outputs { ruby!(:two).value }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
execute(:subroutine2) do
|
|
20
|
+
ruby(:one) { "one" }
|
|
21
|
+
ruby(:two) { skip! }
|
|
22
|
+
# Attempting to access the output of a cog that did not run *will* raise an exception inside the `outputs!` block
|
|
23
|
+
outputs! do
|
|
24
|
+
puts "❗️ This block is expected to raise an exception ❗️"
|
|
25
|
+
ruby!(:two).value
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
execute do
|
|
30
|
+
call(:one, run: :subroutine1) {}
|
|
31
|
+
|
|
32
|
+
ruby { puts "Using the `outputs` block should return `nil`: #{from(call!(:one)) || "nil"}" }
|
|
33
|
+
|
|
34
|
+
# The `outputs!` block in subroutine2 will raise an exception as soon as it is evaluated
|
|
35
|
+
call(:two, run: :subroutine2) {}
|
|
36
|
+
end
|
data/dsl/parallel_map.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
cmd { display! }
|
|
8
|
+
map(:words) do
|
|
9
|
+
# By default, maximum parallelism is 1 and map executions will run synchronously
|
|
10
|
+
# Calling `parallel` with a larger value will allow multiple map items to be run in parallel, up to the limit given
|
|
11
|
+
# Calling `parallel!` or `parallel(0)` will allow unlimited parallelism, processing all map items in parallel
|
|
12
|
+
parallel 3
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
execute(:capitalize_a_word) do
|
|
17
|
+
cmd(:to_upper) do |_, word, index|
|
|
18
|
+
sleep(0.1) if index == 3 # "three" will be slow --> finishing second last
|
|
19
|
+
sleep(0.2) if index == 1 # "one" will be slowest --> finishing last
|
|
20
|
+
["sh", "-c", "echo \"#{word}\" | tr '[:lower:]' '[:upper:]'"]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
execute do
|
|
25
|
+
# Call a subroutine with `map`
|
|
26
|
+
map(:words, run: :capitalize_a_word) do |my|
|
|
27
|
+
my.items = ["one", "two", "three", "four", "five", "six"]
|
|
28
|
+
my.initial_index = 1 # for convenience, just because our items begin with "one"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
cmd do |my|
|
|
32
|
+
my.command = "echo"
|
|
33
|
+
# Regardless of the order in which the items were processed by a parallel map,
|
|
34
|
+
# their results will always be provided to `collect` and `reduce` in the order in which they were given.
|
|
35
|
+
my.args << collect(map!(:words)) { cmd!(:to_upper).text }.join(", ")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
plugin-gem-example (0.1.0)
|
|
5
|
+
roast-ai
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
activesupport (8.0.3)
|
|
11
|
+
base64
|
|
12
|
+
benchmark (>= 0.3)
|
|
13
|
+
bigdecimal
|
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
15
|
+
connection_pool (>= 2.2.5)
|
|
16
|
+
drb
|
|
17
|
+
i18n (>= 1.6, < 2)
|
|
18
|
+
logger (>= 1.4.2)
|
|
19
|
+
minitest (>= 5.1)
|
|
20
|
+
securerandom (>= 0.3)
|
|
21
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
|
+
uri (>= 0.13.1)
|
|
23
|
+
addressable (2.8.7)
|
|
24
|
+
public_suffix (>= 2.0.2, < 7.0)
|
|
25
|
+
ast (2.4.3)
|
|
26
|
+
base64 (0.3.0)
|
|
27
|
+
benchmark (0.4.1)
|
|
28
|
+
bigdecimal (3.3.1)
|
|
29
|
+
cli-kit (5.0.1)
|
|
30
|
+
cli-ui (~> 2.0)
|
|
31
|
+
cli-ui (2.3.0)
|
|
32
|
+
concurrent-ruby (1.3.5)
|
|
33
|
+
connection_pool (2.5.4)
|
|
34
|
+
date (3.4.1)
|
|
35
|
+
diff-lcs (1.6.2)
|
|
36
|
+
dotenv (3.1.8)
|
|
37
|
+
drb (2.2.3)
|
|
38
|
+
erb (5.1.1)
|
|
39
|
+
event_stream_parser (1.0.0)
|
|
40
|
+
faraday (2.14.0)
|
|
41
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
42
|
+
json
|
|
43
|
+
logger
|
|
44
|
+
faraday-multipart (1.1.1)
|
|
45
|
+
multipart-post (~> 2.0)
|
|
46
|
+
faraday-net_http (3.4.1)
|
|
47
|
+
net-http (>= 0.5.0)
|
|
48
|
+
faraday-retry (2.3.2)
|
|
49
|
+
faraday (~> 2.0)
|
|
50
|
+
i18n (1.14.7)
|
|
51
|
+
concurrent-ruby (~> 1.0)
|
|
52
|
+
io-console (0.8.1)
|
|
53
|
+
irb (1.15.2)
|
|
54
|
+
pp (>= 0.6.0)
|
|
55
|
+
rdoc (>= 4.0.0)
|
|
56
|
+
reline (>= 0.4.2)
|
|
57
|
+
json (2.15.1)
|
|
58
|
+
json-schema (6.0.0)
|
|
59
|
+
addressable (~> 2.8)
|
|
60
|
+
bigdecimal (~> 3.1)
|
|
61
|
+
language_server-protocol (3.17.0.5)
|
|
62
|
+
lint_roller (1.1.0)
|
|
63
|
+
logger (1.7.0)
|
|
64
|
+
minitest (5.26.0)
|
|
65
|
+
multipart-post (2.4.1)
|
|
66
|
+
net-http (0.6.0)
|
|
67
|
+
uri
|
|
68
|
+
open_router (0.3.3)
|
|
69
|
+
activesupport (>= 6.0)
|
|
70
|
+
dotenv (>= 2)
|
|
71
|
+
faraday (>= 1)
|
|
72
|
+
faraday-multipart (>= 1)
|
|
73
|
+
ostruct (0.6.3)
|
|
74
|
+
parallel (1.27.0)
|
|
75
|
+
parser (3.3.9.0)
|
|
76
|
+
ast (~> 2.4.1)
|
|
77
|
+
racc
|
|
78
|
+
pp (0.6.3)
|
|
79
|
+
prettyprint
|
|
80
|
+
prettyprint (0.2.0)
|
|
81
|
+
prism (1.6.0)
|
|
82
|
+
psych (5.2.6)
|
|
83
|
+
date
|
|
84
|
+
stringio
|
|
85
|
+
public_suffix (6.0.2)
|
|
86
|
+
racc (1.8.1)
|
|
87
|
+
rainbow (3.1.1)
|
|
88
|
+
raix (1.0.3)
|
|
89
|
+
activesupport (>= 6.0)
|
|
90
|
+
faraday-retry (~> 2.0)
|
|
91
|
+
open_router (~> 0.2)
|
|
92
|
+
ostruct
|
|
93
|
+
ruby-openai (~> 8.1)
|
|
94
|
+
rake (13.3.0)
|
|
95
|
+
rdoc (6.15.0)
|
|
96
|
+
erb
|
|
97
|
+
psych (>= 4.0.0)
|
|
98
|
+
tsort
|
|
99
|
+
regexp_parser (2.11.3)
|
|
100
|
+
reline (0.6.2)
|
|
101
|
+
io-console (~> 0.5)
|
|
102
|
+
rexml (3.4.4)
|
|
103
|
+
roast-ai (0.4.9)
|
|
104
|
+
activesupport (>= 7.0)
|
|
105
|
+
cli-kit (~> 5.0)
|
|
106
|
+
cli-ui (= 2.3.0)
|
|
107
|
+
diff-lcs (~> 1.5)
|
|
108
|
+
json-schema
|
|
109
|
+
open_router (~> 0.3)
|
|
110
|
+
raix (~> 1.0.2)
|
|
111
|
+
ruby-graphviz (~> 1.2)
|
|
112
|
+
sqlite3 (~> 2.6)
|
|
113
|
+
thor (~> 1.3)
|
|
114
|
+
zeitwerk (~> 2.6)
|
|
115
|
+
rubocop (1.81.1)
|
|
116
|
+
json (~> 2.3)
|
|
117
|
+
language_server-protocol (~> 3.17.0.2)
|
|
118
|
+
lint_roller (~> 1.1.0)
|
|
119
|
+
parallel (~> 1.10)
|
|
120
|
+
parser (>= 3.3.0.2)
|
|
121
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
122
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
123
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
124
|
+
ruby-progressbar (~> 1.7)
|
|
125
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
126
|
+
rubocop-ast (1.47.1)
|
|
127
|
+
parser (>= 3.3.7.2)
|
|
128
|
+
prism (~> 1.4)
|
|
129
|
+
ruby-graphviz (1.2.5)
|
|
130
|
+
rexml
|
|
131
|
+
ruby-openai (8.3.0)
|
|
132
|
+
event_stream_parser (>= 0.3.0, < 2.0.0)
|
|
133
|
+
faraday (>= 1)
|
|
134
|
+
faraday-multipart (>= 1)
|
|
135
|
+
ruby-progressbar (1.13.0)
|
|
136
|
+
securerandom (0.4.1)
|
|
137
|
+
sqlite3 (2.7.4-aarch64-linux-gnu)
|
|
138
|
+
sqlite3 (2.7.4-aarch64-linux-musl)
|
|
139
|
+
sqlite3 (2.7.4-arm-linux-gnu)
|
|
140
|
+
sqlite3 (2.7.4-arm-linux-musl)
|
|
141
|
+
sqlite3 (2.7.4-arm64-darwin)
|
|
142
|
+
sqlite3 (2.7.4-x86-linux-gnu)
|
|
143
|
+
sqlite3 (2.7.4-x86-linux-musl)
|
|
144
|
+
sqlite3 (2.7.4-x86_64-darwin)
|
|
145
|
+
sqlite3 (2.7.4-x86_64-linux-gnu)
|
|
146
|
+
sqlite3 (2.7.4-x86_64-linux-musl)
|
|
147
|
+
stringio (3.1.7)
|
|
148
|
+
thor (1.4.0)
|
|
149
|
+
tsort (0.2.0)
|
|
150
|
+
tzinfo (2.0.6)
|
|
151
|
+
concurrent-ruby (~> 1.0)
|
|
152
|
+
unicode-display_width (3.2.0)
|
|
153
|
+
unicode-emoji (~> 4.1)
|
|
154
|
+
unicode-emoji (4.1.0)
|
|
155
|
+
uri (1.0.4)
|
|
156
|
+
zeitwerk (2.7.3)
|
|
157
|
+
|
|
158
|
+
PLATFORMS
|
|
159
|
+
aarch64-linux-gnu
|
|
160
|
+
aarch64-linux-musl
|
|
161
|
+
arm-linux-gnu
|
|
162
|
+
arm-linux-musl
|
|
163
|
+
arm64-darwin
|
|
164
|
+
x86-linux-gnu
|
|
165
|
+
x86-linux-musl
|
|
166
|
+
x86_64-darwin
|
|
167
|
+
x86_64-linux-gnu
|
|
168
|
+
x86_64-linux-musl
|
|
169
|
+
|
|
170
|
+
DEPENDENCIES
|
|
171
|
+
irb
|
|
172
|
+
minitest (~> 5.16)
|
|
173
|
+
plugin-gem-example!
|
|
174
|
+
rake (~> 13.0)
|
|
175
|
+
rubocop (~> 1.21)
|
|
176
|
+
|
|
177
|
+
BUNDLED WITH
|
|
178
|
+
2.6.8
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module MyCogNamespace
|
|
5
|
+
class Other < Roast::DSL::Cog
|
|
6
|
+
class Input < Roast::DSL::Cog::Input
|
|
7
|
+
def validate!
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
#: (Input) -> void
|
|
13
|
+
def execute(input)
|
|
14
|
+
puts "I'm a different cog!"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "plugin-gem-example"
|
|
7
|
+
spec.version = Plugin::Gem::Example::VERSION
|
|
8
|
+
spec.authors = ["Sam Schmidt"]
|
|
9
|
+
spec.email = ["sam.schmidt@shopify.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "TODO: Write a short summary, because RubyGems requires one."
|
|
12
|
+
spec.description = "TODO: Write a longer description or delete this line."
|
|
13
|
+
spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
spec.required_ruby_version = ">= 3.1.0"
|
|
16
|
+
|
|
17
|
+
spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
|
18
|
+
|
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
20
|
+
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
|
21
|
+
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
|
22
|
+
|
|
23
|
+
# Uncomment to register a new dependency of your gem
|
|
24
|
+
spec.add_dependency("roast-ai")
|
|
25
|
+
|
|
26
|
+
# For more information and examples about making a new gem, check out our
|
|
27
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
28
|
+
end
|
data/dsl/prototype.rb
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
# typed: true
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
#: self as Roast::DSL::
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
5
|
|
|
6
6
|
config do
|
|
7
|
-
cmd(:echo) {
|
|
7
|
+
cmd(:echo) { display! }
|
|
8
|
+
cmd(/date/) { display! }
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
execute do
|
|
11
12
|
# Anonymous cog. Added to the stack directly and given an autogenerated key in cog storage
|
|
12
13
|
# Use for actions you do once and forget about, don't need configuration
|
|
13
|
-
cmd { "touch tmp/#{SecureRandom.uuid}
|
|
14
|
+
cmd { |my| my.command = "touch tmp/#{SecureRandom.uuid}" }
|
|
14
15
|
|
|
15
16
|
# Named cog. Configuration for this specific instance will be looked up from config block
|
|
16
|
-
cmd(:echo) { "echo 'Hello World!'" }
|
|
17
|
+
cmd(:echo) { |my| my.command = "echo 'Hello World!'" }
|
|
18
|
+
|
|
19
|
+
# Cogs can implement input coercion for simple return values
|
|
20
|
+
fmt = "\"+%a %b %d %T %Z %Y\""
|
|
21
|
+
cmd(:date_today) { "/bin/date #{fmt}" }
|
|
22
|
+
cmd(:date_yesterday) { RUBY_PLATFORM.include?("darwin") ? "/bin/date -jv -1d #{fmt}" : "/bin/date -d '-1 day' #{fmt}" }
|
|
17
23
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
execute do
|
|
10
|
+
repeat(:loop, run: :loop_body) { 7 }
|
|
11
|
+
|
|
12
|
+
ruby do
|
|
13
|
+
# You can access the final output value of a `repeat` cog directly
|
|
14
|
+
result = repeat!(:loop)
|
|
15
|
+
puts "Ultimate Loop Result: #{result.value}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
ruby do
|
|
19
|
+
puts "---"
|
|
20
|
+
# You can also access the final result, or individual cog results, of any specific iteration
|
|
21
|
+
# In the same manner as you would use `from` to access the results of a single `call` invocation.
|
|
22
|
+
puts "First Iteration Result: #{from(repeat!(:loop).first)}"
|
|
23
|
+
puts "Final Iteration Result: #{from(repeat!(:loop).last)}"
|
|
24
|
+
puts "Second-to-last Iteration Result: #{from(repeat!(:loop).iteration(-2))}"
|
|
25
|
+
# NOTE: accessing a specific iteration will raise an IndexException if the requested index is out of bounds
|
|
26
|
+
# for the number of iterations that ran.
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ruby do
|
|
30
|
+
puts "---"
|
|
31
|
+
# You can access the results of all iterations in the same manner as you would use `collect` or `reduce`
|
|
32
|
+
# to access the complete results of a `map` invocation.
|
|
33
|
+
puts "All :add cog outputs: #{collect(repeat!(:loop).results) { ruby!(:add).value }}"
|
|
34
|
+
puts "Sum of :add cog output: #{reduce(repeat!(:loop).results, 0) { |acc| acc + ruby!(:add).value }}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
execute(:loop_body) do
|
|
39
|
+
# on each loop iteration, the input value provided will be the output value of the previous iteration
|
|
40
|
+
# the initial value will be what was provided when `repeat` was called in the outer scope.
|
|
41
|
+
ruby(:add) do |_, num, idx|
|
|
42
|
+
new_num = num + idx
|
|
43
|
+
s = "iteration #{idx}: #{num} + #{idx} -> #{new_num}"
|
|
44
|
+
puts s
|
|
45
|
+
new_num
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
ruby { |_, _, idx| break! if idx >= 3 }
|
|
49
|
+
|
|
50
|
+
# The value provided to `outputs` will be the input value for the next iteration
|
|
51
|
+
# On the final iteration, it will also be the `repeat` cog's own output value
|
|
52
|
+
outputs { ruby!(:add).value }
|
|
53
|
+
end
|
data/dsl/ruby_cog.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
class MyClass
|
|
7
|
+
class << self
|
|
8
|
+
def add_stuff(a, b)
|
|
9
|
+
a + b
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
config do
|
|
15
|
+
cmd { display! }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
execute do
|
|
19
|
+
cmd(:roast) { "echo Roast" }
|
|
20
|
+
|
|
21
|
+
# The `ruby` cog just passes the return value from its input block directly to its output.
|
|
22
|
+
# Letting you write whatever ruby code you want to generate that output
|
|
23
|
+
ruby(:whatever) do
|
|
24
|
+
# Do whatever you want in this block
|
|
25
|
+
value = cmd!(:roast).text
|
|
26
|
+
puts "Hello, #{value.upcase}"
|
|
27
|
+
puts "Calling a method: #{MyClass.add_stuff(3, 4)}"
|
|
28
|
+
# The value you return will be exposed as the .value attribute on the cog's output
|
|
29
|
+
1..5
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
cmd(:numbers) do |my|
|
|
33
|
+
my.command = "echo"
|
|
34
|
+
value = ruby!(:whatever).value.map { |n| n.to_s * n }
|
|
35
|
+
my.args = value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
ruby(:advanced_hash_output) do
|
|
39
|
+
{
|
|
40
|
+
some_number: 7,
|
|
41
|
+
some_string: "Hello, world!",
|
|
42
|
+
multiply: proc { |a, b| a * b },
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
ruby do
|
|
47
|
+
result = ruby!(:advanced_hash_output) #: untyped
|
|
48
|
+
|
|
49
|
+
# If the output's `value` is a Hash, you can access its items directly from the output object
|
|
50
|
+
puts "Some Number + 1: #{result[:some_number] + 1}"
|
|
51
|
+
# You can also access its items as getter methods on the output object
|
|
52
|
+
puts "Some String to Upper: #{result.some_string.upcase}"
|
|
53
|
+
# And, if one of those items is a proc, you can call it directly on the output object
|
|
54
|
+
puts "Multiply 4 * 3: #{result.multiply(4, 3)}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
ruby(:advanced_object_output) do |my|
|
|
58
|
+
my.value = <<~STRING
|
|
59
|
+
This is a long block of test
|
|
60
|
+
Consisting of many lines
|
|
61
|
+
Three, to be precise
|
|
62
|
+
STRING
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
ruby do
|
|
66
|
+
result = ruby!(:advanced_object_output) #: untyped
|
|
67
|
+
|
|
68
|
+
# You can also call methods on the output's `value` directly, regardless of its type
|
|
69
|
+
puts "The long string has #{result.lines.length} lines"
|
|
70
|
+
puts "And it has #{result.length} characters"
|
|
71
|
+
end
|
|
72
|
+
end
|
data/dsl/simple_agent.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
agent do
|
|
8
|
+
provider :claude
|
|
9
|
+
model "haiku"
|
|
10
|
+
initial_prompt "Always respond in haiku form"
|
|
11
|
+
show_prompt!
|
|
12
|
+
dump_raw_agent_messages_to "tmp/claude-messages.log"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
execute do
|
|
17
|
+
agent { "What is the world's largest lake?" }
|
|
18
|
+
end
|
data/dsl/simple_chat.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#: self as Roast::DSL::Workflow
|
|
5
|
+
|
|
6
|
+
config do
|
|
7
|
+
chat(:lake) { model("gpt-4o") }
|
|
8
|
+
chat(:next) { model("gpt-4o-mini") }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
execute do
|
|
12
|
+
# Ask a question
|
|
13
|
+
chat(:lake) { "What is the deepest lake?" }
|
|
14
|
+
|
|
15
|
+
# Continue the conversation (with a different model!)
|
|
16
|
+
chat(:next) do |my|
|
|
17
|
+
my.prompt = "What answer did you just give, and why?"
|
|
18
|
+
my.session = chat!(:lake).session
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Ask a question with a template prompt. You can pass variables to it as you would an ERB template
|
|
22
|
+
chat { template("dsl/prompts/simple_prompt.md.erb", { lake_answer: chat!(:lake).response }) }
|
|
23
|
+
|
|
24
|
+
# Shorthand to look up a template prompt
|
|
25
|
+
# chat { template("simple_prompt", { lake_answer: chat!(:lake).response }) }
|
|
26
|
+
end
|