activematrix 0.0.5 → 0.0.8

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +96 -28
  3. data/app/jobs/active_matrix/application_job.rb +11 -0
  4. data/app/models/active_matrix/agent/jobs/memory_reaper.rb +87 -0
  5. data/app/models/active_matrix/agent.rb +166 -0
  6. data/app/models/active_matrix/agent_store.rb +80 -0
  7. data/app/models/active_matrix/application_record.rb +15 -0
  8. data/app/models/active_matrix/chat_session.rb +105 -0
  9. data/app/models/active_matrix/knowledge_base.rb +100 -0
  10. data/exe/activematrix +7 -0
  11. data/lib/active_matrix/agent_manager.rb +160 -121
  12. data/lib/active_matrix/agent_registry.rb +25 -21
  13. data/lib/active_matrix/api.rb +8 -2
  14. data/lib/active_matrix/async_query.rb +58 -0
  15. data/lib/active_matrix/bot/base.rb +3 -3
  16. data/lib/active_matrix/bot/builtin_commands.rb +188 -0
  17. data/lib/active_matrix/bot/command_parser.rb +175 -0
  18. data/lib/active_matrix/cli.rb +273 -0
  19. data/lib/active_matrix/client.rb +21 -6
  20. data/lib/active_matrix/client_pool.rb +38 -27
  21. data/lib/active_matrix/daemon/probe_server.rb +118 -0
  22. data/lib/active_matrix/daemon/signal_handler.rb +156 -0
  23. data/lib/active_matrix/daemon/worker.rb +109 -0
  24. data/lib/active_matrix/daemon.rb +236 -0
  25. data/lib/active_matrix/engine.rb +18 -0
  26. data/lib/active_matrix/errors.rb +1 -1
  27. data/lib/active_matrix/event_router.rb +61 -49
  28. data/lib/active_matrix/events.rb +1 -0
  29. data/lib/active_matrix/instrumentation.rb +148 -0
  30. data/lib/active_matrix/memory/agent_memory.rb +7 -21
  31. data/lib/active_matrix/memory/conversation_memory.rb +4 -20
  32. data/lib/active_matrix/memory/global_memory.rb +15 -30
  33. data/lib/active_matrix/message_dispatcher.rb +197 -0
  34. data/lib/active_matrix/metrics.rb +424 -0
  35. data/lib/active_matrix/presence_manager.rb +181 -0
  36. data/lib/active_matrix/railtie.rb +8 -0
  37. data/lib/active_matrix/telemetry.rb +134 -0
  38. data/lib/active_matrix/version.rb +1 -1
  39. data/lib/active_matrix.rb +18 -11
  40. data/lib/generators/active_matrix/install/install_generator.rb +3 -22
  41. data/lib/generators/active_matrix/install/templates/README +5 -2
  42. metadata +191 -31
  43. data/lib/generators/active_matrix/install/templates/agent_memory.rb +0 -47
  44. data/lib/generators/active_matrix/install/templates/conversation_context.rb +0 -72
  45. data/lib/generators/active_matrix/install/templates/create_agent_memories.rb +0 -17
  46. data/lib/generators/active_matrix/install/templates/create_conversation_contexts.rb +0 -21
  47. data/lib/generators/active_matrix/install/templates/create_global_memories.rb +0 -20
  48. data/lib/generators/active_matrix/install/templates/create_matrix_agents.rb +0 -26
  49. data/lib/generators/active_matrix/install/templates/global_memory.rb +0 -70
  50. data/lib/generators/active_matrix/install/templates/matrix_agent.rb +0 -127
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activematrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
8
  - Alexander Olofsson
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
11
  date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: maxitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: opentelemetry-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: mocha
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +52,20 @@ dependencies:
24
52
  - - ">="
25
53
  - !ruby/object:Gem::Version
26
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: state_machines-mermaid
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: ostruct
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +80,20 @@ dependencies:
38
80
  - - ">="
39
81
  - !ruby/object:Gem::Version
40
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails_lens
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
41
97
  - !ruby/object:Gem::Dependency
42
98
  name: rake
43
99
  requirement: !ruby/object:Gem::Requirement
