Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/active_agent/concerns/streaming.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ def _stream_define_callback_wrapper_proc(callback_name, method_proc)
# @return [Proc] callback proc that accepts (message, delta, type)
def stream_broadcaster
proc do |message, delta, type|
self.stream_chunk = StreamChunk.new(message, delta)
cast_message = message.is_a?(Hash) ? Providers::Common::Messages::Types::MessageType.new.cast(message) : message
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Providers::Common::Messages::Types::MessageType.new is instantiated for every streamed chunk. Since stream_broadcaster may be called many times per request, this creates avoidable allocations; consider memoizing the MessageType instance (e.g., build it once per stream_broadcaster call and close over it, or store it in an ivar) and reuse it for each cast.

Copilot uses AI. Check for mistakes.
self.stream_chunk = StreamChunk.new(cast_message, delta)
Comment on lines +271 to +272
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are streaming callback tests, but none currently assert the new behavior that Hash messages are cast to a typed message with .content/.role during streaming. Add a test that calls stream_broadcaster with a Hash message and asserts chunk.message is cast (and that non-Hash messages still pass through unchanged) to prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +271 to +272
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casting Hash messages through Providers::Common::Messages::Types::MessageType drops provider-specific keys (e.g., OpenAI Chat streaming messages can include :tool_calls, and the common MessageType slices assistant hashes down to :role, :content, :name). This is an API change for streaming callbacks that currently can inspect the full provider message hash; consider preserving the original Hash alongside the typed wrapper (or otherwise exposing raw fields) so streaming users don’t lose access to metadata/tool-call details.

Suggested change
cast_message = message.is_a?(Hash) ? Providers::Common::Messages::Types::MessageType.new.cast(message) : message
self.stream_chunk = StreamChunk.new(cast_message, delta)
self.stream_chunk = StreamChunk.new(message, delta)

Copilot uses AI. Check for mistakes.

run_callbacks(:stream_open) if type == :open
run_callbacks(:stream)
Expand Down
Loading