riffer 0.47.1 → 0.48.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.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/rules/rbs-inline.md +5 -1
  3. data/.release-please-manifest.json +1 -1
  4. data/CHANGELOG.md +31 -0
  5. data/Rakefile +1 -1
  6. data/Steepfile +1 -15
  7. data/docs/AGENTS.md +37 -3
  8. data/docs/AGENT_LIFECYCLE.md +1 -0
  9. data/docs/CONFIGURATION.md +1 -1
  10. data/docs/EVALS.md +2 -1
  11. data/docs/MCP.md +0 -4
  12. data/docs/MESSAGES.md +85 -17
  13. data/docs/STREAM_EVENTS.md +31 -4
  14. data/docs/TRACING.md +1 -1
  15. data/docs/providers/AMAZON_BEDROCK.md +1 -1
  16. data/docs/providers/CUSTOM_PROVIDERS.md +58 -4
  17. data/docs/providers/GEMINI.md +1 -1
  18. data/docs/providers/MOCK_PROVIDER.md +17 -0
  19. data/lib/riffer/agent/config.rb +40 -16
  20. data/lib/riffer/agent/outcome.rb +2 -2
  21. data/lib/riffer/agent/response.rb +16 -9
  22. data/lib/riffer/agent/run.rb +24 -9
  23. data/lib/riffer/agent/session.rb +2 -1
  24. data/lib/riffer/agent/structured_output/result.rb +2 -2
  25. data/lib/riffer/agent/structured_output.rb +1 -1
  26. data/lib/riffer/agent.rb +40 -16
  27. data/lib/riffer/config.rb +31 -31
  28. data/lib/riffer/evals/evaluator.rb +29 -2
  29. data/lib/riffer/evals/judge.rb +13 -8
  30. data/lib/riffer/evals/result.rb +6 -6
  31. data/lib/riffer/evals/run_result.rb +1 -1
  32. data/lib/riffer/evals/scenario_result.rb +6 -6
  33. data/lib/riffer/files/resolver.rb +3 -3
  34. data/lib/riffer/guardrails/modification.rb +3 -3
  35. data/lib/riffer/guardrails/result.rb +3 -3
  36. data/lib/riffer/guardrails/runner.rb +4 -4
  37. data/lib/riffer/guardrails/tripwire.rb +4 -4
  38. data/lib/riffer/helpers/deep_dup.rb +42 -0
  39. data/lib/riffer/mcp/manifest.rb +5 -5
  40. data/lib/riffer/mcp/registration.rb +1 -1
  41. data/lib/riffer/mcp/search_tool.rb +1 -1
  42. data/lib/riffer/messages/assistant/reasoning_part.rb +90 -0
  43. data/lib/riffer/messages/assistant/tool_call.rb +63 -0
  44. data/lib/riffer/messages/assistant.rb +55 -7
  45. data/lib/riffer/messages/base.rb +7 -25
  46. data/lib/riffer/messages/system.rb +10 -0
  47. data/lib/riffer/messages/tool.rb +21 -4
  48. data/lib/riffer/messages/{file_part.rb → user/file_part.rb} +18 -17
  49. data/lib/riffer/messages/user.rb +13 -2
  50. data/lib/riffer/params/param.rb +20 -8
  51. data/lib/riffer/params.rb +10 -1
  52. data/lib/riffer/providers/amazon_bedrock.rb +34 -6
  53. data/lib/riffer/providers/anthropic.rb +9 -2
  54. data/lib/riffer/providers/base.rb +28 -10
  55. data/lib/riffer/providers/finish_reason.rb +2 -2
  56. data/lib/riffer/providers/gemini.rb +2 -2
  57. data/lib/riffer/providers/mock.rb +19 -3
  58. data/lib/riffer/providers/open_ai.rb +14 -5
  59. data/lib/riffer/providers/open_router.rb +6 -5
  60. data/lib/riffer/providers/repository.rb +0 -4
  61. data/lib/riffer/providers/token_usage.rb +21 -5
  62. data/lib/riffer/skills/adapter.rb +1 -1
  63. data/lib/riffer/skills/config.rb +12 -0
  64. data/lib/riffer/skills/context.rb +4 -7
  65. data/lib/riffer/skills/filesystem_backend.rb +1 -2
  66. data/lib/riffer/skills/frontmatter.rb +4 -4
  67. data/lib/riffer/skills/xml_adapter.rb +1 -1
  68. data/lib/riffer/stream_events/base.rb +1 -1
  69. data/lib/riffer/stream_events/finish_reason_done.rb +2 -2
  70. data/lib/riffer/stream_events/guardrail_modification.rb +1 -1
  71. data/lib/riffer/stream_events/guardrail_tripwire.rb +1 -1
  72. data/lib/riffer/stream_events/interrupt.rb +2 -2
  73. data/lib/riffer/stream_events/reasoning_delta.rb +1 -1
  74. data/lib/riffer/stream_events/reasoning_done.rb +10 -8
  75. data/lib/riffer/stream_events/skill_activation.rb +1 -1
  76. data/lib/riffer/stream_events/text_delta.rb +1 -1
  77. data/lib/riffer/stream_events/text_done.rb +1 -1
  78. data/lib/riffer/stream_events/token_usage_done.rb +1 -1
  79. data/lib/riffer/stream_events/tool_call_delta.rb +3 -3
  80. data/lib/riffer/stream_events/tool_call_done.rb +4 -4
  81. data/lib/riffer/stream_events/web_search_done.rb +2 -2
  82. data/lib/riffer/stream_events/web_search_status.rb +3 -3
  83. data/lib/riffer/tools/response.rb +4 -4
  84. data/lib/riffer/tools/runtime.rb +3 -4
  85. data/lib/riffer/tracing/capture.rb +2 -4
  86. data/lib/riffer/tracing/stream_recorder.rb +6 -6
  87. data/lib/riffer/version.rb +1 -1
  88. data/lib/riffer.rb +7 -0
  89. data/rbs_collection.lock.yaml +320 -0
  90. data/rbs_collection.yaml +12 -0
  91. data/sig/_private/anthropic.rbs +5 -4
  92. data/sig/_private/aws-sdk-core/event_error.rbs +15 -0
  93. data/sig/generated/riffer/agent/config.rbs +19 -5
  94. data/sig/generated/riffer/agent/response.rbs +6 -1
  95. data/sig/generated/riffer/agent/run.rbs +15 -8
  96. data/sig/generated/riffer/agent.rbs +25 -9
  97. data/sig/generated/riffer/config.rbs +1 -1
  98. data/sig/generated/riffer/evals/evaluator.rbs +20 -1
  99. data/sig/generated/riffer/evals/judge.rbs +5 -2
  100. data/sig/generated/riffer/files/resolver.rbs +6 -6
  101. data/sig/generated/riffer/helpers/deep_dup.rbs +21 -0
  102. data/sig/generated/riffer/messages/assistant/reasoning_part.rbs +58 -0
  103. data/sig/generated/riffer/messages/assistant/tool_call.rbs +42 -0
  104. data/sig/generated/riffer/messages/assistant.rbs +24 -10
  105. data/sig/generated/riffer/messages/system.rbs +6 -0
  106. data/sig/generated/riffer/messages/tool.rbs +6 -0
  107. data/sig/generated/riffer/messages/{file_part.rbs → user/file_part.rbs} +11 -6
  108. data/sig/generated/riffer/messages/user.rbs +9 -3
  109. data/sig/generated/riffer/params/param.rbs +7 -0
  110. data/sig/generated/riffer/params.rbs +6 -0
  111. data/sig/generated/riffer/providers/amazon_bedrock.rbs +14 -5
  112. data/sig/generated/riffer/providers/anthropic.rbs +2 -2
  113. data/sig/generated/riffer/providers/base.rbs +22 -10
  114. data/sig/generated/riffer/providers/gemini.rbs +4 -4
  115. data/sig/generated/riffer/providers/mock.rbs +7 -2
  116. data/sig/generated/riffer/providers/open_ai.rbs +4 -4
  117. data/sig/generated/riffer/providers/open_router.rbs +4 -4
  118. data/sig/generated/riffer/providers/repository.rbs +0 -2
  119. data/sig/generated/riffer/providers/token_usage.rbs +6 -0
  120. data/sig/generated/riffer/skills/config.rbs +9 -0
  121. data/sig/generated/riffer/stream_events/reasoning_done.rbs +8 -6
  122. data/sig/generated/riffer/tools/runtime.rbs +2 -2
  123. data/sig/generated/riffer/tracing/capture.rbs +4 -4
  124. data/sig/generated/riffer.rbs +8 -0
  125. data/sig/manual/riffer/helpers/deep_dup.rbs +5 -0
  126. metadata +13 -5
  127. data/sig/_private/async.rbs +0 -28
  128. data/sig/_private/minitest.rbs +0 -9
