roast-ai 0.4.3 → 0.4.5

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.
Files changed (232) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +2 -0
  3. data/.github/workflows/ci.yaml +1 -0
  4. data/.gitignore +0 -26
  5. data/.rubocop.yml +13 -0
  6. data/.rubocop_todo.yml +21 -0
  7. data/CHANGELOG.md +29 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +47 -29
  10. data/bin/rubocop +27 -0
  11. data/bin/spoom +27 -0
  12. data/bin/srb +27 -0
  13. data/bin/srb-rbi +27 -0
  14. data/bin/tapioca +27 -0
  15. data/docs/INSTRUMENTATION.md +3 -3
  16. data/dsl/simple.rb +10 -0
  17. data/lib/roast/dsl/executor.rb +26 -0
  18. data/lib/roast/dsl.rb +7 -0
  19. data/lib/roast/errors.rb +1 -0
  20. data/lib/roast/factories/api_provider_factory.rb +1 -0
  21. data/lib/roast/helpers/function_caching_interceptor.rb +3 -0
  22. data/lib/roast/helpers/logger.rb +6 -9
  23. data/lib/roast/helpers/metadata_access.rb +1 -0
  24. data/lib/roast/helpers/minitest_coverage_runner.rb +1 -0
  25. data/lib/roast/helpers/path_resolver.rb +8 -18
  26. data/lib/roast/helpers/prompt_loader.rb +3 -2
  27. data/lib/roast/helpers/timeout_handler.rb +3 -5
  28. data/lib/roast/initializers.rb +1 -0
  29. data/lib/roast/resources/api_resource.rb +4 -3
  30. data/lib/roast/resources/base_resource.rb +1 -0
  31. data/lib/roast/resources/directory_resource.rb +1 -0
  32. data/lib/roast/resources/file_resource.rb +1 -0
  33. data/lib/roast/resources/none_resource.rb +1 -0
  34. data/lib/roast/resources/url_resource.rb +2 -1
  35. data/lib/roast/resources.rb +1 -2
  36. data/lib/roast/services/context_threshold_checker.rb +1 -0
  37. data/lib/roast/services/token_counting_service.rb +1 -0
  38. data/lib/roast/tools/apply_diff.rb +1 -0
  39. data/lib/roast/tools/ask_user.rb +1 -0
  40. data/lib/roast/tools/bash.rb +1 -0
  41. data/lib/roast/tools/cmd.rb +1 -0
  42. data/lib/roast/tools/coding_agent.rb +1 -0
  43. data/lib/roast/tools/context_summarizer.rb +1 -0
  44. data/lib/roast/tools/grep.rb +1 -0
  45. data/lib/roast/tools/helpers/coding_agent_message_formatter.rb +1 -0
  46. data/lib/roast/tools/read_file.rb +1 -0
  47. data/lib/roast/tools/search_file.rb +1 -0
  48. data/lib/roast/tools/swarm.rb +1 -0
  49. data/lib/roast/tools/update_files.rb +1 -0
  50. data/lib/roast/tools/write_file.rb +1 -0
  51. data/lib/roast/tools.rb +2 -0
  52. data/lib/roast/value_objects/api_token.rb +1 -0
  53. data/lib/roast/value_objects/step_name.rb +1 -0
  54. data/lib/roast/value_objects/uri_base.rb +1 -0
  55. data/lib/roast/value_objects/workflow_path.rb +1 -0
  56. data/lib/roast/value_objects.rb +1 -0
  57. data/lib/roast/version.rb +2 -1
  58. data/lib/roast/workflow/agent_step.rb +1 -0
  59. data/lib/roast/workflow/api_configuration.rb +1 -0
  60. data/lib/roast/workflow/base_iteration_step.rb +1 -0
  61. data/lib/roast/workflow/base_step.rb +1 -0
  62. data/lib/roast/workflow/base_workflow.rb +1 -0
  63. data/lib/roast/workflow/case_executor.rb +1 -0
  64. data/lib/roast/workflow/case_step.rb +1 -0
  65. data/lib/roast/workflow/command_executor.rb +1 -0
  66. data/lib/roast/workflow/conditional_executor.rb +1 -0
  67. data/lib/roast/workflow/conditional_step.rb +1 -0
  68. data/lib/roast/workflow/configuration.rb +9 -0
  69. data/lib/roast/workflow/configuration_loader.rb +4 -1
  70. data/lib/roast/workflow/context_manager.rb +1 -0
  71. data/lib/roast/workflow/context_path_resolver.rb +1 -0
  72. data/lib/roast/workflow/dot_access_hash.rb +1 -0
  73. data/lib/roast/workflow/each_step.rb +1 -0
  74. data/lib/roast/workflow/error_handler.rb +7 -1
  75. data/lib/roast/workflow/expression_evaluator.rb +1 -0
  76. data/lib/roast/workflow/expression_utils.rb +1 -0
  77. data/lib/roast/workflow/file_state_repository.rb +2 -1
  78. data/lib/roast/workflow/input_executor.rb +1 -0
  79. data/lib/roast/workflow/input_step.rb +1 -0
  80. data/lib/roast/workflow/interpolator.rb +2 -1
  81. data/lib/roast/workflow/iteration_executor.rb +1 -0
  82. data/lib/roast/workflow/llm_boolean_coercer.rb +1 -0
  83. data/lib/roast/workflow/metadata_manager.rb +1 -0
  84. data/lib/roast/workflow/output_handler.rb +1 -0
  85. data/lib/roast/workflow/output_manager.rb +1 -0
  86. data/lib/roast/workflow/parallel_executor.rb +1 -0
  87. data/lib/roast/workflow/prompt_step.rb +1 -0
  88. data/lib/roast/workflow/repeat_step.rb +1 -0
  89. data/lib/roast/workflow/replay_handler.rb +1 -0
  90. data/lib/roast/workflow/resource_resolver.rb +2 -6
  91. data/lib/roast/workflow/session_manager.rb +1 -0
  92. data/lib/roast/workflow/shell_script_step.rb +1 -0
  93. data/lib/roast/workflow/sqlite_state_repository.rb +1 -0
  94. data/lib/roast/workflow/state_manager.rb +1 -0
  95. data/lib/roast/workflow/state_repository.rb +1 -0
  96. data/lib/roast/workflow/state_repository_factory.rb +4 -2
  97. data/lib/roast/workflow/step_completion_reporter.rb +1 -0
  98. data/lib/roast/workflow/step_executor_coordinator.rb +9 -5
  99. data/lib/roast/workflow/step_executor_factory.rb +1 -0
  100. data/lib/roast/workflow/step_executor_registry.rb +2 -3
  101. data/lib/roast/workflow/step_executor_with_reporting.rb +1 -0
  102. data/lib/roast/workflow/step_executors/base_step_executor.rb +1 -0
  103. data/lib/roast/workflow/step_executors/hash_step_executor.rb +1 -0
  104. data/lib/roast/workflow/step_executors/parallel_step_executor.rb +1 -0
  105. data/lib/roast/workflow/step_executors/string_step_executor.rb +1 -0
  106. data/lib/roast/workflow/step_factory.rb +1 -0
  107. data/lib/roast/workflow/step_finder.rb +1 -0
  108. data/lib/roast/workflow/step_loader.rb +1 -0
  109. data/lib/roast/workflow/step_name_extractor.rb +1 -0
  110. data/lib/roast/workflow/step_runner.rb +1 -0
  111. data/lib/roast/workflow/step_type_resolver.rb +1 -0
  112. data/lib/roast/workflow/validation_command.rb +1 -0
  113. data/lib/roast/workflow/validator.rb +1 -0
  114. data/lib/roast/workflow/validators/base_validator.rb +1 -0
  115. data/lib/roast/workflow/validators/dependency_validator.rb +1 -0
  116. data/lib/roast/workflow/validators/linting_validator.rb +1 -0
  117. data/lib/roast/workflow/validators/schema_validator.rb +1 -0
  118. data/lib/roast/workflow/validators/step_collector.rb +1 -0
  119. data/lib/roast/workflow/validators/validation_orchestrator.rb +1 -0
  120. data/lib/roast/workflow/workflow_context.rb +1 -0
  121. data/lib/roast/workflow/workflow_execution_context.rb +1 -0
  122. data/lib/roast/workflow/workflow_executor.rb +2 -1
  123. data/lib/roast/workflow/workflow_initializer.rb +1 -0
  124. data/lib/roast/workflow/workflow_runner.rb +66 -55
  125. data/lib/roast/workflow.rb +1 -0
  126. data/lib/roast/workflow_diagram_generator.rb +3 -2
  127. data/lib/roast.rb +23 -8
  128. data/roast.gemspec +1 -1
  129. data/sorbet/config +8 -0
  130. data/sorbet/rbi/dsl/.gitattributes +1 -0
  131. data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
  132. data/sorbet/rbi/gems/.gitattributes +1 -0
  133. data/sorbet/rbi/gems/activesupport@8.0.2.rbi +19107 -0
  134. data/sorbet/rbi/gems/addressable@2.8.7.rbi +1994 -0
  135. data/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
  136. data/sorbet/rbi/gems/base64@0.3.0.rbi +545 -0
  137. data/sorbet/rbi/gems/benchmark@0.4.1.rbi +619 -0
  138. data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +62 -0
  139. data/sorbet/rbi/gems/cgi@0.5.0.rbi +2961 -0
  140. data/sorbet/rbi/gems/claude_swarm@0.1.19.rbi +568 -0
  141. data/sorbet/rbi/gems/cli-kit@5.0.1.rbi +1991 -0
  142. data/sorbet/rbi/gems/cli-ui@2.3.0.rbi +3181 -0
  143. data/sorbet/rbi/gems/coderay@1.1.3.rbi +9 -0
  144. data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +11657 -0
  145. data/sorbet/rbi/gems/connection_pool@2.5.3.rbi +9 -0
  146. data/sorbet/rbi/gems/crack@1.0.0.rbi +145 -0
  147. data/sorbet/rbi/gems/diff-lcs@1.6.2.rbi +972 -0
  148. data/sorbet/rbi/gems/dotenv@3.1.8.rbi +295 -0
  149. data/sorbet/rbi/gems/drb@2.2.3.rbi +1661 -0
  150. data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +672 -0
  151. data/sorbet/rbi/gems/dry-core@1.1.0.rbi +1894 -0
  152. data/sorbet/rbi/gems/dry-inflector@1.2.0.rbi +659 -0
  153. data/sorbet/rbi/gems/dry-initializer@3.2.0.rbi +781 -0
  154. data/sorbet/rbi/gems/dry-logic@1.6.0.rbi +1127 -0
  155. data/sorbet/rbi/gems/dry-schema@1.14.1.rbi +3727 -0
  156. data/sorbet/rbi/gems/dry-types@1.8.3.rbi +3969 -0
  157. data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  158. data/sorbet/rbi/gems/event_stream_parser@1.0.0.rbi +49 -0
  159. data/sorbet/rbi/gems/faraday-multipart@1.1.1.rbi +283 -0
  160. data/sorbet/rbi/gems/faraday-net_http@3.4.1.rbi +147 -0
  161. data/sorbet/rbi/gems/faraday-retry@2.3.2.rbi +9 -0
  162. data/sorbet/rbi/gems/faraday@2.13.1.rbi +2977 -0
  163. data/sorbet/rbi/gems/fast-mcp-annotations@1.5.3.rbi +1588 -0
  164. data/sorbet/rbi/gems/ffi@1.17.2.rbi +9 -0
  165. data/sorbet/rbi/gems/formatador@1.1.0.rbi +9 -0
  166. data/sorbet/rbi/gems/guard-compat@1.2.1.rbi +102 -0
  167. data/sorbet/rbi/gems/guard-minitest@2.4.6.rbi +402 -0
  168. data/sorbet/rbi/gems/guard@2.19.1.rbi +2283 -0
  169. data/sorbet/rbi/gems/hashdiff@1.2.0.rbi +355 -0
  170. data/sorbet/rbi/gems/i18n@1.14.7.rbi +2359 -0
  171. data/sorbet/rbi/gems/json-schema@5.1.1.rbi +1466 -0
  172. data/sorbet/rbi/gems/json@2.12.2.rbi +2051 -0
  173. data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
  174. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +9 -0
  175. data/sorbet/rbi/gems/listen@3.9.0.rbi +1206 -0
  176. data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  177. data/sorbet/rbi/gems/lumberjack@1.2.10.rbi +1830 -0
  178. data/sorbet/rbi/gems/method_source@1.1.0.rbi +9 -0
  179. data/sorbet/rbi/gems/mime-types-data@3.2025.0617.rbi +136 -0
  180. data/sorbet/rbi/gems/mime-types@3.7.0.rbi +1342 -0
  181. data/sorbet/rbi/gems/minitest-rg@5.3.0.rbi +160 -0
  182. data/sorbet/rbi/gems/minitest@5.25.5.rbi +1640 -0
  183. data/sorbet/rbi/gems/mocha@2.7.1.rbi +12 -0
  184. data/sorbet/rbi/gems/multipart-post@2.4.1.rbi +244 -0
  185. data/sorbet/rbi/gems/nenv@0.3.0.rbi +147 -0
  186. data/sorbet/rbi/gems/net-http@0.6.0.rbi +4247 -0
  187. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  188. data/sorbet/rbi/gems/notiffany@0.1.3.rbi +1079 -0
  189. data/sorbet/rbi/gems/open_router@0.3.3.rbi +230 -0
  190. data/sorbet/rbi/gems/ostruct@0.6.2.rbi +354 -0
  191. data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
  192. data/sorbet/rbi/gems/parser@3.3.8.0.rbi +5535 -0
  193. data/sorbet/rbi/gems/prism@1.4.0.rbi +41732 -0
  194. data/sorbet/rbi/gems/pry@0.15.2.rbi +9 -0
  195. data/sorbet/rbi/gems/public_suffix@6.0.2.rbi +936 -0
  196. data/sorbet/rbi/gems/racc@1.8.1.rbi +158 -0
  197. data/sorbet/rbi/gems/rack@2.2.17.rbi +5659 -0
  198. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +9 -0
  199. data/sorbet/rbi/gems/raix@1.0.2.rbi +1104 -0
  200. data/sorbet/rbi/gems/rake@13.3.0.rbi +3036 -0
  201. data/sorbet/rbi/gems/rb-fsevent@0.11.2.rbi +9 -0
  202. data/sorbet/rbi/gems/rb-inotify@0.11.1.rbi +9 -0
  203. data/sorbet/rbi/gems/rbi@0.3.6.rbi +6893 -0
  204. data/sorbet/rbi/gems/rbs@3.9.4.rbi +6978 -0
  205. data/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +9 -0
  206. data/sorbet/rbi/gems/rexml@3.4.1.rbi +5346 -0
  207. data/sorbet/rbi/gems/rubocop-ast@1.45.1.rbi +9 -0
  208. data/sorbet/rbi/gems/rubocop-shopify@2.17.1.rbi +9 -0
  209. data/sorbet/rbi/gems/rubocop@1.77.0.rbi +9 -0
  210. data/sorbet/rbi/gems/ruby-graphviz@1.2.5.rbi +1333 -0
  211. data/sorbet/rbi/gems/ruby-openai@8.1.0.rbi +758 -0
  212. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +9 -0
  213. data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +9 -0
  214. data/sorbet/rbi/gems/securerandom@0.4.1.rbi +75 -0
  215. data/sorbet/rbi/gems/shellany@0.0.1.rbi +102 -0
  216. data/sorbet/rbi/gems/spoom@1.6.3.rbi +6985 -0
  217. data/sorbet/rbi/gems/sqlite3@2.7.0.rbi +1900 -0
  218. data/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
  219. data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
  220. data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5918 -0
  221. data/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +9 -0
  222. data/sorbet/rbi/gems/unicode-emoji@4.0.4.rbi +9 -0
  223. data/sorbet/rbi/gems/uri@1.0.3.rbi +2349 -0
  224. data/sorbet/rbi/gems/vcr@6.3.1.rbi +3040 -0
  225. data/sorbet/rbi/gems/webmock@3.25.1.rbi +1792 -0
  226. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  227. data/sorbet/rbi/gems/yard@0.9.37.rbi +18492 -0
  228. data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1429 -0
  229. data/sorbet/tapioca/config.yml +13 -0
  230. data/sorbet/tapioca/require.rb +36 -0
  231. metadata +116 -5
  232. data/lib/roast/workflow/configuration_parser.rb +0 -54
