riffer 0.48.0 → 0.49.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 (258) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/rules/comments.md +2 -4
  3. data/.claude/rules/rbs-inline.md +2 -12
  4. data/.release-please-manifest.json +1 -1
  5. data/.rubocop.yml +5 -0
  6. data/CHANGELOG.md +19 -0
  7. data/docs/AGENTS.md +3 -5
  8. data/docs/AGENT_LIFECYCLE.md +13 -16
  9. data/docs/CONFIGURATION.md +22 -33
  10. data/docs/TOOL_ADVANCED.md +1 -3
  11. data/docs/TRACING.md +1 -1
  12. data/docs/providers/AMAZON_BEDROCK.md +31 -0
  13. data/docs/providers/OPENROUTER.md +18 -1
  14. data/docs-site/build.rb +0 -6
  15. data/docs-site/check.rb +1 -5
  16. data/lib/riffer/agent/config.rb +4 -45
  17. data/lib/riffer/agent/context.rb +2 -26
  18. data/lib/riffer/agent/outcome.rb +0 -20
  19. data/lib/riffer/agent/response.rb +0 -38
  20. data/lib/riffer/agent/run.rb +11 -43
  21. data/lib/riffer/agent/serializer.rb +10 -39
  22. data/lib/riffer/agent/session/repair.rb +3 -15
  23. data/lib/riffer/agent/session.rb +25 -38
  24. data/lib/riffer/agent/structured_output/result.rb +0 -8
  25. data/lib/riffer/agent/structured_output.rb +0 -7
  26. data/lib/riffer/agent.rb +10 -130
  27. data/lib/riffer/config/amazon_bedrock.rb +30 -0
  28. data/lib/riffer/config/anthropic.rb +21 -0
  29. data/lib/riffer/config/azure_open_ai.rb +30 -0
  30. data/lib/riffer/config/evals.rb +18 -0
  31. data/lib/riffer/config/files.rb +61 -0
  32. data/lib/riffer/config/gemini.rb +21 -0
  33. data/lib/riffer/config/mcp.rb +31 -0
  34. data/lib/riffer/config/open_ai.rb +30 -0
  35. data/lib/riffer/config/open_router.rb +21 -0
  36. data/lib/riffer/config/pricing/rates.rb +36 -0
  37. data/lib/riffer/config/pricing.rb +64 -0
  38. data/lib/riffer/config/skills.rb +38 -0
  39. data/lib/riffer/config/tracing.rb +43 -0
  40. data/lib/riffer/config.rb +3 -362
  41. data/lib/riffer/evals/evaluator.rb +1 -29
  42. data/lib/riffer/evals/evaluator_runner.rb +0 -15
  43. data/lib/riffer/evals/judge.rb +0 -8
  44. data/lib/riffer/evals/result.rb +1 -11
  45. data/lib/riffer/evals/run_result.rb +0 -12
  46. data/lib/riffer/evals/scenario_result.rb +0 -19
  47. data/lib/riffer/files/downloader.rb +2 -3
  48. data/lib/riffer/files/resolver.rb +2 -7
  49. data/lib/riffer/guardrail.rb +2 -22
  50. data/lib/riffer/guardrails/modification.rb +0 -8
  51. data/lib/riffer/guardrails/result.rb +0 -17
  52. data/lib/riffer/guardrails/runner.rb +2 -11
  53. data/lib/riffer/guardrails/tripwire.rb +0 -8
  54. data/lib/riffer/guardrails.rb +0 -2
  55. data/lib/riffer/helpers/boolean.rb +0 -4
  56. data/lib/riffer/helpers/call_or_value.rb +0 -3
  57. data/lib/riffer/helpers/deep_dup.rb +3 -8
  58. data/lib/riffer/helpers/dependencies.rb +0 -4
  59. data/lib/riffer/helpers/identifier.rb +3 -12
  60. data/lib/riffer/helpers/validate.rb +42 -0
  61. data/lib/riffer/mcp/authenticated_tool.rb +4 -12
  62. data/lib/riffer/mcp/client.rb +0 -7
  63. data/lib/riffer/mcp/manifest.rb +3 -7
  64. data/lib/riffer/mcp/registration.rb +0 -10
  65. data/lib/riffer/mcp/registry.rb +0 -9
  66. data/lib/riffer/mcp/search_tool.rb +0 -4
  67. data/lib/riffer/mcp/tool.rb +1 -4
  68. data/lib/riffer/mcp/tool_factory.rb +3 -6
  69. data/lib/riffer/mcp.rb +2 -23
  70. data/lib/riffer/messages/assistant/reasoning_part.rb +4 -21
  71. data/lib/riffer/messages/assistant/tool_call.rb +1 -9
  72. data/lib/riffer/messages/assistant.rb +1 -21
  73. data/lib/riffer/messages/base.rb +0 -12
  74. data/lib/riffer/messages/system.rb +0 -3
  75. data/lib/riffer/messages/tool.rb +0 -15
  76. data/lib/riffer/messages/user/file_part.rb +2 -30
  77. data/lib/riffer/messages/user.rb +0 -4
  78. data/lib/riffer/params/boolean.rb +1 -5
  79. data/lib/riffer/params/param.rb +3 -31
  80. data/lib/riffer/params.rb +8 -41
  81. data/lib/riffer/providers/amazon_bedrock.rb +101 -42
  82. data/lib/riffer/providers/anthropic.rb +9 -24
  83. data/lib/riffer/providers/azure_open_ai.rb +3 -8
  84. data/lib/riffer/providers/base.rb +7 -28
  85. data/lib/riffer/providers/finish_reason.rb +0 -6
  86. data/lib/riffer/providers/gemini/client.rb +4 -17
  87. data/lib/riffer/providers/gemini.rb +4 -10
  88. data/lib/riffer/providers/mock.rb +1 -26
  89. data/lib/riffer/providers/open_ai.rb +7 -17
  90. data/lib/riffer/providers/open_router.rb +105 -30
  91. data/lib/riffer/providers/repository.rb +2 -14
  92. data/lib/riffer/providers/token_usage.rb +5 -14
  93. data/lib/riffer/registrable.rb +11 -45
  94. data/lib/riffer/runner/fibers.rb +1 -6
  95. data/lib/riffer/runner/sequential.rb +0 -1
  96. data/lib/riffer/runner/threaded.rb +0 -3
  97. data/lib/riffer/runner.rb +0 -3
  98. data/lib/riffer/skills/activate_tool.rb +0 -3
  99. data/lib/riffer/skills/adapter.rb +0 -8
  100. data/lib/riffer/skills/backend.rb +2 -7
  101. data/lib/riffer/skills/config.rb +4 -20
  102. data/lib/riffer/skills/context.rb +0 -29
  103. data/lib/riffer/skills/filesystem_backend.rb +0 -7
  104. data/lib/riffer/skills/frontmatter.rb +2 -16
  105. data/lib/riffer/skills/markdown_adapter.rb +3 -6
  106. data/lib/riffer/skills/xml_adapter.rb +0 -3
  107. data/lib/riffer/stream_events/base.rb +0 -3
  108. data/lib/riffer/stream_events/finish_reason_done.rb +1 -6
  109. data/lib/riffer/stream_events/guardrail_modification.rb +0 -10
  110. data/lib/riffer/stream_events/guardrail_tripwire.rb +0 -10
  111. data/lib/riffer/stream_events/interrupt.rb +2 -12
  112. data/lib/riffer/stream_events/reasoning_delta.rb +0 -3
  113. data/lib/riffer/stream_events/reasoning_done.rb +1 -5
  114. data/lib/riffer/stream_events/skill_activation.rb +0 -3
  115. data/lib/riffer/stream_events/text_delta.rb +0 -2
  116. data/lib/riffer/stream_events/text_done.rb +0 -2
  117. data/lib/riffer/stream_events/token_usage_done.rb +0 -2
  118. data/lib/riffer/stream_events/tool_call_delta.rb +1 -5
  119. data/lib/riffer/stream_events/tool_call_done.rb +0 -5
  120. data/lib/riffer/stream_events/web_search_done.rb +0 -3
  121. data/lib/riffer/stream_events/web_search_status.rb +1 -5
  122. data/lib/riffer/testing/minitest.rb +4 -5
  123. data/lib/riffer/testing.rb +5 -38
  124. data/lib/riffer/tool.rb +2 -28
  125. data/lib/riffer/tools/response.rb +3 -32
  126. data/lib/riffer/tools/runtime/fibers.rb +0 -6
  127. data/lib/riffer/tools/runtime/inline.rb +0 -1
  128. data/lib/riffer/tools/runtime/threaded.rb +0 -6
  129. data/lib/riffer/tools/runtime.rb +5 -26
  130. data/lib/riffer/tools/toolable.rb +0 -37
  131. data/lib/riffer/tracing/capture.rb +3 -5
  132. data/lib/riffer/tracing/no_op.rb +0 -7
  133. data/lib/riffer/tracing/otel.rb +7 -16
  134. data/lib/riffer/tracing/stream_recorder.rb +0 -7
  135. data/lib/riffer/tracing.rb +4 -27
  136. data/lib/riffer/version.rb +1 -1
  137. data/lib/riffer.rb +2 -30
  138. data/sig/generated/riffer/agent/config.rbs +12 -48
  139. data/sig/generated/riffer/agent/context.rbs +2 -26
  140. data/sig/generated/riffer/agent/outcome.rbs +0 -20
  141. data/sig/generated/riffer/agent/response.rbs +1 -29
  142. data/sig/generated/riffer/agent/run.rbs +1 -27
  143. data/sig/generated/riffer/agent/serializer.rbs +2 -27
  144. data/sig/generated/riffer/agent/session/repair.rbs +2 -10
  145. data/sig/generated/riffer/agent/session.rbs +10 -36
  146. data/sig/generated/riffer/agent/structured_output/result.rbs +0 -7
  147. data/sig/generated/riffer/agent/structured_output.rbs +0 -7
  148. data/sig/generated/riffer/agent.rbs +5 -121
  149. data/sig/generated/riffer/config/amazon_bedrock.rbs +21 -0
  150. data/sig/generated/riffer/config/anthropic.rbs +15 -0
  151. data/sig/generated/riffer/config/azure_open_ai.rbs +21 -0
  152. data/sig/generated/riffer/config/evals.rbs +13 -0
  153. data/sig/generated/riffer/config/files.rbs +43 -0
  154. data/sig/generated/riffer/config/gemini.rbs +15 -0
  155. data/sig/generated/riffer/config/mcp.rbs +19 -0
  156. data/sig/generated/riffer/config/open_ai.rbs +21 -0
  157. data/sig/generated/riffer/config/open_router.rbs +15 -0
  158. data/sig/generated/riffer/config/pricing/rates.rbs +19 -0
  159. data/sig/generated/riffer/config/pricing.rbs +31 -0
  160. data/sig/generated/riffer/config/skills.rbs +19 -0
  161. data/sig/generated/riffer/config/tracing.rbs +25 -0
  162. data/sig/generated/riffer/config.rbs +2 -307
  163. data/sig/generated/riffer/evals/evaluator.rbs +0 -28
  164. data/sig/generated/riffer/evals/evaluator_runner.rbs +0 -14
  165. data/sig/generated/riffer/evals/judge.rbs +0 -7
  166. data/sig/generated/riffer/evals/result.rbs +1 -11
  167. data/sig/generated/riffer/evals/run_result.rbs +0 -12
  168. data/sig/generated/riffer/evals/scenario_result.rbs +0 -14
  169. data/sig/generated/riffer/files/resolver.rbs +0 -7
  170. data/sig/generated/riffer/guardrail.rbs +2 -22
  171. data/sig/generated/riffer/guardrails/modification.rbs +0 -6
  172. data/sig/generated/riffer/guardrails/result.rbs +0 -15
  173. data/sig/generated/riffer/guardrails/runner.rbs +0 -11
  174. data/sig/generated/riffer/guardrails/tripwire.rbs +0 -8
  175. data/sig/generated/riffer/guardrails.rbs +0 -2
  176. data/sig/generated/riffer/helpers/boolean.rbs +0 -4
  177. data/sig/generated/riffer/helpers/call_or_value.rbs +0 -3
  178. data/sig/generated/riffer/helpers/deep_dup.rbs +0 -8
  179. data/sig/generated/riffer/helpers/dependencies.rbs +0 -4
  180. data/sig/generated/riffer/helpers/identifier.rbs +0 -12
  181. data/sig/generated/riffer/helpers/validate.rbs +21 -0
  182. data/sig/generated/riffer/mcp/authenticated_tool.rbs +0 -5
  183. data/sig/generated/riffer/mcp/client.rbs +0 -7
  184. data/sig/generated/riffer/mcp/manifest.rbs +3 -7
  185. data/sig/generated/riffer/mcp/registration.rbs +0 -10
  186. data/sig/generated/riffer/mcp/registry.rbs +0 -9
  187. data/sig/generated/riffer/mcp/search_tool.rbs +0 -4
  188. data/sig/generated/riffer/mcp/tool.rbs +0 -4
  189. data/sig/generated/riffer/mcp/tool_factory.rbs +0 -6
  190. data/sig/generated/riffer/mcp.rbs +2 -22
  191. data/sig/generated/riffer/messages/assistant/reasoning_part.rbs +4 -17
  192. data/sig/generated/riffer/messages/assistant/tool_call.rbs +1 -9
  193. data/sig/generated/riffer/messages/assistant.rbs +10 -30
  194. data/sig/generated/riffer/messages/base.rbs +0 -12
  195. data/sig/generated/riffer/messages/system.rbs +0 -3
  196. data/sig/generated/riffer/messages/tool.rbs +0 -12
  197. data/sig/generated/riffer/messages/user/file_part.rbs +0 -30
  198. data/sig/generated/riffer/messages/user.rbs +0 -4
  199. data/sig/generated/riffer/params/boolean.rbs +1 -4
  200. data/sig/generated/riffer/params/param.rbs +0 -31
  201. data/sig/generated/riffer/params.rbs +4 -40
  202. data/sig/generated/riffer/providers/amazon_bedrock.rbs +29 -25
  203. data/sig/generated/riffer/providers/anthropic.rbs +0 -10
  204. data/sig/generated/riffer/providers/azure_open_ai.rbs +0 -8
  205. data/sig/generated/riffer/providers/base.rbs +0 -28
  206. data/sig/generated/riffer/providers/finish_reason.rbs +0 -6
  207. data/sig/generated/riffer/providers/gemini/client.rbs +4 -17
  208. data/sig/generated/riffer/providers/gemini.rbs +0 -6
  209. data/sig/generated/riffer/providers/mock.rbs +0 -26
  210. data/sig/generated/riffer/providers/open_ai.rbs +2 -9
  211. data/sig/generated/riffer/providers/open_router.rbs +33 -14
  212. data/sig/generated/riffer/providers/repository.rbs +2 -14
  213. data/sig/generated/riffer/providers/token_usage.rbs +5 -14
  214. data/sig/generated/riffer/registrable.rbs +0 -45
  215. data/sig/generated/riffer/runner/fibers.rbs +0 -6
  216. data/sig/generated/riffer/runner/sequential.rbs +0 -1
  217. data/sig/generated/riffer/runner/threaded.rbs +0 -3
  218. data/sig/generated/riffer/runner.rbs +0 -3
  219. data/sig/generated/riffer/skills/activate_tool.rbs +0 -3
  220. data/sig/generated/riffer/skills/adapter.rbs +0 -8
  221. data/sig/generated/riffer/skills/backend.rbs +2 -7
  222. data/sig/generated/riffer/skills/config.rbs +0 -20
  223. data/sig/generated/riffer/skills/context.rbs +0 -29
  224. data/sig/generated/riffer/skills/filesystem_backend.rbs +0 -7
  225. data/sig/generated/riffer/skills/frontmatter.rbs +2 -16
  226. data/sig/generated/riffer/skills/markdown_adapter.rbs +0 -6
  227. data/sig/generated/riffer/skills/xml_adapter.rbs +0 -3
  228. data/sig/generated/riffer/stream_events/base.rbs +0 -3
  229. data/sig/generated/riffer/stream_events/finish_reason_done.rbs +1 -6
  230. data/sig/generated/riffer/stream_events/guardrail_modification.rbs +0 -10
  231. data/sig/generated/riffer/stream_events/guardrail_tripwire.rbs +0 -10
  232. data/sig/generated/riffer/stream_events/interrupt.rbs +2 -10
  233. data/sig/generated/riffer/stream_events/reasoning_delta.rbs +0 -3
  234. data/sig/generated/riffer/stream_events/reasoning_done.rbs +1 -5
  235. data/sig/generated/riffer/stream_events/skill_activation.rbs +0 -3
  236. data/sig/generated/riffer/stream_events/text_delta.rbs +0 -2
  237. data/sig/generated/riffer/stream_events/text_done.rbs +0 -2
  238. data/sig/generated/riffer/stream_events/token_usage_done.rbs +0 -2
  239. data/sig/generated/riffer/stream_events/tool_call_delta.rbs +1 -5
  240. data/sig/generated/riffer/stream_events/tool_call_done.rbs +0 -5
  241. data/sig/generated/riffer/stream_events/web_search_done.rbs +0 -3
  242. data/sig/generated/riffer/stream_events/web_search_status.rbs +1 -5
  243. data/sig/generated/riffer/testing.rbs +0 -38
  244. data/sig/generated/riffer/tool.rbs +0 -27
  245. data/sig/generated/riffer/tools/response.rbs +3 -29
  246. data/sig/generated/riffer/tools/runtime/fibers.rbs +0 -5
  247. data/sig/generated/riffer/tools/runtime/inline.rbs +0 -1
  248. data/sig/generated/riffer/tools/runtime/threaded.rbs +0 -5
  249. data/sig/generated/riffer/tools/runtime.rbs +2 -24
  250. data/sig/generated/riffer/tools/toolable.rbs +0 -37
  251. data/sig/generated/riffer/tracing/capture.rbs +2 -5
  252. data/sig/generated/riffer/tracing/no_op.rbs +0 -7
  253. data/sig/generated/riffer/tracing/otel.rbs +7 -16
  254. data/sig/generated/riffer/tracing/stream_recorder.rbs +0 -2
  255. data/sig/generated/riffer/tracing.rbs +4 -23
  256. data/sig/generated/riffer.rbs +2 -29
  257. data/sig/manual/riffer/helpers/validate.rbs +5 -0
  258. metadata +30 -1
