open_router_enhanced 1.0.0 → 1.1.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.
@@ -95,17 +95,20 @@ module OpenRouter
95
95
  # @param model [String|Array] Model identifier, or array of model identifiers if you want to fallback to the next model in case of failure
96
96
  # @param providers [Array<String>] Optional array of provider identifiers, ordered by priority
97
97
  # @param transforms [Array<String>] Optional array of strings that tell OpenRouter to apply a series of transformations to the prompt before sending it to the model. Transformations are applied in-order
98
+ # @param plugins [Array<Hash>] Optional array of plugin hashes like [{id: "response-healing"}]. Available plugins: response-healing, web-search, pdf-inputs
98
99
  # @param tools [Array<Tool>] Optional array of Tool objects or tool definition hashes for function calling
99
100
  # @param tool_choice [String|Hash] Optional tool choice: "auto", "none", "required", or specific tool selection
100
101
  # @param response_format [Hash] Optional response format for structured outputs
102
+ # @param prediction [Hash] Optional predicted output for latency reduction, e.g. {type: "content", content: "predicted text"}
101
103
  # @param extras [Hash] Optional hash of model-specific parameters to send to the OpenRouter API
102
104
  # @param stream [Proc, nil] Optional callable object for streaming
103
105
  # @return [Response] The completion response wrapped in a Response object.
104
- def complete(messages, model: "openrouter/auto", providers: [], transforms: [], tools: [], tool_choice: nil,
105
- response_format: nil, force_structured_output: nil, extras: {}, stream: nil)
106
- parameters = prepare_base_parameters(messages, model, providers, transforms, stream, extras)
106
+ def complete(messages, model: "openrouter/auto", providers: [], transforms: [], plugins: [], tools: [], tool_choice: nil,
107
+ response_format: nil, force_structured_output: nil, prediction: nil, extras: {}, stream: nil)
108
+ parameters = prepare_base_parameters(messages, model, providers, transforms, plugins, prediction, stream, extras)
107
109
  forced_extraction = configure_tools_and_structured_outputs!(parameters, model, tools, tool_choice,
108
110
  response_format, force_structured_output)
111
+ configure_plugins!(parameters, response_format, stream)
109
112
  validate_vision_support(model, messages)
110
113
 
111
114
  # Trigger before_request callbacks
@@ -267,12 +270,14 @@ module OpenRouter
267
270
  private
268
271
 
269
272
  # Prepare the base parameters for the API request
270
- def prepare_base_parameters(messages, model, providers, transforms, stream, extras)
273
+ def prepare_base_parameters(messages, model, providers, transforms, plugins, prediction, stream, extras)
271
274
  parameters = { messages: messages.dup }
272
275
 
273
276
  configure_model_parameter!(parameters, model)
274
277
  configure_provider_parameter!(parameters, providers)
275
278
  configure_transforms_parameter!(parameters, transforms)
279
+ configure_plugins_parameter!(parameters, plugins)
280
+ configure_prediction_parameter!(parameters, prediction)
276
281
  configure_stream_parameter!(parameters, stream)
277
282
 
278
283
  parameters.merge!(extras)
@@ -299,11 +304,52 @@ module OpenRouter
299
304
  parameters[:transforms] = transforms if transforms.any?
300
305
  end
301
306
 
307
+ # Configure the plugins parameter if plugins are specified
308
+ def configure_plugins_parameter!(parameters, plugins)
309
+ parameters[:plugins] = plugins.dup if plugins.any?
310
+ end
311
+
312
+ # Configure the prediction parameter for latency optimization
313
+ def configure_prediction_parameter!(parameters, prediction)
314
+ parameters[:prediction] = prediction if prediction
315
+ end
316
+
302
317
  # Configure the stream parameter if streaming is enabled
303
318
  def configure_stream_parameter!(parameters, stream)
304
319
  parameters[:stream] = stream if stream
305
320
  end
306
321
 
322
+ # Auto-add response-healing plugin when using structured outputs (non-streaming only)
323
+ # This leverages OpenRouter's native JSON healing for better reliability
324
+ def configure_plugins!(parameters, response_format, stream)
325
+ return unless should_auto_add_healing?(response_format, stream)
326
+
327
+ parameters[:plugins] ||= []
328
+
329
+ # Don't duplicate if user already specified response-healing
330
+ return if parameters[:plugins].any? { |p| p[:id] == "response-healing" || p["id"] == "response-healing" }
331
+
332
+ parameters[:plugins] << { id: "response-healing" }
333
+ end
334
+
335
+ # Determine if we should auto-add the response-healing plugin
336
+ def should_auto_add_healing?(response_format, stream)
337
+ return false unless configuration.auto_native_healing
338
+ return false if stream # Response healing doesn't work with streaming
339
+ return false unless response_format
340
+
341
+ # Check if response_format is a structured output type
342
+ case response_format
343
+ when OpenRouter::Schema
344
+ true
345
+ when Hash
346
+ type = response_format[:type] || response_format["type"]
347
+ %w[json_schema json_object].include?(type.to_s)
348
+ else
349
+ false
350
+ end
351
+ end
352
+
307
353
  # Configure tools and structured outputs, returning forced_extraction flag
308
354
  def configure_tools_and_structured_outputs!(parameters, model, tools, tool_choice, response_format,
309
355
  force_structured_output)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenRouter
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/open_router.rb CHANGED
@@ -38,6 +38,9 @@ module OpenRouter
38
38
  # Healing configuration
39
39
  attr_accessor :auto_heal_responses, :healer_model, :max_heal_attempts
40
40
 
41
+ # Native OpenRouter response healing (server-side)
42
+ attr_accessor :auto_native_healing
43
+
41
44
  # Cache configuration
42
45
  attr_accessor :cache_ttl
43
46
 
@@ -73,6 +76,9 @@ module OpenRouter
73
76
  self.healer_model = "openai/gpt-4o-mini"
74
77
  self.max_heal_attempts = 2
75
78
 
79
+ # Native OpenRouter healing (enabled by default for non-streaming structured outputs)
80
+ self.auto_native_healing = ENV.fetch("OPENROUTER_AUTO_NATIVE_HEALING", "true").downcase == "true"
81
+
76
82
  # Cache defaults
77
83
  self.cache_ttl = ENV.fetch("OPENROUTER_CACHE_TTL", DEFAULT_CACHE_TTL).to_i
78
84
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open_router_enhanced
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Stiens
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-10-07 00:00:00.000000000 Z
11
+ date: 2025-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -129,6 +129,7 @@ files:
129
129
  - VCR_CONFIGURATION.md
130
130
  - docs/model_selection.md
131
131
  - docs/observability.md
132
+ - docs/plugins.md
132
133
  - docs/prompt_templates.md
133
134
  - docs/streaming.md
134
135
  - docs/structured_outputs.md