@@ -178,76 +234,150 @@ dependencies:
178
234
  - - "~>"
179
235
  - !ruby/object:Gem::Version
180
236
  version: '3.19'
237
+ - !ruby/object:Gem::Dependency
238
+ name: activejob
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '8.0'
244
+ - - "<"
245
+ - !ruby/object:Gem::Version
246
+ version: '9'
247
+ type: :runtime
248
+ prerelease: false
249
+ version_requirements: !ruby/object:Gem::Requirement
250
+ requirements:
251
+ - - ">="
252
+ - !ruby/object:Gem::Version
253
+ version: '8.0'
254
+ - - "<"
255
+ - !ruby/object:Gem::Version
256
+ version: '9'
181
257
  - !ruby/object:Gem::Dependency
182
258
  name: activerecord
183
259
  requirement: !ruby/object:Gem::Requirement
184
260
  requirements:
185
- - - "~>"
261
+ - - ">="
186
262
  - !ruby/object:Gem::Version
187
263
  version: '8.0'
264
+ - - "<"
265
+ - !ruby/object:Gem::Version
266
+ version: '9'
188
267
  type: :runtime
189
268
  prerelease: false
190
269
  version_requirements: !ruby/object:Gem::Requirement
191
270
  requirements:
192
- - - "~>"
271
+ - - ">="
193
272
  - !ruby/object:Gem::Version
194
273
  version: '8.0'
274
+ - - "<"
275
+ - !ruby/object:Gem::Version
276
+ version: '9'
195
277
  - !ruby/object:Gem::Dependency
196
- name: bcrypt
278
+ name: async
197
279
  requirement: !ruby/object:Gem::Requirement
198
280
  requirements:
199
- - - "~>"
281
+ - - ">="
200
282
  - !ruby/object:Gem::Version
201
- version: '3.1'
283
+ version: '2.21'
202
284
  type: :runtime
203
285
  prerelease: false
204
286
  version_requirements: !ruby/object:Gem::Requirement
205
287
  requirements:
206
- - - "~>"
288
+ - - ">="
207
289
  - !ruby/object:Gem::Version
208
- version: '3.1'
290
+ version: '2.21'
209
291
  - !ruby/object:Gem::Dependency
210
- name: concurrent-ruby
292
+ name: async-http
293
+ requirement: !ruby/object:Gem::Requirement
294
+ requirements:
295
+ - - ">="
296
+ - !ruby/object:Gem::Version
297
+ version: '0.86'
298
+ type: :runtime
299
+ prerelease: false
300
+ version_requirements: !ruby/object:Gem::Requirement
301
+ requirements:
302
+ - - ">="
303
+ - !ruby/object:Gem::Version
304
+ version: '0.86'
305
+ - !ruby/object:Gem::Dependency
306
+ name: bcrypt
211
307
  requirement: !ruby/object:Gem::Requirement
212
308
  requirements:
213
309
  - - "~>"
214
310
  - !ruby/object:Gem::Version
215
- version: '1.2'
311
+ version: '3.1'
216
312
  type: :runtime
217
313
  prerelease: false
218
314
  version_requirements: !ruby/object:Gem::Requirement
219
315
  requirements:
220
316
  - - "~>"
221
317
  - !ruby/object:Gem::Version
222
- version: '1.2'
318
+ version: '3.1'
223
319
  - !ruby/object:Gem::Dependency
224
320
  name: railties
225
321
  requirement: !ruby/object:Gem::Requirement
226
322
  requirements:
227
- - - "~>"
323
+ - - ">="
228
324
  - !ruby/object:Gem::Version
229
325
  version: '8.0'
326
+ - - "<"
327
+ - !ruby/object:Gem::Version
328
+ version: '9'
230
329
  type: :runtime
231
330
  prerelease: false
232
331
  version_requirements: !ruby/object:Gem::Requirement
233
332
  requirements:
234
- - - "~>"
333
+ - - ">="
235
334
  - !ruby/object:Gem::Version
236
335
  version: '8.0'
