riffer 0.31.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 (213) 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 +18 -0
  7. data/docs/08_MESSAGES.md +1 -1
  8. data/docs/14_MCP.md +50 -5
  9. data/docs/providers/02_AMAZON_BEDROCK.md +14 -0
  10. data/lib/riffer/agent/config.rb +42 -47
  11. data/lib/riffer/agent/context.rb +70 -50
  12. data/lib/riffer/agent/response.rb +4 -20
  13. data/lib/riffer/agent/run.rb +28 -67
  14. data/lib/riffer/agent/serializer.rb +22 -81
  15. data/lib/riffer/agent/session/repair.rb +14 -40
  16. data/lib/riffer/agent/session.rb +25 -67
  17. data/lib/riffer/agent/structured_output/result.rb +3 -11
  18. data/lib/riffer/agent/structured_output.rb +5 -13
  19. data/lib/riffer/agent.rb +74 -192
  20. data/lib/riffer/config.rb +34 -101
  21. data/lib/riffer/evals/evaluator.rb +7 -27
  22. data/lib/riffer/evals/evaluator_runner.rb +11 -19
  23. data/lib/riffer/evals/judge.rb +4 -25
  24. data/lib/riffer/evals/result.rb +1 -18
  25. data/lib/riffer/evals/run_result.rb +0 -11
  26. data/lib/riffer/evals/scenario_result.rb +0 -14
  27. data/lib/riffer/evals.rb +0 -6
  28. data/lib/riffer/guardrail.rb +4 -27
  29. data/lib/riffer/guardrails/modification.rb +0 -10
  30. data/lib/riffer/guardrails/result.rb +3 -30
  31. data/lib/riffer/guardrails/runner.rb +5 -22
  32. data/lib/riffer/guardrails/tripwire.rb +1 -19
  33. data/lib/riffer/guardrails.rb +2 -4
  34. data/lib/riffer/helpers/call_or_value.rb +4 -3
  35. data/lib/riffer/helpers/class_name_converter.rb +3 -1
  36. data/lib/riffer/helpers/dependencies.rb +5 -7
  37. data/lib/riffer/helpers.rb +0 -5
  38. data/lib/riffer/mcp/authenticated_tool.rb +9 -9
  39. data/lib/riffer/mcp/client.rb +12 -17
  40. data/lib/riffer/mcp/manifest.rb +13 -10
  41. data/lib/riffer/mcp/registration.rb +2 -11
  42. data/lib/riffer/mcp/registry.rb +44 -52
  43. data/lib/riffer/mcp/search_tool.rb +53 -0
  44. data/lib/riffer/mcp/tool_factory.rb +13 -18
  45. data/lib/riffer/mcp.rb +12 -17
  46. data/lib/riffer/messages/assistant.rb +2 -9
  47. data/lib/riffer/messages/base.rb +46 -16
  48. data/lib/riffer/messages/file_part.rb +32 -24
  49. data/lib/riffer/messages/system.rb +0 -5
  50. data/lib/riffer/messages/tool.rb +0 -10
  51. data/lib/riffer/messages/user.rb +0 -10
  52. data/lib/riffer/messages.rb +0 -7
  53. data/lib/riffer/params/boolean.rb +2 -4
  54. data/lib/riffer/params/param.rb +28 -39
  55. data/lib/riffer/params.rb +9 -21
  56. data/lib/riffer/providers/amazon_bedrock.rb +42 -28
  57. data/lib/riffer/providers/anthropic.rb +4 -9
  58. data/lib/riffer/providers/azure_open_ai.rb +3 -19
  59. data/lib/riffer/providers/base.rb +13 -26
  60. data/lib/riffer/providers/gemini.rb +4 -4
  61. data/lib/riffer/providers/mock.rb +6 -26
  62. data/lib/riffer/providers/open_ai.rb +6 -8
  63. data/lib/riffer/providers/open_router.rb +4 -10
  64. data/lib/riffer/providers/repository.rb +4 -3
  65. data/lib/riffer/providers/token_usage.rb +9 -20
  66. data/lib/riffer/providers.rb +0 -8
  67. data/lib/riffer/runner/fibers.rb +10 -16
  68. data/lib/riffer/runner/sequential.rb +1 -4
  69. data/lib/riffer/runner/threaded.rb +3 -14
  70. data/lib/riffer/runner.rb +2 -15
  71. data/lib/riffer/skills/activate_tool.rb +2 -11
  72. data/lib/riffer/skills/adapter.rb +4 -22
  73. data/lib/riffer/skills/backend.rb +7 -21
  74. data/lib/riffer/skills/config.rb +10 -31
  75. data/lib/riffer/skills/context.rb +5 -20
  76. data/lib/riffer/skills/filesystem_backend.rb +7 -25
  77. data/lib/riffer/skills/frontmatter.rb +10 -28
  78. data/lib/riffer/skills/markdown_adapter.rb +2 -9
  79. data/lib/riffer/skills/xml_adapter.rb +2 -8
  80. data/lib/riffer/stream_events/base.rb +1 -6
  81. data/lib/riffer/stream_events/guardrail_modification.rb +1 -8
  82. data/lib/riffer/stream_events/guardrail_tripwire.rb +1 -8
  83. data/lib/riffer/stream_events/interrupt.rb +4 -7
  84. data/lib/riffer/stream_events/reasoning_delta.rb +2 -4
  85. data/lib/riffer/stream_events/reasoning_done.rb +2 -4
  86. data/lib/riffer/stream_events/skill_activation.rb +2 -4
  87. data/lib/riffer/stream_events/text_delta.rb +0 -2
  88. data/lib/riffer/stream_events/text_done.rb +1 -3
  89. data/lib/riffer/stream_events/token_usage_done.rb +1 -8
  90. data/lib/riffer/stream_events/tool_call_delta.rb +2 -3
  91. data/lib/riffer/stream_events/tool_call_done.rb +1 -3
  92. data/lib/riffer/stream_events/web_search_done.rb +1 -3
  93. data/lib/riffer/stream_events/web_search_status.rb +2 -3
  94. data/lib/riffer/stream_events.rb +0 -10
  95. data/lib/riffer/tool.rb +6 -13
  96. data/lib/riffer/tools/response.rb +8 -4
  97. data/lib/riffer/tools/runtime/fibers.rb +0 -3
  98. data/lib/riffer/tools/runtime/inline.rb +1 -4
  99. data/lib/riffer/tools/runtime/threaded.rb +0 -2
  100. data/lib/riffer/tools/runtime.rb +5 -38
  101. data/lib/riffer/tools/toolable.rb +5 -16
  102. data/lib/riffer/tools.rb +0 -4
  103. data/lib/riffer/version.rb +1 -1
  104. data/lib/riffer.rb +7 -8
  105. data/sig/generated/riffer/agent/config.rbs +29 -46
  106. data/sig/generated/riffer/agent/context.rbs +40 -48
  107. data/sig/generated/riffer/agent/response.rbs +4 -20
  108. data/sig/generated/riffer/agent/run.rbs +12 -61
  109. data/sig/generated/riffer/agent/serializer.rbs +21 -80
  110. data/sig/generated/riffer/agent/session/repair.rbs +12 -40
  111. data/sig/generated/riffer/agent/session.rbs +25 -67
  112. data/sig/generated/riffer/agent/structured_output/result.rbs +2 -10
  113. data/sig/generated/riffer/agent/structured_output.rbs +5 -12
  114. data/sig/generated/riffer/agent.rbs +57 -186
  115. data/sig/generated/riffer/config.rbs +34 -100
  116. data/sig/generated/riffer/evals/evaluator.rbs +7 -27
  117. data/sig/generated/riffer/evals/evaluator_runner.rbs +9 -19
  118. data/sig/generated/riffer/evals/judge.rbs +4 -24
  119. data/sig/generated/riffer/evals/result.rbs +1 -17
  120. data/sig/generated/riffer/evals/run_result.rbs +0 -10
  121. data/sig/generated/riffer/evals/scenario_result.rbs +0 -13
  122. data/sig/generated/riffer/evals.rbs +0 -6
  123. data/sig/generated/riffer/guardrail.rbs +4 -27
  124. data/sig/generated/riffer/guardrails/modification.rbs +0 -10
  125. data/sig/generated/riffer/guardrails/result.rbs +3 -30
  126. data/sig/generated/riffer/guardrails/runner.rbs +5 -22
  127. data/sig/generated/riffer/guardrails/tripwire.rbs +1 -19
  128. data/sig/generated/riffer/guardrails.rbs +2 -4
  129. data/sig/generated/riffer/helpers/call_or_value.rbs +4 -3
  130. data/sig/generated/riffer/helpers/class_name_converter.rbs +1 -1
  131. data/sig/generated/riffer/helpers/dependencies.rbs +3 -7
  132. data/sig/generated/riffer/helpers.rbs +0 -5
  133. data/sig/generated/riffer/mcp/authenticated_tool.rbs +5 -4
  134. data/sig/generated/riffer/mcp/client.rbs +10 -16
  135. data/sig/generated/riffer/mcp/manifest.rbs +9 -9
  136. data/sig/generated/riffer/mcp/registration.rbs +2 -10
  137. data/sig/generated/riffer/mcp/registry.rbs +11 -18
  138. data/sig/generated/riffer/mcp/search_tool.rbs +26 -0
  139. data/sig/generated/riffer/mcp/tool_factory.rbs +10 -15
  140. data/sig/generated/riffer/mcp.rbs +10 -17
  141. data/sig/generated/riffer/messages/assistant.rbs +2 -8
  142. data/sig/generated/riffer/messages/base.rbs +11 -16
  143. data/sig/generated/riffer/messages/file_part.rbs +13 -23
  144. data/sig/generated/riffer/messages/system.rbs +0 -4
  145. data/sig/generated/riffer/messages/tool.rbs +0 -9
  146. data/sig/generated/riffer/messages/user.rbs +0 -9
  147. data/sig/generated/riffer/messages.rbs +0 -7
  148. data/sig/generated/riffer/params/boolean.rbs +2 -4
  149. data/sig/generated/riffer/params/param.rbs +21 -39
  150. data/sig/generated/riffer/params.rbs +9 -21
  151. data/sig/generated/riffer/providers/amazon_bedrock.rbs +21 -25
  152. data/sig/generated/riffer/providers/anthropic.rbs +2 -7
  153. data/sig/generated/riffer/providers/azure_open_ai.rbs +3 -18
  154. data/sig/generated/riffer/providers/base.rbs +9 -25
  155. data/sig/generated/riffer/providers/gemini.rbs +0 -2
  156. data/sig/generated/riffer/providers/mock.rbs +6 -26
  157. data/sig/generated/riffer/providers/open_ai.rbs +1 -5
  158. data/sig/generated/riffer/providers/open_router.rbs +4 -10
  159. data/sig/generated/riffer/providers/repository.rbs +2 -3
  160. data/sig/generated/riffer/providers/token_usage.rbs +6 -16
  161. data/sig/generated/riffer/providers.rbs +0 -8
  162. data/sig/generated/riffer/runner/fibers.rbs +8 -15
  163. data/sig/generated/riffer/runner/sequential.rbs +1 -3
  164. data/sig/generated/riffer/runner/threaded.rbs +3 -13
  165. data/sig/generated/riffer/runner.rbs +2 -14
  166. data/sig/generated/riffer/skills/activate_tool.rbs +2 -11
  167. data/sig/generated/riffer/skills/adapter.rbs +4 -22
  168. data/sig/generated/riffer/skills/backend.rbs +7 -21
  169. data/sig/generated/riffer/skills/config.rbs +10 -31
  170. data/sig/generated/riffer/skills/context.rbs +5 -20
  171. data/sig/generated/riffer/skills/filesystem_backend.rbs +7 -24
  172. data/sig/generated/riffer/skills/frontmatter.rbs +10 -27
  173. data/sig/generated/riffer/skills/markdown_adapter.rbs +2 -9
  174. data/sig/generated/riffer/skills/xml_adapter.rbs +2 -8
  175. data/sig/generated/riffer/stream_events/base.rbs +1 -6
  176. data/sig/generated/riffer/stream_events/guardrail_modification.rbs +1 -8
  177. data/sig/generated/riffer/stream_events/guardrail_tripwire.rbs +1 -8
  178. data/sig/generated/riffer/stream_events/interrupt.rbs +4 -7
  179. data/sig/generated/riffer/stream_events/reasoning_delta.rbs +2 -4
  180. data/sig/generated/riffer/stream_events/reasoning_done.rbs +2 -4
  181. data/sig/generated/riffer/stream_events/skill_activation.rbs +2 -4
  182. data/sig/generated/riffer/stream_events/text_delta.rbs +0 -2
  183. data/sig/generated/riffer/stream_events/text_done.rbs +1 -3
  184. data/sig/generated/riffer/stream_events/token_usage_done.rbs +1 -7
  185. data/sig/generated/riffer/stream_events/tool_call_delta.rbs +2 -3
  186. data/sig/generated/riffer/stream_events/tool_call_done.rbs +1 -3
  187. data/sig/generated/riffer/stream_events/web_search_done.rbs +1 -3
  188. data/sig/generated/riffer/stream_events/web_search_status.rbs +2 -3
  189. data/sig/generated/riffer/stream_events.rbs +0 -10
  190. data/sig/generated/riffer/tool.rbs +5 -12
  191. data/sig/generated/riffer/tools/response.rbs +6 -4
  192. data/sig/generated/riffer/tools/runtime/fibers.rbs +0 -3
  193. data/sig/generated/riffer/tools/runtime/inline.rbs +1 -3
  194. data/sig/generated/riffer/tools/runtime/threaded.rbs +0 -2
  195. data/sig/generated/riffer/tools/runtime.rbs +5 -37
  196. data/sig/generated/riffer/tools/toolable.rbs +4 -14
  197. data/sig/generated/riffer/tools.rbs +0 -4
  198. data/sig/generated/riffer.rbs +5 -4
  199. data/sig/manual/riffer/agent/session/repair.rbs +5 -0
  200. data/sig/manual/riffer/evals/evaluator_runner.rbs +5 -0
  201. data/sig/manual/riffer/helpers/class_name_converter.rbs +5 -0
  202. data/sig/manual/riffer/helpers/dependencies.rbs +5 -0
  203. data/sig/manual/riffer/mcp/authenticated_tool.rbs +5 -0
  204. data/sig/manual/riffer/mcp/registry.rbs +5 -0
  205. data/sig/manual/riffer/mcp/tool_factory.rbs +5 -0
  206. data/sig/manual/riffer/mcp.rbs +5 -0
  207. data/sig/manual/riffer/providers/repository.rbs +5 -0
  208. data/sig/manual/riffer.rbs +5 -0
  209. metadata +17 -9
  210. data/.agents/rdoc.md +0 -69
  211. data/lib/riffer/messages/converter.rb +0 -90
  212. data/sig/generated/riffer/messages/converter.rbs +0 -33
  213. data/sig/manual/riffer/tools/toolable.rbs +0 -6