@@ -1,20 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Shared class-level DSL for anything that presents as a tool to an LLM. Extend
5
- # it to make a class discoverable as a tool; instance-level execution (+call+,
6
- # +call_with_validation+) lives on Riffer::Tool instead.
7
- #
8
- # class MyTool
9
- # extend Riffer::Tools::Toolable
10
- #
11
- # description "Does something useful"
12
- #
13
- # params do
14
- # required :input, String
15
- # end
16
- # end
17
- #
18
4
  # @rbs module-self Module
19
5
  module Riffer::Tools::Toolable
20
6
  # @rbs self.@extenders: Array[Module]?
@@ -26,8 +12,6 @@ module Riffer::Tools::Toolable
26
12
 
27
13
  DEFAULT_TIMEOUT = 10 #: Integer
28
14
 
29
- # Tracks all classes that extend Toolable.
30
- #
31
15
  #--
32
16
  #: (Module) -> void
33
17
  def self.extended(base)
@@ -35,16 +19,12 @@ module Riffer::Tools::Toolable
35
19
  extenders << base
36
20
  end
37
21
 
38
- # Returns all classes that have extended Toolable.
39
- #
40
22
  #--
41
23
  #: () -> Array[Module]
42
24
  def self.all
43
25
  @extenders || []
44
26
  end
