reflexive 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/dashboard.html ADDED
@@ -0,0 +1,620 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Reflexive Nexus - Story Dashboard</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body {
10
+ font-family: 'Courier New', monospace;
11
+ background: #000;
12
+ overflow: hidden;
13
+ color: #fff;
14
+ }
15
+ #three-canvas {
16
+ position: fixed;
17
+ top: 0;
18
+ left: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ z-index: 0;
22
+ }
23
+ .overlay {
24
+ position: fixed;
25
+ top: 0;
26
+ left: 0;
27
+ width: 100%;
28
+ height: 100%;
29
+ z-index: 1;
30
+ pointer-events: none;
31
+ }
32
+ .ui-container {
33
+ position: relative;
34
+ z-index: 2;
35
+ padding: 40px;
36
+ display: flex;
37
+ flex-direction: column;
38
+ height: 100vh;
39
+ pointer-events: none;
40
+ }
41
+ .ui-container > * {
42
+ pointer-events: auto;
43
+ }
44
+ .header {
45
+ text-align: center;
46
+ margin-bottom: 30px;
47
+ }
48
+ h1 {
49
+ font-size: 4em;
50
+ text-shadow:
51
+ 0 0 10px rgba(0, 255, 255, 0.8),
52
+ 0 0 20px rgba(0, 255, 255, 0.6),
53
+ 0 0 30px rgba(0, 255, 255, 0.4),
54
+ 0 0 40px rgba(0, 200, 255, 0.3);
55
+ animation: pulse 3s ease-in-out infinite;
56
+ letter-spacing: 0.1em;
57
+ }
58
+ @keyframes pulse {
59
+ 0%, 100% { text-shadow: 0 0 10px rgba(0, 255, 255, 0.8), 0 0 20px rgba(0, 255, 255, 0.6); }
60
+ 50% { text-shadow: 0 0 20px rgba(0, 255, 255, 1), 0 0 40px rgba(0, 255, 255, 0.8); }
61
+ }
62
+ .content {
63
+ display: grid;
64
+ grid-template-columns: 1fr 1fr;
65
+ gap: 30px;
66
+ flex: 1;
67
+ }
68
+ .panel {
69
+ background: rgba(0, 20, 40, 0.7);
70
+ border: 2px solid rgba(0, 255, 255, 0.4);
71
+ border-radius: 20px;
72
+ padding: 30px;
73
+ backdrop-filter: blur(10px);
74
+ box-shadow:
75
+ 0 0 20px rgba(0, 255, 255, 0.2),
76
+ inset 0 0 20px rgba(0, 255, 255, 0.05);
77
+ }
78
+ .panel h2 {
79
+ color: #00ffff;
80
+ margin-bottom: 20px;
81
+ font-size: 1.8em;
82
+ text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
83
+ }
84
+ .story-text {
85
+ font-size: 1.2em;
86
+ line-height: 1.8;
87
+ color: #a0d8ff;
88
+ margin-bottom: 20px;
89
+ }
90
+ .metrics {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 20px;
94
+ }
95
+ .metric {
96
+ background: rgba(0, 0, 0, 0.5);
97
+ padding: 15px;
98
+ border-radius: 10px;
99
+ border-left: 4px solid #00ffff;
100
+ }
101
+ .metric-label {
102
+ color: #00ffff;
103
+ font-size: 0.9em;
104
+ margin-bottom: 8px;
105
+ }
106
+ .metric-bar {
107
+ height: 30px;
108
+ background: rgba(0, 0, 0, 0.6);
109
+ border-radius: 15px;
110
+ overflow: hidden;
111
+ position: relative;
112
+ }
113
+ .metric-fill {
114
+ height: 100%;
115
+ background: linear-gradient(90deg, #00ff88, #00ffff, #0088ff);
116
+ transition: width 1s ease;
117
+ box-shadow: 0 0 20px rgba(0, 255, 200, 0.6);
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: center;
121
+ font-weight: bold;
122
+ color: #000;
123
+ }
124
+ .choices {
125
+ display: flex;
126
+ flex-direction: column;
127
+ gap: 15px;
128
+ }
129
+ .choice-btn {
130
+ padding: 20px;
131
+ background: linear-gradient(135deg, rgba(0, 255, 136, 0.15), rgba(0, 200, 255, 0.15));
132
+ border: 2px solid rgba(0, 255, 200, 0.5);
133
+ border-radius: 12px;
134
+ color: #fff;
135
+ font-size: 1.2em;
136
+ cursor: pointer;
137
+ transition: all 0.3s ease;
138
+ text-align: left;
139
+ font-family: 'Courier New', monospace;
140
+ }
141
+ .choice-btn:hover {
142
+ background: linear-gradient(135deg, rgba(0, 255, 136, 0.3), rgba(0, 200, 255, 0.3));
143
+ transform: translateX(10px);
144
+ box-shadow: 0 0 30px rgba(0, 255, 200, 0.5);
145
+ border-color: #00ffff;
146
+ }
147
+ .chat-panel {
148
+ grid-column: 1 / -1;
149
+ max-height: 200px;
150
+ }
151
+ .chat-input {
152
+ width: 100%;
153
+ padding: 15px;
154
+ background: rgba(0, 0, 0, 0.6);
155
+ border: 2px solid rgba(0, 255, 255, 0.4);
156
+ border-radius: 10px;
157
+ color: #fff;
158
+ font-size: 1.1em;
159
+ font-family: 'Courier New', monospace;
160
+ transition: all 0.1s ease-out, transform 0.1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
161
+ }
162
+ .chat-input:focus {
163
+ outline: none;
164
+ border-color: #00ffff;
165
+ box-shadow: 0 0 20px rgba(0, 255, 255, 0.4);
166
+ }
167
+ .chat-send {
168
+ margin-top: 10px;
169
+ padding: 15px 30px;
170
+ background: linear-gradient(135deg, #00ff88, #00ffff);
171
+ border: none;
172
+ border-radius: 10px;
173
+ color: #000;
174
+ font-weight: bold;
175
+ cursor: pointer;
176
+ font-size: 1.1em;
177
+ font-family: 'Courier New', monospace;
178
+ }
179
+ .chat-send:hover {
180
+ box-shadow: 0 0 30px rgba(0, 255, 200, 0.8);
181
+ transform: translateY(-2px);
182
+ }
183
+ .start-screen {
184
+ position: relative;
185
+ z-index: 10;
186
+ display: flex;
187
+ flex-direction: column;
188
+ justify-content: center;
189
+ align-items: center;
190
+ height: 100vh;
191
+ }
192
+ .start-btn {
193
+ padding: 30px 60px;
194
+ background: linear-gradient(135deg, #00ff88, #00ffff);
195
+ border: none;
196
+ border-radius: 20px;
197
+ color: #000;
198
+ font-size: 2em;
199
+ font-weight: bold;
200
+ cursor: pointer;
201
+ font-family: 'Courier New', monospace;
202
+ box-shadow: 0 0 40px rgba(0, 255, 200, 0.6);
203
+ }
204
+ .start-btn:hover {
205
+ box-shadow: 0 0 60px rgba(0, 255, 200, 1);
206
+ transform: scale(1.05);
207
+ }
208
+ .hidden { display: none; }
209
+ </style>
210
+ </head>
211
+ <body>
212
+ <canvas id="three-canvas"></canvas>
213
+
214
+ <div id="start-screen" class="start-screen">
215
+ <h1>⚡ REFLEXIVE NEXUS ⚡</h1>
216
+ <p style="font-size: 1.5em; margin: 20px 0; color: #00ffff;">AI-POWERED STORY ENGINE</p>
217
+ <button class="start-btn" onclick="startGame()">► INITIALIZE</button>
218
+ </div>
219
+
220
+ <div id="game-screen" class="ui-container hidden">
221
+ <div class="header">
222
+ <h1>⚡ NEXUS ACTIVE ⚡</h1>
223
+ </div>
224
+
225
+ <div class="content">
226
+ <div class="panel">
227
+ <h2>◉ NARRATIVE STREAM</h2>
228
+ <div class="story-text" id="story-text">Initializing story engine...</div>
229
+
230
+ <div class="chat-panel">
231
+ <input type="text" id="chat-input" class="chat-input" placeholder="► Enter command..." />
232
+ <button class="chat-send" onclick="sendCommand()">⚡ EXECUTE</button>
233
+ </div>
234
+ </div>
235
+
236
+ <div class="panel">
237
+ <h2>◉ SYSTEM METRICS</h2>
238
+ <div class="metrics">
239
+ <div class="metric">
240
+ <div class="metric-label">⚡ QUALITY INDEX</div>
241
+ <div class="metric-bar">
242
+ <div class="metric-fill" id="quality-bar" style="width: 50%">50%</div>
243
+ </div>
244
+ </div>
245
+ <div class="metric">
246
+ <div class="metric-label">📍 SCENE PROGRESSION</div>
247
+ <div class="metric-bar">
248
+ <div class="metric-fill" id="scene-bar" style="width: 10%"><span id="scene-count">0</span></div>
249
+ </div>
250
+ </div>
251
+ <div class="metric">
252
+ <div class="metric-label">💫 ENGAGEMENT FLOW</div>
253
+ <div class="metric-bar">
254
+ <div class="metric-fill" id="engagement-bar" style="width: 50%">50%</div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+
259
+ <h2 style="margin-top: 30px;">◉ ACTION VECTORS</h2>
260
+ <div class="choices" id="choices"></div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+
265
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
266
+ <script>
267
+ // Three.js setup
268
+ let scene, camera, renderer;
269
+ let particleSystem, galaxySystem;
270
+ let time = 0;
271
+
272
+ function initThreeJS() {
273
+ scene = new THREE.Scene();
274
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
275
+ camera.position.z = 30;
276
+
277
+ renderer = new THREE.WebGLRenderer({
278
+ canvas: document.getElementById('three-canvas'),
279
+ antialias: true,
280
+ alpha: true
281
+ });
282
+ renderer.setSize(window.innerWidth, window.innerHeight);
283
+ renderer.setClearColor(0x000000, 1);
284
+
285
+ // Create main particle system with custom shader
286
+ createParticleSystem();
287
+
288
+ // Create rotating galaxy
289
+ createGalaxy();
290
+
291
+ // Animation loop
292
+ animate();
293
+
294
+ window.addEventListener('resize', onWindowResize);
295
+ }
296
+
297
+ function createParticleSystem() {
298
+ const particleCount = 5000;
299
+ const geometry = new THREE.BufferGeometry();
300
+ const positions = new Float32Array(particleCount * 3);
301
+ const colors = new Float32Array(particleCount * 3);
302
+ const sizes = new Float32Array(particleCount);
303
+
304
+ for (let i = 0; i < particleCount; i++) {
305
+ positions[i * 3] = (Math.random() - 0.5) * 100;
306
+ positions[i * 3 + 1] = (Math.random() - 0.5) * 100;
307
+ positions[i * 3 + 2] = (Math.random() - 0.5) * 100;
308
+
309
+ const color = new THREE.Color();
310
+ color.setHSL(0.5 + Math.random() * 0.2, 1.0, 0.5 + Math.random() * 0.3);
311
+ colors[i * 3] = color.r;
312
+ colors[i * 3 + 1] = color.g;
313
+ colors[i * 3 + 2] = color.b;
314
+
315
+ sizes[i] = Math.random() * 3 + 1;
316
+ }
317
+
318
+ geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
319
+ geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
320
+ geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
321
+
322
+ const material = new THREE.ShaderMaterial({
323
+ uniforms: {
324
+ time: { value: 0 },
325
+ mood: { value: 0.5 },
326
+ quality: { value: 0.5 }
327
+ },
328
+ vertexShader: `
329
+ attribute float size;
330
+ varying vec3 vColor;
331
+ uniform float time;
332
+ uniform float mood;
333
+ uniform float quality;
334
+
335
+ void main() {
336
+ vColor = color;
337
+ vec3 pos = position;
338
+
339
+ // Swirling motion based on mood
340
+ float angle = time * 0.2 + length(pos.xy) * 0.02;
341
+ float radius = length(pos.xy);
342
+ pos.x += sin(angle + pos.z * 0.01) * mood * 5.0;
343
+ pos.y += cos(angle + pos.z * 0.01) * mood * 5.0;
344
+ pos.z += sin(time * 0.5 + radius * 0.05) * quality * 3.0;
345
+
346
+ vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
347
+ gl_PointSize = size * (300.0 / -mvPosition.z) * (0.5 + mood + quality * 0.5);
348
+ gl_Position = projectionMatrix * mvPosition;
349
+ }
350
+ `,
351
+ fragmentShader: `
352
+ varying vec3 vColor;
353
+ uniform float mood;
354
+ uniform float quality;
355
+
356
+ void main() {
357
+ vec2 center = gl_PointCoord - vec2(0.5);
358
+ float dist = length(center);
359
+
360
+ if (dist > 0.5) discard;
361
+
362
+ float alpha = 1.0 - (dist * 2.0);
363
+ alpha = pow(alpha, 2.0);
364
+ alpha *= (0.4 + mood * 0.3 + quality * 0.3);
365
+
366
+ // Glow effect
367
+ vec3 glowColor = vColor * (1.0 + mood * 0.5);
368
+
369
+ gl_FragColor = vec4(glowColor, alpha);
370
+ }
371
+ `,
372
+ transparent: true,
373
+ vertexColors: true,
374
+ blending: THREE.AdditiveBlending,
375
+ depthTest: false
376
+ });
377
+
378
+ particleSystem = new THREE.Points(geometry, material);
379
+ scene.add(particleSystem);
380
+ }
381
+
382
+ function createGalaxy() {
383
+ const galaxyCount = 3000;
384
+ const geometry = new THREE.BufferGeometry();
385
+ const positions = new Float32Array(galaxyCount * 3);
386
+ const colors = new Float32Array(galaxyCount * 3);
387
+
388
+ for (let i = 0; i < galaxyCount; i++) {
389
+ const radius = Math.random() * 50 + 10;
390
+ const spinAngle = radius * 0.3;
391
+ const branchAngle = (i % 3) * (Math.PI * 2 / 3);
392
+
393
+ positions[i * 3] = Math.cos(branchAngle + spinAngle) * radius;
394
+ positions[i * 3 + 1] = (Math.random() - 0.5) * 5;
395
+ positions[i * 3 + 2] = Math.sin(branchAngle + spinAngle) * radius;
396
+
397
+ const color = new THREE.Color();
398
+ color.setHSL(0.5 + Math.random() * 0.3, 0.8, 0.6);
399
+ colors[i * 3] = color.r;
400
+ colors[i * 3 + 1] = color.g;
401
+ colors[i * 3 + 2] = color.b;
402
+ }
403
+
404
+ geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
405
+ geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
406
+
407
+ const material = new THREE.PointsMaterial({
408
+ size: 2,
409
+ vertexColors: true,
410
+ transparent: true,
411
+ opacity: 0.6,
412
+ blending: THREE.AdditiveBlending
413
+ });
414
+
415
+ galaxySystem = new THREE.Points(geometry, material);
416
+ galaxySystem.position.z = -20;
417
+ scene.add(galaxySystem);
418
+ }
419
+
420
+ function animate() {
421
+ requestAnimationFrame(animate);
422
+ time += 0.016;
423
+
424
+ // Apply screen shake to camera
425
+ applyShakeToCamera();
426
+
427
+ if (particleSystem) {
428
+ particleSystem.material.uniforms.time.value = time;
429
+ particleSystem.rotation.y += 0.0005;
430
+ particleSystem.rotation.x += 0.0002;
431
+ }
432
+
433
+ if (galaxySystem) {
434
+ galaxySystem.rotation.y += 0.002;
435
+ galaxySystem.rotation.z += 0.001;
436
+ }
437
+
438
+ renderer.render(scene, camera);
439
+ }
440
+
441
+ function onWindowResize() {
442
+ camera.aspect = window.innerWidth / window.innerHeight;
443
+ camera.updateProjectionMatrix();
444
+ renderer.setSize(window.innerWidth, window.innerHeight);
445
+ }
446
+
447
+ function updateParticleMood(quality, engagement) {
448
+ if (particleSystem) {
449
+ particleSystem.material.uniforms.mood.value = engagement;
450
+ particleSystem.material.uniforms.quality.value = quality;
451
+
452
+ // Update particle colors based on quality
453
+ const colors = particleSystem.geometry.attributes.color;
454
+ for (let i = 0; i < colors.count; i++) {
455
+ const color = new THREE.Color();
456
+ if (quality > 0.7) {
457
+ color.setHSL(0.3 + Math.random() * 0.15, 1.0, 0.5);
458
+ } else if (quality < 0.3) {
459
+ color.setHSL(0.0 + Math.random() * 0.1, 1.0, 0.5);
460
+ } else {
461
+ color.setHSL(0.5 + Math.random() * 0.2, 1.0, 0.5);
462
+ }
463
+ colors.array[i * 3] = color.r;
464
+ colors.array[i * 3 + 1] = color.g;
465
+ colors.array[i * 3 + 2] = color.b;
466
+ }
467
+ colors.needsUpdate = true;
468
+ }
469
+ }
470
+
471
+ // Game logic
472
+ let sessionId = null;
473
+
474
+ function startGame() {
475
+ console.log('Starting game...');
476
+ fetch('/api/start', { method: 'POST' })
477
+ .then(res => {
478
+ console.log('Got response:', res.status);
479
+ return res.json();
480
+ })
481
+ .then(data => {
482
+ console.log('Game data:', data);
483
+ sessionId = data.sessionId;
484
+ document.getElementById('start-screen').classList.add('hidden');
485
+ document.getElementById('game-screen').classList.remove('hidden');
486
+ displayGameState(data.state);
487
+ })
488
+ .catch(err => {
489
+ console.error('Error starting game:', err);
490
+ alert('Error starting game: ' + err.message);
491
+ });
492
+ }
493
+
494
+ function makeChoice(index) {
495
+ fetch('/api/choice', {
496
+ method: 'POST',
497
+ headers: { 'Content-Type': 'application/json' },
498
+ body: JSON.stringify({ sessionId, choiceIndex: index })
499
+ })
500
+ .then(res => res.json())
501
+ .then(data => displayGameState(data.state));
502
+ }
503
+
504
+ function sendCommand() {
505
+ const input = document.getElementById('chat-input');
506
+ const prompt = input.value.trim();
507
+ if (!prompt) return;
508
+
509
+ fetch('/api/prompt', {
510
+ method: 'POST',
511
+ headers: { 'Content-Type': 'application/json' },
512
+ body: JSON.stringify({ sessionId, prompt })
513
+ })
514
+ .then(res => res.json())
515
+ .then(data => {
516
+ displayGameState(data.state);
517
+ input.value = '';
518
+ });
519
+ }
520
+
521
+ // Screen shake and input effects
522
+ let shakeIntensity = 0;
523
+ let shakeDecay = 0.95;
524
+
525
+ function triggerShake(intensity = 0.5) {
526
+ shakeIntensity = intensity;
527
+ }
528
+
529
+ function applyShakeToCamera() {
530
+ if (shakeIntensity > 0.01) {
531
+ camera.position.x += (Math.random() - 0.5) * shakeIntensity * 2;
532
+ camera.position.y += (Math.random() - 0.5) * shakeIntensity * 2;
533
+ camera.rotation.z += (Math.random() - 0.5) * shakeIntensity * 0.02;
534
+ shakeIntensity *= shakeDecay;
535
+ } else {
536
+ // Reset to original position smoothly
537
+ camera.position.x *= 0.9;
538
+ camera.position.y *= 0.9;
539
+ camera.rotation.z *= 0.9;
540
+ }
541
+ }
542
+
543
+ document.addEventListener('DOMContentLoaded', () => {
544
+ const chatInput = document.getElementById('chat-input');
545
+
546
+ // Vibrate and shake on keypress
547
+ chatInput.addEventListener('keydown', (e) => {
548
+ if (e.key === 'Enter') {
549
+ sendCommand();
550
+ return;
551
+ }
552
+
553
+ // Trigger screen shake
554
+ triggerShake(0.3);
555
+
556
+ // Particle burst effect
557
+ if (particleSystem) {
558
+ particleSystem.material.uniforms.mood.value = Math.min(1.0, particleSystem.material.uniforms.mood.value + 0.1);
559
+ }
560
+
561
+ // Input vibration effect
562
+ chatInput.style.transform = 'scale(1.02)';
563
+ setTimeout(() => {
564
+ chatInput.style.transform = 'scale(1)';
565
+ }, 100);
566
+
567
+ // Visual flash
568
+ chatInput.style.borderColor = 'rgba(0, 255, 255, 1)';
569
+ chatInput.style.boxShadow = '0 0 30px rgba(0, 255, 255, 0.8)';
570
+ setTimeout(() => {
571
+ chatInput.style.borderColor = 'rgba(0, 255, 255, 0.4)';
572
+ chatInput.style.boxShadow = '0 0 20px rgba(0, 255, 255, 0.4)';
573
+ }, 150);
574
+ });
575
+
576
+ chatInput.addEventListener('keypress', (e) => {
577
+ if (e.key === 'Enter') sendCommand();
578
+ });
579
+ });
580
+
581
+ function displayGameState(state) {
582
+ document.getElementById('story-text').textContent = state.text;
583
+
584
+ const choicesEl = document.getElementById('choices');
585
+ choicesEl.innerHTML = '';
586
+
587
+ if (state.choices && state.choices.length > 0) {
588
+ state.choices.forEach((choice, index) => {
589
+ const btn = document.createElement('button');
590
+ btn.className = 'choice-btn';
591
+ btn.textContent = '▸ ' + choice.text;
592
+ btn.onclick = () => makeChoice(index);
593
+ choicesEl.appendChild(btn);
594
+ });
595
+ }
596
+
597
+ if (state.quality !== undefined) {
598
+ const qualityPct = Math.round(state.quality * 100);
599
+ const engagementPct = Math.round((state.engagement || 0.5) * 100);
600
+ const sceneCount = state.sceneCount || 0;
601
+
602
+ document.getElementById('quality-bar').style.width = qualityPct + '%';
603
+ document.getElementById('quality-bar').textContent = qualityPct + '%';
604
+
605
+ document.getElementById('engagement-bar').style.width = engagementPct + '%';
606
+ document.getElementById('engagement-bar').textContent = engagementPct + '%';
607
+
608
+ document.getElementById('scene-count').textContent = sceneCount;
609
+ document.getElementById('scene-bar').style.width = Math.min(sceneCount * 10, 100) + '%';
610
+
611
+ // Update Three.js particles
612
+ updateParticleMood(state.quality, state.engagement || 0.5);
613
+ }
614
+ }
615
+
616
+ // Initialize Three.js on load
617
+ initThreeJS();
618
+ </script>
619
+ </body>
620
+ </html>