@@ -1,8 +1,6 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
- require "timeout"
4
- require "open3"
5
-
6
4
  module Roast
7
5
  module Helpers
8
6
  # Shared timeout handling logic for command-based tools
@@ -29,8 +27,8 @@ module Roast
29
27
  def call(command, timeout: DEFAULT_TIMEOUT, working_directory: Dir.pwd)
30
28
  timeout = validate_timeout(timeout)
31
29
  output = ""
32
- exit_status = nil
33
- wait_thr = nil
30
+ exit_status = nil #: Integer?
31
+ wait_thr = nil #: Process::Waiter?
34
32
 
35
33
  begin
36
34
  Timeout.timeout(timeout) do
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -57,7 +58,7 @@ module Roast
57
58
  http.use_ssl = (uri.scheme == "https")
58
59
 
59
60
  # Use HEAD request to check existence
60
- request = Net::HTTP::Head.new(uri.path.empty? ? "/" : uri.path)
61
+ request = Net::HTTP::Head.new(uri.path&.empty? ? "/" : uri.path)
61
62
 
62
63
  # Add headers if present in options
63
64
  if options["headers"].is_a?(Hash)
@@ -124,8 +125,8 @@ module Roast
124
125
  # Replace environment variables in the format ${VAR_NAME}
125
126
  def process_env_vars(text)