45
27
 
46
- # Gets or sets the tool description.
47
- #
48
28
  #--
49
29
  #: (?String?) -> String?
50
30
  def description(value = nil)
@@ -53,8 +33,6 @@ module Riffer::Tools::Toolable
53
33
  @description = value.to_s
54
34
  end
55
35
 
56
- # Gets or sets the tool identifier/name.
57
- #
58
36
  #--
59
37
  #: (?String?) -> String
60
38
  def identifier(value = nil)
@@ -63,8 +41,6 @@ module Riffer::Tools::Toolable
63
41
  @identifier = value.to_s
64
42
  end
65
43
 
66
- # Alias for identifier — used by providers.
67
- #
68
44
  #--
69
45
  #: (?String?) -> String
70
46
  def name(value = nil)
@@ -73,8 +49,6 @@ module Riffer::Tools::Toolable
73
49
  identifier
74
50
  end
75
51
 
76
- # Gets or sets the tool timeout in seconds.
77
- #
78
52
  #--
79
53
  #: (?(Integer | Float)?) -> (Integer | Float)
80
54
  def timeout(value = nil)
@@ -83,8 +57,6 @@ module Riffer::Tools::Toolable
83
57
  @timeout = value.to_f
84
58
  end
85
59
 
86
- # Defines parameters using the Params DSL.
87
- #
88
60
  #--
