riffer 0.30.0 → 0.32.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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/.agents/code-style.md +63 -4
  3. data/.agents/rbs-inline.md +1 -6
  4. data/.release-please-manifest.json +1 -1
  5. data/AGENTS.md +1 -2
  6. data/CHANGELOG.md +25 -0
  7. data/docs/08_MESSAGES.md +1 -1
  8. data/docs/14_MCP.md +50 -5
  9. data/docs/15_SERIALIZATION.md +23 -12
  10. data/docs/providers/02_AMAZON_BEDROCK.md +14 -0
  11. data/lib/riffer/agent/config.rb +42 -47
  12. data/lib/riffer/agent/context.rb +70 -50
  13. data/lib/riffer/agent/response.rb +4 -20
  14. data/lib/riffer/agent/run.rb +28 -67
  15. data/lib/riffer/agent/serializer.rb +36 -85
  16. data/lib/riffer/agent/session/repair.rb +14 -40
  17. data/lib/riffer/agent/session.rb +25 -67
  18. data/lib/riffer/agent/structured_output/result.rb +3 -11
  19. data/lib/riffer/agent/structured_output.rb +5 -13
  20. data/lib/riffer/agent.rb +81 -199
  21. data/lib/riffer/config.rb +34 -101
  22. data/lib/riffer/evals/evaluator.rb +7 -27
  23. data/lib/riffer/evals/evaluator_runner.rb +11 -19
  24. data/lib/riffer/evals/judge.rb +4 -25
  25. data/lib/riffer/evals/result.rb +1 -18
  26. data/lib/riffer/evals/run_result.rb +0 -11
  27. data/lib/riffer/evals/scenario_result.rb +0 -14
  28. data/lib/riffer/evals.rb +0 -6
  29. data/lib/riffer/guardrail.rb +4 -27
  30. data/lib/riffer/guardrails/modification.rb +0 -10
  31. data/lib/riffer/guardrails/result.rb +3 -30
  32. data/lib/riffer/guardrails/runner.rb +5 -22
  33. data/lib/riffer/guardrails/tripwire.rb +1 -19
  34. data/lib/riffer/guardrails.rb +2 -4
  35. data/lib/riffer/helpers/call_or_value.rb +4 -3
  36. data/lib/riffer/helpers/class_name_converter.rb +3 -1
  37. data/lib/riffer/helpers/dependencies.rb +5 -7
  38. data/lib/riffer/helpers.rb +0 -5
  39. data/lib/riffer/mcp/authenticated_tool.rb +9 -9
  40. data/lib/riffer/mcp/client.rb +12 -17
  41. data/lib/riffer/mcp/manifest.rb +13 -10
  42. data/lib/riffer/mcp/registration.rb +2 -11
  43. data/lib/riffer/mcp/registry.rb +44 -52
  44. data/lib/riffer/mcp/search_tool.rb +53 -0
  45. data/lib/riffer/mcp/tool_factory.rb +13 -18
  46. data/lib/riffer/mcp.rb +12 -17
  47. data/lib/riffer/messages/assistant.rb +2 -9
  48. data/lib/riffer/messages/base.rb +46 -16
  49. data/lib/riffer/messages/file_part.rb +32 -24
  50. data/lib/riffer/messages/system.rb +0 -5
  51. data/lib/riffer/messages/tool.rb +0 -10
  52. data/lib/riffer/messages/user.rb +0 -10
  53. data/lib/riffer/messages.rb +0 -7
  54. data/lib/riffer/params/boolean.rb +2 -4
  55. data/lib/riffer/params/param.rb +28 -39
  56. data/lib/riffer/params.rb +9 -21
  57. data/lib/riffer/providers/amazon_bedrock.rb +42 -28
  58. data/lib/riffer/providers/anthropic.rb +4 -9
  59. data/lib/riffer/providers/azure_open_ai.rb +3 -19
  60. data/lib/riffer/providers/base.rb +13 -26
  61. data/lib/riffer/providers/gemini.rb +4 -4
  62. data/lib/riffer/providers/mock.rb +6 -26
  63. data/lib/riffer/providers/open_ai.rb +6 -8
  64. data/lib/riffer/providers/open_router.rb +4 -10
  65. data/lib/riffer/providers/repository.rb +4 -3
  66. data/lib/riffer/providers/token_usage.rb +9 -20
  67. data/lib/riffer/providers.rb +0 -8
  68. data/lib/riffer/runner/fibers.rb +10 -16
  69. data/lib/riffer/runner/sequential.rb +1 -4
  70. data/lib/riffer/runner/threaded.rb +3 -14
  71. data/lib/riffer/runner.rb +2 -15
  72. data/lib/riffer/skills/activate_tool.rb +2 -11
  73. data/lib/riffer/skills/adapter.rb +4 -22
  74. data/lib/riffer/skills/backend.rb +7 -21
  75. data/lib/riffer/skills/config.rb +10 -31
  76. data/lib/riffer/skills/context.rb +5 -20
  77. data/lib/riffer/skills/filesystem_backend.rb +7 -25
  78. data/lib/riffer/skills/frontmatter.rb +10 -28
  79. data/lib/riffer/skills/markdown_adapter.rb +2 -9
  80. data/lib/riffer/skills/xml_adapter.rb +2 -8
  81. data/lib/riffer/stream_events/base.rb +1 -6
  82. data/lib/riffer/stream_events/guardrail_modification.rb +1 -8
  83. data/lib/riffer/stream_events/guardrail_tripwire.rb +1 -8
  84. data/lib/riffer/stream_events/interrupt.rb +4 -7
  85. data/lib/riffer/stream_events/reasoning_delta.rb +2 -4
  86. data/lib/riffer/stream_events/reasoning_done.rb +2 -4
  87. data/lib/riffer/stream_events/skill_activation.rb +2 -4
  88. data/lib/riffer/stream_events/text_delta.rb +0 -2
  89. data/lib/riffer/stream_events/text_done.rb +1 -3
  90. data/lib/riffer/stream_events/token_usage_done.rb +1 -8
  91. data/lib/riffer/stream_events/tool_call_delta.rb +2 -3
  92. data/lib/riffer/stream_events/tool_call_done.rb +1 -3
  93. data/lib/riffer/stream_events/web_search_done.rb +1 -3
  94. data/lib/riffer/stream_events/web_search_status.rb +2 -3
  95. data/lib/riffer/stream_events.rb +0 -10
  96. data/lib/riffer/tool.rb +6 -13
  97. data/lib/riffer/tools/response.rb +8 -4
  98. data/lib/riffer/tools/runtime/fibers.rb +0 -3
  99. data/lib/riffer/tools/runtime/inline.rb +1 -4
  100. data/lib/riffer/tools/runtime/threaded.rb +0 -2
  101. data/lib/riffer/tools/runtime.rb +5 -38
  102. data/lib/riffer/tools/toolable.rb +5 -16
  103. data/lib/riffer/tools.rb +0 -4
  104. data/lib/riffer/version.rb +1 -1
  105. data/lib/riffer.rb +7 -8
  106. data/sig/generated/riffer/agent/config.rbs +29 -46
  107. data/sig/generated/riffer/agent/context.rbs +40 -48
  108. data/sig/generated/riffer/agent/response.rbs +4 -20
  109. data/sig/generated/riffer/agent/run.rbs +12 -61
  110. data/sig/generated/riffer/agent/serializer.rbs +28 -81
  111. data/sig/generated/riffer/agent/session/repair.rbs +12 -40
  112. data/sig/generated/riffer/agent/session.rbs +25 -67
  113. data/sig/generated/riffer/agent/structured_output/result.rbs +2 -10
  114. data/sig/generated/riffer/agent/structured_output.rbs +5 -12
  115. data/sig/generated/riffer/agent.rbs +62 -191
  116. data/sig/generated/riffer/config.rbs +34 -100
  117. data/sig/generated/riffer/evals/evaluator.rbs +7 -27
  118. data/sig/generated/riffer/evals/evaluator_runner.rbs +9 -19
  119. data/sig/generated/riffer/evals/judge.rbs +4 -24
  120. data/sig/generated/riffer/evals/result.rbs +1 -17
  121. data/sig/generated/riffer/evals/run_result.rbs +0 -10
  122. data/sig/generated/riffer/evals/scenario_result.rbs +0 -13
  123. data/sig/generated/riffer/evals.rbs +0 -6
  124. data/sig/generated/riffer/guardrail.rbs +4 -27
  125. data/sig/generated/riffer/guardrails/modification.rbs +0 -10
  126. data/sig/generated/riffer/guardrails/result.rbs +3 -30
  127. data/sig/generated/riffer/guardrails/runner.rbs +5 -22
  128. data/sig/generated/riffer/guardrails/tripwire.rbs +1 -19
  129. data/sig/generated/riffer/guardrails.rbs +2 -4
  130. data/sig/generated/riffer/helpers/call_or_value.rbs +4 -3
  131. data/sig/generated/riffer/helpers/class_name_converter.rbs +1 -1
  132. data/sig/generated/riffer/helpers/dependencies.rbs +3 -7
  133. data/sig/generated/riffer/helpers.rbs +0 -5
  134. data/sig/generated/riffer/mcp/authenticated_tool.rbs +5 -4
  135. data/sig/generated/riffer/mcp/client.rbs +10 -16
  136. data/sig/generated/riffer/mcp/manifest.rbs +9 -9
  137. data/sig/generated/riffer/mcp/registration.rbs +2 -10
  138. data/sig/generated/riffer/mcp/registry.rbs +11 -18
  139. data/sig/generated/riffer/mcp/search_tool.rbs +26 -0
  140. data/sig/generated/riffer/mcp/tool_factory.rbs +10 -15
  141. data/sig/generated/riffer/mcp.rbs +10 -17
  142. data/sig/generated/riffer/messages/assistant.rbs +2 -8
  143. data/sig/generated/riffer/messages/base.rbs +11 -16
  144. data/sig/generated/riffer/messages/file_part.rbs +13 -23
  145. data/sig/generated/riffer/messages/system.rbs +0 -4
  146. data/sig/generated/riffer/messages/tool.rbs +0 -9
  147. data/sig/generated/riffer/messages/user.rbs +0 -9
  148. data/sig/generated/riffer/messages.rbs +0 -7
  149. data/sig/generated/riffer/params/boolean.rbs +2 -4
  150. data/sig/generated/riffer/params/param.rbs +21 -39
  151. data/sig/generated/riffer/params.rbs +9 -21
  152. data/sig/generated/riffer/providers/amazon_bedrock.rbs +21 -25
  153. data/sig/generated/riffer/providers/anthropic.rbs +2 -7
  154. data/sig/generated/riffer/providers/azure_open_ai.rbs +3 -18
  155. data/sig/generated/riffer/providers/base.rbs +9 -25
  156. data/sig/generated/riffer/providers/gemini.rbs +0 -2
  157. data/sig/generated/riffer/providers/mock.rbs +6 -26
  158. data/sig/generated/riffer/providers/open_ai.rbs +1 -5
  159. data/sig/generated/riffer/providers/open_router.rbs +4 -10
  160. data/sig/generated/riffer/providers/repository.rbs +2 -3
  161. data/sig/generated/riffer/providers/token_usage.rbs +6 -16
  162. data/sig/generated/riffer/providers.rbs +0 -8
  163. data/sig/generated/riffer/runner/fibers.rbs +8 -15
  164. data/sig/generated/riffer/runner/sequential.rbs +1 -3
  165. data/sig/generated/riffer/runner/threaded.rbs +3 -13
  166. data/sig/generated/riffer/runner.rbs +2 -14
  167. data/sig/generated/riffer/skills/activate_tool.rbs +2 -11
  168. data/sig/generated/riffer/skills/adapter.rbs +4 -22
  169. data/sig/generated/riffer/skills/backend.rbs +7 -21
  170. data/sig/generated/riffer/skills/config.rbs +10 -31
  171. data/sig/generated/riffer/skills/context.rbs +5 -20
  172. data/sig/generated/riffer/skills/filesystem_backend.rbs +7 -24
  173. data/sig/generated/riffer/skills/frontmatter.rbs +10 -27
  174. data/sig/generated/riffer/skills/markdown_adapter.rbs +2 -9
  175. data/sig/generated/riffer/skills/xml_adapter.rbs +2 -8
  176. data/sig/generated/riffer/stream_events/base.rbs +1 -6
  177. data/sig/generated/riffer/stream_events/guardrail_modification.rbs +1 -8
  178. data/sig/generated/riffer/stream_events/guardrail_tripwire.rbs +1 -8
  179. data/sig/generated/riffer/stream_events/interrupt.rbs +4 -7
  180. data/sig/generated/riffer/stream_events/reasoning_delta.rbs +2 -4
  181. data/sig/generated/riffer/stream_events/reasoning_done.rbs +2 -4
  182. data/sig/generated/riffer/stream_events/skill_activation.rbs +2 -4
  183. data/sig/generated/riffer/stream_events/text_delta.rbs +0 -2
  184. data/sig/generated/riffer/stream_events/text_done.rbs +1 -3
  185. data/sig/generated/riffer/stream_events/token_usage_done.rbs +1 -7
  186. data/sig/generated/riffer/stream_events/tool_call_delta.rbs +2 -3
  187. data/sig/generated/riffer/stream_events/tool_call_done.rbs +1 -3
  188. data/sig/generated/riffer/stream_events/web_search_done.rbs +1 -3
  189. data/sig/generated/riffer/stream_events/web_search_status.rbs +2 -3
  190. data/sig/generated/riffer/stream_events.rbs +0 -10
  191. data/sig/generated/riffer/tool.rbs +5 -12
  192. data/sig/generated/riffer/tools/response.rbs +6 -4
  193. data/sig/generated/riffer/tools/runtime/fibers.rbs +0 -3
  194. data/sig/generated/riffer/tools/runtime/inline.rbs +1 -3
  195. data/sig/generated/riffer/tools/runtime/threaded.rbs +0 -2
  196. data/sig/generated/riffer/tools/runtime.rbs +5 -37
  197. data/sig/generated/riffer/tools/toolable.rbs +4 -14
  198. data/sig/generated/riffer/tools.rbs +0 -4
  199. data/sig/generated/riffer.rbs +5 -4
  200. data/sig/manual/riffer/agent/session/repair.rbs +5 -0
  201. data/sig/manual/riffer/evals/evaluator_runner.rbs +5 -0
  202. data/sig/manual/riffer/helpers/class_name_converter.rbs +5 -0
  203. data/sig/manual/riffer/helpers/dependencies.rbs +5 -0
  204. data/sig/manual/riffer/mcp/authenticated_tool.rbs +5 -0
  205. data/sig/manual/riffer/mcp/registry.rbs +5 -0
  206. data/sig/manual/riffer/mcp/tool_factory.rbs +5 -0
  207. data/sig/manual/riffer/mcp.rbs +5 -0
  208. data/sig/manual/riffer/providers/repository.rbs +5 -0
  209. data/sig/manual/riffer.rbs +5 -0
  210. metadata +17 -9
  211. data/.agents/rdoc.md +0 -69
  212. data/lib/riffer/messages/converter.rb +0 -90
  213. data/sig/generated/riffer/messages/converter.rbs +0 -33
  214. data/sig/manual/riffer/tools/toolable.rbs +0 -6
