From 9a5b0a7f146c173c359e44f43a5e1c9556a5c8e5 Mon Sep 17 00:00:00 2001 From: Brian Borge Date: Tue, 19 Aug 2025 11:20:56 -0400 Subject: [PATCH 1/3] Fix Gemini schema conversion - preserve descriptions, - distinguish integer/number types --- lib/ruby_llm/providers/gemini/chat.rb | 49 +++++++++++++++++---------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/lib/ruby_llm/providers/gemini/chat.rb b/lib/ruby_llm/providers/gemini/chat.rb index 65b0fc41c..0b25af51b 100644 --- a/lib/ruby_llm/providers/gemini/chat.rb +++ b/lib/ruby_llm/providers/gemini/chat.rb @@ -89,29 +89,44 @@ def parse_completion_response(response) def convert_schema_to_gemini(schema) # rubocop:disable Metrics/PerceivedComplexity return nil unless schema + result = case schema[:type] + when 'object' + properties = schema[:properties]&.transform_values { |prop| convert_schema_to_gemini(prop) } || {} + { + type: 'OBJECT', + properties: properties, + required: schema[:required] || [] + } + when 'array' + { + type: 'ARRAY', + items: schema[:items] ? convert_schema_to_gemini(schema[:items]) : { type: 'STRING' } + } + when 'number' + { type: 'NUMBER' } + when 'integer' + { type: 'INTEGER' } + when 'boolean' + { type: 'BOOLEAN' } + else + { type: 'STRING' } + end + + result[:description] = schema[:description] if schema[:description] + case schema[:type] - when 'object' - { - type: 'OBJECT', - properties: schema[:properties]&.transform_values { |prop| convert_schema_to_gemini(prop) } || {}, - required: schema[:required] || [] - } - when 'array' - { - type: 'ARRAY', - items: schema[:items] ? convert_schema_to_gemini(schema[:items]) : { type: 'STRING' } - } when 'string' - result = { type: 'STRING' } result[:enum] = schema[:enum] if schema[:enum] - result + result[:format] = schema[:format] if schema[:format] + result[:nullable] = schema[:nullable] if schema.key?(:nullable) when 'number', 'integer' - { type: 'NUMBER' } + result[:format] = schema[:format] if schema[:format] + result[:nullable] = schema[:nullable] if schema.key?(:nullable) when 'boolean' - { type: 'BOOLEAN' } - else - { type: 'STRING' } + result[:nullable] = schema[:nullable] if schema.key?(:nullable) end + + result end def extract_content(data) From 519a10c8bb54b136ea68bcd5f8f36fe9f9873287 Mon Sep 17 00:00:00 2001 From: Brian Borge Date: Tue, 19 Aug 2025 17:24:18 -0400 Subject: [PATCH 2/3] Extends schema conversion to support all fields --- lib/ruby_llm/providers/gemini/chat.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ruby_llm/providers/gemini/chat.rb b/lib/ruby_llm/providers/gemini/chat.rb index 0b25af51b..bcad5058f 100644 --- a/lib/ruby_llm/providers/gemini/chat.rb +++ b/lib/ruby_llm/providers/gemini/chat.rb @@ -121,6 +121,13 @@ def convert_schema_to_gemini(schema) # rubocop:disable Metrics/PerceivedComplexi result[:nullable] = schema[:nullable] if schema.key?(:nullable) when 'number', 'integer' result[:format] = schema[:format] if schema[:format] + result[:minimum] = schema[:minimum] if schema[:minimum] + result[:maximum] = schema[:maximum] if schema[:maximum] + result[:enum] = schema[:enum] if schema[:enum] + result[:nullable] = schema[:nullable] if schema.key?(:nullable) + when 'array' + result[:minItems] = schema[:minItems] if schema[:minItems] + result[:maxItems] = schema[:maxItems] if schema[:maxItems] result[:nullable] = schema[:nullable] if schema.key?(:nullable) when 'boolean' result[:nullable] = schema[:nullable] if schema.key?(:nullable) From c0223362641a394cdf985105aa00a543a53769db Mon Sep 17 00:00:00 2001 From: Brian Borge Date: Tue, 19 Aug 2025 17:39:12 -0400 Subject: [PATCH 3/3] Add missing propertyOrdering schema field --- lib/ruby_llm/providers/gemini/chat.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ruby_llm/providers/gemini/chat.rb b/lib/ruby_llm/providers/gemini/chat.rb index bcad5058f..fc7f8c799 100644 --- a/lib/ruby_llm/providers/gemini/chat.rb +++ b/lib/ruby_llm/providers/gemini/chat.rb @@ -92,11 +92,14 @@ def convert_schema_to_gemini(schema) # rubocop:disable Metrics/PerceivedComplexi result = case schema[:type] when 'object' properties = schema[:properties]&.transform_values { |prop| convert_schema_to_gemini(prop) } || {} - { + object_result = { type: 'OBJECT', properties: properties, required: schema[:required] || [] } + object_result[:propertyOrdering] = schema[:propertyOrdering] if schema[:propertyOrdering] + object_result[:nullable] = schema[:nullable] if schema.key?(:nullable) + object_result when 'array' { type: 'ARRAY',