89
61
  #: () ?{ (Riffer::Params) [self: Riffer::Params] -> void } -> Riffer::Params?
90
62
  def params(&block)
@@ -95,15 +67,12 @@ module Riffer::Tools::Toolable
95
67
  @params_builder = builder
96
68
  end
97
69
 
98
- # Returns the JSON Schema for the tool's parameters.
99
- #
100
70
  #--
101
71
  #: (?strict: bool) -> Hash[Symbol, untyped]
102
72
  def parameters_schema(strict: false)
103
73
  @params_builder&.to_json_schema(strict: strict) || empty_schema
104
74
  end
105
75
 
106
- # Returns the kind of toolable entity; defaults to +:tool+.
107
76
  #--
108
77
  #: (?Symbol?) -> Symbol
109
78
  def kind(value = nil)
@@ -112,8 +81,6 @@ module Riffer::Tools::Toolable
112
81
  @kind = value.to_sym
113
82
  end
114
83
 
115
- # Returns a provider-agnostic tool schema hash.
116
- #
117
84
  #--
118
85
  #: (?strict: bool) -> Hash[Symbol, untyped]
119
86
  def to_tool_schema(strict: false)
@@ -124,10 +91,6 @@ module Riffer::Tools::Toolable
124
91
  }
125
92
  end
126
93
 
127
- # Validates that the minimum required metadata is present for LLM tool use.
128
- #
129
- # Raises Riffer::ArgumentError if validation fails.
130
- #
131
94
  #--
132
95
  #: () -> true
133
96
  def validate_as_tool!
@@ -3,9 +3,6 @@
3
3
 
4
4
  require "json"
5
5
 
6
- # Serializes riffer messages into the GenAI semconv JSON message structure
7
- # for opt-in span content capture. File parts become metadata-only stubs —
8
- # bytes and URLs never reach a span attribute.
9
6
  module Riffer::Tracing::Capture # :nodoc: all
10
7
  extend self
11
8
 
@@ -73,13 +70,14 @@ module Riffer::Tracing::Capture # :nodoc: all
73
70
  #--
74
71
  #: (Riffer::Messages::User::FilePart) -> Hash[Symbol, untyped]
75
72
  def file_part(file)
73
+ # Metadata only: file bytes and URLs must never reach a span attribute.
76
74
  part = { type: "file", media_type: file.media_type } #: Hash[Symbol, untyped]
77
75
  part[:name] = file.filename if file.filename
78
76
  part
79
77
  end
80
78
 
