roast-ai 0.1.6 → 0.2.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/.github/workflows/ci.yaml +1 -1
- data/CHANGELOG.md +48 -0
- data/CLAUDE.md +20 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +11 -6
- data/README.md +225 -13
- data/bin/roast +27 -0
- data/docs/INSTRUMENTATION.md +42 -1
- data/docs/ITERATION_SYNTAX.md +119 -0
- data/examples/conditional/README.md +161 -0
- data/examples/conditional/check_condition/prompt.md +1 -0
- data/examples/conditional/simple_workflow.yml +15 -0
- data/examples/conditional/workflow.yml +23 -0
- data/examples/dot_notation/README.md +37 -0
- data/examples/dot_notation/workflow.yml +44 -0
- data/examples/exit_on_error/README.md +50 -0
- data/examples/exit_on_error/analyze_lint_output/prompt.md +9 -0
- data/examples/exit_on_error/apply_fixes/prompt.md +2 -0
- data/examples/exit_on_error/workflow.yml +19 -0
- data/examples/grading/workflow.yml +5 -1
- data/examples/iteration/IMPLEMENTATION.md +88 -0
- data/examples/iteration/README.md +68 -0
- data/examples/iteration/analyze_complexity/prompt.md +22 -0
- data/examples/iteration/generate_recommendations/prompt.md +21 -0
- data/examples/iteration/generate_report/prompt.md +129 -0
- data/examples/iteration/implement_fix/prompt.md +25 -0
- data/examples/iteration/prioritize_issues/prompt.md +24 -0
- data/examples/iteration/prompts/analyze_file.md +28 -0
- data/examples/iteration/prompts/generate_summary.md +24 -0
- data/examples/iteration/prompts/update_report.md +29 -0
- data/examples/iteration/prompts/write_report.md +22 -0
- data/examples/iteration/read_file/prompt.md +9 -0
- data/examples/iteration/select_next_issue/prompt.md +25 -0
- data/examples/iteration/simple_workflow.md +39 -0
- data/examples/iteration/simple_workflow.yml +58 -0
- data/examples/iteration/update_fix_count/prompt.md +26 -0
- data/examples/iteration/verify_fix/prompt.md +29 -0
- data/examples/iteration/workflow.yml +42 -0
- data/examples/openrouter_example/workflow.yml +2 -2
- data/examples/workflow_generator/README.md +27 -0
- data/examples/workflow_generator/analyze_user_request/prompt.md +34 -0
- data/examples/workflow_generator/create_workflow_files/prompt.md +32 -0
- data/examples/workflow_generator/get_user_input/prompt.md +14 -0
- data/examples/workflow_generator/info_from_roast.rb +22 -0
- data/examples/workflow_generator/workflow.yml +35 -0
- data/lib/roast/errors.rb +9 -0
- data/lib/roast/factories/api_provider_factory.rb +61 -0
- data/lib/roast/helpers/function_caching_interceptor.rb +1 -1
- data/lib/roast/helpers/minitest_coverage_runner.rb +1 -1
- data/lib/roast/helpers/prompt_loader.rb +50 -1
- data/lib/roast/resources/base_resource.rb +7 -0
- data/lib/roast/resources.rb +6 -6
- data/lib/roast/tools/ask_user.rb +40 -0
- data/lib/roast/tools/cmd.rb +1 -1
- data/lib/roast/tools/search_file.rb +1 -1
- data/lib/roast/tools/update_files.rb +413 -0
- data/lib/roast/tools.rb +12 -1
- data/lib/roast/value_objects/api_token.rb +49 -0
- data/lib/roast/value_objects/step_name.rb +39 -0
- data/lib/roast/value_objects/workflow_path.rb +77 -0
- data/lib/roast/value_objects.rb +5 -0
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/api_configuration.rb +61 -0
- data/lib/roast/workflow/base_iteration_step.rb +165 -0
- data/lib/roast/workflow/base_step.rb +4 -24
- data/lib/roast/workflow/base_workflow.rb +76 -73
- data/lib/roast/workflow/command_executor.rb +88 -0
- data/lib/roast/workflow/conditional_executor.rb +50 -0
- data/lib/roast/workflow/conditional_step.rb +96 -0
- data/lib/roast/workflow/configuration.rb +35 -158
- data/lib/roast/workflow/configuration_loader.rb +78 -0
- data/lib/roast/workflow/configuration_parser.rb +13 -248
- data/lib/roast/workflow/context_path_resolver.rb +43 -0
- data/lib/roast/workflow/dot_access_hash.rb +198 -0
- data/lib/roast/workflow/each_step.rb +86 -0
- data/lib/roast/workflow/error_handler.rb +97 -0
- data/lib/roast/workflow/expression_utils.rb +36 -0
- data/lib/roast/workflow/file_state_repository.rb +3 -2
- data/lib/roast/workflow/interpolator.rb +34 -0
- data/lib/roast/workflow/iteration_executor.rb +85 -0
- data/lib/roast/workflow/llm_boolean_coercer.rb +55 -0
- data/lib/roast/workflow/output_handler.rb +35 -0
- data/lib/roast/workflow/output_manager.rb +77 -0
- data/lib/roast/workflow/parallel_executor.rb +49 -0
- data/lib/roast/workflow/repeat_step.rb +75 -0
- data/lib/roast/workflow/replay_handler.rb +123 -0
- data/lib/roast/workflow/resource_resolver.rb +77 -0
- data/lib/roast/workflow/session_manager.rb +6 -2
- data/lib/roast/workflow/state_manager.rb +97 -0
- data/lib/roast/workflow/step_executor_coordinator.rb +205 -0
- data/lib/roast/workflow/step_executor_factory.rb +47 -0
- data/lib/roast/workflow/step_executor_registry.rb +79 -0
- data/lib/roast/workflow/step_executors/base_step_executor.rb +23 -0
- data/lib/roast/workflow/step_executors/hash_step_executor.rb +43 -0
- data/lib/roast/workflow/step_executors/parallel_step_executor.rb +54 -0
- data/lib/roast/workflow/step_executors/string_step_executor.rb +29 -0
- data/lib/roast/workflow/step_finder.rb +97 -0
- data/lib/roast/workflow/step_loader.rb +154 -0
- data/lib/roast/workflow/step_orchestrator.rb +45 -0
- data/lib/roast/workflow/step_runner.rb +23 -0
- data/lib/roast/workflow/step_type_resolver.rb +117 -0
- data/lib/roast/workflow/workflow_context.rb +60 -0
- data/lib/roast/workflow/workflow_executor.rb +90 -209
- data/lib/roast/workflow/workflow_initializer.rb +112 -0
- data/lib/roast/workflow/workflow_runner.rb +87 -0
- data/lib/roast/workflow.rb +3 -0
- data/lib/roast.rb +96 -3
- data/roast.gemspec +3 -1
- data/schema/workflow.json +85 -0
- metadata +112 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ab27704514fc6ddfa09003464d2aa324b852379b0548619e2f0023bebe793ae
|
4
|
+
data.tar.gz: 18c0936f2b5dc2b54ef420be2ac089b8252f64a02227ab33d98db9d2e6249136
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50552385cdb280592a1e331c4a3ec5de2924fa05636af5deb742b96f2fde229e3448e61e6516e570c02a8dc0f416a3b9a3c3d884a800eb89987c90c856a0258d
|
7
|
+
data.tar.gz: 8feeb510d87e6e6256c46cbca3e13fbc65701ceb28b049452e5bea2f44815f7770e688f8422487b431a85c5f459beffadcce590e7b860cde8a1ab4ee939ff50e
|
data/.github/workflows/ci.yaml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.2.0] - 2025-05-26
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- Conditional execution support with `if` and `unless` clauses for workflow steps
|
12
|
+
- Iteration mechanisms for workflows with `repeat` and `each` constructs (resolving issue #48)
|
13
|
+
- Support for conditional repetition with `until` condition and safety limits
|
14
|
+
- Collection iteration with variable binding for processing lists of items
|
15
|
+
- State persistence for loop iterations to enable resumption after failure
|
16
|
+
- Standardized evaluation of Ruby expressions in iteration constructs using `{{}}` syntax
|
17
|
+
- Support for using bash commands, step names, and Ruby expressions in iteration conditions and collections
|
18
|
+
- Intelligent LLM response to boolean conversion with pattern-based recognition for natural language responses
|
19
|
+
- `exit_on_error` configuration option for command steps to continue workflow on failure (resolving issue #71)
|
20
|
+
- Dot notation access for workflow outputs (e.g., `workflow.output.step.field`)
|
21
|
+
- `--pause` flag for stepping through workflow execution interactively
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
- Automatically add `.gitignore` file to cache directory when created (completing issue #22)
|
25
|
+
- Load initializers before trying to load tools in case custom tools are defined in initializers (thanks @palkan)
|
26
|
+
- Fix loading of targetless workflows (thanks @palkan)
|
27
|
+
- Fix OpenRouter support (thanks @xrendan)
|
28
|
+
- API authentication error handling and model access issues
|
29
|
+
- Conditional step transcript replay regression
|
30
|
+
- DotAccessHash serialization for AI prompts
|
31
|
+
|
32
|
+
### Improved
|
33
|
+
- Enhanced search file tool logging to show full expanded paths instead of relative paths
|
34
|
+
- Major refactoring to eliminate circular dependencies and improve architecture
|
35
|
+
- Extracted command execution logic into dedicated CommandExecutor class
|
36
|
+
- Separated conditional execution from iteration logic for better SOLID compliance
|
37
|
+
- Enhanced error messages for API authentication failures
|
38
|
+
- Replaced all `require_relative` with `require` statements for consistency
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
- Refactored god objects to improve code organization and maintainability
|
42
|
+
- Improved separation of concerns between workflow components
|
43
|
+
|
44
|
+
[0.2.0]: https://github.com/Shopify/roast/compare/v0.1.7...v0.2.0
|
45
|
+
|
46
|
+
## [0.1.7] - 2024-05-16
|
47
|
+
|
48
|
+
### Added
|
49
|
+
- `UpdateFiles` tool for applying diffs/patches to multiple files at once
|
50
|
+
- Support for atomic file updates with rollback capability
|
51
|
+
- Comprehensive documentation for all built-in tools
|
52
|
+
- Enhanced README with detailed tool usage examples
|
53
|
+
|
54
|
+
``[0.1.7]: https://github.com/Shopify/roast/compare/v0.1.6...v0.1.7
|
55
|
+
|
8
56
|
## [0.1.6] - 2024-05-15
|
9
57
|
|
10
58
|
### Added
|
data/CLAUDE.md
CHANGED
@@ -12,10 +12,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
12
12
|
- Run single test: `bundle exec ruby -Itest test/path/to/test_file.rb`
|
13
13
|
- Lint: `bundle exec rubocop`
|
14
14
|
- Lint (with autocorrect, preferred): `bundle exec rubocop -A`
|
15
|
+
- Whenever you want to run the whole test suite just run `bundle exec rake` to also run linting, and note the linting errors too (most will auto correct but not all)
|
16
|
+
- **Run roast locally**: Use `bin/roast` (not `bundle exec roast` which may use the installed gem)
|
17
|
+
- Alternative: `bundle exec exe/roast`
|
15
18
|
|
16
19
|
## Tech stack
|
17
20
|
- `thor` and `cli-ui` for the CLI tool
|
18
21
|
- Testing: Use Minitest, VCR for HTTP mocking, test files named with `_test.rb` suffix
|
22
|
+
- Prefer using the more literate `test "this is a test description" do` type of testing that we get from extending ActiveSupport::TestCase over the primitive XUnit-style def test_description headings for tests
|
19
23
|
|
20
24
|
## Code Style Guidelines
|
21
25
|
|
@@ -30,6 +34,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
30
34
|
- Add runtime dependencies to `roast.gemspec`.
|
31
35
|
- Add development dependencies to `Gemfile`.
|
32
36
|
- Don't ever test private methods directly. Specs should test behavior, not implementation.
|
37
|
+
- I do not like test-specific code embedded in production code, don't ever do that
|
38
|
+
- **Do not use require_relative**
|
39
|
+
- Require statements should always be in alphabetical order
|
40
|
+
- Always leave a blank line after module includes and before the rest of the class
|
41
|
+
|
42
|
+
## Architecture Guidelines
|
43
|
+
|
44
|
+
- **Maintain proper separation of concerns**: Don't mix unrelated concepts in the same class or module
|
45
|
+
- Example: Conditional execution (if/unless) should NOT be mixed with iteration execution (each/repeat)
|
46
|
+
- Each concept should have its own executor class and be handled separately
|
47
|
+
- **Use appropriate inheritance**: Only inherit from a base class if the child truly "is-a" type of the parent
|
48
|
+
- Don't inherit just to reuse some methods - use composition instead
|
49
|
+
- **Follow Single Responsibility Principle**: Each class should have one reason to change
|
50
|
+
- IterationExecutor handles iterations (each, repeat)
|
51
|
+
- ConditionalExecutor handles conditionals (if, unless)
|
52
|
+
- Don't combine different responsibilities in one class
|
33
53
|
|
34
54
|
## Git Workflow Practices
|
35
55
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
roast-ai (0.
|
4
|
+
roast-ai (0.2.0)
|
5
5
|
activesupport (~> 8.0)
|
6
|
+
cli-ui
|
7
|
+
diff-lcs (~> 1.5)
|
6
8
|
faraday-retry
|
7
9
|
json-schema
|
8
|
-
raix (~> 0.8.
|
10
|
+
raix (~> 0.8.6)
|
9
11
|
thor (~> 1.3)
|
10
12
|
|
11
13
|
GEM
|
@@ -31,16 +33,18 @@ GEM
|
|
31
33
|
benchmark (0.4.0)
|
32
34
|
bigdecimal (3.1.9)
|
33
35
|
cgi (0.4.2)
|
36
|
+
cli-ui (2.3.1)
|
34
37
|
coderay (1.1.3)
|
35
38
|
concurrent-ruby (1.3.5)
|
36
|
-
connection_pool (2.5.
|
39
|
+
connection_pool (2.5.3)
|
37
40
|
crack (1.0.0)
|
38
41
|
bigdecimal
|
39
42
|
rexml
|
43
|
+
diff-lcs (1.6.1)
|
40
44
|
dotenv (3.1.8)
|
41
45
|
drb (2.2.1)
|
42
46
|
event_stream_parser (1.0.0)
|
43
|
-
faraday (2.13.
|
47
|
+
faraday (2.13.1)
|
44
48
|
faraday-net_http (>= 2.0, < 3.5)
|
45
49
|
json
|
46
50
|
logger
|
@@ -72,7 +76,7 @@ GEM
|
|
72
76
|
hashdiff (1.1.2)
|
73
77
|
i18n (1.14.7)
|
74
78
|
concurrent-ruby (~> 1.0)
|
75
|
-
json (2.
|
79
|
+
json (2.12.0)
|
76
80
|
json-schema (5.1.1)
|
77
81
|
addressable (~> 2.8)
|
78
82
|
bigdecimal (~> 3.1)
|
@@ -111,7 +115,7 @@ GEM
|
|
111
115
|
public_suffix (6.0.1)
|
112
116
|
racc (1.8.1)
|
113
117
|
rainbow (3.1.1)
|
114
|
-
raix (0.8.
|
118
|
+
raix (0.8.6)
|
115
119
|
activesupport (>= 6.0)
|
116
120
|
faraday-retry (~> 2.0)
|
117
121
|
open_router (~> 0.2)
|
@@ -166,6 +170,7 @@ PLATFORMS
|
|
166
170
|
|
167
171
|
DEPENDENCIES
|
168
172
|
cgi
|
173
|
+
cli-ui
|
169
174
|
dotenv
|
170
175
|
guard
|
171
176
|
guard-minitest
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ Each step can have its own prompt file (e.g., `analyze_coverage/prompt.md`) and
|
|
46
46
|
```yaml
|
47
47
|
steps:
|
48
48
|
- prepare_data
|
49
|
-
-
|
49
|
+
-
|
50
50
|
- analyze_code_quality
|
51
51
|
- check_test_coverage
|
52
52
|
- verify_documentation
|
@@ -86,21 +86,21 @@ In Roast, workflows maintain a single conversation with the AI model throughout
|
|
86
86
|
|
87
87
|
Roast supports several types of steps:
|
88
88
|
|
89
|
-
1. **Standard step**: References a directory containing at least a `prompt.md` and optional `output.txt` template. This is the most common type of step.
|
89
|
+
1. **Standard step**: References a directory containing at least a `prompt.md` and optional `output.txt` template. This is the most common type of step.
|
90
90
|
```yaml
|
91
91
|
steps:
|
92
92
|
- analyze_code
|
93
93
|
```
|
94
94
|
|
95
95
|
As an alternative to a directory, you can also implement a custom step as a Ruby class, optionally extending `Roast::Workflow::BaseStep`.
|
96
|
-
|
96
|
+
|
97
97
|
In the example given above, the script would live at `workflow/analyze_code.rb` and should contain a class named `AnalyzeCode` with an initializer that takes a workflow object as context, and a `call` method that will be invoked to run the step. The result of the `call` method will be stored in the `workflow.output` hash.
|
98
98
|
|
99
99
|
|
100
100
|
2. **Parallel steps**: Groups of steps executed concurrently
|
101
101
|
```yaml
|
102
102
|
steps:
|
103
|
-
-
|
103
|
+
-
|
104
104
|
- analyze_code_quality
|
105
105
|
- check_test_coverage
|
106
106
|
```
|
@@ -113,7 +113,72 @@ Roast supports several types of steps:
|
|
113
113
|
```
|
114
114
|
This will execute the command and store the result in the workflow output hash. Explicit key name is optional (`rubocop` in the second line of the example).
|
115
115
|
|
116
|
-
|
116
|
+
By default, commands that exit with non-zero status will halt the workflow. You can configure steps to continue on error:
|
117
|
+
```yaml
|
118
|
+
steps:
|
119
|
+
- lint_check: $(rubocop {{file}})
|
120
|
+
- fix_issues
|
121
|
+
|
122
|
+
# Step configuration
|
123
|
+
lint_check:
|
124
|
+
exit_on_error: false # Continue workflow even if command fails
|
125
|
+
```
|
126
|
+
When `exit_on_error: false`, the command output will include the exit status, allowing subsequent steps to process error information.
|
127
|
+
|
128
|
+
4. **Conditional steps**: Execute different steps based on conditions using `if/unless`
|
129
|
+
```yaml
|
130
|
+
steps:
|
131
|
+
- check_environment:
|
132
|
+
if: "{{ENV['RAILS_ENV'] == 'production'}}"
|
133
|
+
then:
|
134
|
+
- run_production_checks
|
135
|
+
- notify_team
|
136
|
+
else:
|
137
|
+
- run_development_setup
|
138
|
+
|
139
|
+
- verify_dependencies:
|
140
|
+
unless: "$(bundle check)"
|
141
|
+
then:
|
142
|
+
- bundle_install: "$(bundle install)"
|
143
|
+
```
|
144
|
+
|
145
|
+
Conditions can be:
|
146
|
+
- Ruby expressions: `if: "{{output['count'] > 5}}"`
|
147
|
+
- Bash commands: `if: "$(test -f config.yml && echo true)"` (exit code 0 = true)
|
148
|
+
- Step references: `if: "previous_step_name"` (uses the step's output)
|
149
|
+
- Direct values: `if: "true"` or `if: "false"`
|
150
|
+
|
151
|
+
5. **Iteration steps**: Loop over collections or repeat steps with conditions
|
152
|
+
```yaml
|
153
|
+
steps:
|
154
|
+
# Loop over a collection
|
155
|
+
- process_files:
|
156
|
+
each: "{{Dir.glob('**/*.rb')}}"
|
157
|
+
as: current_file
|
158
|
+
steps:
|
159
|
+
- analyze_file
|
160
|
+
- Generate a report for {{current_file}}
|
161
|
+
|
162
|
+
# Repeat until a condition is met
|
163
|
+
- improve_code:
|
164
|
+
repeat:
|
165
|
+
until: "{{output['test_pass'] == true}}"
|
166
|
+
max_iterations: 5
|
167
|
+
steps:
|
168
|
+
- run_tests
|
169
|
+
- fix_issues
|
170
|
+
```
|
171
|
+
|
172
|
+
Each loops support:
|
173
|
+
- Collections from Ruby expressions: `each: "{{[1, 2, 3]}}"`
|
174
|
+
- Command output: `each: "$(ls *.rb)"`
|
175
|
+
- Step references: `each: "file_list"`
|
176
|
+
|
177
|
+
Repeat loops support:
|
178
|
+
- Until conditions: `until: "{{condition}}"`
|
179
|
+
- Maximum iterations: `max_iterations: 10`
|
180
|
+
|
181
|
+
6. **Raw prompt step**: Simple text prompts for the model without tools
|
117
182
|
```yaml
|
118
183
|
steps:
|
119
184
|
- Summarize the changes made to the codebase.
|
@@ -139,7 +204,7 @@ Roast handles data flow between steps in three primary ways:
|
|
139
204
|
- Generate a summary for {{file}}
|
140
205
|
- result_for_{{file}}: store_results
|
141
206
|
```
|
142
|
-
|
207
|
+
|
143
208
|
Interpolation supports:
|
144
209
|
- Simple variable access: `{{file}}`, `{{resource.target}}`
|
145
210
|
- Access to step outputs: `{{output['previous_step']}}`
|
@@ -150,7 +215,7 @@ For typical AI workflows, the continuous conversation history provides seamless
|
|
150
215
|
### Command Line Options
|
151
216
|
|
152
217
|
#### Basic Options
|
153
|
-
- `-o, --output FILE`: Save results to a file instead of outputting to STDOUT
|
218
|
+
- `-o, --output FILE`: Save results to a file instead of outputting to STDOUT
|
154
219
|
- `-c, --concise`: Use concise output templates (exposed as a boolean flag on `workflow`)
|
155
220
|
- `-v, --verbose`: Show output from all steps as they execute
|
156
221
|
- `-r, --replay STEP_NAME`: Resume a workflow from a specific step, optionally with a specific session timestamp
|
@@ -241,7 +306,7 @@ roast execute workflow.yml -t "$(find . -name '*.rb' -mtime -1)"
|
|
241
306
|
# Process changed test files
|
242
307
|
roast execute workflow.yml -t "$(git diff --name-only HEAD | grep _test.rb)"
|
243
308
|
|
244
|
-
# Process staged files
|
309
|
+
# Process staged files
|
245
310
|
roast execute workflow.yml -t "$(git diff --cached --name-only)"
|
246
311
|
```
|
247
312
|
|
@@ -255,7 +320,7 @@ name: API Integration Workflow
|
|
255
320
|
tools:
|
256
321
|
- Roast::Tools::ReadFile
|
257
322
|
- Roast::Tools::WriteFile
|
258
|
-
|
323
|
+
|
259
324
|
# Dynamic API token using shell command
|
260
325
|
api_token: $(cat ~/.my_token)
|
261
326
|
|
@@ -349,7 +414,9 @@ api_provider: openrouter
|
|
349
414
|
api_token: $(echo $OPENROUTER_API_KEY)
|
350
415
|
```
|
351
416
|
|
352
|
-
|
417
|
+
|
418
|
+
This makes it easy to use environment-specific tokens without hardcoding credentials, especially useful in development environments or CI/CD pipelines. Alternatively, Roast will fall back to `OPENROUTER_API_KEY` or `OPENAI_API_KEY` environment variables based on the specified provider.
|
419
|
+
|
353
420
|
|
354
421
|
### Template Output with ERB
|
355
422
|
|
@@ -372,7 +439,7 @@ This is an example of where the `workflow.output` hash is useful - formatting ou
|
|
372
439
|
|
373
440
|
Available in templates:
|
374
441
|
- `response`: The AI's response for this step
|
375
|
-
- `workflow`: Access to the workflow object
|
442
|
+
- `workflow`: Access to the workflow object
|
376
443
|
- `workflow.output`: The shared hash containing results from all steps when you need programmatic access
|
377
444
|
- `workflow.file`: Current file being processed (or `nil` for targetless workflows)
|
378
445
|
- All workflow configuration options
|
@@ -385,6 +452,151 @@ For most workflows, you'll mainly use `response` to access the current step's re
|
|
385
452
|
|
386
453
|
Roast provides extensive instrumentation capabilities using ActiveSupport::Notifications. You can monitor workflow execution, track AI model usage, measure performance, and integrate with external monitoring systems. [Read the full instrumentation documentation](docs/INSTRUMENTATION.md).
|
387
454
|
|
455
|
+
### Built-in Tools
|
456
|
+
|
457
|
+
Roast provides several built-in tools that you can use in your workflows:
|
458
|
+
|
459
|
+
#### ReadFile
|
460
|
+
|
461
|
+
Reads the contents of a file from the filesystem.
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
# Basic usage
|
465
|
+
read_file(path: "path/to/file.txt")
|
466
|
+
|
467
|
+
# Reading a specific portion of a file
|
468
|
+
read_file(path: "path/to/large_file.txt", offset: 100, limit: 50)
|
469
|
+
```
|
470
|
+
|
471
|
+
- The `path` can be absolute or relative to the current working directory
|
472
|
+
- Use `offset` and `limit` for large files to read specific sections (line numbers)
|
473
|
+
- Returns the file content as a string
|
474
|
+
|
475
|
+
#### WriteFile
|
476
|
+
|
477
|
+
Writes content to a file, creating the file if it doesn't exist or overwriting it if it does.
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
# Basic usage
|
481
|
+
write_file(path: "output.txt", content: "This is the file content")
|
482
|
+
|
483
|
+
# With path restriction for security
|
484
|
+
write_file(
|
485
|
+
path: "output.txt",
|
486
|
+
content: "Restricted content",
|
487
|
+
restrict: "/safe/directory" # Only allows writing to files under this path
|
488
|
+
)
|
489
|
+
```
|
490
|
+
|
491
|
+
- Creates missing directories automatically
|
492
|
+
- Can restrict file operations to specific directories for security
|
493
|
+
- Returns a success message with the number of lines written
|
494
|
+
|
495
|
+
#### UpdateFiles
|
496
|
+
|
497
|
+
Applies a unified diff/patch to one or more files. Changes are applied atomically when possible.
|
498
|
+
|
499
|
+
```ruby
|
500
|
+
update_files(
|
501
|
+
diff: <<~DIFF,
|
502
|
+
--- a/file1.txt
|
503
|
+
+++ b/file1.txt
|
504
|
+
@@ -1,3 +1,4 @@
|
505
|
+
line1
|
506
|
+
+new line
|
507
|
+
line2
|
508
|
+
line3
|
509
|
+
|
510
|
+
--- a/file2.txt
|
511
|
+
+++ b/file2.txt
|
512
|
+
@@ -5,7 +5,7 @@
|
513
|
+
line5
|
514
|
+
line6
|
515
|
+
-old line7
|
516
|
+
+updated line7
|
517
|
+
line8
|
518
|
+
DIFF
|
519
|
+
base_path: "/path/to/project", # Optional, defaults to current working directory
|
520
|
+
restrict_path: "/path/to/allowed", # Optional, restricts where files can be modified
|
521
|
+
create_files: true, # Optional, defaults to true
|
522
|
+
)
|
523
|
+
```
|
524
|
+
|
525
|
+
- Accepts standard unified diff format from tools like `git diff`
|
526
|
+
- Supports multiple file changes in a single operation
|
527
|
+
- Handles file creation, deletion, and modification
|
528
|
+
- Performs atomic operations with rollback on failure
|
529
|
+
- Includes fuzzy matching to handle minor context differences
|
530
|
+
- This tool is especially useful for making targeted changes to multiple files at once
|
531
|
+
|
532
|
+
#### Grep
|
533
|
+
|
534
|
+
Searches file contents for a specific pattern using regular expressions.
|
535
|
+
|
536
|
+
```ruby
|
537
|
+
# Basic usage
|
538
|
+
grep(pattern: "function\\s+myFunction")
|
539
|
+
|
540
|
+
# With file filtering
|
541
|
+
grep(pattern: "class\\s+User", include: "*.rb")
|
542
|
+
|
543
|
+
# With directory scope
|
544
|
+
grep(pattern: "TODO:", path: "src/components")
|
545
|
+
```
|
546
|
+
|
547
|
+
- Uses regular expressions for powerful pattern matching
|
548
|
+
- Can filter by file types using the `include` parameter
|
549
|
+
- Can scope searches to specific directories with the `path` parameter
|
550
|
+
- Returns a list of files containing matches
|
551
|
+
|
552
|
+
#### SearchFile
|
553
|
+
|
554
|
+
Provides advanced file search capabilities beyond basic pattern matching.
|
555
|
+
|
556
|
+
```ruby
|
557
|
+
search_file(query: "class User", file_path: "app/models")
|
558
|
+
```
|
559
|
+
|
560
|
+
- Combines pattern matching with contextual search
|
561
|
+
- Useful for finding specific code structures or patterns
|
562
|
+
- Returns matched lines with context
|
563
|
+
|
564
|
+
#### Cmd
|
565
|
+
|
566
|
+
Executes shell commands and returns their output.
|
567
|
+
|
568
|
+
```ruby
|
569
|
+
# Execute a simple command
|
570
|
+
cmd(command: "ls -la")
|
571
|
+
|
572
|
+
# With working directory specified
|
573
|
+
cmd(command: "npm list", cwd: "/path/to/project")
|
574
|
+
|
575
|
+
# With environment variables
|
576
|
+
cmd(command: "deploy", env: { "NODE_ENV" => "production" })
|
577
|
+
```
|
578
|
+
|
579
|
+
- Provides access to shell commands for more complex operations
|
580
|
+
- Can specify working directory and environment variables
|
581
|
+
- Captures and returns command output
|
582
|
+
- Useful for integrating with existing tools and scripts
|
583
|
+
|
584
|
+
#### CodingAgent
|
585
|
+
|
586
|
+
Creates a specialized agent for complex coding tasks or long-running operations.
|
587
|
+
|
588
|
+
```ruby
|
589
|
+
coding_agent(
|
590
|
+
task: "Refactor the authentication module to use JWT tokens",
|
591
|
+
language: "ruby",
|
592
|
+
files: ["app/models/user.rb", "app/controllers/auth_controller.rb"]
|
593
|
+
)
|
594
|
+
```
|
595
|
+
|
596
|
+
- Delegates complex tasks to a specialized coding agent
|
597
|
+
- Useful for tasks that require deep code understanding or multi-step changes
|
598
|
+
- Can work across multiple files and languages
|
599
|
+
|
388
600
|
### Custom Tools
|
389
601
|
|
390
602
|
You can create your own tools using the [Raix function dispatch pattern](https://github.com/OlympiaAI/raix-rails?tab=readme-ov-file#use-of-toolsfunctions). Custom tools should be placed in `.roast/initializers/` (subdirectories are supported):
|
@@ -411,11 +623,11 @@ module MyProject
|
|
411
623
|
|
412
624
|
def call(commit_sha, include_diff = false)
|
413
625
|
Roast::Helpers::Logger.info("🔍 Analyzing commit: #{commit_sha}\n")
|
414
|
-
|
626
|
+
|
415
627
|
# Your implementation here
|
416
628
|
commit_info = `git show #{commit_sha} --stat`
|
417
629
|
commit_info += "\n\n" + `git show #{commit_sha}` if include_diff
|
418
|
-
|
630
|
+
|
419
631
|
commit_info
|
420
632
|
rescue StandardError => e
|
421
633
|
"Error analyzing commit: #{e.message}".tap do |error_message|
|
data/bin/roast
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'roast' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../.ruby-lsp/Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("roast-ai", "roast")
|
data/docs/INSTRUMENTATION.md
CHANGED
@@ -199,4 +199,45 @@ Then run:
|
|
199
199
|
roast execute test_instrumentation.yml some_file.rb
|
200
200
|
```
|
201
201
|
|
202
|
-
Your instrumentation should capture the workflow start, step execution, and workflow completion events.
|
202
|
+
Your instrumentation should capture the workflow start, step execution, and workflow completion events.
|
203
|
+
|
204
|
+
## Available Tools
|
205
|
+
|
206
|
+
Roast provides several built-in tools that you can use in your workflows:
|
207
|
+
|
208
|
+
### WriteFile Tool
|
209
|
+
|
210
|
+
Writes content to a file, creating the file if it doesn't exist or overwriting it if it does.
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
# Example usage in a prompt
|
214
|
+
write_file(path: "output.txt", content: "This is the file content")
|
215
|
+
```
|
216
|
+
|
217
|
+
### UpdateFiles Tool
|
218
|
+
|
219
|
+
Applies a unified diff/patch to one or more files. Changes are applied atomically when possible.
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
# Example usage in a prompt
|
223
|
+
update_files(diff: <<~DIFF, base_path: "/path/to/project", create_files: true)
|
224
|
+
--- a/file1.txt
|
225
|
+
+++ b/file1.txt
|
226
|
+
@@ -1,3 +1,4 @@
|
227
|
+
line1
|
228
|
+
+new line
|
229
|
+
line2
|
230
|
+
line3
|
231
|
+
|
232
|
+
--- a/file2.txt
|
233
|
+
+++ b/file2.txt
|
234
|
+
@@ -5,7 +5,7 @@
|
235
|
+
line5
|
236
|
+
line6
|
237
|
+
-old line7
|
238
|
+
+updated line7
|
239
|
+
line8
|
240
|
+
DIFF
|
241
|
+
```
|
242
|
+
|
243
|
+
This tool is especially useful for making targeted changes to multiple files at once, without having to replace entire file contents.
|