riffer 0.32.1 → 0.34.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +39 -0
  5. data/README.md +13 -11
  6. data/docs/01_OVERVIEW.md +2 -0
  7. data/docs/04_AGENT_LIFECYCLE.md +15 -13
  8. data/docs/08_MESSAGES.md +39 -5
  9. data/docs/09_STREAM_EVENTS.md +14 -0
  10. data/docs/10_CONFIGURATION.md +73 -4
  11. data/docs/13_SKILLS.md +62 -4
  12. data/docs/14_MCP.md +2 -1
  13. data/docs/16_TRACING.md +274 -0
  14. data/docs/17_METRICS.md +153 -0
  15. data/docs/providers/07_CUSTOM_PROVIDERS.md +44 -0
  16. data/lib/riffer/agent/response.rb +11 -2
  17. data/lib/riffer/agent/run.rb +136 -35
  18. data/lib/riffer/agent.rb +1 -1
  19. data/lib/riffer/config.rb +230 -15
  20. data/lib/riffer/guardrail.rb +8 -0
  21. data/lib/riffer/guardrails/runner.rb +58 -0
  22. data/lib/riffer/helpers/boolean.rb +22 -0
  23. data/lib/riffer/mcp/authenticated_tool.rb +14 -20
  24. data/lib/riffer/mcp/registration.rb +4 -4
  25. data/lib/riffer/mcp/tool.rb +23 -0
  26. data/lib/riffer/mcp/tool_factory.rb +14 -22
  27. data/lib/riffer/messages/assistant.rb +15 -3
  28. data/lib/riffer/messages/base.rb +2 -1
  29. data/lib/riffer/metrics/instruments.rb +31 -0
  30. data/lib/riffer/metrics/no_op.rb +14 -0
  31. data/lib/riffer/metrics/otel.rb +80 -0
  32. data/lib/riffer/metrics.rb +94 -0
  33. data/lib/riffer/providers/amazon_bedrock.rb +57 -21
  34. data/lib/riffer/providers/anthropic.rb +59 -24
  35. data/lib/riffer/providers/azure_open_ai.rb +7 -0
  36. data/lib/riffer/providers/base.rb +247 -15
  37. data/lib/riffer/providers/finish_reason.rb +27 -0
  38. data/lib/riffer/providers/gemini.rb +59 -11
  39. data/lib/riffer/providers/mock.rb +30 -9
  40. data/lib/riffer/providers/open_ai.rb +78 -24
  41. data/lib/riffer/providers/open_router.rb +56 -16
  42. data/lib/riffer/providers/repository.rb +9 -0
  43. data/lib/riffer/providers/token_usage.rb +27 -11
  44. data/lib/riffer/skills/activate_tool.rb +11 -2
  45. data/lib/riffer/skills/adapter.rb +15 -0
  46. data/lib/riffer/skills/context.rb +63 -11
  47. data/lib/riffer/skills/markdown_adapter.rb +1 -1
  48. data/lib/riffer/skills/xml_adapter.rb +1 -1
  49. data/lib/riffer/stream_events/finish_reason_done.rb +34 -0
  50. data/lib/riffer/tools/runtime.rb +99 -3
  51. data/lib/riffer/tracing/capture.rb +92 -0
  52. data/lib/riffer/tracing/no_op.rb +61 -0
  53. data/lib/riffer/tracing/otel.rb +132 -0
  54. data/lib/riffer/tracing/stream_recorder.rb +51 -0
  55. data/lib/riffer/tracing.rb +78 -0
  56. data/lib/riffer/version.rb +1 -1
  57. data/sig/_private/opentelemetry.rbs +22 -0
  58. data/sig/generated/riffer/agent/response.rbs +9 -2
  59. data/sig/generated/riffer/agent/run.rbs +28 -8
  60. data/sig/generated/riffer/config.rbs +162 -16
  61. data/sig/generated/riffer/guardrail.rbs +6 -0
  62. data/sig/generated/riffer/guardrails/runner.rbs +22 -0
  63. data/sig/generated/riffer/helpers/boolean.rbs +11 -0
  64. data/sig/generated/riffer/mcp/authenticated_tool.rbs +6 -8
  65. data/sig/generated/riffer/mcp/registration.rbs +4 -4
  66. data/sig/generated/riffer/mcp/tool.rbs +19 -0
  67. data/sig/generated/riffer/mcp/tool_factory.rbs +8 -7
  68. data/sig/generated/riffer/messages/assistant.rbs +10 -4
  69. data/sig/generated/riffer/metrics/instruments.rbs +15 -0
  70. data/sig/generated/riffer/metrics/no_op.rbs +10 -0
  71. data/sig/generated/riffer/metrics/otel.rbs +48 -0
  72. data/sig/generated/riffer/metrics.rbs +72 -0
  73. data/sig/generated/riffer/providers/amazon_bedrock.rbs +35 -14
  74. data/sig/generated/riffer/providers/anthropic.rbs +41 -20
  75. data/sig/generated/riffer/providers/azure_open_ai.rbs +5 -0
  76. data/sig/generated/riffer/providers/base.rbs +78 -2
  77. data/sig/generated/riffer/providers/finish_reason.rbs +19 -0
  78. data/sig/generated/riffer/providers/gemini.rbs +25 -2
  79. data/sig/generated/riffer/providers/mock.rbs +16 -5
  80. data/sig/generated/riffer/providers/open_ai.rbs +44 -22
  81. data/sig/generated/riffer/providers/open_router.rbs +31 -12
  82. data/sig/generated/riffer/providers/repository.rbs +7 -0
  83. data/sig/generated/riffer/providers/token_usage.rbs +20 -10
  84. data/sig/generated/riffer/skills/activate_tool.rbs +7 -1
  85. data/sig/generated/riffer/skills/adapter.rbs +10 -0
  86. data/sig/generated/riffer/skills/context.rbs +42 -4
  87. data/sig/generated/riffer/stream_events/finish_reason_done.rbs +21 -0
  88. data/sig/generated/riffer/tools/runtime.rbs +35 -0
  89. data/sig/generated/riffer/tracing/capture.rbs +46 -0
  90. data/sig/generated/riffer/tracing/no_op.rbs +46 -0
  91. data/sig/generated/riffer/tracing/otel.rbs +84 -0
  92. data/sig/generated/riffer/tracing/stream_recorder.rbs +31 -0
  93. data/sig/generated/riffer/tracing.rbs +52 -0
  94. data/sig/manual/riffer/helpers/boolean.rbs +5 -0
  95. data/sig/manual/riffer/metrics/no_op.rbs +5 -0
  96. data/sig/manual/riffer/metrics.rbs +5 -0
  97. data/sig/manual/riffer/providers.rbs +9 -0
  98. data/sig/manual/riffer/tracing/capture.rbs +5 -0
  99. data/sig/manual/riffer/tracing/no_op.rbs +5 -0
  100. data/sig/manual/riffer/tracing.rbs +5 -0
  101. metadata +42 -6
