activematrix 0.0.1 → 0.0.2

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +218 -51
  3. data/lib/active_matrix/agent_manager.rb +275 -0
  4. data/lib/active_matrix/agent_registry.rb +154 -0
  5. data/lib/active_matrix/bot/multi_instance_base.rb +189 -0
  6. data/lib/active_matrix/client.rb +5 -15
  7. data/lib/active_matrix/client_pool.rb +194 -0
  8. data/lib/active_matrix/event_router.rb +215 -0
  9. data/lib/active_matrix/memory/agent_memory.rb +128 -0
  10. data/lib/active_matrix/memory/base.rb +101 -0
  11. data/lib/active_matrix/memory/conversation_memory.rb +161 -0
  12. data/lib/active_matrix/memory/global_memory.rb +153 -0
  13. data/lib/active_matrix/memory.rb +28 -0
  14. data/lib/active_matrix/room.rb +131 -51
  15. data/lib/active_matrix/rooms/space.rb +1 -5
  16. data/lib/active_matrix/user.rb +10 -0
  17. data/lib/active_matrix/util/account_data_cache.rb +62 -24
  18. data/lib/active_matrix/util/cacheable.rb +73 -0
  19. data/lib/active_matrix/util/extensions.rb +4 -0
  20. data/lib/active_matrix/util/state_event_cache.rb +106 -31
  21. data/lib/active_matrix/version.rb +1 -1
  22. data/lib/active_matrix.rb +51 -3
  23. data/lib/generators/active_matrix/bot/bot_generator.rb +38 -0
  24. data/lib/generators/active_matrix/bot/templates/bot.rb.erb +111 -0
  25. data/lib/generators/active_matrix/bot/templates/bot_spec.rb.erb +68 -0
  26. data/lib/generators/active_matrix/install/install_generator.rb +44 -0
  27. data/lib/generators/active_matrix/install/templates/README +30 -0
  28. data/lib/generators/active_matrix/install/templates/active_matrix.rb +33 -0
  29. data/lib/generators/active_matrix/install/templates/agent_memory.rb +47 -0
  30. data/lib/generators/active_matrix/install/templates/conversation_context.rb +72 -0
  31. data/lib/generators/active_matrix/install/templates/create_agent_memories.rb +17 -0
  32. data/lib/generators/active_matrix/install/templates/create_conversation_contexts.rb +21 -0
  33. data/lib/generators/active_matrix/install/templates/create_global_memories.rb +20 -0
  34. data/lib/generators/active_matrix/install/templates/create_matrix_agents.rb +26 -0
  35. data/lib/generators/active_matrix/install/templates/global_memory.rb +70 -0
  36. data/lib/generators/active_matrix/install/templates/matrix_agent.rb +127 -0
  37. metadata +110 -4
  38. data/lib/active_matrix/util/rails_cache_adapter.rb +0 -37
  39. data/lib/active_matrix/util/tinycache.rb +0 -145
  40. data/lib/active_matrix/util/tinycache_adapter.rb +0 -87
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_matrix/util/tinycache_adapter'
4
-
5
- module ActiveMatrix::Util
6
- module Tinycache
7
- CACHE_LEVELS = {
8
- none: 0,
9
- some: 1,
10
- all: 2
11
- }.freeze
12
-
13
- def self.adapter
14
- @adapter ||= if defined?(::Rails) && ::Rails.respond_to?(:cache)
15
- require 'active_matrix/util/rails_cache_adapter'
16
- RailsCacheAdapter
17
- else
18
- TinycacheAdapter
19
- end
20
- end
21
-
22
- def self.adapter=(adapter)
23
- @adapter = adapter
24
- end
25
-
26
- def self.extended(base)
27
- helper_name = base.send(:cache_helper_module_name)
28
- base.send :remove_const, helper_name if base.const_defined?(helper_name)
29
- base.prepend base.const_set(helper_name, Module.new)
30
-
31
- base.include InstanceMethods
32
- end
33
-
34
- def cached(*methods, **)
35
- methods.each { |method| build_cache_methods(method, **) }
36
- end
37
-
38
- module InstanceMethods
39
- def tinycache_adapter
40
- @tinycache_adapter ||= Tinycache.adapter.new.tap do |adapter|
41
- adapter.config = self.class.tinycache_adapter_config if adapter.respond_to? :config=
42
- adapter.client = client if respond_to?(:client) && adapter.respond_to?(:client=)
43
- end
44
- end
45
- end
46
-
47
- def tinycache_adapter_config
48
- @tinycache_adapter_config ||= {}
49
- end
50
-
51
- private
52
-
53
- def default_cache_key
54
- proc do |method_name, _method_args|
55
- method_name.to_sym
56
- end
57
- end
58
-
59
- def cache_helper_module_name
60
- class_name = name&.gsub(':', '') || to_s.gsub(/[^a-zA-Z_0-9]/, '')
61
- "#{class_name}Tinycache"
62
- end
63
-
64
- def build_cache_methods(method_name, cache_key: default_cache_key, cache_level: :none, expires_in: nil, **opts)
65
- raise ArgumentError, 'Cache key must be a three-arg proc' unless cache_key.is_a? Proc
66
-
67
- method_names = build_method_names(method_name)
68
- tinycache_adapter_config[method_name] = {
69
- level: cache_level,
70
- expires: expires_in || (1 * 365 * 24 * 60 * 60) # 1 year
71
- }
72
-
73
- helper = const_get(cache_helper_module_name)
74
- return if method_names.any? { |k, _| helper.respond_to? k }
75
-
76
- helper.class_eval do
77
- define_method(method_names[:cache_key]) do |*args|
78
- cache_key.call(method_name, args)
79
- end
80
-
81
- define_method(method_names[:with_cache]) do |*args|
82
- tinycache_adapter.fetch(__send__(method_names[:cache_key], *args), expires_in: expires_in) do
83
- named = args.delete_at(-1) if args.last.is_a? Hash
84
- named ||= {}
85
-
86
- __send__(method_names[:without_cache], *args, **named)
87
- end
88
- end
89
-
90
- define_method(method_names[:without_cache]) do |*args|
91
- orig = method(method_name).super_method
92
- named = args.delete_at(-1) if args.last.is_a? Hash
93
- named ||= {}
94
-
95
- orig.call(*args, **named)
96
- end
97
-
98
- define_method(method_names[:clear_cache]) do |*args|
99
- tinycache_adapter.delete(__send__(method_names[:cache_key], *args))
100
- end
101
-
102
- define_method(method_names[:cached]) do
103
- true
104
- end
105
-
106
- define_method(method_names[:has_value]) do |*args|
107
- tinycache_adapter.valid?(__send__(method_names[:cache_key], *args))
108
- end
109
-
110
- define_method(method_name) do |*args|
111
- unless_proc = opts[:unless].is_a?(Symbol) ? opts[:unless].to_proc : opts[:unless]
112
-
113
- raise ArgumentError, 'Invalid proc provided (must have arity between 1..3)' if unless_proc && !(1..3).include?(unless_proc.arity)
114
-
115
- skip_cache = false
116
- skip_cache ||= unless_proc.call(self, method_name, args) if unless_proc&.arity == 3
117
- skip_cache ||= unless_proc.call(method_name, args) if unless_proc&.arity == 2
118
- skip_cache ||= unless_proc.call(args) if unless_proc&.arity == 1
119
- skip_cache ||= CACHE_LEVELS[client&.cache || :all] < CACHE_LEVELS[cache_level]
120
-
121
- if skip_cache
122
- __send__(method_names[:without_cache], *args)
123
- else
124
- __send__(method_names[:with_cache], *args)
125
- end
126
- end
127
- end
128
- end
129
-
130
- def build_method_names(method)
131
- # Clean up method name (split any suffix)
132
- method_name = method.to_s.sub(/([?!=])$/, '')
133
- punctuation = Regexp.last_match(-1)
134
-
135
- {
136
- cache_key: "#{method_name}_cache_key#{punctuation}",
137
- with_cache: "#{method_name}_with_cache#{punctuation}",
138
- without_cache: "#{method_name}_without_cache#{punctuation}",
139
- clear_cache: "clear_#{method_name}_cache#{punctuation}",
140
- cached: "#{method}_cached?",
141
- has_value: "#{method}_has_value?"
142
- }
143
- end
144
- end
145
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveMatrix::Util
4
- class TinycacheAdapter
5
- extend ActiveMatrix::Extensions
6
-
7
- attr_accessor :config, :client
8
-
9
- ignore_inspect :client
10
-
11
- def initialize
12
- @config = {}
13
-
14
- clear
15
- end
16
-
17
- def read(key)
18
- cache[key]&.value
19
- end
20
-
21
- def write(key, value, expires_in: nil, cache_level: nil)
22
- expires_in ||= config.dig(key, :expires)
23
- expires_in ||= 24 * 60 * 60
24
- cache_level ||= client&.cache
25
- cache_level ||= :all
26
- cache_level = Tinycache::CACHE_LEVELS[cache_level] unless cache_level.is_a? Integer
27
-
28
- return value if cache_level < Tinycache::CACHE_LEVELS[config.dig(key, :level) || :none]
29
-
30
- cache[key] = Value.new(value, Time.now, Time.now + expires_in)
31
- value
32
- end
33
-
34
- def exist?(key)
35
- cache.key?(key)
36
- end
37
-
38
- def valid?(key)
39
- exist?(key) && !cache[key].expired?
40
- end
41
-
42
- def fetch(key, expires_in: nil, cache_level: nil, **_opts)
43
- expires_in ||= config.dig(key, :expires)
44
- cache_level ||= client&.cache
45
- cache_level ||= :all
46
- cache_level = Tinycache::CACHE_LEVELS[cache_level]
47
-
48
- return read(key) if exist?(key) && !cache[key].expired?
49
-
50
- value = yield
51
- write(key, value, expires_in: expires_in, cache_level: cache_level)
52
- end
53
-
54
- def delete(key)
55
- return false unless exist?(key)
56
-
57
- cache.delete key
58
- true
59
- end
60
-
61
- def expire(key)
62
- return unless exist? key
63
-
64
- cache[key].expires_at = Time.at(0)
65
- end
66
-
67
- def clear
68
- @cache = {}
69
- end
70
-
71
- def cleanup
72
- @cache.select { |_, v| v.expired? }.each_value { |v| v.value = nil }
73
- end
74
-
75
- private
76
-
77
- Value = Struct.new(:value, :timestamp, :expires_at) do
78
- def expired?
79
- return false if expires_at.nil?
80
-
81
- Time.now > expires_at
82
- end
83
- end
84
-
85
- attr_reader :cache
86
- end
87
- end