activematrix 0.0.4 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ConversationContext < ApplicationRecord
4
- belongs_to :matrix_agent
5
-
6
- validates :user_id, presence: true
7
- validates :room_id, presence: true
8
- validates :user_id, uniqueness: { scope: %i[matrix_agent_id room_id] }
9
-
10
- # Configuration
11
- MAX_HISTORY_SIZE = 20
12
-
13
- # Scopes
14
- scope :recent, -> { order(last_message_at: :desc) }
15
- scope :active, -> { where('last_message_at > ?', 1.hour.ago) }
16
- scope :stale, -> { where('last_message_at < ?', 1.day.ago) }
17
-
18
- # Add a message to the history
19
- def add_message(message_data)
20
- messages = message_history['messages'] || []
21
-
22
- # Add new message
23
- messages << {
24
- 'event_id' => message_data[:event_id],
25
- 'sender' => message_data[:sender],
26
- 'content' => message_data[:content],
27
- 'timestamp' => message_data[:timestamp] || Time.current.to_i
28
- }
29
-
30
- # Keep only recent messages
31
- messages = messages.last(MAX_HISTORY_SIZE)
32
-
33
- # Update record
34
- self.message_history = { 'messages' => messages }
35
- self.last_message_at = Time.current
36
- self.message_count = messages.size
37
- save!
38
-
39
- # Update cache
40
- write_to_cache
41
- end
42
-
43
- # Get recent messages
44
- def recent_messages(limit = 10)
45
- messages = message_history['messages'] || []
46
- messages.last(limit)
47
- end
48
-
49
- # Clear old messages but keep context
50
- def prune_history!
51
- messages = message_history['messages'] || []
52
- self.message_history = { 'messages' => messages.last(5) }
53
- save!
54
- end
55
-
56
- # Cache integration
57
- def cache_key
58
- "conversation/#{matrix_agent_id}/#{user_id}/#{room_id}"
59
- end
60
-
61
- def write_to_cache
62
- Rails.cache.write(cache_key, {
63
- context: context,
64
- recent_messages: recent_messages,
65
- last_message_at: last_message_at
66
- }, expires_in: 1.hour)
67
- end
68
-
69
- def self.cleanup_stale!
70
- stale.destroy_all
71
- end
72
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class GlobalMemory < ApplicationRecord
4
- validates :key, presence: true, uniqueness: true
5
-
6
- scope :active, -> { where('expires_at IS NULL OR expires_at > ?', Time.current) }
7
- scope :expired, -> { where('expires_at <= ?', Time.current) }
8
- scope :by_category, ->(category) { where(category: category) }
9
- scope :readable, -> { where(public_read: true) }
10
- scope :writable, -> { where(public_write: true) }
11
-
12
- def expired?
13
- expires_at.present? && expires_at <= Time.current
14
- end
15
-
16
- def readable_by?(agent)
17
- public_read || (agent.is_a?(MatrixAgent) && agent.admin?)
18
- end
19
-
20
- def writable_by?(agent)
21
- public_write || (agent.is_a?(MatrixAgent) && agent.admin?)
22
- end
23
-
24
- # Cache integration
25
- def cache_key
26
- "global/#{key}"
27
- end
28
-
29
- def write_to_cache
30
- return unless active?
31
-
32
- ttl = expires_at.present? ? expires_at - Time.current : nil
33
- Rails.cache.write(cache_key, value, expires_in: ttl)
34
- end
35
-
36
- def self.get(key)
37
- # Try cache first
38
- cached = Rails.cache.read("global/#{key}")
39
- return cached if cached.present?
40
-
41
- # Fallback to database
42
- memory = find_by(key: key)
43
- return unless memory&.active?
44
-
45
- memory.write_to_cache
46
- memory.value
47
- end
48
-
49
- def self.set(key, value, category: nil, expires_in: nil, public_read: true, public_write: false)
50
- memory = find_or_initialize_by(key: key)
51
- memory.value = value
52
- memory.category = category
53
- memory.expires_at = expires_in.present? ? Time.current + expires_in : nil
54
- memory.public_read = public_read
55
- memory.public_write = public_write
56
- memory.save!
57
- memory.write_to_cache
58
- memory
59
- end
60
-
61
- def self.cleanup_expired!
62
- expired.destroy_all
63
- end
64
-
65
- private
66
-
67
- def active?
68
- !expired?
69
- end
70
- end
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class MatrixAgent < ApplicationRecord
4
- # Associations
5
- has_many :agent_memories, dependent: :destroy
6
- has_many :conversation_contexts, dependent: :destroy
7
-
8
- # Validations
9
- validates :name, presence: true, uniqueness: true
10
- validates :homeserver, presence: true
11
- validates :username, presence: true
12
- validates :bot_class, presence: true
13
- validate :valid_bot_class?
14
-
15
- # Scopes
16
- scope :active, -> { where.not(state: %i[offline error]) }
17
- scope :online, -> { where(state: %i[online_idle online_busy]) }
18
- scope :offline, -> { where(state: :offline) }
19
-
20
- # Encrypts password before saving
21
- before_save :encrypt_password, if: :password_changed?
22
-
23
- # State machine for agent lifecycle
24
- state_machine :state, initial: :offline do
25
- state :offline
26
- state :connecting
27
- state :online_idle
28
- state :online_busy
29
- state :error
30
- state :paused
31
-
32
- event :connect do
33
- transition %i[offline error paused] => :connecting
34
- end
35
-
36
- event :connection_established do
37
- transition connecting: :online_idle
38
- end
39
-
40
- after_transition to: :online_idle do |agent|
41
- agent.update(last_active_at: Time.current)
42
- end
43
-
44
- event :start_processing do
45
- transition online_idle: :online_busy
46
- end
47
-
48
- event :finish_processing do
49
- transition online_busy: :online_idle
50
- end
51
-
52
- event :disconnect do
53
- transition %i[connecting online_idle online_busy] => :offline
54
- end
55
-
56
- event :encounter_error do
57
- transition any => :error
58
- end
59
-
60
- event :pause do
61
- transition %i[online_idle online_busy] => :paused
62
- end
63
-
64
- event :resume do
65
- transition paused: :connecting
66
- end
67
- end
68
-
69
- # Instance methods
70
- def bot_instance
71
- @bot_instance ||= bot_class.constantize.new(client) if running?
72
- end
73
-
74
- def client
75
- @client ||= if access_token.present?
76
- ActiveMatrix::Client.new(homeserver, access_token: access_token)
77
- else
78
- ActiveMatrix::Client.new(homeserver)
79
- end
80
- end
81
-
82
- def running?
83
- %i[online_idle online_busy].include?(state.to_sym)
84
- end
85
-
86
- def memory
87
- @memory ||= ActiveMatrix::Memory::AgentMemory.new(self)
88
- end
89
-
90
- def increment_messages_handled!
91
- increment!(:messages_handled)
92
- end
93
-
94
- def update_activity!
95
- update(last_active_at: Time.current)
96
- end
97
-
98
- # Password handling
99
- attr_accessor :password
100
-
101
- def authenticate(password)
102
- return false unless encrypted_password.present?
103
-
104
- BCrypt::Password.new(encrypted_password) == password
105
- end
106
-
107
- private
108
-
109
- def password_changed?
110
- password.present?
111
- end
112
-
113
- def encrypt_password
114
- self.encrypted_password = BCrypt::Password.create(password) if password.present?
115
- end
116
-
117
- def valid_bot_class?
118
- return false if bot_class.blank?
119
-
120
- begin
121
- klass = bot_class.constantize
122
- errors.add(:bot_class, 'must inherit from ActiveMatrix::Bot::Base') unless klass < ActiveMatrix::Bot::Base
123
- rescue NameError
124
- errors.add(:bot_class, 'must be a valid class name')
125
- end
126
- end
127
- end