@@ -4,6 +4,11 @@
4
4
  class Riffer::Providers::OpenAI < Riffer::Providers::Base
5
5
  WEB_SEARCH_TOOL_TYPE: String
6
6
 
7
+ # The GenAI semconv well-known provider name.
8
+ # --
9
+ # : () -> String
10
+ def self.semconv_provider_name: () -> String
11
+
7
12
  # --
8
13
  # : (**untyped) -> void
9
14
  def initialize: (**untyped) -> void
@@ -22,6 +27,23 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
22
27
  # : (untyped) -> Riffer::Providers::TokenUsage?
23
28
  def extract_token_usage: (untyped) -> Riffer::Providers::TokenUsage?
24
29
 
30
+ # --
31
+ # : (untyped) -> Riffer::Providers::TokenUsage
32
+ def build_token_usage: (untyped) -> Riffer::Providers::TokenUsage
33
+
34
+ # --
35
+ # : (untyped) -> Riffer::Providers::FinishReason?
36
+ def extract_finish_reason: (untyped) -> Riffer::Providers::FinishReason?
37
+
38
+ # The Responses API reports no finish_reason field, so one is derived.
39
+ # --
40
+ # : (untyped) -> Riffer::Providers::FinishReason?
41
+ def build_finish_reason: (untyped) -> Riffer::Providers::FinishReason?
42
+
43
+ # --
44
+ # : (untyped) -> Riffer::Providers::FinishReason
45
+ def incomplete_finish_reason: (untyped) -> Riffer::Providers::FinishReason
46
+
25
47
  # --
26
48
  # : (untyped) -> String
27
49
  def extract_content: (untyped) -> String
@@ -31,48 +53,48 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
31
53
  def extract_tool_calls: (untyped) -> Array[Riffer::Messages::Assistant::ToolCall]
32
54
 
33
55
  # --
34
- # : (Hash[Symbol, untyped], Enumerator::Yielder) -> void
35
- def execute_stream: (Hash[Symbol, untyped], Enumerator::Yielder) -> void
56
+ # : (Hash[Symbol, untyped], Riffer::Providers::_EventSink) -> void
57
+ def execute_stream: (Hash[Symbol, untyped], Riffer::Providers::_EventSink) -> void
36
58
 