@@ -0,0 +1,320 @@
1
+ ---
2
+ path: ".gem_rbs_collection"
3
+ gems:
4
+ - name: addressable
5
+ version: '2.8'
6
+ source:
7
+ type: git
8
+ name: ruby/gem_rbs_collection
9
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
10
+ remote: https://github.com/ruby/gem_rbs_collection.git
11
+ repo_dir: gems
12
+ - name: anthropic
13
+ version: 1.71.0
14
+ source:
15
+ type: rubygems
16
+ - name: ast
17
+ version: '2.4'
18
+ source:
19
+ type: git
20
+ name: ruby/gem_rbs_collection
21
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
22
+ remote: https://github.com/ruby/gem_rbs_collection.git
23
+ repo_dir: gems
24
+ - name: async
25
+ version: '2.12'
26
+ source:
27
+ type: git
28
+ name: ruby/gem_rbs_collection
29
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
30
+ remote: https://github.com/ruby/gem_rbs_collection.git
31
+ repo_dir: gems
32
+ - name: aws-sdk-bedrockruntime
33
+ version: 1.85.0
34
+ source:
35
+ type: rubygems
36
+ - name: aws-sdk-core
37
+ version: 3.257.0
38
+ source:
39
+ type: rubygems
40
+ - name: base64
41
+ version: 0.3.0
42
+ source:
43
+ type: rubygems
44
+ - name: bigdecimal
45
+ version: 4.1.3
46
+ source:
47
+ type: rubygems
48
+ - name: cgi
49
+ version: '0.5'
50
+ source:
51
+ type: git
52
+ name: ruby/gem_rbs_collection
53
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
54
+ remote: https://github.com/ruby/gem_rbs_collection.git
55
+ repo_dir: gems
56
+ - name: concurrent-ruby
57
+ version: '1.1'
58
+ source:
59
+ type: git
60
+ name: ruby/gem_rbs_collection
61
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
62
+ remote: https://github.com/ruby/gem_rbs_collection.git
63
+ repo_dir: gems
64
+ - name: connection_pool
65
+ version: '2.4'
66
+ source:
67
+ type: git
68
+ name: ruby/gem_rbs_collection
69
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
70
+ remote: https://github.com/ruby/gem_rbs_collection.git
71
+ repo_dir: gems
72
+ - name: csv
73
+ version: '3.3'
74
+ source:
75
+ type: git
76
+ name: ruby/gem_rbs_collection
77
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
78
+ remote: https://github.com/ruby/gem_rbs_collection.git
79
+ repo_dir: gems
80
+ - name: dbm
81
+ version: '0'
82
+ source:
83
+ type: stdlib
84
+ - name: delegate
85
+ version: '0'
86
+ source:
87
+ type: stdlib
88
+ - name: digest
89
+ version: '0'
90
+ source:
91
+ type: stdlib
92
+ - name: erb
93
+ version: '0'
94
+ source:
95
+ type: stdlib
96
+ - name: faraday
97
+ version: '2.7'
98
+ source:
99
+ type: git
100
+ name: ruby/gem_rbs_collection
101
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
102
+ remote: https://github.com/ruby/gem_rbs_collection.git
103
+ repo_dir: gems
104
+ - name: ffi
105
+ version: 1.17.4
106
+ source:
107
+ type: rubygems
108
+ - name: fileutils
109
+ version: '0'
110
+ source:
111
+ type: stdlib
112
+ - name: forwardable
113
+ version: '0'
114
+ source:
115
+ type: stdlib
116
+ - name: hashdiff
117
+ version: '1.1'
118
+ source:
119
+ type: git
120
+ name: ruby/gem_rbs_collection
121
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
122
+ remote: https://github.com/ruby/gem_rbs_collection.git
123
+ repo_dir: gems
124
+ - name: io-console
125
+ version: '0'
126
+ source:
127
+ type: stdlib
128
+ - name: json
129
+ version: '0'
130
+ source:
131
+ type: stdlib
132
+ - name: language_server-protocol
133
+ version: 3.17.0.6
134
+ source:
135
+ type: rubygems
136
+ - name: listen
137
+ version: '3.9'
138
+ source:
139
+ type: git
140
+ name: ruby/gem_rbs_collection
141
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
142
+ remote: https://github.com/ruby/gem_rbs_collection.git
143
+ repo_dir: gems
144
+ - name: logger
145
+ version: '1.7'
146
+ source:
147
+ type: git
148
+ name: ruby/gem_rbs_collection
149
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
150
+ remote: https://github.com/ruby/gem_rbs_collection.git
151
+ repo_dir: gems
152
+ - name: minitest
153
+ version: '5.25'
154
+ source:
155
+ type: git
156
+ name: ruby/gem_rbs_collection
157
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
158
+ remote: https://github.com/ruby/gem_rbs_collection.git
159
+ repo_dir: gems
160
+ - name: monitor
161
+ version: '0'
162
+ source:
163
+ type: stdlib
164
+ - name: net-http
165
+ version: '0'
166
+ source:
167
+ type: stdlib
168
+ - name: net-protocol
169
+ version: '0'
170
+ source:
171
+ type: stdlib
172
+ - name: openai
173
+ version: 0.91.0
174
+ source:
175
+ type: rubygems
176
+ - name: openssl
177
+ version: '0'
178
+ source:
179
+ type: stdlib
180
+ - name: optparse
181
+ version: '0'
182
+ source:
183
+ type: stdlib
184
+ - name: parser
185
+ version: '3.2'
186
+ source:
187
+ type: git
188
+ name: ruby/gem_rbs_collection
189
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
190
+ remote: https://github.com/ruby/gem_rbs_collection.git
191
+ repo_dir: gems
192
+ - name: pp
193
+ version: '0'
194
+ source:
195
+ type: stdlib
196
+ - name: prettyprint
197
+ version: '0'
198
+ source:
199
+ type: stdlib
200
+ - name: prism
201
+ version: 1.9.0
202
+ source:
203
+ type: rubygems
204
+ - name: pstore
205
+ version: '0.2'
206
+ source:
207
+ type: git
208
+ name: ruby/gem_rbs_collection
209
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
210
+ remote: https://github.com/ruby/gem_rbs_collection.git
211
+ repo_dir: gems
212
+ - name: psych
213
+ version: '0'
214
+ source:
215
+ type: stdlib
216
+ - name: rainbow
217
+ version: '3.0'
218
+ source:
219
+ type: git
220
+ name: ruby/gem_rbs_collection
221
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
222
+ remote: https://github.com/ruby/gem_rbs_collection.git
223
+ repo_dir: gems
224
+ - name: rake
225
+ version: '13.0'
226
+ source:
227
+ type: git
228
+ name: ruby/gem_rbs_collection
229
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
230
+ remote: https://github.com/ruby/gem_rbs_collection.git
231
+ repo_dir: gems
232
+ - name: random-formatter
233
+ version: '0'
234
+ source:
235
+ type: stdlib
236
+ - name: rbs
237
+ version: 4.2.0
238
+ source:
239
+ type: rubygems
240
+ - name: rbs-inline
241
+ version: 0.14.0
242
+ source:
243
+ type: rubygems
244
+ - name: rdoc
245
+ version: '0'
246
+ source:
247
+ type: stdlib
248
+ - name: regexp_parser
249
+ version: '2.8'
250
+ source:
251
+ type: git
252
+ name: ruby/gem_rbs_collection
253
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
254
+ remote: https://github.com/ruby/gem_rbs_collection.git
255
+ repo_dir: gems
256
+ - name: securerandom
257
+ version: '0'
258
+ source:
259
+ type: stdlib
260
+ - name: singleton
261
+ version: '0'
262
+ source:
263
+ type: stdlib
264
+ - name: socket
265
+ version: '0'
266
+ source:
267
+ type: stdlib
268
+ - name: stringio
269
+ version: '0'
270
+ source:
271
+ type: stdlib
272
+ - name: strscan
273
+ version: '0'
274
+ source:
275
+ type: stdlib
276
+ - name: tempfile
277
+ version: '0'
278
+ source:
279
+ type: stdlib
280
+ - name: thor
281
+ version: '1.2'
282
+ source:
283
+ type: git
284
+ name: ruby/gem_rbs_collection
285
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
286
+ remote: https://github.com/ruby/gem_rbs_collection.git
287
+ repo_dir: gems
288
+ - name: timeout
289
+ version: '0'
290
+ source:
291
+ type: stdlib
292
+ - name: tmpdir
293
+ version: '0'
294
+ source:
295
+ type: stdlib
296
+ - name: tsort
297
+ version: '0'
298
+ source:
299
+ type: stdlib
300
+ - name: uri
301
+ version: '0'
302
+ source:
303
+ type: stdlib
304
+ - name: webmock
305
+ version: '3.19'
306
+ source:
307
+ type: git
308
+ name: ruby/gem_rbs_collection
309
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
310
+ remote: https://github.com/ruby/gem_rbs_collection.git
311
+ repo_dir: gems
312
+ - name: webrick
313
+ version: 1.9.2
314
+ source:
315
+ type: rubygems
316
+ - name: yaml
317
+ version: '0'
318
+ source:
319
+ type: stdlib
320
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,12 @@
1
+ sources:
2
+ - type: git
3
+ name: ruby/gem_rbs_collection
4
+ remote: https://github.com/ruby/gem_rbs_collection.git
5
+ revision: 3913b7dffb65bdffdfe5cb9095108f932e85433b
6
+ repo_dir: gems
7
+
8
+ path: .gem_rbs_collection
9
+
10
+ gems:
11
+ - name: yaml
12
+ - name: cgi
@@ -1,7 +1,7 @@
1
- # Arity patch for the `anthropic` gem (see openai.rbs for the rationale).
2
- # `Messages#create` is positional at runtime but typed keyword-only in the gem's
3
- # RBS; `Messages#stream` is omitted from the gem's RBS but present at runtime
4
- # (returns a MessageStream helper). Loaded only for riffer's own Steep run.
1
+ # Arity patch for the `anthropic` gem (see openai.rbs for the rationale). Both
2
+ # `Messages#create` and `Messages#stream` are positional `def x(params)` at
3
+ # runtime but typed keyword-only in the gem's RBS. Streaming returns `untyped`
4
+ # (a MessageStream helper). Loaded only for riffer's own Steep run.
5
5
  module Anthropic