126
127
  text.gsub(/\${([^}]+)}/) do |_match|
127
- var_name = ::Regexp.last_match(1).strip
128
- ENV.fetch(var_name, "${#{var_name}}")
128
+ var_name = ::Regexp.last_match(1)&.strip
129
+ ENV.fetch(var_name, "${#{var_name}}") unless var_name.nil?
129
130
  end
130
131
  end
131
132
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -18,7 +19,7 @@ module Roast
18
19
  http.use_ssl = (uri.scheme == "https")
19
20
 
20
21
  # Just check the head to see if the resource exists
21
- response = http.request_head(uri.path.empty? ? "/" : uri.path)
22
+ response = http.request_head(uri.path&.empty? ? "/" : uri.path)
22
23
 
23
24
  # Consider 2xx and 3xx as success
24
25
  response.code.to_i < 400
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -21,8 +22,6 @@ module Roast
21
22
  UrlResource.new(target)
22
23
  when :api
23
24
  ApiResource.new(target)
24
- when :command
25
- CommandResource.new(target)
26
25
  when :none
27
26
  NoneResource.new(target)
28
27
  else
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "cli/ui"
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "English"
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "English"
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "shellwords"
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
data/lib/roast/tools.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
5
+ # @requires_ancestor: Kernel
4
6
  module Tools