336
+ - - "<"
337
+ - !ruby/object:Gem::Version
338
+ version: '9'
339
+ - !ruby/object:Gem::Dependency
340
+ name: pg
341
+ requirement: !ruby/object:Gem::Requirement
342
+ requirements:
343
+ - - ">="
344
+ - !ruby/object:Gem::Version
345
+ version: '1.6'
346
+ type: :runtime
347
+ prerelease: false
348
+ version_requirements: !ruby/object:Gem::Requirement
349
+ requirements:
350
+ - - ">="
351
+ - !ruby/object:Gem::Version
352
+ version: '1.6'
237
353
  - !ruby/object:Gem::Dependency
238
354
  name: state_machines-activerecord
239
355
  requirement: !ruby/object:Gem::Requirement
240
356
  requirements:
241
- - - "~>"
357
+ - - ">="
242
358
  - !ruby/object:Gem::Version
243
- version: 0.40.0
359
+ version: 0.100.0
244
360
  type: :runtime
245
361
  prerelease: false
246
362
  version_requirements: !ruby/object:Gem::Requirement
247
363
  requirements:
248
- - - "~>"
364
+ - - ">="
365
+ - !ruby/object:Gem::Version
366
+ version: 0.100.0
367
+ - !ruby/object:Gem::Dependency
368
+ name: thor
369
+ requirement: !ruby/object:Gem::Requirement
370
+ requirements:
371
+ - - ">="
372
+ - !ruby/object:Gem::Version
373
+ version: '1.0'
374
+ type: :runtime
375
+ prerelease: false
376
+ version_requirements: !ruby/object:Gem::Requirement
377
+ requirements:
378
+ - - ">="
249
379
  - !ruby/object:Gem::Version
250
- version: 0.40.0
380
+ version: '1.0'
251
381
  - !ruby/object:Gem::Dependency
252
382
  name: zeitwerk
253
383
  requirement: !ruby/object:Gem::Requirement
@@ -262,12 +392,18 @@ dependencies:
262
392
  - - "~>"
263
393
  - !ruby/object:Gem::Version
264
394
  version: '2.6'
265
- description: A Ruby on Rails gem that provides seamless integration with the Matrix
266
- protocol, enabling Rails applications to connect and communicate with Matrix servers.
395
+ description: |
396
+ ActiveMatrix is a comprehensive Rails-native Matrix SDK that enables developers to build sophisticated multi-agent bot systems
397
+ and real-time communication features. This gem provides deep Rails integration with ActiveRecord models, state machines for
398
+ bot lifecycle management, multi-tiered memory systems, intelligent event routing, connection pooling, and built-in
399
+ inter-agent communication. Perfect for building chatbots, automation systems, monitoring agents, and collaborative AI
400
+ systems within Rails applications. Features include command handling, room management, media support, end-to-end encryption
401
+ capabilities, and extensive protocol support (CS, AS, IS, SS).
267
402
  email:
268
403
  - terminale@gmail.com
269
404
  - ace@haxalot.com
270
- executables: []
405
+ executables:
406
+ - activematrix
271
407
  extensions: []
272
408
  extra_rdoc_files:
273
409
  - CHANGELOG.md
@@ -277,28 +413,49 @@ files:
277
413
  - CHANGELOG.md
278
414
  - LICENSE.txt
279
415
  - README.md
416
+ - app/jobs/active_matrix/application_job.rb
417
+ - app/models/active_matrix/agent.rb
418
+ - app/models/active_matrix/agent/jobs/memory_reaper.rb
419
+ - app/models/active_matrix/agent_store.rb
420
+ - app/models/active_matrix/application_record.rb
421
+ - app/models/active_matrix/chat_session.rb
422
+ - app/models/active_matrix/knowledge_base.rb
423
+ - exe/activematrix
280
424
  - lib/active_matrix.rb
281
425
  - lib/active_matrix/account_data_cache.rb
282
426
  - lib/active_matrix/agent_manager.rb
283
427
  - lib/active_matrix/agent_registry.rb
284
428
  - lib/active_matrix/api.rb
429
+ - lib/active_matrix/async_query.rb
285
430
  - lib/active_matrix/bot.rb
286
431
  - lib/active_matrix/bot/base.rb