37
59
  # --
38
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
39
- def handle_output_item_added_function_call: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
60
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
61
+ def handle_output_item_added_function_call: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
40
62
 
41
63
  # --
42
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
43
- def handle_output_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
64
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
65
+ def handle_output_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
44
66
 
45
67
  # --
46
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
47
- def handle_output_text_done: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
68
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
69
+ def handle_output_text_done: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
48
70
 
49
71
  # --
50
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
51
- def handle_reasoning_summary_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
72
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
73
+ def handle_reasoning_summary_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
52
74
 
53
75
  # --
54
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
55
- def handle_reasoning_summary_text_done: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
76
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
77
+ def handle_reasoning_summary_text_done: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
56
78
 
57
79
  # --
58
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
59
- def handle_function_call_arguments_delta: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
80
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
81
+ def handle_function_call_arguments_delta: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
60
82
 
61
83
  # --
62
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
63
- def handle_function_call_arguments_done: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
84
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
85
+ def handle_function_call_arguments_done: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
64
86
 
65
87
  # --
66
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
67
- def handle_response_completed: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
88
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
89
+ def handle_response_finished: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
68
90
 
69
91
  # --
70
- # : (untyped, status: String, yielder: Enumerator::Yielder) -> void
71
- def handle_web_search_status: (untyped, status: String, yielder: Enumerator::Yielder) -> void
92
+ # : (untyped, status: String, yielder: Riffer::Providers::_EventSink) -> void
93
+ def handle_web_search_status: (untyped, status: String, yielder: Riffer::Providers::_EventSink) -> void
72
94
 
73
95
  # --
74
- # : (untyped, yielder: Enumerator::Yielder) -> void
75
- def handle_output_item_done_web_search: (untyped, yielder: Enumerator::Yielder) -> void
96
+ # : (untyped, yielder: Riffer::Providers::_EventSink) -> void
97
+ def handle_output_item_done_web_search: (untyped, yielder: Riffer::Providers::_EventSink) -> void
76
98
 
77
99
  # --
78
100
  # : (Array[Riffer::Messages::Base]) -> Array[Hash[Symbol, untyped]]
@@ -7,6 +7,13 @@
7
7
  class Riffer::Providers::OpenRouter < Riffer::Providers::Base
8
8
  BASE_URL: String
9
9
 
10
+ FINISH_REASONS: Hash[String, Symbol]
11
+
12
+ # The GenAI semconv well-known provider name.
13
+ # --
14
+ # : () -> String
15
+ def self.semconv_provider_name: () -> String
16
+
10
17
  # --
11
18
  # : (?api_key: String?, **untyped) -> void
12
19
  def initialize: (?api_key: String?, **untyped) -> void
@@ -25,6 +32,18 @@ class Riffer::Providers::OpenRouter < Riffer::Providers::Base
25
32
  # : (untyped) -> Riffer::Providers::TokenUsage?
26
33
  def extract_token_usage: (untyped) -> Riffer::Providers::TokenUsage?
27
34
 
35
+ # --
36
+ # : (untyped) -> Riffer::Providers::TokenUsage
37
+ def build_token_usage: (untyped) -> Riffer::Providers::TokenUsage
38
+
39
+ # --
40
+ # : (untyped) -> Riffer::Providers::FinishReason?
41
+ def extract_finish_reason: (untyped) -> Riffer::Providers::FinishReason?
42
+
43
+ # --
44
+ # : (untyped) -> Riffer::Providers::FinishReason?
45
+ def build_finish_reason: (untyped) -> Riffer::Providers::FinishReason?
46
+
28
47
  # --
29
48
  # : (untyped) -> String
30
49
  def extract_content: (untyped) -> String
@@ -34,28 +53,28 @@ class Riffer::Providers::OpenRouter < Riffer::Providers::Base
34
53
  def extract_tool_calls: (untyped) -> Array[Riffer::Messages::Assistant::ToolCall]
35
54
 
36
55
  # --
37
- # : (Hash[Symbol, untyped], Enumerator::Yielder) -> void
38
- def execute_stream: (Hash[Symbol, untyped], Enumerator::Yielder) -> void
56
+ # : (Hash[Symbol, untyped], Riffer::Providers::_EventSink) -> void
57
+ def execute_stream: (Hash[Symbol, untyped], Riffer::Providers::_EventSink) -> void
39
58
 
40
59
  # --
41
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
42
- def handle_stream_chunk: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
60
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
61
+ def handle_stream_chunk: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
43
62
 
44
63
  # --
45
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
46
- def handle_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
64
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
65
+ def handle_text_delta: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
47
66
 
48
67
  # --
