roast-ai 0.1.0 → 0.1.2
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/cla.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +28 -0
- data/CLAUDE.md +3 -1
- data/Gemfile +0 -1
- data/Gemfile.lock +3 -4
- data/README.md +419 -5
- data/Rakefile +1 -6
- data/docs/INSTRUMENTATION.md +202 -0
- data/examples/api_workflow/README.md +85 -0
- data/examples/api_workflow/fetch_api_data/prompt.md +10 -0
- data/examples/api_workflow/generate_report/prompt.md +10 -0
- data/examples/api_workflow/prompt.md +10 -0
- data/examples/api_workflow/transform_data/prompt.md +10 -0
- data/examples/api_workflow/workflow.yml +30 -0
- data/examples/grading/format_result.rb +25 -9
- data/examples/grading/js_test_runner +31 -0
- data/examples/grading/rb_test_runner +19 -0
- data/examples/grading/read_dependencies/prompt.md +14 -0
- data/examples/grading/run_coverage.rb +2 -2
- data/examples/grading/workflow.yml +3 -12
- data/examples/instrumentation.rb +76 -0
- data/examples/rspec_to_minitest/README.md +68 -0
- data/examples/rspec_to_minitest/analyze_spec/prompt.md +30 -0
- data/examples/rspec_to_minitest/create_minitest/prompt.md +33 -0
- data/examples/rspec_to_minitest/run_and_improve/prompt.md +35 -0
- data/examples/rspec_to_minitest/workflow.md +10 -0
- data/examples/rspec_to_minitest/workflow.yml +40 -0
- data/lib/roast/helpers/function_caching_interceptor.rb +72 -8
- data/lib/roast/helpers/prompt_loader.rb +2 -0
- data/lib/roast/resources/api_resource.rb +137 -0
- data/lib/roast/resources/base_resource.rb +47 -0
- data/lib/roast/resources/directory_resource.rb +40 -0
- data/lib/roast/resources/file_resource.rb +33 -0
- data/lib/roast/resources/none_resource.rb +29 -0
- data/lib/roast/resources/url_resource.rb +63 -0
- data/lib/roast/resources.rb +100 -0
- data/lib/roast/tools/coding_agent.rb +69 -0
- data/lib/roast/tools.rb +1 -0
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/base_step.rb +21 -17
- data/lib/roast/workflow/base_workflow.rb +69 -17
- data/lib/roast/workflow/configuration.rb +83 -8
- data/lib/roast/workflow/configuration_parser.rb +218 -3
- data/lib/roast/workflow/file_state_repository.rb +156 -0
- data/lib/roast/workflow/prompt_step.rb +16 -0
- data/lib/roast/workflow/session_manager.rb +82 -0
- data/lib/roast/workflow/state_repository.rb +21 -0
- data/lib/roast/workflow/workflow_executor.rb +99 -9
- data/lib/roast/workflow.rb +4 -0
- data/lib/roast.rb +2 -5
- data/roast.gemspec +1 -1
- data/schema/workflow.json +12 -0
- metadata +34 -6
- data/.rspec +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 303226cd96dea4eb1edad783b8dd44c6457bc7ee5f639e31819800a0c5927aec
|
4
|
+
data.tar.gz: b00fa9b11708139368b0902a9992fb044397002b30323ac0aa19d8d47ada1e8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e109b56b0c3ae1c192e2e427be837c37e20ec445021fbebe3cd84570b65acbc031d1c875c9ab38be9f01a62a1e64cabcef04e8eade793dbf28994b5147f5b0cd
|
7
|
+
data.tar.gz: 8f51781fdb486a77b4e03daee346e7efd6e932e57a0c2f803a73dded9d3fc3941b27653da1b3b05664eb7b8d47169e238b5c4a32d9b64fb69ee7f278715ab1b4
|
data/.github/workflows/cla.yml
CHANGED
@@ -14,7 +14,7 @@ jobs:
|
|
14
14
|
&& !github.event.issue.pull_request.merged_at
|
15
15
|
&& contains(github.event.comment.body, 'signed')
|
16
16
|
)
|
17
|
-
|| (github.event.pull_request && !github.event.pull_request.merged)
|
17
|
+
|| (github.event.pull_request && !github.event.pull_request.merged)
|
18
18
|
steps:
|
19
19
|
- uses: Shopify/shopify-cla-action@v1
|
20
20
|
with:
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.1.2] - 2024-05-09
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
- problem with step loading using `--replay` option
|
12
|
+
- made access to `workflow.output` more robust by using hash with indifferent access
|
13
|
+
|
14
|
+
[0.1.2]: https://github.com/Shopify/roast/releases/tag/v0.1.2
|
15
|
+
|
16
|
+
## [0.1.1] - 2024-05-09
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- Initial public release of Roast, extracted from Shopify's internal AI orchestration tools
|
20
|
+
- Core workflow execution engine for structured AI interactions
|
21
|
+
- Step-based workflow definition system
|
22
|
+
- Instrumentation hooks for monitoring and debugging
|
23
|
+
- Integration with various LLM providers (via [Raix](https://github.com/OlympiaAI/raix))
|
24
|
+
- Schema validation for workflow inputs and outputs
|
25
|
+
- Command-line interface for running workflows
|
26
|
+
- Comprehensive documentation and examples
|
27
|
+
|
28
|
+
[0.1.1]: https://github.com/Shopify/roast/releases/tag/v0.1.1
|
data/CLAUDE.md
CHANGED
@@ -12,6 +12,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
12
12
|
- Run single test: `bundle exec rspec spec/path/to/test_file.rb`
|
13
13
|
- Lint: `bundle exec rubocop -A`
|
14
14
|
- Default (tests + lint): `bundle exec rake`
|
15
|
+
- Run all tests plus rubocop: `bundle exec rake`
|
15
16
|
|
16
17
|
## Tech stack
|
17
18
|
- `cli-kit` and `cli-ui` for the CLI tool
|
@@ -28,4 +29,5 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
28
29
|
- Dependencies: Prefer existing gems in the Gemfile before adding new ones
|
29
30
|
- Define class methods inside `class << self; end` declarations.
|
30
31
|
- Add runtime dependencies to `roast.gemspec`.
|
31
|
-
- Add development dependencies to `Gemfile`.
|
32
|
+
- Add development dependencies to `Gemfile`.
|
33
|
+
- Don't ever test private methods directly. Specs should test behavior, not implementation.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
roast-ai (0.1.
|
4
|
+
roast-ai (0.1.2)
|
5
5
|
activesupport (~> 8.0)
|
6
6
|
faraday-retry
|
7
7
|
json-schema
|
8
|
-
raix (
|
8
|
+
raix (~> 0.8.4)
|
9
9
|
thor (~> 1.3)
|
10
10
|
|
11
11
|
GEM
|
@@ -111,7 +111,7 @@ GEM
|
|
111
111
|
public_suffix (6.0.1)
|
112
112
|
racc (1.8.1)
|
113
113
|
rainbow (3.1.1)
|
114
|
-
raix (0.8.
|
114
|
+
raix (0.8.4)
|
115
115
|
activesupport (>= 6.0)
|
116
116
|
faraday-retry (~> 2.0)
|
117
117
|
open_router (~> 0.2)
|
@@ -185,7 +185,6 @@ DEPENDENCIES
|
|
185
185
|
pry
|
186
186
|
rake
|
187
187
|
roast-ai!
|
188
|
-
rspec
|
189
188
|
rubocop-shopify
|
190
189
|
vcr
|
191
190
|
webmock
|
data/README.md
CHANGED
@@ -1,23 +1,437 @@
|
|
1
|
-

|
2
2
|
|
3
3
|
# Roast
|
4
4
|
|
5
5
|
A convention-oriented framework for creating structured AI workflows, maintained by the Augmented Engineering team at Shopify.
|
6
6
|
|
7
7
|
## Why you should use Roast
|
8
|
-
|
8
|
+
|
9
|
+
Roast provides a structured, declarative approach to building AI workflows with:
|
10
|
+
|
11
|
+
- **Convention over configuration**: Define powerful workflows using simple YAML configuration files and prompts written in markdown (with ERB support)
|
12
|
+
- **Built-in tools**: Ready-to-use tools for file operations, search, and AI interactions
|
13
|
+
- **Ruby integration**: When prompts aren't enough, write custom steps in Ruby using a clean, extensible architecture
|
14
|
+
- **Shared context**: Each step shares its conversation transcript with its parent workflow by default
|
15
|
+
- **Step customization**: Steps can be fully configured with their own AI models and parameters.
|
16
|
+
- **Session replay**: Rerun previous sessions starting at a specified step to speed up development time
|
17
|
+
- **Parallel execution**: Run multiple steps concurrently to speed up workflow execution
|
18
|
+
- **Function caching:**: Flexibly cache the results of tool function calls to speed up workflows
|
19
|
+
- **Extensive instrumentation**: Monitor and track workflow execution, AI calls, and tool usage ([see instrumentation documentation](docs/INSTRUMENTATION.md))
|
9
20
|
|
10
21
|
## What does it look like?
|
11
|
-
|
22
|
+
|
23
|
+
Here's a simple workflow that analyzes test files:
|
24
|
+
|
25
|
+
```yaml
|
26
|
+
name: analyze_tests
|
27
|
+
# Default model for all steps
|
28
|
+
model: gpt-4o-mini
|
29
|
+
tools:
|
30
|
+
- Roast::Tools::ReadFile
|
31
|
+
- Roast::Tools::Grep
|
32
|
+
|
33
|
+
steps:
|
34
|
+
- read_test_file
|
35
|
+
- analyze_coverage
|
36
|
+
- generate_report
|
37
|
+
|
38
|
+
# Step-specific model overrides the global model
|
39
|
+
analyze_coverage:
|
40
|
+
model: gpt-4-turbo
|
41
|
+
json: true
|
42
|
+
```
|
43
|
+
|
44
|
+
Each step can have its own prompt file (e.g., `analyze_coverage/prompt.md`) and configuration. Steps can be run in parallel by nesting them in arrays:
|
45
|
+
|
46
|
+
```yaml
|
47
|
+
steps:
|
48
|
+
- prepare_data
|
49
|
+
-
|
50
|
+
- analyze_code_quality
|
51
|
+
- check_test_coverage
|
52
|
+
- verify_documentation
|
53
|
+
- generate_final_report
|
54
|
+
```
|
55
|
+
|
56
|
+
Workflows can include steps that run bash commands (wrap in `$()`) and even simple inlined prompts as a natural language string.
|
57
|
+
|
58
|
+
```yaml
|
59
|
+
steps:
|
60
|
+
- analyze_spec
|
61
|
+
- create_minitest
|
62
|
+
- run_and_improve
|
63
|
+
- $(bundle exec rubocop -A)
|
64
|
+
- Summarize the changes made to the codebase.
|
65
|
+
```
|
12
66
|
|
13
67
|
## How to use Roast
|
14
|
-
TBD
|
15
68
|
|
16
|
-
|
69
|
+
1. Create a workflow YAML file defining your steps and tools
|
70
|
+
2. Create prompt files for each step (e.g., `step_name/prompt.md`)
|
71
|
+
3. Run the workflow:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
# With a target file
|
75
|
+
roast execute workflow.yml target_file.rb
|
76
|
+
|
77
|
+
# Or for a targetless workflow (API calls, data generation, etc.)
|
78
|
+
roast execute workflow.yml
|
79
|
+
```
|
80
|
+
|
81
|
+
### Understanding Workflows
|
82
|
+
|
83
|
+
In Roast, workflows maintain a single conversation with the AI model throughout execution. Each step represents one or more user-assistant interactions within this conversation, with optional tool calls. Steps naturally build upon each other through the shared context.
|
84
|
+
|
85
|
+
#### Step Types
|
86
|
+
|
87
|
+
Roast supports several types of steps:
|
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.
|
90
|
+
```yaml
|
91
|
+
steps:
|
92
|
+
- analyze_code
|
93
|
+
```
|
94
|
+
|
95
|
+
As an alternative to a directory, you can also implement a custom step as a Ruby class, optionally extending `Roast::Workflow::BaseStep`.
|
96
|
+
|
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
|
+
|
99
|
+
|
100
|
+
2. **Parallel steps**: Groups of steps executed concurrently
|
101
|
+
```yaml
|
102
|
+
steps:
|
103
|
+
-
|
104
|
+
- analyze_code_quality
|
105
|
+
- check_test_coverage
|
106
|
+
```
|
107
|
+
|
108
|
+
3. **Command execution step**: Executes shell commands directly, just wrap in `$(expr)`
|
109
|
+
```yaml
|
110
|
+
steps:
|
111
|
+
- $(command line expr)
|
112
|
+
- rubocop: $(bundle exec rubocop -A)
|
113
|
+
```
|
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
|
+
|
116
|
+
4. **Raw prompt step**: Simple text prompts for the model without tools
|
117
|
+
```yaml
|
118
|
+
steps:
|
119
|
+
- Summarize the changes made to the codebase.
|
120
|
+
```
|
121
|
+
This creates a simple prompt-response interaction without tool calls or looping. It's detected by the presence of spaces in the step name and is useful for summarization or simple questions at the end of a workflow.
|
122
|
+
|
123
|
+
#### Data Flow Between Steps
|
124
|
+
|
125
|
+
Roast handles data flow between steps in two primary ways:
|
126
|
+
|
127
|
+
1. **Conversation Context (Implicit)**: The LLM naturally remembers the entire conversation history, including all previous prompts and responses. In most cases, this is all you need for a step to reference and build upon previous results. This is the preferred approach for most prompt-oriented workflows.
|
128
|
+
|
129
|
+
2. **Output Hash (Explicit)**: Each step's result is automatically stored in the `workflow.output` hash using the step name as the key. This programmatic access is mainly useful when:
|
130
|
+
- You need to perform non-LLM transformations on data
|
131
|
+
- You're writing custom output logic
|
132
|
+
- You need to access specific values for presentation or logging
|
133
|
+
|
134
|
+
For typical AI workflows, the continuous conversation history provides seamless data flow without requiring explicit access to the output hash. Steps can simply refer to previous information in their prompts, and the AI model will use its memory of the conversation to provide context-aware responses.
|
135
|
+
|
136
|
+
### Command Line Options
|
137
|
+
|
138
|
+
#### Basic Options
|
139
|
+
- `-o, --output FILE`: Save results to a file instead of outputting to STDOUT
|
140
|
+
- `-c, --concise`: Use concise output templates (exposed as a boolean flag on `workflow`)
|
141
|
+
- `-v, --verbose`: Show output from all steps as they execute
|
142
|
+
- `-r, --replay STEP_NAME`: Resume a workflow from a specific step, optionally with a specific session timestamp
|
143
|
+
|
144
|
+
#### Session Replay
|
145
|
+
|
146
|
+
The session replay feature allows you to resume workflows from specific steps, saving time during development and debugging:
|
147
|
+
|
148
|
+
```bash
|
149
|
+
# Resume from a specific step
|
150
|
+
roast execute workflow.yml -r step_name
|
151
|
+
|
152
|
+
# Resume from a specific step in a specific session
|
153
|
+
roast execute workflow.yml -r 20250507_123456_789:step_name
|
154
|
+
```
|
155
|
+
|
156
|
+
Sessions are automatically saved during workflow execution. Each step's state, including the conversation transcript and output, is persisted to a session directory. The session directories are organized by workflow name and file, with timestamps for each run.
|
157
|
+
|
158
|
+
This feature is particularly useful when:
|
159
|
+
- Debugging specific steps in a long workflow
|
160
|
+
- Iterating on prompts without rerunning the entire workflow
|
161
|
+
- Resuming after failures in long-running workflows
|
162
|
+
|
163
|
+
Sessions are stored in the `.roast/sessions/` directory in your project. Note that there is no automatic cleanup of session data, so you might want to periodically delete old sessions yourself.
|
164
|
+
|
165
|
+
#### Target Option (`-t, --target`)
|
166
|
+
|
167
|
+
The target option is highly flexible and accepts several formats:
|
168
|
+
|
169
|
+
**Single file path:**
|
170
|
+
```bash
|
171
|
+
roast execute workflow.yml -t path/to/file.rb
|
172
|
+
|
173
|
+
# is equivalent to
|
174
|
+
roast execute workflow.yml path/to/file.rb
|
175
|
+
```
|
176
|
+
|
177
|
+
**Directory path:**
|
178
|
+
```bash
|
179
|
+
roast execute workflow.yml -t path/to/directory
|
180
|
+
|
181
|
+
# Roast will run on the directory as a resource
|
182
|
+
```
|
183
|
+
|
184
|
+
**Glob patterns:**
|
185
|
+
```bash
|
186
|
+
roast execute workflow.yml -t "**/*_test.rb"
|
187
|
+
|
188
|
+
# Roast will run the workflow on each matching file
|
189
|
+
```
|
190
|
+
|
191
|
+
**URL as target:**
|
192
|
+
```bash
|
193
|
+
roast execute workflow.yml -t "https://api.example.com/data"
|
194
|
+
|
195
|
+
# Roast will run the workflow using the URL as a resource
|
196
|
+
```
|
197
|
+
|
198
|
+
**API configuration (Fetch API-style):**
|
199
|
+
```bash
|
200
|
+
roast execute workflow.yml -t '{
|
201
|
+
"url": "https://api.example.com/resource",
|
202
|
+
"options": {
|
203
|
+
"method": "POST",
|
204
|
+
"headers": {
|
205
|
+
"Content-Type": "application/json",
|
206
|
+
"Authorization": "Bearer ${API_TOKEN}"
|
207
|
+
},
|
208
|
+
"body": {
|
209
|
+
"query": "search term",
|
210
|
+
"limit": 10
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}'
|
214
|
+
|
215
|
+
# Roast will recognize this as an API configuration with Fetch API-style format
|
216
|
+
```
|
217
|
+
|
218
|
+
**Shell command execution with $(...):**
|
219
|
+
```bash
|
220
|
+
roast execute workflow.yml -t "$(find . -name '*.rb' -mtime -1)"
|
221
|
+
|
222
|
+
# Roast will run the workflow on each file returned (expects one per line)
|
223
|
+
```
|
224
|
+
|
225
|
+
**Git integration examples:**
|
226
|
+
```bash
|
227
|
+
# Process changed test files
|
228
|
+
roast execute workflow.yml -t "$(git diff --name-only HEAD | grep _test.rb)"
|
229
|
+
|
230
|
+
# Process staged files
|
231
|
+
roast execute workflow.yml -t "$(git diff --cached --name-only)"
|
232
|
+
```
|
233
|
+
|
234
|
+
#### Targetless Workflows
|
235
|
+
|
236
|
+
Roast also supports workflows that don't operate on a specific pre-defined set of target files:
|
237
|
+
|
238
|
+
**API-driven workflows:**
|
239
|
+
```yaml
|
240
|
+
name: API Integration Workflow
|
241
|
+
tools:
|
242
|
+
- Roast::Tools::ReadFile
|
243
|
+
- Roast::Tools::WriteFile
|
244
|
+
|
245
|
+
# Dynamic API token using shell command
|
246
|
+
api_token: $(cat ~/.my_token)
|
247
|
+
|
248
|
+
# Option 1: Use a targetless workflow with API logic in steps
|
249
|
+
steps:
|
250
|
+
- fetch_api_data # Step will make API calls
|
251
|
+
- transform_data
|
252
|
+
- generate_report
|
253
|
+
|
254
|
+
# Option 2: Specify an API target directly in the workflow
|
255
|
+
target: '{
|
256
|
+
"url": "https://api.example.com/resource",
|
257
|
+
"options": {
|
258
|
+
"method": "GET",
|
259
|
+
"headers": {
|
260
|
+
"Authorization": "Bearer ${API_TOKEN}"
|
261
|
+
}
|
262
|
+
}
|
263
|
+
}'
|
264
|
+
|
265
|
+
steps:
|
266
|
+
- process_api_response
|
267
|
+
- generate_report
|
268
|
+
```
|
269
|
+
|
270
|
+
**Data generation workflows:**
|
271
|
+
```yaml
|
272
|
+
name: Generate Documentation
|
273
|
+
tools:
|
274
|
+
- Roast::Tools::WriteFile
|
275
|
+
steps:
|
276
|
+
- generate_outline
|
277
|
+
- write_documentation
|
278
|
+
- create_examples
|
279
|
+
```
|
280
|
+
|
281
|
+
These targetless workflows are ideal for:
|
282
|
+
- API integrations
|
283
|
+
- Content generation
|
284
|
+
- Report creation
|
285
|
+
- Interactive tools
|
286
|
+
- Scheduled automation tasks
|
287
|
+
|
288
|
+
#### Global Model Configuration
|
289
|
+
|
290
|
+
You can set a default model for all steps in your workflow by specifying the `model` parameter at the top level:
|
291
|
+
|
292
|
+
```yaml
|
293
|
+
name: My Workflow
|
294
|
+
model: gpt-4o-mini # Will be used for all steps unless overridden
|
295
|
+
```
|
296
|
+
|
297
|
+
Individual steps can override this setting with their own model parameter:
|
298
|
+
|
299
|
+
```yaml
|
300
|
+
analyze_data:
|
301
|
+
model: anthropic:claude-3-haiku # Takes precedence over the global model
|
302
|
+
```
|
303
|
+
|
304
|
+
#### Dynamic API Tokens
|
305
|
+
|
306
|
+
Roast allows you to dynamically fetch API tokens using shell commands directly in your workflow configuration:
|
307
|
+
|
308
|
+
```yaml
|
309
|
+
# This will execute the shell command and use the result as the API token
|
310
|
+
api_token: $(print-token --key)
|
311
|
+
|
312
|
+
# Or a simpler example for demonstration:
|
313
|
+
api_token: $(echo $OPENAI_API_KEY)
|
314
|
+
```
|
315
|
+
|
316
|
+
This makes it easy to use environment-specific tokens without hardcoding credentials, especially useful in development environments or CI/CD pipelines.
|
317
|
+
|
318
|
+
### Template Output with ERB
|
319
|
+
|
320
|
+
Each step can have an `output.txt` file that uses ERB templating to format the final output. This allows you to customize how the AI's response is processed and displayed.
|
321
|
+
|
322
|
+
Example `step_name/output.txt`:
|
323
|
+
```erb
|
324
|
+
<% if workflow.verbose %>
|
325
|
+
Detailed Analysis:
|
326
|
+
<%= response %>
|
327
|
+
<% else %>
|
328
|
+
Summary: <%= response.lines.first %>
|
329
|
+
<% end %>
|
330
|
+
|
331
|
+
Files analyzed: <%= workflow.file %>
|
332
|
+
Status: <%= workflow.output['status'] || 'completed' %>
|
333
|
+
```
|
334
|
+
|
335
|
+
This is an example of where the `workflow.output` hash is useful - formatting output for display based on data from previous steps.
|
336
|
+
|
337
|
+
Available in templates:
|
338
|
+
- `response`: The AI's response for this step
|
339
|
+
- `workflow`: Access to the workflow object
|
340
|
+
- `workflow.output`: The shared hash containing results from all steps when you need programmatic access
|
341
|
+
- `workflow.file`: Current file being processed (or `nil` for targetless workflows)
|
342
|
+
- All workflow configuration options
|
343
|
+
|
344
|
+
For most workflows, you'll mainly use `response` to access the current step's results. The `workflow.output` hash becomes valuable when you need to reference specific data points from previous steps in your templates or for conditional display logic.
|
345
|
+
|
346
|
+
## Advanced Features
|
347
|
+
|
348
|
+
### Instrumentation
|
349
|
+
|
350
|
+
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).
|
351
|
+
|
352
|
+
### Custom Tools
|
353
|
+
|
354
|
+
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):
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
# .roast/initializers/tools/git_analyzer.rb
|
358
|
+
module MyProject
|
359
|
+
module Tools
|
360
|
+
module GitAnalyzer
|
361
|
+
extend self
|
362
|
+
|
363
|
+
def self.included(base)
|
364
|
+
base.class_eval do
|
365
|
+
function(
|
366
|
+
:analyze_commit,
|
367
|
+
"Analyze a git commit for code quality and changes",
|
368
|
+
commit_sha: { type: "string", description: "The SHA of the commit to analyze" },
|
369
|
+
include_diff: { type: "boolean", description: "Include the full diff in the analysis", default: false }
|
370
|
+
) do |params|
|
371
|
+
GitAnalyzer.call(params[:commit_sha], params[:include_diff])
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def call(commit_sha, include_diff = false)
|
377
|
+
Roast::Helpers::Logger.info("🔍 Analyzing commit: #{commit_sha}\n")
|
378
|
+
|
379
|
+
# Your implementation here
|
380
|
+
commit_info = `git show #{commit_sha} --stat`
|
381
|
+
commit_info += "\n\n" + `git show #{commit_sha}` if include_diff
|
382
|
+
|
383
|
+
commit_info
|
384
|
+
rescue StandardError => e
|
385
|
+
"Error analyzing commit: #{e.message}".tap do |error_message|
|
386
|
+
Roast::Helpers::Logger.error(error_message + "\n")
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
```
|
393
|
+
|
394
|
+
Then include your tool in the workflow:
|
395
|
+
|
396
|
+
```yaml
|
397
|
+
tools:
|
398
|
+
- MyProject::Tools::GitAnalyzer
|
399
|
+
```
|
400
|
+
|
401
|
+
The tool will be available to the AI model during workflow execution, and it can call `analyze_commit` with the appropriate parameters.
|
402
|
+
|
403
|
+
### Project-specific Configuration
|
404
|
+
|
405
|
+
You can extend Roast with project-specific configuration by creating initializers in `.roast/initializers/`. These are automatically loaded when workflows run, allowing you to:
|
406
|
+
|
407
|
+
- Add custom instrumentation
|
408
|
+
- Configure monitoring and metrics
|
409
|
+
- Set up project-specific tools
|
410
|
+
- Customize workflow behavior
|
411
|
+
|
412
|
+
Example structure:
|
17
413
|
```
|
414
|
+
your-project/
|
415
|
+
├── .roast/
|
416
|
+
│ └── initializers/
|
417
|
+
│ ├── metrics.rb
|
418
|
+
│ ├── logging.rb
|
419
|
+
│ └── custom_tools.rb
|
420
|
+
└── ...
|
421
|
+
```
|
422
|
+
|
423
|
+
## Installation
|
424
|
+
|
425
|
+
```bash
|
18
426
|
$ gem install roast
|
19
427
|
```
|
20
428
|
|
429
|
+
Or add to your Gemfile:
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
gem 'roast'
|
433
|
+
```
|
434
|
+
|
21
435
|
## Development
|
22
436
|
|
23
437
|
After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake` to run the tests and linter. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
|
-
require "rspec/core/rake_task"
|
5
4
|
require "rubocop/rake_task"
|
6
5
|
require "rake/testtask"
|
7
6
|
|
8
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
-
t.pattern = "spec/**/*_spec.rb"
|
10
|
-
end
|
11
|
-
|
12
7
|
Rake::TestTask.new(:minitest) do |t|
|
13
8
|
t.libs << "test"
|
14
9
|
t.libs << "lib"
|
15
10
|
t.test_files = FileList["test/**/*_test.rb"]
|
16
11
|
end
|
17
12
|
|
18
|
-
task test: [:
|
13
|
+
task test: [:minitest]
|
19
14
|
|
20
15
|
RuboCop::RakeTask.new do |task|
|
21
16
|
task.options = ["--autocorrect"]
|