Current section
Files
Jump to
Current section
Files
examples/streaming.exs
#!/usr/bin/env mix run
alias Codex.Items
alias Codex.Events
defmodule Examples.Streaming do
@moduledoc false
def realtime_stream do
{:ok, thread} = Codex.start_thread()
{:ok, stream} =
Codex.Thread.run_streamed(
thread,
"Inspect the project structure and call out any missing README sections"
)
Enum.each(stream, &handle_event/1)
end
def progressive_story do
{:ok, thread} = Codex.start_thread()
{:ok, stream} =
Codex.Thread.run_streamed(thread, "Write a short story about a robot learning Elixir")
stream
|> Stream.filter(fn
%Events.ItemCompleted{item: %Items.AgentMessage{}} -> true
_ -> false
end)
|> Enum.each(fn %Events.ItemCompleted{item: %Items.AgentMessage{text: text}} ->
text
|> String.graphemes()
|> Enum.each(fn char ->
IO.write(char)
Process.sleep(20)
end)
IO.puts("\n")
end)
end
def stateful_stream do
{:ok, thread} = Codex.start_thread()
{:ok, stream} =
Codex.Thread.run_streamed(thread, "Implement a new feature across the codebase")
final_state =
Enum.reduce(stream, initial_state(), fn event, state ->
case event do
%Events.ThreadStarted{thread_id: id} ->
%{state | thread_id: id}
%Events.ItemCompleted{item: %Items.CommandExecution{} = cmd} ->
%{state | commands: [cmd | state.commands]}
%Events.ItemCompleted{item: %Items.FileChange{} = file} ->
%{state | files: [file | state.files]}
%Events.ItemCompleted{item: %Items.AgentMessage{text: text}} ->
%{state | messages: [text | state.messages]}
%Events.TurnCompleted{usage: usage} when is_map(usage) ->
%{state | usage: usage}
_ ->
state
end
end)
IO.inspect(final_state, label: "stream summary")
end
defp handle_event(%Events.ThreadStarted{thread_id: id}) do
IO.puts("Started thread #{id}")
end
defp handle_event(%Events.TurnStarted{}), do: IO.puts("Turn started…")
defp handle_event(%Events.ItemStarted{item: %Items.CommandExecution{command: command}}) do
IO.puts("Executing command: #{command}")
end
defp handle_event(%Events.ItemCompleted{item: %Items.AgentMessage{text: text}}) do
IO.puts("\n=== Agent Message ===\n#{text}")
end
defp handle_event(%Events.TurnCompleted{usage: usage}) do
IO.puts("\nTurn completed (usage=#{inspect(usage)})")
end
defp handle_event(_), do: :ok
defp initial_state do
%{
thread_id: nil,
commands: [],
files: [],
messages: [],
usage: nil
}
end
end
case System.argv() do
["progressive"] ->
Examples.Streaming.progressive_story()
["stateful"] ->
Examples.Streaming.stateful_stream()
["help"] ->
IO.puts("""
mix run examples/streaming.exs [command]
(no arg) – run the real-time streaming example
progressive – stream output character by character
stateful – accumulate streaming state in a map
help – show this usage
""")
_ ->
Examples.Streaming.realtime_stream()
end