@@ -1,11 +1,7 @@
1
1
  # Generated from lib/riffer/agent.rb with RBS::Inline
2
2
 
3
- # Riffer::Agent is the base class for all agents in the Riffer framework.
4
- #
5
- # Provides orchestration for LLM calls, tool use, and message management.
6
- # Subclass this to create your own agents.
7
- #
8
- # See Riffer::Messages and Riffer::Providers.
3
+ # Base class for all agents in the Riffer framework. Subclass it to define an
4
+ # agent's model, instructions, tools, and guardrails.
9
5
  #
10
6
  # class MyAgent < Riffer::Agent
11
7
  # model 'openai/gpt-4o'
@@ -17,15 +13,9 @@
17
13
  class Riffer::Agent
18
14
  self.@config: Riffer::Agent::Config?
19
15
 
20
- include Riffer::Messages::Converter
21
-
22
- extend Riffer::Helpers::ClassNameConverter
23
-
24
16
  INTERRUPT_MAX_STEPS: Symbol
25
17
 
26
- # Returns the per-class Riffer::Agent::Config value object holding every
27
- # DSL setting. Lazily initialized on first read; each subclass has its own.
28
- #
18
+ # Returns the per-class Riffer::Agent::Config holding every DSL setting.
29
19
  # --
30
20
  # : () -> Riffer::Agent::Config