81
- # Semconv's tool_call part carries arguments as a JSON object; riffer holds
82
- # them as a string — parse so the captured payload isn't double-encoded.
79
+ # Semconv's tool_call part carries arguments as a JSON object, so a string
80
+ # would be double-encoded.
83
81
  #--
84
82
  #: (String) -> untyped
85
83
  def parse_arguments(arguments)
@@ -1,13 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # No-op tracing backend, used when OTEL is unavailable or tracing is
5
- # disabled.
6
4
  module Riffer::Tracing::NoOp # :nodoc: all
7
5
  extend self
8
6
 
9
- # No-op stand-in for a span; answers <tt>recording?</tt> with +false+ so
10
- # callers can skip expensive attribute serialization.
11
7
  class Span
12
8
  #--
13
9
  #: (String, untyped) -> void
@@ -34,21 +30,18 @@ module Riffer::Tracing::NoOp # :nodoc: all
34
30
 
35
31
  SPAN = Span.new.freeze #: Riffer::Tracing::NoOp::Span
36
32
 
37
- # Yields the no-op span, ignoring all span options.
38
33
  #--
39
34
  #: [R] (String, **untyped) { (Riffer::Tracing::NoOp::Span) -> R } -> R
40
35
  def in_span(_name, **)
41
36
  yield SPAN
42
37
  end
43
38
 
44
- # Returns +nil+; there is no trace context without OTEL.
45
39
  #--
46
40
  #: () -> nil
47
41
  def current_context
48
42
  nil
49
43
  end
50
44
 
51
- # Yields immediately; there is no context to attach.
52
45
  #--
53
46
  #: [R] (untyped) { () -> R } -> R
54
47
  def with_context(_context)
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # OTEL-backed tracing backend. <tt>::OpenTelemetry</tt> constants appear only
5
- # inside method bodies here, so the gem loads and eager-loads cleanly when the
6
- # OpenTelemetry API is absent.
4
+ # <tt>::OpenTelemetry</tt> constants must appear only inside method bodies, so
5
+ # the gem eager-loads cleanly when the OpenTelemetry API is absent.
7
6
  class Riffer::Tracing::Otel # :nodoc: all
8
7
  SUPPORTED_API_VERSIONS = Gem::Requirement.new(">= 1.1", "< 2") #: Gem::Requirement
9
8
 
10
- # Wraps a live OTEL span behind the port's span surface, so callers never
11
- # touch <tt>::OpenTelemetry</tt> constants (status objects in particular).
9
+ # Keeps callers from touching <tt>::OpenTelemetry</tt> constants (status
10
+ # objects in particular).
12
11
  class Span
13
12
  # @rbs @otel_span: untyped
14
13
 
@@ -36,7 +35,6 @@ class Riffer::Tracing::Otel # :nodoc: all
36
35
  @otel_span.record_exception(exception)
37
36
  end
38
37
 
39
- # Marks the span status as error.
40
38
  #--
41
39
  #: (?String) -> void
42
40
  def error!(description = "")
@@ -51,9 +49,7 @@ class Riffer::Tracing::Otel # :nodoc: all
51
49
  end
52
50
 
53
51
  class << self
54
- # Builds a backend when the OpenTelemetry API is loadable at a supported
55
- # version; returns +nil+ so resolution falls back to NoOp. +provider+
56
- # defaults to the global <tt>OpenTelemetry.tracer_provider</tt>.
52
+ # Returns +nil+ so resolution falls back to NoOp.
57
53
  #--
58
54
  #: (?provider: untyped) -> Riffer::Tracing::Otel?
59
55
  def build(provider: nil)
@@ -69,7 +65,6 @@ class Riffer::Tracing::Otel # :nodoc: all
69
65
  new(provider: provider || ::OpenTelemetry.tracer_provider)
70
66
  end
71
67
 
72
- # Whether the OpenTelemetry API gem is loadable at a supported version.
73
68
  #--
74
69
  #: () -> bool
75
70
  def available?
@@ -79,9 +74,8 @@ class Riffer::Tracing::Otel # :nodoc: all
79
74
  supported?(version)
80
75
  end
81
76
 
82
- # Whether the given opentelemetry-api version is one riffer codes
83
- # against. The gem is undeclared, so this guard is the only protection
84
- # against an incompatible API.
77
+ # opentelemetry-api is undeclared, so this is the only protection against
78
+ # an incompatible API.
85
79
  #--
86
80
  #: (Gem::Version) -> bool
87
81
  def supported?(version)
@@ -109,7 +103,6 @@ class Riffer::Tracing::Otel # :nodoc: all
109
103
  @tracer = provider.tracer("riffer", Riffer::VERSION)
110
104
  end
111
105
 
112
- # Opens an OTEL span around the block, yielding the wrapped span.
113
106
  #--
114
107
  #: [R] (String, attributes: Hash[String, untyped]?, kind: Symbol) { (Riffer::Tracing::Otel::Span) -> R } -> R
115
108
  def in_span(name, attributes:, kind:)
@@ -118,14 +111,12 @@ class Riffer::Tracing::Otel # :nodoc: all
118
111
  end
119
112
  end
120
113
 
121
- # Returns the active OTEL context.
122
114
  #--
123
115
  #: () -> untyped
124
116
  def current_context
125
117
  ::OpenTelemetry::Context.current
126
118
  end
127
119
 
128
- # Runs the block with the given OTEL context active.
129
120
  #--
130
121
  #: [R] (untyped) { () -> R } -> R
131
122
  def with_context(context, &)
@@ -1,23 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Wraps a stream yielder to observe terminal events for span stamping while
5
- # forwarding every event downstream untouched.
6
4
  class Riffer::Tracing::StreamRecorder # :nodoc: all
7
5
  # @rbs @yielder: Enumerator::Yielder
8
6
  # @rbs @clock: ^() -> Float
9
7
  # @rbs @started_at: Float
10
8
 
11
9
  attr_reader :token_usage #: Riffer::Providers::TokenUsage? # @dynamic token_usage
12
-
13
10
  attr_reader :time_to_first_chunk #: Float? # @dynamic time_to_first_chunk