6
6
  module Resources
7
7
  class Messages
@@ -11,6 +11,7 @@ module Anthropic
11
11
 
12
12
  def stream: (Hash[Symbol, untyped] params) -> untyped
13
13
  | (**untyped) -> untyped
14
+ | ...
14
15
  end
15
16
  end
16
17
  end
@@ -0,0 +1,15 @@
1
+ # aws-sdk-core ships no signature for EventError; ConverseStream delivers
2
+ # `:message-type: error` frames to the on_event block as instances of it.
3
+ module Aws
4
+ module Errors
5
+ class EventError < RuntimeError
6
+ def initialize: (Symbol event_type, String code, String message) -> void
7
+
8
+ attr_reader event_type: Symbol
9
+
10
+ attr_reader error_code: String
11
+
12
+ attr_reader error_message: String
13
+ end
14
+ end
15
+ end
@@ -6,6 +6,8 @@
6
6
  class Riffer::Agent::Config
7
7
  DEFAULT_MAX_STEPS: Integer
8
8
 
9
+ @tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?
10
+
9
11
  # The configured agent identifier.
10
12
  attr_reader identifier: String?
11
13
 
@@ -30,9 +32,6 @@ class Riffer::Agent::Config
30
32
  # The accumulated +use_mcp+ tag configurations.
