Real-time terminal visualization for PlanExecutor events.
PlanTracer formats plan execution events into a hierarchical tree view with ANSI colors, providing immediate feedback during development and debugging.
Quick Usage
For simple logging without state tracking:
{:ok, metadata} = PlanExecutor.execute(plan, mission,
llm: my_llm,
on_event: &PlanTracer.log_event/1
)Stateful Tree View
For proper hierarchical output with indentation:
{:ok, tracer} = PlanTracer.start()
{:ok, metadata} = PlanExecutor.execute(plan, mission,
llm: my_llm,
on_event: &PlanTracer.handle_event(tracer, &1)
)
PlanTracer.stop(tracer)Example Output
Mission: Research stock prices
[START] fetch_symbols
[✓] fetch_symbols (150ms)
[START] fetch_prices
[!] fetch_prices - Verification failed: "Count < 5"
REPLAN #1 (fetch_prices: "Count < 5")
Repair plan: 2 tasks
[-] fetch_symbols (Skipped)
[START] fetch_prices
[✓] fetch_prices (400ms)
Execution finished: ok (1250ms)ANSI Colors
- Green (✓): Successful tasks
- Yellow (!): Verification failures, replans
- Red (✗): Task failures
- Cyan (-): Skipped tasks
- Bold: Mission and replan headers
See the Observability Guide for turn history, telemetry events,
and how PlanTracer relates to PtcRunner.Tracer and PtcRunner.TraceLog.
Summary
Functions
Returns a specification to start this module under a supervisor.
Formats an event into a displayable string.
Handles an event with state tracking.
Creates an event handler function bound to a tracer.
Simple stateless event logger.
Starts a stateful tracer for hierarchical output.
Stops the tracer.
Types
@type state() :: %{ mission: String.t() | nil, indent: non_neg_integer(), replan_count: non_neg_integer(), output: :logger | :io }
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec format_event(PtcRunner.PlanExecutor.event()) :: String.t()
Formats an event into a displayable string.
This is the core formatting function used by both log_event/1 and
the stateful tracer. Exposed for testing purposes.
@spec handle_event(pid(), PtcRunner.PlanExecutor.event()) :: :ok
Handles an event with state tracking.
Returns a function suitable for use as on_event callback.
Example
on_event = fn event -> PlanTracer.handle_event(tracer, event) end
PlanExecutor.execute(plan, mission, llm: llm, on_event: on_event)
@spec handler(pid()) :: (PtcRunner.PlanExecutor.event() -> :ok)
Creates an event handler function bound to a tracer.
Example
{:ok, tracer} = PlanTracer.start()
handler = PlanTracer.handler(tracer)
PlanExecutor.execute(plan, mission, llm: llm, on_event: handler)
@spec log_event(PtcRunner.PlanExecutor.event()) :: :ok
Simple stateless event logger.
Formats each event with colors and logs via Logger.info. No state tracking - suitable for quick debugging.
Example
PlanExecutor.execute(plan, mission,
llm: my_llm,
on_event: &PlanTracer.log_event/1
)
Starts a stateful tracer for hierarchical output.
Options
:output- Where to send output::logger(default) or:io
Example
{:ok, tracer} = PlanTracer.start(output: :io)
@spec stop(pid()) :: :ok
Stops the tracer.