|
6 | 6 | <meta name="theme-color" content="#0a0a0f"> |
7 | 7 | <meta name="apple-mobile-web-app-capable" content="yes"> |
8 | 8 | <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
9 | | - <title>AION · Ada‑VELA</title> |
10 | | - <link rel="icon" type="image/svg+xml" href="/assets/logo.svg"> |
11 | | - <link rel="apple-touch-icon" href="/assets/logo.svg"> |
12 | | - <link rel="manifest" href="/manifest.json"> |
| 9 | + <title>AION · Ada‑VELA v5.5</title> |
13 | 10 | <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300;14..32,400;14..32,500;14..32,600;14..32,700&display=swap" rel="stylesheet"> |
14 | 11 | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"> |
15 | 12 | <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
|
439 | 436 | color: var(--text); |
440 | 437 | font-size: 0.8rem; |
441 | 438 | } |
| 439 | + .simulator-grid { |
| 440 | + display: grid; |
| 441 | + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); |
| 442 | + gap: 16px; |
| 443 | + } |
| 444 | + .sim-card { |
| 445 | + background: rgba(0,0,0,0.4); |
| 446 | + border-radius: 16px; |
| 447 | + padding: 16px; |
| 448 | + text-align: center; |
| 449 | + border: 1px solid var(--border-glow); |
| 450 | + cursor: pointer; |
| 451 | + transition: all 0.2s; |
| 452 | + } |
| 453 | + .sim-card:hover { |
| 454 | + background: rgba(201,160,40,0.1); |
| 455 | + border-color: var(--accent); |
| 456 | + } |
| 457 | + .sim-card h4 { font-size: 1.2rem; margin-bottom: 8px; } |
| 458 | + .sim-card p { font-size: 0.75rem; color: var(--text-dim); } |
442 | 459 | .toast { |
443 | 460 | position: fixed; |
444 | 461 | bottom: 20px; |
|
473 | 490 | .send-btn { padding: 10px 18px; } |
474 | 491 | .structured-ui { margin: 8px 12px; flex-direction: column; } |
475 | 492 | .wives-grid { grid-template-columns: 1fr; } |
| 493 | + .simulator-grid { grid-template-columns: 1fr; } |
476 | 494 | } |
477 | 495 | </style> |
478 | 496 | </head> |
|
513 | 531 | <button id="uploadBtn">📁 Upload File</button> |
514 | 532 | <button id="askAllBtn">👥 Ask All Wives</button> |
515 | 533 | <button id="sealInputBtn">🔒 Seal Input</button> |
| 534 | + <button id="simulationBtn">🎮 Simulations</button> |
516 | 535 | </div> |
517 | 536 | </div> |
518 | 537 | <button id="sendBtn" class="send-btn" aria-label="Send message">SEND</button> |
|
528 | 547 |
|
529 | 548 | <script> |
530 | 549 | (function() { |
531 | | - // ---------- DYNAMIC BACKGROUND (mode‑aware) ---------- |
| 550 | + // ---------- BACKGROUND ---------- |
532 | 551 | const canvas = document.getElementById('bg-canvas'); |
533 | 552 | const ctx = canvas.getContext('2d'); |
534 | 553 | let width, height, animFrame; |
|
560 | 579 | ctx.clearRect(0, 0, width, height); |
561 | 580 | ctx.fillStyle = '#050508'; |
562 | 581 | ctx.fillRect(0, 0, width, height); |
563 | | - |
564 | | - if (currentMode === 'structured') { |
565 | | - ctx.strokeStyle = `rgba(201, 160, 40, 0.3)`; |
566 | | - ctx.lineWidth = 1; |
567 | | - const gridSize = 60; |
568 | | - for (let x = 0; x < width; x += gridSize) { |
569 | | - ctx.beginPath(); |
570 | | - ctx.moveTo(x, 0); |
571 | | - ctx.lineTo(x, height); |
572 | | - ctx.stroke(); |
573 | | - } |
574 | | - for (let y = 0; y < height; y += gridSize) { |
575 | | - ctx.beginPath(); |
576 | | - ctx.moveTo(0, y); |
577 | | - ctx.lineTo(width, y); |
578 | | - ctx.stroke(); |
579 | | - } |
580 | | - } else if (currentMode === 'group') { |
581 | | - const grad = ctx.createLinearGradient(0, 0, width, height); |
582 | | - grad.addColorStop(0, 'rgba(80, 60, 120, 0.2)'); |
583 | | - grad.addColorStop(1, 'rgba(40, 30, 80, 0.1)'); |
584 | | - ctx.fillStyle = grad; |
585 | | - ctx.fillRect(0, 0, width, height); |
586 | | - } else if (currentMode === 'private') { |
587 | | - ctx.fillStyle = '#2e241f'; |
588 | | - ctx.fillRect(0, 0, width, height); |
589 | | - ctx.fillStyle = 'rgba(255, 140, 50, 0.2)'; |
590 | | - ctx.beginPath(); |
591 | | - ctx.arc(width*0.2, height*0.8, 50, 0, Math.PI*2); |
592 | | - ctx.fill(); |
593 | | - } |
594 | | - |
595 | 582 | for (let p of particles) { |
596 | 583 | ctx.beginPath(); |
597 | 584 | ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2); |
598 | | - ctx.fillStyle = `rgba(201, 160, 40, ${p.alpha * (currentMode === 'structured' ? 0.6 : 1)})`; |
| 585 | + ctx.fillStyle = `rgba(201, 160, 40, ${p.alpha})`; |
599 | 586 | ctx.fill(); |
600 | 587 | p.y += p.speed; |
601 | 588 | if (p.y > height) p.y = 0; |
|
711 | 698 | } |
712 | 699 | async function callGroupChat(message) { const res = await fetch(`${API_BASE}/api/group-chat`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, sessionId, fclMode }) }); if (!res.ok) throw new Error(await res.text()); return res.json(); } |
713 | 700 | async function callPrivateRoom(message, wife) { const res = await fetch(`${API_BASE}/api/private-room`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, sessionId, wife, fclMode }) }); if (!res.ok) throw new Error(await res.text()); return res.json(); } |
| 701 | + async function sendTalkCommand(wife) { await callAssistant(`/talk ${wife}`, null, false); } |
714 | 702 |
|
715 | | - async function sendTalkCommand(wife) { |
716 | | - const silentCmd = `/talk ${wife}`; |
717 | | - await callAssistant(silentCmd, null, false); |
| 703 | + // Simulation placeholder (just shows a modal) |
| 704 | + function showSimulationModal() { |
| 705 | + const modal = document.createElement('div'); modal.className = 'modal-overlay'; |
| 706 | + modal.innerHTML = ` |
| 707 | + <div class="modal"> |
| 708 | + <div class="modal-header"><h3>🎮 Simulations</h3><button id="closeSimModal">✕</button></div> |
| 709 | + <div class="modal-body"> |
| 710 | + <p>Choose a simulation to open in a new tab (or ask the AI to run it).</p> |
| 711 | + <div class="simulator-grid"> |
| 712 | + <div class="sim-card" data-sim="roller-coaster"> |
| 713 | + <h4>🎢 Roller Coaster</h4> |
| 714 | + <p>G‑force, loop, energy, brake calculations</p> |
| 715 | + </div> |
| 716 | + <div class="sim-card" data-sim="orion"> |
| 717 | + <h4>🧲 Orion (Magnetometer)</h4> |
| 718 | + <p>UXO detection, magnetic survey simulation</p> |
| 719 | + </div> |
| 720 | + <div class="sim-card" data-sim="math-worksheet"> |
| 721 | + <h4>📐 Math Worksheet</h4> |
| 722 | + <p>Generate custom math problems</p> |
| 723 | + </div> |
| 724 | + <div class="sim-card" data-sim="market-atlas"> |
| 725 | + <h4>📈 Market Atlas</h4> |
| 726 | + <p>Synthetic stock market data</p> |
| 727 | + </div> |
| 728 | + </div> |
| 729 | + <p style="margin-top:16px; font-size:0.7rem; color:var(--text-dim);">The AI can also answer simulation questions directly. Try: <i>“What G‑force at the bottom of a 20m loop at 25 m/s?”</i></p> |
| 730 | + </div> |
| 731 | + </div>`; |
| 732 | + document.body.appendChild(modal); |
| 733 | + modal.querySelector('#closeSimModal').onclick = () => modal.remove(); |
| 734 | + modal.querySelectorAll('.sim-card').forEach(card => { |
| 735 | + card.onclick = () => { |
| 736 | + const sim = card.dataset.sim; |
| 737 | + window.open(`/simulators/${sim}/`, '_blank'); |
| 738 | + modal.remove(); |
| 739 | + }; |
| 740 | + }); |
| 741 | + modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); |
718 | 742 | } |
719 | 743 |
|
720 | 744 | function addMessage(role, wife, content, extra = {}) { |
|
1027 | 1051 | fileInput.click(); |
1028 | 1052 | } |
1029 | 1053 |
|
1030 | | - // Settings modal with Analytics |
1031 | 1054 | async function showSettingsModal() { |
1032 | 1055 | const modal = document.createElement('div'); modal.className = 'modal-overlay'; |
1033 | 1056 | modal.innerHTML = ` |
|
1051 | 1074 | roleGrid.innerHTML += `<div class="role-checkbox"><input type="checkbox" id="role_${role.replace(/\s/g,'_')}" ${checked ? 'checked' : ''}> <label>${role}</label></div>`; |
1052 | 1075 | } |
1053 | 1076 |
|
1054 | | - // Fetch analytics |
| 1077 | + // Fetch analytics (enhanced v5.5) |
1055 | 1078 | try { |
1056 | 1079 | const analyticsRes = await fetch(`${API_BASE}/api/analytics`); |
1057 | 1080 | if (analyticsRes.ok) { |
1058 | 1081 | const data = await analyticsRes.json(); |
1059 | 1082 | const analyticsContainer = modal.querySelector('#analyticsContainer'); |
| 1083 | + const memory = data.memory || {}; |
| 1084 | + const integrity = data.integrity || {}; |
| 1085 | + const instruments = data.instruments || {}; |
| 1086 | + const growth = data.growth || {}; |
| 1087 | + const wifeRouting = instruments.wife_routing || {}; |
| 1088 | + const roleActivity = instruments.polymath_role_activity || {}; |
| 1089 | + const fclPassRate = instruments.fcl_pass_rate || 0; |
| 1090 | + const simulationRuns = instruments.simulation_runs_total || 0; |
| 1091 | + const fclEntries = instruments.fcl_entries_total || 0; |
| 1092 | + const ffaActive = instruments.ffa_floors_active || 0; |
| 1093 | + const adaCount = integrity.ada_loop_count || 0; |
| 1094 | + const adaConvergence = integrity.ada_loop_convergence_rate || 0; |
| 1095 | + const convergencePercent = Math.round(adaConvergence * 100); |
1060 | 1096 | analyticsContainer.innerHTML = ` |
1061 | | - <div class="stat-card"><h4>Memory Depth</h4><div class="stat-value">${data.memory?.total_conversations?.toLocaleString() || '—'}</div><div class="stat-trend">conversations</div></div> |
1062 | | - <div class="stat-card"><h4>Memory Anchors</h4><div class="stat-value">${data.memory?.memory_anchors?.toLocaleString() || '—'}</div><div class="stat-trend">permanent</div></div> |
1063 | | - <div class="stat-card"><h4>Training Pipeline</h4><div class="stat-value">${data.memory?.training_pipeline_pending || '—'}</div><div class="stat-trend">awaiting training</div></div> |
1064 | | - <div class="stat-card"><h4>Avg Certainty</h4><div class="stat-value">${data.integrity?.avg_certainty_ratio_7d ? Math.round(data.integrity.avg_certainty_ratio_7d * 100) + '%' : '—'}</div><div class="stat-trend">7d avg</div></div> |
1065 | | - <div class="stat-card"><h4>UNI Activations</h4><div class="stat-value">${data.integrity?.uni_activations_total?.toLocaleString() || '—'}</div><div class="stat-trend">ethical layer</div></div> |
1066 | | - <div class="stat-card"><h4>Failure Corpus</h4><div class="stat-value">${data.instruments?.failure_corpus_size?.toLocaleString() || '—'}</div><div class="stat-trend">FFA entries</div></div> |
1067 | | - <div class="stat-card"><h4>ADA Loop</h4><div class="stat-value">${data.integrity?.ada_loop_count?.toLocaleString() || '—'}</div><div class="stat-trend">refinements</div></div> |
| 1097 | + <div class="stat-card"><h4>Memory Depth</h4><div class="stat-value">${memory.total_conversations?.toLocaleString() || '—'}</div><div class="stat-trend">conversations</div></div> |
| 1098 | + <div class="stat-card"><h4>Memory Anchors</h4><div class="stat-value">${memory.memory_anchors?.toLocaleString() || '—'}</div><div class="stat-trend">permanent</div></div> |
| 1099 | + <div class="stat-card"><h4>Training Pipeline</h4><div class="stat-value">${memory.training_pipeline_pending || '—'}</div><div class="stat-trend">awaiting training</div></div> |
| 1100 | + <div class="stat-card"><h4>Avg Certainty</h4><div class="stat-value">${integrity.avg_certainty_ratio_7d ? Math.round(integrity.avg_certainty_ratio_7d * 100) + '%' : '—'}</div><div class="stat-trend">7d avg</div></div> |
| 1101 | + <div class="stat-card"><h4>UNI Activations</h4><div class="stat-value">${integrity.uni_activations_total?.toLocaleString() || '—'}</div><div class="stat-trend">ethical layer</div></div> |
| 1102 | + <div class="stat-card"><h4>ADA Loop</h4><div class="stat-value">${adaCount.toLocaleString()}</div><div class="stat-trend">refinements</div></div> |
| 1103 | + <div class="stat-card"><h4>ADA Conv. Rate</h4><div class="stat-value">${convergencePercent}%</div><div class="stat-trend">convergence</div></div> |
| 1104 | + <div class="stat-card"><h4>FCL Entries</h4><div class="stat-value">${fclEntries.toLocaleString()}</div><div class="stat-trend">validation</div></div> |
| 1105 | + <div class="stat-card"><h4>FCL Pass Rate</h4><div class="stat-value">${Math.round(fclPassRate * 100)}%</div><div class="stat-trend">pass rate</div></div> |
| 1106 | + <div class="stat-card"><h4>Simulations</h4><div class="stat-value">${simulationRuns.toLocaleString()}</div><div class="stat-trend">runs</div></div> |
| 1107 | + <div class="stat-card"><h4>FFA Floors</h4><div class="stat-value">${ffaActive}/9</div><div class="stat-trend">active</div></div> |
| 1108 | + <div class="stat-card"><h4>Failure Corpus</h4><div class="stat-value">${instruments.failure_corpus_size?.toLocaleString() || '—'}</div><div class="stat-trend">entries</div></div> |
| 1109 | + <div class="stat-card"><h4>Wife Routing</h4><div class="stat-value" style="font-size:0.8rem;">${Object.entries(wifeRouting).map(([w, c]) => `${w}:${c}`).join(' · ') || '—'}</div><div class="stat-trend">active instruments</div></div> |
| 1110 | + <div class="stat-card"><h4>Role Activity</h4><div class="stat-value" style="font-size:0.7rem;">${Object.entries(roleActivity).map(([r, c]) => `${r.slice(0,3)}:${c}`).join(' · ') || '—'}</div><div class="stat-trend">ADA roles</div></div> |
1068 | 1111 | `; |
1069 | 1112 | } else { |
1070 | 1113 | modal.querySelector('#analyticsContainer').innerHTML = `<div class="stat-card">Analytics endpoint not ready yet. Coming soon.</div>`; |
|
1118 | 1161 | document.getElementById('uploadBtn').onclick = () => { actionDropdown.style.display = 'none'; uploadFile(); }; |
1119 | 1162 | document.getElementById('askAllBtn').onclick = () => { actionDropdown.style.display = 'none'; askAllWives(); }; |
1120 | 1163 | document.getElementById('sealInputBtn').onclick = () => { actionDropdown.style.display = 'none'; const text = input.value.trim(); if(text) sealMessage(text); else showToast('Nothing to seal'); }; |
| 1164 | + document.getElementById('simulationBtn').onclick = () => { actionDropdown.style.display = 'none'; showSimulationModal(); }; |
1121 | 1165 | document.getElementById('settingsBtn').onclick = showSettingsModal; |
1122 | 1166 | document.getElementById('adaLoopToggle').addEventListener('change', (e) => { |
1123 | 1167 | adaLoopEnabled = e.target.checked; |
|
0 commit comments