31
33
  attr_reader mcp_configs: Array[Hash[Symbol, untyped]]
32
34
 
33
- # The configured tool runtime.
34
- attr_reader tool_runtime: singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc
35
-
36
35
  # The configured skills.
37
36
  attr_accessor skills_config: Riffer::Skills::Config?
38
37
 
@@ -51,11 +50,11 @@ class Riffer::Agent::Config
51
50
  # ?max_steps: Numeric?,
52
51
  # ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?,
53
52
  # ?mcp_configs: Array[Hash[Symbol, untyped]],
54
- # ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc),
53
+ # ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?,
55
54
  # ?skills_config: Riffer::Skills::Config?,
56
55
  # ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]
57
56
  # ) -> void
58
- def initialize: (?identifier: String?, ?model: (String | Proc)?, ?instructions: (String | Proc)?, ?model_options: Hash[Symbol, untyped], ?structured_output: Riffer::Params?, ?max_steps: Numeric?, ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?, ?mcp_configs: Array[Hash[Symbol, untyped]], ?tool_runtime: singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc, ?skills_config: Riffer::Skills::Config?, ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]) -> void
57
+ def initialize: (?identifier: String?, ?model: (String | Proc)?, ?instructions: (String | Proc)?, ?model_options: Hash[Symbol, untyped], ?structured_output: Riffer::Params?, ?max_steps: Numeric?, ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?, ?mcp_configs: Array[Hash[Symbol, untyped]], ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?, ?skills_config: Riffer::Skills::Config?, ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]) -> void
59
58
 