5
7
  extend self
6
8
 
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
data/lib/roast/version.rb CHANGED
@@ -1,5 +1,6 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
4
- VERSION = "0.4.3"
5
+ VERSION = "0.4.5"
5
6
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -87,6 +88,14 @@ module Roast
87
88
  @tool_configs[tool_name.to_s] || {}
88
89
  end
89
90
 
91
+ def pre_processing?
92
+ pre_processing.any?
93
+ end
94
+
95
+ def post_processing?
96
+ post_processing.any?
97
+ end
98
+
90
99
  private
91
100
 
92
101
  attr_reader :api_configuration
@@ -1,9 +1,12 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
4
5
  module Workflow
5
6
  # Handles loading and parsing of workflow configuration files
6
7
  class ConfigurationLoader
8
+ class ValidationError < StandardError; end
9
+
7
10
  class << self
8
11
  # Load configuration from a YAML file
9
12
  # @param workflow_path [String] Path to the workflow YAML file
@@ -187,7 +190,7 @@ module Roast
187
190
  message
188
191
  end.join("\n")
189
192
 
190
- raise CLI::Kit::Abort, <<~ERROR
193
+ raise ValidationError, <<~ERROR
191
194
  Workflow validation failed with #{validator.errors.size} error(s):
192
195
 
