raix 2.0.3 → 2.0.4

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: 44058aeb590e21ead9e7db9ebdc9a4ecffc9f4771b75663e137b22ecca4cd7d2
4
- data.tar.gz: c59475844e68ef02379d85f7dde02540a58e7659d6b44a7fb83db7f491998635
3
+ metadata.gz: ec3b7449e51440e1d669e323dea0c371a3d18d7d4083090d61599ff1dbce3bbe
4
+ data.tar.gz: 6f2029218c2099ab1172d1d458be9ccb33836078d5abc9b04865cae0d497bc07
5
5
  SHA512:
6
- metadata.gz: 76c43e2109fc3ec1be374c2b5df9e024ad09274e2ece3df976eb6f961d022123453bb995f6f0680921df5f224c439cbd19ec8eac8d5acc201d80193541396509
7
- data.tar.gz: c0ee5f840e83718168668cf844a2cb3e7969f2cd5e199235b8532049660aab0cf7750abcf0e8748ffda7427fee73c7739fc37060c739efc64bcf7b04867c9da5
6
+ metadata.gz: 76e1d77e80023dbc634e4b2f72eaa269f05d539ea97470df1355e69e73d75a6cf4bd2bd7e627ab2cf01fcb381fd85c4b153d28005f32190ff1b8ae69c3bea275
7
+ data.tar.gz: 6fedf4bae5c406b72b83a1aacbc985849eb7c461237e7cc1e12d9ca73ea05a861912f13739bc92ba8ad992bf88f5a31fa530dc9468c5bdb4763f53caf3833843
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.0.4] - 2026-05-19
4
+
5
+ ### Fixed
6
+ - `ruby_llm_request` now preserves the upstream provider's `id`, `model`, and `provider` fields, plus the full `usage` payload (including `prompt_tokens_details.cached_tokens` and `completion_tokens_details.reasoning_tokens`) on the OpenAI-compatible response hash. Previously the conversion dropped everything except `choices` and basic token counts, which broke callers that needed the generation id for authoritative cost lookups (e.g. OpenRouter's `/api/v1/generation` endpoint) or that wanted to verify prompt-cache hits via `cached_tokens`.
7
+ - Added `require "active_support/core_ext/module/delegation"` so `Raix::ChatCompletion` loads cleanly without an external preload of ActiveSupport. The class uses `delegate :configuration, to: :class` but did not pull in the required core ext, so a bare `require "raix"` would raise `NoMethodError` for `delegate`.
8
+
3
9
  ## [2.0.3] - 2026-04-30
4
10
 
5
11
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- raix (2.0.3)
4
+ raix (2.0.4)
5
5
  activesupport (>= 6.0)
6
6
  faraday-retry (~> 2.0)
7
7
  ostruct
@@ -4,6 +4,7 @@ require "active_support/concern"
4
4
  require "active_support/core_ext/object/blank"
5
5
  require "active_support/core_ext/string/filters"
6
6
  require "active_support/core_ext/hash/indifferent_access"
7
+ require "active_support/core_ext/module/delegation"
7
8
  require "ruby_llm"
8
9
 
9
10
  module Raix
@@ -56,9 +57,7 @@ module Raix
56
57
  end
57
58
 
58
59
  # Instance level access to the class-level configuration.
59
- def configuration
60
- self.class.configuration
61
- end
60
+ delegate :configuration, to: :class
62
61
 
63
62
  # This method performs chat completion based on the provided transcript and parameters.
64
63
  #
@@ -398,8 +397,34 @@ module Raix
398
397
  # Non-streaming mode - return OpenAI-compatible response format
399
398
  response_message = has_user_message ? chat.complete : chat.ask
400
399
 
401
- # Convert RubyLLM response to OpenAI format for compatibility
400
+ # Pull through the raw provider payload when available. OpenRouter's
401
+ # `id` is the only handle we have to look up authoritative billing
402
+ # cost via /api/v1/generation, and callers that watch the response
403
+ # snapshot for `model` / cached-token counts shouldn't have to break
404
+ # out of the OpenAI-compatible shape to get them.
405
+ raw_body = response_message.raw.respond_to?(:body) ? response_message.raw.body : nil
406
+ raw_body = {} unless raw_body.is_a?(Hash)
407
+
408
+ usage_payload = {
409
+ "prompt_tokens" => response_message.input_tokens,
410
+ "completion_tokens" => response_message.output_tokens,
411
+ "total_tokens" => (response_message.input_tokens || 0) + (response_message.output_tokens || 0)
412
+ }
413
+
414
+ # Merge prompt_tokens_details / completion_tokens_details (cached tokens,
415
+ # reasoning tokens) when the provider supplied them.
416
+ if (upstream_usage = raw_body["usage"]).is_a?(Hash)
417
+ upstream_usage.each do |key, value|
418
+ next if usage_payload.key?(key)
419
+
420
+ usage_payload[key] = value
421
+ end
422
+ end
423
+
402
424
  {
425
+ "id" => raw_body["id"],
426
+ "model" => raw_body["model"] || response_message.model_id,
427
+ "provider" => raw_body["provider"],
403
428
  "choices" => [
404
429
  {
405
430
  "message" => {
@@ -410,11 +435,7 @@ module Raix
410
435
  "finish_reason" => response_message.tool_call? ? "tool_calls" : "stop"
411
436
  }
412
437
  ],
413
- "usage" => {
414
- "prompt_tokens" => response_message.input_tokens,
415
- "completion_tokens" => response_message.output_tokens,
416
- "total_tokens" => (response_message.input_tokens || 0) + (response_message.output_tokens || 0)
417
- }
438
+ "usage" => usage_payload
418
439
  }
419
440
  end
420
441
  rescue StandardError => e
data/lib/raix/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Raix
4
- VERSION = "2.0.3"
4
+ VERSION = "2.0.4"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raix
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Obie Fernandez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-04-30 00:00:00.000000000 Z
10
+ date: 2026-05-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport