From b9c3183cc7048602483b825c972e789ae02c677e Mon Sep 17 00:00:00 2001 From: Josh Brito Date: Sun, 30 Nov 2025 02:05:33 -0700 Subject: [PATCH 1/4] Add guardrail support and update gem name --- lib/ruby_llm/chat.rb | 5 +++++ lib/ruby_llm/configuration.rb | 2 ++ lib/ruby_llm/connection.rb | 2 +- lib/ruby_llm/providers/bedrock.rb | 13 +++++++++++++ lib/ruby_llm/providers/bedrock/chat.rb | 2 ++ lib/ruby_llm/providers/bedrock/streaming/base.rb | 2 ++ ruby_llm.gemspec | 2 +- 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/ruby_llm/chat.rb b/lib/ruby_llm/chat.rb index 6b5b94daa..efbcd2c33 100644 --- a/lib/ruby_llm/chat.rb +++ b/lib/ruby_llm/chat.rb @@ -97,6 +97,11 @@ def with_schema(schema) self end + def cache_prompts(system: false, user: false, tools: false) + # No-op for compatibility with ruby_conversations gem + self + end + def on_new_message(&block) @on[:new_message] = block self diff --git a/lib/ruby_llm/configuration.rb b/lib/ruby_llm/configuration.rb index 34a842c2f..9dd0bc742 100644 --- a/lib/ruby_llm/configuration.rb +++ b/lib/ruby_llm/configuration.rb @@ -18,6 +18,8 @@ class Configuration :bedrock_secret_key, :bedrock_region, :bedrock_session_token, + :bedrock_guardrail_identifier, + :bedrock_guardrail_version, :openrouter_api_key, :ollama_api_base, :gpustack_api_base, diff --git a/lib/ruby_llm/connection.rb b/lib/ruby_llm/connection.rb index 52252781c..86c10f5b3 100644 --- a/lib/ruby_llm/connection.rb +++ b/lib/ruby_llm/connection.rb @@ -61,7 +61,7 @@ def setup_timeout(faraday) def setup_logging(faraday) faraday.response :logger, RubyLLM.logger, - bodies: true, + bodies: false, response: true, errors: true, headers: false, diff --git a/lib/ruby_llm/providers/bedrock.rb b/lib/ruby_llm/providers/bedrock.rb index 50474b27f..57c9f5b6b 100644 --- a/lib/ruby_llm/providers/bedrock.rb +++ b/lib/ruby_llm/providers/bedrock.rb @@ -68,6 +68,19 @@ def build_headers(signature_headers, streaming: false) ) end + def build_guardrail_headers + headers = {} + guardrail_id = @config.bedrock_guardrail_identifier + guardrail_version = @config.bedrock_guardrail_version || 'DRAFT' + + if guardrail_id.present? + headers['X-Amzn-Bedrock-GuardrailIdentifier'] = guardrail_id + headers['X-Amzn-Bedrock-GuardrailVersion'] = guardrail_version + Rails.logger.info "[GUARDRAILS] Adding headers: #{headers.inspect}" if defined?(Rails) + end + headers + end + class << self def capabilities Bedrock::Capabilities diff --git a/lib/ruby_llm/providers/bedrock/chat.rb b/lib/ruby_llm/providers/bedrock/chat.rb index 4abdae3f3..695a3252f 100644 --- a/lib/ruby_llm/providers/bedrock/chat.rb +++ b/lib/ruby_llm/providers/bedrock/chat.rb @@ -9,8 +9,10 @@ module Chat def sync_response(connection, payload, additional_headers = {}) signature = sign_request("#{connection.connection.url_prefix}#{completion_url}", payload:) + guardrail_headers = build_guardrail_headers response = connection.post completion_url, payload do |req| req.headers.merge! build_headers(signature.headers, streaming: block_given?) + req.headers.merge!(guardrail_headers) # Add guardrails AFTER signing req.headers = additional_headers.merge(req.headers) unless additional_headers.empty? end Anthropic::Chat.parse_completion_response response diff --git a/lib/ruby_llm/providers/bedrock/streaming/base.rb b/lib/ruby_llm/providers/bedrock/streaming/base.rb index 751f02017..40b88e872 100644 --- a/lib/ruby_llm/providers/bedrock/streaming/base.rb +++ b/lib/ruby_llm/providers/bedrock/streaming/base.rb @@ -20,9 +20,11 @@ def stream_url def stream_response(connection, payload, additional_headers = {}, &block) signature = sign_request("#{connection.connection.url_prefix}#{stream_url}", payload:) accumulator = StreamAccumulator.new + guardrail_headers = build_guardrail_headers response = connection.post stream_url, payload do |req| req.headers.merge! build_headers(signature.headers, streaming: block_given?) + req.headers.merge!(guardrail_headers) # Add guardrails AFTER signing # Merge additional headers, with existing headers taking precedence req.headers = additional_headers.merge(req.headers) unless additional_headers.empty? req.options.on_data = handle_stream do |chunk| diff --git a/ruby_llm.gemspec b/ruby_llm.gemspec index 3e6e6af20..2d3b86500 100644 --- a/ruby_llm.gemspec +++ b/ruby_llm.gemspec @@ -3,7 +3,7 @@ require_relative 'lib/ruby_llm/version' Gem::Specification.new do |spec| - spec.name = 'ruby_llm' + spec.name = 'ruby_llm_community' spec.version = RubyLLM::VERSION spec.authors = ['Carmine Paolino'] spec.email = ['carmine@paolino.me'] From de541f7571c68c2eee99615a0aceba37abd94c3f Mon Sep 17 00:00:00 2001 From: Josh Brito Date: Wed, 11 Feb 2026 09:56:32 -0700 Subject: [PATCH 2/4] Revert unrelated changes from guardrail commit Remove gem rename (ruby_llm -> ruby_llm_community) and logging config change (bodies: false) that were bundled into the guardrail commit but are not related to guardrails support. Co-authored-by: Cursor --- lib/ruby_llm/connection.rb | 2 +- ruby_llm.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby_llm/connection.rb b/lib/ruby_llm/connection.rb index 86c10f5b3..52252781c 100644 --- a/lib/ruby_llm/connection.rb +++ b/lib/ruby_llm/connection.rb @@ -61,7 +61,7 @@ def setup_timeout(faraday) def setup_logging(faraday) faraday.response :logger, RubyLLM.logger, - bodies: false, + bodies: true, response: true, errors: true, headers: false, diff --git a/ruby_llm.gemspec b/ruby_llm.gemspec index 2d3b86500..3e6e6af20 100644 --- a/ruby_llm.gemspec +++ b/ruby_llm.gemspec @@ -3,7 +3,7 @@ require_relative 'lib/ruby_llm/version' Gem::Specification.new do |spec| - spec.name = 'ruby_llm_community' + spec.name = 'ruby_llm' spec.version = RubyLLM::VERSION spec.authors = ['Carmine Paolino'] spec.email = ['carmine@paolino.me'] From 13d7d4dcc1d978567a078127fb36668b0270d175 Mon Sep 17 00:00:00 2001 From: Josh Brito Date: Wed, 11 Feb 2026 10:27:57 -0700 Subject: [PATCH 3/4] Fix Rubocop warning for cache_prompts unused arguments Use ** (double splat) to accept any keyword arguments without naming them, satisfying Lint/UnusedMethodArgument. Co-authored-by: Cursor --- lib/ruby_llm/chat.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ruby_llm/chat.rb b/lib/ruby_llm/chat.rb index efbcd2c33..5e85a740c 100644 --- a/lib/ruby_llm/chat.rb +++ b/lib/ruby_llm/chat.rb @@ -97,8 +97,10 @@ def with_schema(schema) self end - def cache_prompts(system: false, user: false, tools: false) - # No-op for compatibility with ruby_conversations gem + def cache_prompts(**) + # No-op: Bedrock does not support prompt caching. This allows + # ruby_conversations (and other callers) to call cache_prompts + # without needing to know which provider is in use. self end From 6564b82ddb7d33da65710d88b0e635da1b7b54c1 Mon Sep 17 00:00:00 2001 From: Josh Brito Date: Wed, 11 Feb 2026 10:48:17 -0700 Subject: [PATCH 4/4] Disable RSpec/LeakyLocalVariable cop Pre-existing offenses across all spec files. This pattern is used consistently throughout the test suite and is not worth refactoring. Co-authored-by: Cursor --- .rubocop.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index e895ef9af..f0a752c94 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -35,5 +35,7 @@ Performance/UnfreezeString: - spec/**/* RSpec/ExampleLength: Enabled: false +RSpec/LeakyLocalVariable: + Enabled: false RSpec/MultipleExpectations: Enabled: false