roast-ai 0.4.2 → 0.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1822868d0357ade29fdbdd3feab6a1beff23ef97621de9e1a9cacee366d5897
4
- data.tar.gz: 00b9aff47853dc8f1f4ffa89bf571975fbe414632909b682fe6caab4e64bee51
3
+ metadata.gz: 90d715c7be58b0ec9d6325f0eafd0b234d8bcf51fa3151c5830717dac034fdb5
4
+ data.tar.gz: d52615bc873667aaf3dc22a29c59b4ae0f6f1dd25af3addaaa4c8ad23eaa7cb4
5
5
  SHA512:
6
- metadata.gz: 95c32a5e010460dfe2e584c7b0ba8b7d617dc965210fc00343bd2c1f647c847f3be41be0bb07a951a41b5aa1447c770b36f4eba97985543f510938044e85453b
7
- data.tar.gz: d221ec8fba42b7187ae30fa4171e2700a7b81b1092693f9fdf1f168a37b6318482f5be8cf3f1be4e8650fe7a56d87ef2a0f93fea13f633e24c95734c285fd75b
6
+ metadata.gz: 80796feab187127b4815af1d6120f5370724e817c55ecc240b2f5c58c39faf63c2e7ccb65ebc58c427a09debea7c26fc2ba26a044450e8696901a5da9aaba4b9
7
+ data.tar.gz: fa9791f7148cad5177f756705eab8778f3925183f734537b5732d712513be494c7124a530e065b5ed40765c967361fd6d4a1ee62897b0ab34db334588f2dfb78
data/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ 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.4.3] - 2025-07-10
9
+
10
+ ### Changed
11
+ - **Updated to raix-openai-eight gem** - Upgraded from `raix` to `raix-openai-eight` gem which supports OpenAI Ruby client v8.1
12
+
8
13
  ## [0.4.2] - 2025-06-20
9
14
 
10
15
  ### Added
data/Gemfile.lock CHANGED
@@ -1,15 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- roast-ai (0.4.2)
4
+ roast-ai (0.4.4)
5
5
  activesupport (>= 7.0)
6
6
  cli-kit (~> 5.0)
7
7
  cli-ui (= 2.3.0)
8
8
  diff-lcs (~> 1.5)
9
- faraday-retry
10
9
  json-schema
11
10
  open_router (~> 0.3)
12
- raix (~> 1.0)
11
+ raix (~> 1.0.2)
13
12
  ruby-graphviz (~> 1.2)
14
13
  sqlite3 (~> 2.6)
15
14
  thor (~> 1.3)
@@ -93,13 +92,13 @@ GEM
93
92
  net-http (>= 0.5.0)
94
93
  faraday-retry (2.3.2)
95
94
  faraday (~> 2.0)
96
- fast-mcp-annotations (1.5.2)
95
+ fast-mcp-annotations (1.5.3)
97
96
  addressable (~> 2.8)
98
97
  base64
99
98
  dry-schema (~> 1.14)
100
99
  json (~> 2.0)
101
100
  mime-types (~> 3.4)
102
- rack (~> 3.1)
101
+ rack (< 3)
103
102
  ffi (1.17.2-arm64-darwin)
104
103
  ffi (1.17.2-x86_64-linux-gnu)
105
104
  formatador (1.1.0)
@@ -165,14 +164,14 @@ GEM
165
164
  method_source (~> 1.0)
166
165
  public_suffix (6.0.2)
167
166
  racc (1.8.1)
168
- rack (3.1.16)
167
+ rack (2.2.17)
169
168
  rainbow (3.1.1)
170
- raix (1.0.1)
169
+ raix (1.0.2)
171
170
  activesupport (>= 6.0)
172
171
  faraday-retry (~> 2.0)
173
172
  open_router (~> 0.2)
174
173
  ostruct
175
- ruby-openai (~> 7)
174
+ ruby-openai (~> 8.1)
176
175
  rake (13.3.0)
177
176
  rb-fsevent (0.11.2)
178
177
  rb-inotify (0.11.1)
@@ -197,7 +196,7 @@ GEM
197
196
  rubocop (~> 1.62)
198
197
  ruby-graphviz (1.2.5)
199
198
  rexml
200
- ruby-openai (7.4.0)
199
+ ruby-openai (8.1.0)
201
200
  event_stream_parser (>= 0.3.0, < 2.0.0)
202
201
  faraday (>= 1)
203
202
  faraday-multipart (>= 1)
@@ -205,9 +204,9 @@ GEM
205
204
  ruby2_keywords (0.0.5)
206
205
  securerandom (0.4.1)
207
206
  shellany (0.0.1)
208
- sqlite3 (2.6.0-arm64-darwin)
209
- sqlite3 (2.6.0-x86_64-linux-gnu)
210
- thor (1.3.2)
207
+ sqlite3 (2.7.0-arm64-darwin)
208
+ sqlite3 (2.7.0-x86_64-linux-gnu)
209
+ thor (1.4.0)
211
210
  tzinfo (2.0.6)
212
211
  concurrent-ruby (~> 1.0)
213
212
  unicode-display_width (3.1.4)
data/README.md CHANGED
@@ -279,35 +279,126 @@ Roast supports several types of steps:
279
279
  ```
280
280
  Agent steps are prefixed with `^` and send the prompt content directly to the CodingAgent tool without LLM translation. This is useful when you want to give precise instructions to a coding agent without the intermediate interpretation layer. Agent steps support both file-based prompts (`fix_linting_errors/prompt.md`) and inline prompts (text with spaces).
281
281
 
282
- 9. **Input step**: Interactive prompts for user input during workflow execution
282
+ **Session continuity for agent steps:**
283
+
284
+ Agent steps support two options for maintaining Claude context across steps:
285
+
286
+ 1. **`continue: true`** - Continues from the immediately previous Claude Code session (note, if multiple Claude Code sessions are being run in parallel in the same working directory, this might not be the previous Claude Code session from this workflow)
287
+ 2. **`resume: step_name`** - Resumes from a specific earlier step's Claude Code session
288
+
289
+ **Continue option:**
290
+
291
+ The `continue` option allows sequential agent steps to maintain a continuous conversation:
292
+
283
293
  ```yaml
284
294
  steps:
285
- - analyze_code
286
- - get_user_feedback:
287
- prompt: "Should we proceed with the refactoring? (yes/no)"
288
- type: confirm
289
- - review_changes:
290
- prompt: "Enter your review comments"
291
- type: text
292
- - select_strategy:
293
- prompt: "Choose optimization strategy"
294
- type: select
295
- options:
296
- - "Performance optimization"
297
- - "Memory optimization"
298
- - "Code clarity"
299
- - api_configuration:
300
- prompt: "Enter API key"
301
- type: password
295
+ - ^analyze_codebase
296
+ - ^implement_feature
297
+ - ^add_tests
298
+
299
+ # Configuration
300
+ analyze_codebase:
301
+ continue: false # Start fresh (default)
302
+
303
+ implement_feature:
304
+ continue: true # Continue from immediately previous analyze_codebase step
305
+
306
+ add_tests:
307
+ continue: true # Continue from immediately previous implement_feature step
302
308
  ```
303
309
 
304
- Input steps pause workflow execution to collect user input. They support several types:
305
- - `text`: Free-form text input (default if type not specified)
306
- - `confirm`: Yes/No confirmation prompts
307
- - `select`: Choice from a list of options
308
- - `password`: Masked input for sensitive data
310
+ **Resume functionality for agent steps:**
311
+
312
+ Agent steps can resume from specific previous Claude Code sessions:
309
313
 
310
- The user's input is stored in the workflow output using the step name as the key and can be accessed in subsequent steps via interpolation (e.g., `{{output.get_user_feedback}}`).
314
+ ```yaml
315
+ steps:
316
+ - ^analyze_codebase
317
+ - ^implement_feature
318
+ - ^polish_implementation
319
+
320
+ # Configuration
321
+ analyze_codebase:
322
+ continue: false # Start fresh
323
+
324
+ implement_feature:
325
+ continue: true # Continue from previous conversation
326
+
327
+ polish_implementation:
328
+ resume: analyze_codebase # Resume from a specific step's session not the immediately previous one
329
+ ```
330
+
331
+ Note: Session IDs are only available when the CodingAgent is configured to output JSON format (includes `--output-format stream-json` in the command). If you are using a custom CodingAgent command that does not produce JSON output, resume functionality will not be available.
332
+
333
+ If `resume` is specified but the step name given does not have CodingAgent session to resume from, the CodingAgent will start Claude Code with a fresh session.
334
+
335
+ 9. **Shell script step**: Execute shell scripts directly as workflow steps
336
+ ```yaml
337
+ steps:
338
+ - setup_environment # Executes setup_environment.sh
339
+ - run_tests # Executes run_tests.sh
340
+ - cleanup
341
+ ```
342
+
343
+ Shell script steps allow you to execute `.sh` files directly as workflow steps alongside Ruby steps and AI prompts. Scripts are automatically discovered in the same locations as other step types.
344
+
345
+ **Configuration options:**
346
+ ```yaml
347
+ # Step configuration
348
+ my_script:
349
+ json: true # Parse stdout as JSON
350
+ exit_on_error: false # Don't fail workflow on non-zero exit
351
+ env: # Custom environment variables
352
+ CUSTOM_VAR: "value"
353
+ ```
354
+
355
+ **Environment integration:** Shell scripts automatically receive workflow context:
356
+ - `ROAST_WORKFLOW_RESOURCE`: Current workflow resource
357
+ - `ROAST_STEP_NAME`: Current step name
358
+ - `ROAST_WORKFLOW_OUTPUT`: Previous step outputs as JSON
359
+
360
+ **Example script (`setup_environment.sh`):**
361
+ ```bash
362
+ #!/bin/bash
363
+ echo "Setting up environment for: $ROAST_WORKFLOW_RESOURCE"
364
+
365
+ # Create a config file that subsequent steps can use
366
+ mkdir -p tmp
367
+ echo "DATABASE_URL=sqlite://test.db" > tmp/config.env
368
+
369
+ # Output data for the workflow (available via ROAST_WORKFLOW_OUTPUT in later steps)
370
+ echo '{"status": "configured", "database": "sqlite://test.db", "config_file": "tmp/config.env"}'
371
+ ```
372
+
373
+ 10. **Input step**: Interactive prompts for user input during workflow execution
374
+ ```yaml
375
+ steps:
376
+ - analyze_code
377
+ - get_user_feedback:
378
+ prompt: "Should we proceed with the refactoring? (yes/no)"
379
+ type: confirm
380
+ - review_changes:
381
+ prompt: "Enter your review comments"
382
+ type: text
383
+ - select_strategy:
384
+ prompt: "Choose optimization strategy"
385
+ type: select
386
+ options:
387
+ - "Performance optimization"
388
+ - "Memory optimization"
389
+ - "Code clarity"
390
+ - api_configuration:
391
+ prompt: "Enter API key"
392
+ type: password
393
+ ```
394
+
395
+ Input steps pause workflow execution to collect user input. They support several types:
396
+ - `text`: Free-form text input (default if type not specified)
397
+ - `confirm`: Yes/No confirmation prompts
398
+ - `select`: Choice from a list of options
399
+ - `password`: Masked input for sensitive data
400
+
401
+ The user's input is stored in the workflow output using the step name as the key and can be accessed in subsequent steps via interpolation (e.g., `{{output.get_user_feedback}}`).
311
402
 
312
403
  #### Step Configuration
313
404
 
@@ -705,6 +796,100 @@ For most workflows, you'll mainly use `response` to access the current step's re
705
796
 
706
797
  ## Advanced Features
707
798
 
799
+ ### Workflow Metadata
800
+
801
+ Roast workflows maintain a metadata store that allows steps to share structured data beyond the standard output hash. This is particularly useful for tracking state that needs to persist across steps but shouldn't be part of the conversation context.
802
+
803
+ #### Setting Metadata
804
+
805
+ Metadata can be set by custom Ruby steps that extend `BaseStep`:
806
+
807
+ ```ruby
808
+ # workflow/analyze_codebase.rb
809
+ class AnalyzeCodebase < Roast::Workflow::BaseStep
810
+ include Roast::Helpers::MetadataAccess
811
+
812
+ def call
813
+ # Perform analysis
814
+ analysis_results = perform_deep_analysis
815
+
816
+ # Store metadata for other steps to use
817
+ workflow.metadata[name.to_s] ||= {}
818
+ workflow.metadata[name.to_s]["total_files"] = analysis_results[:file_count]
819
+ workflow.metadata[name.to_s]["complexity_score"] = analysis_results[:complexity]
820
+ workflow.metadata[name.to_s]["analysis_id"] = SecureRandom.uuid
821
+
822
+ # Return the normal output for the conversation
823
+ "Analyzed #{analysis_results[:file_count]} files with average complexity of #{analysis_results[:complexity]}"
824
+ end
825
+
826
+ private
827
+
828
+ def perform_deep_analysis
829
+ # Your analysis logic here
830
+ { file_count: 42, complexity: 7.5 }
831
+ end
832
+ end
833
+ ```
834
+
835
+ #### Accessing Metadata
836
+
837
+ Metadata from previous steps can be accessed in:
838
+
839
+ 1. **Custom Ruby steps:**
840
+ ```ruby
841
+ class GenerateReport < Roast::Workflow::BaseStep
842
+ def call
843
+ # Access metadata from a previous step
844
+ total_files = workflow.metadata.dig("analyze_codebase", "total_files")
845
+ complexity = workflow.metadata.dig("analyze_codebase", "complexity_score")
846
+
847
+ "Generated report for #{total_files} files with complexity score: #{complexity}"
848
+ end
849
+ end
850
+ ```
851
+
852
+ 2. **Workflow configuration via interpolation:**
853
+ ```yaml
854
+ steps:
855
+ - analyze_codebase
856
+ - validate_threshold
857
+ - generate_report
858
+
859
+ # Use metadata in step configuration
860
+ validate_threshold:
861
+ if: "{{metadata.analyze_codebase.complexity_score > 8.0}}"
862
+ then:
863
+ - send_alert
864
+ - create_ticket
865
+ else:
866
+ - mark_as_passed
867
+
868
+ # Pass metadata to command steps
869
+ send_alert:
870
+ $(slack-notify "High complexity detected: {{metadata.analyze_codebase.complexity_score}}")
871
+ ```
872
+
873
+ 3. **Prompt templates (ERB):**
874
+ ```erb
875
+ # In analyze_codebase/output.txt
876
+ Analysis Summary:
877
+ Files analyzed: <%= workflow.metadata.dig(name.to_s, "total_files") %>
878
+ Complexity score: <%= workflow.metadata.dig(name.to_s, "complexity_score") %>
879
+ Analysis ID: <%= workflow.metadata.dig(name.to_s, "analysis_id") %>
880
+ ```
881
+
882
+ #### Metadata Best Practices
883
+
884
+ - **Use metadata for data that shouldn't be in the conversation**
885
+ - **Don't duplicate output data:** Metadata complements the output hash, it doesn't replace it
886
+
887
+ The metadata system is particularly useful for:
888
+ - Tracking session or transaction IDs across multiple steps
889
+ - Storing configuration or state that tools need to access
890
+ - Passing data between steps without cluttering the AI conversation
891
+ - Implementing complex conditional logic based on computed values
892
+
708
893
  ### Instrumentation
709
894
 
710
895
  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).
@@ -727,11 +912,16 @@ tools:
727
912
  - yarn
728
913
  - Roast::Tools::CodingAgent: # Optional configuration
729
914
  coding_agent_command: claude --model opus -p --allowedTools "Bash, Glob, Grep, LS, Read"
915
+ model: opus # Model to use for all CodingAgent invocations
916
+ retries: 3 # Number of automatic retries on failure (default: 0)
730
917
  ```