14
-
15
11
  attr_reader :finish_reason #: Symbol? # @dynamic finish_reason
16
-
17
12
  attr_reader :raw_finish_reason #: String? # @dynamic raw_finish_reason
18
-
19
13
  attr_reader :content #: String? # @dynamic content
20
-
21
14
  attr_reader :tool_calls #: Array[Riffer::Messages::Assistant::ToolCall] # @dynamic tool_calls
22
15
 
23
16
  #--
@@ -1,21 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Internal tracing port — emits OTEL spans when the host bundles the
5
- # OpenTelemetry API and no-ops otherwise, so riffer never declares an OTEL
6
- # dependency.
4
+ # No-ops unless the host bundles the OpenTelemetry API, so riffer never
5
+ # declares an OTEL dependency.
7
6
  module Riffer::Tracing # :nodoc: all
8
7
  extend self
9
8
 
10
- # @rbs @backend: untyped
11
-
12
- MUTEX = Mutex.new #: Mutex
13
-
14
9
  # The Ruby API cannot attach a schema URL to a tracer, so the semconv pin
15
10
  # lives here as the documented contract version.
16
11
  SCHEMA_URL = "https://opentelemetry.io/schemas/1.37.0" #: String
17
12
 
18
- # Opens a span around the block, yielding the span.
19
13
  #--
20
14
  #: [R] (String, ?attributes: Hash[String, untyped]?, ?kind: Symbol) { (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span) -> R } -> R
21
15
  def in_span(name, attributes: nil, kind: :internal, &)
@@ -24,8 +18,7 @@ module Riffer::Tracing # :nodoc: all
24
18
  backend.in_span(name, attributes: attributes, kind: kind, &)
25
19
  end
26
20
 
27
- # Returns the active trace context, for re-attachment across fiber or
28
- # thread boundaries.
21
+ # For re-attachment across fiber or thread boundaries.
29
22
  #--
30
23
  #: () -> untyped
31
24
  def current_context
@@ -34,8 +27,7 @@ module Riffer::Tracing # :nodoc: all
34
27
  backend.current_context
35
28
  end
36
29
 
37
- # Runs the block with the given trace context active; +nil+ passes through
38
- # so captures taken while tracing was dark stay harmless.
30
+ # +nil+ passes through so captures taken while tracing was off stay harmless.
39
31
  #--
40
32
  #: [R] (untyped) { () -> R } -> R
41
33
  def with_context(context, &)
@@ -44,8 +36,6 @@ module Riffer::Tracing # :nodoc: all
44
36
  backend.with_context(context, &)
45
37
  end
46
38
 
47
- # Stamps token usage onto the span — the <tt>gen_ai.usage.*</tt> counts and,
48
- # when the model was priced, <tt>riffer.cost</tt>.
49
39
  #--
50
40
  #: ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span), Riffer::Providers::TokenUsage?) -> void
51
41
  def record_usage(span, usage)
@@ -58,24 +48,11 @@ module Riffer::Tracing # :nodoc: all
58
48
  span.set_attribute("riffer.cost", usage.cost) if usage.cost
59
49
  end
60
50
 
61
- # Discards the resolved backend so the next span re-resolves it.
62
- #--
63
- #: () -> void
64
- def reset!
65
- MUTEX.synchronize { @backend = nil }
66
- end
67
-
68
51
  private
69
52
 
70
53
  #--
71
54
  #: () -> untyped
72
55
  def backend
73
- @backend || MUTEX.synchronize { @backend ||= resolve_backend }
74
- end
75
-
76
- #--
77
- #: () -> untyped
78
- def resolve_backend
79
56
  Riffer.config.tracing.backend || NoOp
80
57
  end
81
58
  end
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Riffer
5
- VERSION = "0.48.0" #: String
5
+ VERSION = "0.49.0" #: String
6
6
  end
data/lib/riffer.rb CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  require "zeitwerk"
5
5
 
6
- # Riffer is the main module for the Riffer AI framework.
7
6
  loader = Zeitwerk::Loader.for_gem
