Class: Protege::Event

Inherits:
Object
  • Object
show all
Defined in:
lib/protege/events/event.rb

Overview

Base class for every Protege event — both the typed, nil-safe wrapper handed to subscribers and the class-level publish/subscribe surface. Concrete events are one flat class each (+InferenceStartedEvent+, ToolCallCompletedEvent, …) in lib/protege/events/ (a collapsed autoload dir, so they read as Protege:: rather than Protege::Events::), mirroring the Protege::*Error hierarchy.

Each subclass declares its ActiveSupport::Notifications topic with the channel class macro (the same class-attribute style as a provider's protege_id) and writes a plain reader per payload key. Publishing and subscribing go through the subclass:

Protege::InferenceCompletedEvent.emit(persona:, message:, result:)   # engine internals
Protege::InferenceCompletedEvent.subscribe { |event| event.result }  # host / broadcaster

correlation_id is injected automatically from Protege::Current into every emitted event — set it once in AgentMailbox and it rides through the whole processing run. A subscriber's block receives a frozen instance of the specific event class, so event.persona / event.result read the payload with named, nil-safe accessors (and event[:key] reaches anything without a dedicated reader).

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(payload) ⇒ void

Wrap a raw notification payload; frozen so subscribers can't mutate shared state.

Parameters:

  • payload (Hash)

    the event payload as published by emit



28
29
30
31
# File 'lib/protege/events/event.rb', line 28

def initialize(payload)
  @payload = payload
  freeze
end

Instance Attribute Details

#payloadHash (readonly)

Returns the underlying payload hash.

Returns:

  • (Hash)

    the underlying payload hash



22
23
24
# File 'lib/protege/events/event.rb', line 22

def payload
  @payload
end

Class Method Details

.allArray<Class>

Every concrete event class, in fire order. Built lazily on first call (at boot, by Subscribers::HookDispatcher.install!), so each subclass is autoloaded only when referenced here — after this base and its channel macro are defined — keeping lib/ autoload-only with no load-order constraint.

Returns:

  • (Array<Class>)

    the event classes



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/protege/events/event.rb', line 78

def all
  @all ||= [
    InferenceStartedEvent,
    InferenceGeneratedEvent,
    InferenceCompletedEvent,
    InferenceFailedEvent,
    ToolCallsReceivedEvent,
    ToolCallStartedEvent,
    ToolCallCompletedEvent,
    ToolCallFailedEvent,
    InferenceMaxTurnsReachedEvent,
    InferenceChunkEvent,
    LoopRunEnqueuedEvent,
    LoopRunStartedEvent,
    LoopRunCompletedEvent,
    LoopRunFailedEvent
  ].freeze
end

.channel(value = nil) ⇒ String

Declare (with an argument) or read (without) this event's ActiveSupport::Notifications topic. Called in the subclass body — the same class-attribute idiom as a provider's protege_id.

Parameters:

  • value (String, nil) (defaults to: nil)

    the topic to set, or nil to read the declared one

Returns:

  • (String)

    the topic



48
49
50
# File 'lib/protege/events/event.rb', line 48

def channel(value = nil)
  value ? @channel = value : @channel
end

.emit(**payload) ⇒ void

This method returns an undefined value.

Publish this event, injecting correlation_id from Protege::Current so callers never pass it.

Parameters:

  • payload (Hash)

    the event's payload keyed by symbol



56
57
58
59
60
# File 'lib/protege/events/event.rb', line 56

def emit(**payload)
  ActiveSupport::Notifications.instrument(channel,
                                          correlation_id: Protege::Current.correlation_id,
                                          **payload)
end

.subscribe {|event| ... } ⇒ Object

Subscribe to this event, yielding a typed instance of this class (not the raw payload hash).

Yield Parameters:

Returns:

  • (Object)

    the subscription handle returned by ActiveSupport::Notifications



66
67
68
69
70
# File 'lib/protege/events/event.rb', line 66

def subscribe(&block)
  ActiveSupport::Notifications.subscribe(channel) do |_name, _start, _finish, _id, payload|
    block.call new(payload)
  end
end

Instance Method Details

#[](key) ⇒ Object?

Read an arbitrary payload key not covered by a named reader.

Parameters:

  • key (Symbol)

    the payload key

Returns:

  • (Object, nil)

    the value, or nil when absent



40
# File 'lib/protege/events/event.rb', line 40

def [](key) = @payload[key]

#correlation_idString?

Returns the per-run correlation id injected by emit.

Returns:

  • (String, nil)

    the per-run correlation id injected by emit



34
# File 'lib/protege/events/event.rb', line 34

def correlation_id = @payload[:correlation_id]