@@ -1,15 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Skills context for an agent generation cycle.
5
- #
6
- # Coordinates skill discovery, activation, and prompt rendering.
7
- # Tracks activations with caching to avoid redundant backend reads.
8
- #
9
- # Built by the agent during +Agent.new+ and exposed to tools via
10
- # <tt>context.skills</tt> on the agent's +Riffer::Agent::Context+.
11
- #
12
- # See Riffer::Skills::Backend, Riffer::Skills::Frontmatter.
4
+ # Skills context for an agent generation cycle — coordinates discovery,
5
+ # activation, and prompt rendering, caching activations to avoid redundant
6
+ # backend reads. Exposed to tools via <tt>context.skills</tt>.
13
7
  class Riffer::Skills::Context
14
8
  # @rbs @backend: Riffer::Skills::Backend
15
9
  # @rbs @activated: Hash[String, String]
@@ -23,13 +17,6 @@ class Riffer::Skills::Context
23
17
  # Optional callback invoked when a skill is first activated.
24
18
  attr_writer :on_activate #: (^(String) -> void)?
25
19
 
26
- # Creates a new skills context for a generation cycle.
27
- #
28
- # [backend] the skills backend for reading skill bodies.
29
- # [skills] skill catalog indexed by name.
30
- # [adapter] the adapter used to render skill content. The adapter
31
- # carries the activation tool class via its initializer.
32
- #
33
20
  #--
34
21
  #: (backend: Riffer::Skills::Backend, skills: Hash[String, Riffer::Skills::Frontmatter], adapter: Riffer::Skills::Adapter) -> void
35
22
  def initialize(backend:, skills:, adapter:)
@@ -61,10 +48,8 @@ class Riffer::Skills::Context
61
48
  @activated.key?(name)
62
49
  end
63
50
 
64
- # Returns the complete skills section for the system prompt.
65
- #
66
- # Includes the catalog and any pre-activated skill bodies.
67
- #
51
+ # Returns the complete skills section for the system prompt — the catalog plus
52
+ # any pre-activated skill bodies.
68
53
  #--
69
54
  #: () -> String
70
55
  def system_prompt
@@ -1,23 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Built-in backend that reads skills from the filesystem.
5
- #
6
- # Scans configured directories for immediate child directories containing
7
- # +SKILL.md+ files. Directory names must match the skill +name+ field.
8
- #
9
- # backend = Riffer::Skills::FilesystemBackend.new(".skills", "~/.riffer/skills")
10
- # backend.list_skills # => [Riffer::Skills::Frontmatter, ...]
11
- # backend.read_skill("code-review") # => "Full skill instructions..."
12
- #
4
+ # Built-in backend that reads skills from the filesystem. Scans configured
5
+ # directories for immediate child directories containing +SKILL.md+; directory
6
+ # names must match the skill +name+.
13
7
  class Riffer::Skills::FilesystemBackend < Riffer::Skills::Backend
14
8
  # @rbs @paths: Array[String]
15
9
  # @rbs @skills_cache: Hash[String, String]?
16
10
 
17
- # Creates a new FilesystemBackend.
18
- #
19
- # [paths] one or more directory paths to scan for skills.
20
- #
21
11
  #--
22
12
  #: (*String) -> void
23
13
  def initialize(*paths)
@@ -25,12 +15,8 @@ class Riffer::Skills::FilesystemBackend < Riffer::Skills::Backend
25
15
  @skills_cache = nil #: Hash[String, String]?
26
16
  end
27
17
 
28
- # Returns frontmatter for all discovered skills.
29
- #
30
- # Scans each configured path for immediate child directories containing
31
- # SKILL.md. When multiple paths contain a skill with the same name,
32
- # first-path-wins.
33
- #
18
+ # Returns frontmatter for all discovered skills; on a name collision across
19
+ # paths, first-path-wins.
34
20
  #--
35
21
  #: () -> Array[Riffer::Skills::Frontmatter]
36
22
  def list_skills
@@ -59,12 +45,8 @@ class Riffer::Skills::FilesystemBackend < Riffer::Skills::Backend
59
45
  frontmatters
60
46
  end
61
47
 
62
- # Returns the full SKILL.md body (without frontmatter) for a skill.
63
- #
64
- # [name] the skill name to read.
65
- #
66
- # Raises Riffer::ArgumentError if skill not found.
67
- #
48
+ # Returns the full SKILL.md body (without frontmatter) for a skill. Raises
49
+ # Riffer::ArgumentError if the skill is not found.
68
50
  #--
69
51
  #: (String) -> String
70
52
  def read_skill(name)
@@ -3,13 +3,9 @@
3
3
 
4
4
  require "yaml"
5
5
 
6
- # Immutable value object holding parsed SKILL.md YAML frontmatter.
7
- #
8
- # Required fields per the Agent Skills spec: +name+ and +description+.
9
- # All unrecognized top-level frontmatter keys are merged into +metadata+.
10
- #
11
- # frontmatter, body = Riffer::Skills::Frontmatter.parse(raw_content)
12
- #
6
+ # Immutable value object holding parsed SKILL.md YAML frontmatter. Required
7
+ # fields: +name+ and +description+; unrecognized top-level keys are merged into
8
+ # +metadata+.
13
9
  class Riffer::Skills::Frontmatter
14
10
  NAME_PATTERN = /\A[a-z0-9]+(-[a-z0-9]+)*\z/ #: Regexp
15
11
  MAX_NAME_LENGTH = 64 #: Integer
@@ -21,18 +17,13 @@ class Riffer::Skills::Frontmatter
21
17
  # The skill description (1-1024 chars).
22
18
  attr_reader :description #: String
23
19
 
24
- # Arbitrary key-value metadata from the spec's +metadata+ field
25
- # and any unrecognized top-level frontmatter keys.
20
+ # Metadata from the spec's +metadata+ field plus any unrecognized top-level
21
+ # keys.
26
22
  attr_reader :metadata #: Hash[Symbol, untyped]
27
23
 
