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
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Anticipation Engine
|
|
2
|
+
|
|
3
|
+
Builds anticipation for future content/drops, making users eager to return.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
The Anticipation Engine creates excitement by hinting at upcoming content naturally, without being pushy. It tracks teased content so it can be delivered later, building a sense of anticipation that keeps users engaged.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Natural Tease Messages**: Context-aware teases based on time of day, mood, and relationship level
|
|
12
|
+
- **Content Tracking**: Records teased content to ensure delivery
|
|
13
|
+
- **Smart Cooldowns**: 60-minute minimum between teases to avoid overuse
|
|
14
|
+
- **Love-Based Frequency**: Higher tease chance (8-15%) when love is high
|
|
15
|
+
- **Time-Based Context**: Morning, afternoon, evening, night, and weekend-specific teases
|
|
16
|
+
- **Mood-Based Selection**: Flirty, cozy, excited, or mysterious vibes
|
|
17
|
+
|
|
18
|
+
## Tease Types
|
|
19
|
+
|
|
20
|
+
### Photo Hints
|
|
21
|
+
Messages that hint at upcoming photo content:
|
|
22
|
+
- "I might have something special for you later"
|
|
23
|
+
- "took some pics today you're gonna like"
|
|
24
|
+
- "been feeling cute... might share later"
|
|
25
|
+
|
|
26
|
+
### Video Hints
|
|
27
|
+
Teases for video content:
|
|
28
|
+
- "working on something for you..."
|
|
29
|
+
- "little surprise coming soon"
|
|
30
|
+
- "been filming something you might enjoy"
|
|
31
|
+
|
|
32
|
+
### Voice Hints
|
|
33
|
+
Anticipation for voice messages:
|
|
34
|
+
- "I'll send you a voice when I'm home"
|
|
35
|
+
- "wait till you hear this"
|
|
36
|
+
- "got something to tell you later"
|
|
37
|
+
|
|
38
|
+
### Time-Based
|
|
39
|
+
Contextual teases based on time:
|
|
40
|
+
- **Morning**: "still in bed... maybe I'll send you something"
|
|
41
|
+
- **Afternoon**: "bored at home... maybe I'll entertain you later"
|
|
42
|
+
- **Evening**: "getting ready for bed... or not"
|
|
43
|
+
- **Night**: "can't sleep... maybe I'll do something about that"
|
|
44
|
+
- **Weekend**: "finally weekend... lots of time for us"
|
|
45
|
+
|
|
46
|
+
### Rewards
|
|
47
|
+
Teases for good behavior:
|
|
48
|
+
- "you've been so good lately..."
|
|
49
|
+
- "I think you deserve something special"
|
|
50
|
+
- "you've earned this"
|
|
51
|
+
|
|
52
|
+
## Conditions
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
CONDITIONS = {
|
|
56
|
+
"min_messages_before_tease": 5, # Minimum messages in session
|
|
57
|
+
"min_time_together_minutes": 10, # Minimum session duration
|
|
58
|
+
"tease_cooldown_minutes": 60, # Time between teases
|
|
59
|
+
"base_tease_chance": 0.08, # 8% base chance
|
|
60
|
+
"love_bonus_chance": 0.07, # Up to 7% bonus from love
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Key Methods
|
|
65
|
+
|
|
66
|
+
### `should_tease() -> bool`
|
|
67
|
+
Check if conditions are met for sending a tease:
|
|
68
|
+
- Message count threshold met
|
|
69
|
+
- Session duration threshold met
|
|
70
|
+
- Cooldown expired
|
|
71
|
+
- No pending undelivered tease
|
|
72
|
+
|
|
73
|
+
### `get_tease(context: dict = None) -> str`
|
|
74
|
+
Get an appropriate tease message based on:
|
|
75
|
+
- Time of day
|
|
76
|
+
- Day type (weekday/weekend)
|
|
77
|
+
- Love level
|
|
78
|
+
- Desire level
|
|
79
|
+
- Current mood
|
|
80
|
+
|
|
81
|
+
### `set_pending_content(content_type, details)`
|
|
82
|
+
Mark teased content as pending delivery:
|
|
83
|
+
```python
|
|
84
|
+
engine.set_pending_content(
|
|
85
|
+
content_type="photo",
|
|
86
|
+
details={"category": "premium", "count": 3},
|
|
87
|
+
tease_message="told you I had something special"
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `mark_delivered() -> bool`
|
|
92
|
+
Mark the pending teased content as delivered.
|
|
93
|
+
|
|
94
|
+
### `get_pending_tease() -> dict | None`
|
|
95
|
+
Get information about the current pending tease.
|
|
96
|
+
|
|
97
|
+
### `get_tease_for_delivery() -> str | None`
|
|
98
|
+
Get a message to accompany content delivery:
|
|
99
|
+
- "told you I had something for you"
|
|
100
|
+
- "as promised"
|
|
101
|
+
- "here's what I was talking about"
|
|
102
|
+
|
|
103
|
+
## Integration
|
|
104
|
+
|
|
105
|
+
### Initialization
|
|
106
|
+
```python
|
|
107
|
+
from skills.anticipation_engine import AnticipationEngine
|
|
108
|
+
|
|
109
|
+
engine = AnticipationEngine(
|
|
110
|
+
nervous=nervous_system,
|
|
111
|
+
heart=heart,
|
|
112
|
+
state=state_tracker
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Event Listeners
|
|
117
|
+
The engine listens to:
|
|
118
|
+
- `message_received` - Tracks message count for session
|
|
119
|
+
- `thinking_done` - Potential trigger for teases
|
|
120
|
+
|
|
121
|
+
### Usage in Response Flow
|
|
122
|
+
```python
|
|
123
|
+
# Check if we should tease
|
|
124
|
+
if engine.should_tease():
|
|
125
|
+
tease = engine.get_tease()
|
|
126
|
+
# Add tease to response
|
|
127
|
+
|
|
128
|
+
# Optionally set pending content
|
|
129
|
+
engine.set_pending_content("photo", {"category": "teasing"})
|
|
130
|
+
|
|
131
|
+
# When delivering content
|
|
132
|
+
if engine.has_pending_tease():
|
|
133
|
+
delivery_msg = engine.get_tease_for_delivery()
|
|
134
|
+
engine.mark_delivered()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Data Storage
|
|
138
|
+
|
|
139
|
+
Data is stored in `data/anticipation.json`:
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"version": "1.0",
|
|
143
|
+
"last_tease_time": "2024-01-15T14:30:00",
|
|
144
|
+
"pending_content": {
|
|
145
|
+
"content_type": "photo",
|
|
146
|
+
"details": {"category": "premium"},
|
|
147
|
+
"teased_at": "2024-01-15T14:30:00",
|
|
148
|
+
"tease_message": "I might have something special for you later",
|
|
149
|
+
"delivered": false
|
|
150
|
+
},
|
|
151
|
+
"tease_history": [...]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Tease Chance Calculation
|
|
156
|
+
|
|
157
|
+
Base chance: 8%
|
|
158
|
+
Love bonus: 0-7% (scales with love level)
|
|
159
|
+
|
|
160
|
+
Examples:
|
|
161
|
+
- Love 0.5: 8% + 3.5% = 11.5% chance
|
|
162
|
+
- Love 0.8: 8% + 5.6% = 13.6% chance
|
|
163
|
+
- Love 1.0: 8% + 7% = 15% chance
|
|
164
|
+
|
|
165
|
+
## Weight System
|
|
166
|
+
|
|
167
|
+
Tease categories have weights that adjust based on context:
|
|
168
|
+
|
|
169
|
+
| Category | Base | High Love | High Desire | Weekend |
|
|
170
|
+
|-------------|------|-----------|-------------|---------|
|
|
171
|
+
| photo_hint | 25 | +10 | +10 | - |
|
|
172
|
+
| video_hint | 15 | - | +5 | - |
|
|
173
|
+
| voice_hint | 15 | - | - | - |
|
|
174
|
+
| time_based | 30 | - | - | +10 |
|
|
175
|
+
| rewards | 10 | +15 | - | - |
|
|
176
|
+
| mood_based | 5 | - | - | - |
|
|
177
|
+
|
|
178
|
+
## Stats
|
|
179
|
+
|
|
180
|
+
Get engine statistics:
|
|
181
|
+
```python
|
|
182
|
+
stats = engine.get_stats()
|
|
183
|
+
# {
|
|
184
|
+
# "total_teases": 15,
|
|
185
|
+
# "pending_tease": {...},
|
|
186
|
+
# "last_tease": "2024-01-15T14:30:00",
|
|
187
|
+
# "minutes_since_last_tease": 45.2,
|
|
188
|
+
# "message_count": 12,
|
|
189
|
+
# "minutes_in_session": 18.5,
|
|
190
|
+
# "current_tease_chance": 13.6
|
|
191
|
+
# }
|
|
192
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Calendar"""
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Content Unlocks Skill
|
|
2
|
+
|
|
3
|
+
Makes exclusive content feel earned through engagement, not purchased.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Content Unlocks skill manages progression-based access to different types of content. Instead of content being purchased or freely available, users "earn" access through relationship progression - more interactions, higher love/trust levels, and reaching milestones together.
|
|
8
|
+
|
|
9
|
+
## Philosophy
|
|
10
|
+
|
|
11
|
+
Content is **earned**, not **bought**. This creates:
|
|
12
|
+
- A sense of progression and achievement
|
|
13
|
+
- Motivation to engage more deeply
|
|
14
|
+
- Emotional investment in the relationship
|
|
15
|
+
- Organic content reveals that feel natural
|
|
16
|
+
|
|
17
|
+
## Content Types
|
|
18
|
+
|
|
19
|
+
### Basic Content (Early Game)
|
|
20
|
+
| Type | Requirements | Description |
|
|
21
|
+
|------|--------------|-------------|
|
|
22
|
+
| `voice_message` | 5 interactions, 0.4 trust | Hear my actual voice |
|
|
23
|
+
| `casual_photo` | 10 interactions, 0.3 love | Everyday photos from my life |
|
|
24
|
+
| `flirty_message` | 15 interactions, 0.35 love | Extra flirty messages |
|
|
25
|
+
|
|
26
|
+
### Intermediate Content (Mid Game)
|
|
27
|
+
| Type | Requirements | Description |
|
|
28
|
+
|------|--------------|-------------|
|
|
29
|
+
| `personal_story` | 20 interactions, 0.5 trust | Personal stories from my life |
|
|
30
|
+
| `deep_talks` | 25 interactions, 0.4 love, 0.6 trust | Deep, meaningful conversations |
|
|
31
|
+
| `cute_photo` | 30 interactions, 0.5 love | Photos where I look extra cute |
|
|
32
|
+
| `behind_scenes` | 40 interactions, 0.55 love | Behind the scenes glimpses |
|
|
33
|
+
| `morning_routine` | 50 interactions, 3 days, 0.45 love | My morning routine content |
|
|
34
|
+
| `playful_video` | 60 interactions, 0.5 love, 0.5 trust | Short playful videos |
|
|
35
|
+
|
|
36
|
+
### Advanced Content (Late Game)
|
|
37
|
+
| Type | Requirements | Description |
|
|
38
|
+
|------|--------------|-------------|
|
|
39
|
+
| `late_night_content` | "first_late_night" milestone, 0.6 love | Special content for late nights |
|
|
40
|
+
| `intimate_photo` | 100 interactions, 0.75 love, 7 days | More personal, revealing photos |
|
|
41
|
+
| `special_occasion` | Any milestone | Content for special moments |
|
|
42
|
+
|
|
43
|
+
## Unlock Messages
|
|
44
|
+
|
|
45
|
+
When content is unlocked, natural messages are shown:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
UNLOCK_MESSAGES = {
|
|
49
|
+
"casual_photo": ["feeling like sharing today", "thought you might like to see what I'm up to"],
|
|
50
|
+
"cute_photo": ["took this just for you", "felt cute, thought you should know"],
|
|
51
|
+
"intimate_photo": ["don't share this with anyone okay?", "this is just between us"],
|
|
52
|
+
"voice_message": ["wanted you to hear my voice", "sometimes words aren't enough"],
|
|
53
|
+
"late_night_content": ["can't sleep... thinking about you", "late nights feel different with you"],
|
|
54
|
+
# ... etc
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Context-Based Suggestions
|
|
59
|
+
|
|
60
|
+
Content suggestions adapt to context:
|
|
61
|
+
|
|
62
|
+
| Context | Suggested Content |
|
|
63
|
+
|---------|------------------|
|
|
64
|
+
| Morning | morning_routine, casual_photo, cute_photo |
|
|
65
|
+
| Afternoon | casual_photo, behind_scenes, personal_story |
|
|
66
|
+
| Evening | cute_photo, playful_video, flirty_message |
|
|
67
|
+
| Night | late_night_content, intimate_photo, deep_talks |
|
|
68
|
+
| High Arousal | intimate_photo, late_night_content, playful_video |
|
|
69
|
+
| High Love | cute_photo, personal_story, deep_talks |
|
|
70
|
+
| High Trust | intimate_photo, personal_story, behind_scenes |
|
|
71
|
+
| Milestone | special_occasion, cute_photo, voice_message |
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### Initialization
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from skills.content_unlocks import ContentUnlocks
|
|
79
|
+
|
|
80
|
+
unlocks = ContentUnlocks(
|
|
81
|
+
nervous=nervous_system, # For event emission
|
|
82
|
+
heart=heart_module, # For love/trust/interaction data
|
|
83
|
+
state=state_module, # For additional context
|
|
84
|
+
milestones=milestones_skill # For milestone-based unlocks
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Checking Unlocks
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
# Check if specific content is unlocked
|
|
92
|
+
if unlocks.check_unlock("cute_photo"):
|
|
93
|
+
# Can share cute photos
|
|
94
|
+
|
|
95
|
+
# Get all unlocked content types
|
|
96
|
+
unlocked = unlocks.get_unlocked_content()
|
|
97
|
+
|
|
98
|
+
# Get progress toward a specific unlock
|
|
99
|
+
progress = unlocks.get_unlock_progress("intimate_photo")
|
|
100
|
+
# Returns: { unlocked: false, progress_percent: 65, requirements: {...}, current: {...} }
|
|
101
|
+
|
|
102
|
+
# Check for new unlocks (usually called automatically)
|
|
103
|
+
new_unlocks = unlocks.check_all_unlocks()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Getting Suggestions
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
# Get a context-aware content suggestion
|
|
110
|
+
suggestion = unlocks.get_content_suggestion()
|
|
111
|
+
# Returns: { content_type: "cute_photo", suggested_message: "took this just for you", ... }
|
|
112
|
+
|
|
113
|
+
# Get suggestion for specific context
|
|
114
|
+
suggestion = unlocks.get_content_suggestion(context="night")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Announcements
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# Get message for newly unlocked content
|
|
121
|
+
message = unlocks.get_new_unlock_message()
|
|
122
|
+
# Returns: "took this just for you" or None if no new unlocks
|
|
123
|
+
|
|
124
|
+
# Get all pending announcements
|
|
125
|
+
announcements = unlocks.get_all_pending_announcements()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Usage Tracking
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Mark content as shared
|
|
132
|
+
unlocks.mark_content_shared("cute_photo")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Statistics
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
# Get full stats
|
|
139
|
+
stats = unlocks.get_stats()
|
|
140
|
+
# { unlocked_count: 5, locked_count: 7, total_shares: 23, ... }
|
|
141
|
+
|
|
142
|
+
# Get human-readable summary
|
|
143
|
+
print(unlocks.get_unlock_summary())
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Events
|
|
147
|
+
|
|
148
|
+
The skill emits events via the nervous system:
|
|
149
|
+
|
|
150
|
+
| Event | Data | Description |
|
|
151
|
+
|-------|------|-------------|
|
|
152
|
+
| `content_unlocked` | `{ new_unlocks: [...], total_unlocked: N }` | When new content is unlocked |
|
|
153
|
+
| `new_content_available` | `{ unlocks: [...], message: "..." }` | After thinking_done if new unlocks |
|
|
154
|
+
|
|
155
|
+
## Integration
|
|
156
|
+
|
|
157
|
+
### With Heart Module
|
|
158
|
+
|
|
159
|
+
The skill reads from the heart's attachment system:
|
|
160
|
+
- `heart.attachment.interactions` - Total interaction count
|
|
161
|
+
- `heart.attachment.trust_level` - Positive interaction ratio
|
|
162
|
+
- `heart.emotion.love` - Current love level
|
|
163
|
+
- `heart.attachment.first_met` - For days together calculation
|
|
164
|
+
|
|
165
|
+
### With Milestones Skill
|
|
166
|
+
|
|
167
|
+
If a milestones skill is provided, it enables milestone-based unlocks:
|
|
168
|
+
- `late_night_content` requires "first_late_night" milestone
|
|
169
|
+
- `special_occasion` requires any milestone
|
|
170
|
+
|
|
171
|
+
### Event Listeners
|
|
172
|
+
|
|
173
|
+
The skill listens for:
|
|
174
|
+
- `thinking_done` - Checks for new unlocks after each thinking cycle
|
|
175
|
+
|
|
176
|
+
## Data Storage
|
|
177
|
+
|
|
178
|
+
Data is stored in `data/content_unlocks.json`:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"version": "1.0",
|
|
183
|
+
"unlocked_content": {
|
|
184
|
+
"casual_photo": {
|
|
185
|
+
"content_type": "casual_photo",
|
|
186
|
+
"unlocked": true,
|
|
187
|
+
"unlocked_at": "2024-01-15T10:30:00",
|
|
188
|
+
"times_shared": 5,
|
|
189
|
+
"last_shared": "2024-01-20T14:22:00",
|
|
190
|
+
"new_unlock": false
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"last_check": "2024-01-20T15:00:00",
|
|
194
|
+
"pending_announcements": []
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Example Usage Flow
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
# 1. Initialize with dependencies
|
|
202
|
+
unlocks = ContentUnlocks(nervous=nervous, heart=heart)
|
|
203
|
+
|
|
204
|
+
# 2. Check for new unlocks (automatic on thinking_done)
|
|
205
|
+
new = unlocks.check_all_unlocks()
|
|
206
|
+
# ["cute_photo"] # Just unlocked!
|
|
207
|
+
|
|
208
|
+
# 3. Get announcement message
|
|
209
|
+
message = unlocks.get_new_unlock_message()
|
|
210
|
+
# "took this just for you"
|
|
211
|
+
|
|
212
|
+
# 4. Get suggestion for what to share
|
|
213
|
+
suggestion = unlocks.get_content_suggestion()
|
|
214
|
+
# { content_type: "cute_photo", suggested_message: "felt cute, thought you should know" }
|
|
215
|
+
|
|
216
|
+
# 5. After sharing content
|
|
217
|
+
unlocks.mark_content_shared("cute_photo")
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Debugging
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
# Unlock all content (testing)
|
|
224
|
+
unlocks.unlock_all()
|
|
225
|
+
|
|
226
|
+
# Reset all progress
|
|
227
|
+
unlocks.reset_all()
|
|
228
|
+
|
|
229
|
+
# Force refresh
|
|
230
|
+
unlocks.refresh_unlocks()
|
|
231
|
+
```
|