Class EventEmitter

java.lang.Object
dyntabs.ai.event.EventEmitter

public final class EventEmitter extends Object
Internal helper each EasyAI capability uses to produce EasyAIEvents and push them to a registered EasyAIListener.

What this class is for

It removes boilerplate and enforces three guarantees so individual capabilities don't have to re-implement them: it (1) stamps every event with a 1-based EasyAIEvent.sequence() and a timestamp, (2) is a no-op when no listener is registered, and (3) never throws — a misbehaving listener can never break the AI operation it is observing.

Familiar analogy: a stadium's play-by-play commentator assigned to one match. It is created knowing which match it covers (EasyAIEvent.Source), it numbers its calls in order, and if the broadcast booth's microphone fails (the listener throws), the match on the field carries on regardless.

Where it is used in the chain

   AgentBuilder.build()
        → new EventEmitter(Source.AGENT, listener)   // one per operation
        → emitter.started("Planning task")
        → emitter.stepStarted("checkStock", "...")    // pre-step (spinner)
        → emitter.step("checkStock", "→ 42 in stock", Status.SUCCESS)
        → emitter.finished("Task complete")
 

It is public only because EasyAI builders live in the parent package dyntabs.ai; treat it as library-internal — application code interacts with events via EasyAIListener, not this producer.

One EventEmitter should be created per logical operation (per agent run, per index call, per extraction) so its sequence numbering restarts at 1 for each. It is thread-safe in the sense that sequence assignment is atomic, but it is intended for single-operation use.

See Also:
  • Constructor Details

    • EventEmitter

      public EventEmitter(EasyAIEvent.Source source, EasyAIListener listener)
      Create an emitter for one capability and one (optional) listener.
      Parameters:
      source - the capability that will be stamped on every event (required)
      listener - the subscriber to notify, or null to disable emission entirely
  • Method Details

    • isActive

      public boolean isActive()
      Returns:
      true if a listener is registered. Capabilities can guard expensive detail-string building behind this check (e.g. avoid serializing large results when nobody is listening).
    • started

      public void started(String title)
      Emit a "the operation has begun" event (EasyAIEvent.Phase.STARTED, EasyAIEvent.Status.RUNNING).
      Parameters:
      title - short label for the start of the operation (e.g. "Planning task")
    • stepStarted

      public void stepStarted(String toolName, String detail)
      Emit a "a unit of work is about to run" event (EasyAIEvent.Phase.STEP_STARTED, EasyAIEvent.Status.RUNNING). Lets a UI show a spinning row before the result is known.
      Parameters:
      toolName - the tool/method being dispatched (may be null)
      detail - optional description of the pending work (e.g. the arguments)
    • step

      public void step(String toolName, String detail, EasyAIEvent.Status status)
      Emit a "a unit of work just completed" event (EasyAIEvent.Phase.STEP).
      Parameters:
      toolName - the tool/method that ran (may be null)
      detail - short description of what came back (e.g. "args → result")
      status - EasyAIEvent.Status.SUCCESS or EasyAIEvent.Status.ERROR
    • progress

      public void progress(String title, String detail)
      Emit an incremental progress event (EasyAIEvent.Phase.PROGRESS, EasyAIEvent.Status.RUNNING).
      Parameters:
      title - short label (e.g. "Indexing documents")
      detail - progress detail (e.g. "document 7 of 200")
    • result

      public void result(String title, String detail)
      Emit a "a meaningful result was produced" event (EasyAIEvent.Phase.RESULT, EasyAIEvent.Status.SUCCESS).
      Parameters:
      title - short label (e.g. "Extracted Invoice")
      detail - optional result detail
    • retry

      public void retry(String title, String detail)
      Emit a "retrying after a failed attempt" event (EasyAIEvent.Phase.RETRY, EasyAIEvent.Status.WARNING).
      Parameters:
      title - short label (e.g. "Retrying extraction")
      detail - why the retry is happening (e.g. "malformed JSON, attempt 2 of 3")
    • finished

      public void finished(String title)
      Emit a "the operation finished successfully" event (EasyAIEvent.Phase.FINISHED, EasyAIEvent.Status.SUCCESS).
      Parameters:
      title - short closing label (e.g. "Task complete")
    • error

      public void error(String title, String detail)
      Parameters:
      title - short label (e.g. "Agent failed")
      detail - the readable error message
    • emit

      public void emit(EasyAIEvent.Builder builder)
      Finalize a builder (assign sequence + deliver) and hand it to the listener.

      This is the single choke point through which every convenience method flows, so the no-listener short-circuit and the never-throw guarantee live here once. A listener that throws is swallowed deliberately: observation must never change the outcome of the work being observed.

      Parameters:
      builder - a partially-populated event builder; sequence is stamped here