731
918
 
732
919
  Currently supported configurations:
733
920
  - `Roast::Tools::Cmd` via `allowed_commands`: restricts which commands can be executed (defaults to: `pwd`, `find`, `ls`, `rake`, `ruby`, `dev`, `mkdir`)
734
- - `Roast::Tools::CodingAgent` via `coding_agent_command`: customizes the Claude Code CLI command used by the agent
921
+ - `Roast::Tools::CodingAgent` via:
922
+ - `coding_agent_command`: customizes the Claude Code CLI command used by the agent
923
+ - `model`: sets the model for all CodingAgent invocations (e.g., `opus`, `sonnet`)
924
+ - `retries`: number of times to automatically retry if the agent encounters an error (default: 0, no retries)
735
925
 
736
926
  ##### Cmd Tool Configuration
737
927
 
@@ -959,16 +1149,25 @@ bash(command: "ps aux | grep ruby | awk '{print $2}'")
959
1149
  Creates a specialized agent for complex coding tasks or long-running operations.
960
1150
 
961
1151
  ```ruby
1152
+ # Basic usage
1153
+ coding_agent(
1154
+ prompt: "Refactor the authentication module to use JWT tokens",
1155
+ include_context_summary: true, # Include workflow context in the agent prompt
1156
+ continue: true # Continue from previous agent session
1157
+ )
1158
+
1159
+ # With automatic retries on failure
962
1160
  coding_agent(
963
- task: "Refactor the authentication module to use JWT tokens",
964
- language: "ruby",
965
- files: ["app/models/user.rb", "app/controllers/auth_controller.rb"]
1161
+ prompt: "Implement complex feature with error handling",
1162
+ retries: 3 # Retry up to 3 times if the agent encounters errors
966
1163
  )
967
1164
  ```