8
7
  loader.inflector.inflect(
9
8
  "open_ai" => "OpenAI",
@@ -24,78 +23,51 @@ module Riffer
24
23
 
25
24
  # @rbs @config: Riffer::Config?
26
25
 
27
- # Base error class for Riffer.
28
26
  class Error < StandardError; end
29
27
 
30
- # Raised when invalid arguments are provided.
31
28
  class ArgumentError < ::ArgumentError; end
32
29
 
33
- # Raised when tool parameter validation fails.
34
30
  class ValidationError < Error; end
35
31
 
36
- # Raised inside a tool's +call+ when execution exceeds the configured
37
- # timeout. Rescue it in the tool to clean up; otherwise it becomes a
32
+ # Rescue it in the tool to clean up; otherwise it becomes a
38
33
  # +:timeout_error+ response.
39
34
  class TimeoutError < Error; end
40
35
 
41
- # Raised when a tool encounters an expected execution error.
42
36
  class ToolExecutionError < Error; end
43
37
 
44
- # Raised when a provider's stream ends before its terminal event (Bedrock's
45
- # messageStop, Anthropic's message_stop, OpenAI's response.completed /
46
- # incomplete / failed), so a truncated or empty response is never returned
47
- # as a complete message. Events already yielded were delivered; the
48
- # request is safe to retry.
38
+ # Events already yielded were delivered; the request is safe to retry.
49
39
  class IncompleteStreamError < Error; end
50
40
 
51
- # Base error for a file attachment that can't be resolved for the provider.
52
41
  class FileError < Error; end
53
42
 
54
- # Raised when the provider can't accept the file at all.
55
43
  class FileUnsupportedError < FileError; end
56
44
 
57
- # Raised when a download is required but Riffer.config.files.allow_downloads is false.
58
45
  class FileDownloadsDisabledError < FileError; end
59
46
 
60
- # Raised when a message carries more files than Riffer.config.files.max_per_message allows.
61
47
  class TooManyFilesError < FileError; end
62
48
 
63
- # Raised when there's an issue downloading a file
64
49
  class FileDownloadError < FileError; end
65
50
 
66
- # Raised when a file size exceeds Riffer.config.files.max_bytes
67
51
  class FileTooLargeError < FileError; end
68
52
 
69
- # Raised when a downloaded or inline file's sha256 doesn't match.
70
53
  class FileChecksumMismatchError < FileError; end
71
54
 
72
- # Raised when a FilePart's data isn't valid base64
73
55
  class FileEncodingError < FileError; end
74
56
 
75
- # Raised when two registered subclasses share the same identifier.
76
57
  class DuplicateIdentifierError < Error; end
77
58
 
78
- # Returns the Riffer configuration.
79
- #
80
59
  #--
81
60
  #: () -> Riffer::Config
82
61
  def config
83
62
  @config ||= Config.new
84
63
  end
85
64
 
86
- # Yields the configuration for block-based setup.
87
- #
88
- # Riffer.configure do |config|
89
- # config.openai.api_key = ENV['OPENAI_API_KEY']
90
- # end
91
- #
92
65
  #--
93
66
  #: () ?{ (Riffer::Config) -> void } -> void
94
67
  def configure(&)
95
68
  yield config if block_given?
96
69
  end
97
70
 
98
- # Returns the gem version.
99
71
  #--
100
72
  #: () -> String
101
73
  def version
@@ -1,120 +1,84 @@
1
1
  # Generated from lib/riffer/agent/config.rb with RBS::Inline
2
2
 
3
- # Typed configuration object holding every class-level DSL setting on a
4
- # Riffer::Agent subclass. Procs are stored unresolved and resolved per-instance
5
- # later.
6
3
  class Riffer::Agent::Config
7
4
  DEFAULT_MAX_STEPS: Integer
8
5
 
9
6
  @tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?
10
7
 
11
- # The configured agent identifier.
12
8
  attr_reader identifier: String?
13
9
 
14
- # The configured model.
15
10
  attr_reader model: (String | Proc)?
16
11
 
17
- # The configured instructions.
18
12
  attr_reader instructions: (String | Proc)?
19
13
 
20
- # Options passed to generate_text/stream_text.
21
14
  attr_accessor model_options: Hash[Symbol, untyped]
22
15
 
23
- # The configured structured-output schema.
24
16
  attr_reader structured_output: Riffer::Params?
25
17
 
26
- # The maximum number of LLM call steps in the tool-use loop.
27
18
  attr_accessor max_steps: Numeric?
28
19
 
29
- # The configured tools.
30
20
  attr_accessor tools_config: (Array[singleton(Riffer::Tool)] | Proc)?
31
21
 
32
- # The accumulated +use_mcp+ tag configurations.
33
22
  attr_reader mcp_configs: Array[Hash[Symbol, untyped]]
34
23
 
35
- # The configured skills.
36
24
  attr_accessor skills_config: Riffer::Skills::Config?
37
25
 
38
- # Registered guardrail entries keyed by phase.
39
26
  attr_reader guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]
40
27
 
41
- # Builds a new Config. Raises Riffer::ArgumentError if +model+ or
42
- # +instructions+ is invalid (e.g. an empty string).
43
28
  # --
44
29
  # : (
45
- # ?identifier: String?,
46
- # ?model: (String | Proc)?,
47
- # ?instructions: (String | Proc)?,
48
- # ?model_options: Hash[Symbol, untyped],
49
- # ?structured_output: Riffer::Params?,
50
- # ?max_steps: Numeric?,
51
- # ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?,
52
- # ?mcp_configs: Array[Hash[Symbol, untyped]],
53
- # ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?,
54
- # ?skills_config: Riffer::Skills::Config?,
55
- # ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]
56
- # ) -> void
30
+ # ?identifier: String?,
31
+ # ?model: (String | Proc)?,
32
+ # ?instructions: (String | Proc)?,
33
+ # ?model_options: Hash[Symbol, untyped],
34
+ # ?structured_output: Riffer::Params?,
35
+ # ?max_steps: Numeric?,
36
+ # ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?,
37
+ # ?mcp_configs: Array[Hash[Symbol, untyped]],
38
+ # ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?,
39
+ # ?skills_config: Riffer::Skills::Config?,
40
+ # ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]
41
+ # ) -> void
57
42
  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
58
43
 
59
- # Sets +identifier+, coercing the value to String.
60
44
  # --
61
45
  # : (untyped) -> String?
62
46
  def identifier=: (untyped) -> String?
63
47
 
64
- # Sets +structured_output+. Raises Riffer::ArgumentError on an invalid value.
65
48
  # --
66
49
  # : (Riffer::Params?) -> Riffer::Params?
67
50
  def structured_output=: (Riffer::Params?) -> Riffer::Params?
68
51
 
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
52
  # --
73
53
  # : () -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
74
54
  def tool_runtime: () -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
75
55
 
76
- # Sets +tool_runtime+. Raises Riffer::ArgumentError on an invalid value.
77
56
  # --
78
57
  # : ((singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
79
58
  def tool_runtime=: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
80
59
 
81
- # Sets +model+. Raises Riffer::ArgumentError on an invalid value (e.g. an
82
- # empty string).
83
60
  # --
84
61
  # : ((String | Proc)?) -> (String | Proc)?
85
62
  def model=: ((String | Proc)?) -> (String | Proc)?
86
63
 
87
- # Sets +instructions+. Raises Riffer::ArgumentError on an invalid value (e.g.
88
- # an empty string).
89
64
  # --
90
65
  # : ((String | Proc)?) -> (String | Proc)?
91
66
  def instructions=: ((String | Proc)?) -> (String | Proc)?
92
67
 
93
- # Appends an MCP tag entry to +mcp_configs+.
94
- #
95
68
  # --
96
69
  # : (String | Symbol, ?progressive: bool) -> Array[Hash[Symbol, untyped]]
97
70
  def add_mcp: (String | Symbol, ?progressive: bool) -> Array[Hash[Symbol, untyped]]
