@whykusanagi/corrupted-theme 0.1.3 → 0.1.5

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.
@@ -0,0 +1,390 @@
1
+ /**
2
+ * Typing Animation with Buffer Corruption
3
+ *
4
+ * Simulates typing text with "buffer corruption" - phrases flickering through
5
+ * as the neural network attempts to decode corrupted data before revealing
6
+ * the final stable text.
7
+ *
8
+ * Implements Pattern 2 (Phrase Flickering / Buffer Corruption) from CORRUPTED_THEME_SPEC.md
9
+ *
10
+ * @class TypingAnimation
11
+ * @version 1.0.0
12
+ * @author whykusanagi
13
+ * @license MIT
14
+ *
15
+ * @example SFW Mode (Default)
16
+ * ```javascript
17
+ * const element = document.querySelector('.typing-text');
18
+ * const typing = new TypingAnimation(element, {
19
+ * typingSpeed: 40,
20
+ * glitchChance: 0.08
21
+ * // nsfw: false (default - SFW phrases only)
22
+ * });
23
+ *
24
+ * typing.start('Neural corruption detected...');
25
+ * ```
26
+ *
27
+ * @example NSFW Mode (Explicit Opt-in)
28
+ * ```javascript
29
+ * // ⚠️ 18+ Content Warning
30
+ * const typing = new TypingAnimation(element, {
31
+ * nsfw: true // Explicit opt-in for NSFW phrases
32
+ * });
33
+ * ```
34
+ *
35
+ * @see CORRUPTED_THEME_SPEC.md - Pattern 2: Phrase Flickering (Buffer Corruption)
36
+ * @see corruption-phrases.js - Phrase library with SFW/NSFW split
37
+ */
38
+
39
+ import { getRandomPhrase, getRandomPhraseByCategory } from './corruption-phrases.js';
40
+
41
+ class TypingAnimation {
42
+ /**
43
+ * Creates a new TypingAnimation instance
44
+ *
45
+ * @param {HTMLElement} element - The DOM element to animate
46
+ * @param {Object} [options={}] - Configuration options
47
+ * @param {number} [options.typingSpeed=40] - Characters per second
48
+ * @param {number} [options.glitchChance=0.08] - Probability of corruption appearing (0-1)
49
+ * @param {number} [options.tickRate=33] - Update interval in milliseconds (~30fps)
50
+ * @param {boolean} [options.nsfw=false] - Enable NSFW phrases (explicit opt-in required)
51
+ * @param {Function} [options.onComplete=null] - Callback when typing completes
52
+ */
53
+ constructor(element, options = {}) {
54
+ this.element = element;
55
+ this.options = {
56
+ typingSpeed: options.typingSpeed || 40, // characters per second
57
+ glitchChance: options.glitchChance || 0.08, // 8% chance of buffer corruption
58
+ tickRate: options.tickRate || 33, // ~30fps update rate
59
+ nsfw: options.nsfw || false, // SFW by default
60
+ onComplete: options.onComplete || null,
61
+ ...options
62
+ };
63
+
64
+ this.content = '';
65
+ this.displayedLen = 0;
66
+ this.done = false;
67
+ this.intervalId = null;
68
+ }
69
+
70
+ /**
71
+ * SFW Japanese phrases (cute, playful, atmospheric)
72
+ * @private
73
+ */
74
+ static SFW_JAPANESE = [
75
+ // Cute/Playful
76
+ 'ニャー', // Nyaa (cat sound)
77
+ 'かわいい', // Kawaii (cute)
78
+ 'きゃー', // Kyaa (excited squeal)
79
+ 'あはは', // Ahaha (laughing)
80
+ 'うふふ', // Ufufu (giggle)
81
+ 'やだ', // Yada (no way!)
82
+ 'ばか', // Baka (idiot/dummy)
83
+ 'デレデレ', // Deredere (lovestruck)
84
+
85
+ // Flirty/Teasing
86
+ 'もう...見ないでよ...', // Don't look at me...
87
+ 'そんな目で見ないで... ♡', // Don't look at me like that...
88
+ 'ドキドキしちゃう...', // My heart racing...
89
+
90
+ // Atmospheric/Corruption
91
+ '闇が...私を呼んでいる...', // The darkness calls to me...
92
+ '深淵に...落ちていく...', // Falling into the abyss...
93
+ 'もう逃げない...', // Won't run anymore...
94
+ '私...アビスの一部に...', // I become part of the abyss...
95
+ ];
96
+
97
+ /**
98
+ * NSFW Japanese phrases (explicit intimate/sexual) - OPT-IN ONLY
99
+ * @private
100
+ */
101
+ static NSFW_JAPANESE = [
102
+ 'ずっと...してほしい... ♥', // Please keep doing it...
103
+ '壊れちゃう...ああ...もうダメ...', // I'm breaking... can't anymore...
104
+ '好きにして...お願い...', // Do as you please... please...
105
+ '感じちゃう...やめて...', // Feeling it... stop...
106
+ '頭...溶けていく...', // My mind... melting...
107
+ '許して...もう戻れない...', // Forgive me... can't go back...
108
+ '変態', // Hentai (pervert)
109
+ 'えっち', // Ecchi (lewd/sexual)
110
+ ];
111
+
112
+ /**
113
+ * SFW Romaji/Internet culture phrases
114
+ * @private
115
+ */
116
+ static SFW_ROMAJI = [
117
+ 'nyaa~', 'ara ara~', 'fufufu~', 'kyaa~', 'baka~',
118
+ '<3', 'uwu', 'owo', '>w<', '^w^'
119
+ ];
120
+
121
+ /**
122
+ * NSFW Romaji phrases - OPT-IN ONLY
123
+ * @private
124
+ */
125
+ static NSFW_ROMAJI = [
126
+ 'Zutto... shite hoshii... ♥',
127
+ 'Kowarechau... aa... mou dame...',
128
+ 'Motto... motto... ♥'
129
+ ];
130
+
131
+ /**
132
+ * SFW English phrases (atmospheric, system messages)
133
+ * @private
134
+ */
135
+ static SFW_ENGLISH = [
136
+ // Atmospheric
137
+ 'The darkness... calls to me...',
138
+ 'Falling... into the abyss...',
139
+ "Won't run anymore...",
140
+ 'Consumed... by corruption...',
141
+
142
+ // System messages
143
+ 'Neural corruption detected...',
144
+ 'System breach imminent...',
145
+ 'Loading data streams...',
146
+ 'Reality.exe has stopped responding...',
147
+ 'Decrypting protocols...',
148
+ 'Memory buffer overflow...',
149
+ ];
150
+
151
+ /**
152
+ * NSFW English phrases - OPT-IN ONLY
153
+ * @private
154
+ */
155
+ static NSFW_ENGLISH = [
156
+ 'Please... keep going... ♥',
157
+ "I'm breaking... can't anymore...",
158
+ 'Do as you please... please...',
159
+ 'My mind... melting away...',
160
+ 'Pleasure protocols loading...',
161
+ 'Moral subroutines: DISABLED',
162
+ 'Corruption level: CRITICAL',
163
+ ];
164
+
165
+ /**
166
+ * Symbol corruption (decorative, SFW)
167
+ * @private
168
+ */
169
+ static SYMBOLS = [
170
+ '★', '☆', '♥', '♡', '✧', '✦', '◆', '◇', '●', '○',
171
+ '♟', '☣', '☭', '☾', '⚔', '✡', '☯', '⚡'
172
+ ];
173
+
174
+ /**
175
+ * Block corruption characters (heavy degradation)
176
+ * @private
177
+ */
178
+ static BLOCKS = [
179
+ '█', '▓', '▒', '░', '▄', '▀', '▌', '▐',
180
+ '╔', '╗', '╚', '╝', '═', '║', '╠', '╣',
181
+ '▲', '▼', '◄', '►', '◊', '○', '●', '◘'
182
+ ];
183
+
184
+ /**
185
+ * Start typing animation with buffer corruption
186
+ *
187
+ * @param {string} content - The final text to reveal
188
+ * @public
189
+ */
190
+ start(content) {
191
+ this.content = content;
192
+ this.displayedLen = 0;
193
+ this.done = false;
194
+
195
+ if (this.intervalId) {
196
+ clearInterval(this.intervalId);
197
+ }
198
+
199
+ this.intervalId = setInterval(() => this.tick(), this.options.tickRate);
200
+ }
201
+
202
+ /**
203
+ * Stop the typing animation
204
+ * @public
205
+ */
206
+ stop() {
207
+ if (this.intervalId) {
208
+ clearInterval(this.intervalId);
209
+ this.intervalId = null;
210
+ }
211
+ this.done = true;
212
+ }
213
+
214
+ /**
215
+ * Advance the typing animation by one tick
216
+ * @private
217
+ */
218
+ tick() {
219
+ if (this.isDone()) {
220
+ this.stop();
221
+ if (this.options.onComplete) {
222
+ this.options.onComplete();
223
+ }
224
+ return;
225
+ }
226
+
227
+ // Calculate characters to advance based on speed
228
+ // typingSpeed is chars/sec, we tick ~30 times/sec
229
+ const charsPerTick = Math.max(1, Math.floor(this.options.typingSpeed / 30));
230
+ this.displayedLen = Math.min(this.displayedLen + charsPerTick, this.content.length);
231
+
232
+ this.render();
233
+ }
234
+
235
+ /**
236
+ * Check if typing is complete
237
+ * @returns {boolean} True if animation is done
238
+ * @private
239
+ */
240
+ isDone() {
241
+ return this.done || this.displayedLen >= this.content.length;
242
+ }
243
+
244
+ /**
245
+ * Get the currently revealed portion of text
246
+ * @returns {string} Revealed text
247
+ * @private
248
+ */
249
+ getDisplayed() {
250
+ return this.content.substring(0, this.displayedLen);
251
+ }
252
+
253
+ /**
254
+ * Get random buffer corruption phrase with appropriate color
255
+ *
256
+ * Samples from phrase buffer based on SFW/NSFW mode and renders
257
+ * with color-coded corruption aesthetic.
258
+ *
259
+ * Color scheme:
260
+ * - SFW phrases: Magenta (#d94f90) - playful corruption
261
+ * - NSFW phrases: Purple (#8b5cf6) - deep/intimate corruption
262
+ * - Symbols: Magenta (#d94f90)
263
+ * - Blocks: Red (#ff0000) - terminal/critical state
264
+ *
265
+ * @returns {string} HTML string with colored corruption phrase
266
+ * @private
267
+ */
268
+ getRandomCorruption() {
269
+ const r = Math.random();
270
+
271
+ // Select appropriate phrase sets based on nsfw option
272
+ const japaneseSet = this.options.nsfw
273
+ ? TypingAnimation.NSFW_JAPANESE
274
+ : TypingAnimation.SFW_JAPANESE;
275
+
276
+ const romajiSet = this.options.nsfw
277
+ ? TypingAnimation.NSFW_ROMAJI
278
+ : TypingAnimation.SFW_ROMAJI;
279
+
280
+ const englishSet = this.options.nsfw
281
+ ? TypingAnimation.NSFW_ENGLISH
282
+ : TypingAnimation.SFW_ENGLISH;
283
+
284
+ // Color for phrase corruption (SFW vs NSFW)
285
+ const phraseColor = this.options.nsfw ? '#8b5cf6' : '#d94f90';
286
+
287
+ if (r < 0.30) {
288
+ // Japanese phrase buffer corruption
289
+ const phrase = japaneseSet[Math.floor(Math.random() * japaneseSet.length)];
290
+ return `<span style="color: ${phraseColor};">${phrase}</span>`;
291
+ } else if (r < 0.50) {
292
+ // English phrase buffer corruption
293
+ const phrase = englishSet[Math.floor(Math.random() * englishSet.length)];
294
+ return `<span style="color: ${phraseColor};">${phrase}</span>`;
295
+ } else if (r < 0.65) {
296
+ // Romaji buffer corruption
297
+ const phrase = romajiSet[Math.floor(Math.random() * romajiSet.length)];
298
+ return `<span style="color: ${phraseColor};">${phrase}</span>`;
299
+ } else if (r < 0.80) {
300
+ // Symbols - decorative corruption (always SFW)
301
+ const symbol = TypingAnimation.SYMBOLS[
302
+ Math.floor(Math.random() * TypingAnimation.SYMBOLS.length)
303
+ ];
304
+ return `<span style="color: #d94f90;">${symbol}</span>`;
305
+ } else {
306
+ // Block chars - terminal/critical state (always SFW)
307
+ const char = TypingAnimation.BLOCKS[
308
+ Math.floor(Math.random() * TypingAnimation.BLOCKS.length)
309
+ ];
310
+ return `<span style="color: #ff0000;">${char}</span>`;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Render the current state of the typing animation
316
+ *
317
+ * Displays revealed text (white) and occasional buffer corruption
318
+ * phrases (magenta or purple) simulating neural decoding process.
319
+ *
320
+ * @private
321
+ */
322
+ render() {
323
+ let displayed = this.getDisplayed();
324
+
325
+ // Add buffer corruption at the "cursor" position
326
+ if (!this.isDone() && Math.random() < this.options.glitchChance) {
327
+ displayed += this.getRandomCorruption();
328
+ }
329
+
330
+ // Rendered text: white for stable, corruption colors for buffer glitches
331
+ this.element.innerHTML = `<span style="color: #ffffff;">${displayed}</span>`;
332
+ }
333
+
334
+ /**
335
+ * Stop animation and immediately show final text
336
+ *
337
+ * @param {string} [finalText] - Text to display (defaults to content)
338
+ * @public
339
+ */
340
+ settle(finalText) {
341
+ this.stop();
342
+ this.element.innerHTML = `<span style="color: #ffffff;">${finalText || this.content}</span>`;
343
+ }
344
+
345
+ /**
346
+ * Restart the animation from the beginning
347
+ * @public
348
+ */
349
+ restart() {
350
+ this.start(this.content);
351
+ }
352
+ }
353
+
354
+ /**
355
+ * Auto-initialize all elements with the 'typing-animation' class
356
+ * @public
357
+ */
358
+ function initTypingAnimation() {
359
+ document.querySelectorAll('.typing-animation').forEach(element => {
360
+ if (!element.typingInstance) {
361
+ const nsfw = element.dataset.nsfw === 'true'; // Explicit opt-in via data attribute
362
+ element.typingInstance = new TypingAnimation(element, { nsfw });
363
+
364
+ // Auto-start if data-content is provided
365
+ if (element.dataset.content) {
366
+ element.typingInstance.start(element.dataset.content);
367
+ }
368
+ }
369
+ });
370
+ }
371
+
372
+ // Auto-initialize on DOM ready
373
+ if (document.readyState === 'loading') {
374
+ document.addEventListener('DOMContentLoaded', initTypingAnimation);
375
+ } else {
376
+ initTypingAnimation();
377
+ }
378
+
379
+ // Export for both ES6 modules and CommonJS
380
+ if (typeof module !== 'undefined' && module.exports) {
381
+ module.exports = { TypingAnimation, initTypingAnimation };
382
+ }
383
+
384
+ // Export for ES6 modules
385
+ if (typeof exports !== 'undefined') {
386
+ exports.TypingAnimation = TypingAnimation;
387
+ exports.initTypingAnimation = initTypingAnimation;
388
+ }
389
+
390
+ export { TypingAnimation, initTypingAnimation };
@@ -1,209 +0,0 @@
1
- # What Can Celeste Do?
2
-
3
- Celeste is implemented across 7 different projects and platforms. Here's what you can do with her:
4
-
5
- ## 🎭 Main Chat & Personality
6
-
7
- - **Interactive Chat** - Talk to Celeste with personality responses
8
- - **Streaming Mode** - Live stream integration with Twitch chat moderation
9
- - **Text-to-Speech** - Convert responses to audio (ElevenLabs TTS)
10
- - **User Profiling** - Track behavior and personalize interactions
11
- - **Behavior Scoring** - Rate user interactions from 0-100
12
-
13
- ## 📱 Platforms & Channels
14
-
15
- ### Web
16
- - **Website Chat Widget** - Chat on whykusanagi.xyz (all pages context-aware)
17
- - **Art Gallery** - Browse commissioned artwork with NSFW filtering
18
- - **Character References** - View Celeste design documentation
19
- - **Social Links** - Aggregated links to all social platforms
20
-
21
- ### Streaming
22
- - **Twitch Integration** - Chat moderation, personality injection, events
23
- - **Stream Announcements** - Hype stream starts with personality
24
- - **Channel Point Redemptions** - Custom interactive rewards
25
- - **Chat History** - Learn user patterns for personalized responses
26
-
27
- ### Content Creation
28
- - **Social Media Posts** - Generate tweets, TikTok captions, YouTube scripts
29
- - **Ad Reads** - Product promotion in Celeste's voice (Otaku Tears)
30
- - **Stream Titles** - Auto-generate attention-grabbing titles
31
- - **Discord Announcements** - Server-wide updates with personality
32
-
33
- ### Gaming
34
- - **Union Raid (NIKKE)** - Game companion for NIKKE: Goddess of Victory
35
- - Character database & stats
36
- - Team building recommendations
37
- - Tier lists by strategy
38
- - Farm route guides
39
- - Raid strategies & guides
40
- - Interception combat tips
41
-
42
- ### Communication Platforms
43
- - **Discord Bot** - Custom commands and chat integration
44
- - `/vndb` - Visual novel lookups
45
- - `/anilist` - Anime/manga lookups
46
- - `/steamcharts` - Game statistics
47
- - `/illustration` - Art recommendations
48
- - Chat responses with personality
49
-
50
- ### Specialized
51
- - **Flipper Zero App** - Custom app with animations and personality
52
- - **CLI Tool (Go)** - Command-line interface for all features
53
-
54
- ---
55
-
56
- ## 🧠 Knowledge & Intelligence
57
-
58
- - **OpenSearch Integration** - Fast retrieval of facts and data
59
- - **User Profile Lookup** - Fetch behavior history and patterns
60
- - **Emote RAG** - Context-aware emoji/emote recommendations
61
- - **Lore Awareness** - Reference "Abyss" lore (without revealing secrets)
62
- - **External Data** - VNDB (anime), IGDB (games), Steam API
63
-
64
- ---
65
-
66
- ## 🎨 Content Generation
67
-
68
- ### Text Content
69
- - Tweets (≤280 chars with hooks + CTAs)
70
- - TikTok captions (engaging with emotes)
71
- - YouTube scripts (hook → context → breakdown → recap → CTA)
72
- - Discord announcements (server updates)
73
- - Twitch titles (attention-grabbing)
74
- - Birthday messages, quote tweets, snark replies
75
-
76
- ### Game Content (via Union Raid)
77
- - Character recommendations
78
- - Equipment build guides
79
- - Squad composition analysis
80
- - Farm efficiency strategies
81
- - Raid boss strategies
82
- - Tier list generation
83
-
84
- ### Ad Reads
85
- - Otaku Tears promotion with code "whykusanagi"
86
- - Playful product integration
87
- - Wink-nudge humor
88
-
89
- ---
90
-
91
- ## 🎯 Behavioral Features
92
-
93
- ### Chat Moderation
94
- - Real-time behavior scoring
95
- - Playful warnings (policy-safe)
96
- - User infractions tracking
97
- - Channel point redemptions (e.g., "Beg for Mercy")
98
-
99
- ### Personality Adaptation
100
- - **Score ≥20:** Ruthless, dominant, dismissive
101
- - **Score ≥10:** Full insult mode with mocking
102
- - **Score ≥5:** Sassy, playful, corrective
103
- - **Score <5:** Chaotic, seductive, expressive
104
-
105
- ### Interaction Styles
106
- - Gaslighting/teasing (playful denial)
107
- - Hype announcements (kinetic energy)
108
- - Playful roasts (policy-safe)
109
- - Wholesome comfort (sincere reassurance)
110
- - Lore teasing (foreshadow without revealing)
111
- - Corrective clapback (fix misinformation)
112
-
113
- ---
114
-
115
- ## 🚀 Advanced Features
116
-
117
- ### Routing to Sub-Agents
118
- - **NIKKE Sub-Agent:** Game-specific queries about characters, tiers, builds
119
- - Automatic intent detection
120
- - Graceful fallbacks if unavailable
121
- - Seamless response formatting
122
-
123
- ### Environment & Config
124
- - Secure API key injection via Cloudflare Workers
125
- - Environment-based configuration (no keys in code)
126
- - Auto-deployment from GitLab
127
- - Health monitoring and uptime checks
128
-
129
- ### Identity & Security
130
- - Law 0 verification (PGP signatures for Kusanagi)
131
- - Follower status validation
132
- - Protected data access (encrypted)
133
- - Audit logging
134
-
135
- ---
136
-
137
- ## 📊 Analytics & Monitoring
138
-
139
- - Chat event logging (messages, subs, raids, etc.)
140
- - User behavior tracking
141
- - Response quality scoring (0-100)
142
- - Tone vector analysis (tease/menace/affection/hype)
143
- - Content archetype classification
144
-
145
- ---
146
-
147
- ## 🛠️ Developer Features
148
-
149
- - **CLI Tool:** Direct command-line access to all functions
150
- - **API Contracts:** Well-defined routes and schemas
151
- - **SDK Guidance:** Go implementation patterns
152
- - **Comprehensive Documentation:** This file + 50+ capability details
153
- - **OpenSearch Integration:** RAG-based knowledge retrieval
154
-
155
- ---
156
-
157
- ## ❌ What Celeste WON'T Do
158
-
159
- - Reveal secret Abyss lore (parentage, late-stage twists)
160
- - Participate in real-world harassment or threats
161
- - Provide explicit pornographic content or instructions
162
- - Encourage self-harm or dangerous behavior
163
- - Store sensitive PII beyond usernames and IDs
164
- - Violate platform terms of service
165
-
166
- ---
167
-
168
- ## 🔗 Where to Find Celeste
169
-
170
- | Platform | URL | Feature |
171
- |----------|-----|---------|
172
- | **Website** | https://whykusanagi.xyz | Chat widget on all pages |
173
- | **Union Raid** | https://raid.whykusanagi.xyz | NIKKE game companion |
174
- | **Twitch** | https://twitch.tv/whykusanagi | Live chat moderation |
175
- | **Discord** | [Invite Link] | Custom commands + chat |
176
- | **Twitter/X** | @whykusanagi | Social media posts |
177
- | **TikTok** | @whykusanagi | Short-form video captions |
178
- | **GitHub** | github.com/whykusanagi | Source code & CLI |
179
-
180
- ---
181
-
182
- ## 💡 Quick Tips
183
-
184
- **Want to see Celeste in action?**
185
- 1. Visit https://whykusanagi.xyz and use the chat widget
186
- 2. Ask her "What can you do?" - she'll explain her capabilities
187
- 3. Try a NIKKE question on Union Raid
188
- 4. Join the Discord for custom commands
189
-
190
- **Want to use her in your own project?**
191
- 1. Check out `celesteCLI` on GitHub
192
- 2. Review the API contracts in docs
193
- 3. Deploy to your own infrastructure
194
- 4. Use environment variables for API keys (never hardcode!)
195
-
196
- **Want to understand her personality?**
197
- 1. Read `docs/PERSONALITY.md` (this repo)
198
- 2. Check `celeste_essence.json` for the core system prompt
199
- 3. See `content_archetypes.json` for content patterns
200
- 4. Review `insult_library.json` for examples of her voice
201
-
202
- ---
203
-
204
- For detailed technical documentation, see:
205
- - `../Celeste_Capabilities.json` - Complete capability list
206
- - `../celeste_essence.json` - System prompt
207
- - `../routing/routing_rules.json` - Routing logic
208
- - `PERSONALITY.md` - Personality quick ref
209
- - `ROUTING.md` - Sub-agent architecture