60
59
  # Sets +identifier+, coercing the value to String.
61
60
  # --
@@ -67,6 +66,13 @@ class Riffer::Agent::Config
67
66
  # : (Riffer::Params?) -> Riffer::Params?
68
67
  def structured_output=: (Riffer::Params?) -> Riffer::Params?
69
68
 
69
+ # Returns the declared tool runtime, or +Riffer.config.tool_runtime+ when none
70
+ # was declared. Resolving the global here rather than at construction is what
71
+ # lets a copy tell an inherited runtime from a defaulted one.
72
+ # --
73
+ # : () -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
74
+ def tool_runtime: () -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
75
+
70
76
  # Sets +tool_runtime+. Raises Riffer::ArgumentError on an invalid value.
71
77
  # --
72
78
  # : ((singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
@@ -105,6 +111,14 @@ class Riffer::Agent::Config
105
111
 
106
112
  private
107
113
 
114
+ # +dup+ would leave the copy sharing every collection with this one, so a
115
+ # declaration on either would reach the other. The nesting runs deeper than one
116
+ # level: an mcp entry holds its own +:tags+ array, a guardrail entry its own
117
+ # +:options+ hash, and +model_options+ is arbitrary.
118
+ # --
119
+ # : (Riffer::Agent::Config) -> void
120
+ def initialize_copy: (Riffer::Agent::Config) -> void
121
+
108
122
  # --