28
- # Parses a raw SKILL.md string into a Frontmatter and body.
29
- #
30
- # Splits on YAML front matter delimiters (+---+). Unrecognized
31
- # top-level keys become +metadata+. Available to custom backends
32
- # so they don't need to reimplement parsing.
33
- #
34
- # Raises Riffer::ArgumentError if frontmatter is invalid.
35
- #
24
+ # Parses a raw SKILL.md string into a +[Frontmatter, body]+ pair — public so
25
+ # custom backends needn't reimplement parsing. Raises Riffer::ArgumentError
26
+ # if the frontmatter is invalid.
36
27
  #--
37
28
  #: (String) -> [Riffer::Skills::Frontmatter, String]
38
29
  def self.parse(raw)
@@ -42,9 +33,7 @@ class Riffer::Skills::Frontmatter
42
33
  end
43
34
 
44
35
  # Parses only the frontmatter from a raw SKILL.md string, ignoring the body.
45
- #
46
- # Raises Riffer::ArgumentError if frontmatter is invalid.
47
- #
36
+ # Raises Riffer::ArgumentError if the frontmatter is invalid.
48
37
  #--
49
38
  #: (String) -> Riffer::Skills::Frontmatter
50
39
  def self.parse_frontmatter(raw)
@@ -68,14 +57,7 @@ class Riffer::Skills::Frontmatter
68
57
  end
69
58
  private_class_method :split_frontmatter
70
59
 
71
- # Creates a new Frontmatter.
72
- #
73
- # [name] the skill name (must match +[a-z0-9]([a-z0-9-]*[a-z0-9])?+, 1-64 chars).
74
- # [description] the skill description (1-1024 chars).
75
- # [metadata] optional metadata hash.
76
- #
77
- # Raises Riffer::ArgumentError if name or description is invalid.
78
- #
60
+ # Raises Riffer::ArgumentError if +name+ or +description+ is invalid.
79
61
  #--
80
62
  #: (name: String, description: String, ?metadata: Hash[Symbol, untyped]) -> void
81
63
  def initialize(name:, description:, metadata: {})
@@ -1,17 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Default Markdown skill adapter.
5
- #
6
- # Renders a skill catalog as Markdown for the system prompt.
7
- # Used by OpenAI, Amazon Bedrock, and other providers.
8
- #
9
- # See Riffer::Skills::XmlAdapter for the Anthropic/Claude variant.
4
+ # Default skill adapter — renders a skill catalog as Markdown for the system
5
+ # prompt.
10
6
  class Riffer::Skills::MarkdownAdapter < Riffer::Skills::Adapter
11
7
  # Renders a skill catalog as Markdown.
12
- #
13
- # [skills] array of Frontmatter objects to render.
14
- #
15
8
  #--
16
9
  #: (Array[Riffer::Skills::Frontmatter]) -> String
17
10
  def render_catalog(skills)
@@ -3,16 +3,10 @@
3
3
 
4
4
  require "cgi"
5
5
 
6
- # XML skill adapter, optimized for Anthropic/Claude.
7
- #
8
- # Renders a skill catalog as XML for the system prompt.
9
- #
10
- # See Riffer::Skills::MarkdownAdapter for the default variant.
6
+ # Renders a skill catalog as XML for the system prompt, optimized for
7
+ # Anthropic/Claude.
11
8
  class Riffer::Skills::XmlAdapter < Riffer::Skills::Adapter
12
9
  # Renders a skill catalog as XML.
13
- #
14
- # [skills] array of Frontmatter objects to render.
15
- #
16
10
  #--
17
11
  #: (Array[Riffer::Skills::Frontmatter]) -> String
18
12
  def render_catalog(skills)
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Base class for all streaming events in the Riffer framework.
5
- #
6
- # Subclasses must implement the +to_h+ method.
4
+ # Base class for all streaming events. Subclasses must implement +to_h+.
7
5
  class Riffer::StreamEvents::Base
8
6
  # The message role (typically :assistant).
9
7
  attr_reader :role #: Symbol
@@ -15,9 +13,6 @@ class Riffer::StreamEvents::Base
15
13
  end
16
14
 
17
15
  # Converts the event to a hash.
18
- #
19
- # Raises NotImplementedError if not implemented by subclass.
20
- #
21
16
  #--
22
17
  #: () -> Hash[Symbol, untyped]
23
18
  def to_h
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents a guardrail modification event during streaming.
5
- #
6
- # Emitted when a guardrail transforms data during the streaming pipeline.
4
+ # Emitted when a guardrail transforms data during streaming.
7
5
  class Riffer::StreamEvents::GuardrailModification < Riffer::StreamEvents::Base
8
6
  # The modification record.
9
7
  attr_reader :modification #: Riffer::Guardrails::Modification
10
8
 
11
- # Creates a new guardrail modification stream event.
12
- #
13
- # [modification] the modification details.
14
- # [role] the message role (defaults to :assistant).
15
- #
16
9
  #--
17
10
  #: (Riffer::Guardrails::Modification, ?role: Symbol) -> void
18
11
  def initialize(modification, role: :assistant)
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents a guardrail tripwire event during streaming.
5
- #
6
- # Emitted when a guardrail blocks execution during the streaming pipeline.
4
+ # Emitted when a guardrail blocks execution during streaming.
7
5
  class Riffer::StreamEvents::GuardrailTripwire < Riffer::StreamEvents::Base
8
6
  # The tripwire containing block details.
9
7
  attr_reader :tripwire #: Riffer::Guardrails::Tripwire