49
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
50
- def handle_reasoning_delta: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
68
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
69
+ def handle_reasoning_delta: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
51
70
 
52
71
  # --
53
- # : (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
54
- def handle_tool_call_deltas: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
72
+ # : (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
73
+ def handle_tool_call_deltas: (untyped, state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
55
74
 
56
75
  # --
57
- # : (state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
58
- def emit_tool_call_done_events: (state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
76
+ # : (state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
77
+ def emit_tool_call_done_events: (state: Hash[Symbol, untyped], yielder: Riffer::Providers::_EventSink) -> void
59
78
 
60
79
  # --
61
80
  # : (untyped) -> bool
@@ -2,6 +2,8 @@
2
2
 
3
3
  # Registry for finding provider classes by identifier.
4
4
  module Riffer::Providers::Repository
5
+ @key_for: Hash[singleton(Riffer::Providers::Base), Symbol]?
6
+
5
7
  REPO: Hash[Symbol, ^() -> singleton(Riffer::Providers::Base)]
6
8
 
7
9
  # Finds a provider class by identifier.
@@ -9,4 +11,9 @@ module Riffer::Providers::Repository
9
11
  # --
10
12
  # : ((String | Symbol)) -> singleton(Riffer::Providers::Base)?
11
13
  def find: (String | Symbol) -> singleton(Riffer::Providers::Base)?
14
+
15
+ # Returns the registry identifier for a provider class, or nil when unregistered.
16
+ # --
17
+ # : (singleton(Riffer::Providers::Base)) -> Symbol?
18
+ def key_for: (singleton(Riffer::Providers::Base)) -> Symbol?
12
19
  end
@@ -1,22 +1,26 @@
1
1
  # Generated from lib/riffer/providers/token_usage.rb with RBS::Inline
2
2
 
3
- # Represents token usage data from an LLM API call.
3
+ # Normalized token usage for an LLM API call. Buckets carry the same
4
+ # meaning for every provider.
4
5
  class Riffer::Providers::TokenUsage
5
- # Number of tokens in the input/prompt.
6
+ # Number of tokens entering the context window, including cache reads and writes.
6
7
  attr_reader input_tokens: Integer
7
8
 
8
- # Number of tokens in the output/response.
9
+ # Number of tokens generated by the model, including reasoning/thinking tokens.
9
10
  attr_reader output_tokens: Integer
10
11
 
11
- # Number of tokens written to cache, when the provider reports it.
12
+ # Subset of +input_tokens+ written to the provider's prompt cache, when the provider reports it.
12
13
  attr_reader cache_write_tokens: Integer?
13
14
 
14
- # Number of tokens read from cache, when the provider reports it.
15
+ # Subset of +input_tokens+ read from the provider's prompt cache, when the provider reports it.
15
16
  attr_reader cache_read_tokens: Integer?
16
17
 
18
+ # Cost of the call, set when the model is priced. For observability, not billing.
19
+ attr_reader cost: Float?
20
+
17
21
  # --
18
- # : (input_tokens: Integer, output_tokens: Integer, ?cache_write_tokens: Integer?, ?cache_read_tokens: Integer?) -> void
19
- def initialize: (input_tokens: Integer, output_tokens: Integer, ?cache_write_tokens: Integer?, ?cache_read_tokens: Integer?) -> void
22
+ # : (input_tokens: Integer, output_tokens: Integer, ?cache_write_tokens: Integer?, ?cache_read_tokens: Integer?, ?cost: Float?) -> void
23
+ def initialize: (input_tokens: Integer, output_tokens: Integer, ?cache_write_tokens: Integer?, ?cache_read_tokens: Integer?, ?cost: Float?) -> void
20
24
 
21
25
  # Returns the total number of tokens (input + output).
22
26
  #
@@ -30,14 +34,20 @@ class Riffer::Providers::TokenUsage
30
34
  # : (Riffer::Providers::TokenUsage) -> Riffer::Providers::TokenUsage
31
35
  def +: (Riffer::Providers::TokenUsage) -> Riffer::Providers::TokenUsage
32
36
 
33
- # Converts the token usage to a hash; cache tokens are omitted when nil.
37
+ # Converts the token usage to a hash; cache tokens and cost are omitted when nil.
34
38
  # --
35
- # : () -> Hash[Symbol, Integer]
36
- def to_h: () -> Hash[Symbol, Integer]
39
+ # : () -> Hash[Symbol, (Integer | Float)]
40
+ def to_h: () -> Hash[Symbol, Integer | Float]
37
41
 
38
42
  private
39
43
 
40
44
  # --
41
45
  # : (Integer?, Integer?) -> Integer?
42
46
  def add_nullable: (Integer?, Integer?) -> Integer?
47
+
48
+ # nil is absorbing, not zero: one unpriced call makes the run total nil
49
+ # rather than silently under-reporting.
50
+ # --
51
+ # : (Float?, Float?) -> Float?
52
+ def add_cost: (Float?, Float?) -> Float?
43
53
  end
@@ -3,8 +3,14 @@
3
3
  # Tool the LLM calls to activate a skill and receive its instructions;
4
4
  # registered automatically when an agent has skills configured.
5
5
  class Riffer::Skills::ActivateTool < Riffer::Tool
6
- # Activates a skill by name and returns its body.
6
+ # Activates a skill by name and returns its wrapped body, or a short pointer when the skill is already active.
7
7
  # --
8
8
  # : (context: Riffer::Agent::Context?, name: String) -> Riffer::Tools::Response
9
9
  def call: (context: Riffer::Agent::Context?, name: String) -> Riffer::Tools::Response
10
+
11
+ private
12
+
13
+ # --
14
+ # : (String) -> String
15
+ def already_active_message: (String) -> String
10
16
  end
@@ -16,4 +16,14 @@ class Riffer::Skills::Adapter
16
16
  # --
17
17
  # : (Array[Riffer::Skills::Frontmatter]) -> String
18
18
  def render_catalog: (Array[Riffer::Skills::Frontmatter]) -> String
19
+
20
+ # Renders an activated skill body wrapped in identifying tags.
21
+ # --
22
+ # : (Riffer::Skills::Frontmatter, String) -> String
23
+ def render_activation: (Riffer::Skills::Frontmatter, String) -> String
24
+
25
+ # The behavioral instructions rendered alongside the catalog.
26
+ # --
27
+ # : () -> String
28
+ def catalog_instructions: () -> String
19
29
  end
@@ -1,12 +1,16 @@
1
1
  # Generated from lib/riffer/skills/context.rb with RBS::Inline
2
2
 
3
3
  # Skills context for an agent generation cycle — coordinates discovery,
4
- # activation, and prompt rendering, caching activations to avoid redundant
4
+ # activation, and prompt rendering, caching skill bodies to avoid redundant
5
5
  # backend reads. Exposed to tools via <tt>context.skills</tt>.
6
6
  class Riffer::Skills::Context
7
- @backend: Riffer::Skills::Backend
7
+ @preactivated: Array[String]
8
+
9
+ @activated: Array[String]
8
10
 
9
- @activated: Hash[String, String]
11
+ @bodies: Hash[String, String]
12
+
13
+ @backend: Riffer::Skills::Backend
10
14
 
11
15
  # Skill catalog indexed by name.
12
16
  attr_reader skills: Hash[String, Riffer::Skills::Frontmatter]
@@ -15,12 +19,20 @@ class Riffer::Skills::Context
15
19
  attr_reader adapter: Riffer::Skills::Adapter
16
20
 
17
21
  # Optional callback invoked when a skill is first activated.
18
- attr_writer on_activate: (^(String) -> void)?
22
+ attr_accessor on_activate: (^(String) -> void)?
19
23
 
20
24
  # --
21
25
  # : (backend: Riffer::Skills::Backend, skills: Hash[String, Riffer::Skills::Frontmatter], adapter: Riffer::Skills::Adapter) -> void
22
26
  def initialize: (backend: Riffer::Skills::Backend, skills: Hash[String, Riffer::Skills::Frontmatter], adapter: Riffer::Skills::Adapter) -> void
23
27
 
28
+ # Returns a skill's body without recording an activation.
29
+ #
30
+ # Raises Riffer::ArgumentError if the skill is not in the catalog.
31
+ #
32
+ # --
33
+ # : (String) -> String
34
+ def read: (String) -> String
35
+
24
36
  # Activates a skill by name. Returns the cached body on re-activation.
25
37
  #
26
38
  # Raises Riffer::ArgumentError if the skill is not in the catalog.
@@ -29,6 +41,32 @@ class Riffer::Skills::Context
29
41
  # : (String) -> String
30
42
  def activate: (String) -> String
31
43
 
44
+ # Activates a skill and returns its body wrapped for injection as a user
45
+ # message.
46
+ #
47
+ # Raises Riffer::ArgumentError if the skill is not in the catalog.
48
+ #
49
+ # --
50
+ # : (String) -> String
51
+ def activation_prompt: (String) -> String
52
+
53
+ # Activates a skill whose body renders in the system prompt rather than the
54
+ # conversation.
55
+ #
56
+ # Raises Riffer::ArgumentError if the skill is not in the catalog.
57
+ #
58
+ # --
59
+ # : (String) -> void
60
+ def preactivate: (String) -> void
61
+
62
+ # Clears a skill's activation so the next activation is treated as the first.
63
+ #
64
+ # Raises Riffer::ArgumentError if the skill is not in the catalog.
65
+ #
66
+ # --
67
+ # : (String) -> void
68
+ def deactivate: (String) -> void
69
+
32
70
  # Returns whether a skill has been activated.
33
71
  #
34
72
  # --
@@ -0,0 +1,21 @@
1
+ # Generated from lib/riffer/stream_events/finish_reason_done.rb with RBS::Inline
2
+
3
+ # Normalized reason the LLM finished, emitted once near the end of the
4
+ # stream; no ordering guarantee relative to TokenUsageDone.
5
+ class Riffer::StreamEvents::FinishReasonDone < Riffer::StreamEvents::Base
6
+ # The normalized finish reason (see <tt>Riffer::Providers::FinishReason::VALUES</tt>).
7
+ attr_reader finish_reason: Symbol
8
+
9
+ # The provider's raw finish-reason value, when one exists on the wire.
10
+ attr_reader raw_finish_reason: String?
11
+
12
+ # Raises Riffer::ArgumentError when +finish_reason+ is outside the
13
+ # normalized vocabulary.
14
+ # --
15
+ # : (finish_reason: Symbol, ?raw_finish_reason: String?, ?role: Symbol) -> void
16
+ def initialize: (finish_reason: Symbol, ?raw_finish_reason: String?, ?role: Symbol) -> void
17
+
18
+ # --
19
+ # : () -> Hash[Symbol, untyped]
20
+ def to_h: () -> Hash[Symbol, untyped]
21
+ end
@@ -35,6 +35,10 @@ class Riffer::Tools::Runtime
35
35
 
36
36
  private
37
37
 
38
+ # --
39
+ # : (Riffer::Messages::Assistant::ToolCall) { () -> Riffer::Tools::Response } -> [Riffer::Messages::Assistant::ToolCall, Riffer::Tools::Response]
40
+ def instrument_tool_call: (Riffer::Messages::Assistant::ToolCall) { () -> Riffer::Tools::Response } -> [ Riffer::Messages::Assistant::ToolCall, Riffer::Tools::Response ]
41
+
38
42
  # --
39
43
  # : (Riffer::Messages::Assistant::ToolCall, tools: Array[singleton(Riffer::Tool)], context: Riffer::Agent::Context?, ?assistant_message: Riffer::Messages::Assistant?) -> Riffer::Tools::Response
40
44
  def dispatch_tool_call: (Riffer::Messages::Assistant::ToolCall, tools: Array[singleton(Riffer::Tool)], context: Riffer::Agent::Context?, ?assistant_message: Riffer::Messages::Assistant?) -> Riffer::Tools::Response
@@ -42,4 +46,35 @@ class Riffer::Tools::Runtime
42
46
  # --
43
47
  # : (String?) -> Hash[Symbol, untyped]
44
48
  def parse_arguments: (String?) -> Hash[Symbol, untyped]
49
+
50
+ # Emitted outside +around_tool_call+ so host enrichment spans nest beneath it.
51
+ # --
52
+ # : [R] (Riffer::Messages::Assistant::ToolCall) { ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span)) -> R } -> R
53
+ def in_tool_span: [R] (Riffer::Messages::Assistant::ToolCall) { (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span) -> R } -> R
54
+
55
+ # --
56
+ # : (Riffer::Messages::Assistant::ToolCall) -> Hash[String, untyped]
57
+ def tool_span_attributes: (Riffer::Messages::Assistant::ToolCall) -> Hash[String, untyped]
58
+
59
+ # --
60
+ # : (Riffer::Messages::Assistant::ToolCall, String?) -> Hash[String, untyped]
61
+ def tool_metric_attributes: (Riffer::Messages::Assistant::ToolCall, String?) -> Hash[String, untyped]
62
+
63
+ # A returned error Response is a handled outcome, so its status stays unset —
64
+ # an error span status is reserved for a raised exception.
65
+ # --
66
+ # : ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span), Riffer::Tools::Response) -> void
67
+ def record_tool_outcome: (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span, Riffer::Tools::Response) -> void
68
+
69
+ # --
70
+ # : ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span), Riffer::Messages::Assistant::ToolCall) -> void
71
+ def capture_tool_arguments: (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span, Riffer::Messages::Assistant::ToolCall) -> void
72
+
73
+ # --
74
+ # : ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span), Riffer::Tools::Response) -> void
75
+ def capture_tool_result: (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span, Riffer::Tools::Response) -> void
76
+
77
+ # --
78
+ # : ((Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span)) -> bool
79
+ def capture_tool_content?: (Riffer::Tracing::Otel::Span | Riffer::Tracing::NoOp::Span) -> bool
45
80
  end
@@ -0,0 +1,46 @@
1
+ # Generated from lib/riffer/tracing/capture.rb with RBS::Inline
2
+
3
+ # Serializes riffer messages into the GenAI semconv JSON message structure
4
+ # for opt-in span content capture. File parts become metadata-only stubs —
5
+ # bytes and URLs never reach a span attribute.
6
+ module Riffer::Tracing::Capture
7
+ # --
8
+ # : (Array[Riffer::Messages::Base]) -> String
9
+ def input_messages: (Array[Riffer::Messages::Base]) -> String
10
+
11
+ # --
12
+ # : (Array[Riffer::Messages::Base]) -> String?
13
+ def system_instructions: (Array[Riffer::Messages::Base]) -> String?
14
+
15
+ # --
16
+ # : (content: String?, tool_calls: Array[Riffer::Messages::Assistant::ToolCall], finish_reason: Symbol?) -> String
17
+ def output_messages: (content: String?, tool_calls: Array[Riffer::Messages::Assistant::ToolCall], finish_reason: Symbol?) -> String
18
+
19
+ private
20
+
21
+ # --
22
+ # : (Riffer::Messages::Base) -> Hash[Symbol, untyped]?
23
+ def convert_message: (Riffer::Messages::Base) -> Hash[Symbol, untyped]?
24
+
25
+ # --
26
+ # : (String?, Array[Riffer::Messages::Assistant::ToolCall]) -> Array[Hash[Symbol, untyped]]
27
+ def assistant_parts: (String?, Array[Riffer::Messages::Assistant::ToolCall]) -> Array[Hash[Symbol, untyped]]
28
+
29
+ # --
30
+ # : (String?) -> Hash[Symbol, untyped]
31
+ def text_part: (String?) -> Hash[Symbol, untyped]
32
+
33
+ # --
34
+ # : (Riffer::Messages::Assistant::ToolCall) -> Hash[Symbol, untyped]
35
+ def tool_call_part: (Riffer::Messages::Assistant::ToolCall) -> Hash[Symbol, untyped]
36
+
37
+ # --
38
+ # : (Riffer::Messages::FilePart) -> Hash[Symbol, untyped]
39
+ def file_part: (Riffer::Messages::FilePart) -> Hash[Symbol, untyped]
40
+
41
+ # Semconv's tool_call part carries arguments as a JSON object; riffer holds
42
+ # them as a string — parse so the captured payload isn't double-encoded.
43
+ # --
44
+ # : (untyped) -> untyped
45
+ def parse_arguments: (untyped) -> untyped
46
+ end
@@ -0,0 +1,46 @@
1
+ # Generated from lib/riffer/tracing/no_op.rb with RBS::Inline
2
+
3
+ # No-op tracing backend, used when OTEL is unavailable or tracing is
4
+ # disabled.
5
+ module Riffer::Tracing::NoOp
6
+ # No-op stand-in for a span; answers <tt>recording?</tt> with +false+ so
7
+ # callers can skip expensive attribute serialization.
8
+ class Span
9
+ # --
10
+ # : (String, untyped) -> void
11
+ def set_attribute: (String, untyped) -> void
12
+
13
+ # --
14
+ # : (String, ?attributes: Hash[String, untyped]?) -> void
15
+ def add_event: (String, ?attributes: Hash[String, untyped]?) -> void
16
+
17
+ # --
18
+ # : (Exception) -> void
19
+ def record_exception: (Exception) -> void
20
+
21
+ # --
22
+ # : (?String) -> void
23
+ def error!: (?String) -> void
24
+
25
+ # --
26
+ # : () -> bool
27
+ def recording?: () -> bool
28
+ end
29
+
30
+ SPAN: Riffer::Tracing::NoOp::Span
31
+
32
+ # Yields the no-op span, ignoring all span options.
33
+ # --
34
+ # : [R] (String, **untyped) { (Riffer::Tracing::NoOp::Span) -> R } -> R
35
+ def in_span: [R] (String, **untyped) { (Riffer::Tracing::NoOp::Span) -> R } -> R
36
+
37
+ # Returns +nil+; there is no trace context without OTEL.
38
+ # --
39
+ # : () -> nil
40
+ def current_context: () -> nil
41
+
42
+ # Yields immediately; there is no context to attach.
43
+ # --
44
+ # : [R] (untyped) { () -> R } -> R
45
+ def with_context: [R] (untyped) { () -> R } -> R
46
+ end
@@ -0,0 +1,84 @@
1
+ # Generated from lib/riffer/tracing/otel.rb with RBS::Inline
2
+
3
+ # OTEL-backed tracing backend. <tt>::OpenTelemetry</tt> constants appear only
4
+ # inside method bodies here, so the gem loads and eager-loads cleanly when the
5
+ # OpenTelemetry API is absent.
6
+ class Riffer::Tracing::Otel
7
+ # :nodoc: all
8
+ SUPPORTED_API_VERSIONS: Gem::Requirement
9
+
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).
12
+ class Span
13
+ @otel_span: untyped
14
+
15
+ # --
16
+ # : (untyped) -> void
17
+ def initialize: (untyped) -> void
18
+
19
+ # --
20
+ # : (String, untyped) -> void
21
+ def set_attribute: (String, untyped) -> void
22
+
23
+ # --
24
+ # : (String, ?attributes: Hash[String, untyped]?) -> void
25
+ def add_event: (String, ?attributes: Hash[String, untyped]?) -> void
26
+
27
+ # --
28
+ # : (Exception) -> void
29
+ def record_exception: (Exception) -> void
30
+
31
+ # Marks the span status as error.
32
+ # --
33
+ # : (?String) -> void
34
+ def error!: (?String) -> void
35
+
36
+ # --
37
+ # : () -> bool
38
+ def recording?: () -> bool
39
+ end
40
+
41
+ # Builds a backend when the OpenTelemetry API is loadable at a supported
42
+ # version; returns +nil+ so resolution falls back to NoOp. +provider+
43
+ # defaults to the global <tt>OpenTelemetry.tracer_provider</tt>.
44
+ # --
45
+ # : (?provider: untyped) -> Riffer::Tracing::Otel?
46
+ def self.build: (?provider: untyped) -> Riffer::Tracing::Otel?
47
+
48
+ # Whether the OpenTelemetry API gem is loadable at a supported version.
49
+ # --
50
+ # : () -> bool
51
+ def self.available?: () -> bool
52
+
53
+ # Whether the given opentelemetry-api version is one riffer codes
54
+ # against. The gem is undeclared, so this guard is the only protection
55
+ # against an incompatible API.
56
+ # --
57
+ # : (Gem::Version) -> bool
58
+ def self.supported?: (Gem::Version) -> bool
59
+
60
+ # --
61
+ # : () -> Gem::Version?
62
+ private def self.api_version: () -> Gem::Version?
63
+
64
+ @tracer: untyped
65
+
66
+ # --
67
+ # : (provider: untyped) -> void
68
+ def initialize: (provider: untyped) -> void
69
+
70
+ # Opens an OTEL span around the block, yielding the wrapped span.
71
+ # --
72
+ # : [R] (String, attributes: Hash[String, untyped]?, kind: Symbol) { (Riffer::Tracing::Otel::Span) -> R } -> R
73
+ def in_span: [R] (String, attributes: Hash[String, untyped]?, kind: Symbol) { (Riffer::Tracing::Otel::Span) -> R } -> R
74
+
75
+ # Returns the active OTEL context.
76
+ # --
77
+ # : () -> untyped
78
+ def current_context: () -> untyped
79
+
80
+ # Runs the block with the given OTEL context active.
81
+ # --
82
+ # : [R] (untyped) { () -> R } -> R
83
+ def with_context: [R] (untyped) { () -> R } -> R
84
+ end
@@ -0,0 +1,31 @@
1
+ # Generated from lib/riffer/tracing/stream_recorder.rb with RBS::Inline
2
+
3
+ # Wraps a stream yielder to observe terminal events for span stamping while
4
+ # forwarding every event downstream untouched.
5
+ class Riffer::Tracing::StreamRecorder
6
+ @yielder: Enumerator::Yielder
7
+
8
+ attr_reader token_usage: Riffer::Providers::TokenUsage?
9
+
10
+ attr_reader finish_reason: Symbol?
11
+
12
+ attr_reader raw_finish_reason: String?
13
+
14
+ attr_reader content: String?
15
+
16
+ attr_reader tool_calls: Array[Riffer::Messages::Assistant::ToolCall]
17
+
18
+ # --
19
+ # : (Enumerator::Yielder) -> void
20
+ def initialize: (Enumerator::Yielder) -> void
21
+
22
+ # --
23
+ # : (Riffer::StreamEvents::Base) -> self
24
+ def <<: (Riffer::StreamEvents::Base) -> self
25
+
26
+ private
27
+
28
+ # --
29
+ # : (Riffer::StreamEvents::Base) -> void
30
+ def record: (Riffer::StreamEvents::Base) -> void
31
+ end