roast-ai 0.4.7 → 0.4.9
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/.gitignore +1 -0
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +3 -3
- data/README.md +9 -5
- data/Rakefile +2 -0
- data/dsl/less_simple.rb +112 -0
- data/dsl/prototype.rb +17 -0
- data/dsl/simple.rb +5 -7
- data/dsl/step_communication.rb +18 -0
- data/examples/README.md +9 -0
- data/examples/available_tools_demo/workflow.yml +1 -1
- data/examples/basic_prompt_workflow/workflow.md +1 -0
- data/examples/basic_prompt_workflow/workflow.yml +14 -0
- data/examples/grading/README.md +1 -26
- data/examples/grading/analyze_coverage/prompt.md +1 -1
- data/examples/grading/calculate_final_grade.rb +10 -13
- data/examples/grading/format_result.rb +5 -8
- data/examples/grading/generate_grades/prompt.md +1 -1
- data/examples/grading/generate_recommendations/prompt.md +1 -1
- data/examples/grading/read_dependencies/prompt.md +0 -1
- data/examples/grading/verify_test_helpers/prompt.md +1 -1
- data/examples/grading/workflow.md +1 -4
- data/examples/grading/workflow.yml +3 -16
- data/lib/roast/dsl/cog/config.rb +31 -0
- data/lib/roast/dsl/cog/stack.rb +21 -0
- data/lib/roast/dsl/cog/store.rb +26 -0
- data/lib/roast/dsl/cog.rb +70 -0
- data/lib/roast/dsl/cog_execution_context.rb +29 -0
- data/lib/roast/dsl/cogs/cmd.rb +55 -0
- data/lib/roast/dsl/cogs/graph.rb +53 -0
- data/lib/roast/dsl/cogs.rb +65 -0
- data/lib/roast/dsl/config_context.rb +54 -0
- data/lib/roast/dsl/executor.rb +62 -7
- data/lib/roast/dsl/workflow_execution_context.rb +47 -0
- data/lib/roast/error.rb +7 -0
- data/lib/roast/errors.rb +3 -3
- data/lib/roast/graph/edge.rb +25 -0
- data/lib/roast/graph/node.rb +40 -0
- data/lib/roast/graph/quantum_edge.rb +27 -0
- data/lib/roast/graph/threaded_exec.rb +93 -0
- data/lib/roast/graph.rb +233 -0
- data/lib/roast/resources/api_resource.rb +2 -2
- data/lib/roast/resources/url_resource.rb +2 -2
- data/lib/roast/tools/apply_diff.rb +1 -1
- data/lib/roast/tools/ask_user.rb +1 -1
- data/lib/roast/tools/bash.rb +1 -1
- data/lib/roast/tools/cmd.rb +2 -2
- data/lib/roast/tools/coding_agent.rb +2 -2
- data/lib/roast/tools/grep.rb +1 -1
- data/lib/roast/tools/read_file.rb +1 -1
- data/lib/roast/tools/search_file.rb +1 -1
- data/lib/roast/tools/swarm.rb +1 -1
- data/lib/roast/tools/update_files.rb +2 -2
- data/lib/roast/tools/write_file.rb +1 -1
- data/lib/roast/tools.rb +1 -1
- data/lib/roast/value_objects/api_token.rb +1 -1
- data/lib/roast/value_objects/uri_base.rb +1 -1
- data/lib/roast/value_objects/workflow_path.rb +1 -1
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/base_step.rb +2 -3
- data/lib/roast/workflow/base_workflow.rb +38 -2
- data/lib/roast/workflow/command_executor.rb +1 -1
- data/lib/roast/workflow/configuration_loader.rb +1 -1
- data/lib/roast/workflow/error_handler.rb +1 -1
- data/lib/roast/workflow/step_executor_registry.rb +1 -1
- data/lib/roast/workflow/step_loader.rb +3 -8
- data/lib/roast/workflow/workflow_executor.rb +1 -1
- data/lib/roast.rb +7 -2
- data/sorbet/config +2 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/activesupport.rbi +495 -0
- data/sorbet/rbi/annotations/faraday.rbi +17 -0
- data/sorbet/rbi/annotations/minitest.rbi +119 -0
- data/sorbet/rbi/annotations/mocha.rbi +34 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/annotations/webmock.rbi +9 -0
- data/sorbet/rbi/gems/rbs-inline@0.12.0.rbi +2170 -0
- data/sorbet/rbi/gems/{rexml@3.4.1.rbi → rexml@3.4.2.rbi} +284 -239
- data/sorbet/rbi/shims/lib/roast/dsl/config_context.rbi +11 -0
- data/sorbet/rbi/shims/lib/roast/dsl/workflow_execution_context.rbi +11 -0
- data/sorbet/rbi/todo.rbi +7 -0
- metadata +37 -231
- data/CHANGELOG.md +0 -369
- data/examples/agent_continue/add_documentation/prompt.md +0 -5
- data/examples/agent_continue/add_error_handling/prompt.md +0 -5
- data/examples/agent_continue/analyze_codebase/prompt.md +0 -7
- data/examples/agent_continue/combined_workflow.yml +0 -24
- data/examples/agent_continue/continue_adding_features/prompt.md +0 -4
- data/examples/agent_continue/create_integration_tests/prompt.md +0 -3
- data/examples/agent_continue/document_with_context/prompt.md +0 -5
- data/examples/agent_continue/explore_api/prompt.md +0 -6
- data/examples/agent_continue/implement_client/prompt.md +0 -6
- data/examples/agent_continue/inline_workflow.yml +0 -20
- data/examples/agent_continue/refactor_code/prompt.md +0 -2
- data/examples/agent_continue/verify_changes/prompt.md +0 -6
- data/examples/agent_continue/workflow.yml +0 -27
- data/examples/agent_workflow/README.md +0 -75
- data/examples/agent_workflow/apply_refactorings/prompt.md +0 -22
- data/examples/agent_workflow/identify_code_smells/prompt.md +0 -15
- data/examples/agent_workflow/summarize_improvements/prompt.md +0 -18
- data/examples/agent_workflow/workflow.png +0 -0
- data/examples/agent_workflow/workflow.yml +0 -16
- data/examples/api_workflow/README.md +0 -85
- data/examples/api_workflow/fetch_api_data/prompt.md +0 -10
- data/examples/api_workflow/generate_report/prompt.md +0 -10
- data/examples/api_workflow/prompt.md +0 -10
- data/examples/api_workflow/transform_data/prompt.md +0 -10
- data/examples/api_workflow/workflow.png +0 -0
- data/examples/api_workflow/workflow.yml +0 -30
- data/examples/apply_diff_demo/README.md +0 -58
- data/examples/apply_diff_demo/apply_simple_change/prompt.md +0 -13
- data/examples/apply_diff_demo/create_sample_file/prompt.md +0 -11
- data/examples/apply_diff_demo/workflow.yml +0 -24
- data/examples/available_tools_demo/workflow.png +0 -0
- data/examples/bash_prototyping/README.md +0 -53
- data/examples/bash_prototyping/analyze_network/prompt.md +0 -13
- data/examples/bash_prototyping/analyze_system/prompt.md +0 -11
- data/examples/bash_prototyping/api_testing.png +0 -0
- data/examples/bash_prototyping/api_testing.yml +0 -14
- data/examples/bash_prototyping/check_processes/prompt.md +0 -11
- data/examples/bash_prototyping/generate_report/prompt.md +0 -16
- data/examples/bash_prototyping/process_json_response/prompt.md +0 -24
- data/examples/bash_prototyping/system_analysis.png +0 -0
- data/examples/bash_prototyping/system_analysis.yml +0 -14
- data/examples/bash_prototyping/test_public_api/prompt.md +0 -22
- data/examples/case_when/README.md +0 -58
- data/examples/case_when/detect_language/prompt.md +0 -16
- data/examples/case_when/workflow.png +0 -0
- data/examples/case_when/workflow.yml +0 -58
- data/examples/cmd/README.md +0 -99
- data/examples/cmd/analyze_project/prompt.md +0 -57
- data/examples/cmd/basic_demo/prompt.md +0 -48
- data/examples/cmd/basic_workflow.png +0 -0
- data/examples/cmd/basic_workflow.yml +0 -16
- data/examples/cmd/check_repository/prompt.md +0 -57
- data/examples/cmd/create_and_verify/prompt.md +0 -56
- data/examples/cmd/dev_workflow.png +0 -0
- data/examples/cmd/dev_workflow.yml +0 -26
- data/examples/cmd/explore_project/prompt.md +0 -67
- data/examples/cmd/explorer_workflow.png +0 -0
- data/examples/cmd/explorer_workflow.yml +0 -21
- data/examples/cmd/smart_tool_selection/prompt.md +0 -99
- data/examples/coding_agent_with_model.yml +0 -20
- data/examples/coding_agent_with_retries.yml +0 -30
- data/examples/conditional/README.md +0 -161
- data/examples/conditional/check_condition/prompt.md +0 -1
- data/examples/conditional/simple_workflow.png +0 -0
- data/examples/conditional/simple_workflow.yml +0 -15
- data/examples/conditional/workflow.png +0 -0
- data/examples/conditional/workflow.yml +0 -23
- data/examples/context_management_demo/README.md +0 -43
- data/examples/context_management_demo/workflow.yml +0 -42
- data/examples/direct_coerce_syntax/README.md +0 -32
- data/examples/direct_coerce_syntax/workflow.png +0 -0
- data/examples/direct_coerce_syntax/workflow.yml +0 -36
- data/examples/dot_notation/README.md +0 -37
- data/examples/dot_notation/workflow.png +0 -0
- data/examples/dot_notation/workflow.yml +0 -44
- data/examples/exit_on_error/README.md +0 -50
- data/examples/exit_on_error/analyze_lint_output/prompt.md +0 -9
- data/examples/exit_on_error/apply_fixes/prompt.md +0 -2
- data/examples/exit_on_error/workflow.png +0 -0
- data/examples/exit_on_error/workflow.yml +0 -19
- data/examples/grading/js_test_runner +0 -31
- data/examples/grading/rb_test_runner +0 -19
- data/examples/grading/run_coverage.rb +0 -54
- data/examples/grading/workflow.png +0 -0
- data/examples/grading/workflow.rb.md +0 -6
- data/examples/grading/workflow.ts+tsx.md +0 -6
- data/examples/instrumentation.rb +0 -76
- data/examples/interpolation/README.md +0 -50
- data/examples/interpolation/analyze_file/prompt.md +0 -1
- data/examples/interpolation/analyze_patterns/prompt.md +0 -27
- data/examples/interpolation/generate_report_for_js/prompt.md +0 -3
- data/examples/interpolation/generate_report_for_rb/prompt.md +0 -3
- data/examples/interpolation/sample.js +0 -48
- data/examples/interpolation/sample.rb +0 -42
- data/examples/interpolation/workflow.md +0 -1
- data/examples/interpolation/workflow.png +0 -0
- data/examples/interpolation/workflow.yml +0 -21
- data/examples/iteration/IMPLEMENTATION.md +0 -88
- data/examples/iteration/README.md +0 -68
- data/examples/iteration/analyze_complexity/prompt.md +0 -22
- data/examples/iteration/generate_recommendations/prompt.md +0 -21
- data/examples/iteration/generate_report/prompt.md +0 -129
- data/examples/iteration/implement_fix/prompt.md +0 -25
- data/examples/iteration/prioritize_issues/prompt.md +0 -24
- data/examples/iteration/prompts/analyze_file.md +0 -28
- data/examples/iteration/prompts/generate_summary.md +0 -24
- data/examples/iteration/prompts/update_report.md +0 -29
- data/examples/iteration/prompts/write_report.md +0 -22
- data/examples/iteration/read_file/prompt.md +0 -9
- data/examples/iteration/select_next_issue/prompt.md +0 -25
- data/examples/iteration/simple_workflow.md +0 -39
- data/examples/iteration/simple_workflow.yml +0 -58
- data/examples/iteration/update_fix_count/prompt.md +0 -26
- data/examples/iteration/verify_fix/prompt.md +0 -29
- data/examples/iteration/workflow.png +0 -0
- data/examples/iteration/workflow.yml +0 -42
- data/examples/json_handling/README.md +0 -32
- data/examples/json_handling/workflow.png +0 -0
- data/examples/json_handling/workflow.yml +0 -52
- data/examples/mcp/README.md +0 -223
- data/examples/mcp/analyze_changes/prompt.md +0 -8
- data/examples/mcp/analyze_issues/prompt.md +0 -4
- data/examples/mcp/analyze_schema/prompt.md +0 -4
- data/examples/mcp/check_data_quality/prompt.md +0 -5
- data/examples/mcp/check_documentation/prompt.md +0 -4
- data/examples/mcp/create_recommendations/prompt.md +0 -5
- data/examples/mcp/database_workflow.png +0 -0
- data/examples/mcp/database_workflow.yml +0 -29
- data/examples/mcp/env_demo/workflow.png +0 -0
- data/examples/mcp/env_demo/workflow.yml +0 -34
- data/examples/mcp/fetch_pr_context/prompt.md +0 -4
- data/examples/mcp/filesystem_demo/create_test_file/prompt.md +0 -2
- data/examples/mcp/filesystem_demo/list_files/prompt.md +0 -6
- data/examples/mcp/filesystem_demo/read_with_mcp/prompt.md +0 -7
- data/examples/mcp/filesystem_demo/workflow.png +0 -0
- data/examples/mcp/filesystem_demo/workflow.yml +0 -38
- data/examples/mcp/generate_insights/prompt.md +0 -4
- data/examples/mcp/generate_report/prompt.md +0 -6
- data/examples/mcp/generate_review/prompt.md +0 -16
- data/examples/mcp/github_workflow.png +0 -0
- data/examples/mcp/github_workflow.yml +0 -32
- data/examples/mcp/multi_mcp_workflow.png +0 -0
- data/examples/mcp/multi_mcp_workflow.yml +0 -58
- data/examples/mcp/post_review/prompt.md +0 -3
- data/examples/mcp/save_report/prompt.md +0 -6
- data/examples/mcp/search_issues/prompt.md +0 -2
- data/examples/mcp/summarize/prompt.md +0 -1
- data/examples/mcp/test_filesystem/prompt.md +0 -6
- data/examples/mcp/test_github/prompt.md +0 -8
- data/examples/mcp/test_read/prompt.md +0 -1
- data/examples/mcp/workflow.png +0 -0
- data/examples/mcp/workflow.yml +0 -35
- data/examples/no_model_fallback/README.md +0 -17
- data/examples/no_model_fallback/analyze_file/prompt.md +0 -1
- data/examples/no_model_fallback/analyze_patterns/prompt.md +0 -27
- data/examples/no_model_fallback/generate_report_for_md/prompt.md +0 -10
- data/examples/no_model_fallback/generate_report_for_rb/prompt.md +0 -3
- data/examples/no_model_fallback/sample.rb +0 -42
- data/examples/no_model_fallback/workflow.yml +0 -19
- data/examples/openrouter_example/README.md +0 -48
- data/examples/openrouter_example/analyze_input/prompt.md +0 -16
- data/examples/openrouter_example/generate_response/prompt.md +0 -9
- data/examples/openrouter_example/workflow.png +0 -0
- data/examples/openrouter_example/workflow.yml +0 -12
- data/examples/pre_post_processing/README.md +0 -111
- data/examples/pre_post_processing/analyze_test_file/prompt.md +0 -23
- data/examples/pre_post_processing/improve_test_coverage/prompt.md +0 -17
- data/examples/pre_post_processing/optimize_test_performance/prompt.md +0 -25
- data/examples/pre_post_processing/post_processing/aggregate_metrics/prompt.md +0 -31
- data/examples/pre_post_processing/post_processing/cleanup_environment/prompt.md +0 -28
- data/examples/pre_post_processing/post_processing/generate_summary_report/prompt.md +0 -32
- data/examples/pre_post_processing/post_processing/output.txt +0 -24
- data/examples/pre_post_processing/pre_processing/gather_baseline_metrics/prompt.md +0 -26
- data/examples/pre_post_processing/pre_processing/setup_test_environment/prompt.md +0 -11
- data/examples/pre_post_processing/validate_changes/prompt.md +0 -24
- data/examples/pre_post_processing/workflow.png +0 -0
- data/examples/pre_post_processing/workflow.yml +0 -21
- data/examples/retry/workflow.yml +0 -23
- data/examples/rspec_to_minitest/README.md +0 -68
- data/examples/rspec_to_minitest/analyze_spec/prompt.md +0 -30
- data/examples/rspec_to_minitest/create_minitest/prompt.md +0 -33
- data/examples/rspec_to_minitest/run_and_improve/prompt.md +0 -35
- data/examples/rspec_to_minitest/workflow.md +0 -10
- data/examples/rspec_to_minitest/workflow.png +0 -0
- data/examples/rspec_to_minitest/workflow.yml +0 -40
- data/examples/shared_config/README.md +0 -52
- data/examples/shared_config/example_with_shared_config/workflow.png +0 -0
- data/examples/shared_config/example_with_shared_config/workflow.yml +0 -6
- data/examples/shared_config/shared.png +0 -0
- data/examples/shared_config/shared.yml +0 -7
- data/examples/single_target_prepost/README.md +0 -36
- data/examples/single_target_prepost/post_processing/output.txt +0 -27
- data/examples/single_target_prepost/pre_processing/gather_dependencies/prompt.md +0 -11
- data/examples/single_target_prepost/workflow.png +0 -0
- data/examples/single_target_prepost/workflow.yml +0 -20
- data/examples/smart_coercion_defaults/README.md +0 -65
- data/examples/smart_coercion_defaults/workflow.png +0 -0
- data/examples/smart_coercion_defaults/workflow.yml +0 -44
- data/examples/step_configuration/README.md +0 -84
- data/examples/step_configuration/workflow.png +0 -0
- data/examples/step_configuration/workflow.yml +0 -57
- data/examples/swarm_example.yml +0 -25
- data/examples/tool_config_example/README.md +0 -109
- data/examples/tool_config_example/example_step/prompt.md +0 -42
- data/examples/tool_config_example/workflow.png +0 -0
- data/examples/tool_config_example/workflow.yml +0 -17
- data/examples/user_input/README.md +0 -90
- data/examples/user_input/funny_name/create_backstory/prompt.md +0 -10
- data/examples/user_input/funny_name/workflow.png +0 -0
- data/examples/user_input/funny_name/workflow.yml +0 -25
- data/examples/user_input/generate_summary/prompt.md +0 -11
- data/examples/user_input/simple_input_demo/workflow.png +0 -0
- data/examples/user_input/simple_input_demo/workflow.yml +0 -35
- data/examples/user_input/survey_workflow.png +0 -0
- data/examples/user_input/survey_workflow.yml +0 -71
- data/examples/user_input/welcome_message/prompt.md +0 -3
- data/examples/user_input/workflow.png +0 -0
- data/examples/user_input/workflow.yml +0 -73
- data/examples/workflow_generator/README.md +0 -27
- data/examples/workflow_generator/analyze_user_request/prompt.md +0 -34
- data/examples/workflow_generator/create_workflow_files/prompt.md +0 -32
- data/examples/workflow_generator/get_user_input/prompt.md +0 -14
- data/examples/workflow_generator/info_from_roast.rb +0 -22
- data/examples/workflow_generator/workflow.png +0 -0
- data/examples/workflow_generator/workflow.yml +0 -34
- data/package-lock.json +0 -6
- /data/sorbet/rbi/gems/{rack@2.2.17.rbi → rack@2.2.18.rbi} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc01ff6a90dbe17c735b17935bb75bcfda0ee47c0b9dbee6234292cc4f5f3799
|
4
|
+
data.tar.gz: caa21e581b5476a65c2dc8b0b7a27f1b20baf2f493260d954785724f73a3ff40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ea65bb2381627119b5740f9353b064d046e26b2769e0be36baf3f13b9696e30e6bd6332fbbf8c4305fea33d1b2bb12d81a4a56871f3793c3718e2ac8407c6ae
|
7
|
+
data.tar.gz: 23ff60c01817d64bae76bb16c0395d8cc7aa95cd621550cebc5fc6763fcf5ba8a023542bf07b49067fa9210d8f228f538b0e82159d897397d08532deece73bc4
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
roast-ai (0.4.
|
4
|
+
roast-ai (0.4.9)
|
5
5
|
activesupport (>= 7.0)
|
6
6
|
cli-kit (~> 5.0)
|
7
7
|
cli-ui (= 2.3.0)
|
@@ -167,7 +167,7 @@ GEM
|
|
167
167
|
method_source (~> 1.0)
|
168
168
|
public_suffix (6.0.2)
|
169
169
|
racc (1.8.1)
|
170
|
-
rack (2.2.
|
170
|
+
rack (2.2.19)
|
171
171
|
rainbow (3.1.1)
|
172
172
|
raix (1.0.2)
|
173
173
|
activesupport (>= 6.0)
|
@@ -185,7 +185,7 @@ GEM
|
|
185
185
|
rbs (3.9.4)
|
186
186
|
logger
|
187
187
|
regexp_parser (2.10.0)
|
188
|
-
rexml (3.4.
|
188
|
+
rexml (3.4.2)
|
189
189
|
rubocop (1.77.0)
|
190
190
|
json (~> 2.3)
|
191
191
|
language_server-protocol (~> 3.17.0.2)
|
data/README.md
CHANGED
@@ -374,20 +374,24 @@ Roast supports several types of steps:
|
|
374
374
|
```yaml
|
375
375
|
steps:
|
376
376
|
- analyze_code
|
377
|
-
-
|
377
|
+
- input:
|
378
|
+
name: get_user_feedback
|
378
379
|
prompt: "Should we proceed with the refactoring? (yes/no)"
|
379
380
|
type: confirm
|
380
|
-
-
|
381
|
+
- input:
|
382
|
+
name: review_changes
|
381
383
|
prompt: "Enter your review comments"
|
382
384
|
type: text
|
383
|
-
-
|
385
|
+
- input:
|
386
|
+
name: select_strategy
|
384
387
|
prompt: "Choose optimization strategy"
|
385
|
-
type:
|
388
|
+
type: choice
|
386
389
|
options:
|
387
390
|
- "Performance optimization"
|
388
391
|
- "Memory optimization"
|
389
392
|
- "Code clarity"
|
390
|
-
-
|
393
|
+
- input:
|
394
|
+
name: api_configuration
|
391
395
|
prompt: "Enter API key"
|
392
396
|
type: password
|
393
397
|
```
|
data/Rakefile
CHANGED
data/dsl/less_simple.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#### cmd
|
5
|
+
|
6
|
+
# Passing just the command to execute will run it and return the output
|
7
|
+
cmd <<~SHELLSTEP
|
8
|
+
echo "raw run without storing, should see me once""
|
9
|
+
SHELLSTEP
|
10
|
+
|
11
|
+
# Passing a name finds or creates an object and returns that
|
12
|
+
cmd_cog = cmd(:hello)
|
13
|
+
puts "This is our new cmd_cog named ':hello': #{cmd_cog}"
|
14
|
+
|
15
|
+
# We can set a command to run for later
|
16
|
+
cmd(:set_and_run).set("echo 'set_and_run, should see me once'")
|
17
|
+
cmd(:set_and_run).run
|
18
|
+
|
19
|
+
# Similarly, we can run immediately and then re-run later
|
20
|
+
cmd(:run_and_rerun).run("echo 'run_and_rerun, should see me twice'")
|
21
|
+
cmd(:run_and_rerun).run
|
22
|
+
|
23
|
+
#### graph
|
24
|
+
|
25
|
+
# We can open and re-open a graph, and then execute it
|
26
|
+
graph(:updatable) do |graph|
|
27
|
+
graph.node(:open_cmd) do |state|
|
28
|
+
state[:open] = cmd("echo 'From a node added in first open, should see me once'")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
graph(:updatable) do |graph|
|
33
|
+
graph.node(:reopen_cmd) do |state|
|
34
|
+
state[:reopen] = cmd("echo 'From a node added in reopen, should see me once'")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
graph(:yea).execute
|
39
|
+
|
40
|
+
# We can also just populate and execute a graph in one go by calling graph.execute in the block.
|
41
|
+
graph(:define_and_exec) do |graph|
|
42
|
+
graph.node(:hi) do |state|
|
43
|
+
state[:hi_msg] = cmd("echo 'hi msg'")
|
44
|
+
end
|
45
|
+
|
46
|
+
graph.execute
|
47
|
+
end
|
48
|
+
|
49
|
+
# We can have subgraphs, because why not
|
50
|
+
graph(:outer) do |graph|
|
51
|
+
graph.subgraph(:inner) do |subgraph|
|
52
|
+
subgraph.node(:inner_node) do |inner_state|
|
53
|
+
inner_state[:foo] = cmd("echo 'inner_state foo'")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
graph.node(:outer) do |outer_state|
|
58
|
+
outer_state[:bar] = cmd("echo 'outer_state bar'")
|
59
|
+
end
|
60
|
+
|
61
|
+
graph.execute
|
62
|
+
end
|
63
|
+
|
64
|
+
# We can specify our own edges
|
65
|
+
graph(:edges) do |graph|
|
66
|
+
graph.node(:thing1) do |state|
|
67
|
+
state[:thing1] = cmd("echo 'thing1'")
|
68
|
+
end
|
69
|
+
|
70
|
+
graph.node(:thing2) do |state|
|
71
|
+
state[:thing2] = cmd("echo 'thing2'")
|
72
|
+
end
|
73
|
+
|
74
|
+
graph.edge(from: :START, to: :thing1)
|
75
|
+
graph.edge(from: :thing1, to: :thing2)
|
76
|
+
graph.edge(from: :thing2, to: :DONE)
|
77
|
+
|
78
|
+
graph.execute
|
79
|
+
end
|
80
|
+
|
81
|
+
# We can have parallel execution
|
82
|
+
graph(:parallel) do |graph|
|
83
|
+
graph.node(:thing1) do |state|
|
84
|
+
state[:thing1] = cmd("sleep 0.5 && echo 'parallel thing1'")
|
85
|
+
end
|
86
|
+
|
87
|
+
graph.node(:thing2) do |state|
|
88
|
+
state[:thing2] = cmd("sleep 0.5 && echo 'parallel thing2'")
|
89
|
+
end
|
90
|
+
|
91
|
+
graph.edge(from: :START, to: [:thing1, :thing2])
|
92
|
+
graph.edge(from: [:thing1, :thing2], to: :DONE)
|
93
|
+
|
94
|
+
graph.execute
|
95
|
+
end
|
96
|
+
|
97
|
+
# We can have edges that are defined with a block
|
98
|
+
graph(:quantum) do |graph|
|
99
|
+
graph.node(:thing1) do |state|
|
100
|
+
state[:thing1] = cmd("echo 'quantum thing1'")
|
101
|
+
end
|
102
|
+
|
103
|
+
graph.edge(from: :START) do |_state|
|
104
|
+
:thing1
|
105
|
+
end
|
106
|
+
|
107
|
+
graph.edge(from: :thing1) do |_state|
|
108
|
+
:DONE
|
109
|
+
end
|
110
|
+
|
111
|
+
graph.execute
|
112
|
+
end
|
data/dsl/prototype.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#: self as Roast::DSL::Executor
|
5
|
+
|
6
|
+
config do
|
7
|
+
cmd(:echo) { print_all! }
|
8
|
+
end
|
9
|
+
|
10
|
+
execute do
|
11
|
+
# Anonymous cog. Added to the stack directly and given an autogenerated key in cog storage
|
12
|
+
# Use for actions you do once and forget about, don't need configuration
|
13
|
+
cmd { "touch tmp/#{SecureRandom.uuid} " }
|
14
|
+
|
15
|
+
# Named cog. Configuration for this specific instance will be looked up from config block
|
16
|
+
cmd(:echo) { "echo 'Hello World!'" }
|
17
|
+
end
|
data/dsl/simple.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: false
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
# This is a dead simple workflow that calls two shell scripts
|
7
|
-
shell <<~SHELLSTEP
|
4
|
+
# This is a dead simple workflow that calls two commands
|
5
|
+
cmd <<~CMDSTEP
|
8
6
|
echo "I have no idea what's going on"
|
9
|
-
|
10
|
-
|
7
|
+
CMDSTEP
|
8
|
+
cmd "pwd"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# How do we pass information between steps?
|
5
|
+
# Demonstrate by passing result of a command output to another step
|
6
|
+
|
7
|
+
config do
|
8
|
+
cmd(:echo) { display! }
|
9
|
+
end
|
10
|
+
|
11
|
+
execute do
|
12
|
+
cmd(:ls) { "ls -al" }
|
13
|
+
cmd(:echo) do
|
14
|
+
# TODO: this is a bespoke output object for cmd, is there a generic one we can offer
|
15
|
+
first_line = cmd(:ls).command_output.split("\n").second
|
16
|
+
"echo '#{first_line}'"
|
17
|
+
end
|
18
|
+
end
|
data/examples/README.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
These examples demonstrate various usages and features of Roast. They are automatically tested and verified by functional tests (see `test/functional/roast_examples_test.rb`).
|
2
|
+
|
3
|
+
### available_tools_demo
|
4
|
+
|
5
|
+
Demonstrates use of Roast tool implementations in LLM steps. Steps are implemented with `prompt.md` in directories that match the step name
|
6
|
+
|
7
|
+
### basic_prompt_workflow
|
8
|
+
|
9
|
+
Demonstrates using LLM steps to glean insights from a provided data file (`test/fixtures/sample_data/skateboard_orders.csv`).
|
@@ -0,0 +1 @@
|
|
1
|
+
You are a skateboard shop owner looking for insights on their business.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
name: Analyze My Business
|
2
|
+
description: Examines a CSV list of orders for insights
|
3
|
+
|
4
|
+
# Default model for all steps
|
5
|
+
model: google:gemini-2.5-flash
|
6
|
+
tools:
|
7
|
+
- Roast::Tools::ReadFile
|
8
|
+
- Roast::Tools::Grep
|
9
|
+
|
10
|
+
steps:
|
11
|
+
- Read the provided CSV files.
|
12
|
+
- "Where are most of my customers from?"
|
13
|
+
- "What is my most popular product?"
|
14
|
+
- Summarize the insights from the report.
|
data/examples/grading/README.md
CHANGED
@@ -2,30 +2,6 @@
|
|
2
2
|
|
3
3
|
This workflow acts as a senior software engineer and testing expert to evaluate the quality of test files based on best practices and guidelines.
|
4
4
|
|
5
|
-
## Prerequisites
|
6
|
-
|
7
|
-
This example uses `shadowenv` for environment management, which is specific to Shopify's development environment. If you're not using shadowenv, you'll need to adapt the commands to your own setup.
|
8
|
-
|
9
|
-
### If you're using shadowenv:
|
10
|
-
```bash
|
11
|
-
brew install shadowenv
|
12
|
-
```
|
13
|
-
|
14
|
-
### If you're NOT using shadowenv:
|
15
|
-
You'll need to modify the `run_coverage.rb` file to remove the shadowenv commands. Look for lines like:
|
16
|
-
```ruby
|
17
|
-
command = "shadowenv exec -- bundle exec ruby ..."
|
18
|
-
```
|
19
|
-
|
20
|
-
And change them to match your environment:
|
21
|
-
```ruby
|
22
|
-
# For standard Ruby/Bundler setup:
|
23
|
-
command = "bundle exec ruby ..."
|
24
|
-
|
25
|
-
# Or if you're using rbenv/rvm:
|
26
|
-
command = "ruby ..."
|
27
|
-
```
|
28
|
-
|
29
5
|
## Usage
|
30
6
|
|
31
7
|
```bash
|
@@ -52,7 +28,6 @@ Feel free to adapt this workflow to your testing environment:
|
|
52
28
|
- **Different test frameworks**: Modify `run_coverage.rb` to work with RSpec, Jest, pytest, etc.
|
53
29
|
- **Coverage tools**: Replace the coverage command with your preferred tool (SimpleCov, Istanbul, Coverage.py)
|
54
30
|
- **Grading criteria**: Adjust the prompts in each step to match your team's standards
|
55
|
-
- **Environment setup**: Remove or replace shadowenv with your environment management tool
|
56
31
|
|
57
32
|
## Example Output
|
58
33
|
|
@@ -68,4 +43,4 @@ RECOMMENDATIONS:
|
|
68
43
|
- Add edge case testing for error conditions
|
69
44
|
- Improve test descriptions for clarity
|
70
45
|
- Consider extracting common setup to helper methods
|
71
|
-
```
|
46
|
+
```
|
@@ -1,21 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class CalculateFinalGrade < Roast::Workflow::BaseStep
|
4
|
-
attr_accessor :llm_analysis
|
5
|
-
|
6
4
|
WEIGHTS = {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
readability: 0.1,
|
13
|
-
maintainability: 0.1,
|
14
|
-
effectiveness: 0.1,
|
5
|
+
test_helpers: 0.2,
|
6
|
+
mocks_and_stubs: 0.2,
|
7
|
+
readability: 0.2,
|
8
|
+
maintainability: 0.2,
|
9
|
+
effectiveness: 0.2,
|
15
10
|
}.freeze
|
16
11
|
|
17
12
|
def call
|
18
|
-
|
13
|
+
llm_analysis = workflow.output["generate_grades"]
|
14
|
+
|
19
15
|
weighted_sum = WEIGHTS.sum do |criterion, weight|
|
20
16
|
score = llm_analysis[criterion.to_s]["score"].to_f / 10.0
|
21
17
|
score * weight
|
@@ -26,7 +22,7 @@ class CalculateFinalGrade < Roast::Workflow::BaseStep
|
|
26
22
|
weighted_score: weighted_sum,
|
27
23
|
letter_grade: calculate_letter_grade(weighted_sum),
|
28
24
|
},
|
29
|
-
rubric_scores: calculate_rubric_scores,
|
25
|
+
rubric_scores: calculate_rubric_scores(llm_analysis),
|
30
26
|
}
|
31
27
|
end
|
32
28
|
|
@@ -47,10 +43,11 @@ class CalculateFinalGrade < Roast::Workflow::BaseStep
|
|
47
43
|
end
|
48
44
|
end
|
49
45
|
|
50
|
-
def calculate_rubric_scores
|
46
|
+
def calculate_rubric_scores(llm_analysis)
|
51
47
|
scores = {}
|
52
48
|
|
53
49
|
WEIGHTS.each_key do |criterion|
|
50
|
+
next 1 unless llm_analysis[criterion.to_s]
|
54
51
|
raw_score = llm_analysis[criterion.to_s]["score"].to_f
|
55
52
|
normalized_score = raw_score / 10.0
|
56
53
|
|
@@ -2,14 +2,11 @@
|
|
2
2
|
|
3
3
|
class FormatResult < Roast::Workflow::BaseStep
|
4
4
|
RUBRIC = {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
readability: { description: "Test Readability", weight: 0.1 },
|
11
|
-
maintainability: { description: "Test Maintainability", weight: 0.1 },
|
12
|
-
effectiveness: { description: "Test Effectiveness", weight: 0.1 },
|
5
|
+
test_helpers: { description: "Test Helpers Usage", weight: 0.2 },
|
6
|
+
mocks_and_stubs: { description: "Mocks and Stubs Usage", weight: 0.2 },
|
7
|
+
readability: { description: "Test Readability", weight: 0.2 },
|
8
|
+
maintainability: { description: "Test Maintainability", weight: 0.2 },
|
9
|
+
effectiveness: { description: "Test Effectiveness", weight: 0.2 },
|
13
10
|
}.freeze
|
14
11
|
|
15
12
|
def call
|
@@ -13,4 +13,3 @@ If you are told to find the dependencies of `test/services/country_db_interface_
|
|
13
13
|
then you would use the functions as explained above and ultimately respond with `<sut>app/services/country_db_interface.rb</sut>`
|
14
14
|
|
15
15
|
If the file is found at `lib/roast/workflow/workflow_initializer.rb`, respond with `<sut>lib/roast/workflow/workflow_initializer.rb</sut>` (include the lib/ prefix)
|
16
|
-
|
@@ -50,4 +50,4 @@ Once you are done understanding the custom test helpers used in the test file, a
|
|
50
50
|
|
51
51
|
Where possible, use your best judgment to make recommendations for how to fix problems that you find, but ONLY related to test helpers.
|
52
52
|
|
53
|
-
Note: You are only being used to help find problems so it is not necessary to report on correct usage of helpers or to make positive comments.
|
53
|
+
Note: You are only being used to help find problems so it is not necessary to report on correct usage of helpers or to make positive comments.
|
@@ -2,7 +2,4 @@ As a senior software engineer and testing expert, evaluate the quality of this t
|
|
2
2
|
|
3
3
|
Next I will now provide the source code of the test that we will be analyzing, and then step you through a series of analysis activities, before finally asking you to provided a final report.
|
4
4
|
|
5
|
-
|
6
|
-
# <%= file %>
|
7
|
-
<%= File.read(file) %>
|
8
|
-
</test>
|
5
|
+
# <%= file %> <%= File.read(file) %>
|
@@ -1,21 +1,13 @@
|
|
1
1
|
name: Test Grading
|
2
|
-
api_token: $(echo $OPENAI_API_KEY)
|
3
|
-
# model: anthropic:claude-opus-4
|
4
|
-
model: gpt-4.1-mini
|
5
2
|
|
6
3
|
tools:
|
7
4
|
- Roast::Tools::Grep
|
8
5
|
- Roast::Tools::ReadFile
|
9
6
|
- Roast::Tools::SearchFile
|
10
7
|
|
11
|
-
# Uncomment this to run the workflow on modified tests automatically
|
12
|
-
# each: '% cd $(git rev-parse --show-toplevel) && git status --porcelain | grep "_test\.rb" | cut -c4- | xargs realpath'
|
13
|
-
|
14
8
|
steps:
|
15
9
|
- read_dependencies
|
16
|
-
- run_coverage
|
17
10
|
-
|
18
|
-
- analyze_coverage
|
19
11
|
- verify_test_helpers
|
20
12
|
- verify_mocks_and_stubs
|
21
13
|
- generate_grades
|
@@ -23,19 +15,14 @@ steps:
|
|
23
15
|
- format_result
|
24
16
|
- generate_recommendations
|
25
17
|
|
26
|
-
# set non-default attributes for steps below
|
27
18
|
analyze_coverage:
|
28
|
-
# model: gpt-4.1-mini
|
29
19
|
json: true
|
30
|
-
|
20
|
+
|
31
21
|
generate_grades:
|
32
|
-
|
22
|
+
model: o3
|
33
23
|
json: true
|
34
24
|
|
35
25
|
generate_recommendations:
|
36
|
-
|
26
|
+
model: o3
|
37
27
|
json: true
|
38
|
-
params:
|
39
|
-
max_completion_tokens: 5_000
|
40
|
-
|
41
28
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Roast
|
5
|
+
module DSL
|
6
|
+
class Cog
|
7
|
+
class Config
|
8
|
+
attr_reader :values
|
9
|
+
|
10
|
+
def initialize(initial = {})
|
11
|
+
@values = initial
|
12
|
+
end
|
13
|
+
|
14
|
+
def merge(config_object)
|
15
|
+
self.class.new(values.merge(config_object.values))
|
16
|
+
end
|
17
|
+
|
18
|
+
# It is recommended to implement a custom config object for a nicer interface,
|
19
|
+
# but for simple cases where it would just be a key value store we provide one by default.
|
20
|
+
|
21
|
+
def []=(key, value)
|
22
|
+
@values[key] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
@values[key]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Roast
|
5
|
+
module DSL
|
6
|
+
class Cog
|
7
|
+
class Stack
|
8
|
+
delegate :map, :push, :size, :empty?, to: :@queue
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@queue = []
|
12
|
+
end
|
13
|
+
|
14
|
+
#: () -> Roast::DSL::Cog?
|
15
|
+
def pop
|
16
|
+
@queue.shift
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Roast
|
5
|
+
module DSL
|
6
|
+
class Cog
|
7
|
+
class Store
|
8
|
+
class CogAlreadyDefinedError < Roast::Error; end
|
9
|
+
|
10
|
+
delegate :[], to: :store
|
11
|
+
|
12
|
+
#: (Symbol, Roast::DSL::Cog) -> Roast::DSL::Cog
|
13
|
+
def insert(id, inst)
|
14
|
+
raise CogAlreadyDefinedError if store.key?(id)
|
15
|
+
|
16
|
+
store[id] = inst
|
17
|
+
end
|
18
|
+
|
19
|
+
#: () -> Hash[Symbol, Roast::DSL::Cog]
|
20
|
+
def store
|
21
|
+
@store ||= {}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Roast
|
5
|
+
module DSL
|
6
|
+
class Cog
|
7
|
+
class CogAlreadyRanError < StandardError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def on_create
|
11
|
+
eigen = self
|
12
|
+
proc do |instance_name = Random.uuid, &action|
|
13
|
+
#: self as Roast::DSL::WorkflowExecutionContext
|
14
|
+
add_cog_instance(instance_name, eigen.new(instance_name, action))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_config
|
19
|
+
eigen = self
|
20
|
+
proc do |cog_name = nil, &configuration|
|
21
|
+
#: self as Roast::DSL::ConfigContext
|
22
|
+
config_object = if cog_name.nil?
|
23
|
+
fetch_execution_scope(eigen)
|
24
|
+
else
|
25
|
+
fetch_or_create_cog_config(eigen, cog_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
config_object.instance_exec(&configuration) if configuration
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def config_class
|
33
|
+
@config_class ||= find_child_config_or_default
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def find_child_config_or_default
|
39
|
+
config_constant = "#{name}::Config"
|
40
|
+
const_defined?(config_constant) ? const_get(config_constant) : Cog::Config # rubocop:disable Sorbet/ConstantsFromStrings
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :name, :output
|
45
|
+
|
46
|
+
def initialize(name, cog_input_proc)
|
47
|
+
@name = name
|
48
|
+
@cog_input_proc = cog_input_proc
|
49
|
+
@finished = false
|
50
|
+
end
|
51
|
+
|
52
|
+
def run!(config, cog_execution_context)
|
53
|
+
raise CogAlreadyRanError if ran?
|
54
|
+
|
55
|
+
@config = config
|
56
|
+
@output = execute(cog_execution_context.instance_exec(&@cog_input_proc))
|
57
|
+
@finished = true
|
58
|
+
end
|
59
|
+
|
60
|
+
def ran?
|
61
|
+
@finished
|
62
|
+
end
|
63
|
+
|
64
|
+
# Inheriting cog must implement this
|
65
|
+
def execute(input)
|
66
|
+
raise NotImplementedError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|