432
+ - lib/active_matrix/bot/builtin_commands.rb
433
+ - lib/active_matrix/bot/command_parser.rb
287
434
  - lib/active_matrix/bot/multi_instance_base.rb
288
435
  - lib/active_matrix/cacheable.rb
436
+ - lib/active_matrix/cli.rb
289
437
  - lib/active_matrix/client.rb
290
438
  - lib/active_matrix/client_pool.rb
439
+ - lib/active_matrix/daemon.rb
440
+ - lib/active_matrix/daemon/probe_server.rb
441
+ - lib/active_matrix/daemon/signal_handler.rb
442
+ - lib/active_matrix/daemon/worker.rb
443
+ - lib/active_matrix/engine.rb
291
444
  - lib/active_matrix/errors.rb
292
445
  - lib/active_matrix/event_router.rb
293
446
  - lib/active_matrix/events.rb
294
447
  - lib/active_matrix/extensions.rb
448
+ - lib/active_matrix/instrumentation.rb
295
449
  - lib/active_matrix/logging.rb
296
450
  - lib/active_matrix/memory.rb
297
451
  - lib/active_matrix/memory/agent_memory.rb
298
452
  - lib/active_matrix/memory/base.rb
299
453
  - lib/active_matrix/memory/conversation_memory.rb
300
454
  - lib/active_matrix/memory/global_memory.rb
455
+ - lib/active_matrix/message_dispatcher.rb
456
+ - lib/active_matrix/metrics.rb
301
457
  - lib/active_matrix/mxid.rb
458
+ - lib/active_matrix/presence_manager.rb
302
459
  - lib/active_matrix/protocols/as.rb
303
460
  - lib/active_matrix/protocols/cs.rb
304
461
  - lib/active_matrix/protocols/is.rb
@@ -309,6 +466,7 @@ files:
309
466
  - lib/active_matrix/room.rb
310
467
  - lib/active_matrix/rooms/space.rb
311
468
  - lib/active_matrix/state_event_cache.rb
469
+ - lib/active_matrix/telemetry.rb
312
470
  - lib/active_matrix/uri_module.rb
313
471
  - lib/active_matrix/user.rb
314
472
  - lib/active_matrix/version.rb
@@ -319,19 +477,20 @@ files:
319
477
  - lib/generators/active_matrix/install/install_generator.rb
320
478
  - lib/generators/active_matrix/install/templates/README
321
479
  - lib/generators/active_matrix/install/templates/active_matrix.rb
322
- - lib/generators/active_matrix/install/templates/agent_memory.rb
323
- - lib/generators/active_matrix/install/templates/conversation_context.rb
324
- - lib/generators/active_matrix/install/templates/create_agent_memories.rb
325
- - lib/generators/active_matrix/install/templates/create_conversation_contexts.rb
326
- - lib/generators/active_matrix/install/templates/create_global_memories.rb
327
- - lib/generators/active_matrix/install/templates/create_matrix_agents.rb
328
- - lib/generators/active_matrix/install/templates/global_memory.rb
329
- - lib/generators/active_matrix/install/templates/matrix_agent.rb
330
480
  homepage: https://github.com/seuros/activematrix
331
481
  licenses:
332
482
  - MIT
333
483
  metadata:
334
484
  rubygems_mfa_required: 'true'
485
+ homepage_uri: https://github.com/seuros/activematrix
486
+ source_code_uri: https://github.com/seuros/activematrix
487
+ changelog_uri: https://github.com/seuros/activematrix/blob/master/CHANGELOG.md
488
+ documentation_uri: https://rubydoc.info/gems/activematrix
489
+ bug_tracker_uri: https://github.com/seuros/activematrix/issues
490
+ wiki_uri: https://github.com/seuros/activematrix/wiki
491
+ tags: matrix, matrix-protocol, matrix-sdk, matrix-api, matrix-client, rails, rails-engine,
492
+ activerecord, activejob, rails-integration, bot, chatbot, multi-agent, agent-system,
493
+ bot-framework, real-time, messaging, communication, chat, state-machine
335
494
  rdoc_options: []
336
495
  require_paths:
337
496
  - lib
