Class: ActiveMatrix::Bot::MultiInstanceBase

Inherits:
Base
  • Object
show all
Defined in:
lib/active_matrix/bot/multi_instance_base.rb,
lib/active_matrix/event_router.rb

Overview

Base class for multi-instance bot support

Defined Under Namespace

Classes: SettingsProxy

Constant Summary

Constants inherited from Base

Base::CALLERS_TO_IGNORE, Base::EMPTY_BOT_FILTER

Instance Attribute Summary collapse

Attributes inherited from Base

#client, #event, #logger

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

all_handlers, #bot, client, command, command?, #command?, #command_allowed?, disable, enable, event, #event?, event?, #event_allowed?, #expanded_prefix, #get_command, get_command, #get_event, get_event, #in_event?, logger, quit!, #register_command, #register_event, remove_command, remove_event, reset!, #room, run!, running?, #sender, #sender_admin?, #sender_moderator?, set, settings, #unregister_command, #unregister_event

Methods included from Extensions

#events, #ignore_inspect

Methods included from Logging

included, #logger, #logger=

Constructor Details

#initialize(client_or_agent, **params) ⇒ MultiInstanceBase

Returns a new instance of MultiInstanceBase.



8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 8

def initialize(client_or_agent, **params)
  # Handle both client and agent record initialization
  if client_or_agent.respond_to?(:homeserver) && !client_or_agent.respond_to?(:client) # It's a client
    super
    @agent_record = params[:agent_record]
  else # It's an agent record
    @agent_record = client_or_agent
    super(@agent_record.client, **params)
  end

  setup_agent_context if @agent_record
end

Instance Attribute Details

#agent_recordObject (readonly)

Returns the value of attribute agent_record.



6
7
8
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 6

def agent_record
  @agent_record
end

Class Method Details

.event_routesObject

Get defined routes



189
190
191
# File 'lib/active_matrix/event_router.rb', line 189

def self.event_routes
  @event_routes || []
end

.route(event_type: nil, room_id: nil, user_id: nil, priority: 50, &block) ⇒ Object

Route events to this bot



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/active_matrix/event_router.rb', line 176

def self.route(event_type: nil, room_id: nil, user_id: nil, priority: 50, &block)
  # Routes will be registered when bot instance is created
  @event_routes ||= []
  @event_routes << {
    event_type: event_type,
    room_id: room_id,
    user_id: user_id,
    priority: priority,
    handler: block
  }
end

Instance Method Details

#_handle_event(event) ⇒ Object



123
124
125
126
127
128
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 123

def _handle_event(event)
  mark_busy!
  super
ensure
  mark_idle!
end

#_handle_message(event) ⇒ Object

Override event handling to track conversation



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 110

def _handle_message(event)
  # Mark as busy while processing
  mark_busy!

  # Track conversation if we have an agent record
  conversation_memory(event[:sender], event[:room_id])&.add_message(event) if @agent_record && event[:type] == 'm.room.message'

  super
ensure
  # Mark as idle when done
  mark_idle!
end

#agent_nameObject

Agent state helpers



59
60
61
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 59

def agent_name
  @agent_record&.name || settings.bot_name
end

#agent_stateObject



63
64
65
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 63

def agent_state
  @agent_record&.state || 'unknown'
end

#broadcast_to_agents(selector, data) ⇒ Object

Inter-agent communication



76
77
78
79
80
81
82
83
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 76

def broadcast_to_agents(selector, data)
  return unless defined?(AgentRegistry)

  registry = AgentRegistry.instance
  registry.broadcast_to(selector) do |agent_bot|
    agent_bot.receive_broadcast(data, from: self)
  end
end

#clear_routesObject

Clear routes for this instance



208
209
210
211
212
# File 'lib/active_matrix/event_router.rb', line 208

def clear_routes
  return unless @agent_record

  EventRouter.instance.clear_agent_routes(@agent_record.id)
end

#conversation_contextObject

Get current conversation context



44
45
46
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 44

def conversation_context
  conversation_memory&.context || {}
end

#conversation_memory(user_id = nil, room_id = nil) ⇒ Object

Access conversation memory



27
28
29
30
31
32
33
34
35
36
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 27

def conversation_memory(user_id = nil, room_id = nil)
  user_id ||= event[:sender] if in_event?
  room_id ||= event[:room_id] if in_event?

  return nil unless user_id && room_id

  @conversation_memories ||= {}
  @conversation_memories["#{user_id}/#{room_id}"] ||=
    ActiveMatrix::Memory.for_conversation(@agent_record, user_id, room_id)
end

#global_memoryObject

Access global memory



39
40
41
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 39

def global_memory
  ActiveMatrix::Memory.global
end

#mark_busy!Object



67
68
69
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 67

def mark_busy!
  @agent_record&.start_processing! if @agent_record&.may_start_processing?
end

#mark_idle!Object



71
72
73
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 71

def mark_idle!
  @agent_record&.finish_processing! if @agent_record&.may_finish_processing?
end

#memoryObject

Access agent-specific memory



22
23
24
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 22

def memory
  @memory ||= ActiveMatrix::Memory.for_agent(@agent_record)
end

#receive_broadcast(data, from:) ⇒ Object



105
106
107
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 105

def receive_broadcast(data, from:)
  logger.debug "Received broadcast from #{from.agent_name}: #{data.inspect}"
end

#receive_message(data, from:) ⇒ Object

Receive inter-agent messages (override in subclasses)



101
102
103
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 101

def receive_message(data, from:)
  logger.debug "Received message from #{from.agent_name}: #{data.inspect}"
end

#register_routesObject

Register routes for this instance



194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/active_matrix/event_router.rb', line 194

def register_routes
  return unless @agent_record

  router = EventRouter.instance

  self.class.event_routes.each do |route_def|
    router.register_route(
      agent_id: @agent_record.id,
      **route_def
    )
  end
end

#remember_in_conversation(key) ⇒ Object

Remember something in conversation



54
55
56
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 54

def remember_in_conversation(key, &)
  conversation_memory&.remember(key, &)
end

#send_to_agent(agent_name, data) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 85

def send_to_agent(agent_name, data)
  return unless defined?(AgentRegistry)

  registry = AgentRegistry.instance
  entry = registry.get_by_name(agent_name)

  if entry
    entry[:instance].receive_message(data, from: self)
    true
  else
    logger.warn "Agent #{agent_name} not found or not running"
    false
  end
end

#settingsObject

Enhanced settings with agent-specific overrides



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 131

def settings
  return self.class unless @agent_record

  # Merge agent-specific settings with class settings
  @settings ||= begin
    base_settings = self.class.settings
    agent_settings = @agent_record.settings || {}

    # Create a settings proxy that checks agent settings first
    SettingsProxy.new(base_settings, agent_settings)
  end
end

#update_context(data) ⇒ Object

Update conversation context



49
50
51
# File 'lib/active_matrix/bot/multi_instance_base.rb', line 49

def update_context(data)
  conversation_memory&.update_context(data)
end