10
8
 
11
- # Creates a new tripwire stream event.
12
- #
13
- # [tripwire] the tripwire details.
14
- # [role] the message role (defaults to :assistant).
15
- #
16
9
  #--
17
10
  #: (Riffer::Guardrails::Tripwire, ?role: Symbol) -> void
18
11
  def initialize(tripwire, role: :assistant)
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents an interrupt event during streaming.
5
- #
6
- # Emitted when a callback interrupts the agent loop via +throw :riffer_interrupt+.
4
+ # Represents an interrupt during streaming, fired when a callback throws
5
+ # +:riffer_interrupt+.
7
6
  class Riffer::StreamEvents::Interrupt < Riffer::StreamEvents::Base
8
7
  # The reason provided with the interrupt, if any.
9
8
  attr_reader :reason #: (String | Symbol)?
10
9
 
11
- # Call ids of tool_use blocks that riffer filled with placeholder
12
- # results when the interrupt fired. Populated only when
13
- # +Riffer.config.experimental_history_healing+ is on.
10
+ # Call ids of tool_use blocks riffer filled with placeholder results when the
11
+ # interrupt fired (only when history healing is on).
14
12
  attr_reader :healed_tool_call_ids #: Array[String]
15
13
 
16
14
  #--
@@ -22,7 +20,6 @@ class Riffer::StreamEvents::Interrupt < Riffer::StreamEvents::Base
22
20
  end
23
21
 
24
22
  # Converts the event to a hash.
25
- #
26
23
  #--
27
24
  #: () -> Hash[Symbol, untyped]
28
25
  def to_h
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents an incremental reasoning chunk during streaming.
5
- #
6
- # Emitted when the LLM produces reasoning/thinking content incrementally.
7
- # Only available with providers that support reasoning (e.g., OpenAI with reasoning option).
4
+ # Represents an incremental reasoning chunk during streaming; only emitted by
5
+ # providers that support reasoning (e.g. OpenAI with the reasoning option).
8
6
  class Riffer::StreamEvents::ReasoningDelta < Riffer::StreamEvents::Base
9
7
  # The incremental reasoning content.
10
8
  attr_reader :content #: String
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents completion of reasoning during streaming.
5
- #
6
- # Emitted when the LLM has finished producing reasoning/thinking content.
7
- # Only available with providers that support reasoning (e.g., OpenAI with reasoning option).
4
+ # Represents completed reasoning during streaming; only emitted by providers
5
+ # that support reasoning (e.g. OpenAI with the reasoning option).
8
6
  class Riffer::StreamEvents::ReasoningDone < Riffer::StreamEvents::Base
9
7
  # The complete reasoning content.
10
8
  attr_reader :content #: String
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Emitted when a skill is activated during streaming.
5
- #
6
- # Fired by the +on_activate+ callback on Riffer::Skills::Context
7
- # when the LLM calls the skill activation tool.
4
+ # Emitted when a skill is activated during streaming, via the +on_activate+
5
+ # callback when the LLM calls the activation tool.
8
6
  class Riffer::StreamEvents::SkillActivation < Riffer::StreamEvents::Base
9
7
  # The activated skill name.
10
8
  attr_reader :name #: String
@@ -2,8 +2,6 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  # Represents an incremental text chunk during streaming.
5
- #
6
- # Emitted when the LLM produces text content incrementally.
7
5
  class Riffer::StreamEvents::TextDelta < Riffer::StreamEvents::Base
8
6
  # The incremental text content.
9
7
  attr_reader :content #: String
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents completion of text generation during streaming.
5
- #
6
- # Emitted when the LLM has finished producing text content.
4
+ # Represents completed text generation during streaming.
7
5
  class Riffer::StreamEvents::TextDone < Riffer::StreamEvents::Base
8
6
  # The complete text content.
9
7
  attr_reader :content #: String
@@ -1,14 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents completion of token usage tracking during streaming.
5
- #
6
- # Emitted when the LLM has finished and token usage data is available.
7
- #
8
- # event.token_usage.input_tokens # => 100
9
- # event.token_usage.output_tokens # => 50
10
- # event.token_usage.total_tokens # => 150
11
- #
4
+ # Final token usage for the response, emitted when the LLM finishes.
12
5
  class Riffer::StreamEvents::TokenUsageDone < Riffer::StreamEvents::Base
13
6
  # The token usage data for this response.
14
7
  attr_reader :token_usage #: Riffer::Providers::TokenUsage
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Riffer::StreamEvents::ToolCallDelta represents an incremental tool call chunk during streaming.
5
- #
6
- # Emitted when the LLM is building a tool call, containing partial argument data.
4
+ # Represents an incremental tool call chunk (partial argument data) during
5
+ # streaming.
7
6
  class Riffer::StreamEvents::ToolCallDelta < Riffer::StreamEvents::Base
8
7
  # The tool call item identifier.
9
8
  attr_reader :item_id #: String
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Riffer::StreamEvents::ToolCallDone represents a completed tool call during streaming.
5
- #
6
- # Emitted when the LLM has finished building a tool call with complete arguments.
4
+ # Represents a completed tool call during streaming.
7
5
  class Riffer::StreamEvents::ToolCallDone < Riffer::StreamEvents::Base
8
6
  # The tool call item identifier.