193
196
  #{error_messages}
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,10 +1,12 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
4
5
  module Workflow
5
6
  # Handles error logging and instrumentation for workflow execution
6
7
  class ErrorHandler
7
- def initialize
8
+ def initialize(workflow = nil)
9
+ @workflow = workflow
8
10
  # Use the Roast logger singleton
9
11
  end
10
12
 
@@ -14,6 +16,7 @@ module Roast
14
16
  ActiveSupport::Notifications.instrument("roast.step.start", {
15
17
  step_name: step_name,
16
18
  resource_type: resource_type,
19
+ workflow_name: @workflow&.name,
17
20
  })
18
21
 
19
22
  result = yield
@@ -23,6 +26,7 @@ module Roast
23
26
  ActiveSupport::Notifications.instrument("roast.step.complete", {
24
27
  step_name: step_name,
25
28
  resource_type: resource_type,
29
+ workflow_name: @workflow&.name,
26
30
  success: true,
27
31
  execution_time: execution_time,
28
32
  result_size: result.to_s.length,
@@ -64,6 +68,7 @@ module Roast
64
68
  ActiveSupport::Notifications.instrument("roast.step.error", {
65
69
  step_name: step_name,
66
70
  resource_type: resource_type,
71
+ workflow_name: @workflow&.name,
67
72
  error: error.class.name,
68
73
  message: error.message,
69
74
  execution_time: execution_time,
@@ -76,6 +81,7 @@ module Roast
76
81
  ActiveSupport::Notifications.instrument("roast.step.error", {
77
82
  step_name: step_name,
78
83
  resource_type: resource_type,
84
+ workflow_name: @workflow&.name,
79
85
  error: error.class.name,
80
86
  message: error.message,
81
87
  execution_time: execution_time,
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -53,7 +54,7 @@ module Roast
53
54
  state_data = load_state_file(state_file)
54
55
 
55
56
  # Extract the loaded step name for diagnostics
56
- loaded_step = File.basename(state_file).split("_", 3)[2].sub(/\.json$/, "")
57
+ loaded_step = File.basename(state_file).split("_", 3)[2].to_s.sub(/\.json$/, "")
57
58
  $stderr.puts "Found state from step: #{loaded_step} (will replay from here to #{step_name})"
58
59
 
59
60
  # If no timestamp provided and workflow has no session, copy states to new session
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "timeout"
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -16,7 +17,7 @@ module Roast
16
17
 
17
18
  # Replace all {{expression}} with their evaluated values
18
19
  text.gsub(/\{\{([^}]+)\}\}/) do |match|
19
- expression = Regexp.last_match(1).strip
20
+ expression = Regexp.last_match(1).to_s.strip
20
21
  begin
21
22
  # Evaluate the expression in the context
22
23
  result = @context.instance_eval(expression).to_s
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -51,12 +52,7 @@ module Roast
51
52
  def process_shell_command(command)
52
53
  # If it's a bash command with the $(command) syntax
53
54
  if command =~ /^\$\((.*)\)$/
54
- return Open3.capture2e({}, ::Regexp.last_match(1)).first.strip
55
- end
56
-
57
- # Legacy % prefix for backward compatibility
58
- if command.start_with?("% ")
59
- return Open3.capture2e({}, *command.split(" ")[1..-1]).first.strip
55
+ return Open3.capture2e({}, ::Regexp.last_match(1).to_s).first.strip
60
56
  end
61
57
 
62
58
  # Not a shell command, return as is
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "json"
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -22,9 +23,10 @@ module Roast
22
23
  private
23
24
 
24
25
  def default_type
26
+ state_storage = ENV["ROAST_STATE_STORAGE"]
25
27
  # Check environment variable first (for backwards compatibility)
26
- if ENV["ROAST_STATE_STORAGE"]
27
- ENV["ROAST_STATE_STORAGE"].downcase
28
+ if state_storage
29
+ state_storage.downcase
28
30
  else
29
31
  # Default to SQLite for better functionality
30
32
  "sqlite"
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Roast
@@ -145,9 +146,11 @@ module Roast
145
146
  def execute_command_step(step, options)
146
147
  exit_on_error = options.fetch(:exit_on_error, true)
147
148
  resource_type = @context.resource_type
149
+ step_key = options[:step_key]
150
+ display_name = step_key || step
148
151
 
149
- error_handler.with_error_handling(step, resource_type: resource_type) do
150
- $stderr.puts "Executing: #{step} (Resource type: #{resource_type || "unknown"})"
152
+ error_handler.with_error_handling(display_name, resource_type: resource_type) do
153
+ $stderr.puts "Executing: #{display_name} (Resource type: #{resource_type || "unknown"})"
151
154
 
152
155
  begin
153
156
  output = command_executor.execute(step, exit_on_error: exit_on_error)
@@ -169,7 +172,7 @@ module Roast
169
172
  output
170
173
  rescue CommandExecutor::CommandExecutionError => e
171
174
  # Print user-friendly error message
172
- $stderr.puts "\n❌ Command failed: #{step}"
175
+ $stderr.puts "\n❌ Command failed: #{display_name}"
173
176
  $stderr.puts " Exit status: #{e.exit_status}" if e.exit_status
174
177
 
175
178
  # Show command output if available
@@ -257,9 +260,10 @@ module Roast
257
260
  interpolated_step = interpolator.interpolate(step)
258
261
 
259
262
  if StepTypeResolver.command_step?(interpolated_step)
260
- # Command step - execute directly, preserving any passed options
263
+ # Command step - execute directly, preserving any passed options including step_key
261
264
  exit_on_error = options.fetch(:exit_on_error, true)
262
- execute_command_step(interpolated_step, { exit_on_error: })
265
+ step_key = options[:step_key]
266
+ execute_command_step(interpolated_step, { exit_on_error:, step_key: })
263
267
  else
264
268
  exit_on_error = options.fetch(:exit_on_error, context.exit_on_error?(step))
265
269
  execute_standard_step(interpolated_step, options.merge(exit_on_error:))