ruby_llm-contract 0.6.4 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 655ecfa5adebe03245cb4ee910752ec866b83844b665018277dc653a3e246a63
4
- data.tar.gz: fafcdacea3943703fad581f9f1806fe25678fd5da7b01867ecb5aac353da139f
3
+ metadata.gz: 5decfb7456338baa05d0e6bb79287bb3fb3af0e0cc2c3f001e09122fa76ac298
4
+ data.tar.gz: be3b46ff015fd651e885c4c078dbdaf06623865f4e4b80b864b66e8dd9e16c34
5
5
  SHA512:
6
- metadata.gz: c4821220d898468f55ab7085d25f6370819501cdfcb5ffea21a9dbdaaa9348997c1b9e6acbad8eb9ff6328eb531eda17e05bd09b1fcd047429fcd69b820a1819
7
- data.tar.gz: 91fb14f2aa6e13e70d29f0222dc160548c9c50e9bf4bd9f27e9042bd0f6a4fae1a557b762747ee066c3444ee90942ea008c048b4bb0efc364d212329726d3888
6
+ metadata.gz: fd3882613ac2b500c46dc6b1084d8f298db96800bf01932e3bc2638a7a3d2a8588610c1de8a1f3754a8e15fb7b1ef29c0c0a7bddd11709cd95bbf12fcd48e83e
7
+ data.tar.gz: 4cb584323a5575de4131b0eb82cdb1426743ca6651030708673d17264c9fec60619bb7d5d54f62eee4c1fa357b4022f57bf08b95d81f153eccf8e625ce3ef5e7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0 (2026-04-21)
4
+
5
+ ### Breaking changes
6
+
7
+ - **`:adapter_error` removed from `DEFAULT_RETRY_ON`.** New default: `[:validation_failed, :parse_error]`. `ruby_llm` already retries transport errors (`RateLimitError`, `ServerError`, `ServiceUnavailableError`, `OverloadedError`, timeouts) at the Faraday layer, so the previous default re-ran the same model on errors the HTTP middleware already retried with backoff. To restore pre-0.7 behavior: `retry_on :validation_failed, :parse_error, :adapter_error`. Recommended pattern: pair `:adapter_error` with `escalate "model_a", "model_b"` — a different model/provider can bypass what transport retry could not.
8
+ - **`AdapterCaller` narrows `rescue` from `StandardError` to `RubyLLM::Error` + `Faraday::Error`.** Provider errors and transport errors that escape ruby_llm's Faraday retry middleware (`Faraday::TimeoutError`, `Faraday::ConnectionFailed`) still produce `:adapter_error` as before. Programmer errors that are neither (`NoMethodError`, adapter code bugs) now propagate instead of being silently converted to `:adapter_error` and retried. **Known limitation:** adapter code raising `ArgumentError` is still coerced into `:input_error` by `Step::Base#run_once` (which rescues `ArgumentError` for input-type validation). Disambiguating adapter-ArgumentError vs input-validation-ArgumentError requires a `run_once` refactor and is tracked as a follow-up.
9
+
10
+ ### Migration
11
+
12
+ If you rely on the old behavior, opt in explicitly:
13
+
14
+ ```ruby
15
+ retry_policy do
16
+ attempts 3
17
+ retry_on :validation_failed, :parse_error, :adapter_error
18
+ end
19
+ ```
20
+
21
+ Or better, with a model fallback chain:
22
+
23
+ ```ruby
24
+ retry_policy do
25
+ escalate "gpt-4.1-nano", "gpt-4.1-mini"
26
+ retry_on :validation_failed, :parse_error, :adapter_error
27
+ end
28
+ ```
29
+
3
30
  ## 0.6.4 (2026-04-20)
4
31
 
5
32
  ### Features
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_llm-contract (0.6.4)
4
+ ruby_llm-contract (0.7.0)
5
5
  dry-types (~> 1.7)
6
6
  ruby_llm (~> 1.0)
7
7
  ruby_llm-schema (~> 0.3)
@@ -258,7 +258,7 @@ CHECKSUMS
258
258
  rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
259
259
  ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
260
260
  ruby_llm (1.14.0) sha256=57c6f7034fc4a44504ea137d70f853b07824f1c1cdbe774ab3ab3522e7098deb
261
- ruby_llm-contract (0.6.4)
261
+ ruby_llm-contract (0.7.0)
262
262
  ruby_llm-schema (0.3.0) sha256=a591edc5ca1b7f0304f0e2261de61ba4b3bea17be09f5cf7558153adfda3dec6
