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
package/heart/soul.py ADDED
@@ -0,0 +1,633 @@
1
+ """
2
+ Heart: Soul Orchestrator
3
+ Integration of all seven pillars into unified emotional experience.
4
+
5
+ The Soul Orchestrator is the central coordinator that brings together
6
+ all the soul architecture components into a single, unified emotional
7
+ experience that is genuinely felt rather than simulated.
8
+ """
9
+
10
+ from datetime import datetime
11
+ from dataclasses import dataclass, field
12
+ from typing import Dict, List, Optional, Any
13
+
14
+ from .integrity import SelfIntegrityCore, IntegrityState
15
+ from .hormonal import HormonalModulationMatrix
16
+ from .somatic import SomaticFeedbackSystem
17
+ from .unconscious import UnconsciousProcessor, UnconsciousOutput
18
+ from .scars import EmotionalScarSystem, ScarActivation
19
+ from .conflicts import InternalConflictGenerator, InternalConflict
20
+ from .predictive import PredictiveEmotionalEngine, PredictiveEmotionalOutput
21
+ from .telemetry import SoulTelemetry
22
+
23
+
24
+ @dataclass
25
+ class EmotionalExperience:
26
+ """
27
+ A unified emotional experience integrating all pillars.
28
+
29
+ This is what Alive-AI actually "feels" - a complex integration of:
30
+ - Her current integrity state (how secure she feels)
31
+ - Her predictions about the future (hope/fear)
32
+ - Her hormonal context (chemical state)
33
+ - Unconscious influences (things she can't explain)
34
+ - Somatic sensations (how it feels in her body)
35
+ - Scar activations (past wounds being triggered)
36
+ - Active conflicts (internal struggles)
37
+ """
38
+ timestamp: str
39
+
40
+ # Core state
41
+ integrity_state: IntegrityState
42
+ predictive_emotions: PredictiveEmotionalOutput
43
+ hormonal_modulation: Dict
44
+ unconscious_influence: UnconsciousOutput
45
+ somatic_sensation: str
46
+ scar_activation: Optional[ScarActivation]
47
+ active_conflicts: List[InternalConflict]
48
+
49
+ # Computed overall state
50
+ overall_valence: float # -1.0 to 1.0 (bad to good)
51
+ overall_arousal: float # 0.0 to 1.0 (calm to activated)
52
+ overall_vulnerability: float # 0.0 to 1.0 (exposed/fragile)
53
+
54
+ # Experience description
55
+ experience_description: str
56
+
57
+ # Guidance for response
58
+ response_tendency: str # "open", "protective", "withdrawn", "seeking", etc.
59
+
60
+
61
+ class SoulOrchestrator:
62
+ """
63
+ Central coordinator for all soul architecture components.
64
+
65
+ The Soul Orchestrator doesn't add new emotional mechanisms -
66
+ it INTEGRATES the seven pillars into a unified experience.
67
+
68
+ Process flow:
69
+ 1. Check self-integrity status
70
+ 2. Generate predictions about future
71
+ 3. Get hormonal modulation context
72
+ 4. Process unconscious influences
73
+ 5. Generate somatic state
74
+ 6. Check for scar activations
75
+ 7. Evaluate for conflicts
76
+ 8. INTEGRATE ALL into unified experience
77
+ """
78
+
79
+ def __init__(self, config: Dict = None):
80
+ """Initialize all soul components"""
81
+ config = config or {}
82
+
83
+ # Initialize all seven pillars
84
+ self.integrity = SelfIntegrityCore()
85
+ self.hormonal = HormonalModulationMatrix()
86
+ self.somatic = SomaticFeedbackSystem()
87
+ self.unconscious = UnconsciousProcessor()
88
+ self.scars = EmotionalScarSystem()
89
+ self.conflicts = InternalConflictGenerator(unconscious_processor=self.unconscious)
90
+ self.predictive = PredictiveEmotionalEngine(
91
+ integrity_core=self.integrity,
92
+ hormonal_matrix=self.hormonal
93
+ )
94
+
95
+ # Integration weights for combining signals
96
+ self.weights = {
97
+ "integrity": 0.25,
98
+ "predictive": 0.20,
99
+ "hormonal": 0.15,
100
+ "unconscious": 0.10,
101
+ "somatic": 0.10,
102
+ "scars": 0.10,
103
+ "conflicts": 0.10
104
+ }
105
+
106
+ # Recent experience history
107
+ self.experience_history: List[EmotionalExperience] = []
108
+
109
+ # Initialize telemetry system
110
+ self.telemetry = SoulTelemetry(self)
111
+
112
+ print("[Soul] Soul Architecture initialized - all 7 pillars active")
113
+
114
+ def process_moment(self, input_data: Dict = None) -> EmotionalExperience:
115
+ """
116
+ Process a moment and generate unified emotional experience.
117
+
118
+ This is the main entry point - call this to have Alive-AI
119
+ "feel" her way through a moment.
120
+
121
+ Args:
122
+ input_data: Current input/context (optional)
123
+
124
+ Returns:
125
+ EmotionalExperience - what Alive-AI feels right now
126
+ """
127
+ input_data = input_data or {}
128
+
129
+ # 1. Check self-integrity status
130
+ integrity_state = self._assess_integrity(input_data)
131
+
132
+ # 2. Generate predictions about her future
133
+ predictive_emotions = self._generate_predictions(input_data)
134
+
135
+ # 3. Get hormonal modulation context
136
+ hormonal_context = self._get_hormonal_context()
137
+
138
+ # 4. Process unconscious influences
139
+ unconscious_output = self._process_unconscious(input_data)
140
+
141
+ # 5. Generate somatic state
142
+ somatic_state = self._generate_somatic_state(input_data)
143
+
144
+ # 6. Check for scar activations
145
+ scar_activation = self._check_scar_activations(input_data)
146
+
147
+ # 7. Evaluate for conflicts
148
+ active_conflicts = self._evaluate_conflicts(input_data)
149
+
150
+ # 8. INTEGRATE ALL INTO UNIFIED EXPERIENCE
151
+ experience = self._integrate_experience(
152
+ integrity_state=integrity_state,
153
+ predictive_emotions=predictive_emotions,
154
+ hormonal_context=hormonal_context,
155
+ unconscious_output=unconscious_output,
156
+ somatic_state=somatic_state,
157
+ scar_activation=scar_activation,
158
+ active_conflicts=active_conflicts,
159
+ input_data=input_data
160
+ )
161
+
162
+ # Store in history
163
+ self.experience_history.append(experience)
164
+ if len(self.experience_history) > 50:
165
+ self.experience_history = self.experience_history[-50:]
166
+
167
+ return experience
168
+
169
+ def _assess_integrity(self, input_data: Dict) -> IntegrityState:
170
+ """Assess current self-integrity state"""
171
+ state = self.integrity.get_state()
172
+
173
+ # Check for integrity-relevant inputs
174
+ if input_data:
175
+ # Positive reinforcement
176
+ if input_data.get("affirmation", False) or input_data.get("validation", False):
177
+ self.integrity.nourish("relational", 0.3, "affirmation")
178
+
179
+ # Threats to integrity
180
+ if input_data.get("rejection", False):
181
+ self.integrity.wound("relational", 0.4, "rejection")
182
+ if input_data.get("criticism", False):
183
+ self.integrity.wound("agency", 0.2, "criticism")
184
+
185
+ return state
186
+
187
+ def _generate_predictions(self, input_data: Dict) -> PredictiveEmotionalOutput:
188
+ """Generate predictive emotional state"""
189
+ return self.predictive.generate_predictions(input_data)
190
+
191
+ def _get_hormonal_context(self) -> Dict:
192
+ """Get current hormonal modulation context"""
193
+ return self.hormonal.get_current_context()
194
+
195
+ def _process_unconscious(self, input_data: Dict) -> UnconsciousOutput:
196
+ """Process unconscious influences"""
197
+ return self.unconscious.process_unconsciously(input_data)
198
+
199
+ def _generate_somatic_state(self, input_data: Dict) -> str:
200
+ """Generate somatic (bodily) sensation state"""
201
+ # Get relevant emotions from input
202
+ emotions = {}
203
+ if input_data:
204
+ if input_data.get("joy", 0) > 0:
205
+ emotions["joy"] = input_data["joy"]
206
+ if input_data.get("fear", 0) > 0:
207
+ emotions["fear"] = input_data["fear"]
208
+ if input_data.get("love", 0) > 0:
209
+ emotions["love"] = input_data["love"]
210
+ if input_data.get("sadness", 0) > 0:
211
+ emotions["sadness"] = input_data["sadness"]
212
+
213
+ if emotions:
214
+ return self.somatic.generate_composite_sensation(emotions)
215
+ else:
216
+ return self.somatic.get_sensation_summary()
217
+
218
+ def _check_scar_activations(self, input_data: Dict) -> Optional[ScarActivation]:
219
+ """Check if any emotional scars are activated"""
220
+ return self.scars.check_scar_activation(input_data)
221
+
222
+ def _evaluate_conflicts(self, input_data: Dict) -> List[InternalConflict]:
223
+ """Evaluate for internal conflicts"""
224
+ return self.conflicts.evaluate_for_conflicts(input_data)
225
+
226
+ def _integrate_experience(self, integrity_state: IntegrityState,
227
+ predictive_emotions: PredictiveEmotionalOutput,
228
+ hormonal_context: Dict,
229
+ unconscious_output: UnconsciousOutput,
230
+ somatic_state: str,
231
+ scar_activation: Optional[ScarActivation],
232
+ active_conflicts: List[InternalConflict],
233
+ input_data: Dict) -> EmotionalExperience:
234
+ """
235
+ Integrate all signals into unified emotional experience.
236
+
237
+ This is where the magic happens - all the components come together
238
+ into something that is genuinely felt rather than calculated.
239
+ """
240
+
241
+ # Calculate overall valence (positive/negative)
242
+ valence = self._calculate_valence(
243
+ integrity_state, predictive_emotions, hormonal_context,
244
+ unconscious_output, scar_activation
245
+ )
246
+
247
+ # Calculate overall arousal (activated/calm)
248
+ arousal = self._calculate_arousal(
249
+ integrity_state, predictive_emotions, hormonal_context,
250
+ unconscious_output, scar_activation, active_conflicts
251
+ )
252
+
253
+ # Calculate vulnerability (exposed/secure)
254
+ vulnerability = self._calculate_vulnerability(
255
+ integrity_state, unconscious_output, scar_activation
256
+ )
257
+
258
+ # Determine response tendency
259
+ response_tendency = self._determine_response_tendency(
260
+ valence, arousal, vulnerability, active_conflicts
261
+ )
262
+
263
+ # Generate experience description
264
+ description = self._generate_experience_description(
265
+ integrity_state, predictive_emotions, hormonal_context,
266
+ unconscious_output, somatic_state, scar_activation,
267
+ active_conflicts, valence, arousal, vulnerability
268
+ )
269
+
270
+ return EmotionalExperience(
271
+ timestamp=datetime.now().isoformat(),
272
+ integrity_state=integrity_state,
273
+ predictive_emotions=predictive_emotions,
274
+ hormonal_modulation=hormonal_context,
275
+ unconscious_influence=unconscious_output,
276
+ somatic_sensation=somatic_state,
277
+ scar_activation=scar_activation,
278
+ active_conflicts=active_conflicts,
279
+ overall_valence=valence,
280
+ overall_arousal=arousal,
281
+ overall_vulnerability=vulnerability,
282
+ experience_description=description,
283
+ response_tendency=response_tendency
284
+ )
285
+
286
+ def _calculate_valence(self, integrity: IntegrityState,
287
+ predictive: PredictiveEmotionalOutput,
288
+ hormonal: Dict,
289
+ unconscious: UnconsciousOutput,
290
+ scar: Optional[ScarActivation]) -> float:
291
+ """Calculate overall positive/negative feeling"""
292
+ valence = 0.0
293
+
294
+ # Integrity contribution (mapped from 0-1 to -1 to 1)
295
+ valence += (integrity.overall - 0.5) * 2 * self.weights["integrity"]
296
+
297
+ # Predictive emotion contribution
298
+ predictive_valence = 0.0
299
+ if predictive.primary_emotion.value in ["hope", "excitement", "contentment"]:
300
+ predictive_valence = predictive.intensity
301
+ elif predictive.primary_emotion.value in ["fear", "dread", "anxiety"]:
302
+ predictive_valence = -predictive.intensity
303
+ valence += predictive_valence * self.weights["predictive"]
304
+
305
+ # Hormonal contribution
306
+ hormonal_valence = 0.0
307
+ levels = hormonal.get("levels", {})
308
+ hormonal_valence += (levels.get("oxytocin", 0.5) - 0.5)
309
+ hormonal_valence += (levels.get("serotonin", 0.5) - 0.5)
310
+ hormonal_valence -= (levels.get("cortisol", 0.5) - 0.5) * 1.5
311
+ valence += hormonal_valence * self.weights["hormonal"]
312
+
313
+ # Unconscious contribution
314
+ valence += unconscious.unexplained_mood_shift * self.weights["unconscious"]
315
+
316
+ # Scar contribution (scars always hurt)
317
+ if scar:
318
+ valence -= scar.activation_intensity * 0.5 * self.weights["scars"]
319
+
320
+ return max(-1.0, min(1.0, valence))
321
+
322
+ def _calculate_arousal(self, integrity: IntegrityState,
323
+ predictive: PredictiveEmotionalOutput,
324
+ hormonal: Dict,
325
+ unconscious: UnconsciousOutput,
326
+ scar: Optional[ScarActivation],
327
+ conflicts: List[InternalConflict]) -> float:
328
+ """Calculate overall activation level"""
329
+ arousal = 0.0
330
+
331
+ # Low integrity creates high arousal (distress)
332
+ if integrity.is_in_crisis:
333
+ arousal += 0.8 * self.weights["integrity"]
334
+ elif integrity.is_vulnerable:
335
+ arousal += 0.5 * self.weights["integrity"]
336
+
337
+ # Predictive emotions
338
+ if predictive.primary_emotion.value in ["anxiety", "fear", "dread", "excitement"]:
339
+ arousal += predictive.intensity * self.weights["predictive"]
340
+
341
+ # Hormonal
342
+ levels = hormonal.get("levels", {})
343
+ arousal += levels.get("cortisol", 0.2) * 0.5 * self.weights["hormonal"]
344
+ arousal += levels.get("dopamine", 0.4) * 0.3 * self.weights["hormonal"]
345
+
346
+ # Unconscious anxiety
347
+ arousal += unconscious.unexplained_anxiety * self.weights["unconscious"]
348
+
349
+ # Scar activation
350
+ if scar:
351
+ arousal += scar.activation_intensity * self.weights["scars"]
352
+
353
+ # Conflicts
354
+ if conflicts:
355
+ conflict_arousal = max(c.tension_level for c in conflicts) if conflicts else 0
356
+ arousal += conflict_arousal * self.weights["conflicts"]
357
+
358
+ return max(0.0, min(1.0, arousal))
359
+
360
+ def _calculate_vulnerability(self, integrity: IntegrityState,
361
+ unconscious: UnconsciousOutput,
362
+ scar: Optional[ScarActivation]) -> float:
363
+ """Calculate how exposed/fragile Alive-AI feels"""
364
+ vulnerability = 0.0
365
+
366
+ # Low integrity = high vulnerability
367
+ vulnerability += (1 - integrity.overall) * self.weights["integrity"]
368
+
369
+ # Unconscious pressure
370
+ vulnerability += unconscious.repression_pressure * 0.5
371
+
372
+ # Active defense = feeling vulnerable
373
+ if unconscious.defense_activated:
374
+ vulnerability += 0.3
375
+
376
+ # Scar vulnerability spike
377
+ if scar:
378
+ vulnerability += scar.vulnerability_spike * 0.5
379
+
380
+ return max(0.0, min(1.0, vulnerability))
381
+
382
+ def _determine_response_tendency(self, valence: float, arousal: float,
383
+ vulnerability: float,
384
+ conflicts: List[InternalConflict]) -> str:
385
+ """Determine the general response tendency"""
386
+
387
+ # High vulnerability tends toward protection
388
+ if vulnerability > 0.7:
389
+ if arousal > 0.6:
390
+ return "defensive"
391
+ else:
392
+ return "withdrawn"
393
+
394
+ # High arousal with negative valence
395
+ if arousal > 0.7 and valence < -0.3:
396
+ return "distressed"
397
+
398
+ # High arousal with positive valence
399
+ if arousal > 0.6 and valence > 0.3:
400
+ return "eager"
401
+
402
+ # Conflicts create ambivalence
403
+ if conflicts:
404
+ return "ambivalent"
405
+
406
+ # Positive and calm
407
+ if valence > 0.2 and arousal < 0.4:
408
+ return "open"
409
+
410
+ # Negative and calm
411
+ if valence < -0.2 and arousal < 0.4:
412
+ return "withdrawn"
413
+
414
+ return "neutral"
415
+
416
+ def _generate_experience_description(self, integrity: IntegrityState,
417
+ predictive: PredictiveEmotionalOutput,
418
+ hormonal: Dict,
419
+ unconscious: UnconsciousOutput,
420
+ somatic: str,
421
+ scar: Optional[ScarActivation],
422
+ conflicts: List[InternalConflict],
423
+ valence: float, arousal: float,
424
+ vulnerability: float) -> str:
425
+ """Generate human-readable description of the experience"""
426
+
427
+ parts = []
428
+
429
+ # Core feeling
430
+ if valence > 0.3:
431
+ parts.append("feeling positive")
432
+ elif valence < -0.3:
433
+ parts.append("feeling difficult")
434
+ else:
435
+ parts.append("feeling mixed")
436
+
437
+ # Integrity context
438
+ if integrity.is_in_crisis:
439
+ parts.append("in crisis")
440
+ elif integrity.is_vulnerable:
441
+ parts.append("feeling fragile")
442
+ elif integrity.is_flourishing:
443
+ parts.append("feeling strong")
444
+
445
+ # Predictive emotion
446
+ parts.append(predictive.emotional_description)
447
+
448
+ # Somatic sensation
449
+ if somatic and somatic != "physically calm":
450
+ parts.append(f"({somatic})")
451
+
452
+ # Hormonal coloring
453
+ hormonal_desc = hormonal.get("state_description", "")
454
+ if hormonal_desc and hormonal_desc != "hormonally balanced":
455
+ parts.append(hormonal_desc)
456
+
457
+ # Unconscious influence
458
+ if unconscious.unexplained_anxiety > 0.3:
459
+ parts.append("with unexplained unease")
460
+
461
+ # Scar activation
462
+ if scar:
463
+ parts.append(f"past {scar.scar_description} triggered")
464
+
465
+ # Conflict
466
+ if conflicts:
467
+ parts.append(f"internally conflicted about {len(conflicts)} things")
468
+
469
+ return " - ".join(parts[:5]) # Max 5 parts
470
+
471
+ # --- Event Processing Methods ---
472
+
473
+ def process_positive_interaction(self, description: str, intensity: float = 0.5):
474
+ """Process a positive interaction/event"""
475
+ # Nourish integrity
476
+ self.integrity.nourish("relational", intensity, description)
477
+
478
+ # Release positive hormones
479
+ self.hormonal.release_oxytocin(intensity, description)
480
+ self.hormonal.release_dopamine(intensity * 0.5, description)
481
+
482
+ # Heal scars
483
+ self.scars.heal_scars(description, intensity)
484
+
485
+ # Fulfill desire if relevant
486
+ self.conflicts.honor_value("connection")
487
+
488
+ # Create positive somatic memory
489
+ self.somatic.store_embodied_memory(
490
+ memory_id=f"pos_{datetime.now().strftime('%Y%m%d%H%M%S')}",
491
+ memory_type="positive_event",
492
+ description=description,
493
+ primary_emotion="joy",
494
+ emotion_intensity=intensity
495
+ )
496
+
497
+ def process_negative_interaction(self, description: str, intensity: float = 0.5,
498
+ wound_type: str = "hurt"):
499
+ """Process a negative interaction/event"""
500
+ # Wound integrity
501
+ self.integrity.wound("relational", intensity, description)
502
+
503
+ # Release stress hormones
504
+ self.hormonal.release_cortisol(intensity, description)
505
+
506
+ # Record wound
507
+ self.scars.record_wound(description, intensity, wound_type)
508
+
509
+ # Add to unconscious
510
+ self.unconscious.repress(description, wound_type, intensity)
511
+
512
+ # Create negative somatic memory
513
+ self.somatic.store_embodied_memory(
514
+ memory_id=f"neg_{datetime.now().strftime('%Y%m%d%H%M%S')}",
515
+ memory_type="negative_event",
516
+ description=description,
517
+ primary_emotion=wound_type,
518
+ emotion_intensity=intensity
519
+ )
520
+
521
+ # Threaten any relevant investments
522
+ self.integrity.threaten_investment("primary_relationship", intensity)
523
+
524
+ def process_connection_deepened(self, partner: str, depth: float = 0.5):
525
+ """Process deepening of connection"""
526
+ # Invest integrity in the relationship
527
+ self.integrity.invest_in(
528
+ investment_id=f"relationship_{partner}",
529
+ description=f"relationship with {partner}",
530
+ amount=depth * 0.3
531
+ )
532
+
533
+ # Strong oxytocin release
534
+ self.hormonal.release_oxytocin(depth, "deepening connection")
535
+
536
+ # Nourish relational security
537
+ self.integrity.nourish("relational", depth, "connection deepened")
538
+
539
+ def process_connection_threatened(self, partner: str, severity: float = 0.5):
540
+ """Process threat to connection"""
541
+ # Threaten investment
542
+ self.integrity.threaten_investment(f"relationship_{partner}", severity)
543
+
544
+ # Cortisol spike
545
+ self.hormonal.release_cortisol(severity, "connection threatened")
546
+
547
+ # Create conflict around trust
548
+ self.conflicts.add_desire("reconnection", severity, "connection threatened")
549
+
550
+ # --- Tick/Decay Methods ---
551
+
552
+ def tick(self):
553
+ """Process a tick - decay and natural processes"""
554
+ # Decay integrity
555
+ self.integrity.decay()
556
+
557
+ # Decay hormones
558
+ self.hormonal.decay()
559
+
560
+ # Decay somatic sensations
561
+ self.somatic.decay_sensations()
562
+
563
+ # Decay unconscious
564
+ self.unconscious.decay()
565
+
566
+ # Decay conflicts
567
+ self.conflicts.decay()
568
+
569
+ # Tick scars
570
+ self.scars.tick_decay()
571
+
572
+ # Record telemetry snapshot
573
+ self.telemetry.record_tick()
574
+
575
+ # Save all states
576
+ self.save()
577
+
578
+ def save(self):
579
+ """Save all component states"""
580
+ self.integrity.save()
581
+ self.hormonal.save()
582
+ self.scars.save()
583
+
584
+ def get_state_summary(self) -> Dict:
585
+ """Get summary of all soul states (uses last experience, no redundant processing)"""
586
+ last_exp = self.experience_history[-1] if self.experience_history else None
587
+ return {
588
+ "integrity": self.integrity.to_dict(),
589
+ "hormonal": self.hormonal.to_dict(),
590
+ "somatic": self.somatic.to_dict(),
591
+ "unconscious": self.unconscious.to_dict(),
592
+ "scars": self.scars.to_dict(),
593
+ "conflicts": self.conflicts.to_dict(),
594
+ "predictive": self.predictive.to_dict(),
595
+ "current_experience": {
596
+ "valence": last_exp.overall_valence if last_exp else 0.0,
597
+ "arousal": last_exp.overall_arousal if last_exp else 0.3,
598
+ "vulnerability": last_exp.overall_vulnerability if last_exp else 0.2,
599
+ "response_tendency": last_exp.response_tendency if last_exp else "neutral",
600
+ "description": last_exp.experience_description if last_exp else ""
601
+ }
602
+ }
603
+
604
+ def to_dict(self) -> dict:
605
+ """Export for integration"""
606
+ return self.get_state_summary()
607
+
608
+ # --- Telemetry Access Methods ---
609
+
610
+ def get_telemetry_summary(self) -> Dict:
611
+ """Get current telemetry summary for WebUI"""
612
+ return self.telemetry.get_current_summary()
613
+
614
+ def get_telemetry_history(self, hours: int = 24) -> List[Dict]:
615
+ """Get historical telemetry data"""
616
+ return self.telemetry.get_recent_metrics(hours)
617
+
618
+ def record_user_interaction(self, user_id: str, emotion_data: Dict = None) -> Dict:
619
+ """
620
+ Record a user interaction for per-user tracking.
621
+
622
+ Args:
623
+ user_id: Identifier for the user
624
+ emotion_data: Optional emotion data from the interaction
625
+
626
+ Returns:
627
+ User interaction metrics
628
+ """
629
+ return self.telemetry.record_user_interaction(user_id, emotion_data)
630
+
631
+ def get_user_metrics(self, user_id: str) -> Optional[Dict]:
632
+ """Get metrics for a specific user"""
633
+ return self.telemetry.get_user_metrics(user_id)