activeagent 1.0.0.rc1 → 1.0.1
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/CHANGELOG.md +102 -1
- data/lib/active_agent/providers/_base_provider.rb +94 -82
- data/lib/active_agent/providers/anthropic/_types.rb +2 -2
- data/lib/active_agent/providers/anthropic/options.rb +4 -6
- data/lib/active_agent/providers/anthropic/request.rb +157 -78
- data/lib/active_agent/providers/anthropic/transforms.rb +482 -0
- data/lib/active_agent/providers/anthropic_provider.rb +159 -59
- data/lib/active_agent/providers/common/messages/_types.rb +46 -3
- data/lib/active_agent/providers/common/messages/assistant.rb +20 -4
- data/lib/active_agent/providers/common/responses/base.rb +118 -70
- data/lib/active_agent/providers/common/usage.rb +385 -0
- data/lib/active_agent/providers/concerns/instrumentation.rb +263 -0
- data/lib/active_agent/providers/concerns/previewable.rb +39 -5
- data/lib/active_agent/providers/concerns/tool_choice_clearing.rb +62 -0
- data/lib/active_agent/providers/log_subscriber.rb +64 -246
- data/lib/active_agent/providers/mock_provider.rb +23 -23
- data/lib/active_agent/providers/ollama/chat/request.rb +214 -35
- data/lib/active_agent/providers/ollama/chat/transforms.rb +135 -0
- data/lib/active_agent/providers/ollama/embedding/request.rb +160 -47
- data/lib/active_agent/providers/ollama/embedding/transforms.rb +160 -0
- data/lib/active_agent/providers/ollama_provider.rb +0 -1
- data/lib/active_agent/providers/open_ai/_base.rb +3 -2
- data/lib/active_agent/providers/open_ai/chat/_types.rb +13 -1
- data/lib/active_agent/providers/open_ai/chat/request.rb +132 -186
- data/lib/active_agent/providers/open_ai/chat/transforms.rb +444 -0
- data/lib/active_agent/providers/open_ai/chat_provider.rb +95 -36
- data/lib/active_agent/providers/open_ai/embedding/_types.rb +13 -2
- data/lib/active_agent/providers/open_ai/embedding/request.rb +38 -70
- data/lib/active_agent/providers/open_ai/embedding/transforms.rb +88 -0
- data/lib/active_agent/providers/open_ai/responses/_types.rb +1 -7
- data/lib/active_agent/providers/open_ai/responses/request.rb +116 -135
- data/lib/active_agent/providers/open_ai/responses/transforms.rb +363 -0
- data/lib/active_agent/providers/open_ai/responses_provider.rb +115 -30
- data/lib/active_agent/providers/open_ai_provider.rb +0 -3
- data/lib/active_agent/providers/open_router/_types.rb +27 -1
- data/lib/active_agent/providers/open_router/options.rb +49 -1
- data/lib/active_agent/providers/open_router/request.rb +252 -66
- data/lib/active_agent/providers/open_router/requests/_types.rb +0 -1
- data/lib/active_agent/providers/open_router/requests/messages/_types.rb +37 -40
- data/lib/active_agent/providers/open_router/requests/messages/content/file.rb +19 -3
- data/lib/active_agent/providers/open_router/requests/messages/content/files/details.rb +15 -4
- data/lib/active_agent/providers/open_router/requests/plugin.rb +19 -3
- data/lib/active_agent/providers/open_router/requests/plugins/pdf_config.rb +30 -8
- data/lib/active_agent/providers/open_router/requests/prediction.rb +17 -0
- data/lib/active_agent/providers/open_router/requests/provider_preferences/max_price.rb +41 -7
- data/lib/active_agent/providers/open_router/requests/provider_preferences.rb +60 -19
- data/lib/active_agent/providers/open_router/requests/response_format.rb +30 -2
- data/lib/active_agent/providers/open_router/transforms.rb +164 -0
- data/lib/active_agent/providers/open_router_provider.rb +23 -0
- data/lib/active_agent/version.rb +1 -1
- metadata +17 -160
- data/lib/active_agent/generation_provider/open_router/types.rb +0 -505
- data/lib/active_agent/generation_provider/xai_provider.rb +0 -144
- data/lib/active_agent/providers/anthropic/requests/_types.rb +0 -190
- data/lib/active_agent/providers/anthropic/requests/container_params.rb +0 -19
- data/lib/active_agent/providers/anthropic/requests/content/base.rb +0 -21
- data/lib/active_agent/providers/anthropic/requests/content/sources/base.rb +0 -22
- data/lib/active_agent/providers/anthropic/requests/context_management_config.rb +0 -18
- data/lib/active_agent/providers/anthropic/requests/messages/_types.rb +0 -189
- data/lib/active_agent/providers/anthropic/requests/messages/assistant.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/base.rb +0 -63
- data/lib/active_agent/providers/anthropic/requests/messages/content/_types.rb +0 -143
- data/lib/active_agent/providers/anthropic/requests/messages/content/base.rb +0 -21
- data/lib/active_agent/providers/anthropic/requests/messages/content/document.rb +0 -26
- data/lib/active_agent/providers/anthropic/requests/messages/content/image.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/redacted_thinking.rb +0 -21
- data/lib/active_agent/providers/anthropic/requests/messages/content/search_result.rb +0 -27
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/_types.rb +0 -171
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/base.rb +0 -22
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_base64.rb +0 -25
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_file.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_text.rb +0 -25
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/document_url.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_base64.rb +0 -27
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_file.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/sources/image_url.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/text.rb +0 -22
- data/lib/active_agent/providers/anthropic/requests/messages/content/thinking.rb +0 -23
- data/lib/active_agent/providers/anthropic/requests/messages/content/tool_result.rb +0 -24
- data/lib/active_agent/providers/anthropic/requests/messages/content/tool_use.rb +0 -28
- data/lib/active_agent/providers/anthropic/requests/messages/user.rb +0 -21
- data/lib/active_agent/providers/anthropic/requests/metadata.rb +0 -18
- data/lib/active_agent/providers/anthropic/requests/response_format.rb +0 -22
- data/lib/active_agent/providers/anthropic/requests/thinking_config/_types.rb +0 -60
- data/lib/active_agent/providers/anthropic/requests/thinking_config/base.rb +0 -20
- data/lib/active_agent/providers/anthropic/requests/thinking_config/disabled.rb +0 -16
- data/lib/active_agent/providers/anthropic/requests/thinking_config/enabled.rb +0 -20
- data/lib/active_agent/providers/anthropic/requests/tool_choice/_types.rb +0 -78
- data/lib/active_agent/providers/anthropic/requests/tool_choice/any.rb +0 -17
- data/lib/active_agent/providers/anthropic/requests/tool_choice/auto.rb +0 -17
- data/lib/active_agent/providers/anthropic/requests/tool_choice/base.rb +0 -20
- data/lib/active_agent/providers/anthropic/requests/tool_choice/none.rb +0 -16
- data/lib/active_agent/providers/anthropic/requests/tool_choice/tool.rb +0 -20
- data/lib/active_agent/providers/ollama/chat/requests/_types.rb +0 -3
- data/lib/active_agent/providers/ollama/chat/requests/messages/_types.rb +0 -116
- data/lib/active_agent/providers/ollama/chat/requests/messages/assistant.rb +0 -19
- data/lib/active_agent/providers/ollama/chat/requests/messages/user.rb +0 -19
- data/lib/active_agent/providers/ollama/embedding/requests/_types.rb +0 -83
- data/lib/active_agent/providers/ollama/embedding/requests/options.rb +0 -104
- data/lib/active_agent/providers/open_ai/chat/requests/_types.rb +0 -229
- data/lib/active_agent/providers/open_ai/chat/requests/audio.rb +0 -24
- data/lib/active_agent/providers/open_ai/chat/requests/messages/_types.rb +0 -123
- data/lib/active_agent/providers/open_ai/chat/requests/messages/assistant.rb +0 -42
- data/lib/active_agent/providers/open_ai/chat/requests/messages/base.rb +0 -78
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/_types.rb +0 -133
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/audio.rb +0 -35
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/base.rb +0 -24
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/file.rb +0 -26
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/_types.rb +0 -60
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/files/details.rb +0 -41
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/image.rb +0 -37
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/refusal.rb +0 -25
- data/lib/active_agent/providers/open_ai/chat/requests/messages/content/text.rb +0 -25
- data/lib/active_agent/providers/open_ai/chat/requests/messages/developer.rb +0 -25
- data/lib/active_agent/providers/open_ai/chat/requests/messages/function.rb +0 -25
- data/lib/active_agent/providers/open_ai/chat/requests/messages/system.rb +0 -25
- data/lib/active_agent/providers/open_ai/chat/requests/messages/tool.rb +0 -26
- data/lib/active_agent/providers/open_ai/chat/requests/messages/user.rb +0 -32
- data/lib/active_agent/providers/open_ai/chat/requests/prediction.rb +0 -46
- data/lib/active_agent/providers/open_ai/chat/requests/response_format.rb +0 -53
- data/lib/active_agent/providers/open_ai/chat/requests/stream_options.rb +0 -24
- data/lib/active_agent/providers/open_ai/chat/requests/tool_choice.rb +0 -26
- data/lib/active_agent/providers/open_ai/chat/requests/tools/_types.rb +0 -5
- data/lib/active_agent/providers/open_ai/chat/requests/tools/base.rb +0 -22
- data/lib/active_agent/providers/open_ai/chat/requests/tools/custom_tool.rb +0 -41
- data/lib/active_agent/providers/open_ai/chat/requests/tools/function_tool.rb +0 -51
- data/lib/active_agent/providers/open_ai/chat/requests/web_search_options.rb +0 -45
- data/lib/active_agent/providers/open_ai/embedding/requests/_types.rb +0 -49
- data/lib/active_agent/providers/open_ai/responses/requests/_types.rb +0 -231
- data/lib/active_agent/providers/open_ai/responses/requests/conversation.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/_types.rb +0 -264
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/assistant_message.rb +0 -22
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/base.rb +0 -89
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/code_interpreter_tool_call.rb +0 -30
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/computer_tool_call_output.rb +0 -33
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/_types.rb +0 -207
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/base.rb +0 -22
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_audio.rb +0 -26
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_file.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_image.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/content/input_text.rb +0 -25
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/custom_tool_call_output.rb +0 -27
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/developer_message.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/file_search_tool_call.rb +0 -25
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_call_output.rb +0 -32
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/function_tool_call.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/image_gen_tool_call.rb +0 -27
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/input_message.rb +0 -31
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/item_reference.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call.rb +0 -26
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/local_shell_tool_call_output.rb +0 -33
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_request.rb +0 -30
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_approval_response.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_list_tools.rb +0 -29
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/mcp_tool_call.rb +0 -35
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/output_message.rb +0 -35
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/reasoning.rb +0 -33
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/system_message.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_call_base.rb +0 -27
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/tool_message.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/user_message.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/inputs/web_search_tool_call.rb +0 -24
- data/lib/active_agent/providers/open_ai/responses/requests/prompt_reference.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/reasoning.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/stream_options.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/text/_types.rb +0 -89
- data/lib/active_agent/providers/open_ai/responses/requests/text/base.rb +0 -22
- data/lib/active_agent/providers/open_ai/responses/requests/text/json_object.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/text/json_schema.rb +0 -48
- data/lib/active_agent/providers/open_ai/responses/requests/text/plain.rb +0 -20
- data/lib/active_agent/providers/open_ai/responses/requests/text.rb +0 -41
- data/lib/active_agent/providers/open_ai/responses/requests/tool_choice.rb +0 -26
- data/lib/active_agent/providers/open_ai/responses/requests/tools/_types.rb +0 -112
- data/lib/active_agent/providers/open_ai/responses/requests/tools/base.rb +0 -25
- data/lib/active_agent/providers/open_ai/responses/requests/tools/code_interpreter_tool.rb +0 -23
- data/lib/active_agent/providers/open_ai/responses/requests/tools/computer_tool.rb +0 -27
- data/lib/active_agent/providers/open_ai/responses/requests/tools/custom_tool.rb +0 -28
- data/lib/active_agent/providers/open_ai/responses/requests/tools/file_search_tool.rb +0 -27
- data/lib/active_agent/providers/open_ai/responses/requests/tools/function_tool.rb +0 -29
- data/lib/active_agent/providers/open_ai/responses/requests/tools/image_generation_tool.rb +0 -37
- data/lib/active_agent/providers/open_ai/responses/requests/tools/local_shell_tool.rb +0 -21
- data/lib/active_agent/providers/open_ai/responses/requests/tools/mcp_tool.rb +0 -41
- data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_preview_tool.rb +0 -24
- data/lib/active_agent/providers/open_ai/responses/requests/tools/web_search_tool.rb +0 -25
- data/lib/active_agent/providers/open_ai/schema.yml +0 -65937
- data/lib/active_agent/providers/open_router/requests/message.rb +0 -1
- data/lib/active_agent/providers/open_router/requests/messages/assistant.rb +0 -20
- data/lib/active_agent/providers/open_router/requests/messages/user.rb +0 -30
|
@@ -4,8 +4,25 @@ module ActiveAgent
|
|
|
4
4
|
module Providers
|
|
5
5
|
module OpenRouter
|
|
6
6
|
module Requests
|
|
7
|
+
# Prediction configuration for prefilling responses
|
|
8
|
+
#
|
|
9
|
+
# Allows prefilling the start of the model's response. When provided,
|
|
10
|
+
# the model continues from this predicted content.
|
|
11
|
+
#
|
|
12
|
+
# @example Content prediction
|
|
13
|
+
# prediction = Prediction.new(
|
|
14
|
+
# type: 'content',
|
|
15
|
+
# content: 'Once upon a time'
|
|
16
|
+
# )
|
|
17
|
+
#
|
|
18
|
+
# @see https://platform.openai.com/docs/api-reference/chat/create#chat-create-prediction
|
|
7
19
|
class Prediction < Common::BaseModel
|
|
20
|
+
# @!attribute type
|
|
21
|
+
# @return [String] prediction type (currently only 'content' is supported)
|
|
8
22
|
attribute :type, :string
|
|
23
|
+
|
|
24
|
+
# @!attribute content
|
|
25
|
+
# @return [String] predicted content to prefill the response
|
|
9
26
|
attribute :content, :string
|
|
10
27
|
|
|
11
28
|
validates :type, inclusion: { in: %w[content] }, allow_nil: true
|
|
@@ -5,14 +5,48 @@ module ActiveAgent
|
|
|
5
5
|
module OpenRouter
|
|
6
6
|
module Requests
|
|
7
7
|
# Maximum price configuration for provider routing
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
#
|
|
9
|
+
# Specifies maximum acceptable prices (in USD per million tokens or per
|
|
10
|
+
# operation) for filtering providers. OpenRouter will only route to
|
|
11
|
+
# providers within these price constraints.
|
|
12
|
+
#
|
|
13
|
+
# @example Setting prompt and completion limits
|
|
14
|
+
# max_price = MaxPrice.new(
|
|
15
|
+
# prompt: 0.01, # $0.01 per million input tokens
|
|
16
|
+
# completion: 0.03 # $0.03 per million output tokens
|
|
17
|
+
# )
|
|
18
|
+
#
|
|
19
|
+
# @example Setting all constraints
|
|
20
|
+
# max_price = MaxPrice.new(
|
|
21
|
+
# prompt: 0.01,
|
|
22
|
+
# completion: 0.03,
|
|
23
|
+
# image: 0.001,
|
|
24
|
+
# audio: 0.002,
|
|
25
|
+
# request: 0.0001
|
|
26
|
+
# )
|
|
27
|
+
#
|
|
28
|
+
# @see https://openrouter.ai/docs/provider-routing OpenRouter Provider Routing
|
|
29
|
+
# @see ProviderPreferences
|
|
10
30
|
class MaxPrice < Common::BaseModel
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
attribute :
|
|
14
|
-
|
|
15
|
-
|
|
31
|
+
# @!attribute prompt
|
|
32
|
+
# @return [Float, nil] maximum price per million prompt tokens (input)
|
|
33
|
+
attribute :prompt, :float
|
|
34
|
+
|
|
35
|
+
# @!attribute completion
|
|
36
|
+
# @return [Float, nil] maximum price per million completion tokens (output)
|
|
37
|
+
attribute :completion, :float
|
|
38
|
+
|
|
39
|
+
# @!attribute image
|
|
40
|
+
# @return [Float, nil] maximum price per image operation
|
|
41
|
+
attribute :image, :float
|
|
42
|
+
|
|
43
|
+
# @!attribute audio
|
|
44
|
+
# @return [Float, nil] maximum price per audio operation
|
|
45
|
+
attribute :audio, :float
|
|
46
|
+
|
|
47
|
+
# @!attribute request
|
|
48
|
+
# @return [Float, nil] maximum price per request
|
|
49
|
+
attribute :request, :float
|
|
16
50
|
|
|
17
51
|
validates :prompt, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
|
18
52
|
validates :completion, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
|
@@ -7,44 +7,85 @@ module ActiveAgent
|
|
|
7
7
|
module OpenRouter
|
|
8
8
|
module Requests
|
|
9
9
|
# Provider preferences for routing requests to specific providers
|
|
10
|
-
#
|
|
10
|
+
#
|
|
11
|
+
# Controls how OpenRouter selects and routes requests to underlying model
|
|
12
|
+
# providers. Enables filtering by parameters, cost constraints, privacy
|
|
13
|
+
# settings, and provider-specific preferences.
|
|
14
|
+
#
|
|
15
|
+
# @example Basic provider routing
|
|
16
|
+
# prefs = ProviderPreferences.new(
|
|
17
|
+
# require_parameters: true,
|
|
18
|
+
# allow_fallbacks: false
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# @example Privacy-focused routing
|
|
22
|
+
# prefs = ProviderPreferences.new(
|
|
23
|
+
# data_collection: 'deny',
|
|
24
|
+
# zdr: true
|
|
25
|
+
# )
|
|
26
|
+
#
|
|
27
|
+
# @example Cost-optimized routing
|
|
28
|
+
# prefs = ProviderPreferences.new(
|
|
29
|
+
# sort: 'price',
|
|
30
|
+
# max_price: { prompt: 0.01, completion: 0.03 }
|
|
31
|
+
# )
|
|
32
|
+
#
|
|
33
|
+
# @example Provider ordering
|
|
34
|
+
# prefs = ProviderPreferences.new(
|
|
35
|
+
# order: ['OpenAI', 'Anthropic'],
|
|
36
|
+
# ignore: ['Together']
|
|
37
|
+
# )
|
|
38
|
+
#
|
|
39
|
+
# @see https://openrouter.ai/docs/provider-routing OpenRouter Provider Routing
|
|
40
|
+
# @see MaxPrice
|
|
11
41
|
class ProviderPreferences < Common::BaseModel
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
42
|
+
# @!attribute allow_fallbacks
|
|
43
|
+
# @return [Boolean, nil] whether to allow backup providers when primary is unavailable
|
|
44
|
+
# - true: (default) use next best provider when primary unavailable
|
|
45
|
+
# - false: only use primary/custom provider, return error if unavailable
|
|
15
46
|
attribute :allow_fallbacks, :boolean
|
|
16
47
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
48
|
+
# @!attribute require_parameters
|
|
49
|
+
# @return [Boolean, nil] whether to filter to providers supporting all parameters
|
|
50
|
+
# - true: only use providers that support all provided parameters
|
|
51
|
+
# - false: providers receive only the parameters they support
|
|
19
52
|
attribute :require_parameters, :boolean
|
|
20
53
|
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
54
|
+
# @!attribute data_collection
|
|
55
|
+
# @return [String, nil] data collection preference
|
|
56
|
+
# - 'allow': (default) allow providers which store/train on user data
|
|
57
|
+
# - 'deny': only use providers that don't collect user data
|
|
24
58
|
attribute :data_collection, :string
|
|
25
59
|
|
|
26
|
-
#
|
|
60
|
+
# @!attribute zdr
|
|
61
|
+
# @return [Boolean, nil] zero data retention mode (stricter privacy)
|
|
27
62
|
attribute :zdr, :boolean
|
|
28
63
|
|
|
29
|
-
#
|
|
64
|
+
# @!attribute order
|
|
65
|
+
# @return [Array<String>] ordered list of provider slugs to try in sequence
|
|
30
66
|
attribute :order, default: -> { [] }
|
|
31
67
|
|
|
32
|
-
#
|
|
68
|
+
# @!attribute only
|
|
69
|
+
# @return [Array<String>] allowlist of provider slugs (merged with account settings)
|
|
33
70
|
attribute :only, default: -> { [] }
|
|
34
71
|
|
|
35
|
-
#
|
|
72
|
+
# @!attribute ignore
|
|
73
|
+
# @return [Array<String>] blocklist of provider slugs (merged with account settings)
|
|
36
74
|
attribute :ignore, default: -> { [] }
|
|
37
75
|
|
|
38
|
-
#
|
|
39
|
-
#
|
|
76
|
+
# @!attribute quantizations
|
|
77
|
+
# @return [Array<String>] quantization levels to filter providers by
|
|
78
|
+
# Options: int4, int8, fp4, fp6, fp8, fp16, bf16, fp32, unknown
|
|
40
79
|
attribute :quantizations, default: -> { [] }
|
|
41
80
|
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
81
|
+
# @!attribute sort
|
|
82
|
+
# @return [String, nil] sorting strategy when order not specified
|
|
83
|
+
# Options: price, throughput, latency
|
|
84
|
+
# Note: disables load balancing when set
|
|
45
85
|
attribute :sort, :string
|
|
46
86
|
|
|
47
|
-
#
|
|
87
|
+
# @!attribute max_price
|
|
88
|
+
# @return [MaxPrice, nil] maximum price constraints per token/operation
|
|
48
89
|
attribute :max_price, MaxPriceType.new
|
|
49
90
|
|
|
50
91
|
# Validations matching the schema
|
|
@@ -4,11 +4,39 @@ module ActiveAgent
|
|
|
4
4
|
module Providers
|
|
5
5
|
module OpenRouter
|
|
6
6
|
module Requests
|
|
7
|
+
# Response format configuration for structured output
|
|
8
|
+
#
|
|
9
|
+
# Enables JSON-formatted responses using OpenAI's structured output format.
|
|
10
|
+
# When using structured output, OpenRouter automatically sets
|
|
11
|
+
# provider.require_parameters=true to route to compatible models.
|
|
12
|
+
#
|
|
13
|
+
# @example JSON object format
|
|
14
|
+
# format = ResponseFormat.new(type: 'json_object')
|
|
15
|
+
#
|
|
16
|
+
# @example JSON schema format
|
|
17
|
+
# format = ResponseFormat.new(
|
|
18
|
+
# type: 'json_schema',
|
|
19
|
+
# json_schema: {
|
|
20
|
+
# name: 'user_profile',
|
|
21
|
+
# description: 'A user profile',
|
|
22
|
+
# schema: { type: 'object', properties: { name: { type: 'string' } } },
|
|
23
|
+
# strict: true
|
|
24
|
+
# }
|
|
25
|
+
# )
|
|
26
|
+
#
|
|
27
|
+
# @see https://openrouter.ai/docs/structured-outputs OpenRouter Structured Outputs
|
|
28
|
+
# @see https://platform.openai.com/docs/guides/structured-outputs OpenAI Structured Outputs
|
|
7
29
|
class ResponseFormat < Common::BaseModel
|
|
8
|
-
#
|
|
30
|
+
# @!attribute type
|
|
31
|
+
# @return [String] response format type ('json_object' or 'json_schema')
|
|
9
32
|
attribute :type, :string
|
|
10
33
|
|
|
11
|
-
#
|
|
34
|
+
# @!attribute json_schema
|
|
35
|
+
# @return [Hash, nil] JSON schema configuration (required when type is 'json_schema')
|
|
36
|
+
# @option json_schema [String] :name schema name (max 64 chars, alphanumeric/underscore/dash)
|
|
37
|
+
# @option json_schema [String] :description schema description
|
|
38
|
+
# @option json_schema [Hash] :schema JSON schema definition
|
|
39
|
+
# @option json_schema [Boolean] :strict whether to enforce strict schema adherence
|
|
12
40
|
attribute :json_schema # Hash with name, description, schema, strict
|
|
13
41
|
|
|
14
42
|
validates :type, inclusion: { in: %w[json_object json_schema] }, allow_nil: true
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/hash/keys"
|
|
4
|
+
require_relative "../open_ai/chat/transforms"
|
|
5
|
+
|
|
6
|
+
module ActiveAgent
|
|
7
|
+
module Providers
|
|
8
|
+
module OpenRouter
|
|
9
|
+
# Provides transformation methods for normalizing OpenRouter parameters
|
|
10
|
+
# to work with OpenAI gem's native format plus OpenRouter extensions
|
|
11
|
+
#
|
|
12
|
+
# Leverages OpenAI::Chat::Transforms for base message normalization while
|
|
13
|
+
# adding handling for OpenRouter-specific parameters like plugins, provider
|
|
14
|
+
# preferences, and model fallbacks.
|
|
15
|
+
module Transforms
|
|
16
|
+
class << self
|
|
17
|
+
# Converts gem model object to hash via JSON round-trip
|
|
18
|
+
#
|
|
19
|
+
# @param gem_object [Object]
|
|
20
|
+
# @return [Hash] with symbolized keys
|
|
21
|
+
def gem_to_hash(gem_object)
|
|
22
|
+
OpenAI::Chat::Transforms.gem_to_hash(gem_object)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Normalizes all request parameters for OpenRouter API
|
|
26
|
+
#
|
|
27
|
+
# Handles both OpenAI-compatible parameters and OpenRouter-specific extensions.
|
|
28
|
+
# OpenRouter-specific params (plugins, provider, transforms, models, route) are
|
|
29
|
+
# extracted and returned separately for manual serialization.
|
|
30
|
+
#
|
|
31
|
+
# @param params [Hash]
|
|
32
|
+
# @return [Array<Hash, Hash>] tuple of [openai_params, openrouter_params]
|
|
33
|
+
def normalize_params(params)
|
|
34
|
+
params = params.dup
|
|
35
|
+
|
|
36
|
+
# Extract OpenRouter-specific parameters
|
|
37
|
+
openrouter_params = {}
|
|
38
|
+
openrouter_params[:plugins] = params.delete(:plugins) if params.key?(:plugins)
|
|
39
|
+
openrouter_params[:provider] = params.delete(:provider) if params.key?(:provider)
|
|
40
|
+
openrouter_params[:transforms] = params.delete(:transforms) if params.key?(:transforms)
|
|
41
|
+
openrouter_params[:models] = params.delete(:models) if params.key?(:models)
|
|
42
|
+
openrouter_params[:route] = params.delete(:route) if params.key?(:route)
|
|
43
|
+
|
|
44
|
+
# Extract OpenRouter-specific sampling parameters not in OpenAI
|
|
45
|
+
openrouter_params[:top_k] = params.delete(:top_k) if params.key?(:top_k)
|
|
46
|
+
openrouter_params[:min_p] = params.delete(:min_p) if params.key?(:min_p)
|
|
47
|
+
openrouter_params[:top_a] = params.delete(:top_a) if params.key?(:top_a)
|
|
48
|
+
openrouter_params[:repetition_penalty] = params.delete(:repetition_penalty) if params.key?(:repetition_penalty)
|
|
49
|
+
|
|
50
|
+
# Handle response_format special logic for OpenRouter
|
|
51
|
+
# OpenRouter requires provider.require_parameters=true for structured output
|
|
52
|
+
if params[:response_format]
|
|
53
|
+
response_format = params[:response_format]
|
|
54
|
+
response_format_hash = response_format.is_a?(Hash) ? response_format : { type: response_format }
|
|
55
|
+
|
|
56
|
+
if %i[json_object json_schema].include?(response_format_hash[:type].to_sym)
|
|
57
|
+
openrouter_params[:provider] ||= {}
|
|
58
|
+
openrouter_params[:provider][:require_parameters] = true
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Use OpenAI transforms for the base parameters
|
|
63
|
+
openai_params = OpenAI::Chat::Transforms.normalize_params(params)
|
|
64
|
+
|
|
65
|
+
# Override tool_choice normalization for OpenRouter's "any" vs "required" difference
|
|
66
|
+
if openai_params[:tool_choice]
|
|
67
|
+
openai_params[:tool_choice] = normalize_tool_choice(openai_params[:tool_choice])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
[ openai_params, openrouter_params ]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Normalizes tools using OpenAI transforms
|
|
74
|
+
#
|
|
75
|
+
# @param tools [Array<Hash>]
|
|
76
|
+
# @return [Array<Hash>]
|
|
77
|
+
def normalize_tools(tools)
|
|
78
|
+
OpenAI::Chat::Transforms.normalize_tools(tools)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Normalizes tool_choice for OpenRouter API differences
|
|
82
|
+
#
|
|
83
|
+
# OpenRouter uses "any" instead of OpenAI's "required" for forcing tool use.
|
|
84
|
+
# Converts common format to OpenRouter-specific format:
|
|
85
|
+
# - "required" (common) → "any" (OpenRouter)
|
|
86
|
+
# - Everything else delegates to OpenAI transforms
|
|
87
|
+
#
|
|
88
|
+
# @param tool_choice [String, Hash, Symbol]
|
|
89
|
+
# @return [String, Hash, Symbol]
|
|
90
|
+
def normalize_tool_choice(tool_choice)
|
|
91
|
+
# Convert "required" to OpenRouter's "any"
|
|
92
|
+
return "any" if tool_choice.to_s == "required"
|
|
93
|
+
|
|
94
|
+
# For everything else, use OpenAI transforms
|
|
95
|
+
OpenAI::Chat::Transforms.normalize_tool_choice(tool_choice)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Normalizes messages using OpenAI transforms
|
|
99
|
+
#
|
|
100
|
+
# @param messages [Array, String, Hash, nil]
|
|
101
|
+
# @return [Array<OpenAI::Models::Chat::ChatCompletionMessageParam>, nil]
|
|
102
|
+
def normalize_messages(messages)
|
|
103
|
+
OpenAI::Chat::Transforms.normalize_messages(messages)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Normalizes response_format for OpenRouter
|
|
107
|
+
#
|
|
108
|
+
# Delegates to OpenAI transforms. The special handling for structured output
|
|
109
|
+
# (setting provider.require_parameters=true) is handled in normalize_params.
|
|
110
|
+
#
|
|
111
|
+
# @param format [Hash, Symbol, String]
|
|
112
|
+
# @return [Hash]
|
|
113
|
+
def normalize_response_format(format)
|
|
114
|
+
OpenAI::Chat::Transforms.normalize_response_format(format)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Cleans up serialized request for API submission
|
|
118
|
+
#
|
|
119
|
+
# Merges OpenAI-compatible params with OpenRouter-specific params.
|
|
120
|
+
#
|
|
121
|
+
# @param openai_hash [Hash] serialized OpenAI request
|
|
122
|
+
# @param openrouter_params [Hash] OpenRouter-specific parameters
|
|
123
|
+
# @param defaults [Hash] default values to remove
|
|
124
|
+
# @param gem_object [Object] original gem object
|
|
125
|
+
# @return [Hash] cleaned and merged request hash
|
|
126
|
+
def cleanup_serialized_request(openai_hash, openrouter_params, defaults, gem_object)
|
|
127
|
+
# Start with OpenAI cleanup
|
|
128
|
+
cleaned = OpenAI::Chat::Transforms.cleanup_serialized_request(openai_hash, defaults, gem_object)
|
|
129
|
+
|
|
130
|
+
# Merge OpenRouter-specific params, but skip default values
|
|
131
|
+
openrouter_params.each do |key, value|
|
|
132
|
+
# Skip if value is nil, empty, or matches the default
|
|
133
|
+
next if value.nil?
|
|
134
|
+
next if value.respond_to?(:empty?) && value.empty?
|
|
135
|
+
next if defaults.key?(key) && defaults[key] == value
|
|
136
|
+
|
|
137
|
+
cleaned[key] = serialize_openrouter_param(key, value)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
cleaned
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Serializes OpenRouter-specific parameters
|
|
144
|
+
#
|
|
145
|
+
# @param key [Symbol]
|
|
146
|
+
# @param value [Object]
|
|
147
|
+
# @return [Object] serialized value
|
|
148
|
+
def serialize_openrouter_param(key, value)
|
|
149
|
+
case key
|
|
150
|
+
when :provider
|
|
151
|
+
# Serialize provider preferences object
|
|
152
|
+
value.respond_to?(:serialize) ? value.serialize : value
|
|
153
|
+
when :plugins
|
|
154
|
+
# Serialize plugins array
|
|
155
|
+
value.respond_to?(:map) ? value.map { |p| p.respond_to?(:serialize) ? p.serialize : p } : value
|
|
156
|
+
else
|
|
157
|
+
value
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -33,6 +33,20 @@ module ActiveAgent
|
|
|
33
33
|
|
|
34
34
|
protected
|
|
35
35
|
|
|
36
|
+
# @see BaseProvider#prepare_prompt_request
|
|
37
|
+
# @return [Request]
|
|
38
|
+
def prepare_prompt_request
|
|
39
|
+
prepare_prompt_request_tools
|
|
40
|
+
super
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns true if tool_choice == "any" (OpenRouter's equivalent of "required").
|
|
44
|
+
#
|
|
45
|
+
# @return [Boolean]
|
|
46
|
+
def tool_choice_forces_required?
|
|
47
|
+
request.tool_choice == "any"
|
|
48
|
+
end
|
|
49
|
+
|
|
36
50
|
# Merges streaming delta into the message with role cleanup.
|
|
37
51
|
#
|
|
38
52
|
# Overrides parent to handle OpenRouter's role copying behavior which duplicates
|
|
@@ -48,6 +62,15 @@ module ActiveAgent
|
|
|
48
62
|
|
|
49
63
|
hash_merge_delta(message, delta)
|
|
50
64
|
end
|
|
65
|
+
|
|
66
|
+
# @see BaseProvider#api_response_normalize
|
|
67
|
+
# @param api_response [OpenAI::Models::ChatCompletion]
|
|
68
|
+
# @return [Hash] normalized response hash
|
|
69
|
+
def api_response_normalize(api_response)
|
|
70
|
+
return api_response unless api_response
|
|
71
|
+
|
|
72
|
+
OpenAI::Chat::Transforms.gem_to_hash(api_response)
|
|
73
|
+
end
|
|
51
74
|
end
|
|
52
75
|
end
|
|
53
76
|
end
|
data/lib/active_agent/version.rb
CHANGED