PtcRunner.PlanTracer (PtcRunner v0.7.0)

Copy Markdown View Source

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

state()

@type state() :: %{
  mission: String.t() | nil,
  indent: non_neg_integer(),
  replan_count: non_neg_integer(),
  output: :logger | :io
}

Functions

child_spec(arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

format_event(event)

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

handle_event(tracer, event)

@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)

handler(tracer)

@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)

log_event(event)

@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
)

start(opts \\ [])

@spec start(keyword()) :: {:ok, pid()}

Starts a stateful tracer for hierarchical output.

Options

  • :output - Where to send output: :logger (default) or :io

Example

{:ok, tracer} = PlanTracer.start(output: :io)

stop(tracer)

@spec stop(pid()) :: :ok

Stops the tracer.