roast-ai 0.4.10 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/commands/docs/write-comments.md +36 -0
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/ci.yaml +10 -6
- data/.gitignore +0 -1
- data/.rubocop.yml +7 -1
- data/CLAUDE.md +2 -2
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +19 -18
- data/Gemfile.lock +35 -58
- data/README.md +118 -1432
- data/README_LEGACY.md +1464 -0
- data/Rakefile +39 -4
- data/dev.yml +29 -0
- data/dsl/agent_sessions.rb +20 -0
- data/dsl/async_cogs.rb +49 -0
- data/dsl/async_cogs_complex.rb +67 -0
- data/dsl/call.rb +44 -0
- data/dsl/collect_from.rb +72 -0
- data/dsl/json_output.rb +28 -0
- data/dsl/map.rb +55 -0
- data/dsl/map_reduce.rb +37 -0
- data/dsl/map_with_index.rb +49 -0
- data/dsl/next_break.rb +40 -0
- data/dsl/next_break_parallel.rb +44 -0
- data/dsl/outputs.rb +39 -0
- data/dsl/outputs_bang.rb +36 -0
- data/dsl/parallel_map.rb +37 -0
- data/dsl/prompts/simple_prompt.md.erb +3 -0
- data/dsl/prototype.rb +5 -7
- data/dsl/repeat_loop_results.rb +53 -0
- data/dsl/ruby_cog.rb +72 -0
- data/dsl/simple_agent.rb +18 -0
- data/dsl/simple_chat.rb +15 -1
- data/dsl/simple_repeat.rb +29 -0
- data/dsl/skip.rb +36 -0
- data/dsl/step_communication.rb +2 -3
- data/dsl/targets_and_params.rb +57 -0
- data/dsl/temperature.rb +17 -0
- data/dsl/temporary_directory.rb +22 -0
- data/dsl/tutorial/01_your_first_workflow/README.md +179 -0
- data/dsl/tutorial/01_your_first_workflow/configured_chat.rb +33 -0
- data/dsl/tutorial/01_your_first_workflow/hello.rb +23 -0
- data/dsl/tutorial/02_chaining_cogs/README.md +310 -0
- data/dsl/tutorial/02_chaining_cogs/code_review.rb +104 -0
- data/dsl/tutorial/02_chaining_cogs/session_resumption.rb +92 -0
- data/dsl/tutorial/02_chaining_cogs/simple_chain.rb +84 -0
- data/dsl/tutorial/03_targets_and_params/README.md +230 -0
- data/dsl/tutorial/03_targets_and_params/multiple_targets.rb +65 -0
- data/dsl/tutorial/03_targets_and_params/single_target.rb +65 -0
- data/dsl/tutorial/04_configuration_options/README.md +209 -0
- data/dsl/tutorial/04_configuration_options/control_display_and_temperature.rb +104 -0
- data/dsl/tutorial/04_configuration_options/simple_config.rb +68 -0
- data/dsl/tutorial/05_control_flow/README.md +156 -0
- data/dsl/tutorial/05_control_flow/conditional_execution.rb +62 -0
- data/dsl/tutorial/05_control_flow/handling_failures.rb +77 -0
- data/dsl/tutorial/06_reusable_scopes/README.md +172 -0
- data/dsl/tutorial/06_reusable_scopes/accessing_scope_outputs.rb +126 -0
- data/dsl/tutorial/06_reusable_scopes/basic_scope.rb +63 -0
- data/dsl/tutorial/06_reusable_scopes/parameterized_scope.rb +78 -0
- data/dsl/tutorial/07_processing_collections/README.md +152 -0
- data/dsl/tutorial/07_processing_collections/basic_map.rb +70 -0
- data/dsl/tutorial/07_processing_collections/parallel_map.rb +74 -0
- data/dsl/tutorial/08_iterative_workflows/README.md +231 -0
- data/dsl/tutorial/08_iterative_workflows/basic_repeat.rb +57 -0
- data/dsl/tutorial/08_iterative_workflows/conditional_break.rb +57 -0
- data/dsl/tutorial/09_async_cogs/README.md +197 -0
- data/dsl/tutorial/09_async_cogs/basic_async.rb +38 -0
- data/dsl/tutorial/README.md +222 -0
- data/dsl/working_directory.rb +16 -0
- data/exe/roast +1 -1
- data/internal/documentation/architectural-notes.md +115 -0
- data/internal/documentation/doc-comments-external.md +686 -0
- data/internal/documentation/doc-comments-internal.md +342 -0
- data/internal/documentation/doc-comments.md +211 -0
- data/lib/roast/dsl/cog/config.rb +274 -3
- data/lib/roast/dsl/cog/input.rb +53 -10
- data/lib/roast/dsl/cog/output.rb +297 -8
- data/lib/roast/dsl/cog/registry.rb +35 -3
- data/lib/roast/dsl/cog/stack.rb +1 -1
- data/lib/roast/dsl/cog/store.rb +5 -5
- data/lib/roast/dsl/cog.rb +70 -14
- data/lib/roast/dsl/cog_input_context.rb +36 -1
- data/lib/roast/dsl/cog_input_manager.rb +116 -7
- data/lib/roast/dsl/cogs/agent/config.rb +465 -0
- data/lib/roast/dsl/cogs/agent/input.rb +81 -0
- data/lib/roast/dsl/cogs/agent/output.rb +59 -0
- data/lib/roast/dsl/cogs/agent/provider.rb +51 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/claude_invocation.rb +185 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/message.rb +73 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/assistant_message.rb +36 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/result_message.rb +61 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/system_message.rb +47 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/text_message.rb +36 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_result_message.rb +47 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_use_message.rb +46 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/unknown_message.rb +27 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/messages/user_message.rb +37 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/tool_result.rb +51 -0
- data/lib/roast/dsl/cogs/agent/providers/claude/tool_use.rb +48 -0
- data/lib/roast/dsl/cogs/agent/providers/claude.rb +31 -0
- data/lib/roast/dsl/cogs/agent/stats.rb +92 -0
- data/lib/roast/dsl/cogs/agent/usage.rb +62 -0
- data/lib/roast/dsl/cogs/agent.rb +75 -0
- data/lib/roast/dsl/cogs/chat/config.rb +453 -0
- data/lib/roast/dsl/cogs/chat/input.rb +92 -0
- data/lib/roast/dsl/cogs/chat/output.rb +64 -0
- data/lib/roast/dsl/cogs/chat/session.rb +68 -0
- data/lib/roast/dsl/cogs/chat.rb +59 -56
- data/lib/roast/dsl/cogs/cmd.rb +248 -61
- data/lib/roast/dsl/cogs/ruby.rb +171 -0
- data/lib/roast/dsl/command_runner.rb +191 -0
- data/lib/roast/dsl/config_manager.rb +58 -11
- data/lib/roast/dsl/control_flow.rb +41 -0
- data/lib/roast/dsl/execution_manager.rb +162 -32
- data/lib/roast/dsl/nil_assertions.rb +23 -0
- data/lib/roast/dsl/system_cog/params.rb +32 -0
- data/lib/roast/dsl/system_cog.rb +36 -0
- data/lib/roast/dsl/system_cogs/call.rb +162 -0
- data/lib/roast/dsl/system_cogs/map.rb +448 -0
- data/lib/roast/dsl/system_cogs/repeat.rb +242 -0
- data/lib/roast/dsl/workflow.rb +26 -16
- data/lib/roast/dsl/workflow_context.rb +20 -0
- data/lib/roast/dsl/workflow_params.rb +24 -0
- data/lib/roast/sorbet_runtime_stub.rb +154 -0
- data/lib/roast/tools/apply_diff.rb +1 -3
- data/lib/roast/tools/cmd.rb +4 -3
- data/lib/roast/tools/read_file.rb +1 -1
- data/lib/roast/tools/update_files.rb +1 -1
- data/lib/roast/tools/write_file.rb +1 -1
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/base_workflow.rb +4 -0
- data/lib/roast/workflow/step_loader.rb +14 -2
- data/lib/roast-ai.rb +4 -0
- data/lib/roast.rb +58 -21
- data/{roast.gemspec → roast-ai.gemspec} +9 -13
- data/sorbet/rbi/gems/async@2.34.0.rbi +1577 -0
- data/sorbet/rbi/gems/cli-kit@5.2.0.rbi +2063 -0
- data/sorbet/rbi/gems/{cli-ui@2.3.0.rbi → cli-ui@2.7.0-6bdefd1d06305e5d6ae312ac76f9c88f88658dda.rbi} +1418 -1013
- data/sorbet/rbi/gems/console@1.34.2.rbi +1193 -0
- data/sorbet/rbi/gems/fiber-annotation@0.2.0.rbi +50 -0
- data/sorbet/rbi/gems/fiber-local@1.1.0.rbi +35 -0
- data/sorbet/rbi/gems/fiber-storage@1.0.1.rbi +41 -0
- data/sorbet/rbi/gems/io-event@1.14.0.rbi +724 -0
- data/sorbet/rbi/gems/metrics@0.15.0.rbi +9 -0
- data/sorbet/rbi/gems/traces@0.18.2.rbi +9 -0
- data/sorbet/rbi/shims/lib/roast/dsl/cog_input_context.rbi +1185 -5
- data/sorbet/rbi/shims/lib/roast/dsl/config_context.rbi +311 -5
- data/sorbet/rbi/shims/lib/roast/dsl/execution_context.rbi +486 -5
- data/sorbet/tapioca/config.yml +6 -0
- data/sorbet/tapioca/require.rb +2 -0
- metadata +157 -30
- data/dsl/less_simple.rb +0 -112
- data/dsl/scoped_executors.rb +0 -28
- data/dsl/simple.rb +0 -8
- data/lib/roast/dsl/cogs/execute.rb +0 -46
- data/lib/roast/dsl/cogs/graph.rb +0 -53
- data/sorbet/rbi/gems/cgi@0.5.0.rbi +0 -2961
- data/sorbet/rbi/gems/claude_swarm@0.1.19.rbi +0 -568
- data/sorbet/rbi/gems/cli-kit@5.0.1.rbi +0 -1991
- data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +0 -672
- data/sorbet/rbi/gems/dry-core@1.1.0.rbi +0 -1894
- data/sorbet/rbi/gems/dry-inflector@1.2.0.rbi +0 -659
- data/sorbet/rbi/gems/dry-initializer@3.2.0.rbi +0 -781
- data/sorbet/rbi/gems/dry-logic@1.6.0.rbi +0 -1127
- data/sorbet/rbi/gems/dry-schema@1.14.1.rbi +0 -3727
- data/sorbet/rbi/gems/dry-types@1.8.3.rbi +0 -3969
- data/sorbet/rbi/gems/fast-mcp-annotations@1.5.3.rbi +0 -1588
- data/sorbet/rbi/gems/mime-types-data@3.2025.0617.rbi +0 -136
- data/sorbet/rbi/gems/mime-types@3.7.0.rbi +0 -1342
- data/sorbet/rbi/gems/rack@2.2.19.rbi +0 -5676
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +0 -435
- data/sorbet/rbi/gems/yard@0.9.37.rbi +0 -18492
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Roast
|
|
5
|
+
module DSL
|
|
6
|
+
module SystemCogs
|
|
7
|
+
# Repeat cog for executing a scope multiple times in a loop
|
|
8
|
+
#
|
|
9
|
+
# Executes a named execution scope (defined with `execute(:name)`) repeatedly until
|
|
10
|
+
# a `break!` is called. The output from each iteration becomes the input value for
|
|
11
|
+
# the next iteration, allowing for iterative transformations.
|
|
12
|
+
class Repeat < SystemCog
|
|
13
|
+
# Configuration for the `repeat` cog
|
|
14
|
+
#
|
|
15
|
+
# Currently has no configuration options.
|
|
16
|
+
class Config < Cog::Config; end
|
|
17
|
+
|
|
18
|
+
# Parameters for the `repeat` cog
|
|
19
|
+
class Params < SystemCog::Params
|
|
20
|
+
# The name of the execution scope to invoke for each iteration
|
|
21
|
+
#
|
|
22
|
+
#: Symbol
|
|
23
|
+
attr_accessor :run
|
|
24
|
+
|
|
25
|
+
# Initialize parameters with the cog name and execution scope
|
|
26
|
+
#
|
|
27
|
+
#: (?Symbol?, run: Symbol) -> void
|
|
28
|
+
def initialize(name = nil, run:)
|
|
29
|
+
super(name)
|
|
30
|
+
@run = run
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Input for the `repeat` cog
|
|
35
|
+
#
|
|
36
|
+
# Provides the initial value to pass to the first iteration. Each subsequent iteration
|
|
37
|
+
# receives the output from the previous iteration as its value.
|
|
38
|
+
class Input < Cog::Input
|
|
39
|
+
# The initial value to pass to the first iteration
|
|
40
|
+
#
|
|
41
|
+
# This value will be passed to the execution scope on the first iteration. Subsequent
|
|
42
|
+
# iterations receive the output from the previous iteration. Required.
|
|
43
|
+
#
|
|
44
|
+
#: untyped
|
|
45
|
+
attr_accessor :value
|
|
46
|
+
|
|
47
|
+
# The starting index for the first iteration
|
|
48
|
+
#
|
|
49
|
+
# Defaults to `0`. This affects the index value passed to each iteration.
|
|
50
|
+
#
|
|
51
|
+
# Integer
|
|
52
|
+
attr_accessor :index
|
|
53
|
+
|
|
54
|
+
# The maximum number of iterations for which the loop may run
|
|
55
|
+
#
|
|
56
|
+
# Defaults to `nil`, meaning that no maximum iteration limit is applied
|
|
57
|
+
#
|
|
58
|
+
#: Integer?
|
|
59
|
+
attr_accessor :max_iterations
|
|
60
|
+
|
|
61
|
+
# Initialize the input with default values
|
|
62
|
+
#
|
|
63
|
+
#: () -> void
|
|
64
|
+
def initialize
|
|
65
|
+
super
|
|
66
|
+
@index = 0
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Validate that required input values are present
|
|
70
|
+
#
|
|
71
|
+
#: () -> void
|
|
72
|
+
def validate!
|
|
73
|
+
raise Cog::Input::InvalidInputError, "'value' is required" if value.nil? && !coerce_ran?
|
|
74
|
+
raise Cog::Input::InvalidInputError, "'max_iterations' must be >= 1 if present" if (max_iterations || 1) < 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Coerce the input from the return value of the input block
|
|
78
|
+
#
|
|
79
|
+
# Sets the value from the input block's return value if not already set directly.
|
|
80
|
+
#
|
|
81
|
+
#: (untyped) -> void
|
|
82
|
+
def coerce(input_return_value)
|
|
83
|
+
super
|
|
84
|
+
@value = input_return_value unless @value.present?
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Output from running the `repeat` cog
|
|
89
|
+
#
|
|
90
|
+
# Contains results from all iterations that ran. Provides access to the final value
|
|
91
|
+
# (output from the last iteration) as well as individual iteration results.
|
|
92
|
+
#
|
|
93
|
+
# #### See Also
|
|
94
|
+
# - `Roast::DSL::CogInputContext#collect` - retrieves all iteration outputs as an array (via `results`)
|
|
95
|
+
# - `Roast::DSL::CogInputContext#reduce` - reduces iteration outputs to a single value (via `results`)
|
|
96
|
+
class Output < Cog::Output
|
|
97
|
+
# Initialize the output with results for all iterations
|
|
98
|
+
#
|
|
99
|
+
#: (Array[ExecutionManager]) -> void
|
|
100
|
+
def initialize(execution_managers)
|
|
101
|
+
super()
|
|
102
|
+
@execution_managers = execution_managers
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Get the final output value from the last iteration
|
|
106
|
+
#
|
|
107
|
+
# This is the output from the last iteration before `break!` was called.
|
|
108
|
+
# Returns `nil` if no iterations ran.
|
|
109
|
+
#
|
|
110
|
+
# #### Usage
|
|
111
|
+
# ```ruby
|
|
112
|
+
# # Get the final result directly
|
|
113
|
+
# final = repeat!(:process)
|
|
114
|
+
# ```
|
|
115
|
+
#
|
|
116
|
+
# #### See Also
|
|
117
|
+
# - `last`
|
|
118
|
+
# - `results`
|
|
119
|
+
#
|
|
120
|
+
#: () -> untyped
|
|
121
|
+
def value
|
|
122
|
+
@execution_managers.last&.final_output
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Get the output from a specific iteration
|
|
126
|
+
#
|
|
127
|
+
# Returns a `Roast::DSL::SystemCogs::Call::Output` object for the iteration at the given index.
|
|
128
|
+
# Supports negative indices to count from the end (e.g., `-1` for the last iteration).
|
|
129
|
+
#
|
|
130
|
+
# #### Usage
|
|
131
|
+
# ```ruby
|
|
132
|
+
# # Access a specific iteration
|
|
133
|
+
# result = from(repeat!(:process).iteration(2))
|
|
134
|
+
#
|
|
135
|
+
# # Access with negative index
|
|
136
|
+
# result = from(repeat!(:process).iteration(-1))
|
|
137
|
+
# ```
|
|
138
|
+
#
|
|
139
|
+
# #### See Also
|
|
140
|
+
# - `first`
|
|
141
|
+
# - `last`
|
|
142
|
+
# - `value`
|
|
143
|
+
# - `Roast::DSL::CogInputContext#from`
|
|
144
|
+
#
|
|
145
|
+
#: (Integer) -> Call::Output
|
|
146
|
+
def iteration(index)
|
|
147
|
+
Call::Output.new(@execution_managers.fetch(index))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Get the output from the first iteration
|
|
151
|
+
#
|
|
152
|
+
# Convenience method equivalent to `iteration(0)`.
|
|
153
|
+
#
|
|
154
|
+
# #### See Also
|
|
155
|
+
# - `iteration`
|
|
156
|
+
# - `last`
|
|
157
|
+
#
|
|
158
|
+
#: () -> Call::Output
|
|
159
|
+
def first
|
|
160
|
+
iteration(0)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Get the output from the last iteration
|
|
164
|
+
#
|
|
165
|
+
# Convenience method equivalent to `iteration(-1)`. Returns the same value as
|
|
166
|
+
# calling `value`, but wrapped in a `Roast::DSL::SystemCogs::Call::Output` for use with `from`.
|
|
167
|
+
#
|
|
168
|
+
# #### See Also
|
|
169
|
+
# - `iteration`
|
|
170
|
+
# - `first`
|
|
171
|
+
# - `value`
|
|
172
|
+
#
|
|
173
|
+
#: () -> Call::Output
|
|
174
|
+
def last
|
|
175
|
+
iteration(-1)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Get all iteration results as a `Roast::DSL::SystemCogs::Map::Output` object
|
|
179
|
+
#
|
|
180
|
+
# Returns a `Roast::DSL::SystemCogs::Map::Output` containing all iterations, which can be used with
|
|
181
|
+
# `collect` or `reduce` to process all iteration outputs.
|
|
182
|
+
#
|
|
183
|
+
# #### Usage
|
|
184
|
+
# ```ruby
|
|
185
|
+
# # Collect all iteration outputs
|
|
186
|
+
# all_results = collect(repeat!(:process).results)
|
|
187
|
+
#
|
|
188
|
+
# # Reduce all iteration outputs
|
|
189
|
+
# sum = reduce(repeat!(:process).results, 0) { |acc, output| acc + output }
|
|
190
|
+
# ```
|
|
191
|
+
#
|
|
192
|
+
# #### See Also
|
|
193
|
+
# - `value`
|
|
194
|
+
# - `Roast::DSL::CogInputContext#collect`
|
|
195
|
+
# - `Roast::DSL::CogInputContext#reduce`
|
|
196
|
+
# - `Roast::DSL::SystemCogs::Map::Output`
|
|
197
|
+
#
|
|
198
|
+
#: () -> Map::Output
|
|
199
|
+
def results
|
|
200
|
+
Map::Output.new(@execution_managers)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# @requires_ancestor: Roast::DSL::ExecutionManager
|
|
205
|
+
module Manager
|
|
206
|
+
private
|
|
207
|
+
|
|
208
|
+
#: (Params, ^(Cog::Input) -> untyped) -> SystemCogs::Repeat
|
|
209
|
+
def create_repeat_system_cog(params, input_proc)
|
|
210
|
+
SystemCogs::Repeat.new(params.name, input_proc) do |input|
|
|
211
|
+
input = input #: as Input
|
|
212
|
+
raise ExecutionManager::ExecutionScopeNotSpecifiedError unless params.run.present?
|
|
213
|
+
|
|
214
|
+
ems = [] #: Array[ExecutionManager]
|
|
215
|
+
scope_value = input.value.deep_dup
|
|
216
|
+
max_iterations = input.max_iterations
|
|
217
|
+
loop do
|
|
218
|
+
ems << em = ExecutionManager.new(
|
|
219
|
+
@cog_registry,
|
|
220
|
+
@config_manager,
|
|
221
|
+
@all_execution_procs,
|
|
222
|
+
@workflow_context,
|
|
223
|
+
scope: params.run,
|
|
224
|
+
scope_value: scope_value,
|
|
225
|
+
scope_index: ems.length,
|
|
226
|
+
)
|
|
227
|
+
em.prepare!
|
|
228
|
+
em.run!
|
|
229
|
+
scope_value = em.final_output
|
|
230
|
+
break if max_iterations.present? && ems.length >= max_iterations
|
|
231
|
+
rescue ControlFlow::Break
|
|
232
|
+
# TODO: do something with the message passed to break!
|
|
233
|
+
break
|
|
234
|
+
end
|
|
235
|
+
Output.new(ems)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
data/lib/roast/dsl/workflow.rb
CHANGED
|
@@ -11,18 +11,22 @@ module Roast
|
|
|
11
11
|
class InvalidCogReference < WorkflowError; end
|
|
12
12
|
|
|
13
13
|
class << self
|
|
14
|
-
#: (String) -> void
|
|
15
|
-
def from_file(workflow_path)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
#: (String, WorkflowParams) -> void
|
|
15
|
+
def from_file(workflow_path, params)
|
|
16
|
+
Dir.mktmpdir("roast-") do |tmpdir|
|
|
17
|
+
workflow_context = WorkflowContext.new(params:, tmpdir:)
|
|
18
|
+
workflow = new(workflow_path, workflow_context)
|
|
19
|
+
workflow.prepare!
|
|
20
|
+
workflow.start!
|
|
21
|
+
end
|
|
19
22
|
end
|
|
20
23
|
end
|
|
21
24
|
|
|
22
|
-
#: (String) -> void
|
|
23
|
-
def initialize(workflow_path)
|
|
24
|
-
@workflow_path = Pathname.new(workflow_path)
|
|
25
|
-
@
|
|
25
|
+
#: (String, WorkflowContext) -> void
|
|
26
|
+
def initialize(workflow_path, workflow_context)
|
|
27
|
+
@workflow_path = Pathname.new(workflow_path) #: Pathname
|
|
28
|
+
@workflow_context = workflow_context #: WorkflowContext
|
|
29
|
+
@workflow_definition = File.read(workflow_path) #: String
|
|
26
30
|
@cog_registry = Cog::Registry.new #: Cog::Registry
|
|
27
31
|
@config_procs = [] #: Array[^() -> void]
|
|
28
32
|
@execution_procs = { nil: [] } #: Hash[Symbol?, Array[^() -> void]]
|
|
@@ -37,9 +41,10 @@ module Roast
|
|
|
37
41
|
@preparing = true
|
|
38
42
|
extract_dsl_procs!
|
|
39
43
|
@config_manager = ConfigManager.new(@cog_registry, @config_procs)
|
|
40
|
-
@config_manager.prepare!
|
|
41
|
-
|
|
42
|
-
@execution_manager.
|
|
44
|
+
@config_manager.not_nil!.prepare!
|
|
45
|
+
# TODO: probably we should just not pass the params as the top-level scope value anymore
|
|
46
|
+
@execution_manager = ExecutionManager.new(@cog_registry, @config_manager.not_nil!, @execution_procs, @workflow_context, scope_value: @workflow_context.params)
|
|
47
|
+
@execution_manager.not_nil!.prepare!
|
|
43
48
|
|
|
44
49
|
@prepared = true
|
|
45
50
|
end
|
|
@@ -50,7 +55,12 @@ module Roast
|
|
|
50
55
|
raise WorkflowAlreadyStartedError if started? || completed?
|
|
51
56
|
|
|
52
57
|
@started = true
|
|
53
|
-
|
|
58
|
+
begin
|
|
59
|
+
@execution_manager.run!
|
|
60
|
+
rescue ControlFlow::Break
|
|
61
|
+
# treat `break!` like `next!` in the top-level executor scope
|
|
62
|
+
# TODO: maybe do something with the message passed to break!
|
|
63
|
+
end
|
|
54
64
|
@completed = true
|
|
55
65
|
end
|
|
56
66
|
|
|
@@ -74,12 +84,12 @@ module Roast
|
|
|
74
84
|
@completed ||= false
|
|
75
85
|
end
|
|
76
86
|
|
|
77
|
-
#: { () [self: ConfigContext] -> void } -> void
|
|
87
|
+
#: { () [self: Roast::DSL::ConfigContext] -> void } -> void
|
|
78
88
|
def config(&block)
|
|
79
89
|
@config_procs << block
|
|
80
90
|
end
|
|
81
91
|
|
|
82
|
-
#: (?Symbol?) { () [self: ExecutionContext] -> void } -> void
|
|
92
|
+
#: (?Symbol?) { () [self: Roast::DSL::ExecutionContext] -> void } -> void
|
|
83
93
|
def execute(scope = nil, &block)
|
|
84
94
|
(@execution_procs[scope] ||= []) << block
|
|
85
95
|
end
|
|
@@ -106,7 +116,7 @@ module Roast
|
|
|
106
116
|
# but does not evaluate any of them individually yet.
|
|
107
117
|
#: () -> void
|
|
108
118
|
def extract_dsl_procs!
|
|
109
|
-
instance_eval(@workflow_definition)
|
|
119
|
+
instance_eval(@workflow_definition, @workflow_path.realpath.to_s, 1)
|
|
110
120
|
end
|
|
111
121
|
end
|
|
112
122
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Roast
|
|
5
|
+
module DSL
|
|
6
|
+
class WorkflowContext
|
|
7
|
+
#: WorkflowParams
|
|
8
|
+
attr_reader :params
|
|
9
|
+
|
|
10
|
+
#: String
|
|
11
|
+
attr_reader :tmpdir
|
|
12
|
+
|
|
13
|
+
#: (params: WorkflowParams, tmpdir: String) -> void
|
|
14
|
+
def initialize(params:, tmpdir:)
|
|
15
|
+
@params = params
|
|
16
|
+
@tmpdir = tmpdir
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Roast
|
|
5
|
+
module DSL
|
|
6
|
+
class WorkflowParams
|
|
7
|
+
#: Array[String]
|
|
8
|
+
attr_reader :targets
|
|
9
|
+
|
|
10
|
+
#: Array[Symbol]
|
|
11
|
+
attr_reader :args
|
|
12
|
+
|
|
13
|
+
#: Hash[Symbol, String]
|
|
14
|
+
attr_reader :kwargs
|
|
15
|
+
|
|
16
|
+
#: (Array[String], Array[Symbol], Hash[Symbol, String]) -> void
|
|
17
|
+
def initialize(targets, args, kwargs)
|
|
18
|
+
@targets = targets
|
|
19
|
+
@args = args
|
|
20
|
+
@kwargs = kwargs
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# typed: ignore
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module T
|
|
5
|
+
class << self
|
|
6
|
+
def absurd(value); end
|
|
7
|
+
def all(type_a, type_b, *types); end
|
|
8
|
+
def any(type_a, type_b, *types); end
|
|
9
|
+
def attached_class; end
|
|
10
|
+
def class_of(klass); end
|
|
11
|
+
def enum(values); end
|
|
12
|
+
def nilable(type); end
|
|
13
|
+
def noreturn; end
|
|
14
|
+
def self_type; end
|
|
15
|
+
def type_alias(type = nil, &_blk); end
|
|
16
|
+
def type_parameter(name); end
|
|
17
|
+
def untyped; end
|
|
18
|
+
|
|
19
|
+
def assert_type!(value, _type, _checked: true)
|
|
20
|
+
value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cast(value, _type, _checked: true)
|
|
24
|
+
value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def let(value, _type, _checked: true)
|
|
28
|
+
value
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def must(arg, _msg = nil)
|
|
32
|
+
arg
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def proc
|
|
36
|
+
T::Proc.new
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def reveal_type(value)
|
|
40
|
+
value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def unsafe(value)
|
|
44
|
+
value
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Sig
|
|
49
|
+
def sig(arg0 = nil, &blk); end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module Helpers
|
|
53
|
+
def abstract!; end
|
|
54
|
+
def interface!; end
|
|
55
|
+
def final!; end
|
|
56
|
+
def sealed!; end
|
|
57
|
+
def mixes_in_class_methods(mod); end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module Generic
|
|
61
|
+
include(T::Helpers)
|
|
62
|
+
|
|
63
|
+
def type_parameters(*params); end
|
|
64
|
+
def type_member(variance = :invariant, fixed: nil, lower: nil, upper: BasicObject); end
|
|
65
|
+
def type_template(variance = :invariant, fixed: nil, lower: nil, upper: BasicObject); end
|
|
66
|
+
|
|
67
|
+
def [](*types)
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
module Array
|
|
73
|
+
class << self
|
|
74
|
+
def [](type); end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
Boolean = Object.new.freeze
|
|
79
|
+
|
|
80
|
+
module Configuration
|
|
81
|
+
class << self
|
|
82
|
+
def call_validation_error_handler(signature, opts); end
|
|
83
|
+
def call_validation_error_handler=(value); end
|
|
84
|
+
def default_checked_level=(default_checked_level); end
|
|
85
|
+
def enable_checking_for_sigs_marked_checked_tests; end
|
|
86
|
+
def enable_final_checks_on_hooks; end
|
|
87
|
+
def enable_legacy_t_enum_migration_mode; end
|
|
88
|
+
def reset_final_checks_on_hooks; end
|
|
89
|
+
def hard_assert_handler(str, extra); end
|
|
90
|
+
def hard_assert_handler=(value); end
|
|
91
|
+
def inline_type_error_handler(error); end
|
|
92
|
+
def inline_type_error_handler=(value); end
|
|
93
|
+
def log_info_handler(str, extra); end
|
|
94
|
+
def log_info_handler=(value); end
|
|
95
|
+
def scalar_types; end
|
|
96
|
+
def scalar_types=(values); end
|
|
97
|
+
def sealed_violation_whitelist; end
|
|
98
|
+
def sealed_violation_whitelist=(sealed_violation_whitelist); end
|
|
99
|
+
def sig_builder_error_handler=(value); end
|
|
100
|
+
def sig_validation_error_handler(error, opts); end
|
|
101
|
+
def sig_validation_error_handler=(value); end
|
|
102
|
+
def soft_assert_handler(str, extra); end
|
|
103
|
+
def soft_assert_handler=(value); end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
module Enumerable
|
|
108
|
+
class << self
|
|
109
|
+
def [](type); end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
module Enumerator
|
|
114
|
+
class << self
|
|
115
|
+
def [](type); end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
module Hash
|
|
120
|
+
class << self
|
|
121
|
+
def [](keys, values); end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class Proc
|
|
126
|
+
def bind(*_)
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def params(*_param)
|
|
131
|
+
self
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def void
|
|
135
|
+
self
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def returns(_type)
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
module Range
|
|
144
|
+
class << self
|
|
145
|
+
def [](type); end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
module Set
|
|
150
|
+
class << self
|
|
151
|
+
def [](type); end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# typed: false
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "cli/ui"
|
|
5
|
-
|
|
6
4
|
module Roast
|
|
7
5
|
module Tools
|
|
8
6
|
module ApplyDiff
|
|
@@ -64,7 +62,7 @@ module Roast
|
|
|
64
62
|
Roast::Helpers::Logger.info(cancel_msg + "\n")
|
|
65
63
|
cancel_msg
|
|
66
64
|
end
|
|
67
|
-
rescue Roast::Error => e
|
|
65
|
+
rescue Roast::Error, Errno::EACCES, Errno::ENOENT => e
|
|
68
66
|
error_message = "Error applying diff: #{e.message}"
|
|
69
67
|
Roast::Helpers::Logger.error(error_message + "\n")
|
|
70
68
|
Roast::Helpers::Logger.debug(e.backtrace.join("\n") + "\n") if ENV["DEBUG"]
|
data/lib/roast/tools/cmd.rb
CHANGED
|
@@ -153,9 +153,10 @@ module Roast
|
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
format_output(command, result, status.exitstatus)
|
|
156
|
-
rescue Timeout::Error => e
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
rescue Timeout::Error, Errno::ENOENT => e
|
|
157
|
+
error_message = "Error running command: #{e.message}"
|
|
158
|
+
Roast::Helpers::Logger.error(error_message + "\n")
|
|
159
|
+
error_message
|
|
159
160
|
end
|
|
160
161
|
|
|
161
162
|
def format_output(command, result, exit_status)
|
|
@@ -39,7 +39,7 @@ module Roast
|
|
|
39
39
|
else
|
|
40
40
|
File.read(path)
|
|
41
41
|
end
|
|
42
|
-
rescue Roast::Error => e
|
|
42
|
+
rescue Roast::Error, Errno::ENOENT, Errno::EACCES => e
|
|
43
43
|
"Error reading file: #{e.message}".tap do |error_message|
|
|
44
44
|
Roast::Helpers::Logger.error(error_message + "\n")
|
|
45
45
|
Roast::Helpers::Logger.debug(e.backtrace.join("\n") + "\n") if ENV["DEBUG"]
|
|
@@ -49,7 +49,7 @@ module Roast
|
|
|
49
49
|
Roast::Helpers::Logger.error(restriction_message)
|
|
50
50
|
"Error: Path must start with '#{restrict_path}' to use the write_file tool, try again."
|
|
51
51
|
end
|
|
52
|
-
rescue Roast::Error => e
|
|
52
|
+
rescue Roast::Error, Errno::EACCES, Errno::ENOENT => e
|
|
53
53
|
"Error writing file: #{e.message}".tap do |error_message|
|
|
54
54
|
Roast::Helpers::Logger.error(error_message + "\n")
|
|
55
55
|
Roast::Helpers::Logger.debug(e.backtrace.join("\n") + "\n") if ENV["DEBUG"]
|
data/lib/roast/version.rb
CHANGED
|
@@ -169,7 +169,14 @@ module Roast
|
|
|
169
169
|
raise StepExecutionError.new("Syntax error in step file: #{e.message}", step_name: step_name, original_error: e)
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
-
step_class = step_name.
|
|
172
|
+
step_class = if Object.const_defined?(step_name.camelize, false)
|
|
173
|
+
step_name.camelize.constantize
|
|
174
|
+
elsif Object.const_defined?(step_name.classify, false)
|
|
175
|
+
step_name.classify.constantize
|
|
176
|
+
else
|
|
177
|
+
raise StepExecutionError.new("No class named #{step_name.camelize} found in step file #{file_path}", step_name: step_name)
|
|
178
|
+
end
|
|
179
|
+
|
|
173
180
|
context = File.dirname(file_path)
|
|
174
181
|
# For Ruby steps, we instantiate the specific class directly
|
|
175
182
|
# Convert step_name to StepName value object
|
|
@@ -208,7 +215,12 @@ module Roast
|
|
|
208
215
|
def configure_step(step, step_name, is_last_step: nil)
|
|
209
216
|
step_config = config_hash[step_name]
|
|
210
217
|
|
|
211
|
-
#
|
|
218
|
+
# Apply global model if no step-specific model is configured
|
|
219
|
+
if config_hash.key?("model") && !step_config&.key?("model")
|
|
220
|
+
step.model = config_hash["model"]
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Apply step-specific model (overrides global model)
|
|
212
224
|
step.model = step_config["model"] if step_config&.key?("model")
|
|
213
225
|
|
|
214
226
|
# Pass resource to step if supported
|
data/lib/roast-ai.rb
ADDED