109
123
  # : (untyped, String) -> void
110
124
  def validate_string_or_proc!: (untyped, String) -> void
@@ -23,6 +23,10 @@ class Riffer::Agent::Response
23
23
  # The modifications made by guardrails during processing.
24
24
  attr_reader modifications: Array[Riffer::Guardrails::Modification]
25
25
 
26
+ # The reasoning parts on the final assistant message, if the provider
27
+ # produced any.
28
+ attr_reader reasoning: Array[Riffer::Messages::Assistant::ReasoningPart]
29
+
26
30
  # The parsed structured output, if structured output was configured.
27
31
  attr_reader structured_output: Hash[Symbol, untyped]?
28
32
 
@@ -46,13 +50,14 @@ class Riffer::Agent::Response
46
50
  # outcome: Riffer::Agent::Outcome,
47
51
  # ?tripwire: Riffer::Guardrails::Tripwire?,
48
52
  # ?modifications: Array[Riffer::Guardrails::Modification],
53
+ # ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart],
49
54
  # ?structured_output: Hash[Symbol, untyped]?,
50
55
  # ?messages: Array[Riffer::Messages::Base],
51
56
  # ?healed_tool_call_ids: Array[String],
52
57
  # ?token_usage: Riffer::Providers::TokenUsage?,
53
58
  # ?steps: Integer
54
59
  # ) -> void
55
- def initialize: (String, outcome: Riffer::Agent::Outcome, ?tripwire: Riffer::Guardrails::Tripwire?, ?modifications: Array[Riffer::Guardrails::Modification], ?structured_output: Hash[Symbol, untyped]?, ?messages: Array[Riffer::Messages::Base], ?healed_tool_call_ids: Array[String], ?token_usage: Riffer::Providers::TokenUsage?, ?steps: Integer) -> void
60
+ def initialize: (String, outcome: Riffer::Agent::Outcome, ?tripwire: Riffer::Guardrails::Tripwire?, ?modifications: Array[Riffer::Guardrails::Modification], ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart], ?structured_output: Hash[Symbol, untyped]?, ?messages: Array[Riffer::Messages::Base], ?healed_tool_call_ids: Array[String], ?token_usage: Riffer::Providers::TokenUsage?, ?steps: Integer) -> void
56
61
 
57
62
  # Returns true if any guardrail modified data during processing.
58
63
  #
@@ -7,20 +7,21 @@ module Riffer::Agent::Run
7
7
  # for prompt/files semantics.
8
8
  #
9
9
  # --
10
- # : (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
11
- def generate: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
10
+ # : (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
11
+ def generate: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
12
12
 
13
13
  # Runs the streaming loop for the given agent. See Riffer::Agent#stream
14
14
  # for prompt/files semantics.
15
15
  #
16
16
  # --
17
- # : (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
18
- def stream: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
17
+ # : (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
18
+ def stream: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
19
19
 
20
20
  private
21
21
 
22
22
  # Both +generate+ and +stream+ funnel here, so this is the single place raw
23
- # +tags+ are normalized. The clean <tt>String => String</tt> map is then
23
+ # +tags+ are normalized and merged over the default tags (a caller tag wins
24
+ # on a shared key). The clean <tt>String => String</tt> map is then
24
25
  # threaded to every span builder in the run as +riffer.tag.*+ and to each
25
26
  # provider call (via +merged_model_options+) for native request-metadata
26
27
  # mapping.