968
1165
 
969
- - Delegates complex tasks to a specialized coding agent
1166
+ - Delegates complex tasks to a specialized coding agent (Claude Code)
970
1167
  - Useful for tasks that require deep code understanding or multi-step changes
971
1168
  - Can work across multiple files and languages
1169
+ - Supports automatic retries on transient failures (network issues, API errors)
1170
+ - Retries can be configured globally (see Tool Configuration) or per invocation
972
1171
 
973
1172
  ### MCP (Model Context Protocol) Tools
974
1173
 
@@ -0,0 +1,20 @@
1
+ name: CodingAgent with Model Configuration
2
+ description: |
3
+ Example workflow demonstrating how to configure the CodingAgent tool
4
+ with specific model options like opus
5
+
6
+ tools:
7
+ - Roast::Tools::CodingAgent:
8
+ model: opus
9
+ # You can also add other claude options here:
10
+ # temperature: 0.7
11
+ # max_tokens: 1000
12
+
13
+ steps:
14
+ - analyze_code: |
15
+ Analyze the Ruby code in lib/roast/tools/coding_agent.rb
16
+ and explain how the CodingAgent tool works.
17
+
18
+ - implement_feature: |
19
+ Create a simple Ruby script that demonstrates using command-line
20
+ options similar to how CodingAgent builds its commands.
@@ -0,0 +1,30 @@
1
+ name: CodingAgent with Retries Configuration
2
+ description: |
3
+ Example workflow demonstrating how to configure the CodingAgent tool
4
+ with automatic retries on failure. The retries option will automatically
5
+ retry the coding agent if it encounters an error during execution.
6
+ Note: this is not the same as running the step
7
+
8
+ tools:
9
+ - Roast::Tools::CodingAgent:
10
+ retries: 2 # Automatically retry up to 2 times on failure
11
+
12
+ steps:
13
+ # This step invokes the coding agent directly using the specified number of retries
14
+ - ^implement_a_feature: |
15
+ Create a Ruby script that demonstrates robust error handling.
16
+ The script should:
17
+ 1. Attempt to read a file that might not exist
18
+ 2. Handle any errors gracefully
19
+ 3. Log the results
20
+
21
+
22
+ # This step invokes the general workflow LLM which can in turn invoke the coding agent.
23
+ # When the general LLM invokes the coding agent, it will execute with the specified number of retries.
24
+ - add_tests: |
25
+ Add test for the feature you just implemented.
26
+ Run the tests and iterate until they all pass.
27
+ Use the CodingAgent tool to write the tests.
28
+
29
+ add_tests:
30
+ retries: 4
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roast
4
+ module Helpers
5
+ module MetadataAccess
6
+ def step_metadata(step_name = nil)
7
+ step_name ||= current_step_name
8
+ return {} unless step_name
9
+
10
+ metadata = workflow_metadata || {}
11
+ metadata[step_name] || {}
12
+ end
13
+
14
+ def set_current_step_metadata(key, value)
15
+ step_name = current_step_name
16
+ metadata = workflow_metadata
17
+
18
+ return unless step_name && metadata
19
+
20
+ metadata[step_name] ||= {}
21
+ metadata[step_name][key] = value
22
+ end
23
+
24
+ private
25
+
26
+ def workflow_metadata
27
+ metadata = Thread.current[:workflow_metadata]
28
+ Roast::Helpers::Logger.warn("MetadataAccess#workflow_metadata is not present") if metadata.nil?
29
+ metadata
30
+ end
31
+
32
+ def current_step_name
33
+ step_name = Thread.current[:current_step_name]
34
+ Roast::Helpers::Logger.warn("MetadataAccess#current_step_name is not present") if step_name.nil?
35
+ step_name
36
+ end
37
+ end
38
+ end
39
+ end
@@ -17,7 +17,7 @@ module Roast
17
17
  # output, status = TimeoutHandler.call("pwd", timeout: 10, working_directory: "/tmp")
18
18
  class TimeoutHandler
19
19
  DEFAULT_TIMEOUT = 30
20
- MAX_TIMEOUT = 300
20
+ MAX_TIMEOUT = 3600
21
21
 
22
22
  class << self
23
23
  # Execute a command with timeout using Open3 with proper process cleanup