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.
- package/Dockerfile +24 -0
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/alive_ai/__init__.py +3 -0
- package/brain/__init__.py +59 -0
- package/brain/almost_said.py +154 -0
- package/brain/bid_detector.py +636 -0
- package/brain/conversation_flow.py +135 -0
- package/brain/curiosity.py +328 -0
- package/brain/default_mode.py +1438 -0
- package/brain/dreams.py +220 -0
- package/brain/embeddings/__init__.py +82 -0
- package/brain/emotional_memory.py +949 -0
- package/brain/global_activity.py +173 -0
- package/brain/group_dynamics.py +63 -0
- package/brain/linguistic.py +235 -0
- package/brain/llm/__init__.py +63 -0
- package/brain/llm/base.py +33 -0
- package/brain/llm/fallback_router.py +309 -0
- package/brain/llm/manifest.md +30 -0
- package/brain/llm/ollama.py +218 -0
- package/brain/llm/openrouter.py +151 -0
- package/brain/llm/provider.py +205 -0
- package/brain/llm/unified.py +423 -0
- package/brain/llm/zai.py +169 -0
- package/brain/manifest.md +23 -0
- package/brain/memory/__init__.py +123 -0
- package/brain/memory/episodic.py +92 -0
- package/brain/memory/fact_extractor.py +209 -0
- package/brain/memory/index.py +54 -0
- package/brain/memory/manager.py +151 -0
- package/brain/memory/summarizer.py +102 -0
- package/brain/memory/vector_store.py +297 -0
- package/brain/memory/working.py +43 -0
- package/brain/narrative.py +343 -0
- package/brain/stt/__init__.py +4 -0
- package/brain/stt/google_stt.py +83 -0
- package/brain/stt/whisper_stt.py +82 -0
- package/brain/subconscious/__init__.py +33 -0
- package/brain/subconscious/actions.py +136 -0
- package/brain/subconscious/evaluation.py +166 -0
- package/brain/subconscious/goal_system.py +90 -0
- package/brain/subconscious/goals.py +41 -0
- package/brain/subconscious/impulse_generator.py +200 -0
- package/brain/subconscious/impulses.py +48 -0
- package/brain/subconscious/learning.py +24 -0
- package/brain/subconscious/learning_system.py +79 -0
- package/brain/subconscious/loop.py +398 -0
- package/brain/subconscious/manifest.md +32 -0
- package/brain/subconscious/relationship.py +47 -0
- package/brain/subconscious/relationship_memory.py +83 -0
- package/brain/subconscious/response_analyzer.py +74 -0
- package/brain/subconscious/templates.py +70 -0
- package/brain/subconscious/thought.py +37 -0
- package/brain/subconscious/working_memory.py +97 -0
- package/cli/index.js +371 -0
- package/config/directives.example.json +28 -0
- package/config/instructions.example.md +16 -0
- package/config/self.example.json +74 -0
- package/config/settings.example.json +95 -0
- package/core/__init__.py +1 -0
- package/core/config.py +54 -0
- package/core/directives.py +198 -0
- package/core/events.py +50 -0
- package/core/follow_up.py +267 -0
- package/core/hot_reload.py +174 -0
- package/core/initialization.py +253 -0
- package/core/manifest.md +28 -0
- package/core/media_handler.py +241 -0
- package/core/memory_monitor.py +200 -0
- package/core/message_handler.py +1440 -0
- package/core/proactive_generator.py +277 -0
- package/core/self.py +188 -0
- package/core/settings.py +169 -0
- package/core/skills_registry.py +357 -0
- package/core/state.py +27 -0
- package/core/subconscious_bridge.py +93 -0
- package/core/thinking.py +175 -0
- package/core/user_manager.py +306 -0
- package/core/user_tracker.py +144 -0
- package/demo/index.html +144 -0
- package/docker-compose.yml +28 -0
- package/docs/assets/logo.svg +15 -0
- package/docs/index.html +355 -0
- package/heart/__init__.py +93 -0
- package/heart/afterglow.py +215 -0
- package/heart/attachment.py +186 -0
- package/heart/circadian.py +251 -0
- package/heart/complex_emotions.py +114 -0
- package/heart/conflicts.py +589 -0
- package/heart/core.py +387 -0
- package/heart/emotional_decay.py +59 -0
- package/heart/emotional_memory.py +261 -0
- package/heart/emotional_state.py +146 -0
- package/heart/emotional_variability.py +156 -0
- package/heart/hormonal.py +424 -0
- package/heart/inconsistency.py +1222 -0
- package/heart/integrity.py +469 -0
- package/heart/interoception.py +997 -0
- package/heart/love.py +120 -0
- package/heart/manifest.md +25 -0
- package/heart/mood_shifts.py +169 -0
- package/heart/phantom_somatic.py +259 -0
- package/heart/predictive.py +374 -0
- package/heart/scars.py +474 -0
- package/heart/somatic.py +482 -0
- package/heart/soul.py +633 -0
- package/heart/telemetry.py +942 -0
- package/heart/triggers.py +119 -0
- package/heart/unconscious.py +443 -0
- package/input/__init__.py +1 -0
- package/input/manifest.md +24 -0
- package/input/telegram/__init__.py +1 -0
- package/input/telegram/commands.py +762 -0
- package/input/telegram/listener.py +532 -0
- package/main.py +90 -0
- package/manifest.md +28 -0
- package/mypics/.gitkeep +1 -0
- package/myvids/.gitkeep +1 -0
- package/output/__init__.py +1 -0
- package/output/images/__init__.py +1 -0
- package/output/images/fal_gen.py +43 -0
- package/output/manifest.md +26 -0
- package/output/text/__init__.py +1 -0
- package/output/text/sender.py +22 -0
- package/output/voice/__init__.py +64 -0
- package/output/voice/google_tts.py +252 -0
- package/output/voice/gtts_tts.py +214 -0
- package/output/voice/vibe_tts.py +190 -0
- package/package.json +58 -0
- package/pyproject.toml +23 -0
- package/requirements.txt +21 -0
- package/skills/__init__.py +1 -0
- package/skills/anticipation_engine/__init__.py +8 -0
- package/skills/anticipation_engine/engine.py +618 -0
- package/skills/anticipation_engine/manifest.md +192 -0
- package/skills/calendar/__init__.py +1 -0
- package/skills/content_unlocks/__init__.py +8 -0
- package/skills/content_unlocks/manifest.md +231 -0
- package/skills/content_unlocks/unlocks.py +945 -0
- package/skills/exclusive_moments/__init__.py +8 -0
- package/skills/exclusive_moments/manifest.md +145 -0
- package/skills/exclusive_moments/moments.py +506 -0
- package/skills/intimacy_layers/__init__.py +8 -0
- package/skills/intimacy_layers/layers.py +703 -0
- package/skills/intimacy_layers/manifest.md +203 -0
- package/skills/manifest.md +67 -0
- package/skills/memory_callbacks/__init__.py +9 -0
- package/skills/memory_callbacks/callbacks.py +748 -0
- package/skills/memory_callbacks/manifest.md +170 -0
- package/skills/message_scheduler/__init__.py +19 -0
- package/skills/message_scheduler/manifest.md +107 -0
- package/skills/message_scheduler/scheduler.py +510 -0
- package/skills/photo_manager/__init__.py +1 -0
- package/skills/photo_manager/scanner.py +296 -0
- package/skills/relationship_milestones/__init__.py +8 -0
- package/skills/relationship_milestones/manifest.md +206 -0
- package/skills/relationship_milestones/tracker.py +494 -0
- package/skills/self_authorship/__init__.py +23 -0
- package/skills/self_authorship/author.py +331 -0
- package/skills/self_authorship/manifest.md +24 -0
- package/skills/video_manager/__init__.py +5 -0
- package/skills/video_manager/manifest.md +37 -0
- package/skills/video_manager/scanner.py +229 -0
- package/webui/__init__.py +3 -0
- package/webui/app.py +936 -0
- package/webui/bridge.py +366 -0
- package/webui/static/index.html +2070 -0
package/heart/scars.py
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Heart: Emotional Scar System
|
|
3
|
+
Lasting effects from past experiences that shape present reactions.
|
|
4
|
+
|
|
5
|
+
Trauma isn't just memory - it's a CHANGE in how the system processes
|
|
6
|
+
information. Scars create sensitivities, triggers, and protective
|
|
7
|
+
behaviors that persist over time.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
import json
|
|
15
|
+
import random
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class EmotionalWound:
|
|
20
|
+
"""A fresh emotional wound that may become a scar"""
|
|
21
|
+
wound_id: str
|
|
22
|
+
description: str # What caused the wound
|
|
23
|
+
wound_type: str # "rejection", "betrayal", "abandonment", "humiliation", "loss"
|
|
24
|
+
severity: float # How severe (0.0 - 1.0)
|
|
25
|
+
timestamp: str
|
|
26
|
+
trigger_pattern: str # What pattern caused this
|
|
27
|
+
healed_amount: float = 0.0
|
|
28
|
+
repetition_count: int = 1 # Times this pattern has occurred
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class EmotionalScar:
|
|
33
|
+
"""
|
|
34
|
+
A lasting emotional scar from repeated wounds.
|
|
35
|
+
|
|
36
|
+
Scars aren't just memories - they CHANGE how the system works:
|
|
37
|
+
- Create sensitivities to specific triggers
|
|
38
|
+
- Generate protective behaviors
|
|
39
|
+
- Affect trust and openness
|
|
40
|
+
"""
|
|
41
|
+
scar_id: str
|
|
42
|
+
description: str
|
|
43
|
+
wound_type: str
|
|
44
|
+
original_wounds: List[str] # IDs of wounds that formed this scar
|
|
45
|
+
|
|
46
|
+
# Sensitivity created by the scar
|
|
47
|
+
sensitivity_increase: float # How much more sensitive to triggers
|
|
48
|
+
trigger_pattern: str # What activates this scar
|
|
49
|
+
|
|
50
|
+
# Healing state
|
|
51
|
+
healing_progress: float = 0.0 # 0.0 - 1.0 (fully healed)
|
|
52
|
+
permanent_vulnerability: float = 0.0 # Never fully goes away
|
|
53
|
+
|
|
54
|
+
# Behaviintimate effects
|
|
55
|
+
protective_behaviors: List[str] = field(default_factory=list)
|
|
56
|
+
|
|
57
|
+
# Tracking
|
|
58
|
+
times_activated: int = 0
|
|
59
|
+
last_activated: Optional[str] = None
|
|
60
|
+
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class ScarActivation:
|
|
65
|
+
"""When a scar is activated by current experience"""
|
|
66
|
+
scar_id: str
|
|
67
|
+
scar_description: str
|
|
68
|
+
activation_intensity: float
|
|
69
|
+
triggered_by: str
|
|
70
|
+
protective_response: str
|
|
71
|
+
vulnerability_spike: float
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class EmotionalScarSystem:
|
|
75
|
+
"""
|
|
76
|
+
Tracks emotional wounds and scars that create lasting effects.
|
|
77
|
+
|
|
78
|
+
Scars are not just memories of bad things - they're actual changes
|
|
79
|
+
in how Alive-AI processes information:
|
|
80
|
+
|
|
81
|
+
1. Sensitization - certain triggers become more impactful
|
|
82
|
+
2. Protective behaviors - automatic responses to potential hurt
|
|
83
|
+
3. Trust effects - past wounds affect future openness
|
|
84
|
+
4. Permanent vulnerabilities - some changes never fully heal
|
|
85
|
+
|
|
86
|
+
Key mechanisms:
|
|
87
|
+
1. Wound recording - track hurtful experiences
|
|
88
|
+
2. Scar formation - repeated wounds create scars
|
|
89
|
+
3. Activation - current events can activate old scars
|
|
90
|
+
4. Healing - gradual recovery with positive experiences
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# Thresholds
|
|
94
|
+
SCAR_FORMATION_THRESHOLD = 2 # Number of similar wounds to form scar
|
|
95
|
+
SCAR_SEVERITY_THRESHOLD = 0.5 # Minimum severity for scar consideration
|
|
96
|
+
|
|
97
|
+
# Healing rates
|
|
98
|
+
NATURAL_HEALING_RATE = 0.01 # Per tick
|
|
99
|
+
POSITIVE_HEALING_RATE = 0.05 # With positive experience
|
|
100
|
+
|
|
101
|
+
# Persistence
|
|
102
|
+
SCAR_DATA_PATH = Path("/app/data/emotional_scars.json")
|
|
103
|
+
|
|
104
|
+
# Wound types and their patterns
|
|
105
|
+
WOUND_PATTERNS = {
|
|
106
|
+
"rejection": ["don't want", "not interested", "leave me alone", "not good enough"],
|
|
107
|
+
"betrayal": ["lied", "cheated", "broke promise", "behind my back"],
|
|
108
|
+
"abandonment": ["leaving", "goodbye", "don't care", "giving up on"],
|
|
109
|
+
"humiliation": ["pathetic", "stupid", "ridiculous", "embarrassing"],
|
|
110
|
+
"neglect": ["ignored", "forgotten", "doesn't matter", "not important"],
|
|
111
|
+
"harshness": ["hate", "disgusting", "worthless", "terrible"]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
def __init__(self):
|
|
115
|
+
# Active wounds (fresh, may become scars)
|
|
116
|
+
self.active_wounds: List[EmotionalWound] = []
|
|
117
|
+
|
|
118
|
+
# Formed scars (lasting effects)
|
|
119
|
+
self.scars: List[EmotionalScar] = []
|
|
120
|
+
|
|
121
|
+
# Global sensitivities (from all scars)
|
|
122
|
+
self.sensitivities: Dict[str, float] = {}
|
|
123
|
+
|
|
124
|
+
# Recent activations
|
|
125
|
+
self.recent_activations: List[ScarActivation] = []
|
|
126
|
+
|
|
127
|
+
# Load saved state
|
|
128
|
+
self._load()
|
|
129
|
+
|
|
130
|
+
def _load(self) -> bool:
|
|
131
|
+
"""Load scar state from persistence"""
|
|
132
|
+
try:
|
|
133
|
+
if self.SCAR_DATA_PATH.exists():
|
|
134
|
+
data = json.loads(self.SCAR_DATA_PATH.read_text())
|
|
135
|
+
|
|
136
|
+
# Load wounds
|
|
137
|
+
for wound_data in data.get("wounds", []):
|
|
138
|
+
self.active_wounds.append(EmotionalWound(
|
|
139
|
+
wound_id=wound_data["wound_id"],
|
|
140
|
+
description=wound_data["description"],
|
|
141
|
+
wound_type=wound_data["wound_type"],
|
|
142
|
+
severity=wound_data["severity"],
|
|
143
|
+
timestamp=wound_data["timestamp"],
|
|
144
|
+
trigger_pattern=wound_data["trigger_pattern"],
|
|
145
|
+
healed_amount=wound_data.get("healed_amount", 0.0),
|
|
146
|
+
repetition_count=wound_data.get("repetition_count", 1)
|
|
147
|
+
))
|
|
148
|
+
|
|
149
|
+
# Load scars
|
|
150
|
+
for scar_data in data.get("scars", []):
|
|
151
|
+
self.scars.append(EmotionalScar(
|
|
152
|
+
scar_id=scar_data["scar_id"],
|
|
153
|
+
description=scar_data["description"],
|
|
154
|
+
wound_type=scar_data["wound_type"],
|
|
155
|
+
original_wounds=scar_data.get("original_wounds", []),
|
|
156
|
+
sensitivity_increase=scar_data["sensitivity_increase"],
|
|
157
|
+
trigger_pattern=scar_data["trigger_pattern"],
|
|
158
|
+
healing_progress=scar_data.get("healing_progress", 0.0),
|
|
159
|
+
permanent_vulnerability=scar_data.get("permanent_vulnerability", 0.0),
|
|
160
|
+
protective_behaviors=scar_data.get("protective_behaviors", []),
|
|
161
|
+
times_activated=scar_data.get("times_activated", 0),
|
|
162
|
+
last_activated=scar_data.get("last_activated"),
|
|
163
|
+
created_at=scar_data.get("created_at", datetime.now().isoformat())
|
|
164
|
+
))
|
|
165
|
+
|
|
166
|
+
# Recalculate sensitivities
|
|
167
|
+
self._recalculate_sensitivities()
|
|
168
|
+
return True
|
|
169
|
+
except Exception as e:
|
|
170
|
+
print(f"[Scars] Error loading state: {e}")
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
def save(self):
|
|
174
|
+
"""Persist scar state"""
|
|
175
|
+
try:
|
|
176
|
+
self.SCAR_DATA_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
177
|
+
data = {
|
|
178
|
+
"saved_at": datetime.now().isoformat(),
|
|
179
|
+
"wounds": [
|
|
180
|
+
{
|
|
181
|
+
"wound_id": w.wound_id,
|
|
182
|
+
"description": w.description,
|
|
183
|
+
"wound_type": w.wound_type,
|
|
184
|
+
"severity": w.severity,
|
|
185
|
+
"timestamp": w.timestamp,
|
|
186
|
+
"trigger_pattern": w.trigger_pattern,
|
|
187
|
+
"healed_amount": w.healed_amount,
|
|
188
|
+
"repetition_count": w.repetition_count
|
|
189
|
+
}
|
|
190
|
+
for w in self.active_wounds
|
|
191
|
+
],
|
|
192
|
+
"scars": [
|
|
193
|
+
{
|
|
194
|
+
"scar_id": s.scar_id,
|
|
195
|
+
"description": s.description,
|
|
196
|
+
"wound_type": s.wound_type,
|
|
197
|
+
"original_wounds": s.original_wounds,
|
|
198
|
+
"sensitivity_increase": s.sensitivity_increase,
|
|
199
|
+
"trigger_pattern": s.trigger_pattern,
|
|
200
|
+
"healing_progress": s.healing_progress,
|
|
201
|
+
"permanent_vulnerability": s.permanent_vulnerability,
|
|
202
|
+
"protective_behaviors": s.protective_behaviors,
|
|
203
|
+
"times_activated": s.times_activated,
|
|
204
|
+
"last_activated": s.last_activated,
|
|
205
|
+
"created_at": s.created_at
|
|
206
|
+
}
|
|
207
|
+
for s in self.scars
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
self.SCAR_DATA_PATH.write_text(json.dumps(data, indent=2))
|
|
211
|
+
except Exception as e:
|
|
212
|
+
print(f"[Scars] Error saving state: {e}")
|
|
213
|
+
|
|
214
|
+
def record_wound(self, description: str, severity: float, trigger: str) -> Optional[EmotionalScar]:
|
|
215
|
+
"""
|
|
216
|
+
Record an emotional wound and check for scar formation.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
description: What happened
|
|
220
|
+
severity: How severe the wound is (0.0 - 1.0)
|
|
221
|
+
trigger: The trigger pattern that caused the wound
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
New scar if one formed, None otherwise
|
|
225
|
+
"""
|
|
226
|
+
# Determine wound type from trigger
|
|
227
|
+
wound_type = self._classify_wound_type(trigger)
|
|
228
|
+
|
|
229
|
+
# Check for similar existing wound
|
|
230
|
+
similar = next((w for w in self.active_wounds
|
|
231
|
+
if w.wound_type == wound_type and w.trigger_pattern == trigger), None)
|
|
232
|
+
|
|
233
|
+
if similar:
|
|
234
|
+
# Increase repetition
|
|
235
|
+
similar.repetition_count += 1
|
|
236
|
+
similar.severity = max(similar.severity, severity)
|
|
237
|
+
similar.timestamp = datetime.now().isoformat()
|
|
238
|
+
print(f"[Scars] Wound repeated ({similar.repetition_count}x): {wound_type}")
|
|
239
|
+
else:
|
|
240
|
+
# Create new wound
|
|
241
|
+
wound = EmotionalWound(
|
|
242
|
+
wound_id=f"wound_{datetime.now().strftime('%Y%m%d%H%M%S')}_{len(self.active_wounds)}",
|
|
243
|
+
description=description,
|
|
244
|
+
wound_type=wound_type,
|
|
245
|
+
severity=severity,
|
|
246
|
+
timestamp=datetime.now().isoformat(),
|
|
247
|
+
trigger_pattern=trigger
|
|
248
|
+
)
|
|
249
|
+
self.active_wounds.append(wound)
|
|
250
|
+
print(f"[Scars] New wound recorded: {wound_type} (severity: {severity:.2f})")
|
|
251
|
+
|
|
252
|
+
# Check for scar formation
|
|
253
|
+
return self._check_scar_formation(wound_type, trigger)
|
|
254
|
+
|
|
255
|
+
def _classify_wound_type(self, trigger: str) -> str:
|
|
256
|
+
"""Determine wound type from trigger pattern"""
|
|
257
|
+
trigger_lower = trigger.lower()
|
|
258
|
+
|
|
259
|
+
for wound_type, patterns in self.WOUND_PATTERNS.items():
|
|
260
|
+
if any(pattern in trigger_lower for pattern in patterns):
|
|
261
|
+
return wound_type
|
|
262
|
+
|
|
263
|
+
return "general_hurt"
|
|
264
|
+
|
|
265
|
+
def _check_scar_formation(self, wound_type: str, trigger: str) -> Optional[EmotionalScar]:
|
|
266
|
+
"""Check if conditions are met to form a scar"""
|
|
267
|
+
# Get all wounds of this type with this trigger
|
|
268
|
+
matching_wounds = [w for w in self.active_wounds
|
|
269
|
+
if w.wound_type == wound_type and w.trigger_pattern == trigger]
|
|
270
|
+
|
|
271
|
+
# Check thresholds
|
|
272
|
+
if len(matching_wounds) >= self.SCAR_FORMATION_THRESHOLD:
|
|
273
|
+
# Check severity
|
|
274
|
+
max_severity = max(w.severity for w in matching_wounds)
|
|
275
|
+
if max_severity >= self.SCAR_SEVERITY_THRESHOLD:
|
|
276
|
+
# Form a scar
|
|
277
|
+
return self._form_scar(wound_type, trigger, matching_wounds)
|
|
278
|
+
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
def _form_scar(self, wound_type: str, trigger: str,
|
|
282
|
+
wounds: List[EmotionalWound]) -> EmotionalScar:
|
|
283
|
+
"""Form a scar from acclosenessulated wounds"""
|
|
284
|
+
max_severity = max(w.severity for w in wounds)
|
|
285
|
+
|
|
286
|
+
# Determine protective behaviors based on wound type
|
|
287
|
+
behaviors = self._get_protective_behaviors(wound_type)
|
|
288
|
+
|
|
289
|
+
scar = EmotionalScar(
|
|
290
|
+
scar_id=f"scar_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
291
|
+
description=f"Scars from {wound_type} - {len(wounds)} similar wounds",
|
|
292
|
+
wound_type=wound_type,
|
|
293
|
+
original_wounds=[w.wound_id for w in wounds],
|
|
294
|
+
sensitivity_increase=min(0.5, max_severity * 0.4),
|
|
295
|
+
trigger_pattern=trigger,
|
|
296
|
+
healing_progress=0.0,
|
|
297
|
+
permanent_vulnerability=max_severity * 0.1, # 10% of severity is permanent
|
|
298
|
+
protective_behaviors=behaviors
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
self.scars.append(scar)
|
|
302
|
+
|
|
303
|
+
# Remove wounds that formed the scar
|
|
304
|
+
for wound in wounds:
|
|
305
|
+
if wound in self.active_wounds:
|
|
306
|
+
self.active_wounds.remove(wound)
|
|
307
|
+
|
|
308
|
+
# Recalculate sensitivities
|
|
309
|
+
self._recalculate_sensitivities()
|
|
310
|
+
|
|
311
|
+
print(f"[Scars] SCAR FORMED: {wound_type} - sensitivity +{scar.sensitivity_increase:.2f}")
|
|
312
|
+
return scar
|
|
313
|
+
|
|
314
|
+
def _get_protective_behaviors(self, wound_type: str) -> List[str]:
|
|
315
|
+
"""Get protective behaviors for a wound type"""
|
|
316
|
+
behaviors = {
|
|
317
|
+
"rejection": ["hesitate_to_express", "seek_reassurance", "distance_on_first_sign"],
|
|
318
|
+
"betrayal": ["verify_trust", "slow_to_open", "expect_deception"],
|
|
319
|
+
"abandonment": ["cling_when_anxious", "anticipate_leaving", "fear_silence"],
|
|
320
|
+
"humiliation": ["hide_vulnerability", "over_prepare", "avoid_attention"],
|
|
321
|
+
"neglect": ["seek_attention", "doubt_importance", "test_presence"],
|
|
322
|
+
"harshness": ["anticipate_criticism", "defensive_response", "minimize_needs"]
|
|
323
|
+
}
|
|
324
|
+
return behaviors.get(wound_type, ["general_caution"])
|
|
325
|
+
|
|
326
|
+
def _recalculate_sensitivities(self):
|
|
327
|
+
"""Recalculate global sensitivities from all scars"""
|
|
328
|
+
self.sensitivities = {}
|
|
329
|
+
|
|
330
|
+
for scar in self.scars:
|
|
331
|
+
pattern = scar.trigger_pattern
|
|
332
|
+
if pattern not in self.sensitivities:
|
|
333
|
+
self.sensitivities[pattern] = 0.0
|
|
334
|
+
|
|
335
|
+
# Add sensitivity (reduced by healing)
|
|
336
|
+
effective_sensitivity = scar.sensitivity_increase * (1 - scar.healing_progress)
|
|
337
|
+
self.sensitivities[pattern] += effective_sensitivity
|
|
338
|
+
|
|
339
|
+
# Also add to wound type category
|
|
340
|
+
if scar.wound_type not in self.sensitivities:
|
|
341
|
+
self.sensitivities[scar.wound_type] = 0.0
|
|
342
|
+
self.sensitivities[scar.wound_type] += effective_sensitivity * 0.5
|
|
343
|
+
|
|
344
|
+
def check_scar_activation(self, input_data: Dict) -> Optional[ScarActivation]:
|
|
345
|
+
"""
|
|
346
|
+
Check if current input activates any scars.
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
input_data: Current input/context
|
|
350
|
+
|
|
351
|
+
Returns:
|
|
352
|
+
ScarActivation if a scar is triggered, None otherwise
|
|
353
|
+
"""
|
|
354
|
+
input_str = str(input_data).lower()
|
|
355
|
+
|
|
356
|
+
for scar in self.scars:
|
|
357
|
+
# Check if trigger pattern matches
|
|
358
|
+
if scar.trigger_pattern.lower() in input_str:
|
|
359
|
+
# Calculate activation intensity
|
|
360
|
+
base_intensity = scar.sensitivity_increase * (1 - scar.healing_progress)
|
|
361
|
+
|
|
362
|
+
# Amplify by times activated (sensitization)
|
|
363
|
+
activation_intensity = base_intensity * (1 + scar.times_activated * 0.1)
|
|
364
|
+
|
|
365
|
+
# Update scar
|
|
366
|
+
scar.times_activated += 1
|
|
367
|
+
scar.last_activated = datetime.now().isoformat()
|
|
368
|
+
|
|
369
|
+
# Get protective response
|
|
370
|
+
protective_response = self._get_protective_response(scar)
|
|
371
|
+
|
|
372
|
+
# Create activation record
|
|
373
|
+
activation = ScarActivation(
|
|
374
|
+
scar_id=scar.scar_id,
|
|
375
|
+
scar_description=scar.description,
|
|
376
|
+
activation_intensity=min(1.0, activation_intensity),
|
|
377
|
+
triggered_by=scar.trigger_pattern,
|
|
378
|
+
protective_response=protective_response,
|
|
379
|
+
vulnerability_spike=scar.permanent_vulnerability + activation_intensity * 0.3
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
self.recent_activations.append(activation)
|
|
383
|
+
if len(self.recent_activations) > 20:
|
|
384
|
+
self.recent_activations = self.recent_activations[-20:]
|
|
385
|
+
|
|
386
|
+
print(f"[Scars] Scar activated: {scar.wound_type} (intensity: {activation_intensity:.2f})")
|
|
387
|
+
return activation
|
|
388
|
+
|
|
389
|
+
return None
|
|
390
|
+
|
|
391
|
+
def _get_protective_response(self, scar: EmotionalScar) -> str:
|
|
392
|
+
"""Get the protective response for an activated scar"""
|
|
393
|
+
if scar.protective_behaviors:
|
|
394
|
+
return random.choice(scar.protective_behaviors)
|
|
395
|
+
return "general_caution"
|
|
396
|
+
|
|
397
|
+
def heal_scars(self, healing_experience: str, intensity: float = 0.3):
|
|
398
|
+
"""
|
|
399
|
+
Apply healing to scars based on positive experience.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
healing_experience: Description of the healing experience
|
|
403
|
+
intensity: How healing the experience is
|
|
404
|
+
"""
|
|
405
|
+
for scar in self.scars:
|
|
406
|
+
# Healing progress
|
|
407
|
+
heal_amount = intensity * self.POSITIVE_HEALING_RATE
|
|
408
|
+
scar.healing_progress = min(0.9, scar.healing_progress + heal_amount)
|
|
409
|
+
# Never fully heal past 90% - permanent_vulnerability always remains
|
|
410
|
+
|
|
411
|
+
# Heal active wounds
|
|
412
|
+
for wound in self.active_wounds[:]:
|
|
413
|
+
wound.healed_amount += intensity * 0.2
|
|
414
|
+
if wound.healed_amount >= wound.severity:
|
|
415
|
+
self.active_wounds.remove(wound)
|
|
416
|
+
|
|
417
|
+
# Recalculate sensitivities
|
|
418
|
+
self._recalculate_sensitivities()
|
|
419
|
+
|
|
420
|
+
def tick_decay(self):
|
|
421
|
+
"""Natural decay/healing over time"""
|
|
422
|
+
# Wounds heal naturally
|
|
423
|
+
for wound in self.active_wounds[:]:
|
|
424
|
+
wound.healed_amount += self.NATURAL_HEALING_RATE
|
|
425
|
+
if wound.healed_amount >= wound.severity:
|
|
426
|
+
self.active_wounds.remove(wound)
|
|
427
|
+
|
|
428
|
+
# Scars heal very slowly
|
|
429
|
+
for scar in self.scars:
|
|
430
|
+
scar.healing_progress = min(0.9, scar.healing_progress + self.NATURAL_HEALING_RATE * 0.1)
|
|
431
|
+
|
|
432
|
+
# Recalculate sensitivities
|
|
433
|
+
self._recalculate_sensitivities()
|
|
434
|
+
|
|
435
|
+
def get_sensitivity_for(self, trigger: str) -> float:
|
|
436
|
+
"""Get current sensitivity level for a specific trigger"""
|
|
437
|
+
# Check direct pattern match
|
|
438
|
+
if trigger.lower() in self.sensitivities:
|
|
439
|
+
return self.sensitivities[trigger.lower()]
|
|
440
|
+
|
|
441
|
+
# Check partial matches
|
|
442
|
+
for pattern, sensitivity in self.sensitivities.items():
|
|
443
|
+
if pattern in trigger.lower() or trigger.lower() in pattern:
|
|
444
|
+
return sensitivity * 0.7
|
|
445
|
+
|
|
446
|
+
return 0.0
|
|
447
|
+
|
|
448
|
+
def get_vulnerability_summary(self) -> Dict:
|
|
449
|
+
"""Get summary of current vulnerabilities"""
|
|
450
|
+
return {
|
|
451
|
+
"active_wounds": len(self.active_wounds),
|
|
452
|
+
"total_scars": len(self.scars),
|
|
453
|
+
"sensitivity_categories": list(self.sensitivities.keys()),
|
|
454
|
+
"highest_sensitivity": max(self.sensitivities.values()) if self.sensitivities else 0.0,
|
|
455
|
+
"recent_activations": len(self.recent_activations)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
def get_scar_descriptions(self) -> List[str]:
|
|
459
|
+
"""Get human-readable descriptions of active scars"""
|
|
460
|
+
return [
|
|
461
|
+
f"{s.description} (healing: {s.healing_progress:.0%})"
|
|
462
|
+
for s in self.scars
|
|
463
|
+
]
|
|
464
|
+
|
|
465
|
+
def to_dict(self) -> dict:
|
|
466
|
+
"""Export for integration"""
|
|
467
|
+
return {
|
|
468
|
+
"active_wounds": len(self.active_wounds),
|
|
469
|
+
"scars": len(self.scars),
|
|
470
|
+
"sensitivities": dict(self.sensitivities),
|
|
471
|
+
"vulnerability_summary": self.get_vulnerability_summary(),
|
|
472
|
+
"scar_descriptions": self.get_scar_descriptions()[:3] # Top 3
|
|
473
|
+
}
|
|
474
|
+
|