9
7
  attr_reader :item_id #: String
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents the result of a web search during streaming.
5
- #
6
- # Emitted when the LLM has finished a server-side web search.
4
+ # The result of a completed server-side web search during streaming.
7
5
  class Riffer::StreamEvents::WebSearchDone < Riffer::StreamEvents::Base
8
6
  # The search query used.
9
7
  attr_reader :query #: String
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Represents a web search status notification during streaming.
5
- #
6
- # Emitted when the LLM performs a server-side web search and its status changes.
4
+ # A web search status notification, emitted as a server-side web search
5
+ # progresses.
7
6
  class Riffer::StreamEvents::WebSearchStatus < Riffer::StreamEvents::Base
8
7
  # The web search status ("in_progress", "searching", "completed", "open_page").
9
8
  attr_reader :status #: String
@@ -1,15 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Namespace for streaming event types in the Riffer framework.
5
- #
6
- # When streaming responses, these events are yielded to represent incremental updates:
7
- # - Riffer::StreamEvents::TextDelta - Incremental text content
8
- # - Riffer::StreamEvents::TextDone - Complete text content
9
- # - Riffer::StreamEvents::ToolCallDelta - Incremental tool call arguments
10
- # - Riffer::StreamEvents::ToolCallDone - Complete tool call
11
- # - Riffer::StreamEvents::ReasoningDelta - Incremental reasoning content
12
- # - Riffer::StreamEvents::ReasoningDone - Complete reasoning content
13
- # - Riffer::StreamEvents::SkillActivation - Skill activated during streaming
14
4
  module Riffer::StreamEvents
15
5
  end
data/lib/riffer/tool.rb CHANGED
@@ -3,12 +3,8 @@
3
3
 
4
4
  require "timeout"
5
5
 
6
- # Riffer::Tool is the base class for all tools in the Riffer framework.
7
- #
8
- # Provides a DSL for defining tool description and parameters.
9
- # Subclasses must implement the +call+ method.
10
- #
11
- # See Riffer::Agent.
6
+ # Base class for all tools in the Riffer framework. Subclasses must implement
7
+ # the +call+ method.
12
8
  #
13
9
  # class WeatherLookupTool < Riffer::Tool
14
10
  # description "Provides current weather information for a specified city."
@@ -29,16 +25,13 @@ class Riffer::Tool
29
25
  kind :tool
30
26
 
31
27
  # Executes the tool with the given arguments.
32
- #
33
- # Raises NotImplementedError if not implemented by subclass.
34
- #
35
28
  #--
36
29
  #: (context: Riffer::Agent::Context?, **untyped) -> Riffer::Tools::Response
37
30
  def call(context:, **kwargs)
38
31
  raise NotImplementedError, "#{self.class} must implement #call"
39
32
  end
40
33
 
41
- # Creates a text response. Shorthand for Riffer::Tools::Response.text.
34
+ # Creates a text response.
42
35
  #
43
36
  #--
44
37
  #: (untyped) -> Riffer::Tools::Response
@@ -46,7 +39,7 @@ class Riffer::Tool
46
39
  Riffer::Tools::Response.text(result)
47
40
  end
48
41
 
49
- # Creates a JSON response. Shorthand for Riffer::Tools::Response.json.
42
+ # Creates a JSON response.
50
43
  #
51
44
  #--
52
45
  #: (untyped) -> Riffer::Tools::Response
@@ -54,7 +47,7 @@ class Riffer::Tool
54
47
  Riffer::Tools::Response.json(result)
55
48
  end
56
49
 
57
- # Creates an error response. Shorthand for Riffer::Tools::Response.error.
50
+ # Creates an error response.
58
51
  #
59
52
  #--
60
53
  #: (String, ?type: Symbol) -> Riffer::Tools::Response
@@ -75,7 +68,7 @@ class Riffer::Tool
75
68
  validated_args = params_builder ? params_builder.validate(kwargs) : kwargs
76
69
 
77
70
  result = Timeout.timeout(self.class.timeout) do
78
- call(context: context, **validated_args)
71
+ call(context: context, **validated_args) #: untyped
79
72
  end
80
73
 
81
74
  unless result.is_a?(Riffer::Tools::Response)
@@ -3,10 +3,7 @@
3
3
 
4
4
  require "json"
5
5
 
6
- # Riffer::Tools::Response represents the result of a tool execution.
7
- #
8
- # All tools must return a Response object from their +call+ method.
9
- # Use +Response.success+ for successful results and +Response.error+ for failures.
6
+ # Represents the result of a tool execution; every tool's +call+ must return one.
10
7
  #
11
8
  # class MyTool < Riffer::Tool
12
9
  # def call(context:, **kwargs)
@@ -22,8 +19,13 @@ class Riffer::Tools::Response
22
19
 
23
20
  VALID_FORMATS = %i[text json].freeze #: Array[Symbol]
24
21
 
22
+ # The response content.
25
23
  attr_reader :content #: String
24
+
25
+ # The error message, or +nil+ on success.
26
26
  attr_reader :error_message #: String?
27
+
28
+ # The error type, or +nil+ on success.
27
29
  attr_reader :error_type #: Symbol?
28
30
 
29
31
  # Creates a success response.
@@ -65,10 +67,12 @@ class Riffer::Tools::Response
65
67
  new(content: message, success: false, error_message: message, error_type: type)
66
68
  end
67
69
 
70
+ # Returns true if the tool execution succeeded.
68
71
  #--
