Skip to content

Releases: OlympiaAI/raix

Release 2.0.5

Choose a tag to compare

@obie obie released this 04 Jun 09:27
2d46314

Fixed

  • Raix::Configuration no longer defaults temperature to 0.0. The default was being injected into every request payload, which OpenRouter rejects with 404 No endpoints found that can handle the requested parameters when routed to providers whose supported_parameters list omits temperature (notably Anthropic's Claude 4.7 family) and provider.require_parameters: true is set — which Raix sets automatically whenever json: true is passed to chat_completion. Callers that want a specific temperature should set one explicitly (self.temperature = 0.0 on the including class, or Raix.configure { |c| c.temperature = 0.0 } globally); when unset, Raix now omits the parameter and the provider's own server-side default applies. max_tokens, max_completion_tokens, and model defaults are unchanged.
  • Raix::FunctionToolAdapter now forwards the full JSON-Schema dict for each function parameter to RubyLLM instead of rebuilding it from type + description only. Rich schema fields like additionalProperties, items, enum, and nested properties were silently dropped, leaving providers (notably Gemini's structured output via OpenRouter) to invent degenerate shapes for type: object arguments — e.g. emitting {"prefix" => false} instead of {"prefix:title" => "..."}. Function declarations with rich object schemas now reach the provider intact.
  • The outer tool-args schema continues to inject additionalProperties: false and strict: true by default for OpenAI strict-mode compatibility, but consumers can override either by setting them explicitly in the function declaration.
  • Multimodal transcript content is no longer silently dropped on the RubyLLM backend. OpenAI-style content arrays (a text part plus one or more { type: "image_url", image_url: { url: ... } } parts) were passed to RubyLLM verbatim, which treats the array as plain text — so a vision model received text only and confabulated an answer. Raix now translates image_url parts into RubyLLM attachments via Raix::MultimodalContentAdapter, decoding base64 data: URIs into binary IO (RubyLLM's Attachment does not natively recognize data: URIs) and passing http(s) URLs through. Text-only completions are unaffected (#51).

Release 2.0.4

Choose a tag to compare

@obie obie released this 19 May 12:21

Fixed

  • 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.
  • 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.

Release 2.0.2

Choose a tag to compare

@obie obie released this 19 May 12:21

Fixed

  • Ensure gem files are world-readable (644) for Docker deployments where gems are installed as root but the app runs as a non-root user.
  • Added gemspec-level safety net that normalizes file permissions at build time.

Release 2.0.3

Choose a tag to compare

@obie obie released this 19 May 12:21

Fixed

  • NoMethodError: undefined method 'strip' for nil in Raix::ChatCompletion when an LLM (notably Gemini under certain stop conditions) returns a final assistant message with "content": null. Three call sites in lib/raix/chat_completion.rb now use content.to_s.strip so a nil response coerces to "" instead of raising.

Release 2.0.1

Choose a tag to compare

@obie obie released this 20 Mar 19:21

Changed

  • Replaced require_relative with Zeitwerk autoloading (thanks @seuros, PR #47)
  • Fixed RuboCop documentation offense

Release 2.0.0

Choose a tag to compare

@obie obie released this 20 Mar 18:37

Breaking Changes

  • Migrated from OpenRouter/OpenAI gems to RubyLLM - Raix now uses RubyLLM as its unified backend for all LLM providers. This provides better multi-provider support and a more consistent API.
  • Configuration changes - API keys are now configured through RubyLLM's configuration system instead of separate client instances.
  • Removed direct client dependencies - openrouter and ruby-openai gems are no longer direct dependencies; RubyLLM handles provider connections.

Added

  • before_completion hook - New hook system for intercepting and modifying chat completion requests before they're sent to the AI provider.
    • Configure at global, class, or instance levels
    • Hooks receive a CompletionContext with access to messages, params, and the chat completion instance
    • Messages are mutable for content filtering, PII redaction, adding system prompts, etc.
    • Params can be modified for dynamic model selection, A/B testing, and more
    • Supports any callable object (Proc, Lambda, or object responding to #call)
  • FunctionToolAdapter - New adapter for converting Raix function declarations to RubyLLM tool format
  • TranscriptAdapter - New adapter for bridging Raix's abbreviated message format with standard OpenAI format

Changed

  • Chat completions now use RubyLLM's unified API for all providers (OpenAI, Anthropic, Google, etc.)
  • Improved provider detection based on model name patterns
  • Streamlined internal architecture with dedicated adapters

Migration Guide

Update your configuration from:

Raix.configure do |config|
  config.openrouter_client = OpenRouter::Client.new(access_token: "...")
  config.openai_client = OpenAI::Client.new(access_token: "...")
end

To:

RubyLLM.configure do |config|
  config.openrouter_api_key = ENV["OPENROUTER_API_KEY"]
  config.openai_api_key = ENV["OPENAI_API_KEY"]
  # Also supports: anthropic_api_key, gemini_api_key
end

Release 1.0.3

Choose a tag to compare

@obie obie released this 08 Aug 23:46

Added support for GPT5

v1.0.2

Choose a tag to compare

@obie obie released this 16 Jul 01:55
f18ce41

What's Changed

Added

  • Added method to check for API client availability in Configuration

Changed

  • Updated ruby-openai dependency to ~> 8.1

Fixed

  • Fixed gemspec file reference

Full Changelog: v1.0.1...v1.0.2

v1.0.1

Choose a tag to compare

@obie obie released this 05 Jun 01:58
v1.0.1
bbbf3fe

What's Changed

Fixed

  • Fixed PromptDeclarations module namespace - now properly namespaced under Raix (#8)
  • Removed Rails.logger dependencies from PromptDeclarations for non-Rails environments
  • Fixed documentation example showing incorrect openai: true usage (should be model string) (#9)
  • Added comprehensive tests for PromptDeclarations module

Changed

  • Improved error handling in PromptDeclarations to catch StandardError instead of generic rescue

Issues Resolved

  • Closes #8 - Prompt declarations in README.md to not match the code
  • Closes #9 - Chat Completion Fails Due to Invalid JSON Payload (Status 400)

Full Changelog: v1.0.0...v1.0.1

v1.0.0

Choose a tag to compare

@obie obie released this 04 Jun 22:23
v1.0.0
7d290d6

Major Release: Automatic Tool Call Continuation

This major release introduces automatic continuation after tool calls, eliminating the need for the loop parameter entirely. The system now automatically handles tool execution and continues the conversation until the AI provides a final text response.

Breaking Changes

  • Deprecated loop parameter - The system now automatically continues conversations after tool calls. The loop parameter shows a deprecation warning but still works for backwards compatibility.
  • Tool-based completions now return strings instead of arrays - When functions are called, the final response is a string containing the AI's text response, not an array of function results.
  • stop_looping\! renamed to stop_tool_calls_and_respond\! - Better reflects the new automatic continuation behavior.

New Features

  • Automatic conversation continuation - Chat completions automatically continue after tool execution without needing the loop parameter.
  • max_tool_calls parameter - Controls the maximum number of tool invocations to prevent infinite loops (default: 25).
  • Configuration for max_tool_calls - Added max_tool_calls to the Configuration class with sensible defaults.

Migration Guide

# Before
response = ai.chat_completion(loop: true)

# After (automatic)
response = ai.chat_completion

# To limit tool calls
response = ai.chat_completion(max_tool_calls: 5)

Other Changes

  • Improved CI/CD workflow to use bundle exec rake ci for consistent testing
  • Fixed conflict between loop attribute and Ruby's Kernel.loop method (fixes #11)
  • Fixed various RuboCop warnings using keyword argument forwarding
  • Improved error handling with proper warning messages

See the CHANGELOG for full details.