From 74e10805f07605d494a7084b74ced35b806e4c09 Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 11:30:33 -0700 Subject: [PATCH 1/8] Update .gemspec file to allow for lower versions --- ruby_llm.gemspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby_llm.gemspec b/ruby_llm.gemspec index 35728d367..a95bb4497 100644 --- a/ruby_llm.gemspec +++ b/ruby_llm.gemspec @@ -36,9 +36,9 @@ Gem::Specification.new do |spec| # Runtime dependencies spec.add_dependency 'base64' spec.add_dependency 'event_stream_parser', '~> 1' - spec.add_dependency 'faraday', '~> 2' + spec.add_dependency "faraday", ENV['FARADAY_VERSION'] || ">= 1.10.0" spec.add_dependency 'faraday-multipart', '~> 1' - spec.add_dependency 'faraday-net_http', '~> 3' - spec.add_dependency 'faraday-retry', '~> 2' + spec.add_dependency 'faraday-net_http', '~> 1' + spec.add_dependency 'faraday-retry', '~> 1' spec.add_dependency 'zeitwerk', '~> 2' end From 0d2a7b5965a162238c897cb8076a7db1355a3d42 Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 11:31:05 -0700 Subject: [PATCH 2/8] Update cicd.yml to validate downgraded versions work --- .github/workflows/cicd.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 0bc25865a..7131d3362 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -61,6 +61,11 @@ jobs: files: ./coverage/coverage.xml fail_ci_if_error: false + - name: Run the test suite with lower Faraday versions + run: FARADAY_VERSION=1.10.3 bundle exec rspec + env: + OLLAMA_API_BASE: http://localhost:11434/v1 # dummy + publish: name: Build + Publish needs: test From 8fb2d388d6979f79fade39b00e0d852ba0886130 Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 12:53:25 -0700 Subject: [PATCH 3/8] Update cicd.yml to install faraday version correctly --- .github/workflows/cicd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 7131d3362..05ad12487 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -62,7 +62,7 @@ jobs: fail_ci_if_error: false - name: Run the test suite with lower Faraday versions - run: FARADAY_VERSION=1.10.3 bundle exec rspec + run: FARADAY_VERSION=1.10.3 bundle install && bundle exec rspec env: OLLAMA_API_BASE: http://localhost:11434/v1 # dummy From 351111e7a10742266723526982006de69d9abb59 Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 12:53:59 -0700 Subject: [PATCH 4/8] Update streaming.rb to handle Faraday 1.x and 2.x --- lib/ruby_llm/streaming.rb | 45 +++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/ruby_llm/streaming.rb b/lib/ruby_llm/streaming.rb index d328e7b8d..cb1c98661 100644 --- a/lib/ruby_llm/streaming.rb +++ b/lib/ruby_llm/streaming.rb @@ -12,9 +12,18 @@ def stream_response(connection, payload, &block) accumulator = StreamAccumulator.new connection.post stream_url, payload do |req| - req.options.on_data = handle_stream do |chunk| - accumulator.add chunk - block.call chunk + if Faraday::VERSION.start_with?('1') + # Handle Faraday 1.x streaming with :on_data key + req.options[:on_data] = handle_stream do |chunk| + accumulator.add chunk + block.call chunk + end + else + # Handle Faraday 2.x streaming with on_data method + req.options.on_data = handle_stream do |chunk| + accumulator.add chunk + block.call chunk + end end end @@ -33,15 +42,29 @@ def to_json_stream(&block) buffer = String.new parser = EventStreamParser::Parser.new - proc do |chunk, _bytes, env| - RubyLLM.logger.debug "Received chunk: #{chunk}" + if Faraday::VERSION.start_with?('1') + # Faraday 1.x: on_data receives (chunk, size) + proc do |chunk, size| + RubyLLM.logger.debug "Received chunk: #{chunk}" - if error_chunk?(chunk) - handle_error_chunk(chunk, env) - elsif env&.status != 200 - handle_failed_response(chunk, buffer, env) - else - yield handle_sse(chunk, parser, env, &block) + if error_chunk?(chunk) + handle_error_chunk(chunk, nil) + else + yield handle_sse(chunk, parser, nil, &block) + end + end + else + # Faraday 2.x: on_data receives (chunk, bytes, env) + proc do |chunk, _bytes, env| + RubyLLM.logger.debug "Received chunk: #{chunk}" + + if error_chunk?(chunk) + handle_error_chunk(chunk, env) + elsif env&.status != 200 + handle_failed_response(chunk, buffer, env) + else + yield handle_sse(chunk, parser, env, &block) + end end end end From 0b1e7345bc751a6b9a1c94cadc5eb9f6a11a737d Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 12:54:22 -0700 Subject: [PATCH 5/8] Update gemspec for related libs --- ruby_llm.gemspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby_llm.gemspec b/ruby_llm.gemspec index a95bb4497..f1241875b 100644 --- a/ruby_llm.gemspec +++ b/ruby_llm.gemspec @@ -37,8 +37,8 @@ Gem::Specification.new do |spec| spec.add_dependency 'base64' spec.add_dependency 'event_stream_parser', '~> 1' spec.add_dependency "faraday", ENV['FARADAY_VERSION'] || ">= 1.10.0" - spec.add_dependency 'faraday-multipart', '~> 1' - spec.add_dependency 'faraday-net_http', '~> 1' - spec.add_dependency 'faraday-retry', '~> 1' + spec.add_dependency 'faraday-multipart', '>= 1' + spec.add_dependency 'faraday-net_http', '>= 1' + spec.add_dependency 'faraday-retry', '>= 1' spec.add_dependency 'zeitwerk', '~> 2' end From bf2cb87eb3fba13103a91d14ab84596aa2d3b203 Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 13:00:41 -0700 Subject: [PATCH 6/8] Apply rubocop to streaming.rb and fix issues --- lib/ruby_llm/streaming.rb | 52 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/lib/ruby_llm/streaming.rb b/lib/ruby_llm/streaming.rb index cb1c98661..2ecf53913 100644 --- a/lib/ruby_llm/streaming.rb +++ b/lib/ruby_llm/streaming.rb @@ -38,33 +38,45 @@ def handle_stream(&block) private - def to_json_stream(&block) + def to_json_stream(&) buffer = String.new parser = EventStreamParser::Parser.new + create_stream_processor(parser, buffer, &) + end + + def create_stream_processor(parser, buffer, &) if Faraday::VERSION.start_with?('1') # Faraday 1.x: on_data receives (chunk, size) - proc do |chunk, size| - RubyLLM.logger.debug "Received chunk: #{chunk}" - - if error_chunk?(chunk) - handle_error_chunk(chunk, nil) - else - yield handle_sse(chunk, parser, nil, &block) - end - end + legacy_stream_processor(parser, &) else # Faraday 2.x: on_data receives (chunk, bytes, env) - proc do |chunk, _bytes, env| - RubyLLM.logger.debug "Received chunk: #{chunk}" - - if error_chunk?(chunk) - handle_error_chunk(chunk, env) - elsif env&.status != 200 - handle_failed_response(chunk, buffer, env) - else - yield handle_sse(chunk, parser, env, &block) - end + stream_processor(parser, buffer, &) + end + end + + def process_stream_chunk(chunk, parser, _env, &) + RubyLLM.logger.debug "Received chunk: #{chunk}" + + if error_chunk?(chunk) + handle_error_chunk(chunk, nil) + else + yield handle_sse(chunk, parser, nil, &) + end + end + + def legacy_stream_processor(parser, &block) + proc do |chunk, _size| + process_stream_chunk(chunk, parser, nil, &block) + end + end + + def stream_processor(parser, buffer, &block) + proc do |chunk, _bytes, env| + if env&.status == 200 + process_stream_chunk(chunk, parser, env, &block) + else + handle_failed_response(chunk, buffer, env) end end end From 0d3a6a8dbc040b9f80449b2f26a1c57172dcc1cc Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Wed, 14 May 2025 13:00:52 -0700 Subject: [PATCH 7/8] Apply rubocop to gemspec and fix --- ruby_llm.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby_llm.gemspec b/ruby_llm.gemspec index f1241875b..fc1105a1c 100644 --- a/ruby_llm.gemspec +++ b/ruby_llm.gemspec @@ -36,7 +36,7 @@ Gem::Specification.new do |spec| # Runtime dependencies spec.add_dependency 'base64' spec.add_dependency 'event_stream_parser', '~> 1' - spec.add_dependency "faraday", ENV['FARADAY_VERSION'] || ">= 1.10.0" + spec.add_dependency 'faraday', ENV['FARADAY_VERSION'] || '>= 1.10.0' spec.add_dependency 'faraday-multipart', '>= 1' spec.add_dependency 'faraday-net_http', '>= 1' spec.add_dependency 'faraday-retry', '>= 1' From 9be49546c2d37f2812aa01126b9248e74dda82bb Mon Sep 17 00:00:00 2001 From: Raj Mirpuri <19713518+itstheraj@users.noreply.github.com> Date: Thu, 15 May 2025 13:16:23 -0700 Subject: [PATCH 8/8] Update streaming.rb to use idiomatic pattern when forking Faraday logic --- lib/ruby_llm/streaming.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ruby_llm/streaming.rb b/lib/ruby_llm/streaming.rb index 2ecf53913..b7017896e 100644 --- a/lib/ruby_llm/streaming.rb +++ b/lib/ruby_llm/streaming.rb @@ -12,15 +12,15 @@ def stream_response(connection, payload, &block) accumulator = StreamAccumulator.new connection.post stream_url, payload do |req| - if Faraday::VERSION.start_with?('1') - # Handle Faraday 1.x streaming with :on_data key - req.options[:on_data] = handle_stream do |chunk| + if req.options.respond_to?(:on_data) + # Handle Faraday 2.x streaming with on_data method + req.options.on_data = handle_stream do |chunk| accumulator.add chunk block.call chunk end else - # Handle Faraday 2.x streaming with on_data method - req.options.on_data = handle_stream do |chunk| + # Handle Faraday 1.x streaming with :on_data key + req.options[:on_data] = handle_stream do |chunk| accumulator.add chunk block.call chunk end