31
21
  def self.config: () -> Riffer::Agent::Config
@@ -36,16 +26,13 @@ class Riffer::Agent
36
26
  # : (?String?) -> String
37
27
  def self.identifier: (?String?) -> String
38
28
 
39
- # Gets or sets the model string (e.g., "openai/gpt-4o") or Proc.
29
+ # Gets or sets the model string (e.g., "openai/gpt-4o").
40
30
  #
41
31
  # --
42
32
  # : (?(String | Proc)?) -> (String | Proc)?
43
33
  def self.model: (?(String | Proc)?) -> (String | Proc)?
44
34
 
45
- # Gets or sets the agent instructions.
46
- #
47
- # Accepts a static string or a Proc for dynamic instructions.
48
- # When a Proc is given, it is called at generate time and receives
35
+ # Gets or sets the agent instructions. A Proc is called at generate time with
49
36
  # the +context+ hash (which may be +nil+).
50
37
  #
51
38
  # instructions "You are a helpful assistant."
@@ -71,18 +58,13 @@ class Riffer::Agent
71
58
  def self.model_options: (?Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]
72
59
 
73
60
  # Gets or sets the structured output schema for this agent.
74
- #
75
- # Accepts a Riffer::Params instance or a block evaluated against a new Params.
76
- #
77
61
  # --
78
62
  # : (?Riffer::Params?) ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?
79
63
  def self.structured_output: (?Riffer::Params?) ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?
80
64
 
81
65
  # Gets or sets the maximum number of LLM call steps in the tool-use loop.
82
- #
83
- # Defaults to Riffer::Agent::Config::DEFAULT_MAX_STEPS (16). Set to +nil+
84
- # for unlimited steps. The splat distinguishes a getter call (no argument)
85
- # from setting the limit to +nil+.
66
+ # The splat distinguishes a getter (no argument) from setting the limit to
67
+ # +nil+ (unlimited); it defaults to Riffer::Agent::Config::DEFAULT_MAX_STEPS.
86
68
  #
