roast-ai 0.4.10 → 0.5.1

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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/docs/write-comments.md +36 -0
  3. data/.github/CODEOWNERS +1 -1
  4. data/.github/workflows/ci.yaml +10 -6
  5. data/.gitignore +0 -1
  6. data/.rubocop.yml +7 -1
  7. data/.ruby-version +1 -1
  8. data/CLAUDE.md +2 -2
  9. data/CONTRIBUTING.md +2 -0
  10. data/Gemfile +19 -18
  11. data/Gemfile.lock +35 -58
  12. data/README.md +118 -1432
  13. data/README_LEGACY.md +1464 -0
  14. data/Rakefile +39 -4
  15. data/dev.yml +29 -0
  16. data/dsl/agent_sessions.rb +20 -0
  17. data/dsl/async_cogs.rb +49 -0
  18. data/dsl/async_cogs_complex.rb +67 -0
  19. data/dsl/call.rb +44 -0
  20. data/dsl/collect_from.rb +72 -0
  21. data/dsl/json_output.rb +28 -0
  22. data/dsl/map.rb +55 -0
  23. data/dsl/map_reduce.rb +37 -0
  24. data/dsl/map_with_index.rb +49 -0
  25. data/dsl/next_break.rb +45 -0
  26. data/dsl/next_break_parallel.rb +44 -0
  27. data/dsl/outputs.rb +39 -0
  28. data/dsl/outputs_bang.rb +36 -0
  29. data/dsl/parallel_map.rb +37 -0
  30. data/dsl/prompts/simple_prompt.md.erb +3 -0
  31. data/dsl/prototype.rb +5 -7
  32. data/dsl/repeat_loop_results.rb +53 -0
  33. data/dsl/ruby_cog.rb +72 -0
  34. data/dsl/simple_agent.rb +18 -0
  35. data/dsl/simple_chat.rb +15 -1
  36. data/dsl/simple_repeat.rb +29 -0
  37. data/dsl/skip.rb +36 -0
  38. data/dsl/step_communication.rb +2 -3
  39. data/dsl/targets_and_params.rb +57 -0
  40. data/dsl/temperature.rb +17 -0
  41. data/dsl/temporary_directory.rb +22 -0
  42. data/dsl/tutorial/01_your_first_workflow/README.md +179 -0
  43. data/dsl/tutorial/01_your_first_workflow/configured_chat.rb +33 -0
  44. data/dsl/tutorial/01_your_first_workflow/hello.rb +23 -0
  45. data/dsl/tutorial/02_chaining_cogs/README.md +310 -0
  46. data/dsl/tutorial/02_chaining_cogs/code_review.rb +104 -0
  47. data/dsl/tutorial/02_chaining_cogs/session_resumption.rb +92 -0
  48. data/dsl/tutorial/02_chaining_cogs/simple_chain.rb +84 -0
  49. data/dsl/tutorial/03_targets_and_params/README.md +230 -0
  50. data/dsl/tutorial/03_targets_and_params/multiple_targets.rb +65 -0
  51. data/dsl/tutorial/03_targets_and_params/single_target.rb +65 -0
  52. data/dsl/tutorial/04_configuration_options/README.md +209 -0
  53. data/dsl/tutorial/04_configuration_options/control_display_and_temperature.rb +104 -0
  54. data/dsl/tutorial/04_configuration_options/simple_config.rb +68 -0
  55. data/dsl/tutorial/05_control_flow/README.md +156 -0
  56. data/dsl/tutorial/05_control_flow/conditional_execution.rb +62 -0
  57. data/dsl/tutorial/05_control_flow/handling_failures.rb +77 -0
  58. data/dsl/tutorial/06_reusable_scopes/README.md +172 -0
  59. data/dsl/tutorial/06_reusable_scopes/accessing_scope_outputs.rb +126 -0
  60. data/dsl/tutorial/06_reusable_scopes/basic_scope.rb +63 -0
  61. data/dsl/tutorial/06_reusable_scopes/parameterized_scope.rb +78 -0
  62. data/dsl/tutorial/07_processing_collections/README.md +152 -0
  63. data/dsl/tutorial/07_processing_collections/basic_map.rb +70 -0
  64. data/dsl/tutorial/07_processing_collections/parallel_map.rb +74 -0
  65. data/dsl/tutorial/08_iterative_workflows/README.md +231 -0
  66. data/dsl/tutorial/08_iterative_workflows/basic_repeat.rb +57 -0
  67. data/dsl/tutorial/08_iterative_workflows/conditional_break.rb +57 -0
  68. data/dsl/tutorial/09_async_cogs/README.md +197 -0
  69. data/dsl/tutorial/09_async_cogs/basic_async.rb +38 -0
  70. data/dsl/tutorial/README.md +222 -0
  71. data/dsl/working_directory.rb +16 -0
  72. data/exe/roast +1 -1
  73. data/internal/documentation/architectural-notes.md +115 -0
  74. data/internal/documentation/doc-comments-external.md +686 -0
  75. data/internal/documentation/doc-comments-internal.md +342 -0
  76. data/internal/documentation/doc-comments.md +211 -0
  77. data/lib/roast/dsl/cog/config.rb +274 -3
  78. data/lib/roast/dsl/cog/input.rb +53 -10
  79. data/lib/roast/dsl/cog/output.rb +297 -8
  80. data/lib/roast/dsl/cog/registry.rb +35 -3
  81. data/lib/roast/dsl/cog/stack.rb +1 -1
  82. data/lib/roast/dsl/cog/store.rb +5 -5
  83. data/lib/roast/dsl/cog.rb +70 -14
  84. data/lib/roast/dsl/cog_input_context.rb +36 -1
  85. data/lib/roast/dsl/cog_input_manager.rb +116 -7
  86. data/lib/roast/dsl/cogs/agent/config.rb +465 -0
  87. data/lib/roast/dsl/cogs/agent/input.rb +81 -0
  88. data/lib/roast/dsl/cogs/agent/output.rb +59 -0
  89. data/lib/roast/dsl/cogs/agent/provider.rb +51 -0
  90. data/lib/roast/dsl/cogs/agent/providers/claude/claude_invocation.rb +185 -0
  91. data/lib/roast/dsl/cogs/agent/providers/claude/message.rb +73 -0
  92. data/lib/roast/dsl/cogs/agent/providers/claude/messages/assistant_message.rb +36 -0
  93. data/lib/roast/dsl/cogs/agent/providers/claude/messages/result_message.rb +61 -0
  94. data/lib/roast/dsl/cogs/agent/providers/claude/messages/system_message.rb +47 -0
  95. data/lib/roast/dsl/cogs/agent/providers/claude/messages/text_message.rb +36 -0
  96. data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_result_message.rb +47 -0
  97. data/lib/roast/dsl/cogs/agent/providers/claude/messages/tool_use_message.rb +46 -0
  98. data/lib/roast/dsl/cogs/agent/providers/claude/messages/unknown_message.rb +27 -0
  99. data/lib/roast/dsl/cogs/agent/providers/claude/messages/user_message.rb +37 -0
  100. data/lib/roast/dsl/cogs/agent/providers/claude/tool_result.rb +51 -0
  101. data/lib/roast/dsl/cogs/agent/providers/claude/tool_use.rb +48 -0
  102. data/lib/roast/dsl/cogs/agent/providers/claude.rb +31 -0
  103. data/lib/roast/dsl/cogs/agent/stats.rb +92 -0
  104. data/lib/roast/dsl/cogs/agent/usage.rb +62 -0
  105. data/lib/roast/dsl/cogs/agent.rb +75 -0
  106. data/lib/roast/dsl/cogs/chat/config.rb +453 -0
  107. data/lib/roast/dsl/cogs/chat/input.rb +92 -0
  108. data/lib/roast/dsl/cogs/chat/output.rb +64 -0
  109. data/lib/roast/dsl/cogs/chat/session.rb +68 -0
  110. data/lib/roast/dsl/cogs/chat.rb +59 -56
  111. data/lib/roast/dsl/cogs/cmd.rb +251 -61
  112. data/lib/roast/dsl/cogs/ruby.rb +171 -0
  113. data/lib/roast/dsl/command_runner.rb +191 -0
  114. data/lib/roast/dsl/config_manager.rb +58 -11
  115. data/lib/roast/dsl/control_flow.rb +41 -0
  116. data/lib/roast/dsl/execution_manager.rb +162 -32
  117. data/lib/roast/dsl/nil_assertions.rb +23 -0
  118. data/lib/roast/dsl/system_cog/params.rb +32 -0
  119. data/lib/roast/dsl/system_cog.rb +36 -0
  120. data/lib/roast/dsl/system_cogs/call.rb +163 -0
  121. data/lib/roast/dsl/system_cogs/map.rb +454 -0
  122. data/lib/roast/dsl/system_cogs/repeat.rb +242 -0
  123. data/lib/roast/dsl/workflow.rb +26 -16
  124. data/lib/roast/dsl/workflow_context.rb +20 -0
  125. data/lib/roast/dsl/workflow_params.rb +24 -0
  126. data/lib/roast/helpers/minitest_coverage_runner.rb +1 -1
  127. data/lib/roast/sorbet_runtime_stub.rb +154 -0
  128. data/lib/roast/tools/apply_diff.rb +1 -3
  129. data/lib/roast/tools/cmd.rb +4 -3
  130. data/lib/roast/tools/read_file.rb +1 -1
  131. data/lib/roast/tools/update_files.rb +1 -1
  132. data/lib/roast/tools/write_file.rb +1 -1
  133. data/lib/roast/version.rb +1 -1
  134. data/lib/roast/workflow/base_workflow.rb +4 -0
  135. data/lib/roast/workflow/step_loader.rb +14 -2
  136. data/lib/roast-ai.rb +4 -0
  137. data/lib/roast.rb +58 -21
  138. data/{roast.gemspec → roast-ai.gemspec} +9 -13
  139. data/sorbet/rbi/gems/async@2.34.0.rbi +1577 -0
  140. data/sorbet/rbi/gems/cli-kit@5.2.0.rbi +2063 -0
  141. data/sorbet/rbi/gems/{cli-ui@2.3.0.rbi → cli-ui@2.7.0-6bdefd1d06305e5d6ae312ac76f9c88f88658dda.rbi} +1418 -1013
  142. data/sorbet/rbi/gems/console@1.34.2.rbi +1193 -0
  143. data/sorbet/rbi/gems/fiber-annotation@0.2.0.rbi +50 -0
  144. data/sorbet/rbi/gems/fiber-local@1.1.0.rbi +35 -0
  145. data/sorbet/rbi/gems/fiber-storage@1.0.1.rbi +41 -0
  146. data/sorbet/rbi/gems/io-event@1.14.0.rbi +724 -0
  147. data/sorbet/rbi/gems/metrics@0.15.0.rbi +9 -0
  148. data/sorbet/rbi/gems/traces@0.18.2.rbi +9 -0
  149. data/sorbet/rbi/shims/lib/roast/dsl/cog_input_context.rbi +1185 -5
  150. data/sorbet/rbi/shims/lib/roast/dsl/config_context.rbi +311 -5
  151. data/sorbet/rbi/shims/lib/roast/dsl/execution_context.rbi +486 -5
  152. data/sorbet/tapioca/config.yml +6 -0
  153. data/sorbet/tapioca/require.rb +2 -0
  154. metadata +157 -30
  155. data/dsl/less_simple.rb +0 -112
  156. data/dsl/scoped_executors.rb +0 -28
  157. data/dsl/simple.rb +0 -8
  158. data/lib/roast/dsl/cogs/execute.rb +0 -46
  159. data/lib/roast/dsl/cogs/graph.rb +0 -53
  160. data/sorbet/rbi/gems/cgi@0.5.0.rbi +0 -2961
  161. data/sorbet/rbi/gems/claude_swarm@0.1.19.rbi +0 -568
  162. data/sorbet/rbi/gems/cli-kit@5.0.1.rbi +0 -1991
  163. data/sorbet/rbi/gems/dry-configurable@1.3.0.rbi +0 -672
  164. data/sorbet/rbi/gems/dry-core@1.1.0.rbi +0 -1894
  165. data/sorbet/rbi/gems/dry-inflector@1.2.0.rbi +0 -659
  166. data/sorbet/rbi/gems/dry-initializer@3.2.0.rbi +0 -781
  167. data/sorbet/rbi/gems/dry-logic@1.6.0.rbi +0 -1127
  168. data/sorbet/rbi/gems/dry-schema@1.14.1.rbi +0 -3727
  169. data/sorbet/rbi/gems/dry-types@1.8.3.rbi +0 -3969
  170. data/sorbet/rbi/gems/fast-mcp-annotations@1.5.3.rbi +0 -1588
  171. data/sorbet/rbi/gems/mime-types-data@3.2025.0617.rbi +0 -136
  172. data/sorbet/rbi/gems/mime-types@3.7.0.rbi +0 -1342
  173. data/sorbet/rbi/gems/rack@2.2.19.rbi +0 -5676
  174. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +0 -435
  175. data/sorbet/rbi/gems/yard@0.9.37.rbi +0 -18492
