diff --git a/lib/ruby_llm/stream_accumulator.rb b/lib/ruby_llm/stream_accumulator.rb index ccfbb335d..a9e0f3152 100644 --- a/lib/ruby_llm/stream_accumulator.rb +++ b/lib/ruby_llm/stream_accumulator.rb @@ -28,7 +28,7 @@ def initialize def add(chunk) RubyLLM.logger.debug { chunk.inspect } if RubyLLM.config.log_stream_debug - @model_id ||= chunk.model_id + @model_id = chunk.model_id if @model_id.to_s.empty? handle_chunk_content(chunk) accumulate_citations(chunk.citations) diff --git a/spec/ruby_llm/stream_accumulator_spec.rb b/spec/ruby_llm/stream_accumulator_spec.rb index 1d159a68e..b539601c4 100644 --- a/spec/ruby_llm/stream_accumulator_spec.rb +++ b/spec/ruby_llm/stream_accumulator_spec.rb @@ -4,6 +4,26 @@ RSpec.describe RubyLLM::StreamAccumulator do describe '#add' do + it 'ignores an empty model_id from an initial chunk' do + accumulator = described_class.new + + accumulator.add(RubyLLM::Chunk.new(role: :assistant, content: '', model_id: '')) + accumulator.add(RubyLLM::Chunk.new(role: :assistant, content: 'Hi', model_id: 'gpt-5.4-2026-03-05')) + + message = accumulator.to_message(nil) + expect(message.model_id).to eq('gpt-5.4-2026-03-05') + end + + it 'keeps the first non-empty model_id' do + accumulator = described_class.new + + accumulator.add(RubyLLM::Chunk.new(role: :assistant, content: 'Hi', model_id: 'model-a')) + accumulator.add(RubyLLM::Chunk.new(role: :assistant, content: '!', model_id: 'model-b')) + + message = accumulator.to_message(nil) + expect(message.model_id).to eq('model-a') + end + it 'handles tool call deltas that omit arguments' do accumulator = described_class.new tool_call = RubyLLM::ToolCall.new(id: 'call_1', name: 'weather', arguments: nil)