98
71
 
99
- # Appends a guardrail entry to +guardrails+ for the given phase; +:around+
100
- # appends to both +:before+ and +:after+. Raises Riffer::ArgumentError unless
101
- # +phase+ is :before, :after, or :around.
102
72
  # --
103
73
  # : (Symbol, klass: singleton(Riffer::Guardrail), ?options: Hash[Symbol, untyped]) -> void
104
74
  def add_guardrail: (Symbol, klass: singleton(Riffer::Guardrail), ?options: Hash[Symbol, untyped]) -> void
105
75
 
106
- # Returns the guardrail entries for the given phase, or +[]+ if none.
107
- #
108
76
  # --
109
77
  # : (Symbol) -> Array[Hash[Symbol, untyped]]
110
78
  def guardrails_for: (Symbol) -> Array[Hash[Symbol, untyped]]
111
79
 
112
80
  private
113
81
 
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
82
  # --
119
83
  # : (Riffer::Agent::Config) -> void
120
84
  def initialize_copy: (Riffer::Agent::Config) -> void
@@ -1,74 +1,52 @@
1
1
  # Generated from lib/riffer/agent/context.rb with RBS::Inline
2
2
 
3
- # Typed value object wrapping the runtime context Hash held by a Riffer::Agent.
4
- # Exposes typed +skills+, +token_usage+, +mcp_progressive_tools+, and
5
- # +discovered_tools+ accessors while preserving +#[]+ / +#dig+ for caller-provided keys.
6
3
  class Riffer::Agent::Context
7
4
  @data: Hash[Symbol, untyped]
8
5
 
9
6
  RESERVED_KEYS: Array[Symbol]
10
7
 
11
- # Builds a new context. The caller Hash is duped so later caller mutations
12
- # don't leak in. Raises Riffer::ArgumentError if it contains a reserved key.
8
+ # Raises Riffer::ArgumentError if +data+ contains a reserved key.
13
9
  # --
14
10
  # : (?Hash[Symbol, untyped]) -> void
15
11
  def initialize: (?Hash[Symbol, untyped]) -> void
16
12
 
17
- # The agent's resolved +Riffer::Skills::Context+, or +nil+ when skills
18
- # are not configured.
19
- #
20
13
  # --
21
14
  # : () -> Riffer::Skills::Context?
22
15
  def skills: () -> Riffer::Skills::Context?
23
16
 
24
- # Sets the resolved skills context. Raises Riffer::ArgumentError on an
25
- # invalid value.
26
17
  # --
27
18
  # : (Riffer::Skills::Context?) -> Riffer::Skills::Context?
28
19
  def skills=: (Riffer::Skills::Context?) -> Riffer::Skills::Context?
29
20
 
30
- # The cumulative +Riffer::Providers::TokenUsage+ across every Run on this agent,
31
- # or +nil+ before the first response is recorded.
32
- #
21
+ # Cumulative across every run on this agent.
33
22
  # --
34
23
  # : () -> Riffer::Providers::TokenUsage?
35
24
  def token_usage: () -> Riffer::Providers::TokenUsage?
36
25
 
37
- # Sets the cumulative token usage. Raises Riffer::ArgumentError on an invalid
38
- # value.
39
26
  # --
40
27
  # : (Riffer::Providers::TokenUsage?) -> Riffer::Providers::TokenUsage?
41
28
  def token_usage=: (Riffer::Providers::TokenUsage?) -> Riffer::Providers::TokenUsage?
42
29
 
43
- # Hash-style read, preserved so tools can pull caller-provided keys via
44
- # <tt>context[:agent]</tt>.
45
30
  # --
46
31
  # : (Symbol) -> untyped
47
32
  def []: (Symbol) -> untyped
48
33
 
49
- # Auth-wrapped MCP tool classes for progressive discovery, or +nil+.
50
34
  # --
51
35
  # : () -> Array[singleton(Riffer::Tool)]?
52
36
  def mcp_progressive_tools: () -> Array[singleton(Riffer::Tool)]?
53
37
 
54
- # Sets progressive MCP tools. Raises Riffer::ArgumentError on an invalid value.
55
38
  # --
56
39
  # : (Array[singleton(Riffer::Tool)]?) -> Array[singleton(Riffer::Tool)]?
57
40
  def mcp_progressive_tools=: (Array[singleton(Riffer::Tool)]?) -> Array[singleton(Riffer::Tool)]?
58
41
 
59
- # MCP tool classes discovered during progressive search. Accumulates across
60
- # +generate+ calls and is merged into the active tool list on every LLM call.
61
42
  # --
62
43
  # : () -> Array[singleton(Riffer::Tool)]?
63
44
  def discovered_tools: () -> Array[singleton(Riffer::Tool)]?
64
45
 
65
- # Sets the discovered tools array. Raises Riffer::ArgumentError on an invalid value.
66
46
  # --
67
47
  # : (Array[singleton(Riffer::Tool)]?) -> Array[singleton(Riffer::Tool)]?
68
48
  def discovered_tools=: (Array[singleton(Riffer::Tool)]?) -> Array[singleton(Riffer::Tool)]?
69
49
 
70
- # Accumulates newly discovered MCP tool classes, deduplicating by name.
71
- # Each call extends the existing set; calling multiple times is safe.
72
50
  # --
73
51
  # : (Array[singleton(Riffer::Tool)]) -> Array[singleton(Riffer::Tool)]
74
52
  def discover_tools: (Array[singleton(Riffer::Tool)]) -> Array[singleton(Riffer::Tool)]
@@ -77,8 +55,6 @@ class Riffer::Agent::Context
77
55
  # : (*Symbol) -> untyped
78
56
  def dig: (*Symbol) -> untyped
79
57
 
80
- # Returns a copy of the underlying Hash; mutating it does not affect this
81
- # context.
82
58
  # --
83
59
  # : () -> Hash[Symbol, untyped]
84
60
  def to_h: () -> Hash[Symbol, untyped]