Consume Glean's streaming endpoints as they arrive.
Generated operations buffer the whole response before returning, which is the
right thing for ordinary calls and the wrong thing for a chat or agent run
that is meant to appear a token at a time. These functions send the same
requests but hand back a Stream.
Glean uses two wire formats and this module covers both:
- agent runs are
text/event-stream, decoded byGleanex.SSE - chat is newline-delimited JSON, decoded by
Gleanex.NDJSON
Consuming a stream
The response is delivered to the process that made the request, so the stream must be consumed in that same process, and only once.
Examples
{:ok, events} = Gleanex.Streaming.agent_run(config, %{agentId: "abc", input: %{}})
for event <- events do
case Gleanex.SSE.json_data(event) do
{:ok, payload} -> IO.inspect(payload)
{:error, _} -> :ok
end
end
{:ok, chunks} = Gleanex.Streaming.chat(config, %{messages: messages})
chunks
|> Stream.flat_map(&get_in(&1, ["messages", Access.all(), "fragments"]))
|> Enum.each(&IO.write/1)Failures before the first byte arrive as {:error, %Gleanex.Error{}}. A
failure part way through a stream raises while the stream is being consumed,
because by then a response has already been reported as successful.
Summary
Functions
Stream a Client API agent run as server-sent events.
Stream a chat response, one ChatResponse per element.
Stream a Platform API agent run as server-sent events.
Types
@type stream() :: Enumerable.t()
A lazily consumed response body.
Functions
@spec agent_run(Gleanex.Config.t(), map(), keyword()) :: {:ok, stream()} | {:error, Gleanex.Error.t()}
Stream a Client API agent run as server-sent events.
Calls POST /agents/runs/stream, the streaming counterpart of
Gleanex.Client.Agents.create_and_wait_run/2.
@spec chat(Gleanex.Config.t(), map(), keyword()) :: {:ok, stream()} | {:error, Gleanex.Error.t()}
Stream a chat response, one ChatResponse per element.
Sets stream: true in the request body; anything you pass wins over that, so
it can be turned back off if you want the buffered form.
Bodies are returned as plain decoded maps rather than
Gleanex.Client.ChatResponse structs, because each streamed line is a partial
response and the struct's shape would imply more than has actually arrived.
@spec platform_agent_run(Gleanex.Config.t(), String.t(), map(), keyword()) :: {:ok, stream()} | {:error, Gleanex.Error.t()}
Stream a Platform API agent run as server-sent events.
Calls POST /agents/{agent_id}/runs with stream set, the streaming form of
Gleanex.Platform.Agents.create_run/3.