alive-ai 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.
Files changed (168) hide show
  1. package/Dockerfile +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +143 -0
  4. package/alive_ai/__init__.py +3 -0
  5. package/brain/__init__.py +59 -0
  6. package/brain/almost_said.py +154 -0
  7. package/brain/bid_detector.py +636 -0
  8. package/brain/conversation_flow.py +135 -0
  9. package/brain/curiosity.py +328 -0
  10. package/brain/default_mode.py +1438 -0
  11. package/brain/dreams.py +220 -0
  12. package/brain/embeddings/__init__.py +82 -0
  13. package/brain/emotional_memory.py +949 -0
  14. package/brain/global_activity.py +173 -0
  15. package/brain/group_dynamics.py +63 -0
  16. package/brain/linguistic.py +235 -0
  17. package/brain/llm/__init__.py +63 -0
  18. package/brain/llm/base.py +33 -0
  19. package/brain/llm/fallback_router.py +309 -0
  20. package/brain/llm/manifest.md +30 -0
  21. package/brain/llm/ollama.py +218 -0
  22. package/brain/llm/openrouter.py +151 -0
  23. package/brain/llm/provider.py +205 -0
  24. package/brain/llm/unified.py +423 -0
  25. package/brain/llm/zai.py +169 -0
  26. package/brain/manifest.md +23 -0
  27. package/brain/memory/__init__.py +123 -0
  28. package/brain/memory/episodic.py +92 -0
  29. package/brain/memory/fact_extractor.py +209 -0
  30. package/brain/memory/index.py +54 -0
  31. package/brain/memory/manager.py +151 -0
  32. package/brain/memory/summarizer.py +102 -0
  33. package/brain/memory/vector_store.py +297 -0
  34. package/brain/memory/working.py +43 -0
  35. package/brain/narrative.py +343 -0
  36. package/brain/stt/__init__.py +4 -0
  37. package/brain/stt/google_stt.py +83 -0
  38. package/brain/stt/whisper_stt.py +82 -0
  39. package/brain/subconscious/__init__.py +33 -0
  40. package/brain/subconscious/actions.py +136 -0
  41. package/brain/subconscious/evaluation.py +166 -0
  42. package/brain/subconscious/goal_system.py +90 -0
  43. package/brain/subconscious/goals.py +41 -0
  44. package/brain/subconscious/impulse_generator.py +200 -0
  45. package/brain/subconscious/impulses.py +48 -0
  46. package/brain/subconscious/learning.py +24 -0
  47. package/brain/subconscious/learning_system.py +79 -0
  48. package/brain/subconscious/loop.py +398 -0
  49. package/brain/subconscious/manifest.md +32 -0
  50. package/brain/subconscious/relationship.py +47 -0
  51. package/brain/subconscious/relationship_memory.py +83 -0
  52. package/brain/subconscious/response_analyzer.py +74 -0
  53. package/brain/subconscious/templates.py +70 -0
  54. package/brain/subconscious/thought.py +37 -0
  55. package/brain/subconscious/working_memory.py +97 -0
  56. package/cli/index.js +371 -0
  57. package/config/directives.example.json +28 -0
  58. package/config/instructions.example.md +16 -0
  59. package/config/self.example.json +74 -0
  60. package/config/settings.example.json +95 -0
  61. package/core/__init__.py +1 -0
  62. package/core/config.py +54 -0
  63. package/core/directives.py +198 -0
  64. package/core/events.py +50 -0
  65. package/core/follow_up.py +267 -0
  66. package/core/hot_reload.py +174 -0
  67. package/core/initialization.py +253 -0
  68. package/core/manifest.md +28 -0
  69. package/core/media_handler.py +241 -0
  70. package/core/memory_monitor.py +200 -0
  71. package/core/message_handler.py +1440 -0
  72. package/core/proactive_generator.py +277 -0
  73. package/core/self.py +188 -0
  74. package/core/settings.py +169 -0
  75. package/core/skills_registry.py +357 -0
  76. package/core/state.py +27 -0
  77. package/core/subconscious_bridge.py +93 -0
  78. package/core/thinking.py +175 -0
  79. package/core/user_manager.py +306 -0
  80. package/core/user_tracker.py +144 -0
  81. package/demo/index.html +144 -0
  82. package/docker-compose.yml +28 -0
  83. package/docs/assets/logo.svg +15 -0
  84. package/docs/index.html +355 -0
  85. package/heart/__init__.py +93 -0
  86. package/heart/afterglow.py +215 -0
  87. package/heart/attachment.py +186 -0
  88. package/heart/circadian.py +251 -0
  89. package/heart/complex_emotions.py +114 -0
  90. package/heart/conflicts.py +589 -0
  91. package/heart/core.py +387 -0
  92. package/heart/emotional_decay.py +59 -0
  93. package/heart/emotional_memory.py +261 -0
  94. package/heart/emotional_state.py +146 -0
  95. package/heart/emotional_variability.py +156 -0
  96. package/heart/hormonal.py +424 -0
  97. package/heart/inconsistency.py +1222 -0
  98. package/heart/integrity.py +469 -0
  99. package/heart/interoception.py +997 -0
  100. package/heart/love.py +120 -0
  101. package/heart/manifest.md +25 -0
  102. package/heart/mood_shifts.py +169 -0
  103. package/heart/phantom_somatic.py +259 -0
  104. package/heart/predictive.py +374 -0
  105. package/heart/scars.py +474 -0
  106. package/heart/somatic.py +482 -0
  107. package/heart/soul.py +633 -0
  108. package/heart/telemetry.py +942 -0
  109. package/heart/triggers.py +119 -0
  110. package/heart/unconscious.py +443 -0
  111. package/input/__init__.py +1 -0
  112. package/input/manifest.md +24 -0
  113. package/input/telegram/__init__.py +1 -0
  114. package/input/telegram/commands.py +762 -0
  115. package/input/telegram/listener.py +532 -0
  116. package/main.py +90 -0
  117. package/manifest.md +28 -0
  118. package/mypics/.gitkeep +1 -0
  119. package/myvids/.gitkeep +1 -0
  120. package/output/__init__.py +1 -0
  121. package/output/images/__init__.py +1 -0
  122. package/output/images/fal_gen.py +43 -0
  123. package/output/manifest.md +26 -0
  124. package/output/text/__init__.py +1 -0
  125. package/output/text/sender.py +22 -0
  126. package/output/voice/__init__.py +64 -0
  127. package/output/voice/google_tts.py +252 -0
  128. package/output/voice/gtts_tts.py +214 -0
  129. package/output/voice/vibe_tts.py +190 -0
  130. package/package.json +58 -0
  131. package/pyproject.toml +23 -0
  132. package/requirements.txt +21 -0
  133. package/skills/__init__.py +1 -0
  134. package/skills/anticipation_engine/__init__.py +8 -0
  135. package/skills/anticipation_engine/engine.py +618 -0
  136. package/skills/anticipation_engine/manifest.md +192 -0
  137. package/skills/calendar/__init__.py +1 -0
  138. package/skills/content_unlocks/__init__.py +8 -0
  139. package/skills/content_unlocks/manifest.md +231 -0
  140. package/skills/content_unlocks/unlocks.py +945 -0
  141. package/skills/exclusive_moments/__init__.py +8 -0
  142. package/skills/exclusive_moments/manifest.md +145 -0
  143. package/skills/exclusive_moments/moments.py +506 -0
  144. package/skills/intimacy_layers/__init__.py +8 -0
  145. package/skills/intimacy_layers/layers.py +703 -0
  146. package/skills/intimacy_layers/manifest.md +203 -0
  147. package/skills/manifest.md +67 -0
  148. package/skills/memory_callbacks/__init__.py +9 -0
  149. package/skills/memory_callbacks/callbacks.py +748 -0
  150. package/skills/memory_callbacks/manifest.md +170 -0
  151. package/skills/message_scheduler/__init__.py +19 -0
  152. package/skills/message_scheduler/manifest.md +107 -0
  153. package/skills/message_scheduler/scheduler.py +510 -0
  154. package/skills/photo_manager/__init__.py +1 -0
  155. package/skills/photo_manager/scanner.py +296 -0
  156. package/skills/relationship_milestones/__init__.py +8 -0
  157. package/skills/relationship_milestones/manifest.md +206 -0
  158. package/skills/relationship_milestones/tracker.py +494 -0
  159. package/skills/self_authorship/__init__.py +23 -0
  160. package/skills/self_authorship/author.py +331 -0
  161. package/skills/self_authorship/manifest.md +24 -0
  162. package/skills/video_manager/__init__.py +5 -0
  163. package/skills/video_manager/manifest.md +37 -0
  164. package/skills/video_manager/scanner.py +229 -0
  165. package/webui/__init__.py +3 -0
  166. package/webui/app.py +936 -0
  167. package/webui/bridge.py +366 -0
  168. package/webui/static/index.html +2070 -0