@@ -0,0 +1,465 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ module Cogs
7
+ class Agent < Cog
8
+ class Config < Cog::Config
9
+ VALID_PROVIDERS = [:claude].freeze #: Array[Symbol]
10
+
11
+ # Configure the cog to use a specified provider when invoking an agent
12
+ #
13
+ # The provider is the source of the agent tool itself.
14
+ # If no provider is specified, Anthropic Claude Code (`:claude`) will be used as the default provider.
15
+ #
16
+ # A provider must be properly installed on your system in order for Roast to be able to use it.
17
+ #
18
+ # #### See Also
19
+ # - `use_default_provider!`
20
+ #
21
+ #: (Symbol) -> void
22
+ def provider(provider)
23
+ @values[:provider] = provider
24
+ end
25
+
26
+ # Configure the cog to use the default provider when invoking an agent
27
+ #
28
+ # The default provider used by Roast is Anthropic Claude Code (`:claude`).
29
+ #
30
+ # The provider must be properly installed on your system in order for Roast to be able to use it.
31
+ #
32
+ # #### See Also
33
+ # - `provider`
34
+ #
35
+ #: () -> void
36
+ def use_default_provider!
37
+ @values[:provider] = nil
38
+ end
39
+
40
+ # Get the validated provider name that the cog is configured to use when invoking an agent
41
+ #
42
+ # Note: this method will return the name of a valid provider or raise an `InvalidConfigError`.
43
+ # It will __not__, however, validate that the agent is properly installed on your system.
44
+ # If the agent is not properly installed, you will likely experience a failure when Roast attempts to
45
+ # run your workflow.
46
+ #
47
+ # #### See Also
48
+ # - `provider`
49
+ # - `use_default_provider!`
50
+ #
51
+ #: () -> Symbol
52
+ def valid_provider!
53
+ provider = @values[:provider] || VALID_PROVIDERS.first
54
+ unless VALID_PROVIDERS.include?(provider)
55
+ raise ArgumentError, "'#{provider}' is not a valid provider. Available providers include: #{VALID_PROVIDERS.join(", ")}"
56
+ end
57
+
58
+ provider
59
+ end
60
+
61
+ # Configure the cog to use a specific base command when invoking the agent
62
+ #
63
+ # The command format is provider-specific.
64
+ #
65
+ # #### See Also
66
+ # - `use_default_command!`
67
+ #
68
+ #: (String | Array[String]) -> void
69
+ def command(command)
70
+ @values[:command] = command
71
+ end
72
+
73
+ # Configure the cog to use the provider's default command when invoking the agent
74
+ #
75
+ # Note: the default command will be different for different providers.
76
+ #
77
+ # #### See Also
78
+ # - `command`
79
+ #
80
+ #: () -> void
81
+ def use_default_command!
82
+ @values[:command] = nil
83
+ end
84
+
85
+ # Get the validated, configured value of the command the cog is configured to use when running the agent
86
+ #
87
+ # Returns `nil` if the provider should use its own default command, however that is configured.
88
+ #
89
+ # #### See Also
90
+ # - `command`
91
+ # - `use_default_command!`
92
+ #
93
+ #: () -> (String | Array[String])?
94
+ def valid_command
95
+ @values[:command].presence
96
+ end
97
+
98
+ # Configure the cog to use a specific model when invoking the agent
99
+ #
100
+ # The model name format is provider-specific.
101
+ #
102
+ # #### See Also
103
+ # - `use_default_model!`
104
+ #
105
+ #: (String) -> void
106
+ def model(model)
107
+ @values[:model] = model
108
+ end
109
+
110
+ # Configure the cog to use the provider's default model when invoking the agent
111
+ #
112
+ # Note: the default model will be different for different providers.
113
+ #
114
+ # #### See Also
115
+ # - `model`
116
+ #
117
+ #: () -> void
118
+ def use_default_model!
119
+ @values[:model] = nil
120
+ end
121
+
122
+ # Get the validated, configured value of the model the cog is configured to use when running the agent
123
+ #
124
+ # Returns `nil` if the provider should use its own default model, however that is configured.
125
+ #
126
+ # #### See Also
127
+ # - `model`
128
+ # - `use_default_model!`
129
+ #
130
+ #: () -> String?
131
+ def valid_model
132
+ @values[:model].presence
133
+ end
134
+
135
+ # Configure the cog with an initial prompt component that will be appended to the agent's system prompt
136
+ # every time the agent is invoked
137
+ #
138
+ # #### See Also
139
+ # - `no_initial_prompt!`
140
+ #
141
+ #: (String) -> void
142
+ def initial_prompt(prompt)
143
+ @values[:initial_prompt] = prompt
144
+ end
145
+
146
+ # Configure the cog __not__ to append an initial prompt to the agent's system prompt when the agent is invoked
147
+ #
148
+ # #### See Also
149
+ # - `initial_prompt`
150
+ #
151
+ #: () -> void
152
+ def no_initial_prompt!
153
+ @values[:initial_prompt] = ""
154
+ end
155
+
156
+ # Get the validated, configured initial prompt that will be appended to the agent's system prompt when
157
+ # the agent is invoked
158
+ #
159
+ # Returns `nil` if __no__ prompt should be appended.
160
+ #
161
+ # #### See Also
162
+ # - `initial_prompt`
163
+ # - `no_initial_prompt!`
164
+ #
165
+ #: () -> String?
166
+ def valid_initial_prompt
167
+ @values[:initial_prompt].presence
168
+ end
169
+
170
+ # Configure the cog to apply the default set of system and user permissions when running the agent
171
+ #
172
+ # How these permissions are defined and configured is specific to the agent provider being used.
173
+ #
174
+ # The cog's default behaviour is to run with __no__ permissions.
175
+ #
176
+ # #### Alias Methods
177
+ # - `apply_permissions!`
178
+ # - `no_skip_permissions!`
179
+ #
180
+ # #### Inverse Methods
181
+ # - `no_apply_permissions!`
182
+ # - `skip_permissions!`
183
+ #
184
+ #: () -> void
185
+ def apply_permissions!
186
+ @values[:apply_permissions] = true
187
+ end
188
+
189
+ # Configure the cog to run the agent with __no__ permissions applied
190
+ #
191
+ # The cog's default behaviour is to run with __no__ permissions.
192
+ #
193
+ # #### Alias Methods
194
+ # - `no_apply_permissions!`
195
+ # - `skip_permissions!`
196
+ #
197
+ # #### Inverse Methods
198
+ # - `apply_permissions!`
199
+ # - `no_skip_permissions!`
200
+ #
201
+ #: () -> void
202
+ def no_apply_permissions!
203
+ @values[:apply_permissions] = false
204
+ end
205
+
206
+ # Check if the cog is configured to apply permissions when running the agent
207
+ #
208
+ # #### See Also
209
+ # - `apply_permissions!`
210
+ # - `no_apply_permissions!`
211
+ # - `skip_permissions!`
212
+ # - `no_skip_permissions!`
213
+ #
214
+ #: () -> bool
215
+ def apply_permissions?
216
+ !!@values[:apply_permissions]
217
+ end
218
+
219
+ # Configure the cog to display the prompt when running the agent
220
+ #
221
+ # Disabled by default.
222
+ #
223
+ # #### See Also
224
+ # - `no_show_prompt!`
225
+ # - `show_prompt?`
226
+ # - `display!`
227
+ #
228
+ #: () -> void
229
+ def show_prompt!
230
+ @values[:show_prompt] = true
231
+ end
232
+
233
+ # Configure the cog __not__ to display the prompt when running the agent
234
+ #
235
+ # This is the default behaviour.
236
+ #
237
+ # #### See Also
238
+ # - `show_prompt!`
239
+ # - `show_prompt?`
240
+ # - `no_display!`
241
+ # - `quiet!`
242
+ #
243
+ #: () -> void
244
+ def no_show_prompt!
245
+ @values[:show_prompt] = false
246
+ end
247
+
248
+ # Check if the cog is configured to display the prompt when running the agent
249
+ #
250
+ # #### See Also
251
+ # - `show_prompt!`
252
+ # - `no_show_prompt!`
253
+ #
254
+ #: () -> bool
255
+ def show_prompt?
256
+ @values.fetch(:show_prompt, false)
257
+ end
258
+
259
+ # Configure the cog to display the agent's in-progress messages when running
260
+ #
261
+ # This includes thinking blocks and other intermediate output from the agent.
262
+ # Enabled by default.
263
+ #
264
+ # #### See Also
265
+ # - `no_show_progress!`
266
+ # - `show_progress?`
267
+ # - `display!`
268
+ #
269
+ #: () -> void
270
+ def show_progress!
271
+ @values[:show_progress] = true
272
+ end
273
+
274
+ # Configure the cog __not__ to display the agent's in-progress messages when running
275
+ #
276
+ # This will hide thinking blocks and other intermediate output from the agent.
277
+ #
278
+ # #### See Also
279
+ # - `show_progress!`
280
+ # - `show_progress?`
281
+ # - `no_display!`
282
+ # - `quiet!`
283
+ #
284
+ #: () -> void
285
+ def no_show_progress!
286
+ @values[:show_progress] = false
287
+ end
288
+
289
+ # Check if the cog is configured to display the agent's in-progress messages when running
290
+ #
291
+ # #### See Also
292
+ # - `show_progress!`
293
+ # - `no_show_progress!`
294
+ #
295
+ #: () -> bool
296
+ def show_progress?
297
+ @values.fetch(:show_progress, true)
298
+ end
299
+
300
+ # Configure the cog to display the agent's final response
301
+ #
302
+ # Enabled by default.
303
+ #
304
+ # #### See Also
305
+ # - `no_show_response!`
306
+ # - `show_response?`
307
+ # - `display!`
308
+ #
309
+ #: () -> void
310
+ def show_response!
311
+ @values[:show_response] = true
312
+ end
313
+
314
+ # Configure the cog __not__ to display the agent's final response
315
+ #
316
+ # #### See Also
317
+ # - `show_response!`
318
+ # - `show_response?`
319
+ # - `no_display!`
320
+ # - `quiet!`
321
+ #
322
+ #: () -> void
323
+ def no_show_response!
324
+ @values[:show_response] = false
325
+ end
326
+
327
+ # Check if the cog is configured to display the agent's final response
328
+ #
329
+ # #### See Also
330
+ # - `show_response!`
331
+ # - `no_show_response!`
332
+ #
333
+ #: () -> bool
334
+ def show_response?
335
+ @values.fetch(:show_response, true)
336
+ end
337
+
338
+ # Configure the cog to display statistics about the agent's operation
339
+ #
340
+ # Enabled by default.
341
+ #
342
+ # #### See Also
343
+ # - `no_show_stats!`
344
+ # - `show_stats?`
345
+ # - `display!`
346
+ #
347
+ #: () -> void
348
+ def show_stats!
349
+ @values[:show_stats] = true
350
+ end
351
+
352
+ # Configure the cog __not__ to display statistics about the agent's operation
353
+ #
354
+ # #### See Also
355
+ # - `show_stats!`
356
+ # - `show_stats?`
357
+ # - `no_display!`
358
+ # - `quiet!`
359
+ #
360
+ #: () -> void
361
+ def no_show_stats!
362
+ @values[:show_stats] = false
363
+ end
364
+
365
+ # Check if the cog is configured to display statistics about the agent's operation
366
+ #
367
+ # #### See Also
368
+ # - `show_stats!`
369
+ # - `no_show_stats!`
370
+ #
371
+ #: () -> bool
372
+ def show_stats?
373
+ @values.fetch(:show_stats, true)
374
+ end
375
+
376
+ # Configure the cog to display all agent output
377
+ #
378
+ # This enables `show_prompt!`, `show_progress!`, `show_response!`, and `show_stats!`.
379
+ #
380
+ # #### See Also
381
+ # - `no_display!`
382
+ # - `quiet!`
383
+ # - `show_prompt!`
384
+ # - `show_progress!`
385
+ # - `show_response!`
386
+ # - `show_stats!`
387
+ #
388
+ #: () -> void
389
+ def display!
390
+ show_prompt!
391
+ show_progress!
392
+ show_response!
393
+ show_stats!
394
+ end
395
+
396
+ # Configure the cog to __hide__ all agent output
397
+ #
398
+ # This enables `no_show_prompt!`, `no_show_progress!`, `no_show_response!`, `no_show_stats!`.
399
+ #
400
+ # #### Alias Methods
401
+ # - `no_display!`
402
+ # - `quiet!`
403
+ #
404
+ # #### See Also
405
+ # - `display!`
406
+ # - `quiet!`
407
+ # - `no_show_prompt!`
408
+ # - `no_show_progress!`
409
+ # - `no_show_response!`
410
+ # - `no_show_stats!`
411
+ #
412
+ #: () -> void
413
+ def no_display!
414
+ no_show_prompt!
415
+ no_show_progress!
416
+ no_show_response!
417
+ no_show_stats!
418
+ end
419
+
420
+ # Check if the cog is configured to display any output while running
421
+ #
422
+ # #### See Also
423
+ # - `show_prompt?`
424
+ # - `show_progress?`
425
+ # - `show_response?`
426
+ # - `show_stats?`
427
+ #
428
+ #: () -> bool
429
+ def display?
430
+ show_prompt? || show_progress? || show_response? || show_stats?
431
+ end
432
+
433
+ # Configure the cog to dump raw messages received from the agent process to a file
434
+ #
435
+ # This is intended for development and debugging purposes to inspect the raw message stream
436
+ # from the agent provider.
437
+ #
438
+ #: (String) -> void
439
+ def dump_raw_agent_messages_to(filename)
440
+ @values[:dump_raw_agent_messages_to] = filename
441
+ end
442
+
443
+ # Get the validated, configured path to which raw agent messages should be dumped
444
+ #
445
+ # Returns `nil` if no path has been configured.
446
+ #
447
+ # This is intended for development and debugging purposes to inspect the raw message stream
448
+ # from the agent provider.
449
+ #
450
+ # #### See Also
451
+ # - `dump_raw_agent_messages_to`
452
+ #
453
+ #: () -> Pathname?
454
+ def valid_dump_raw_agent_messages_to_path
455
+ Pathname.new(@values[:dump_raw_agent_messages_to]) if @values[:dump_raw_agent_messages_to]
456
+ end
457
+
458
+ alias_method(:skip_permissions!, :no_apply_permissions!)
459
+ alias_method(:no_skip_permissions!, :apply_permissions!)
460
+ alias_method(:quiet!, :no_display!)
461
+ end
462
+ end
463
+ end
464
+ end
465
+ end
@@ -0,0 +1,81 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ module Cogs
7
+ class Agent < Cog
8
+ # Input specification for the agent cog
9
+ #
10
+ # The agent cog requires a prompt that will be sent to the agent for processing.
11
+ # Optionally, a session identifier can be provided to maintain context across multiple invocations.
12
+ class Input < Cog::Input
13
+ # The prompt to send to the agent for processing
14
+ #
15
+ #: String?
16
+ attr_accessor :prompt
17
+
18
+ # Optional session identifier for maintaining conversation context
19
+ #
20
+ # When provided, the agent will use this session to maintain context across
21
+ # multiple invocations, allowing for conversational interactions.
22
+ #
23
+ # The agent will fork a new session from this point, so multiple agents can resume from the
24
+ # same session state.
25
+ #
26
+ #: String?
27
+ attr_accessor :session
28
+
29
+ #: () -> void
30
+ def initialize
31
+ super
32
+ @prompt = nil #: String?
33
+ end
34
+
35
+ # Validate that the input has all required parameters
36
+ #
37
+ # This method ensures that a prompt has been provided before the agent executes.
38
+ #
39
+ # #### See Also
40
+ # - `coerce`
41
+ # - `valid_prompt!`
42
+ #
43
+ #: () -> void
44
+ def validate!
45
+ valid_prompt!
46
+ end
47
+
48
+ # Coerce the input from the return value of the input block
49
+ #
50
+ # If the input block returns a String, it will be used as the prompt value.
51
+ #
52
+ # #### See Also
53
+ # - `validate!`
54
+ #
55
+ #: (untyped) -> void
56
+ def coerce(input_return_value)
57
+ if input_return_value.is_a?(String)
58
+ self.prompt ||= input_return_value
59
+ end
60
+ end
61
+
62
+ # Get the validated prompt value
63
+ #
64
+ # Returns the prompt if it is present, otherwise raises an `InvalidInputError`.
65
+ #
66
+ # #### See Also
67
+ # - `prompt`
68
+ # - `validate!`
69
+ #
70
+ #: () -> String
71
+ def valid_prompt!
72
+ valid_prompt = @prompt
73
+ raise Cog::Input::InvalidInputError, "'prompt' is required" unless valid_prompt.present?
74
+
75
+ valid_prompt
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,59 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ module Cogs
7
+ class Agent < Cog
8
+ # Output from running the agent cog
9
+ #
10
+ # Contains the agent's final response text, session identifier for conversation continuity,
11
+ # and statistics about the agent execution.
12
+ class Output < Cog::Output
13
+ include Cog::Output::WithJson
14
+ include Cog::Output::WithNumber
15
+ include Cog::Output::WithText
16
+
17
+ # The agent's final response text
18
+ #
19
+ # This is the text content of the agent's last message in the conversation.
20
+ # For multi-turn conversations, this represents only the final response, not the
21
+ # entire conversation history.
22
+ #
23
+ # #### See Also
24
+ # - `text` (from WithText module)
25
+ # - `lines` (from WithText module)
26
+ #
27
+ #: String
28
+ attr_reader :response
29
+
30
+ # The session identifier for this agent conversation
31
+ #
32
+ # This identifier can be used to resume the conversation in subsequent agent invocations.
33
+ # When provided to a new agent cog's input, the agent will have access to the full
34
+ # conversation history from this session.
35
+ #
36
+ # An agent resuming from this session will fork the session, so multiple agents can
37
+ # independently resume from the same initial session and each see the same state.
38
+ #
39
+ #: String
40
+ attr_reader :session
41
+
42
+ # Statistics about the agent execution
43
+ #
44
+ # Contains metrics such as execution duration, number of turns (back-and-forth exchanges
45
+ # with the agent), token usage, and per-model usage breakdown.
46
+ #
47
+ #: Stats
48
+ attr_reader :stats
49
+
50
+ private
51
+
52
+ def raw_text
53
+ response
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,51 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ module Cogs
7
+ class Agent < Cog
8
+ # Abstract base class for agent provider implementations
9
+ #
10
+ # Providers are responsible for interfacing with specific agent backends (e.g., Claude)
11
+ # to execute agent requests. Each provider must implement the `invoke` method to handle
12
+ # agent execution according to their specific API requirements.
13
+ #
14
+ # Subclasses should override `invoke` to provide concrete implementations that communicate
15
+ # with their respective agent services.
16
+ class Provider
17
+ # Initialize a new provider with the given configuration
18
+ #
19
+ # Stores the agent configuration for use during invocation. The configuration contains
20
+ # all settings needed to communicate with the agent service, such as API keys, model
21
+ # names, and execution parameters.
22
+ #
23
+ # #### See Also
24
+ # - `invoke`
25
+ #
26
+ #: (Config) -> void
27
+ def initialize(config)
28
+ super()
29
+ @config = config
30
+ end
31
+
32
+ # Execute an agent request and return the result
33
+ #
34
+ # This method must be implemented by subclasses to handle the actual agent execution.
35
+ # Implementations should use the stored configuration to set up the request, send the
36
+ # input to the agent service, and return a properly formatted output.
37
+ #
38
+ # Raises `NotImplementedError` if called on the base Provider class.
39
+ #
40
+ # #### See Also
41
+ # - `initialize`
42
+ #
43
+ #: (Input) -> Output
44
+ def invoke(input)
45
+ raise NotImplementedError, "Subclasses must implement #invoke"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end