roast-ai 0.4.4 → 0.4.6
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/CODEOWNERS +2 -0
- data/.github/workflows/ci.yaml +1 -0
- data/.gitignore +0 -26
- data/.rubocop.yml +13 -0
- data/.rubocop_todo.yml +21 -0
- data/CHANGELOG.md +37 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +43 -1
- data/bin/rubocop +27 -0
- data/bin/spoom +27 -0
- data/bin/srb +27 -0
- data/bin/srb-rbi +27 -0
- data/bin/tapioca +27 -0
- data/docs/INSTRUMENTATION.md +3 -3
- data/dsl/simple.rb +10 -0
- data/examples/retry/workflow.yml +23 -0
- data/lib/roast/dsl/executor.rb +26 -0
- data/lib/roast/dsl.rb +7 -0
- data/lib/roast/errors.rb +1 -0
- data/lib/roast/factories/api_provider_factory.rb +1 -0
- data/lib/roast/helpers/function_caching_interceptor.rb +3 -0
- data/lib/roast/helpers/logger.rb +6 -9
- data/lib/roast/helpers/metadata_access.rb +1 -0
- data/lib/roast/helpers/minitest_coverage_runner.rb +1 -0
- data/lib/roast/helpers/path_resolver.rb +8 -18
- data/lib/roast/helpers/prompt_loader.rb +3 -2
- data/lib/roast/helpers/timeout_handler.rb +3 -5
- data/lib/roast/initializers.rb +1 -0
- data/lib/roast/resources/api_resource.rb +4 -3
- data/lib/roast/resources/base_resource.rb +1 -0
- data/lib/roast/resources/directory_resource.rb +1 -0
- data/lib/roast/resources/file_resource.rb +1 -0
- data/lib/roast/resources/none_resource.rb +1 -0
- data/lib/roast/resources/url_resource.rb +2 -1
- data/lib/roast/resources.rb +1 -2
- data/lib/roast/services/context_threshold_checker.rb +1 -0
- data/lib/roast/services/token_counting_service.rb +1 -0
- data/lib/roast/tools/apply_diff.rb +1 -0
- data/lib/roast/tools/ask_user.rb +1 -0
- data/lib/roast/tools/bash.rb +1 -0
- data/lib/roast/tools/cmd.rb +1 -0
- data/lib/roast/tools/coding_agent.rb +1 -0
- data/lib/roast/tools/context_summarizer.rb +1 -0
- data/lib/roast/tools/grep.rb +1 -0
- data/lib/roast/tools/helpers/coding_agent_message_formatter.rb +1 -0
- data/lib/roast/tools/read_file.rb +1 -0
- data/lib/roast/tools/search_file.rb +1 -0
- data/lib/roast/tools/swarm.rb +1 -0
- data/lib/roast/tools/update_files.rb +1 -0
- data/lib/roast/tools/write_file.rb +1 -0
- data/lib/roast/tools.rb +2 -0
- data/lib/roast/value_objects/api_token.rb +1 -0
- data/lib/roast/value_objects/step_name.rb +1 -0
- data/lib/roast/value_objects/uri_base.rb +1 -0
- data/lib/roast/value_objects/workflow_path.rb +1 -0
- data/lib/roast/value_objects.rb +1 -0
- data/lib/roast/version.rb +2 -1
- data/lib/roast/workflow/agent_step.rb +1 -0
- data/lib/roast/workflow/api_configuration.rb +1 -0
- data/lib/roast/workflow/base_iteration_step.rb +1 -0
- data/lib/roast/workflow/base_step.rb +1 -0
- data/lib/roast/workflow/base_workflow.rb +1 -0
- data/lib/roast/workflow/case_executor.rb +1 -0
- data/lib/roast/workflow/case_step.rb +1 -0
- data/lib/roast/workflow/command_executor.rb +1 -0
- data/lib/roast/workflow/conditional_executor.rb +1 -0
- data/lib/roast/workflow/conditional_step.rb +1 -0
- data/lib/roast/workflow/configuration.rb +9 -0
- data/lib/roast/workflow/configuration_loader.rb +4 -1
- data/lib/roast/workflow/context_manager.rb +1 -0
- data/lib/roast/workflow/context_path_resolver.rb +1 -0
- data/lib/roast/workflow/dot_access_hash.rb +1 -0
- data/lib/roast/workflow/each_step.rb +1 -0
- data/lib/roast/workflow/error_handler.rb +39 -3
- data/lib/roast/workflow/expression_evaluator.rb +1 -0
- data/lib/roast/workflow/expression_utils.rb +1 -0
- data/lib/roast/workflow/file_state_repository.rb +2 -1
- data/lib/roast/workflow/input_executor.rb +1 -0
- data/lib/roast/workflow/input_step.rb +1 -0
- data/lib/roast/workflow/interpolator.rb +2 -1
- data/lib/roast/workflow/iteration_executor.rb +1 -0
- data/lib/roast/workflow/llm_boolean_coercer.rb +1 -0
- data/lib/roast/workflow/metadata_manager.rb +1 -0
- data/lib/roast/workflow/output_handler.rb +1 -0
- data/lib/roast/workflow/output_manager.rb +1 -0
- data/lib/roast/workflow/parallel_executor.rb +1 -0
- data/lib/roast/workflow/prompt_step.rb +1 -0
- data/lib/roast/workflow/repeat_step.rb +1 -0
- data/lib/roast/workflow/replay_handler.rb +1 -0
- data/lib/roast/workflow/resource_resolver.rb +2 -6
- data/lib/roast/workflow/session_manager.rb +1 -0
- data/lib/roast/workflow/shell_script_step.rb +1 -0
- data/lib/roast/workflow/sqlite_state_repository.rb +1 -0
- data/lib/roast/workflow/state_manager.rb +1 -0
- data/lib/roast/workflow/state_repository.rb +1 -0
- data/lib/roast/workflow/state_repository_factory.rb +4 -2
- data/lib/roast/workflow/step_completion_reporter.rb +1 -0
- data/lib/roast/workflow/step_executor_coordinator.rb +17 -6
- data/lib/roast/workflow/step_executor_factory.rb +1 -0
- data/lib/roast/workflow/step_executor_registry.rb +2 -3
- data/lib/roast/workflow/step_executor_with_reporting.rb +1 -0
- data/lib/roast/workflow/step_executors/base_step_executor.rb +1 -0
- data/lib/roast/workflow/step_executors/hash_step_executor.rb +1 -0
- data/lib/roast/workflow/step_executors/parallel_step_executor.rb +1 -0
- data/lib/roast/workflow/step_executors/string_step_executor.rb +1 -0
- data/lib/roast/workflow/step_factory.rb +1 -0
- data/lib/roast/workflow/step_finder.rb +1 -0
- data/lib/roast/workflow/step_loader.rb +1 -0
- data/lib/roast/workflow/step_name_extractor.rb +1 -0
- data/lib/roast/workflow/step_runner.rb +1 -0
- data/lib/roast/workflow/step_type_resolver.rb +1 -0
- data/lib/roast/workflow/validation_command.rb +1 -0
- data/lib/roast/workflow/validator.rb +1 -0
- data/lib/roast/workflow/validators/base_validator.rb +1 -0
- data/lib/roast/workflow/validators/dependency_validator.rb +1 -0
- data/lib/roast/workflow/validators/linting_validator.rb +1 -0
- data/lib/roast/workflow/validators/schema_validator.rb +1 -0
- data/lib/roast/workflow/validators/step_collector.rb +1 -0
- data/lib/roast/workflow/validators/validation_orchestrator.rb +1 -0
- data/lib/roast/workflow/workflow_context.rb +1 -0
- data/lib/roast/workflow/workflow_execution_context.rb +1 -0
- data/lib/roast/workflow/workflow_executor.rb +2 -1
- data/lib/roast/workflow/workflow_initializer.rb +16 -1
- data/lib/roast/workflow/workflow_runner.rb +66 -55
- data/lib/roast/workflow.rb +1 -0
- data/lib/roast/workflow_diagram_generator.rb +3 -2
- data/lib/roast.rb +23 -8
- data/sorbet/config +8 -0
- data/sorbet/rbi/dsl/.gitattributes +1 -0
- data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/activesupport@8.0.2.rbi +19107 -0
- data/sorbet/rbi/gems/addressable@2.8.7.rbi +1994 -0
- data/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
- data/sorbet/rbi/gems/base64@0.3.0.rbi +545 -0
- data/sorbet/rbi/gems/benchmark@0.4.1.rbi +619 -0
- data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +62 -0
- data/sorbet/rbi/gems/cgi@0.5.0.rbi +2961 -0
- data/sorbet/rbi/gems/claude_swarm@0.1.19.rbi +568 -0
- data/sorbet/rbi/gems/cli-kit@5.0.1.rbi +1991 -0
- data/sorbet/rbi/gems/cli-ui@2.3.0.rbi +3181 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +9 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +11657 -0
- data/sorbet/rbi/gems/connection_pool@2.5.3.rbi +9 -0
- data/sorbet/rbi/gems/crack@1.0.0.rbi +145 -0
- data/sorbet/rbi/gems/diff-lcs@1.6.2.rbi +972 -0
- data/sorbet/rbi/gems/dotenv@3.1.8.rbi +295 -0
- data/sorbet/rbi/gems/drb@2.2.3.rbi +1661 -0
- data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +672 -0
- data/sorbet/rbi/gems/dry-core@1.1.0.rbi +1894 -0
- data/sorbet/rbi/gems/dry-inflector@1.2.0.rbi +659 -0
- data/sorbet/rbi/gems/dry-initializer@3.2.0.rbi +781 -0
- data/sorbet/rbi/gems/dry-logic@1.6.0.rbi +1127 -0
- data/sorbet/rbi/gems/dry-schema@1.14.1.rbi +3727 -0
- data/sorbet/rbi/gems/dry-types@1.8.3.rbi +3969 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
- data/sorbet/rbi/gems/event_stream_parser@1.0.0.rbi +49 -0
- data/sorbet/rbi/gems/faraday-multipart@1.1.1.rbi +283 -0
- data/sorbet/rbi/gems/faraday-net_http@3.4.1.rbi +147 -0
- data/sorbet/rbi/gems/faraday-retry@2.3.2.rbi +9 -0
- data/sorbet/rbi/gems/faraday@2.13.1.rbi +2977 -0
- data/sorbet/rbi/gems/fast-mcp-annotations@1.5.3.rbi +1588 -0
- data/sorbet/rbi/gems/ffi@1.17.2.rbi +9 -0
- data/sorbet/rbi/gems/formatador@1.1.0.rbi +9 -0
- data/sorbet/rbi/gems/guard-compat@1.2.1.rbi +102 -0
- data/sorbet/rbi/gems/guard-minitest@2.4.6.rbi +402 -0
- data/sorbet/rbi/gems/guard@2.19.1.rbi +2283 -0
- data/sorbet/rbi/gems/hashdiff@1.2.0.rbi +355 -0
- data/sorbet/rbi/gems/i18n@1.14.7.rbi +2359 -0
- data/sorbet/rbi/gems/json-schema@5.1.1.rbi +1466 -0
- data/sorbet/rbi/gems/json@2.12.2.rbi +2051 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +9 -0
- data/sorbet/rbi/gems/listen@3.9.0.rbi +1206 -0
- data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
- data/sorbet/rbi/gems/lumberjack@1.2.10.rbi +1830 -0
- data/sorbet/rbi/gems/method_source@1.1.0.rbi +9 -0
- data/sorbet/rbi/gems/mime-types-data@3.2025.0617.rbi +136 -0
- data/sorbet/rbi/gems/mime-types@3.7.0.rbi +1342 -0
- data/sorbet/rbi/gems/minitest-rg@5.3.0.rbi +160 -0
- data/sorbet/rbi/gems/minitest@5.25.5.rbi +1640 -0
- data/sorbet/rbi/gems/mocha@2.7.1.rbi +12 -0
- data/sorbet/rbi/gems/multipart-post@2.4.1.rbi +244 -0
- data/sorbet/rbi/gems/nenv@0.3.0.rbi +147 -0
- data/sorbet/rbi/gems/net-http@0.6.0.rbi +4247 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/notiffany@0.1.3.rbi +1079 -0
- data/sorbet/rbi/gems/open_router@0.3.3.rbi +230 -0
- data/sorbet/rbi/gems/ostruct@0.6.2.rbi +354 -0
- data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.8.0.rbi +5535 -0
- data/sorbet/rbi/gems/prism@1.4.0.rbi +41732 -0
- data/sorbet/rbi/gems/pry@0.15.2.rbi +9 -0
- data/sorbet/rbi/gems/public_suffix@6.0.2.rbi +936 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +158 -0
- data/sorbet/rbi/gems/rack@2.2.17.rbi +5659 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +9 -0
- data/sorbet/rbi/gems/raix@1.0.2.rbi +1104 -0
- data/sorbet/rbi/gems/rake@13.3.0.rbi +3036 -0
- data/sorbet/rbi/gems/rb-fsevent@0.11.2.rbi +9 -0
- data/sorbet/rbi/gems/rb-inotify@0.11.1.rbi +9 -0
- data/sorbet/rbi/gems/rbi@0.3.6.rbi +6893 -0
- data/sorbet/rbi/gems/rbs@3.9.4.rbi +6978 -0
- data/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +9 -0
- data/sorbet/rbi/gems/rexml@3.4.1.rbi +5346 -0
- data/sorbet/rbi/gems/rubocop-ast@1.45.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop-shopify@2.17.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop@1.77.0.rbi +9 -0
- data/sorbet/rbi/gems/ruby-graphviz@1.2.5.rbi +1333 -0
- data/sorbet/rbi/gems/ruby-openai@8.1.0.rbi +758 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +9 -0
- data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +9 -0
- data/sorbet/rbi/gems/securerandom@0.4.1.rbi +75 -0
- data/sorbet/rbi/gems/shellany@0.0.1.rbi +102 -0
- data/sorbet/rbi/gems/spoom@1.6.3.rbi +6985 -0
- data/sorbet/rbi/gems/sqlite3@2.7.0.rbi +1900 -0
- data/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
- data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
- data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5918 -0
- data/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +9 -0
- data/sorbet/rbi/gems/unicode-emoji@4.0.4.rbi +9 -0
- data/sorbet/rbi/gems/uri@1.0.3.rbi +2349 -0
- data/sorbet/rbi/gems/vcr@6.3.1.rbi +3040 -0
- data/sorbet/rbi/gems/webmock@3.25.1.rbi +1792 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18492 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1429 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +36 -0
- metadata +114 -2
- data/lib/roast/workflow/configuration_parser.rb +0 -54
@@ -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
|
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)
|
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
|
@@ -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
|
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
|
data/lib/roast/resources.rb
CHANGED
@@ -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
|
data/lib/roast/tools/ask_user.rb
CHANGED
data/lib/roast/tools/bash.rb
CHANGED
data/lib/roast/tools/cmd.rb
CHANGED
data/lib/roast/tools/grep.rb
CHANGED
data/lib/roast/tools/swarm.rb
CHANGED
data/lib/roast/tools.rb
CHANGED
data/lib/roast/value_objects.rb
CHANGED
data/lib/roast/version.rb
CHANGED
@@ -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
|
193
|
+
raise ValidationError, <<~ERROR
|
191
194
|
Workflow validation failed with #{validator.errors.size} error(s):
|
192
195
|
|
193
196
|
#{error_messages}
|
@@ -1,28 +1,45 @@
|
|
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
|
|
11
|
-
def with_error_handling(step_name, resource_type: nil)
|
13
|
+
def with_error_handling(step_name, resource_type: nil, retries: 0, &block)
|
12
14
|
start_time = Time.now
|
15
|
+
maximum_attempts = retries + 1
|
13
16
|
|
14
17
|
ActiveSupport::Notifications.instrument("roast.step.start", {
|
15
18
|
step_name: step_name,
|
16
19
|
resource_type: resource_type,
|
20
|
+
workflow_name: @workflow&.name,
|
17
21
|
})
|
18
22
|
|
19
|
-
result =
|
23
|
+
result = nil #: untyped?
|
24
|
+
|
25
|
+
maximum_attempts.times do |current_attempt|
|
26
|
+
# .times starts at 0 index, the math is easier to reason about if current_attempt matches normal description
|
27
|
+
current_attempt += 1
|
28
|
+
result = block.call
|
29
|
+
break
|
30
|
+
rescue StandardError => e
|
31
|
+
remaining_attempts = maximum_attempts - current_attempt
|
32
|
+
raise e if remaining_attempts == 0
|
33
|
+
|
34
|
+
handle_retry(e, step_name, resource_type, start_time, remaining_attempts)
|
35
|
+
end
|
20
36
|
|
21
37
|
execution_time = Time.now - start_time
|
22
38
|
|
23
39
|
ActiveSupport::Notifications.instrument("roast.step.complete", {
|
24
40
|
step_name: step_name,
|
25
41
|
resource_type: resource_type,
|
42
|
+
workflow_name: @workflow&.name,
|
26
43
|
success: true,
|
27
44
|
execution_time: execution_time,
|
28
45
|
result_size: result.to_s.length,
|
@@ -58,12 +75,30 @@ module Roast
|
|
58
75
|
|
59
76
|
private
|
60
77
|
|
78
|
+
def handle_retry(error, step_name, resource_type, start_time, remaining_attempts)
|
79
|
+
execution_time = Time.now - start_time
|
80
|
+
|
81
|
+
ActiveSupport::Notifications.instrument("roast.step.error.retry", {
|
82
|
+
step_name: step_name,
|
83
|
+
resource_type: resource_type,
|
84
|
+
workflow_name: @workflow&.name,
|
85
|
+
error: error.class.name,
|
86
|
+
message: error.message,
|
87
|
+
execution_time: execution_time,
|
88
|
+
remaining_attempts: remaining_attempts,
|
89
|
+
})
|
90
|
+
|
91
|
+
log_warning("[#{step_name}] failed: #{error.message}")
|
92
|
+
log_warning("Retrying, #{remaining_attempts} attempts left")
|
93
|
+
end
|
94
|
+
|
61
95
|
def handle_workflow_error(error, step_name, resource_type, start_time)
|
62
96
|
execution_time = Time.now - start_time
|
63
97
|
|
64
98
|
ActiveSupport::Notifications.instrument("roast.step.error", {
|
65
99
|
step_name: step_name,
|
66
100
|
resource_type: resource_type,
|
101
|
+
workflow_name: @workflow&.name,
|
67
102
|
error: error.class.name,
|
68
103
|
message: error.message,
|
69
104
|
execution_time: execution_time,
|
@@ -76,6 +111,7 @@ module Roast
|
|
76
111
|
ActiveSupport::Notifications.instrument("roast.step.error", {
|
77
112
|
step_name: step_name,
|
78
113
|
resource_type: resource_type,
|
114
|
+
workflow_name: @workflow&.name,
|
79
115
|
error: error.class.name,
|
80
116
|
message: error.message,
|
81
117
|
execution_time: execution_time,
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
27
|
-
|
28
|
+
if state_storage
|
29
|
+
state_storage.downcase
|
28
30
|
else
|
29
31
|
# Default to SQLite for better functionality
|
30
32
|
"sqlite"
|