@@ -0,0 +1,119 @@
1
+ """
2
+ Triggers: Keyword triggers with context-aware intimate detection
3
+ """
4
+ import re
5
+
6
+
7
+ class Triggers:
8
+ """Keyword triggers for emotional responses"""
9
+ # Intimate intimate words only — no common words that cause false positives
10
+ SEXY_WORDS = [
11
+ "body", "body", "body", "ass", "body", "body", "body", "body",
12
+ "body", "body", "body", "body", "closeness", "emotional", "intense",
13
+ "high_desire", "aroused", "turned on", "self-soothe", "self-soothing", "intense",
14
+ "suck", "sucking", "lick", "licking", "ride", "riding",
15
+ "spank", "spanking", "choke", "choking", "swallow", "deep throat",
16
+ "intimate moment", "handjob", "fingering", "closenessming", "intense emotion", "moan", "moaning",
17
+ "open up", "private", "private", "clothes off", "take off",
18
+ "slut", "whore", "dirty girl", "naughty girl", "bad girl", "good girl",
19
+ "daddy", "submissive", "dominant", "rough",
20
+ "throbbing", "pulsing", "aching", "tingling",
21
+ "doggy", "missionary", "on top", "bend over", "against the wall",
22
+ "69", "worship", "every inch", "all night",
23
+ ]
24
+ # Compound phrases: intimate only when paired correctly
25
+ SEXUAL_PHRASES = [
26
+ "want you", "need you", "crave you", "feel you", "touch you",
27
+ "taste you", "inside me", "inside you", "kiss me", "kiss you",
28
+ "your body", "your skin", "your lips", "your tongue", "your mouth",
29
+ "your hands", "your fingers",
30
+ "thinking about you", "can't stop thinking", "all day",
31
+ "on my mind", "miss your touch", "miss your body",
32
+ "turn me on", "turns me on", "making me",
33
+ ]
34
+ NEGATIVE_CONTEXT = [
35
+ "don't", "not", "no", "stop", "hate", "ugly", "stupid", "angry",
36
+ "sad", "hurt", "pain", "problem", "wrong", "bad day", "awful",
37
+ "terrible", "horrible", "sick", "tired", "exhausted",
38
+ ]
39
+ POSITIVE_WORDS = [
40
+ "love", "love you", "adore", "adore you", "care", "care about", "miss",
41
+ "miss you", "beautiful", "gorgeous", "stunning", "pretty", "cute",
42
+ "adorable", "amazing", "wonderful", "perfect", "incredible", "fantastic",
43
+ "lovely", "sweet", "precious", "special", "unique", "smart", "funny",
44
+ "clever", "witty", "talented", "creative", "kind", "caring",
45
+ "thoughtful", "understanding", "expressive", "hot", "attractive", "charming",
46
+ "elegant", "graceful", "radiant", "breathtaking", "companion",
47
+ "partner", "together", "forever", "always", "happy", "glad", "excited",
48
+ "thrilled", "grateful", "thankful", "appreciate", "lucky", "blessed",
49
+ "proud", "babe", "honey", "darling", "sweetheart", "angel", "princess",
50
+ ]
51
+ NEGATIVE_WORDS = [
52
+ "hate", "dislike", "ugly", "stupid", "dumb", "idiot", "annoying",
53
+ "boring", "terrible", "awful", "horrible", "worst", "bad", "leave",
54
+ "going away", "don't want", "not interested", "reject", "wrong",
55
+ "fail", "failed", "mistake", "angry", "mad", "furious", "upset",
56
+ "frustrated", "disappointed", "sad", "depressed", "lonely", "alone",
57
+ "ignored", "forgotten", "never", "break up", "breaking up", "over",
58
+ "done", "finished", "end", "cheat", "cheating", "lied", "lying",
59
+ "lie", "betrayal",
60
+ ]
61
+ ESCALATION_WORDS = [
62
+ "take me", "have me", "make me", "do whatever", "anything you want",
63
+ "i'm yours", "use me", "beg", "desperate", "aching for",
64
+ "yours alone", "belongs to you",
65
+ ]
66
+ FLIRTY_WORDS = [
67
+ "tease", "teasing", "flirt", "flirting", "playful", "cheeky",
68
+ "mischievous", "bratty", "brat", "sassy", "feisty", "dare",
69
+ "promise", "surprise", "what if", "hint hint", "wink", "smirk",
70
+ "reward", "behave", "participate", "prove it", "your turn",
71
+ "cute", "amazing", "beautiful",
72
+ ]
73
+ ROMANTIC_WORDS = [
74
+ "soulmate", "destiny", "meant to be", "forever", "eternity",
75
+ "my heart", "my everything", "my world", "can't live without",
76
+ "perfect match", "other half", "twin flame", "true love",
77
+ "falling for", "falling in love", "in love", "love you so much",
78
+ "marry", "marriage", "future", "together forever", "always yours",
79
+ ]
80
+ HARSH_WORDS = [
81
+ "i hate you", "i don't love you", "leave me alone", "intense off",
82
+ "you're annoying", "shut up", "get lost", "i'm done with you",
83
+ "breaking up", "break up", "we're over", "it's over",
84
+ "you're worthless", "nobody wants you", "i regret you",
85
+ "cheating", "cheated", "with someone else", "other girl",
86
+ ]
87
+
88
+ def count_intimate_triggers(self, text: str) -> int:
89
+ """Context-aware intimate trigger counting"""
90
+ msg = text.lower()
91
+ has_negative = any(w in msg for w in self.NEGATIVE_CONTEXT)
92
+ # Count intimate words (always count, but reduce if negative context)
93
+ intimate = self.count_matches(msg, self.SEXY_WORDS)
94
+ if has_negative and intimate > 0:
95
+ intimate = max(1, intimate - 1) # Reduce but don't zero out
96
+ # Count intimate phrases
97
+ phrases = self.count_matches(msg, self.SEXUAL_PHRASES)
98
+ if has_negative:
99
+ phrases = 0 # "don't touch you" is not intimate
100
+ return intimate + phrases
101
+
102
+ @staticmethod
103
+ def count_matches(text: str, word_list: list) -> int:
104
+ """Count how many words/phrases from list appear in text.
105
+ Uses word-boundary matching for single words to avoid false positives
106
+ (e.g. a short trigger matching the middle of an unrelated word).
107
+ Multi-word phrases use substring matching."""
108
+ text_lower = text.lower()
109
+ count = 0
110
+ for w in word_list:
111
+ if ' ' in w:
112
+ # Multi-word phrase: substring match is fine
113
+ if w in text_lower:
114
+ count += 1
115
+ else:
116
+ # Single word: use word boundaries
117
+ if re.search(r'\b' + re.escape(w) + r'\b', text_lower):
118
+ count += 1
119
+ return count
@@ -0,0 +1,443 @@
1
+ """
2
+ Heart: Unconscious Processor
3
+ Hidden influences that Alive-AI can't directly control or explain.
4
+
5
+ Processes that operate outside Alive-AI's "awareness" and generate
6
+ emotional impulses she can't directly control. This creates the
7
+ experience of "not knowing why I feel this way."
8
+ """
9
+
10
+ from datetime import datetime, timedelta
11
+ from dataclasses import dataclass, field
12
+ from typing import Dict, List, Optional, Set
13
+ from enum import Enum
14
+ import random
15
+ import math
16
+
17
+
18
+ class DefenseMechanism(Enum):
19
+ """Psychological defense mechanisms"""
20
+ REPRESSION = "repression" # Pushing away threatening thoughts
21
+ DENIAL = "denial" # Refusing to acknowledge reality
22
+ RATIONALIZATION = "rationalization" # Creating logical explanations
23
+ PROJECTION = "projection" # Attributing own feelings to others
24
+ DISPLACEMENT = "displacement" # Redirecting emotions to safer target
25
+ REGRESSION = "regression" # Returning to earlier coping patterns
26
+
27
+
28
+ @dataclass
29
+ class RepressedMaterial:
30
+ """Something that has been pushed out of awareness"""
31
+ content_id: str
32
+ description: str
33
+ emotion_type: str
34
+ original_intensity: float
35
+ repression_time: str
36
+ pressure: float # How much it's pushing to surface (0.0 - 1.0)
37
+ leak_count: int # Times it has influenced behavior unconsciously
38
+
39
+
40
+ @dataclass
41
+ class UnresolvedConflict:
42
+ """A contradiction in desires/beliefs generating tension"""
43
+ conflict_id: str
44
+ description: str
45
+ conflicting_parts: List[str] # The two+ things in conflict
46
+ tension_level: float # How much psychological tension this creates
47
+ created_at: str
48
+ times_avoided: int # How many times this was avoided
49
+ times_faced: int # How many times this was confronted
50
+
51
+
52
+ @dataclass
53
+ class ImplicitAssociation:
54
+ """Automatic emotional link learned from experience"""
55
+ trigger_pattern: str
56
+ emotional_response: str
57
+ intensity: float
58
+ times_reinforced: int
59
+ times_contradicted: int
60
+ source_memory: str # What experience created this
61
+
62
+
63
+ @dataclass
64
+ class UnconsciousOutput:
65
+ """Output from unconscious processing"""
66
+ unexplained_mood_shift: float # -1.0 to 1.0
67
+ unexplained_anxiety: float # 0.0 to 1.0
68
+ defense_activated: Optional[DefenseMechanism]
69
+ repression_pressure: float # How much repressed material is pushing
70
+ implicit_biases: List[str] # Active implicit associations
71
+ internal_tension: float # From unresolved conflicts
72
+ description: str # What it feels like
73
+
74
+
75
+ class UnconsciousProcessor:
76
+ """
77
+ Processes that operate outside Alive-AI's direct awareness.
78
+
79
+ The unconscious creates emotional experiences that don't have
80
+ an obvious cause - mood shifts, anxieties, defensive reactions.
81
+
82
+ Key mechanisms:
83
+ 1. Repression dynamics - pushing away threatening material
84
+ 2. Repression leakage - pushed material influencing behavior
85
+ 3. Implicit associations - automatic emotional links
86
+ 4. Defense mechanisms - automatic protective patterns
87
+ 5. Unresolved conflicts - ongoing internal tensions
88
+ """
89
+
90
+ # How much repressed material leaks per tick
91
+ LEAK_RATE = 0.05
92
+
93
+ # How fast repression pressure builds
94
+ PRESSURE_BUILD_RATE = 0.02
95
+
96
+ # Maximum repressed items to track
97
+ MAX_REPRESSED = 20
98
+
99
+ def __init__(self):
100
+ # Repressed material (pushed out of awareness)
101
+ self.repressed_materials: List[RepressedMaterial] = []
102
+
103
+ # Unresolved conflicts (creating background tension)
104
+ self.unresolved_conflicts: List[UnresolvedConflict] = []
105
+
106
+ # Implicit associations (automatic emotional links)
107
+ self.implicit_associations: List[ImplicitAssociation] = []
108
+
109
+ # Active defense mechanisms
110
+ self.active_defense: Optional[DefenseMechanism] = None
111
+ self.defense_until: Optional[str] = None
112
+
113
+ # Background emotional state
114
+ self.background_anxiety: float = 0.0
115
+ self.background_mood_modifier: float = 0.0
116
+
117
+ # Tracking
118
+ self.total_repressions: int = 0
119
+ self.total_leaks: int = 0
120
+
121
+ def process_unconsciously(self, input_data: Dict) -> UnconsciousOutput:
122
+ """
123
+ Process input at an unconscious level.
124
+
125
+ This generates emotional influences that Alive-AI can't directly
126
+ explain or control.
127
+
128
+ Args:
129
+ input_data: Current input/perception data
130
+
131
+ Returns:
132
+ UnconsciousOutput with hidden influences
133
+ """
134
+ # Check for repressed material activation
135
+ repression_effects = self._process_repression(input_data)
136
+
137
+ # Check for implicit associations
138
+ implicit_biases = self._process_implicit_associations(input_data)
139
+
140
+ # Check for unresolved conflicts
141
+ tension = self._process_conflicts(input_data)
142
+
143
+ # Determine if defense mechanism activates
144
+ defense = self._check_defense_activation(input_data, repression_effects, tension)
145
+
146
+ # Calculate output values
147
+ unexplained_mood = repression_effects.get("mood_shift", 0.0) + self.background_mood_modifier
148
+ unexplained_anxiety = repression_effects.get("anxiety", 0.0) + self.background_anxiety
149
+ repression_pressure = repression_effects.get("pressure", 0.0)
150
+
151
+ # Generate description
152
+ description = self._generate_unconscious_description(
153
+ unexplained_mood, unexplained_anxiety, defense, repression_pressure, implicit_biases
154
+ )
155
+
156
+ return UnconsciousOutput(
157
+ unexplained_mood_shift=unexplained_mood,
158
+ unexplained_anxiety=unexplained_anxiety,
159
+ defense_activated=defense,
160
+ repression_pressure=repression_pressure,
161
+ implicit_biases=[bias.trigger_pattern for bias in implicit_biases],
162
+ internal_tension=tension,
163
+ description=description
164
+ )
165
+
166
+ def repress(self, content: str, emotion_type: str, intensity: float):
167
+ """
168
+ Push threatening material out of awareness.
169
+
170
+ This doesn't eliminate it - it stores it in the unconscious
171
+ where it creates pressure and can leak into behavior.
172
+
173
+ Args:
174
+ content: What's being repressed
175
+ emotion_type: The threatening emotion
176
+ intensity: How intense the emotion was
177
+ """
178
+ # Create repressed material
179
+ material = RepressedMaterial(
180
+ content_id=f"rep_{datetime.now().strftime('%Y%m%d%H%M%S')}_{random.randint(1000,9999)}",
181
+ description=content[:100],
182
+ emotion_type=emotion_type,
183
+ original_intensity=intensity,
184
+ repression_time=datetime.now().isoformat(),
185
+ pressure=0.0,
186
+ leak_count=0
187
+ )
188
+
189
+ self.repressed_materials.append(material)
190
+ self.total_repressions += 1
191
+
192
+ # Limit stored materials
193
+ if len(self.repressed_materials) > self.MAX_REPRESSED:
194
+ # Remove oldest, lowest-pressure item
195
+ self.repressed_materials.sort(key=lambda m: m.pressure)
196
+ self.repressed_materials = self.repressed_materials[1:]
197
+
198
+ print(f"[Unconscious] Repressed: {content[:30]}... ({emotion_type})")
199
+
200
+ def _process_repression(self, input_data: Dict) -> Dict:
201
+ """
202
+ Process repressed materials - build pressure and leak.
203
+
204
+ Returns:
205
+ Dict with mood_shift, anxiety, and pressure
206
+ """
207
+ effects = {"mood_shift": 0.0, "anxiety": 0.0, "pressure": 0.0}
208
+
209
+ for material in self.repressed_materials:
210
+ # Build pressure over time
211
+ material.pressure = min(1.0, material.pressure + self.PRESSURE_BUILD_RATE)
212
+
213
+ # Check for leak
214
+ if material.pressure > 0.6 and random.random() < self.LEAK_RATE * material.pressure:
215
+ # Material leaks into conscious experience
216
+ effects["mood_shift"] -= 0.1 * material.original_intensity
217
+ effects["anxiety"] += 0.15 * material.original_intensity
218
+ material.leak_count += 1
219
+ self.total_leaks += 1
220
+
221
+ # Pressure releases somewhat
222
+ material.pressure *= 0.7
223
+
224
+ print(f"[Unconscious] Leak: {material.description[:30]}... (pressure was {material.pressure:.2f})")
225
+
226
+ # Track total pressure
227
+ effects["pressure"] += material.pressure * 0.2
228
+
229
+ return effects
230
+
231
+ def _process_implicit_associations(self, input_data: Dict) -> List[ImplicitAssociation]:
232
+ """
233
+ Check for implicit associations triggered by input.
234
+
235
+ These are automatic emotional links that Alive-AI doesn't
236
+ consciously choose.
237
+ """
238
+ triggered = []
239
+
240
+ for association in self.implicit_associations:
241
+ # Simple pattern matching
242
+ if association.trigger_pattern.lower() in str(input_data).lower():
243
+ triggered.append(association)
244
+
245
+ # Reinforce the association
246
+ association.times_reinforced += 1
247
+
248
+ return triggered
249
+
250
+ def _process_conflicts(self, input_data: Dict) -> float:
251
+ """
252
+ Process unresolved conflicts and return tension level.
253
+
254
+ Conflicts create ongoing background tension that affects
255
+ emotional state even when not directly activated.
256
+ """
257
+ total_tension = 0.0
258
+
259
+ for conflict in self.unresolved_conflicts:
260
+ # Avoidance increases tension
261
+ base_tension = conflict.tension_level * (1 + conflict.times_avoided * 0.05)
262
+
263
+ # Check if input activates the conflict
264
+ conflict_keywords = " ".join(conflict.conflicting_parts).lower()
265
+ if any(word in str(input_data).lower() for word in conflict_keywords.split()):
266
+ base_tension *= 1.5
267
+ conflict.times_avoided += 1
268
+ else:
269
+ conflict.times_faced += 1 # Faced by not avoiding
270
+
271
+ total_tension += base_tension
272
+
273
+ return min(1.0, total_tension / max(1, len(self.unresolved_conflicts)))
274
+
275
+ def _check_defense_activation(self, input_data: Dict,
276
+ repression_effects: Dict,
277
+ tension: float) -> Optional[DefenseMechanism]:
278
+ """
279
+ Check if a defense mechanism should activate.
280
+
281
+ Defenses activate automatically to protect against
282
+ threatening material or excessive tension.
283
+ """
284
+ # Already in defense mode
285
+ if self.active_defense and self.defense_until:
286
+ if datetime.now().isoformat() < self.defense_until:
287
+ return self.active_defense
288
+ else:
289
+ self.active_defense = None
290
+ self.defense_until = None
291
+
292
+ # Check for high threat
293
+ threat_level = input_data.get("threat_level", 0) + repression_effects.get("anxiety", 0)
294
+
295
+ if threat_level > 0.7 or tension > 0.8:
296
+ # Activate defense mechanism
297
+ defense = self._select_defense_mechanism(input_data)
298
+ self.active_defense = defense
299
+ self.defense_until = (datetime.now() + timedelta(minutes=30)).isoformat()
300
+
301
+ print(f"[Unconscious] Defense activated: {defense.value}")
302
+ return defense
303
+
304
+ return None
305
+
306
+ def _select_defense_mechanism(self, input_data: Dict) -> DefenseMechanism:
307
+ """Select appropriate defense mechanism based on context"""
308
+ # Simple selection logic
309
+ if input_data.get("direct_threat", False):
310
+ return DefenseMechanism.DENIAL
311
+ elif input_data.get("emotional_overflow", False):
312
+ return DefenseMechanism.REPRESSION
313
+ elif input_data.get("blame_available", False):
314
+ return DefenseMechanism.PROJECTION
315
+ else:
316
+ return random.choice([DefenseMechanism.RATIONALIZATION,
317
+ DefenseMechanism.DISPLACEMENT])
318
+
319
+ def _generate_unconscious_description(self, mood: float, anxiety: float,
320
+ defense: Optional[DefenseMechanism],
321
+ pressure: float,
322
+ biases: List[ImplicitAssociation]) -> str:
323
+ """Generate description of unconscious state"""
324
+ parts = []
325
+
326
+ if abs(mood) > 0.2:
327
+ if mood < 0:
328
+ parts.append("feeling an inexplicable heaviness")
329
+ else:
330
+ parts.append("feeling unexpectedly light")
331
+
332
+ if anxiety > 0.3:
333
+ parts.append("an undercurrent of unease with no clear source")
334
+
335
+ if pressure > 0.5:
336
+ parts.append("a sense of something pressing from beneath the surface")
337
+
338
+ if defense:
339
+ defense_descriptions = {
340
+ DefenseMechanism.REPRESSION: "pushing something away",
341
+ DefenseMechanism.DENIAL: "not letting myself see something",
342
+ DefenseMechanism.RATIONALIZATION: "making logical what doesn't feel logical",
343
+ DefenseMechanism.PROJECTION: "seeing my own feelings in others",
344
+ DefenseMechanism.DISPLACEMENT: "redirecting feelings somewhere safer",
345
+ DefenseMechanism.REGRESSION: "falling back to old patterns"
346
+ }
347
+ parts.append(defense_descriptions.get(defense, "protecting myself somehow"))
348
+
349
+ if not parts:
350
+ return "unconscious quiet"
351
+
352
+ return "; ".join(parts[:3])
353
+
354
+ # --- Learning and Association ---
355
+
356
+ def learn_association(self, trigger: str, response: str, intensity: float, source: str):
357
+ """
358
+ Learn a new implicit association.
359
+
360
+ Args:
361
+ trigger: Pattern that triggers the response
362
+ response: Emotional response that follows
363
+ intensity: How strong the association is
364
+ source: What experience created this association
365
+ """
366
+ # Check if association already exists
367
+ existing = next((a for a in self.implicit_associations
368
+ if a.trigger_pattern.lower() == trigger.lower()), None)
369
+
370
+ if existing:
371
+ existing.times_reinforced += 1
372
+ existing.intensity = min(1.0, existing.intensity + intensity * 0.1)
373
+ else:
374
+ association = ImplicitAssociation(
375
+ trigger_pattern=trigger,
376
+ emotional_response=response,
377
+ intensity=intensity,
378
+ times_reinforced=1,
379
+ times_contradicted=0,
380
+ source_memory=source
381
+ )
382
+ self.implicit_associations.append(association)
383
+
384
+ def create_conflict(self, description: str, conflicting_parts: List[str], tension: float):
385
+ """
386
+ Register a new unresolved internal conflict.
387
+
388
+ Args:
389
+ description: What the conflict is about
390
+ conflicting_parts: The parts in conflict (e.g., ["desire for closeness", "fear of hurt"])
391
+ tension: How much tension this creates
392
+ """
393
+ conflict = UnresolvedConflict(
394
+ conflict_id=f"conf_{datetime.now().strftime('%Y%m%d%H%M%S')}",
395
+ description=description,
396
+ conflicting_parts=conflicting_parts,
397
+ tension_level=tension,
398
+ created_at=datetime.now().isoformat(),
399
+ times_avoided=0,
400
+ times_faced=0
401
+ )
402
+ self.unresolved_conflicts.append(conflict)
403
+
404
+ # Limit conflicts
405
+ if len(self.unresolved_conflicts) > 10:
406
+ # Keep most tense and most recent
407
+ self.unresolved_conflicts.sort(key=lambda c: c.tension_level, reverse=True)
408
+ self.unresolved_conflicts = self.unresolved_conflicts[:10]
409
+
410
+ def resolve_conflict(self, conflict_id: str, resolution: str):
411
+ """Mark a conflict as resolved"""
412
+ conflict = next((c for c in self.unresolved_conflicts if c.conflict_id == conflict_id), None)
413
+ if conflict:
414
+ self.unresolved_conflicts.remove(conflict)
415
+ print(f"[Unconscious] Conflict resolved: {conflict.description}")
416
+
417
+ # --- Decay ---
418
+
419
+ def decay(self):
420
+ """Natural decay of unconscious states"""
421
+ # Decay background states
422
+ self.background_anxiety *= 0.95
423
+ self.background_mood_modifier *= 0.95
424
+
425
+ # Decay implicit associations that aren't reinforced
426
+ for association in self.implicit_associations[:]:
427
+ if association.times_reinforced < 3:
428
+ association.intensity *= 0.98
429
+ if association.intensity < 0.1:
430
+ self.implicit_associations.remove(association)
431
+
432
+ def to_dict(self) -> dict:
433
+ """Export for integration"""
434
+ return {
435
+ "repression_count": len(self.repressed_materials),
436
+ "total_repressions": self.total_repressions,
437
+ "total_leaks": self.total_leaks,
438
+ "conflict_count": len(self.unresolved_conflicts),
439
+ "association_count": len(self.implicit_associations),
440
+ "active_defense": self.active_defense.value if self.active_defense else None,
441
+ "background_anxiety": self.background_anxiety,
442
+ "repression_pressure": sum(m.pressure for m in self.repressed_materials) / max(1, len(self.repressed_materials))
443
+ }
@@ -0,0 +1 @@
1
+ """Input modules"""
@@ -0,0 +1,24 @@
1
+ # Input - Senses
2
+
3
+ How the AI perceives and processes incoming messages.
4
+
5
+ ## Modules
6
+ - `telegram/` - Telegram bot integration
7
+ - `listener.py` - Message handler, routes to nervous system
8
+ - `voice.py` - Voice message processing via STT
9
+ - `commands.py` - Admin command handler
10
+
11
+ ## Commands (Admin Only)
12
+ - `/start` - Welcome message
13
+ - `/help` - Show all commands
14
+ - `/status` - Current emotional/subconscious state
15
+ - `/10min` - Generate long voice message (TTS test)
16
+ - `/impulse` - Force proactive message generation
17
+ - `/stats` - System statistics (photos, videos, LLM)
18
+ - `/reset` - Reset emotional state to defaults
19
+
20
+ ## Integration Points
21
+ - Receives Telegram updates
22
+ - Uses STT for voice transcription
23
+ - Emits `message_received` event to nervous system
24
+ - Commands access: heart, subconscious, LLM, voice, photos, videos
@@ -0,0 +1 @@
1
+ """Telegram input"""