Packages

A Gleam framework for building AI agents — type-safe, multi-provider, with tool calling, streaming, and simulation testing

Current section

Files

Jump to
glean src glean@stream.erl
Raw

src/glean@stream.erl

-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}.