87
69
  # max_steps # reads the current limit
88
70
  # max_steps 8 # cap the loop at 8 steps
@@ -98,31 +80,25 @@ class Riffer::Agent
98
80
  # : (?(Array[singleton(Riffer::Tool)] | Proc)?) -> (Array[singleton(Riffer::Tool)] | Proc)?
99
81
  def self.uses_tools: (?(Array[singleton(Riffer::Tool)] | Proc)?) -> (Array[singleton(Riffer::Tool)] | Proc)?
100
82
 
101
- # Opts this agent into tools from all MCP registrations that share any of
102
- # the given tag(s).
83
+ # Opts this agent into MCP tools from registrations matching the given tag.
84
+ # Progressive registrations expose +mcp_search+ instead of every schema up front.
103
85
  #
104
- # +tag+ - a String or Symbol; matched against registration manifest tags.
105
- #
106
- # : (String | Symbol) -> void
107
- def self.use_mcp: (String | Symbol) -> void
86
+ # : (String | Symbol, ?progressive: bool) -> void
87
+ def self.use_mcp: (String | Symbol, ?progressive: bool) -> void
108
88
 
109
89
  # Returns the accumulated +use_mcp+ configurations for this agent class.
110
90
  #
111
91
  # : () -> Array[Hash[Symbol, untyped]]
112
92
  def self.mcp_configs: () -> Array[Hash[Symbol, untyped]]
113
93
 
114
- # Gets or sets the tool runtime for this agent.
115
- #
116
- # Accepts a Riffer::Tools::Runtime subclass, a Riffer::Tools::Runtime instance,
117
- # or a Proc. Defaults to <tt>Riffer.config.tool_runtime</tt> when unset.
118
- #
94
+ # Gets or sets the tool runtime for this agent; defaults to
95
+ # <tt>Riffer.config.tool_runtime</tt> when unset.
119
96
  # --
120
97
  # : (?(singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
