-module(glean@stream). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glean/stream.gleam"). -export([collect_text/1, collect_tool_calls/1, add_usage/2, zero_usage/0]). -export_type([usage/0, stream_event/0, tool_call_accumulator/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type usage() :: {usage, integer(), integer()}. -type stream_event() :: {text_start, binary()} | {text_delta, binary(), binary()} | {text_end, binary()} | {reasoning_start, binary()} | {reasoning_delta, binary(), binary()} | {reasoning_end, binary()} | {tool_call_start, binary(), binary(), binary()} | {tool_call_delta, binary(), binary(), binary()} | {tool_call_end, binary(), binary()} | {tool_result_event, binary(), binary(), binary()} | {tool_error_event, binary(), binary(), binary()} | {step_start, integer()} | {step_end, integer()} | {finish, glean@error:finish_reason(), usage()} | {stream_error, binary()}. -type tool_call_accumulator() :: {tool_call_accumulator, binary(), binary(), gleam@string_tree:string_tree()}. -file("src/glean/stream.gleam", 36). ?DOC(" Accumulate all text deltas from a list of stream events into a single string.\n"). -spec collect_text(list(stream_event())) -> binary(). collect_text(Events) -> _pipe = Events, _pipe@1 = gleam@list:fold( _pipe, gleam@string_tree:new(), fun(Acc, Event) -> case Event of {text_delta, _, Delta} -> gleam@string_tree:append(Acc, Delta); _ -> Acc end end ), unicode:characters_to_binary(_pipe@1). -file("src/glean/stream.gleam", 66). -spec collect_tool_calls_loop( list(stream_event()), list({binary(), binary(), binary()}), gleam@option:option(tool_call_accumulator()) ) -> list({binary(), binary(), binary()}). collect_tool_calls_loop(Events, Completed, Current) -> case Events of [] -> lists:reverse(Completed); [Event | Rest] -> case Event of {tool_call_start, _, Tool_call_id, Tool_name} -> collect_tool_calls_loop( Rest, Completed, {some, {tool_call_accumulator, Tool_call_id, Tool_name, gleam@string_tree:new()}} ); {tool_call_delta, _, _, Delta} -> case Current of {some, Acc} -> collect_tool_calls_loop( Rest, Completed, {some, {tool_call_accumulator, erlang:element(2, Acc), erlang:element(3, Acc), gleam@string_tree:append( erlang:element(4, Acc), Delta )}} ); none -> collect_tool_calls_loop(Rest, Completed, Current) end; {tool_call_end, _, _} -> case Current of {some, Acc@1} -> Entry = {erlang:element(2, Acc@1), erlang:element(3, Acc@1), unicode:characters_to_binary( erlang:element(4, Acc@1) )}, collect_tool_calls_loop( Rest, [Entry | Completed], none ); none -> collect_tool_calls_loop(Rest, Completed, Current) end; _ -> collect_tool_calls_loop(Rest, Completed, Current) end end. -file("src/glean/stream.gleam", 58). ?DOC( " Extract all completed tool calls from stream events.\n" " Returns a list of (tool_call_id, tool_name, arguments_json) tuples.\n" ). -spec collect_tool_calls(list(stream_event())) -> list({binary(), binary(), binary()}). collect_tool_calls(Events) -> collect_tool_calls_loop(Events, [], none). -file("src/glean/stream.gleam", 118). ?DOC(" Add usage from two Usage values together.\n"). -spec add_usage(usage(), usage()) -> usage(). add_usage(A, B) -> {usage, erlang:element(2, A) + erlang:element(2, B), erlang:element(3, A) + erlang:element(3, B)}. -file("src/glean/stream.gleam", 126). ?DOC(" Zero usage (useful as initial accumulator).\n"). -spec zero_usage() -> usage(). zero_usage() -> {usage, 0, 0}.