69
72
  #: () -> bool
70
73
  def success? = @success
71
74
 
75
+ # Returns true if the tool execution failed.
72
76
  #--
73
77
  #: () -> bool
74
78
  def error? = !@success
@@ -8,9 +8,6 @@
8
8
  # end
9
9
  #
10
10
  class Riffer::Tools::Runtime::Fibers < Riffer::Tools::Runtime
11
- # [max_concurrency] maximum number of tool calls to execute simultaneously.
12
- # When +nil+, all tool calls run as fibers without limit.
13
- #
14
11
  #--
15
12
  #: (?max_concurrency: Integer?) -> void
16
13
  def initialize(max_concurrency: nil)
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  # rbs_inline: enabled
3
3
 
4
- # Executes tool calls sequentially in the current thread.
5
- #
6
- # This is the default tool runtime used when no runtime is configured.
7
- #
4
+ # Executes tool calls sequentially in the current thread — the default runtime.
8
5
  class Riffer::Tools::Runtime::Inline < Riffer::Tools::Runtime
9
6
  #--
10
7
  #: () -> void
@@ -10,8 +10,6 @@
10
10
  class Riffer::Tools::Runtime::Threaded < Riffer::Tools::Runtime
11
11
  DEFAULT_MAX_CONCURRENCY = 5 #: Integer
12
12
 
13
- # [max_concurrency] maximum number of tool calls to execute simultaneously.
14
- #
15
13
  #--
16
14
  #: (?max_concurrency: Integer) -> void
17
15
  def initialize(max_concurrency: DEFAULT_MAX_CONCURRENCY)
@@ -3,25 +3,12 @@
3
3
 
4
4
  require "json"
5
5
 
6
- # Riffer::Tools::Runtime handles tool call execution for an agent.
7
- #
8
- # Composes with a Riffer::Runner for concurrency control and provides
9
- # +execute+ as the sole public entry point.
10
- #
11
- # Subclass and override +dispatch_tool_call+ to customize how individual
12
- # tool calls are dispatched (e.g., HTTP, gRPC).
13
- #
14
- # runtime = Riffer::Tools::Runtime::Inline.new
15
- # results = runtime.execute(tool_calls, tools: tools, context: context)
16
- #
6
+ # Handles tool call execution for an agent, composing with a Riffer::Runner for
7
+ # concurrency. Subclass and override +dispatch_tool_call+ to customize dispatch
8
+ # (e.g. HTTP, gRPC).
17
9
  class Riffer::Tools::Runtime
18
10
  # @rbs @runner: Riffer::Runner
19
11
 
20
- # [runner] the concurrency runner to use for batch execution.
21
- #
22
- # Subclasses must provide a runner; instantiating Riffer::Tools::Runtime directly
23
- # raises +NotImplementedError+.
24
- #
25
12
  #--
26
13
  #: (runner: Riffer::Runner) -> void
27
14
  def initialize(runner:)
@@ -30,15 +17,6 @@ class Riffer::Tools::Runtime
30
17
  end
31
18
 
32
19
  # Executes a batch of tool calls, returning <tt>[tool_call, response]</tt> pairs.
33
- #
34
- # [tool_calls] the tool calls to execute.
35
- # [tools] the resolved tool classes.
36
- # [context] the context hash.
37
- # [assistant_message] the assistant message that produced these tool
38
- # calls, when known. Forwarded to +around_tool_call+ and
39
- # +dispatch_tool_call+ so subclasses can access it (e.g. for
40
- # instrumentation that needs the accompanying assistant text).
41
- #
42
20
  #--
43
21
  #: (Array[Riffer::Messages::Assistant::ToolCall], tools: Array[singleton(Riffer::Tool)], context: Riffer::Agent::Context?, ?assistant_message: Riffer::Messages::Assistant?) -> Array[[Riffer::Messages::Assistant::ToolCall, Riffer::Tools::Response]]
44
22
  def execute(tool_calls, tools:, context:, assistant_message: nil)
@@ -50,10 +28,8 @@ class Riffer::Tools::Runtime
50
28
  end
51
29
  end
52
30
 
53
- # Hook that wraps each tool call execution. Override in subclasses
54
- # to customize. Must +yield+ to continue execution.
55
- #
56
- # The default implementation simply yields.
31
+ # Hook wrapping each tool call; override in subclasses to instrument or
32
+ # customize. Must +yield+ to continue.
57
33
  #
58
34
  # class InstrumentedRuntime < Riffer::Tools::Runtime::Inline
59
35
  # private
@@ -74,15 +50,6 @@ class Riffer::Tools::Runtime
74
50
 
75
51
  private
76
52
 
77
- # Dispatches a single tool call. Override in subclasses to change
78
- # how individual tools are invoked (e.g., HTTP, gRPC).
79
- #
80
- # [tool_call] the tool call to execute.
81
- # [tools] the resolved tool classes.
82
- # [context] the context hash.
83
- # [assistant_message] the assistant message that produced this tool
84
- # call, when known.
85
- #
86
53
  #--
87
54
  #: (Riffer::Messages::Assistant::ToolCall, tools: Array[singleton(Riffer::Tool)], context: Riffer::Agent::Context?, ?assistant_message: Riffer::Messages::Assistant?) -> Riffer::Tools::Response
88
55
  def dispatch_tool_call(tool_call, tools:, context:, assistant_message: nil)