riffer 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/rules/rbs-inline.md +5 -1
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +31 -0
- data/Rakefile +1 -1
- data/Steepfile +1 -15
- data/docs/AGENTS.md +37 -3
- data/docs/AGENT_LIFECYCLE.md +1 -0
- data/docs/CONFIGURATION.md +1 -1
- data/docs/EVALS.md +2 -1
- data/docs/MCP.md +0 -4
- data/docs/MESSAGES.md +85 -17
- data/docs/STREAM_EVENTS.md +31 -4
- data/docs/TRACING.md +1 -1
- data/docs/providers/AMAZON_BEDROCK.md +1 -1
- data/docs/providers/CUSTOM_PROVIDERS.md +58 -4
- data/docs/providers/GEMINI.md +1 -1
- data/docs/providers/MOCK_PROVIDER.md +17 -0
- data/lib/riffer/agent/config.rb +40 -16
- data/lib/riffer/agent/outcome.rb +2 -2
- data/lib/riffer/agent/response.rb +16 -9
- data/lib/riffer/agent/run.rb +24 -9
- data/lib/riffer/agent/session.rb +2 -1
- data/lib/riffer/agent/structured_output/result.rb +2 -2
- data/lib/riffer/agent/structured_output.rb +1 -1
- data/lib/riffer/agent.rb +40 -16
- data/lib/riffer/config.rb +31 -31
- data/lib/riffer/evals/evaluator.rb +29 -2
- data/lib/riffer/evals/judge.rb +13 -8
- data/lib/riffer/evals/result.rb +6 -6
- data/lib/riffer/evals/run_result.rb +1 -1
- data/lib/riffer/evals/scenario_result.rb +6 -6
- data/lib/riffer/files/resolver.rb +3 -3
- data/lib/riffer/guardrails/modification.rb +3 -3
- data/lib/riffer/guardrails/result.rb +3 -3
- data/lib/riffer/guardrails/runner.rb +4 -4
- data/lib/riffer/guardrails/tripwire.rb +4 -4
- data/lib/riffer/helpers/deep_dup.rb +42 -0
- data/lib/riffer/mcp/manifest.rb +5 -5
- data/lib/riffer/mcp/registration.rb +1 -1
- data/lib/riffer/mcp/search_tool.rb +1 -1
- data/lib/riffer/messages/assistant/reasoning_part.rb +90 -0
- data/lib/riffer/messages/assistant/tool_call.rb +63 -0
- data/lib/riffer/messages/assistant.rb +55 -7
- data/lib/riffer/messages/base.rb +7 -25
- data/lib/riffer/messages/system.rb +10 -0
- data/lib/riffer/messages/tool.rb +21 -4
- data/lib/riffer/messages/{file_part.rb → user/file_part.rb} +18 -17
- data/lib/riffer/messages/user.rb +13 -2
- data/lib/riffer/params/param.rb +20 -8
- data/lib/riffer/params.rb +10 -1
- data/lib/riffer/providers/amazon_bedrock.rb +34 -6
- data/lib/riffer/providers/anthropic.rb +9 -2
- data/lib/riffer/providers/base.rb +28 -10
- data/lib/riffer/providers/finish_reason.rb +2 -2
- data/lib/riffer/providers/gemini.rb +2 -2
- data/lib/riffer/providers/mock.rb +19 -3
- data/lib/riffer/providers/open_ai.rb +14 -5
- data/lib/riffer/providers/open_router.rb +6 -5
- data/lib/riffer/providers/repository.rb +0 -4
- data/lib/riffer/providers/token_usage.rb +21 -5
- data/lib/riffer/skills/adapter.rb +1 -1
- data/lib/riffer/skills/config.rb +12 -0
- data/lib/riffer/skills/context.rb +4 -7
- data/lib/riffer/skills/filesystem_backend.rb +1 -2
- data/lib/riffer/skills/frontmatter.rb +4 -4
- data/lib/riffer/skills/xml_adapter.rb +1 -1
- data/lib/riffer/stream_events/base.rb +1 -1
- data/lib/riffer/stream_events/finish_reason_done.rb +2 -2
- data/lib/riffer/stream_events/guardrail_modification.rb +1 -1
- data/lib/riffer/stream_events/guardrail_tripwire.rb +1 -1
- data/lib/riffer/stream_events/interrupt.rb +2 -2
- data/lib/riffer/stream_events/reasoning_delta.rb +1 -1
- data/lib/riffer/stream_events/reasoning_done.rb +10 -8
- data/lib/riffer/stream_events/skill_activation.rb +1 -1
- data/lib/riffer/stream_events/text_delta.rb +1 -1
- data/lib/riffer/stream_events/text_done.rb +1 -1
- data/lib/riffer/stream_events/token_usage_done.rb +1 -1
- data/lib/riffer/stream_events/tool_call_delta.rb +3 -3
- data/lib/riffer/stream_events/tool_call_done.rb +4 -4
- data/lib/riffer/stream_events/web_search_done.rb +2 -2
- data/lib/riffer/stream_events/web_search_status.rb +3 -3
- data/lib/riffer/tools/response.rb +4 -4
- data/lib/riffer/tools/runtime.rb +3 -4
- data/lib/riffer/tracing/capture.rb +2 -4
- data/lib/riffer/tracing/stream_recorder.rb +6 -6
- data/lib/riffer/version.rb +1 -1
- data/lib/riffer.rb +7 -0
- data/rbs_collection.lock.yaml +320 -0
- data/rbs_collection.yaml +12 -0
- data/sig/_private/anthropic.rbs +5 -4
- data/sig/_private/aws-sdk-core/event_error.rbs +15 -0
- data/sig/generated/riffer/agent/config.rbs +19 -5
- data/sig/generated/riffer/agent/response.rbs +6 -1
- data/sig/generated/riffer/agent/run.rbs +15 -8
- data/sig/generated/riffer/agent.rbs +25 -9
- data/sig/generated/riffer/config.rbs +1 -1
- data/sig/generated/riffer/evals/evaluator.rbs +20 -1
- data/sig/generated/riffer/evals/judge.rbs +5 -2
- data/sig/generated/riffer/files/resolver.rbs +6 -6
- data/sig/generated/riffer/helpers/deep_dup.rbs +21 -0
- data/sig/generated/riffer/messages/assistant/reasoning_part.rbs +58 -0
- data/sig/generated/riffer/messages/assistant/tool_call.rbs +42 -0
- data/sig/generated/riffer/messages/assistant.rbs +24 -10
- data/sig/generated/riffer/messages/system.rbs +6 -0
- data/sig/generated/riffer/messages/tool.rbs +6 -0
- data/sig/generated/riffer/messages/{file_part.rbs → user/file_part.rbs} +11 -6
- data/sig/generated/riffer/messages/user.rbs +9 -3
- data/sig/generated/riffer/params/param.rbs +7 -0
- data/sig/generated/riffer/params.rbs +6 -0
- data/sig/generated/riffer/providers/amazon_bedrock.rbs +14 -5
- data/sig/generated/riffer/providers/anthropic.rbs +2 -2
- data/sig/generated/riffer/providers/base.rbs +22 -10
- data/sig/generated/riffer/providers/gemini.rbs +4 -4
- data/sig/generated/riffer/providers/mock.rbs +7 -2
- data/sig/generated/riffer/providers/open_ai.rbs +4 -4
- data/sig/generated/riffer/providers/open_router.rbs +4 -4
- data/sig/generated/riffer/providers/repository.rbs +0 -2
- data/sig/generated/riffer/providers/token_usage.rbs +6 -0
- data/sig/generated/riffer/skills/config.rbs +9 -0
- data/sig/generated/riffer/stream_events/reasoning_done.rbs +8 -6
- data/sig/generated/riffer/tools/runtime.rbs +2 -2
- data/sig/generated/riffer/tracing/capture.rbs +4 -4
- data/sig/generated/riffer.rbs +8 -0
- data/sig/manual/riffer/helpers/deep_dup.rbs +5 -0
- metadata +13 -5
- data/sig/_private/async.rbs +0 -28
- data/sig/_private/minitest.rbs +0 -9
data/lib/riffer/agent/config.rb
CHANGED
|
@@ -7,38 +7,37 @@
|
|
|
7
7
|
class Riffer::Agent::Config
|
|
8
8
|
DEFAULT_MAX_STEPS = 16 #: Integer
|
|
9
9
|
|
|
10
|
+
# @rbs @tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?
|
|
11
|
+
|
|
10
12
|
# The configured agent identifier.
|
|
11
|
-
attr_reader :identifier #: String?
|
|
13
|
+
attr_reader :identifier #: String? # @dynamic identifier
|
|
12
14
|
|
|
13
15
|
# The configured model.
|
|
14
|
-
attr_reader :model #: (String | Proc)?
|
|
16
|
+
attr_reader :model #: (String | Proc)? # @dynamic model
|
|
15
17
|
|
|
16
18
|
# The configured instructions.
|
|
17
|
-
attr_reader :instructions #: (String | Proc)?
|
|
19
|
+
attr_reader :instructions #: (String | Proc)? # @dynamic instructions
|
|
18
20
|
|
|
19
21
|
# Options passed to generate_text/stream_text.
|
|
20
|
-
attr_accessor :model_options #: Hash[Symbol, untyped]
|
|
22
|
+
attr_accessor :model_options #: Hash[Symbol, untyped] # @dynamic model_options, model_options=
|
|
21
23
|
|
|
22
24
|
# The configured structured-output schema.
|
|
23
|
-
attr_reader :structured_output #: Riffer::Params?
|
|
25
|
+
attr_reader :structured_output #: Riffer::Params? # @dynamic structured_output
|
|
24
26
|
|
|
25
27
|
# The maximum number of LLM call steps in the tool-use loop.
|
|
26
|
-
attr_accessor :max_steps #: Numeric?
|
|
28
|
+
attr_accessor :max_steps #: Numeric? # @dynamic max_steps, max_steps=
|
|
27
29
|
|
|
28
30
|
# The configured tools.
|
|
29
|
-
attr_accessor :tools_config #: (Array[singleton(Riffer::Tool)] | Proc)?
|
|
31
|
+
attr_accessor :tools_config #: (Array[singleton(Riffer::Tool)] | Proc)? # @dynamic tools_config, tools_config=
|
|
30
32
|
|
|
31
33
|
# The accumulated +use_mcp+ tag configurations.
|
|
32
|
-
attr_reader :mcp_configs #: Array[Hash[Symbol, untyped]]
|
|
33
|
-
|
|
34
|
-
# The configured tool runtime.
|
|
35
|
-
attr_reader :tool_runtime #: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
|
|
34
|
+
attr_reader :mcp_configs #: Array[Hash[Symbol, untyped]] # @dynamic mcp_configs
|
|
36
35
|
|
|
37
36
|
# The configured skills.
|
|
38
|
-
attr_accessor :skills_config #: Riffer::Skills::Config?
|
|
37
|
+
attr_accessor :skills_config #: Riffer::Skills::Config? # @dynamic skills_config, skills_config=
|
|
39
38
|
|
|
40
39
|
# Registered guardrail entries keyed by phase.
|
|
41
|
-
attr_reader :guardrails #: Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
|
40
|
+
attr_reader :guardrails #: Hash[Symbol, Array[Hash[Symbol, untyped]]] # @dynamic guardrails
|
|
42
41
|
|
|
43
42
|
# Builds a new Config. Raises Riffer::ArgumentError if +model+ or
|
|
44
43
|
# +instructions+ is invalid (e.g. an empty string).
|
|
@@ -52,7 +51,7 @@ class Riffer::Agent::Config
|
|
|
52
51
|
# ?max_steps: Numeric?,
|
|
53
52
|
# ?tools_config: (Array[singleton(Riffer::Tool)] | Proc)?,
|
|
54
53
|
# ?mcp_configs: Array[Hash[Symbol, untyped]],
|
|
55
|
-
# ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
|
|
54
|
+
# ?tool_runtime: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)?,
|
|
56
55
|
# ?skills_config: Riffer::Skills::Config?,
|
|
57
56
|
# ?guardrails: Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
|
58
57
|
# ) -> void
|
|
@@ -65,7 +64,7 @@ class Riffer::Agent::Config
|
|
|
65
64
|
max_steps: DEFAULT_MAX_STEPS,
|
|
66
65
|
tools_config: nil,
|
|
67
66
|
mcp_configs: [],
|
|
68
|
-
tool_runtime:
|
|
67
|
+
tool_runtime: nil,
|
|
69
68
|
skills_config: nil,
|
|
70
69
|
guardrails: { before: [], after: [] }
|
|
71
70
|
)
|
|
@@ -79,7 +78,7 @@ class Riffer::Agent::Config
|
|
|
79
78
|
self.model = model
|
|
80
79
|
self.instructions = instructions
|
|
81
80
|
self.structured_output = structured_output
|
|
82
|
-
self.tool_runtime = tool_runtime
|
|
81
|
+
self.tool_runtime = tool_runtime if tool_runtime
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
# Sets +identifier+, coercing the value to String.
|
|
@@ -100,6 +99,15 @@ class Riffer::Agent::Config
|
|
|
100
99
|
@structured_output = value
|
|
101
100
|
end
|
|
102
101
|
|
|
102
|
+
# Returns the declared tool runtime, or +Riffer.config.tool_runtime+ when none
|
|
103
|
+
# was declared. Resolving the global here rather than at construction is what
|
|
104
|
+
# lets a copy tell an inherited runtime from a defaulted one.
|
|
105
|
+
#--
|
|
106
|
+
#: () -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
|
|
107
|
+
def tool_runtime
|
|
108
|
+
@tool_runtime || Riffer.config.tool_runtime
|
|
109
|
+
end
|
|
110
|
+
|
|
103
111
|
# Sets +tool_runtime+. Raises Riffer::ArgumentError on an invalid value.
|
|
104
112
|
#--
|
|
105
113
|
#: ((singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)) -> (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
|
|
@@ -177,6 +185,22 @@ class Riffer::Agent::Config
|
|
|
177
185
|
|
|
178
186
|
private
|
|
179
187
|
|
|
188
|
+
# +dup+ would leave the copy sharing every collection with this one, so a
|
|
189
|
+
# declaration on either would reach the other. The nesting runs deeper than one
|
|
190
|
+
# level: an mcp entry holds its own +:tags+ array, a guardrail entry its own
|
|
191
|
+
# +:options+ hash, and +model_options+ is arbitrary.
|
|
192
|
+
#--
|
|
193
|
+
#: (Riffer::Agent::Config) -> void
|
|
194
|
+
def initialize_copy(source)
|
|
195
|
+
super
|
|
196
|
+
@model_options = Riffer::Helpers::DeepDup.call(source.model_options)
|
|
197
|
+
@mcp_configs = Riffer::Helpers::DeepDup.call(source.mcp_configs)
|
|
198
|
+
@guardrails = Riffer::Helpers::DeepDup.call(source.guardrails)
|
|
199
|
+
@tools_config = Riffer::Helpers::DeepDup.call(source.tools_config)
|
|
200
|
+
@skills_config = source.skills_config&.dup
|
|
201
|
+
@structured_output = source.structured_output&.dup
|
|
202
|
+
end
|
|
203
|
+
|
|
180
204
|
#--
|
|
181
205
|
#: (untyped, String) -> void
|
|
182
206
|
def validate_string_or_proc!(value, name)
|
data/lib/riffer/agent/outcome.rb
CHANGED
|
@@ -25,10 +25,10 @@ class Riffer::Agent::Outcome
|
|
|
25
25
|
PROVIDER_STOP_REASONS).freeze #: Array[Symbol]
|
|
26
26
|
|
|
27
27
|
# Why the run ended.
|
|
28
|
-
attr_reader :reason #: Symbol
|
|
28
|
+
attr_reader :reason #: Symbol # @dynamic reason
|
|
29
29
|
|
|
30
30
|
# Human-readable specifics for +reason+, when there are any.
|
|
31
|
-
attr_reader :detail #: String?
|
|
31
|
+
attr_reader :detail #: String? # @dynamic detail
|
|
32
32
|
|
|
33
33
|
# Raises Riffer::ArgumentError when +reason+ is outside VALUES.
|
|
34
34
|
#--
|
|
@@ -13,33 +13,37 @@
|
|
|
13
13
|
# end
|
|
14
14
|
class Riffer::Agent::Response
|
|
15
15
|
# The response content.
|
|
16
|
-
attr_reader :content #: String
|
|
16
|
+
attr_reader :content #: String # @dynamic content
|
|
17
17
|
|
|
18
18
|
# How the run ended.
|
|
19
|
-
attr_reader :outcome #: Riffer::Agent::Outcome
|
|
19
|
+
attr_reader :outcome #: Riffer::Agent::Outcome # @dynamic outcome
|
|
20
20
|
|
|
21
21
|
# The tripwire if execution was blocked.
|
|
22
|
-
attr_reader :tripwire #: Riffer::Guardrails::Tripwire?
|
|
22
|
+
attr_reader :tripwire #: Riffer::Guardrails::Tripwire? # @dynamic tripwire
|
|
23
23
|
|
|
24
24
|
# The modifications made by guardrails during processing.
|
|
25
|
-
attr_reader :modifications #: Array[Riffer::Guardrails::Modification]
|
|
25
|
+
attr_reader :modifications #: Array[Riffer::Guardrails::Modification] # @dynamic modifications
|
|
26
|
+
|
|
27
|
+
# The reasoning parts on the final assistant message, if the provider
|
|
28
|
+
# produced any.
|
|
29
|
+
attr_reader :reasoning #: Array[Riffer::Messages::Assistant::ReasoningPart] # @dynamic reasoning
|
|
26
30
|
|
|
27
31
|
# The parsed structured output, if structured output was configured.
|
|
28
|
-
attr_reader :structured_output #: Hash[Symbol, untyped]?
|
|
32
|
+
attr_reader :structured_output #: Hash[Symbol, untyped]? # @dynamic structured_output
|
|
29
33
|
|
|
30
34
|
# The aggregate token usage across this run's LLM calls, if any was reported.
|
|
31
|
-
attr_reader :token_usage #: Riffer::Providers::TokenUsage?
|
|
35
|
+
attr_reader :token_usage #: Riffer::Providers::TokenUsage? # @dynamic token_usage
|
|
32
36
|
|
|
33
37
|
# The number of LLM calls made during this run (0 when a before-guardrail
|
|
34
38
|
# blocks before any call). Distinct from the session's cumulative step count.
|
|
35
|
-
attr_reader :steps #: Integer
|
|
39
|
+
attr_reader :steps #: Integer # @dynamic steps
|
|
36
40
|
|
|
37
41
|
# The full message history from the agent conversation.
|
|
38
|
-
attr_reader :messages #: Array[Riffer::Messages::Base]
|
|
42
|
+
attr_reader :messages #: Array[Riffer::Messages::Base] # @dynamic messages
|
|
39
43
|
|
|
40
44
|
# Call ids of tool_use blocks riffer filled with placeholder results this
|
|
41
45
|
# turn (when an interrupt left them unanswered and history healing is on).
|
|
42
|
-
attr_reader :healed_tool_call_ids #: Array[String]
|
|
46
|
+
attr_reader :healed_tool_call_ids #: Array[String] # @dynamic healed_tool_call_ids
|
|
43
47
|
|
|
44
48
|
#--
|
|
45
49
|
#: (
|
|
@@ -47,6 +51,7 @@ class Riffer::Agent::Response
|
|
|
47
51
|
# outcome: Riffer::Agent::Outcome,
|
|
48
52
|
# ?tripwire: Riffer::Guardrails::Tripwire?,
|
|
49
53
|
# ?modifications: Array[Riffer::Guardrails::Modification],
|
|
54
|
+
# ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart],
|
|
50
55
|
# ?structured_output: Hash[Symbol, untyped]?,
|
|
51
56
|
# ?messages: Array[Riffer::Messages::Base],
|
|
52
57
|
# ?healed_tool_call_ids: Array[String],
|
|
@@ -58,6 +63,7 @@ class Riffer::Agent::Response
|
|
|
58
63
|
outcome:,
|
|
59
64
|
tripwire: nil,
|
|
60
65
|
modifications: [],
|
|
66
|
+
reasoning: [],
|
|
61
67
|
structured_output: nil,
|
|
62
68
|
messages: [],
|
|
63
69
|
healed_tool_call_ids: [],
|
|
@@ -68,6 +74,7 @@ class Riffer::Agent::Response
|
|
|
68
74
|
@outcome = outcome
|
|
69
75
|
@tripwire = tripwire
|
|
70
76
|
@modifications = modifications
|
|
77
|
+
@reasoning = reasoning
|
|
71
78
|
@structured_output = structured_output
|
|
72
79
|
@messages = messages
|
|
73
80
|
@healed_tool_call_ids = healed_tool_call_ids
|
data/lib/riffer/agent/run.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Riffer::Agent::Run
|
|
|
10
10
|
# for prompt/files semantics.
|
|
11
11
|
#
|
|
12
12
|
#--
|
|
13
|
-
#: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
13
|
+
#: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
14
14
|
def generate(agent:, prompt: nil, files: nil, tags: {})
|
|
15
15
|
append_user_message(agent, prompt, files: files)
|
|
16
16
|
run_loop(agent, tags: tags)
|
|
@@ -20,7 +20,7 @@ module Riffer::Agent::Run
|
|
|
20
20
|
# for prompt/files semantics.
|
|
21
21
|
#
|
|
22
22
|
#--
|
|
23
|
-
#: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
23
|
+
#: (agent: Riffer::Agent, ?prompt: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
24
24
|
def stream(agent:, prompt: nil, files: nil, tags: {})
|
|
25
25
|
append_user_message(agent, prompt, files: files)
|
|
26
26
|
# The enumerator body runs in its own fiber, where the fiber-local OTEL
|
|
@@ -36,16 +36,17 @@ module Riffer::Agent::Run
|
|
|
36
36
|
private
|
|
37
37
|
|
|
38
38
|
# Both +generate+ and +stream+ funnel here, so this is the single place raw
|
|
39
|
-
# +tags+ are normalized
|
|
39
|
+
# +tags+ are normalized and merged over the default tags (a caller tag wins
|
|
40
|
+
# on a shared key). The clean <tt>String => String</tt> map is then
|
|
40
41
|
# threaded to every span builder in the run as +riffer.tag.*+ and to each
|
|
41
42
|
# provider call (via +merged_model_options+) for native request-metadata
|
|
42
43
|
# mapping.
|
|
43
44
|
#--
|
|
44
45
|
#: (Riffer::Agent, ?tags: Hash[(String | Symbol), untyped]?, ?stream_yielder: Enumerator::Yielder?) -> Riffer::Agent::Response
|
|
45
46
|
def run_loop(agent, tags: {}, stream_yielder: nil)
|
|
46
|
-
tags = normalize_tags(tags)
|
|
47
|
+
tags = default_tags(agent).merge(normalize_tags(tags))
|
|
47
48
|
Riffer::Tracing.in_span(
|
|
48
|
-
"invoke_agent #{agent.
|
|
49
|
+
"invoke_agent #{agent.identifier}",
|
|
49
50
|
attributes: run_span_attributes(agent, tags),
|
|
50
51
|
kind: :internal,
|
|
51
52
|
) do |span|
|
|
@@ -153,6 +154,7 @@ module Riffer::Agent::Run
|
|
|
153
154
|
def accumulate_streamed_response(agent, stream_yielder, tags = {})
|
|
154
155
|
accumulated_content = +""
|
|
155
156
|
accumulated_tool_calls = [] #: Array[Riffer::Messages::Assistant::ToolCall]
|
|
157
|
+
accumulated_reasoning = [] #: Array[Riffer::Messages::Assistant::ReasoningPart]
|
|
156
158
|
accumulated_token_usage = nil #: Riffer::Providers::TokenUsage?
|
|
157
159
|
accumulated_finish_reason = nil #: Symbol?
|
|
158
160
|
accumulated_finish_reason_raw = nil #: String?
|
|
@@ -175,6 +177,8 @@ module Riffer::Agent::Run
|
|
|
175
177
|
name: event.name,
|
|
176
178
|
arguments: event.arguments,
|
|
177
179
|
)
|
|
180
|
+
when Riffer::StreamEvents::ReasoningDone
|
|
181
|
+
accumulated_reasoning << event.part
|
|
178
182
|
when Riffer::StreamEvents::TokenUsageDone
|
|
179
183
|
accumulated_token_usage = event.token_usage
|
|
180
184
|
when Riffer::StreamEvents::FinishReasonDone
|
|
@@ -186,6 +190,7 @@ module Riffer::Agent::Run
|
|
|
186
190
|
Riffer::Messages::Assistant.new(
|
|
187
191
|
accumulated_content,
|
|
188
192
|
tool_calls: accumulated_tool_calls,
|
|
193
|
+
reasoning: accumulated_reasoning,
|
|
189
194
|
token_usage: accumulated_token_usage,
|
|
190
195
|
finish_reason: accumulated_finish_reason,
|
|
191
196
|
finish_reason_raw: accumulated_finish_reason_raw,
|
|
@@ -228,6 +233,7 @@ module Riffer::Agent::Run
|
|
|
228
233
|
message&.content || "",
|
|
229
234
|
outcome: final_outcome(message, result, interrupted: interrupted, interrupt_reason: interrupt_reason),
|
|
230
235
|
modifications: all_modifications,
|
|
236
|
+
reasoning: message&.reasoning || [],
|
|
231
237
|
structured_output: result&.object,
|
|
232
238
|
**extra,
|
|
233
239
|
)
|
|
@@ -381,6 +387,13 @@ module Riffer::Agent::Run
|
|
|
381
387
|
opts
|
|
382
388
|
end
|
|
383
389
|
|
|
390
|
+
# The tags riffer adds to every run, identifying the agent it's on behalf of.
|
|
391
|
+
#--
|
|
392
|
+
#: (Riffer::Agent) -> Hash[String, String]
|
|
393
|
+
def default_tags(agent)
|
|
394
|
+
{ "kind" => "agent", "agent" => agent.identifier }
|
|
395
|
+
end
|
|
396
|
+
|
|
384
397
|
#--
|
|
385
398
|
#: (
|
|
386
399
|
# Riffer::Agent,
|
|
@@ -388,6 +401,7 @@ module Riffer::Agent::Run
|
|
|
388
401
|
# outcome: Riffer::Agent::Outcome,
|
|
389
402
|
# ?tripwire: Riffer::Guardrails::Tripwire?,
|
|
390
403
|
# ?modifications: Array[Riffer::Guardrails::Modification],
|
|
404
|
+
# ?reasoning: Array[Riffer::Messages::Assistant::ReasoningPart],
|
|
391
405
|
# ?structured_output: Hash[Symbol, untyped]?,
|
|
392
406
|
# ?healed_tool_call_ids: Array[String],
|
|
393
407
|
# ?token_usage: Riffer::Providers::TokenUsage?,
|
|
@@ -399,6 +413,7 @@ module Riffer::Agent::Run
|
|
|
399
413
|
outcome:,
|
|
400
414
|
tripwire: nil,
|
|
401
415
|
modifications: [],
|
|
416
|
+
reasoning: [],
|
|
402
417
|
structured_output: nil,
|
|
403
418
|
healed_tool_call_ids: [],
|
|
404
419
|
token_usage: nil,
|
|
@@ -410,6 +425,7 @@ module Riffer::Agent::Run
|
|
|
410
425
|
outcome: outcome,
|
|
411
426
|
tripwire: tripwire,
|
|
412
427
|
modifications: modifications,
|
|
428
|
+
reasoning: reasoning,
|
|
413
429
|
structured_output: structured_output,
|
|
414
430
|
messages: messages.frozen? ? messages : messages.dup.freeze,
|
|
415
431
|
healed_tool_call_ids: healed_tool_call_ids,
|
|
@@ -421,12 +437,12 @@ module Riffer::Agent::Run
|
|
|
421
437
|
# Raises when +files+ are supplied without a +prompt+ — the provider needs
|
|
422
438
|
# text to anchor the attachments.
|
|
423
439
|
#--
|
|
424
|
-
#: (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?) -> void
|
|
440
|
+
#: (Riffer::Agent, String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?) -> void
|
|
425
441
|
def append_user_message(agent, prompt, files: nil)
|
|
426
442
|
raise Riffer::ArgumentError, "files: requires a prompt" if files && !files.empty? && prompt.nil?
|
|
427
443
|
return unless prompt
|
|
428
444
|
|
|
429
|
-
file_parts = (files || []).map { |f| Riffer::Messages::FilePart.from_hash(f) }
|
|
445
|
+
file_parts = (files || []).map { |f| Riffer::Messages::User::FilePart.from_hash(f) }
|
|
430
446
|
agent.session.add(Riffer::Messages::User.new(prompt, files: file_parts), silent: true)
|
|
431
447
|
end
|
|
432
448
|
|
|
@@ -451,7 +467,7 @@ module Riffer::Agent::Run
|
|
|
451
467
|
def run_span_attributes(agent, tags = {})
|
|
452
468
|
{
|
|
453
469
|
"gen_ai.operation.name" => "invoke_agent",
|
|
454
|
-
"gen_ai.agent.name" => agent.
|
|
470
|
+
"gen_ai.agent.name" => agent.identifier,
|
|
455
471
|
"gen_ai.provider.name" => agent.provider.class.semconv_provider_name,
|
|
456
472
|
"gen_ai.request.model" => agent.model_name,
|
|
457
473
|
}.merge(tag_attributes(tags))
|
|
@@ -461,7 +477,6 @@ module Riffer::Agent::Run
|
|
|
461
477
|
#: (Hash[(String | Symbol), untyped]?) -> Hash[String, String]
|
|
462
478
|
def normalize_tags(tags)
|
|
463
479
|
return {} if tags.nil?
|
|
464
|
-
raise Riffer::ArgumentError, "tags: must be a Hash, got #{tags.class}" unless tags.is_a?(Hash)
|
|
465
480
|
|
|
466
481
|
result = {} #: Hash[String, String]
|
|
467
482
|
tags.each do |key, value|
|
data/lib/riffer/agent/session.rb
CHANGED
|
@@ -18,7 +18,7 @@ class Riffer::Agent::Session
|
|
|
18
18
|
# @rbs @callbacks: Array[^(Riffer::Messages::Base) -> void]
|
|
19
19
|
|
|
20
20
|
# The message history.
|
|
21
|
-
attr_reader :messages #: Array[Riffer::Messages::Base]
|
|
21
|
+
attr_reader :messages #: Array[Riffer::Messages::Base] # @dynamic messages
|
|
22
22
|
|
|
23
23
|
#--
|
|
24
24
|
#: (?messages: Array[Riffer::Messages::Base]) -> void
|
|
@@ -201,6 +201,7 @@ class Riffer::Agent::Session
|
|
|
201
201
|
attrs.fetch(:content, old.content),
|
|
202
202
|
id: attrs.fetch(:id, old.id),
|
|
203
203
|
tool_calls: attrs.fetch(:tool_calls, old.tool_calls),
|
|
204
|
+
reasoning: attrs.fetch(:reasoning, old.reasoning),
|
|
204
205
|
token_usage: attrs.fetch(:token_usage, old.token_usage),
|
|
205
206
|
structured_output: attrs.fetch(:structured_output, old.structured_output),
|
|
206
207
|
finish_reason: attrs.fetch(:finish_reason, old.finish_reason),
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
# Wraps the result of structured output parsing and validation.
|
|
5
5
|
class Riffer::Agent::StructuredOutput::Result
|
|
6
6
|
# The validated object, or +nil+ on failure.
|
|
7
|
-
attr_reader :object #: Hash[Symbol, untyped]?
|
|
7
|
+
attr_reader :object #: Hash[Symbol, untyped]? # @dynamic object
|
|
8
8
|
|
|
9
9
|
# The error message, or +nil+ on success.
|
|
10
|
-
attr_reader :error #: String?
|
|
10
|
+
attr_reader :error #: String? # @dynamic error
|
|
11
11
|
|
|
12
12
|
#--
|
|
13
13
|
#: (?object: Hash[Symbol, untyped]?, ?error: String?) -> void
|
data/lib/riffer/agent.rb
CHANGED
|
@@ -28,6 +28,19 @@ class Riffer::Agent
|
|
|
28
28
|
@config ||= Riffer::Agent::Config.new
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# +identifier+ is cleared because it is configuration here but identity on the
|
|
32
|
+
# subclass; two classes claiming one raise Riffer::DuplicateIdentifierError at
|
|
33
|
+
# the next registry lookup.
|
|
34
|
+
#--
|
|
35
|
+
#: (Class) -> void
|
|
36
|
+
def self.inherited(subclass)
|
|
37
|
+
super
|
|
38
|
+
copy = config.dup
|
|
39
|
+
copy.identifier = nil
|
|
40
|
+
subclass.instance_variable_set(:@config, copy)
|
|
41
|
+
end
|
|
42
|
+
private_class_method :inherited
|
|
43
|
+
|
|
31
44
|
# Gets or sets the agent identifier.
|
|
32
45
|
#
|
|
33
46
|
#--
|
|
@@ -148,14 +161,14 @@ class Riffer::Agent
|
|
|
148
161
|
|
|
149
162
|
# Generates a response using a new agent instance.
|
|
150
163
|
#--
|
|
151
|
-
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
164
|
+
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
152
165
|
def self.generate(prompt = nil, files: nil, context: nil, tags: {})
|
|
153
166
|
new(context: context).generate(prompt, files: files, tags: tags)
|
|
154
167
|
end
|
|
155
168
|
|
|
156
169
|
# Streams a response using a new agent instance.
|
|
157
170
|
#--
|
|
158
|
-
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
171
|
+
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?context: Hash[Symbol, untyped]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
159
172
|
def self.stream(prompt = nil, files: nil, context: nil, tags: {})
|
|
160
173
|
new(context: context).stream(prompt, files: files, tags: tags)
|
|
161
174
|
end
|
|
@@ -214,44 +227,44 @@ class Riffer::Agent
|
|
|
214
227
|
end
|
|
215
228
|
|
|
216
229
|
# The conversation handle.
|
|
217
|
-
attr_reader :session #: Riffer::Agent::Session
|
|
230
|
+
attr_reader :session #: Riffer::Agent::Session # @dynamic session
|
|
218
231
|
|
|
219
232
|
# The per-instance Riffer::Agent::Config.
|
|
220
|
-
attr_reader :config #: Riffer::Agent::Config
|
|
233
|
+
attr_reader :config #: Riffer::Agent::Config # @dynamic config
|
|
221
234
|
|
|
222
235
|
# The system message built from the configured +instructions+, or +nil+ when
|
|
223
236
|
# none are configured.
|
|
224
|
-
attr_reader :instruction_message #: Riffer::Messages::System?
|
|
237
|
+
attr_reader :instruction_message #: Riffer::Messages::System? # @dynamic instruction_message
|
|
225
238
|
|
|
226
239
|
# The system message describing the configured skills catalog, or +nil+ when
|
|
227
240
|
# skills are unconfigured or the catalog is empty.
|
|
228
|
-
attr_reader :skills_message #: Riffer::Messages::System?
|
|
241
|
+
attr_reader :skills_message #: Riffer::Messages::System? # @dynamic skills_message
|
|
229
242
|
|
|
230
243
|
# The mutable runtime context shared with every +Riffer::Agent::Run+ this
|
|
231
244
|
# agent executes and threaded through all Proc-based settings.
|
|
232
|
-
attr_reader :context #: Riffer::Agent::Context
|
|
245
|
+
attr_reader :context #: Riffer::Agent::Context # @dynamic context
|
|
233
246
|
|
|
234
247
|
# The resolved provider name (the part before "/" in the model string),
|
|
235
248
|
# e.g. +"openai"+.
|
|
236
|
-
attr_reader :provider_name #: String
|
|
249
|
+
attr_reader :provider_name #: String # @dynamic provider_name
|
|
237
250
|
|
|
238
251
|
# The resolved model name (the part after "/" in the model string), used as
|
|
239
252
|
# the model argument on every LLM call.
|
|
240
|
-
attr_reader :model_name #: String
|
|
253
|
+
attr_reader :model_name #: String # @dynamic model_name
|
|
241
254
|
|
|
242
255
|
# The provider client. Public so tests can pre-queue responses on
|
|
243
256
|
# +Riffer::Providers::Mock+ before calling +#generate+.
|
|
244
|
-
attr_reader :provider #: Riffer::Providers::Base
|
|
257
|
+
attr_reader :provider #: Riffer::Providers::Base # @dynamic provider
|
|
245
258
|
|
|
246
259
|
# The +Riffer::Agent::StructuredOutput+ wrapping the configured schema, or
|
|
247
260
|
# +nil+ when not configured.
|
|
248
|
-
attr_reader :structured_output #: Riffer::Agent::StructuredOutput?
|
|
261
|
+
attr_reader :structured_output #: Riffer::Agent::StructuredOutput? # @dynamic structured_output
|
|
249
262
|
|
|
250
263
|
# The tool classes the LLM sees on every call this agent makes.
|
|
251
|
-
attr_reader :tools #: Array[singleton(Riffer::Tool)]
|
|
264
|
+
attr_reader :tools #: Array[singleton(Riffer::Tool)] # @dynamic tools
|
|
252
265
|
|
|
253
266
|
# The tool runtime instance used to execute tool calls.
|
|
254
|
-
attr_reader :tool_runtime #: Riffer::Tools::Runtime
|
|
267
|
+
attr_reader :tool_runtime #: Riffer::Tools::Runtime # @dynamic tool_runtime
|
|
255
268
|
|
|
256
269
|
# Initializes a new agent.
|
|
257
270
|
#
|
|
@@ -284,6 +297,16 @@ class Riffer::Agent
|
|
|
284
297
|
@session.set(Riffer::Agent::Session::Repair.prune_orphans(@session.messages))
|
|
285
298
|
end
|
|
286
299
|
|
|
300
|
+
# The identifier for this agent: the instance config's identifier when set
|
|
301
|
+
# (e.g. an agent restored with +Riffer::Agent.from_h+), otherwise the class
|
|
302
|
+
# identifier.
|
|
303
|
+
#
|
|
304
|
+
#--
|
|
305
|
+
#: () -> String
|
|
306
|
+
def identifier
|
|
307
|
+
config.identifier || self.class.identifier
|
|
308
|
+
end
|
|
309
|
+
|
|
287
310
|
# Generates a response from the agent.
|
|
288
311
|
#
|
|
289
312
|
# With +prompt+, a new user message is appended (silently — +on_message+ does
|
|
@@ -296,10 +319,11 @@ class Riffer::Agent
|
|
|
296
319
|
# are stamped as +riffer.tag.*+ on every span the call emits. See
|
|
297
320
|
# +docs/AGENTS.md+ for the per-provider mapping. The reserved key
|
|
298
321
|
# +user_id+ also maps to the provider's native user identifier where one
|
|
299
|
-
# exists.
|
|
322
|
+
# exists. Riffer adds the default tags +kind+ (+"agent"+) and +agent+ (the
|
|
323
|
+
# agent identifier); a caller tag with the same key wins.
|
|
300
324
|
#
|
|
301
325
|
#--
|
|
302
|
-
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
326
|
+
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Riffer::Agent::Response
|
|
303
327
|
def generate(prompt = nil, files: nil, tags: {})
|
|
304
328
|
Riffer::Agent::Run.generate(agent: self, prompt: prompt, files: files, tags: tags)
|
|
305
329
|
end
|
|
@@ -311,7 +335,7 @@ class Riffer::Agent
|
|
|
311
335
|
# Raises Riffer::ArgumentError if structured output is configured.
|
|
312
336
|
#
|
|
313
337
|
#--
|
|
314
|
-
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
338
|
+
#: (?String?, ?files: Array[Hash[Symbol, untyped] | Riffer::Messages::User::FilePart]?, ?tags: Hash[(String | Symbol), untyped]) -> Enumerator[Riffer::StreamEvents::Base, Riffer::Agent::Response]
|
|
315
339
|
def stream(prompt = nil, files: nil, tags: {})
|
|
316
340
|
if @structured_output
|
|
317
341
|
raise Riffer::ArgumentError,
|
data/lib/riffer/config.rb
CHANGED
|
@@ -16,11 +16,11 @@ class Riffer::Config
|
|
|
16
16
|
class Skills
|
|
17
17
|
# The tool class the LLM calls to activate a skill; defaults to
|
|
18
18
|
# <tt>Riffer::Skills::ActivateTool</tt>.
|
|
19
|
-
attr_reader :default_activate_tool #: singleton(Riffer::Tool)
|
|
19
|
+
attr_reader :default_activate_tool #: singleton(Riffer::Tool) # @dynamic default_activate_tool
|
|
20
20
|
|
|
21
21
|
# Default skills backend for agents that declare a +skills+ block without
|
|
22
22
|
# one; defaults to +nil+.
|
|
23
|
-
attr_reader :default_backend #: (Riffer::Skills::Backend | Proc)?
|
|
23
|
+
attr_reader :default_backend #: (Riffer::Skills::Backend | Proc)? # @dynamic default_backend
|
|
24
24
|
|
|
25
25
|
#--
|
|
26
26
|
#: () -> void
|
|
@@ -61,17 +61,17 @@ class Riffer::Config
|
|
|
61
61
|
class Tracing
|
|
62
62
|
# Whether riffer emits OTEL spans; defaults to +true+, a no-op until a
|
|
63
63
|
# host wires an OTEL SDK.
|
|
64
|
-
attr_reader :enabled #: bool
|
|
64
|
+
attr_reader :enabled #: bool # @dynamic enabled
|
|
65
65
|
|
|
66
66
|
# Whether LLM-call spans capture full message content
|
|
67
67
|
# (<tt>gen_ai.input.messages</tt>, <tt>gen_ai.output.messages</tt>,
|
|
68
68
|
# <tt>gen_ai.system_instructions</tt>); defaults to +false+ — message
|
|
69
69
|
# content routinely carries sensitive data.
|
|
70
|
-
attr_reader :capture_messages #: bool
|
|
70
|
+
attr_reader :capture_messages #: bool # @dynamic capture_messages
|
|
71
71
|
|
|
72
72
|
# The backend riffer routes spans through; defaults to +nil+, a no-op.
|
|
73
73
|
# Riffer auto-detects no backend; assigning one is opt-in.
|
|
74
|
-
attr_reader :backend #: untyped
|
|
74
|
+
attr_reader :backend #: untyped # @dynamic backend
|
|
75
75
|
|
|
76
76
|
#--
|
|
77
77
|
#: () -> void
|
|
@@ -115,20 +115,20 @@ class Riffer::Config
|
|
|
115
115
|
end
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
-
# File-attachment-download policy for +Riffer::Messages::FilePart+ URL sources
|
|
118
|
+
# File-attachment-download policy for +Riffer::Messages::User::FilePart+ URL sources
|
|
119
119
|
class Files
|
|
120
120
|
# Allow file attachments to be downloaded to send to providers.
|
|
121
|
-
attr_reader :allow_downloads #: bool
|
|
121
|
+
attr_reader :allow_downloads #: bool # @dynamic allow_downloads
|
|
122
122
|
# Maximum file size to download before failing.
|
|
123
|
-
attr_reader :max_bytes #: Integer
|
|
123
|
+
attr_reader :max_bytes #: Integer # @dynamic max_bytes
|
|
124
124
|
# Maximum amount of time to spend downloading a file before failing.
|
|
125
|
-
attr_reader :timeout #: Integer
|
|
125
|
+
attr_reader :timeout #: Integer # @dynamic timeout
|
|
126
126
|
# Maximum number of files to include in an individual message.
|
|
127
|
-
attr_reader :max_per_message #: Integer?
|
|
127
|
+
attr_reader :max_per_message #: Integer? # @dynamic max_per_message
|
|
128
128
|
# Execution pattern for downloading files.
|
|
129
|
-
attr_reader :runner #: Riffer::Runner
|
|
129
|
+
attr_reader :runner #: Riffer::Runner # @dynamic runner
|
|
130
130
|
# The object used to fetch a URL source's bytes
|
|
131
|
-
attr_reader :downloader #: untyped
|
|
131
|
+
attr_reader :downloader #: untyped # @dynamic downloader
|
|
132
132
|
|
|
133
133
|
#--
|
|
134
134
|
#: () -> void
|
|
@@ -215,16 +215,16 @@ class Riffer::Config
|
|
|
215
215
|
# and +cache_write+ fall back to the +input+ rate when unset.
|
|
216
216
|
class Rates
|
|
217
217
|
# Input rate per million tokens.
|
|
218
|
-
attr_reader :input #: Float
|
|
218
|
+
attr_reader :input #: Float # @dynamic input
|
|
219
219
|
|
|
220
220
|
# Output rate per million tokens.
|
|
221
|
-
attr_reader :output #: Float
|
|
221
|
+
attr_reader :output #: Float # @dynamic output
|
|
222
222
|
|
|
223
223
|
# Cache-read rate per million tokens.
|
|
224
|
-
attr_reader :cache_read #: Float?
|
|
224
|
+
attr_reader :cache_read #: Float? # @dynamic cache_read
|
|
225
225
|
|
|
226
226
|
# Cache-write rate per million tokens.
|
|
227
|
-
attr_reader :cache_write #: Float?
|
|
227
|
+
attr_reader :cache_write #: Float? # @dynamic cache_write
|
|
228
228
|
|
|
229
229
|
#--
|
|
230
230
|
#: (input: Float, output: Float, ?cache_read: Float?, ?cache_write: Float?) -> void
|
|
@@ -329,34 +329,34 @@ class Riffer::Config
|
|
|
329
329
|
VALID_MESSAGE_ID_STRATEGIES = %i[none uuid uuidv7].freeze
|
|
330
330
|
|
|
331
331
|
# Amazon Bedrock configuration.
|
|
332
|
-
attr_reader :amazon_bedrock #: Riffer::Config::AmazonBedrock
|
|
332
|
+
attr_reader :amazon_bedrock #: Riffer::Config::AmazonBedrock # @dynamic amazon_bedrock
|
|
333
333
|
|
|
334
334
|
# Anthropic configuration.
|
|
335
|
-
attr_reader :anthropic #: Riffer::Config::Anthropic
|
|
335
|
+
attr_reader :anthropic #: Riffer::Config::Anthropic # @dynamic anthropic
|
|
336
336
|
|
|
337
337
|
# Azure OpenAI configuration.
|
|
338
|
-
attr_reader :azure_openai #: Riffer::Config::AzureOpenAI
|
|
338
|
+
attr_reader :azure_openai #: Riffer::Config::AzureOpenAI # @dynamic azure_openai
|
|
339
339
|
|
|
340
340
|
# Google Gemini configuration.
|
|
341
|
-
attr_reader :gemini #: Riffer::Config::Gemini
|
|
341
|
+
attr_reader :gemini #: Riffer::Config::Gemini # @dynamic gemini
|
|
342
342
|
|
|
343
343
|
# OpenAI configuration.
|
|
344
|
-
attr_reader :openai #: Riffer::Config::OpenAI
|
|
344
|
+
attr_reader :openai #: Riffer::Config::OpenAI # @dynamic openai
|
|
345
345
|
|
|
346
346
|
# OpenRouter configuration.
|
|
347
|
-
attr_reader :openrouter #: Riffer::Config::OpenRouter
|
|
347
|
+
attr_reader :openrouter #: Riffer::Config::OpenRouter # @dynamic openrouter
|
|
348
348
|
|
|
349
349
|
# Evals configuration.
|
|
350
|
-
attr_reader :evals #: Riffer::Config::Evals
|
|
350
|
+
attr_reader :evals #: Riffer::Config::Evals # @dynamic evals
|
|
351
351
|
|
|
352
352
|
# MCP configuration. +credentials+ is an optional Proc returning per-run
|
|
353
353
|
# +tools/call+ headers (or +nil+ to deny); +discovery_runner+ runs tool
|
|
354
354
|
# discovery.
|
|
355
|
-
attr_reader :mcp #: Riffer::Config::Mcp
|
|
355
|
+
attr_reader :mcp #: Riffer::Config::Mcp # @dynamic mcp
|
|
356
356
|
|
|
357
357
|
# Global tool runtime configuration (experimental); defaults to
|
|
358
358
|
# <tt>Riffer::Tools::Runtime::Inline.new</tt>.
|
|
359
|
-
attr_reader :tool_runtime #: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc)
|
|
359
|
+
attr_reader :tool_runtime #: (singleton(Riffer::Tools::Runtime) | Riffer::Tools::Runtime | Proc) # @dynamic tool_runtime
|
|
360
360
|
|
|
361
361
|
# Sets the global tool runtime. Raises Riffer::ArgumentError on an invalid
|
|
362
362
|
# value.
|
|
@@ -374,20 +374,20 @@ class Riffer::Config
|
|
|
374
374
|
end
|
|
375
375
|
|
|
376
376
|
# Skills-related global configuration.
|
|
377
|
-
attr_reader :skills #: Riffer::Config::Skills
|
|
377
|
+
attr_reader :skills #: Riffer::Config::Skills # @dynamic skills
|
|
378
378
|
|
|
379
379
|
# Tracing-related global configuration.
|
|
380
|
-
attr_reader :tracing #: Riffer::Config::Tracing
|
|
380
|
+
attr_reader :tracing #: Riffer::Config::Tracing # @dynamic tracing
|
|
381
381
|
|
|
382
|
-
attr_reader :files #: Riffer::Config::Files
|
|
382
|
+
attr_reader :files #: Riffer::Config::Files # @dynamic files
|
|
383
383
|
|
|
384
384
|
# Consumer-configured per-model token pricing.
|
|
385
|
-
attr_reader :pricing #: Riffer::Config::Pricing
|
|
385
|
+
attr_reader :pricing #: Riffer::Config::Pricing # @dynamic pricing
|
|
386
386
|
|
|
387
387
|
# Strategy for auto-generating message ids: +:none+ (default), +:uuid+, or
|
|
388
388
|
# +:uuidv7+. When not +:none+, messages get an +id+ at construction, and
|
|
389
389
|
# seeded messages passed to +Riffer::Agent#generate+ must carry their own.
|
|
390
|
-
attr_reader :message_id_strategy #: Symbol
|
|
390
|
+
attr_reader :message_id_strategy #: Symbol # @dynamic message_id_strategy
|
|
391
391
|
|
|
392
392
|
# Sets the message id strategy. Raises Riffer::ArgumentError unless the value
|
|
393
393
|
# is +:none+, +:uuid+, or +:uuidv7+.
|
|
@@ -404,7 +404,7 @@ class Riffer::Config
|
|
|
404
404
|
# Experimental: when +true+, riffer maintains the +tool_use+ ↔ +tool_result+
|
|
405
405
|
# invariant itself — stripping orphaned exchanges and filling interrupted
|
|
406
406
|
# ones. Defaults to +false+; the surface may change without notice.
|
|
407
|
-
attr_reader :experimental_history_healing #: bool
|
|
407
|
+
attr_reader :experimental_history_healing #: bool # @dynamic experimental_history_healing
|
|
408
408
|
|
|
409
409
|
# Sets the +experimental_history_healing+ flag, coercing boolean-ish values so
|
|
410
410
|
# an env-var +"false"+ (truthy in Ruby) doesn't silently enable healing.
|