@@ -100,6 +101,11 @@ module Riffer::Agent::Run
100
101
  # : (Riffer::Agent, ?Hash[String, String]) -> Hash[Symbol, untyped]
101
102
  def merged_model_options: (Riffer::Agent, ?Hash[String, String]) -> Hash[Symbol, untyped]
102
103
 
104
+ # The tags riffer adds to every run, identifying the agent it's on behalf of.
105
+ # --
106
+ # : (Riffer::Agent) -> Hash[String, String]
107
+ def default_tags: (Riffer::Agent) -> Hash[String, String]
108
+
103
109
  # --
104
110
  # : (
105
111
  # Riffer::Agent,
@@ -107,18 +113,19 @@ module Riffer::Agent::Run
107
113
  # outcome: Riffer::Agent::Outcome,
108
114
  # ?tripwire: Riffer::Guardrails::Tripwire?,
109
115
  # ?modifications: Array[Riffer::Guardrails::Modification],
116
+ # ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart],
110
117
  # ?structured_output: Hash[Symbol, untyped]?,
111
118
  # ?healed_tool_call_ids: Array[String],
112
119
  # ?token_usage: Riffer::Providers::TokenUsage?,
113
120
  # ?steps: Integer
114
121
  # ) -> Riffer::Agent::Response
115
- def build_response: (Riffer::Agent, String, outcome: Riffer::Agent::Outcome, ?tripwire: Riffer::Guardrails::Tripwire?, ?modifications: Array[Riffer::Guardrails::Modification], ?structured_output: Hash[Symbol, untyped]?, ?healed_tool_call_ids: Array[String], ?token_usage: Riffer::Providers::TokenUsage?, ?steps: Integer) -> Riffer::Agent::Response
122
+ def build_response: (Riffer::Agent, String, outcome: Riffer::Agent::Outcome, ?tripwire: Riffer::Guardrails::Tripwire?, ?modifications: Array[Riffer::Guardrails::Modification], ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart], ?structured_output: Hash[Symbol, untyped]?, ?healed_tool_call_ids: Array[String], ?token_usage: Riffer::Providers::TokenUsage?, ?steps: Integer) -> Riffer::Agent::Response
116
123
 
117
124
  # Raises when +files+ are supplied without a +prompt+ — the provider needs
118
125
  # text to anchor the attachments.
119
126
  # --