@@ -346,7 +505,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
346
505
  - !ruby/object:Gem::Version
347
506
  version: '0'
348
507
  requirements: []
349
- rubygems_version: 3.6.7
508
+ rubygems_version: 4.0.1
350
509
  specification_version: 4
351
- summary: Rails gem for connecting to Matrix protocol
510
+ summary: Rails-native Matrix SDK for building multi-agent bot systems and real-time
511
+ communication
352
512
  test_files: []
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class AgentMemory < ApplicationRecord
4
- belongs_to :matrix_agent
5
-
6
- validates :key, presence: true, uniqueness: { scope: :matrix_agent_id }
7
-
8
- scope :active, -> { where('expires_at IS NULL OR expires_at > ?', Time.current) }
9
- scope :expired, -> { where('expires_at <= ?', Time.current) }
10
-
11
- # Automatically clean up expired memories
12
- after_commit :schedule_cleanup, if: :expires_at?
13
-
14
- def expired?
15
- expires_at.present? && expires_at <= Time.current
16
- end
17
-
18
- def ttl=(seconds)
19
- self.expires_at = seconds.present? ? Time.current + seconds : nil
20
- end
21
-
22
- def ttl
23
- return nil unless expires_at.present?
24
-
25
- remaining = expires_at - Time.current
26
- [remaining, 0].max
27
- end
28
-
29
- # Cache integration
30
- def cache_key
31
- "agent_memory/#{matrix_agent_id}/#{key}"
32
- end
33
-
34
- def write_to_cache
35
- Rails.cache.write(cache_key, value, expires_in: ttl)
36
- end
37
-
38
- def self.cleanup_expired!
39
- expired.destroy_all
40
- end
41
-
42
- private
43
-
44
- def schedule_cleanup
45
- AgentMemoryCleanupJob.set(wait_until: expires_at).perform_later if defined?(AgentMemoryCleanupJob)
46
- end
47
- end
@@ -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,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateAgentMemories < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- create_table :agent_memories do |t|
6
- t.references :matrix_agent, null: false, foreign_key: true
7
- t.string :key, null: false
8
- t.jsonb :value, default: {}
9
- t.datetime :expires_at
10
-
11
- t.timestamps
12
-
13
- t.index [:matrix_agent_id, :key], unique: true
14
- t.index :expires_at
15
- end
16
- end
17
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateConversationContexts < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- create_table :conversation_contexts do |t|
6
- t.references :matrix_agent, null: false, foreign_key: true
7
- t.string :user_id, null: false
8
- t.string :room_id, null: false
9
- t.jsonb :context, default: {}
10
- t.jsonb :message_history, default: { messages: [] }
11
- t.datetime :last_message_at
12
- t.integer :message_count, default: 0
13
-
14
- t.timestamps
15
-
16
- t.index [:matrix_agent_id, :user_id, :room_id], unique: true, name: 'idx_conv_context_unique'
17
- t.index :last_message_at
18
- t.index :room_id
19
- end
20
- end
21
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateGlobalMemories < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- create_table :global_memories do |t|
6
- t.string :key, null: false
7
- t.jsonb :value, default: {}
8
- t.string :category
9
- t.datetime :expires_at
10
- t.boolean :public_read, default: true
11
- t.boolean :public_write, default: false
12
-
13
- t.timestamps
14
-
15
- t.index :key, unique: true
16
- t.index :category
17
- t.index :expires_at
18
- end
19
- end
20
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateMatrixAgents < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- create_table :matrix_agents do |t|
6
- t.string :name, null: false
7
- t.string :homeserver, null: false
8
- t.string :username, null: false
9
- t.string :encrypted_password
10
- t.string :access_token
11
- t.string :state, default: 'offline', null: false
12
- t.string :bot_class, null: false
13
- t.jsonb :settings, default: {}
14
- t.string :last_sync_token
15
- t.datetime :last_active_at
16
- t.integer :rooms_count, default: 0
17
- t.integer :messages_handled, default: 0
18
-
19
- t.timestamps
20
-
21
- t.index :name, unique: true
22
- t.index :state
23
- t.index [:homeserver, :username]
24
- end
25
- end
26
- 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