lex-agentic-social 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-social.gemspec +30 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/client.rb +28 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship.rb +90 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_engine.rb +109 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_model.rb +93 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship.rb +112 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/apprenticeship.rb +19 -0
- data/lib/legion/extensions/agentic/social/conflict/actors/stale_check.rb +45 -0
- data/lib/legion/extensions/agentic/social/conflict/client.rb +27 -0
- data/lib/legion/extensions/agentic/social/conflict/helpers/conflict_log.rb +70 -0
- data/lib/legion/extensions/agentic/social/conflict/helpers/llm_enhancer.rb +130 -0
- data/lib/legion/extensions/agentic/social/conflict/helpers/severity.rb +47 -0
- data/lib/legion/extensions/agentic/social/conflict/runners/conflict.rb +112 -0
- data/lib/legion/extensions/agentic/social/conflict/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/conflict.rb +19 -0
- data/lib/legion/extensions/agentic/social/conscience/client.rb +26 -0
- data/lib/legion/extensions/agentic/social/conscience/helpers/constants.rb +53 -0
- data/lib/legion/extensions/agentic/social/conscience/helpers/moral_evaluator.rb +178 -0
- data/lib/legion/extensions/agentic/social/conscience/helpers/moral_store.rb +116 -0
- data/lib/legion/extensions/agentic/social/conscience/runners/conscience.rb +117 -0
- data/lib/legion/extensions/agentic/social/conscience/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/conscience.rb +19 -0
- data/lib/legion/extensions/agentic/social/consent/actors/tier_evaluation.rb +45 -0
- data/lib/legion/extensions/agentic/social/consent/client.rb +27 -0
- data/lib/legion/extensions/agentic/social/consent/helpers/consent_map.rb +199 -0
- data/lib/legion/extensions/agentic/social/consent/helpers/tiers.rb +54 -0
- data/lib/legion/extensions/agentic/social/consent/local_migrations/20260316000010_create_consent_domains.rb +16 -0
- data/lib/legion/extensions/agentic/social/consent/runners/consent.rb +228 -0
- data/lib/legion/extensions/agentic/social/consent/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/consent.rb +25 -0
- data/lib/legion/extensions/agentic/social/entrainment/client.rb +19 -0
- data/lib/legion/extensions/agentic/social/entrainment/helpers/constants.rb +40 -0
- data/lib/legion/extensions/agentic/social/entrainment/helpers/entrainment_engine.rb +120 -0
- data/lib/legion/extensions/agentic/social/entrainment/helpers/pairing.rb +86 -0
- data/lib/legion/extensions/agentic/social/entrainment/runners/cognitive_entrainment.rb +89 -0
- data/lib/legion/extensions/agentic/social/entrainment/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/entrainment.rb +19 -0
- data/lib/legion/extensions/agentic/social/governance/actors/shadow_ai_scan.rb +19 -0
- data/lib/legion/extensions/agentic/social/governance/actors/vote_timeout.rb +45 -0
- data/lib/legion/extensions/agentic/social/governance/client.rb +27 -0
- data/lib/legion/extensions/agentic/social/governance/helpers/layers.rb +40 -0
- data/lib/legion/extensions/agentic/social/governance/helpers/proposal.rb +94 -0
- data/lib/legion/extensions/agentic/social/governance/runners/governance.rb +87 -0
- data/lib/legion/extensions/agentic/social/governance/runners/shadow_ai.rb +93 -0
- data/lib/legion/extensions/agentic/social/governance/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/governance.rb +20 -0
- data/lib/legion/extensions/agentic/social/joint_attention/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/social/joint_attention/client.rb +28 -0
- data/lib/legion/extensions/agentic/social/joint_attention/helpers/attention_target.rb +124 -0
- data/lib/legion/extensions/agentic/social/joint_attention/helpers/constants.rb +34 -0
- data/lib/legion/extensions/agentic/social/joint_attention/helpers/joint_focus_manager.rb +157 -0
- data/lib/legion/extensions/agentic/social/joint_attention/runners/joint_attention.rb +88 -0
- data/lib/legion/extensions/agentic/social/joint_attention/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/joint_attention.rb +20 -0
- data/lib/legion/extensions/agentic/social/mentalizing/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/social/mentalizing/client.rb +28 -0
- data/lib/legion/extensions/agentic/social/mentalizing/helpers/belief_attribution.rb +58 -0
- data/lib/legion/extensions/agentic/social/mentalizing/helpers/constants.rb +33 -0
- data/lib/legion/extensions/agentic/social/mentalizing/helpers/mental_model.rb +137 -0
- data/lib/legion/extensions/agentic/social/mentalizing/runners/mentalizing.rb +93 -0
- data/lib/legion/extensions/agentic/social/mentalizing/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/mentalizing.rb +20 -0
- data/lib/legion/extensions/agentic/social/mirror/client.rb +33 -0
- data/lib/legion/extensions/agentic/social/mirror/helpers/constants.rb +65 -0
- data/lib/legion/extensions/agentic/social/mirror/helpers/mirror_engine.rb +132 -0
- data/lib/legion/extensions/agentic/social/mirror/helpers/mirror_event.rb +46 -0
- data/lib/legion/extensions/agentic/social/mirror/helpers/simulation.rb +43 -0
- data/lib/legion/extensions/agentic/social/mirror/runners/observe.rb +52 -0
- data/lib/legion/extensions/agentic/social/mirror/runners/resonance.rb +79 -0
- data/lib/legion/extensions/agentic/social/mirror/runners/simulate.rb +63 -0
- data/lib/legion/extensions/agentic/social/mirror/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/mirror.rb +22 -0
- data/lib/legion/extensions/agentic/social/mirror_system/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/social/mirror_system/client.rb +28 -0
- data/lib/legion/extensions/agentic/social/mirror_system/helpers/constants.rb +62 -0
- data/lib/legion/extensions/agentic/social/mirror_system/helpers/mirror_system.rb +162 -0
- data/lib/legion/extensions/agentic/social/mirror_system/helpers/observed_behavior.rb +67 -0
- data/lib/legion/extensions/agentic/social/mirror_system/runners/mirror.rb +99 -0
- data/lib/legion/extensions/agentic/social/mirror_system/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/mirror_system.rb +20 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/client.rb +19 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/constants.rb +49 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/dilemma.rb +68 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/llm_enhancer.rb +140 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb +239 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_foundation.rb +45 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/runners/moral_reasoning.rb +121 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/moral_reasoning.rb +21 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/client.rb +29 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/constants.rb +67 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/perspective.rb +45 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_view.rb +57 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine.rb +166 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting.rb +167 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting.rb +20 -0
- data/lib/legion/extensions/agentic/social/social/client.rb +25 -0
- data/lib/legion/extensions/agentic/social/social/helpers/constants.rb +84 -0
- data/lib/legion/extensions/agentic/social/social/helpers/social_graph.rb +172 -0
- data/lib/legion/extensions/agentic/social/social/runners/social.rb +146 -0
- data/lib/legion/extensions/agentic/social/social/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/social.rb +18 -0
- data/lib/legion/extensions/agentic/social/social_learning/client.rb +25 -0
- data/lib/legion/extensions/agentic/social/social_learning/helpers/constants.rb +42 -0
- data/lib/legion/extensions/agentic/social/social_learning/helpers/model_agent.rb +82 -0
- data/lib/legion/extensions/agentic/social/social_learning/helpers/observed_behavior.rb +61 -0
- data/lib/legion/extensions/agentic/social/social_learning/helpers/social_learning_engine.rb +134 -0
- data/lib/legion/extensions/agentic/social/social_learning/runners/social_learning.rb +105 -0
- data/lib/legion/extensions/agentic/social/social_learning/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/social_learning.rb +20 -0
- data/lib/legion/extensions/agentic/social/symbiosis/client.rb +23 -0
- data/lib/legion/extensions/agentic/social/symbiosis/helpers/constants.rb +50 -0
- data/lib/legion/extensions/agentic/social/symbiosis/helpers/ecosystem.rb +113 -0
- data/lib/legion/extensions/agentic/social/symbiosis/helpers/symbiosis_engine.rb +104 -0
- data/lib/legion/extensions/agentic/social/symbiosis/helpers/symbiotic_bond.rb +112 -0
- data/lib/legion/extensions/agentic/social/symbiosis/runners/cognitive_symbiosis.rb +101 -0
- data/lib/legion/extensions/agentic/social/symbiosis/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/symbiosis.rb +22 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/client.rb +26 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/agent_model.rb +173 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/constants.rb +70 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/mental_state_tracker.rb +169 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/runners/theory_of_mind.rb +159 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/theory_of_mind.rb +19 -0
- data/lib/legion/extensions/agentic/social/trust/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/social/trust/client.rb +27 -0
- data/lib/legion/extensions/agentic/social/trust/helpers/trust_map.rb +160 -0
- data/lib/legion/extensions/agentic/social/trust/helpers/trust_model.rb +52 -0
- data/lib/legion/extensions/agentic/social/trust/local_migrations/20260316000020_create_trust_entries.rb +23 -0
- data/lib/legion/extensions/agentic/social/trust/runners/trust.rb +80 -0
- data/lib/legion/extensions/agentic/social/trust/version.rb +13 -0
- data/lib/legion/extensions/agentic/social/trust.rb +25 -0
- data/lib/legion/extensions/agentic/social/version.rb +11 -0
- data/lib/legion/extensions/agentic/social.rb +34 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/cognitive_apprenticeship_spec.rb +11 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_engine_spec.rb +146 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_model_spec.rb +124 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_spec.rb +136 -0
- data/spec/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship_spec.rb +154 -0
- data/spec/legion/extensions/agentic/social/conflict/actors/stale_check_spec.rb +45 -0
- data/spec/legion/extensions/agentic/social/conflict/client_spec.rb +15 -0
- data/spec/legion/extensions/agentic/social/conflict/helpers/conflict_log_spec.rb +232 -0
- data/spec/legion/extensions/agentic/social/conflict/helpers/llm_enhancer_spec.rb +189 -0
- data/spec/legion/extensions/agentic/social/conflict/helpers/severity_spec.rb +215 -0
- data/spec/legion/extensions/agentic/social/conflict/runners/conflict_spec.rb +151 -0
- data/spec/legion/extensions/agentic/social/conscience/client_spec.rb +58 -0
- data/spec/legion/extensions/agentic/social/conscience/helpers/constants_spec.rb +124 -0
- data/spec/legion/extensions/agentic/social/conscience/helpers/moral_evaluator_spec.rb +253 -0
- data/spec/legion/extensions/agentic/social/conscience/helpers/moral_store_spec.rb +230 -0
- data/spec/legion/extensions/agentic/social/conscience/runners/conscience_spec.rb +239 -0
- data/spec/legion/extensions/agentic/social/consent/actors/tier_evaluation_spec.rb +46 -0
- data/spec/legion/extensions/agentic/social/consent/client_spec.rb +33 -0
- data/spec/legion/extensions/agentic/social/consent/helpers/tiers_spec.rb +49 -0
- data/spec/legion/extensions/agentic/social/consent/local_persistence_spec.rb +234 -0
- data/spec/legion/extensions/agentic/social/consent/runners/consent_spec.rb +224 -0
- data/spec/legion/extensions/agentic/social/entrainment/client_spec.rb +21 -0
- data/spec/legion/extensions/agentic/social/entrainment/helpers/entrainment_engine_spec.rb +116 -0
- data/spec/legion/extensions/agentic/social/entrainment/helpers/pairing_spec.rb +103 -0
- data/spec/legion/extensions/agentic/social/entrainment/runners/cognitive_entrainment_spec.rb +87 -0
- data/spec/legion/extensions/agentic/social/governance/actors/vote_timeout_spec.rb +45 -0
- data/spec/legion/extensions/agentic/social/governance/client_spec.rb +14 -0
- data/spec/legion/extensions/agentic/social/governance/helpers/layers_spec.rb +190 -0
- data/spec/legion/extensions/agentic/social/governance/helpers/proposal_spec.rb +188 -0
- data/spec/legion/extensions/agentic/social/governance/runners/governance_spec.rb +101 -0
- data/spec/legion/extensions/agentic/social/governance/runners/shadow_ai_spec.rb +65 -0
- data/spec/legion/extensions/agentic/social/joint_attention/client_spec.rb +36 -0
- data/spec/legion/extensions/agentic/social/joint_attention/helpers/attention_target_spec.rb +258 -0
- data/spec/legion/extensions/agentic/social/joint_attention/helpers/joint_focus_manager_spec.rb +238 -0
- data/spec/legion/extensions/agentic/social/joint_attention/runners/joint_attention_spec.rb +228 -0
- data/spec/legion/extensions/agentic/social/mentalizing/client_spec.rb +19 -0
- data/spec/legion/extensions/agentic/social/mentalizing/helpers/belief_attribution_spec.rb +108 -0
- data/spec/legion/extensions/agentic/social/mentalizing/helpers/mental_model_spec.rb +179 -0
- data/spec/legion/extensions/agentic/social/mentalizing/runners/mentalizing_spec.rb +162 -0
- data/spec/legion/extensions/agentic/social/mirror/client_spec.rb +92 -0
- data/spec/legion/extensions/agentic/social/mirror/helpers/constants_spec.rb +123 -0
- data/spec/legion/extensions/agentic/social/mirror/helpers/mirror_engine_spec.rb +217 -0
- data/spec/legion/extensions/agentic/social/mirror/helpers/mirror_event_spec.rb +102 -0
- data/spec/legion/extensions/agentic/social/mirror/helpers/simulation_spec.rb +100 -0
- data/spec/legion/extensions/agentic/social/mirror/runners/observe_spec.rb +77 -0
- data/spec/legion/extensions/agentic/social/mirror/runners/resonance_spec.rb +123 -0
- data/spec/legion/extensions/agentic/social/mirror/runners/simulate_spec.rb +103 -0
- data/spec/legion/extensions/agentic/social/mirror_system/client_spec.rb +40 -0
- data/spec/legion/extensions/agentic/social/mirror_system/helpers/mirror_system_spec.rb +144 -0
- data/spec/legion/extensions/agentic/social/mirror_system/helpers/observed_behavior_spec.rb +98 -0
- data/spec/legion/extensions/agentic/social/mirror_system/runners/mirror_spec.rb +122 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/client_spec.rb +34 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/dilemma_spec.rb +108 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/llm_enhancer_spec.rb +232 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine_spec.rb +266 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/moral_foundation_spec.rb +70 -0
- data/spec/legion/extensions/agentic/social/moral_reasoning/runners/moral_reasoning_spec.rb +275 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/client_spec.rb +30 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/constants_spec.rb +99 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_spec.rb +77 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_view_spec.rb +105 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine_spec.rb +246 -0
- data/spec/legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting_spec.rb +277 -0
- data/spec/legion/extensions/agentic/social/social/client_spec.rb +72 -0
- data/spec/legion/extensions/agentic/social/social/helpers/constants_spec.rb +99 -0
- data/spec/legion/extensions/agentic/social/social/helpers/social_graph_spec.rb +322 -0
- data/spec/legion/extensions/agentic/social/social/runners/social_spec.rb +220 -0
- data/spec/legion/extensions/agentic/social/social_learning/client_spec.rb +25 -0
- data/spec/legion/extensions/agentic/social/social_learning/helpers/constants_spec.rb +44 -0
- data/spec/legion/extensions/agentic/social/social_learning/helpers/model_agent_spec.rb +120 -0
- data/spec/legion/extensions/agentic/social/social_learning/helpers/observed_behavior_spec.rb +81 -0
- data/spec/legion/extensions/agentic/social/social_learning/helpers/social_learning_engine_spec.rb +196 -0
- data/spec/legion/extensions/agentic/social/social_learning/runners/social_learning_spec.rb +150 -0
- data/spec/legion/extensions/agentic/social/symbiosis/client_spec.rb +45 -0
- data/spec/legion/extensions/agentic/social/symbiosis/helpers/constants_spec.rb +73 -0
- data/spec/legion/extensions/agentic/social/symbiosis/helpers/ecosystem_spec.rb +185 -0
- data/spec/legion/extensions/agentic/social/symbiosis/helpers/symbiosis_engine_spec.rb +182 -0
- data/spec/legion/extensions/agentic/social/symbiosis/helpers/symbiotic_bond_spec.rb +209 -0
- data/spec/legion/extensions/agentic/social/symbiosis/runners/cognitive_symbiosis_spec.rb +182 -0
- data/spec/legion/extensions/agentic/social/theory_of_mind/client_spec.rb +63 -0
- data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/agent_model_spec.rb +244 -0
- data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/constants_spec.rb +71 -0
- data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/mental_state_tracker_spec.rb +228 -0
- data/spec/legion/extensions/agentic/social/theory_of_mind/runners/theory_of_mind_spec.rb +221 -0
- data/spec/legion/extensions/agentic/social/trust/actors/decay_spec.rb +62 -0
- data/spec/legion/extensions/agentic/social/trust/client_spec.rb +17 -0
- data/spec/legion/extensions/agentic/social/trust/helpers/trust_map_spec.rb +299 -0
- data/spec/legion/extensions/agentic/social/trust/helpers/trust_model_spec.rb +179 -0
- data/spec/legion/extensions/agentic/social/trust/local_persistence_spec.rb +359 -0
- data/spec/legion/extensions/agentic/social/trust/runners/trust_spec.rb +84 -0
- data/spec/spec_helper.rb +54 -0
- metadata +319 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module JointAttention
|
|
8
|
+
module Helpers
|
|
9
|
+
class JointFocusManager
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :targets, :history
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@targets = {}
|
|
16
|
+
@agent_focus = {}
|
|
17
|
+
@history = []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_target(name:, domain:, priority:, creator:)
|
|
21
|
+
prune_targets if @targets.size >= MAX_TARGETS
|
|
22
|
+
target = AttentionTarget.new(
|
|
23
|
+
name: name,
|
|
24
|
+
domain: domain,
|
|
25
|
+
priority: priority,
|
|
26
|
+
creator_agent_id: creator
|
|
27
|
+
)
|
|
28
|
+
@targets[target.id] = target
|
|
29
|
+
record_history(event: :target_created, target_id: target.id, agent_id: creator)
|
|
30
|
+
join_target(target_id: target.id, agent_id: creator)
|
|
31
|
+
target
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def join_target(target_id:, agent_id:, gaze: nil)
|
|
35
|
+
target = @targets[target_id]
|
|
36
|
+
return :target_not_found unless target
|
|
37
|
+
|
|
38
|
+
current = agent_target_ids(agent_id)
|
|
39
|
+
return :capacity_exceeded if current.size >= MAX_SIMULTANEOUS_TARGETS && !current.include?(target_id)
|
|
40
|
+
|
|
41
|
+
result = target.add_attendee(agent_id: agent_id, gaze: gaze)
|
|
42
|
+
if result == :joined
|
|
43
|
+
@agent_focus[agent_id] ||= []
|
|
44
|
+
@agent_focus[agent_id] << target_id unless @agent_focus[agent_id].include?(target_id)
|
|
45
|
+
record_history(event: :agent_joined, target_id: target_id, agent_id: agent_id)
|
|
46
|
+
end
|
|
47
|
+
result
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def leave_target(target_id:, agent_id:)
|
|
51
|
+
target = @targets[target_id]
|
|
52
|
+
return :target_not_found unless target
|
|
53
|
+
|
|
54
|
+
result = target.remove_attendee(agent_id: agent_id)
|
|
55
|
+
if result == :removed
|
|
56
|
+
@agent_focus[agent_id]&.delete(target_id)
|
|
57
|
+
record_history(event: :agent_left, target_id: target_id, agent_id: agent_id)
|
|
58
|
+
end
|
|
59
|
+
result
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def direct_attention(from_agent:, to_agent:, target_id:)
|
|
63
|
+
target = @targets[target_id]
|
|
64
|
+
return :target_not_found unless target
|
|
65
|
+
|
|
66
|
+
return :referrer_not_attending unless target.attendees.key?(from_agent)
|
|
67
|
+
|
|
68
|
+
join_result = join_target(target_id: target_id, agent_id: to_agent)
|
|
69
|
+
return join_result if join_result == :capacity_exceeded
|
|
70
|
+
|
|
71
|
+
target.boost_focus(agent_id: to_agent, amount: REFERRAL_BOOST) if target.attendees.key?(to_agent)
|
|
72
|
+
record_history(event: :attention_directed, target_id: target_id, from_agent: from_agent, to_agent: to_agent)
|
|
73
|
+
:directed
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def establish_shared(target_id:, agent_a:, agent_b:)
|
|
77
|
+
target = @targets[target_id]
|
|
78
|
+
return :target_not_found unless target
|
|
79
|
+
|
|
80
|
+
result = target.establish_mutual_awareness(agent_a: agent_a, agent_b: agent_b)
|
|
81
|
+
record_history(event: :shared_awareness, target_id: target_id, agent_a: agent_a, agent_b: agent_b) if result == :established
|
|
82
|
+
result
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def update_gaze(target_id:, agent_id:, gaze:)
|
|
86
|
+
target = @targets[target_id]
|
|
87
|
+
return :target_not_found unless target
|
|
88
|
+
|
|
89
|
+
target.update_gaze(agent_id: agent_id, gaze: gaze)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def targets_for_agent(agent_id:)
|
|
93
|
+
ids = agent_target_ids(agent_id)
|
|
94
|
+
ids.filter_map { |tid| @targets[tid] }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def attendees_for_target(target_id:)
|
|
98
|
+
target = @targets[target_id]
|
|
99
|
+
return [] unless target
|
|
100
|
+
|
|
101
|
+
target.attendees.keys
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def shared_targets(agent_a:, agent_b:)
|
|
105
|
+
ids_a = agent_target_ids(agent_a)
|
|
106
|
+
ids_b = agent_target_ids(agent_b)
|
|
107
|
+
(ids_a & ids_b).filter_map { |tid| @targets[tid] }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def decay_all
|
|
111
|
+
@targets.each_value(&:decay)
|
|
112
|
+
@targets.each_value(&:prune_faded_attendees)
|
|
113
|
+
sync_agent_focus
|
|
114
|
+
@targets.reject! { |_, t| t.faded? }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def target_count
|
|
118
|
+
@targets.size
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_h
|
|
122
|
+
{
|
|
123
|
+
target_count: target_count,
|
|
124
|
+
agent_count: @agent_focus.count { |_, ids| ids.any? },
|
|
125
|
+
history_size: @history.size,
|
|
126
|
+
targets: @targets.transform_values(&:to_h)
|
|
127
|
+
}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def agent_target_ids(agent_id)
|
|
133
|
+
@agent_focus.fetch(agent_id, [])
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def sync_agent_focus
|
|
137
|
+
@agent_focus.each_value { |ids| ids.select! { |tid| @targets.key?(tid) } }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def record_history(event)
|
|
141
|
+
@history << event.merge(at: Time.now.utc)
|
|
142
|
+
@history.shift while @history.size > MAX_HISTORY
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def prune_targets
|
|
146
|
+
sorted = @targets.values.sort_by { |t| [t.focus_strength, t.created_at] }
|
|
147
|
+
to_remove = sorted.first(@targets.size - MAX_TARGETS + 1)
|
|
148
|
+
to_remove.each { |t| @targets.delete(t.id) }
|
|
149
|
+
sync_agent_focus
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module JointAttention
|
|
8
|
+
module Runners
|
|
9
|
+
module JointAttention
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def create_attention_target(name:, domain:, creator:, priority: 0.5, **)
|
|
14
|
+
target = joint_focus_manager.create_target(name: name, domain: domain, priority: priority, creator: creator)
|
|
15
|
+
Legion::Logging.debug "[joint_attention] create_target: name=#{name} domain=#{domain} priority=#{priority} " \
|
|
16
|
+
"creator=#{creator} id=#{target.id}"
|
|
17
|
+
{ success: true, target: target.to_h }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def join_attention(target_id:, agent_id:, gaze: nil, **)
|
|
21
|
+
result = joint_focus_manager.join_target(target_id: target_id, agent_id: agent_id, gaze: gaze)
|
|
22
|
+
Legion::Logging.debug "[joint_attention] join: target_id=#{target_id} agent_id=#{agent_id} gaze=#{gaze} result=#{result}"
|
|
23
|
+
{ success: %i[joined already_attending].include?(result), result: result, target_id: target_id, agent_id: agent_id }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def leave_attention(target_id:, agent_id:, **)
|
|
27
|
+
result = joint_focus_manager.leave_target(target_id: target_id, agent_id: agent_id)
|
|
28
|
+
Legion::Logging.debug "[joint_attention] leave: target_id=#{target_id} agent_id=#{agent_id} result=#{result}"
|
|
29
|
+
{ success: result == :removed, result: result, target_id: target_id, agent_id: agent_id }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def direct_attention(from_agent:, to_agent:, target_id:, **)
|
|
33
|
+
result = joint_focus_manager.direct_attention(from_agent: from_agent, to_agent: to_agent, target_id: target_id)
|
|
34
|
+
Legion::Logging.debug "[joint_attention] direct: from=#{from_agent} to=#{to_agent} target_id=#{target_id} result=#{result}"
|
|
35
|
+
{ success: %i[directed already_attending].include?(result), result: result, target_id: target_id,
|
|
36
|
+
from_agent: from_agent, to_agent: to_agent }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def establish_mutual_awareness(target_id:, agent_a:, agent_b:, **)
|
|
40
|
+
result = joint_focus_manager.establish_shared(target_id: target_id, agent_a: agent_a, agent_b: agent_b)
|
|
41
|
+
Legion::Logging.debug "[joint_attention] mutual_awareness: target_id=#{target_id} " \
|
|
42
|
+
"agent_a=#{agent_a} agent_b=#{agent_b} result=#{result}"
|
|
43
|
+
{ success: result == :established, result: result, target_id: target_id, agent_a: agent_a, agent_b: agent_b }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update_gaze(target_id:, agent_id:, gaze:, **)
|
|
47
|
+
result = joint_focus_manager.update_gaze(target_id: target_id, agent_id: agent_id, gaze: gaze)
|
|
48
|
+
Legion::Logging.debug "[joint_attention] update_gaze: target_id=#{target_id} agent_id=#{agent_id} gaze=#{gaze} result=#{result}"
|
|
49
|
+
{ success: result == :updated, result: result, target_id: target_id, agent_id: agent_id, gaze: gaze }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def shared_focus(agent_a:, agent_b:, **)
|
|
53
|
+
targets = joint_focus_manager.shared_targets(agent_a: agent_a, agent_b: agent_b)
|
|
54
|
+
Legion::Logging.debug "[joint_attention] shared_focus: agent_a=#{agent_a} agent_b=#{agent_b} count=#{targets.size}"
|
|
55
|
+
{ success: true, agent_a: agent_a, agent_b: agent_b, shared_targets: targets.map(&:to_h), count: targets.size }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def attention_targets_for(agent_id:, **)
|
|
59
|
+
targets = joint_focus_manager.targets_for_agent(agent_id: agent_id)
|
|
60
|
+
Legion::Logging.debug "[joint_attention] targets_for: agent_id=#{agent_id} count=#{targets.size}"
|
|
61
|
+
{ success: true, agent_id: agent_id, targets: targets.map(&:to_h), count: targets.size }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def update_joint_attention(**)
|
|
65
|
+
joint_focus_manager.decay_all
|
|
66
|
+
stats = joint_focus_manager.to_h
|
|
67
|
+
Legion::Logging.debug "[joint_attention] decay_tick: targets=#{stats[:target_count]} agents=#{stats[:agent_count]}"
|
|
68
|
+
{ success: true, targets: stats[:target_count], agents: stats[:agent_count], history: stats[:history_size] }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def joint_attention_stats(**)
|
|
72
|
+
stats = joint_focus_manager.to_h
|
|
73
|
+
Legion::Logging.debug "[joint_attention] stats: targets=#{stats[:target_count]} agents=#{stats[:agent_count]}"
|
|
74
|
+
{ success: true, stats: stats }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def joint_focus_manager
|
|
80
|
+
@joint_focus_manager ||= Helpers::JointFocusManager.new
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'legion/extensions/agentic/social/joint_attention/version'
|
|
5
|
+
require 'legion/extensions/agentic/social/joint_attention/helpers/constants'
|
|
6
|
+
require 'legion/extensions/agentic/social/joint_attention/helpers/attention_target'
|
|
7
|
+
require 'legion/extensions/agentic/social/joint_attention/helpers/joint_focus_manager'
|
|
8
|
+
require 'legion/extensions/agentic/social/joint_attention/runners/joint_attention'
|
|
9
|
+
require 'legion/extensions/agentic/social/joint_attention/client'
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module Agentic
|
|
14
|
+
module Social
|
|
15
|
+
module JointAttention
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/actors/every'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Social
|
|
9
|
+
module Mentalizing
|
|
10
|
+
module Actor
|
|
11
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
12
|
+
def runner_class
|
|
13
|
+
Legion::Extensions::Agentic::Social::Mentalizing::Runners::Mentalizing
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def runner_function
|
|
17
|
+
'update_mentalizing'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def time
|
|
21
|
+
300
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def run_now?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def use_runner?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def check_subtask?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def generate_task?
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/social/mentalizing/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/social/mentalizing/helpers/belief_attribution'
|
|
5
|
+
require 'legion/extensions/agentic/social/mentalizing/helpers/mental_model'
|
|
6
|
+
require 'legion/extensions/agentic/social/mentalizing/runners/mentalizing'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Agentic
|
|
11
|
+
module Social
|
|
12
|
+
module Mentalizing
|
|
13
|
+
class Client
|
|
14
|
+
include Runners::Mentalizing
|
|
15
|
+
|
|
16
|
+
def initialize(**)
|
|
17
|
+
@mental_model = Helpers::MentalModel.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
attr_reader :mental_model
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module Mentalizing
|
|
8
|
+
module Helpers
|
|
9
|
+
class BeliefAttribution
|
|
10
|
+
attr_reader :id, :agent_id, :subject, :content, :depth, :about_agent_id, :created_at
|
|
11
|
+
attr_accessor :confidence
|
|
12
|
+
|
|
13
|
+
def initialize(agent_id:, subject:, content:, confidence:, depth: 0, about_agent_id: nil)
|
|
14
|
+
@id = SecureRandom.uuid
|
|
15
|
+
@agent_id = agent_id
|
|
16
|
+
@subject = subject
|
|
17
|
+
@content = content
|
|
18
|
+
@confidence = confidence.clamp(0.0, 1.0)
|
|
19
|
+
@depth = depth
|
|
20
|
+
@about_agent_id = about_agent_id
|
|
21
|
+
@created_at = Time.now.utc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def decay
|
|
25
|
+
@confidence = [@confidence - Constants::BELIEF_DECAY, Constants::BELIEF_FLOOR].max
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def reinforce(amount: Constants::CONFIDENCE_ALPHA)
|
|
29
|
+
@confidence = [@confidence + amount, 1.0].min
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def label
|
|
33
|
+
Constants::CONFIDENCE_LABELS.each do |range, lbl|
|
|
34
|
+
return lbl if range.cover?(@confidence)
|
|
35
|
+
end
|
|
36
|
+
:unknown
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_h
|
|
40
|
+
{
|
|
41
|
+
id: @id,
|
|
42
|
+
agent_id: @agent_id,
|
|
43
|
+
subject: @subject,
|
|
44
|
+
content: @content,
|
|
45
|
+
confidence: @confidence,
|
|
46
|
+
depth: @depth,
|
|
47
|
+
about_agent_id: @about_agent_id,
|
|
48
|
+
label: label,
|
|
49
|
+
created_at: @created_at
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module Mentalizing
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
MAX_AGENTS = 50
|
|
11
|
+
MAX_BELIEFS_PER_AGENT = 30
|
|
12
|
+
MAX_RECURSION_DEPTH = 4
|
|
13
|
+
BELIEF_DECAY = 0.02
|
|
14
|
+
BELIEF_FLOOR = 0.05
|
|
15
|
+
CONFIDENCE_ALPHA = 0.12
|
|
16
|
+
DEFAULT_CONFIDENCE = 0.3
|
|
17
|
+
MAX_HISTORY = 200
|
|
18
|
+
PROJECTION_DISCOUNT = 0.7
|
|
19
|
+
|
|
20
|
+
CONFIDENCE_LABELS = {
|
|
21
|
+
(0.8..) => :certain,
|
|
22
|
+
(0.6...0.8) => :confident,
|
|
23
|
+
(0.4...0.6) => :uncertain,
|
|
24
|
+
(0.2...0.4) => :speculative,
|
|
25
|
+
(..0.2) => :unknown
|
|
26
|
+
}.freeze
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module Mentalizing
|
|
8
|
+
module Helpers
|
|
9
|
+
class MentalModel
|
|
10
|
+
def initialize
|
|
11
|
+
@models = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def attribute_belief(agent_id:, subject:, content:, confidence:, depth: 0, about_agent_id: nil)
|
|
15
|
+
ensure_agent_capacity(agent_id)
|
|
16
|
+
capped_depth = [depth.to_i, Constants::MAX_RECURSION_DEPTH].min
|
|
17
|
+
belief = BeliefAttribution.new(
|
|
18
|
+
agent_id: agent_id,
|
|
19
|
+
subject: subject,
|
|
20
|
+
content: content,
|
|
21
|
+
confidence: confidence,
|
|
22
|
+
depth: capped_depth,
|
|
23
|
+
about_agent_id: about_agent_id
|
|
24
|
+
)
|
|
25
|
+
@models[agent_id] ||= []
|
|
26
|
+
@models[agent_id] << belief
|
|
27
|
+
prune_agent_beliefs(agent_id)
|
|
28
|
+
belief
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def beliefs_for(agent_id:)
|
|
32
|
+
@models[agent_id] || []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def beliefs_about(about_agent_id:)
|
|
36
|
+
@models.values.flatten.select { |b| b.about_agent_id == about_agent_id }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def recursive_belief(agent_id:, about_agent_id:, subject:)
|
|
40
|
+
beliefs = beliefs_for(agent_id: agent_id)
|
|
41
|
+
beliefs.select { |b| b.about_agent_id == about_agent_id && b.subject == subject }
|
|
42
|
+
.max_by(&:confidence)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def project_self(subject:, own_belief:, other_agent_id:)
|
|
46
|
+
discounted = (own_belief * Constants::PROJECTION_DISCOUNT).clamp(0.0, 1.0)
|
|
47
|
+
attribute_belief(
|
|
48
|
+
agent_id: :self,
|
|
49
|
+
subject: subject,
|
|
50
|
+
content: "projected: #{other_agent_id} thinks I believe this",
|
|
51
|
+
confidence: discounted,
|
|
52
|
+
depth: 1,
|
|
53
|
+
about_agent_id: other_agent_id
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def alignment(agent_a:, agent_b:, subject:)
|
|
58
|
+
beliefs_a = beliefs_on_subject(agent_a, subject)
|
|
59
|
+
beliefs_b = beliefs_on_subject(agent_b, subject)
|
|
60
|
+
return 0.0 if beliefs_a.empty? || beliefs_b.empty?
|
|
61
|
+
|
|
62
|
+
conf_a = beliefs_a.map(&:confidence).sum / beliefs_a.size
|
|
63
|
+
conf_b = beliefs_b.map(&:confidence).sum / beliefs_b.size
|
|
64
|
+
1.0 - (conf_a - conf_b).abs
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def detect_false_belief(agent_id:, subject:, reality:)
|
|
68
|
+
relevant = beliefs_for(agent_id: agent_id).select { |b| b.subject == subject }
|
|
69
|
+
return { false_belief: false, reason: :no_beliefs } if relevant.empty?
|
|
70
|
+
|
|
71
|
+
strongest = relevant.max_by(&:confidence)
|
|
72
|
+
false_belief = strongest.content != reality
|
|
73
|
+
{
|
|
74
|
+
false_belief: false_belief,
|
|
75
|
+
agent_id: agent_id,
|
|
76
|
+
subject: subject,
|
|
77
|
+
held_belief: strongest.content,
|
|
78
|
+
reality: reality,
|
|
79
|
+
confidence: strongest.confidence
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def decay_all
|
|
84
|
+
@models.each_value { |beliefs| beliefs.each(&:decay) }
|
|
85
|
+
prune_expired
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def remove_agent(agent_id:)
|
|
89
|
+
@models.delete(agent_id)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def agent_count
|
|
93
|
+
@models.size
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def belief_count
|
|
97
|
+
@models.values.sum(&:size)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def to_h
|
|
101
|
+
@models.transform_values { |beliefs| beliefs.map(&:to_h) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def beliefs_on_subject(agent_id, subject)
|
|
107
|
+
beliefs_for(agent_id: agent_id).select { |b| b.subject == subject }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def ensure_agent_capacity(agent_id)
|
|
111
|
+
return if @models.size < Constants::MAX_AGENTS
|
|
112
|
+
return if @models.key?(agent_id)
|
|
113
|
+
|
|
114
|
+
oldest_key = @models.keys.first
|
|
115
|
+
@models.delete(oldest_key)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def prune_agent_beliefs(agent_id)
|
|
119
|
+
list = @models[agent_id]
|
|
120
|
+
return unless list && list.size > Constants::MAX_BELIEFS_PER_AGENT
|
|
121
|
+
|
|
122
|
+
@models[agent_id] = list.sort_by(&:confidence).last(Constants::MAX_BELIEFS_PER_AGENT)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def prune_expired
|
|
126
|
+
@models.each_value do |beliefs|
|
|
127
|
+
beliefs.reject! { |b| b.confidence <= Constants::BELIEF_FLOOR }
|
|
128
|
+
end
|
|
129
|
+
@models.reject! { |_, v| v.empty? }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Social
|
|
7
|
+
module Mentalizing
|
|
8
|
+
module Runners
|
|
9
|
+
module Mentalizing
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def attribute_belief(agent_id:, subject:, content:, confidence: nil, depth: 0, about_agent_id: nil, **)
|
|
14
|
+
depth = [depth.to_i, Helpers::Constants::MAX_RECURSION_DEPTH].min
|
|
15
|
+
conf = confidence || Helpers::Constants::DEFAULT_CONFIDENCE
|
|
16
|
+
belief = mental_model.attribute_belief(
|
|
17
|
+
agent_id: agent_id,
|
|
18
|
+
subject: subject,
|
|
19
|
+
content: content,
|
|
20
|
+
confidence: conf.to_f,
|
|
21
|
+
depth: depth,
|
|
22
|
+
about_agent_id: about_agent_id
|
|
23
|
+
)
|
|
24
|
+
Legion::Logging.debug "[mentalizing] attribute agent=#{agent_id} subject=#{subject} depth=#{depth} conf=#{belief.confidence.round(2)}"
|
|
25
|
+
{ attributed: true, belief: belief.to_h }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def project_belief(subject:, own_belief:, other_agent_id:, **)
|
|
29
|
+
belief = mental_model.project_self(subject: subject, own_belief: own_belief.to_f, other_agent_id: other_agent_id)
|
|
30
|
+
Legion::Logging.debug "[mentalizing] project subject=#{subject} other=#{other_agent_id} discounted_conf=#{belief.confidence.round(2)}"
|
|
31
|
+
{ projected: true, belief: belief.to_h }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def check_alignment(agent_a:, agent_b:, subject:, **)
|
|
35
|
+
score = mental_model.alignment(agent_a: agent_a, agent_b: agent_b, subject: subject)
|
|
36
|
+
Legion::Logging.debug "[mentalizing] alignment agent_a=#{agent_a} agent_b=#{agent_b} subject=#{subject} score=#{score.round(2)}"
|
|
37
|
+
{ agent_a: agent_a, agent_b: agent_b, subject: subject, alignment: score.round(4) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def detect_false_belief(agent_id:, subject:, reality:, **)
|
|
41
|
+
result = mental_model.detect_false_belief(agent_id: agent_id, subject: subject, reality: reality)
|
|
42
|
+
Legion::Logging.info "[mentalizing] false_belief_check agent=#{agent_id} subject=#{subject} false=#{result[:false_belief]}"
|
|
43
|
+
result
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def beliefs_for_agent(agent_id:, **)
|
|
47
|
+
beliefs = mental_model.beliefs_for(agent_id: agent_id)
|
|
48
|
+
Legion::Logging.debug "[mentalizing] beliefs_for agent=#{agent_id} count=#{beliefs.size}"
|
|
49
|
+
{ agent_id: agent_id, beliefs: beliefs.map(&:to_h), count: beliefs.size }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def beliefs_about_agent(about_agent_id:, **)
|
|
53
|
+
beliefs = mental_model.beliefs_about(about_agent_id: about_agent_id)
|
|
54
|
+
Legion::Logging.debug "[mentalizing] beliefs_about about=#{about_agent_id} count=#{beliefs.size}"
|
|
55
|
+
{ about_agent_id: about_agent_id, beliefs: beliefs.map(&:to_h), count: beliefs.size }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def recursive_belief_lookup(agent_id:, about_agent_id:, subject:, **)
|
|
59
|
+
belief = mental_model.recursive_belief(agent_id: agent_id, about_agent_id: about_agent_id, subject: subject)
|
|
60
|
+
if belief
|
|
61
|
+
Legion::Logging.debug "[mentalizing] recursive agent=#{agent_id} about=#{about_agent_id} subject=#{subject} found=true"
|
|
62
|
+
{ found: true, belief: belief.to_h }
|
|
63
|
+
else
|
|
64
|
+
Legion::Logging.debug "[mentalizing] recursive agent=#{agent_id} about=#{about_agent_id} subject=#{subject} found=false"
|
|
65
|
+
{ found: false, agent_id: agent_id, about_agent_id: about_agent_id, subject: subject }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def update_mentalizing(**)
|
|
70
|
+
mental_model.decay_all
|
|
71
|
+
Legion::Logging.debug "[mentalizing] decay cycle agents=#{mental_model.agent_count} beliefs=#{mental_model.belief_count}"
|
|
72
|
+
{ decayed: true, agents: mental_model.agent_count, beliefs: mental_model.belief_count }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def mentalizing_stats(**)
|
|
76
|
+
{
|
|
77
|
+
agents: mental_model.agent_count,
|
|
78
|
+
beliefs: mental_model.belief_count
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def mental_model
|
|
85
|
+
@mental_model ||= Helpers::MentalModel.new
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|