121
98
  def self.tool_runtime: (?(singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
122
99
 
123
- # Configures skills for this agent via a block DSL.
124
- #
125
- # Returns the current Riffer::Skills::Config when called without a block.
100
+ # Configures skills for this agent via a block DSL, or returns the current
101
+ # Riffer::Skills::Config when called without a block.
126
102
  #
127
103
  # skills do
128
104
  # backend Riffer::Skills::FilesystemBackend.new(".skills")
@@ -147,139 +123,84 @@ class Riffer::Agent
147
123
  def self.all: () -> Array[singleton(Riffer::Agent)]
148
124
 
149
125
  # Generates a response using a new agent instance.
150
- #
151
- # +context:+ is threaded into +new+; +prompt+ and +files:+ are forwarded
152
- # to +#generate+.
153
- #
154
126
  # --
155
127
  # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Riffer::Agent::Response
156
128
  def self.generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Riffer::Agent::Response
157
129
 
158
130
  # Streams a response using a new agent instance.
159
- #
160
- # +context:+ is threaded into +new+; +prompt+ and +files:+ are forwarded
161
- # to +#stream+.
162
- #
163
131
  # --
164
132
  # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Enumerator[Riffer::StreamEvents::Base, void]
165
133
  def self.stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?) -> Enumerator[Riffer::StreamEvents::Base, void]
166
134
 
167
- # Reconstructs a runnable agent from a wire dict produced by +#to_h+.
168
- #
169
- # Delegates to Riffer::Agent::Serializer.from_h. See it for the
170
- # +tool_resolver+ / +tool_runtime+ injection points and what does not
171
- # transfer.
172
- #
135
+ # Reconstructs a runnable agent from a wire hash produced by +#to_h+.
173
136
  # --
174
- # : (Hash[Symbol, untyped], ?context: Hash[Symbol, untyped]?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
175
- def self.from_h: (Hash[Symbol, untyped], ?context: Hash[Symbol, untyped]?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
137
+ # : (Hash[Symbol, untyped], ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
138
+ def self.from_h: (Hash[Symbol, untyped], ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
176
139
 
177
140
  # Reconstructs a runnable agent from a JSON string produced by +#to_json+.
178
- #
179
- # Delegates to Riffer::Agent::Serializer.from_json, which parses the JSON
180
- # (with symbol keys) for you. See Riffer::Agent::Serializer.from_h for the
181
- # +tool_resolver+ / +tool_runtime+ injection points.
182
- #
183
141
  # --
184
- # : (String, ?context: Hash[Symbol, untyped]?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
185
- def self.from_json: (String, ?context: Hash[Symbol, untyped]?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
142
+ # : (String, ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
143
+ def self.from_json: (String, ?context: Hash[Symbol, untyped]?, ?session: Riffer::Agent::Session?, ?tool_resolver: ^(Hash[Symbol, untyped]) -> singleton(Riffer::Tool), ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?) -> Riffer::Agent
186
144
 
187
- # Registers a guardrail for input, output, or both phases.
188
- #
189
- # [phase] :before, :after, or :around.
190
- # [with] the guardrail class (must be subclass of Riffer::Guardrail).
191
- # [options] additional options passed to the guardrail.
192
- #
193
- # Raises Riffer::ArgumentError if phase is invalid or guardrail is not a Guardrail class.
145
+ # Registers a guardrail for input, output, or both phases. Raises
146
+ # Riffer::ArgumentError unless +phase+ is :before, :after, or :around.
194
147
  # --
195
148
  # : (Symbol, with: singleton(Riffer::Guardrail), **untyped) -> void
196
149
  def self.guardrail: (Symbol, with: singleton(Riffer::Guardrail), **untyped) -> void
197
150
 
198
151
  # Returns the registered guardrail configs for a given phase.
199
- #
200
- # [phase] :before or :after.
201
- #
202
152
  # --
203
153
  # : (Symbol) -> Array[Hash[Symbol, untyped]]
204
154
  def self.guardrails_for: (Symbol) -> Array[Hash[Symbol, untyped]]
205
155
 
206
- # The conversation handle. See Riffer::Agent::Session.
156
+ # The conversation handle.
207
157
  attr_reader session: Riffer::Agent::Session
208
158
 
209
- # The per-instance Riffer::Agent::Config. Either the class-level default or
210
- # an explicit Config passed to +Agent.new(config:)+.
159
+ # The per-instance Riffer::Agent::Config.
211
160
  attr_reader config: Riffer::Agent::Config
212
161
 
213
- # The system message built from the configured +instructions+, or +nil+
214
- # when no instructions are configured. Built once at +Agent.new+ using the
215
- # constructor +context:+ and cached. Useful for persistence flows.
162
+ # The system message built from the configured +instructions+, or +nil+ when
163
+ # none are configured.
216
164
  attr_reader instruction_message: Riffer::Messages::System?
217
165
 
218
- # The system message describing the configured skills catalog, or +nil+
219
- # when skills are unconfigured or the catalog is empty. Built once at
220
- # +Agent.new+ and cached.
166
+ # The system message describing the configured skills catalog, or +nil+ when
167
+ # skills are unconfigured or the catalog is empty.
221
168
  attr_reader skills_message: Riffer::Messages::System?
222
169
 
223
- # The mutable runtime context, a +Riffer::Agent::Context+ value object
224
- # threaded into every Proc-based DSL setting, guardrail, tool runtime,
225
- # and skills resolution, and shared with every +Riffer::Agent::Run+
226
- # this agent executes. Exposes:
227
- #
228
- # - +context.skills+ — the resolved +Riffer::Skills::Context+ (when
229
- # skills are configured), set at +Agent.new+ time.
230
- # - +context.token_usage+ — the cumulative +Riffer::Providers::TokenUsage+,
231
- # updated by each Run as the loop progresses.
232
- # - +context[:key]+ / <tt>context.dig(:key)</tt> — Hash-style reads for
233
- # caller-provided keys (e.g. <tt>context[:agent]</tt>,
234
- # <tt>context[:tenant]</tt>). +:skills+ and +:token_usage+ are
235
- # reserved and cannot be passed by the caller.
170
+ # The mutable runtime context shared with every +Riffer::Agent::Run+ this
171
+ # agent executes and threaded through all Proc-based settings.
236
172
  attr_reader context: Riffer::Agent::Context
237
173
 
238
- # The resolved provider name (the part before "provider/"), e.g. +"openai"+.
239
- # Resolved eagerly at +Agent.new+ alongside +model_name+; together they
240
- # form the provider-neutral model identifier the agent serializes.
174
+ # The resolved provider name (the part before "/" in the model string),
175
+ # e.g. +"openai"+.
241
176
  attr_reader provider_name: String
242
177
 
243
- # The resolved model name (the part after "provider/"), used as the model
244
- # argument on every LLM call. Resolved eagerly at +Agent.new+.
178
+ # The resolved model name (the part after "/" in the model string), used as
179
+ # the model argument on every LLM call.
245
180
  attr_reader model_name: String
246
181
 
247
- # The provider client. Built eagerly at +Agent.new+ from the configured
248
- # provider class and +Config#provider_options+, then handed to every
249
- # +Riffer::Agent::Run+ this agent executes. Public so tests can pre-queue
250
- # responses on +Riffer::Providers::Mock+ before calling +#generate+.
182
+ # The provider client. Public so tests can pre-queue responses on
183
+ # +Riffer::Providers::Mock+ before calling +#generate+.
251
184
  attr_reader provider: Riffer::Providers::Base
252
185
 
253
- # The +Riffer::Agent::StructuredOutput+ wrapping the configured schema, or +nil+
254
- # when structured output is not configured. Resolved eagerly at +Agent.new+.
186
+ # The +Riffer::Agent::StructuredOutput+ wrapping the configured schema, or
187
+ # +nil+ when not configured.
255
188
  attr_reader structured_output: Riffer::Agent::StructuredOutput?
256
189
 
257
- # The tool classes the LLM sees on every call this agent makes. Resolved
258
- # eagerly at +Agent.new+ (Proc-form +uses_tools+ is called against
259
- # +context+ once; MCP tools and the skill_activate tool are merged in).
190
+ # The tool classes the LLM sees on every call this agent makes.
260
191
  attr_reader tools: Array[singleton(Riffer::Tool)]
261
192
 
262
- # The tool runtime instance used to execute tool calls. Resolved eagerly
263
- # at +Agent.new+ (Proc-form +tool_runtime+ is called against +context+ once).
193
+ # The tool runtime instance used to execute tool calls.
264
194
  attr_reader tool_runtime: Riffer::Tools::Runtime
265
195
 
266
196
  # Initializes a new agent.
267
197
  #
268
- # When +session:+ is omitted, a fresh +Riffer::Agent::Session+ is built and seeded
269
- # with the system instruction message and skills catalog (when configured),
270
- # using +context:+. When +session:+ is provided, the agent uses it as-is —
271
- # the caller is responsible for the session's contents (typical use case:
272
- # cross-process resume from persisted history). With
273
- # +Riffer.config.experimental_history_healing+ on, a provided session is
274
- # healed at construction time so the +tool_use+ ↔ +tool_result+ invariant
275
- # holds before the next inference call.
276
- #
277
- # +context:+ flows through Proc-based instructions, model, skills resolution,
278
- # tool resolution, guardrails, and tool runtime. It is fixed for the
279
- # lifetime of the agent.
198
+ # A provided +session:+ is used as-is the caller owns its contents (e.g.
199
+ # cross-process resume from persisted history); an omitted one is seeded with
200
+ # the instruction and skills messages.
280
201
  #
281
- # Raises Riffer::ArgumentError if the configured model string is invalid
282
- # (must be "provider/model" format).
202
+ # Raises Riffer::ArgumentError unless the configured model string is
203
+ # "provider/model" format.
283
204
  #
284
205
  # --
285
206
  # : (?session: Riffer::Agent::Session?, ?context: Hash[Symbol, untyped]?, ?config: Riffer::Agent::Config?) -> void
@@ -287,60 +208,38 @@ class Riffer::Agent
287
208
 
288
209
  # Generates a response from the agent.
289
210
  #
290
- # Runs the inference loop via +Riffer::Agent::Run.generate+. When +prompt+
291
- # is given, a new +Riffer::Messages::User+ is appended to the session
292
- # (silently +on_message+ does not fire for user inputs) and then the
293
- # loop runs. When +prompt+ is omitted, the loop runs against the current
294
- # session — useful for resuming a persisted conversation whose last turn
295
- # is already a user message, or for picking up pending tool calls after
296
- # an interrupt.
297
- #
298
- # +files:+ requires +prompt+. Pass files to attach to the new user message.
211
+ # With +prompt+, a new user message is appended (silently — +on_message+ does
212
+ # not fire for user inputs) before the loop runs. Without it, the loop runs
213
+ # against the current session, resuming a persisted conversation or pending
214
+ # tool calls. +files:+ requires +prompt+.
299
215
  #
300
216
  # --
301
217
  # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Riffer::Agent::Response
302
218
  def generate: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Riffer::Agent::Response
303
219
 
304
- # Streams a response from the agent.
305
- #
306
- # Runs the inference loop via +Riffer::Agent::Run.stream+, returning an
307
- # +Enumerator+ of +Riffer::StreamEvents+.
220
+ # Streams a response from the agent, returning an +Enumerator+ of
221
+ # +Riffer::StreamEvents+. See +#generate+ for prompt/files semantics.
308
222
  #
309
223
  # Raises Riffer::ArgumentError if structured output is configured.
310
224
  #
311
- # See +#generate+ for prompt/files semantics.
312
- #
313
225
  # --
314
226
  # : (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Enumerator[Riffer::StreamEvents::Base, void]
315
227
  def stream: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> Enumerator[Riffer::StreamEvents::Base, void]
316
228
 
317
- # Interrupts the agent loop.
318
- #
319
- # Call from an +on_message+ callback to cleanly interrupt the loop.
320
- # Equivalent to <tt>throw :riffer_interrupt, reason</tt>.
321
- #
322
- # When +Riffer.config.experimental_history_healing+ is enabled, riffer
323
- # fills any orphaned +tool_use+ on the way out with a placeholder
324
- # +Riffer::Messages::Tool+ carrying +error_type: :interrupted+. The
325
- # filled call_ids are exposed on
326
- # +Riffer::Agent::Response#healed_tool_call_ids+ (and the streaming
327
- # +Riffer::StreamEvents::Interrupt+ event).
328
- #
229
+ # Interrupts the agent loop from an +on_message+ callback. Equivalent to
230
+ # <tt>throw :riffer_interrupt, reason</tt>.
329
231
  # --
330
232
  # : (?(String | Symbol)?) -> void
331
233
  def interrupt!: (?(String | Symbol)?) -> void
332
234
 
333
- # Snapshots this resolved agent into a self-contained, provider-neutral
334
- # wire dict. Delegates to Riffer::Agent::Serializer.to_h.
335
- #
235
+ # Snapshots this resolved agent into a self-contained, provider-neutral wire
236
+ # hash.
336
237
  # --
337
238
  # : () -> Hash[Symbol, untyped]
338
239
  def to_h: () -> Hash[Symbol, untyped]
339
240
 
340
- # Snapshots this resolved agent into a wire JSON string. Delegates to
341
- # Riffer::Agent::Serializer.to_json. The +*+ absorbs the JSON generator
342
- # state argument so <tt>JSON.generate(agent)</tt> works too.
343
- #
241
+ # Snapshots this resolved agent into a wire JSON string. The +*+ absorbs the
242
+ # JSON generator state argument so <tt>JSON.generate(agent)</tt> works too.
344
243
  # --
345
244
  # : (*untyped) -> String
346
245
  def to_json: (*untyped) -> String
@@ -355,28 +254,14 @@ class Riffer::Agent
355
254
  # : () -> Riffer::Messages::System?
356
255
  def build_skills_message: () -> Riffer::Messages::System?
357
256
 
358
- # Resolves +Config#model+ to a "provider/model" string (calling the Proc
359
- # form against +@context+) and parses it.
360
- #
361
- # Returns +[provider_name, model_name]+. Raises Riffer::ArgumentError on an
362
- # invalid model string.
363
- #
364
257
  # --
365
258
  # : () -> [String, String]
366
259
  def resolve_provider_and_model: () -> [ String, String ]
367
260
 
368
- # Builds the provider client from the resolved +@provider_name+ and the
369
- # configured +provider_options+.
370
- #
371
- # Raises Riffer::ArgumentError on an unregistered provider.
372
- #
373
261
  # --
374
262
  # : () -> Riffer::Providers::Base
375
263
  def build_provider: () -> Riffer::Providers::Base
376
264
 
377
- # Resolves the skills backend, lists skills, and selects an adapter.
378
- # Returns nil if skills are unconfigured or the backend is empty.
379
- #
380
265
  # --
381
266
  # : () -> Riffer::Skills::Context?
382
267
  def resolve_skills: () -> Riffer::Skills::Context?
@@ -385,19 +270,6 @@ class Riffer::Agent
385
270
  # : () -> Riffer::Agent::StructuredOutput?
386
271
  def resolve_structured_output: () -> Riffer::Agent::StructuredOutput?
387
272
 
388
- # Resolves the full tool catalog for the agent:
389
- #
390
- # - The configured +uses_tools+ value (Proc-form resolved against +context+).
391
- # - The skill activation tool, when a +skills+ block is configured. The
392
- # activation tool class comes from the per-agent +skills do; activate_tool ...; end+
393
- # override when set, otherwise from +Riffer.config.skills.default_activate_tool+.
394
- # - All MCP tools matching any +use_mcp+ tag, optionally wrapped in
395
- # AuthenticatedTool when +Riffer.config.mcp.credentials+ is configured.
396
- #
397
- # Raises Riffer::ArgumentError on tool name conflicts with the skill
398
- # activation tool, on duplicate tool names across sources, or on tool
399
- # classes missing required metadata (description, params).
400
- #
401
273
  # --
402
274
  # : () -> Array[singleton(Riffer::Tool)]
403
275
  def resolve_tools: () -> Array[singleton(Riffer::Tool)]
@@ -410,16 +282,15 @@ class Riffer::Agent
410
282
  # : () -> Array[singleton(Riffer::Tool)]
411
283
  def resolve_mcp_tool_classes: () -> Array[singleton(Riffer::Tool)]
412
284
 
413
- # Each matching MCP registration once, with tag symbols unioned across +use_mcp+ rows.
414
- #
415
- # : (Array[Hash[Symbol, untyped]]) -> Hash[Riffer::Mcp::Registration, Array[Symbol]]
416
- def gather_mcp_registrations_with_tags: (Array[Hash[Symbol, untyped]]) -> Hash[Riffer::Mcp::Registration, Array[Symbol]]
285
+ # --
286
+ # : (Array[Hash[Symbol, untyped]]) -> [Hash[Riffer::Mcp::Registration, Array[Symbol]], Hash[Riffer::Mcp::Registration, Array[Symbol]]]
287
+ def gather_mcp_registrations_with_tags: (Array[Hash[Symbol, untyped]]) -> [ Hash[Riffer::Mcp::Registration, Array[Symbol]], Hash[Riffer::Mcp::Registration, Array[Symbol]] ]
417
288
 
289
+ # --
418
290
  # : (Riffer::Mcp::Registration, Array[Symbol], (^(manifest: Riffer::Mcp::Manifest, matched_tags: Array[Symbol], context: Riffer::Agent::Context) -> Hash[Symbol, untyped]?)?, Riffer::Agent::Context) -> Array[singleton(Riffer::Tool)]
419
291
  def mcp_tools_for_registration: (Riffer::Mcp::Registration, Array[Symbol], (^(manifest: Riffer::Mcp::Manifest, matched_tags: Array[Symbol], context: Riffer::Agent::Context) -> Hash[Symbol, untyped]?)?, Riffer::Agent::Context) -> Array[singleton(Riffer::Tool)]
420
292
 
421
- # Raises if two or more tool classes share the same +.name+ (ambiguous dispatch).
422
- #
293
+ # --
423
294
  # : (Array[singleton(Riffer::Tool)]) -> void
424
295
  def assert_distinct_tool_names!: (Array[singleton(Riffer::Tool)]) -> void
425
296
  end
@@ -1,19 +1,6 @@
1
1
  # Generated from lib/riffer/config.rb with RBS::Inline
2
2
 
3
3
  # Configuration for the Riffer framework.
4
- #
5
- # Provides configuration options for AI providers and other settings.
6
- #
7
- # Riffer.config.openai.api_key = "sk-..."
8
- #
9
- # Riffer.config.amazon_bedrock.region = "us-east-1"
10
- # Riffer.config.amazon_bedrock.api_token = "..."
11
- #
12
- # Riffer.config.anthropic.api_key = "sk-ant-..."
13
- #
14
- # Riffer.config.openrouter.api_key = "sk-or-..."
15
- #
16
- # Riffer.config.evals.judge_model = "anthropic/claude-sonnet-4-20250514"
17
4
  class Riffer::Config
18
5
  class AmazonBedrock < Struct[untyped]
19
6
  attr_accessor api_token(): untyped
@@ -82,41 +69,27 @@ class Riffer::Config
82
69
  end
83
70
 
84
71
  # Skills-related global configuration.
85
- #
86
- # See <tt>Riffer.config.skills.default_activate_tool</tt> and
87
- # <tt>Riffer.config.skills.default_backend</tt>.
88
72
  class Skills
89
- # Default skill activation tool class.
90
- #
91
- # The tool class the LLM calls to activate a skill. Defaults to
92
- # <tt>Riffer::Skills::ActivateTool</tt>. Per-agent override is available
93
- # via <tt>skills do; activate_tool ...; end</tt>.
73
+ # The tool class the LLM calls to activate a skill; defaults to
74
+ # <tt>Riffer::Skills::ActivateTool</tt>.
94
75
  attr_reader default_activate_tool: singleton(Riffer::Tool)
95
76
 
96
- # Default skills backend.
97
- #
98
- # Used by agents that declare a +skills+ block without specifying a
99
- # backend. Accepts a Riffer::Skills::Backend instance or a Proc.
100
- # Defaults to +nil+ (no global default).
77
+ # Default skills backend for agents that declare a +skills+ block without
78
+ # one; defaults to +nil+.
101
79
  attr_reader default_backend: (Riffer::Skills::Backend | Proc)?
102
80
 
103
81
  # --
104
82
  # : () -> void
105
83
  def initialize: () -> void
106
84
 
107
- # Sets the default skill activation tool class.
108
- #
109
- # Raises +Riffer::ArgumentError+ if the value is not a Riffer::Tool subclass.
110
- #
85
+ # Sets the default skill activation tool class. Raises Riffer::ArgumentError
86
+ # on an invalid value.
111
87
  # --
112
88
  # : (singleton(Riffer::Tool)) -> void
113
89
  def default_activate_tool=: (singleton(Riffer::Tool)) -> void
114
90
 
115
- # Sets the default skills backend.
116
- #
117
- # Raises +Riffer::ArgumentError+ if the value is not a
118
- # Riffer::Skills::Backend instance, a Proc, or +nil+.
119
- #
91
+ # Sets the default skills backend. Raises Riffer::ArgumentError on an
92
+ # invalid value.
120
93
  # --
121
94
  # : ((Riffer::Skills::Backend | Proc)?) -> void
122
95
  def default_backend=: ((Riffer::Skills::Backend | Proc)?) -> void
@@ -124,103 +97,64 @@ class Riffer::Config
124
97
 
125
98
  VALID_MESSAGE_ID_STRATEGIES: untyped
126
99
 
127
- # Amazon Bedrock configuration (Struct with +api_token+ and +region+).
100
+ # Amazon Bedrock configuration.
128
101
  attr_reader amazon_bedrock: Riffer::Config::AmazonBedrock
129
102
 
130
- # Anthropic configuration (Struct with +api_key+).
103
+ # Anthropic configuration.
131
104
  attr_reader anthropic: Riffer::Config::Anthropic
132
105
 
133
- # Azure OpenAI configuration (Struct with +api_key+ and +endpoint+).
106
+ # Azure OpenAI configuration.
134
107
  attr_reader azure_openai: Riffer::Config::AzureOpenAI
135
108
 
136
- # Google Gemini configuration (Struct with +api_key+, +open_timeout+, and +read_timeout+).
109
+ # Google Gemini configuration.
137
110
  attr_reader gemini: Riffer::Config::Gemini
138
111
 
139
- # OpenAI configuration (Struct with +api_key+).
112
+ # OpenAI configuration.
140
113
  attr_reader openai: Riffer::Config::OpenAI
141
114
 
142
- # OpenRouter configuration (Struct with +api_key+).
115
+ # OpenRouter configuration.
143
116
  attr_reader openrouter: Riffer::Config::OpenRouter
144
117
 
145
- # Evals configuration (Struct with +judge_model+).
118
+ # Evals configuration.
146
119
  attr_reader evals: Riffer::Config::Evals
147
120
 
148
- # MCP configuration (Struct with +credentials+ and +discovery_runner+).
149
- #
150
- # +credentials+ is an optional Proc for per-run MCP +tools/call+ HTTP headers.
151
- # Signature: +->(manifest:, matched_tags:, context:) { Hash or nil }+.
152
- # +nil+ from the proc at tool-resolution time omits that server's tools; +nil+
153
- # at tool-call time raises Riffer::Mcp::CredentialsDeniedError.
154
- #
155
- # +discovery_runner+ is the Riffer::Runner used to execute tool discovery
156
- # (default +Runner::Sequential+).
121
+ # MCP configuration. +credentials+ is an optional Proc returning per-run
122
+ # +tools/call+ headers (or +nil+ to deny); +discovery_runner+ runs tool
123
+ # discovery.
157
124
  attr_reader mcp: Riffer::Config::Mcp
158
125
 
159
- # Global tool runtime configuration (experimental).
160
- #
161
- # Accepts a Riffer::Tools::Runtime subclass, a Riffer::Tools::Runtime instance,
162
- # or a Proc. Defaults to <tt>Riffer::Tools::Runtime::Inline.new</tt>.
126
+ # Global tool runtime configuration (experimental); defaults to
127
+ # <tt>Riffer::Tools::Runtime::Inline.new</tt>.
163
128
  attr_reader tool_runtime: singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc
164
129
 
165
- # Sets the global tool runtime.
166
- #
167
- # Raises +Riffer::ArgumentError+ if the value is not a valid runtime
168
- # (ToolRuntime subclass, ToolRuntime instance, or Proc).
169
- #
130
+ # Sets the global tool runtime. Raises Riffer::ArgumentError on an invalid
131
+ # value.
170
132
  # --
171
133
  # : ((singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)) -> void
172
134
  def tool_runtime=: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc) -> void
173
135
 
174
- # Skills-related global configuration. Returns a Riffer::Config::Skills
175
- # object — see <tt>Riffer.config.skills.default_activate_tool</tt>.
136
+ # Skills-related global configuration.
176
137
  attr_reader skills: Riffer::Config::Skills
177
138
 
178
- # Strategy for auto-generating message ids. One of +:none+ (default, no id),
179
- # +:uuid+ (UUIDv4), or +:uuidv7+ (time-ordered UUIDv7).
180
- #
181
- # When set to anything other than +:none+, each +Riffer::Messages::Base+
182
- # instance gets an +id+ populated at construction time, and seeded messages
183
- # passed to +Riffer::Agent#generate+ must carry their own +:id+.
139
+ # Strategy for auto-generating message ids: +:none+ (default), +:uuid+, or
140
+ # +:uuidv7+. When not +:none+, messages get an +id+ at construction, and
141
+ # seeded messages passed to +Riffer::Agent#generate+ must carry their own.
184
142
  attr_reader message_id_strategy: Symbol
185
143
 
186
- # Sets the message id strategy.
187
- #
188
- # Raises +Riffer::ArgumentError+ if the value is not one of
189
- # +:none+, +:uuid+, or +:uuidv7+.
190
- #
144
+ # Sets the message id strategy. Raises Riffer::ArgumentError unless the value
145
+ # is +:none+, +:uuid+, or +:uuidv7+.
191
146
  # --
192
147
  # : (Symbol) -> void
193
148
  def message_id_strategy=: (Symbol) -> void
194
149
 
195
- # Experimental: when +true+, riffer keeps the +tool_use+ ↔ +tool_result+
196
- # invariant intact on its own.
197
- #
198
- # - On +Riffer::Agent#generate(messages_array)+, orphaned +tool_use+
199
- # exchanges and parentless +Riffer::Messages::Tool+ messages are
200
- # silently stripped from the seed. Pending tool calls on the resume
201
- # boundary (last assistant whose tail is purely Tool results) are
202
- # preserved for +execute_pending_tool_calls+.
203
- # - On any interrupt (caller-issued +interrupt!+ or
204
- # +INTERRUPT_MAX_STEPS+), riffer fills any orphaned +tool_use+ with a
205
- # placeholder +Riffer::Messages::Tool+ carrying
206
- # +error_type: :interrupted+, leaving history valid for the next turn.
207
- # Filled call_ids are exposed on
208
- # +Riffer::Agent::Response#healed_tool_call_ids+ (and the streaming
209
- # +Riffer::StreamEvents::Interrupt+ event).
210
- #
211
- # Defaults to +false+ — the pre-healing behavior. Experimental: the
212
- # surface and default may change without notice.
150
+ # Experimental: when +true+, riffer maintains the +tool_use+ ↔ +tool_result+
151
+ # invariant itself stripping orphaned exchanges and filling interrupted
152
+ # ones. Defaults to +false+; the surface may change without notice.
213
153
  attr_reader experimental_history_healing: bool
214
154
 
215
- # Sets the +experimental_history_healing+ flag.
216
- #
217
- # Coerces common boolean representations so values pulled from
218
- # environment variables don't silently enable healing — the string
219
- # +"false"+ is truthy in Ruby and would otherwise flip the flag on.
220
- # Accepts +true+/+false+, +"true"+/+"false"+, +1+/+0+, +"1"+/+"0"+, and
221
- # +nil+ (treated as +false+, the default). Raises
222
- # +Riffer::ArgumentError+ for any other value.
223
- #
155
+ # Sets the +experimental_history_healing+ flag, coercing boolean-ish values so
156
+ # an env-var +"false"+ (truthy in Ruby) doesn't silently enable healing.
157
+ # Raises Riffer::ArgumentError on an unrecognized value.
224
158
  # --
225
159
  # : (untyped) -> void
226
160
  def experimental_history_healing=: (untyped) -> void