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,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,8 @@
1
+ """
2
+ Content Unlocks Skill
3
+ Makes exclusive content feel earned through engagement, not purchased.
4
+ """
5
+
6
+ from .unlocks import ContentUnlocks
7
+
8
+ __all__ = ["ContentUnlocks"]
@@ -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
+ ```