120
- # : (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> void
121
- def append_user_message: (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> void
127
+ # : (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?) -> void
128
+ def append_user_message: (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?) -> void
122
129
 
123
130
  # --
124
131
  # : (Riffer::Agent, Riffer::Providers::TokenUsage?) -> void
@@ -22,6 +22,13 @@ class Riffer::Agent
22
22
  # : () -> Riffer::Agent::Config
23
23
  def self.config: () -> Riffer::Agent::Config
24
24
 
25
+ # +identifier+ is cleared because it is configuration here but identity on the
26
+ # subclass; two classes claiming one raise Riffer::DuplicateIdentifierError at
27
+ # the next registry lookup.
28
+ # --
29
+ # : (Class) -> void
30
+ def self.inherited: (Class) -> void
31
+
25
32
  # Gets or sets the agent identifier.
26
33
  #
27
34
  # --
@@ -108,13 +115,13 @@ class Riffer::Agent
108
115
 
109
116
  # Generates a response using a new agent instance.
110
117
  # --
111
- # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
112
- def self.generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
118
+ # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
119
+ def self.generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
113
120
 
114
121
  # Streams a response using a new agent instance.
115
122
  # --
116
- # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
117
- def self.stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
123
+ # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
124
+ def self.stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
118
125
 
119
126
  # Reconstructs a runnable agent from a wire hash produced by +#to_h+.
120
127
  # --
@@ -190,6 +197,14 @@ class Riffer::Agent
190
197
  # : (?session: Riffer::Agent::Session?, ?context: Hash[Symbol, untyped]?, ?config: Riffer::Agent::Config?) -> void
191
198
  def initialize: (?session: Riffer::Agent::Session?, ?context: Hash[Symbol, untyped]?, ?config: Riffer::Agent::Config?) -> void
192
199
 
200
+ # The identifier for this agent: the instance config's identifier when set
201
+ # (e.g. an agent restored with +Riffer::Agent.from_h+), otherwise the class
202
+ # identifier.
203
+ #
204
+ # --
205
+ # : () -> String
206
+ def identifier: () -> String
207
+
193
208
  # Generates a response from the agent.
194
209
  #
195
210
  # With +prompt+, a new user message is appended (silently — +on_message+ does
@@ -202,11 +217,12 @@ class Riffer::Agent
202
217
  # are stamped as +riffer.tag.*+ on every span the call emits. See
203
218
  # +docs/AGENTS.md+ for the per-provider mapping. The reserved key
204
219
  # +user_id+ also maps to the provider's native user identifier where one
205
- # exists.
220
+ # exists. Riffer adds the default tags +kind+ (+"agent"+) and +agent+ (the
221
+ # agent identifier); a caller tag with the same key wins.
206
222
  #
207
223
  # --
208
- # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
209
- def generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
224
+ # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
225
+ def generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Riffer::Agent::Response
210
226
 
211
227
  # Streams a response from the agent as an +Enumerator+ of
212
228
  # +Riffer::StreamEvents+ whose block-form +each+ returns the final
@@ -215,8 +231,8 @@ class Riffer::Agent
215
231
  # Raises Riffer::ArgumentError if structured output is configured.
216
232
  #
217
233
  # --
218
- # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
219
- def stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
234
+ # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
235
+ def stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[String | Symbol, untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
220
236
 
221
237
  # Interrupts the agent loop from an +on_message+ callback. Equivalent to
222
238
  # <tt>throw :riffer_interrupt, reason</tt>.
@@ -147,7 +147,7 @@ class Riffer::Config
147
147
  def backend=: (untyped) -> void
148
148
  end
149
149
 
150
- # File-attachment-download policy for +Riffer::Messages::FilePart+ URL sources
150
+ # File-attachment-download policy for +Riffer::Messages::User::FilePart+ URL sources
151
151
  class Files
152
152
  # Allow file attachments to be downloaded to send to providers.
153
153
  attr_reader allow_downloads: bool
@@ -16,8 +16,13 @@ class Riffer::Evals::Evaluator
16
16
 
17
17
  self.@judge_model: String?
18
18
 
19
+ self.@identifier: String?
20
+
19
21
  @judge: Riffer::Evals::Judge?
20
22
 
23
+ # The identifier for an anonymous evaluator class.
24
+ DEFAULT_IDENTIFIER: String
25
+
21
26
  # Gets or sets the evaluation instructions (criteria and scoring rubric).
22
27
  #
23
28
  # --
@@ -36,6 +41,19 @@ class Riffer::Evals::Evaluator
36
41
  # : (?String?) -> String?
37
42
  def self.judge_model: (?String?) -> String?
38
43
 
44
+ # Gets or sets the evaluator identifier, sent as the +agent+ tag on judge
45
+ # calls. Defaults to the snake_cased class name, or DEFAULT_IDENTIFIER for
46
+ # an anonymous class.
47
+ #
48
+ # --
49
+ # : (?String?) -> String
50
+ def self.identifier: (?String?) -> String
51
+
52
+ # Anonymous classes derive an empty identifier.
53
+ # --
54
+ # : () -> String
55
+ private def self.derived_identifier: () -> String
56
+
39
57
  # Evaluates an input/output pair. The default calls the judge with the
40
58
  # class-level +instructions+; override for custom logic (e.g. rule-based
41
59
  # evaluators).
@@ -49,7 +67,8 @@ class Riffer::Evals::Evaluator
49
67
  # : (String | Array[Hash[Symbol, untyped] | Riffer::Messages::Base]) -> String
50
68
  def format_input: (String | Array[Hash[Symbol, untyped] | Riffer::Messages::Base]) -> String
51
69
 
52
- # Returns a Judge instance configured for this evaluator.
70
+ # Returns a Judge instance configured for this evaluator. Its calls carry
71
+ # the +kind+ (+"judge"+) and +agent+ (the evaluator identifier) tags.
53
72
  #
54
73
  # --
55
74
  # : () -> Riffer::Evals::Judge
@@ -19,10 +19,13 @@ class Riffer::Evals::Judge
19
19
  # The model string (provider/model format).
20
20
  attr_reader model: String
21
21
 
22
+ # The tags passed to the provider on every call.
23
+ attr_reader tags: Hash[String, String]
24
+
22
25
  # Raises Riffer::ArgumentError unless +model+ is "provider/model" format.
23
26
  # --
24
- # : (model: String) -> void
25
- def initialize: (model: String) -> void
27
+ # : (model: String, ?tags: Hash[String, String]) -> void
28
+ def initialize: (model: String, ?tags: Hash[String, String]) -> void
26
29
 
27
30
  # Evaluates an input/output pair using the configured LLM.
28
31
  # --