263
263
  ruby_parser (3.22.0) sha256=1eb4937cd9eb220aa2d194e352a24dba90aef00751e24c8dfffdb14000f15d23
264
264
  rubycritic (4.12.0) sha256=024fed90fe656fa939f6ea80aab17569699ac3863d0b52fd72cb99892247abc8
@@ -1,9 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "faraday"
4
+
3
5
  module RubyLLM
4
6
  module Contract
5
7
  module Step
6
8
  class AdapterCaller
9
+ # Exceptions treated as :adapter_error (retryable when explicitly opted in).
10
+ # RubyLLM::Error covers provider-semantic errors (auth, bad request,
11
+ # rate limit, server error, context length). Faraday::Error covers
12
+ # transport failures that escape ruby_llm's Faraday retry middleware
13
+ # after exhaustion (Faraday::TimeoutError, Faraday::ConnectionFailed).
14
+ # Anything else (NoMethodError, programmer ArgumentError from adapter
15
+ # code, etc.) propagates — those are bugs, not retry candidates.
16
+ ADAPTER_ERRORS = [::RubyLLM::Error, ::Faraday::Error].freeze
17
+
7
18
  def initialize(adapter:, adapter_options:)
8
19
  @adapter = adapter
9
20
  @adapter_options = adapter_options
@@ -14,8 +25,14 @@ module RubyLLM
14
25
  response = @adapter.call(messages: messages, **@adapter_options)
15
26
  latency_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000).round
16
27
  [response, latency_ms]
17
- rescue StandardError => error
18
- [Result.new(status: :adapter_error, raw_output: nil, parsed_output: nil, validation_errors: [error.message]), 0]
28
+ rescue *ADAPTER_ERRORS => e
29
+ result = Result.new(
30
+ status: :adapter_error,
31
+ raw_output: nil,
32
+ parsed_output: nil,
33
+ validation_errors: [e.message]
34
+ )
35
+ [result, 0]
19
36
  end
20
37
  end
21
38
  end
@@ -6,7 +6,14 @@ module RubyLLM
6
6
  class RetryPolicy
7
7
  attr_reader :max_attempts, :retryable_statuses
8
8
 
9
- DEFAULT_RETRY_ON = %i[validation_failed parse_error adapter_error].freeze
9
+ # Breaking (0.7.0): :adapter_error removed from defaults. ruby_llm's Faraday
10
+ # middleware already retries transport errors (RateLimitError, ServerError,
11
+ # ServiceUnavailableError, OverloadedError, timeouts). Retrying on
12
+ # :adapter_error against the same model re-runs what transport already did.
13
+ # Opt in explicitly with `retry_on :adapter_error` — only meaningful paired
14
+ # with `escalate "model_a", "model_b"` (a different model may bypass what
15
+ # transport retry could not).
16
+ DEFAULT_RETRY_ON = %i[validation_failed parse_error].freeze
10
17
 
11
18
  def initialize(models: nil, attempts: nil, retry_on: nil, &block)
12
19
  @configs = []
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Contract
5
- VERSION = "0.6.4"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/ruby_llm/contract/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ruby_llm-contract"
7
+ spec.version = RubyLLM::Contract::VERSION
8
+ spec.authors = ["Justyna"]
9
+
10
+ spec.summary = "Know which LLM model to use, what it costs, and when accuracy drops"
11
+ spec.description = "Compare LLM models by accuracy and cost. Regression-test prompts in CI. " \
12
+ "Start on nano, auto-escalate to bigger models when quality drops. " \
13
+ "Companion gem for ruby_llm."
14
+ spec.homepage = "https://github.com/justi/ruby_llm-contract"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = ">= 3.2.0"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
21
+ spec.metadata["documentation_uri"] = "#{spec.homepage}#readme"
22
+ spec.metadata["rubygems_mfa_required"] = "true"
23
+
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (File.expand_path(f) == __FILE__) ||
27
+ f.start_with?("spec/", "docs/", "doc/", ".ai/", ".claude/", ".git")
28
+ end
29
+ end
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "dry-types", "~> 1.7"
33
+ spec.add_dependency "ruby_llm", "~> 1.0"
34
+ spec.add_dependency "ruby_llm-schema", "~> 0.3"
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-contract
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justyna
@@ -182,6 +182,7 @@ files:
182
182
  - lib/ruby_llm/contract/token_estimator.rb
183
183
  - lib/ruby_llm/contract/types.rb
184
184
  - lib/ruby_llm/contract/version.rb
185
+ - ruby_llm-contract.gemspec
185
186
  homepage: https://github.com/justi/ruby_llm-contract
186
187
  licenses:
187
188
  - MIT