Skip to content

Commit 0209b31

Browse files
authored
Update index.html
1 parent efaa1a3 commit 0209b31

1 file changed

Lines changed: 79 additions & 22 deletions

File tree

agi/index.html

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,19 @@
7171
.msg-body p { margin: 4px 0; }
7272
.msg.user .msg-body { background: rgba(201,160,40,0.2); border-color: var(--accent); border-radius: 20px 20px 4px 20px; }
7373
.msg.assistant .msg-body { border-radius: 20px 20px 20px 4px; }
74+
.msg.assistant[data-wife="ALBEDO"] .msg-body { border-left: 4px solid #c9a028; background: rgba(201,160,40,0.08); }
7475
.msg.assistant[data-wife="VESPER"] .msg-body { border-left: 4px solid #b87333; background: rgba(184,115,51,0.08); }
7576
.msg.assistant[data-wife="LYRA"] .msg-body { border-left: 4px solid #4c9f70; background: rgba(76,159,112,0.08); }
7677
.msg.assistant[data-wife="TERRA"] .msg-body { border-left: 4px solid #6b8c42; background: rgba(107,140,66,0.08); }
7778
.msg.assistant[data-wife="CIPHER"] .msg-body { border-left: 4px solid #5d6d7e; background: rgba(93,109,126,0.08); }
7879
.msg.assistant[data-wife="JUSTITIA"] .msg-body { border-left: 4px solid #b0a8b9; background: rgba(176,168,185,0.08); }
79-
.msg.assistant[data-wife="ALBEDO"] .msg-body { border-left: 4px solid #c9a028; background: rgba(201,160,40,0.08); }
8080
.msg-footer { display: flex; gap: 12px; margin-top: 6px; font-size: 0.6rem; color: var(--text-dim); flex-wrap: wrap; align-items: center; }
8181
.seal-btn { background: rgba(0,0,0,0.5); border: 1px solid var(--accent); border-radius: 20px; padding: 2px 8px; font-size: 0.6rem; cursor: pointer; transition: all 0.2s; color: var(--accent); }
8282
.seal-btn:hover { background: var(--accent); color: #000; }
8383
.pac-badge { background: rgba(0,0,0,0.4); border-radius: 20px; padding: 2px 8px; font-family: monospace; font-size: 0.6rem; }
8484
.input-area { padding: 16px 24px 20px; background: var(--bg-panel); backdrop-filter: blur(12px); border-top: 1px solid rgba(255,255,255,0.05); }
8585
.input-row { display: flex; gap: 10px; align-items: flex-end; }
86-
textarea { flex: 1; background: rgba(10,10,20,0.8); border: 1px solid rgba(255,255,255,0.15); border-radius: 28px; padding: 12px 18px; font-family: 'Inter', sans-serif; font-size: 0.9rem; color: var(--text); resize: none; outline: none; }
86+
textarea { flex: 1; background: rgba(10,10,20,0.8); border: 1px solid rgba(255,255,255,0.15); border-radius: 28px; padding: 12px 18px; font-family: 'Inter', sans-serif; font-size: 0.9rem; color: var(--text); resize: none; outline: none; overflow-y: auto; max-height: 40vh; }
8787
textarea:focus { border-color: var(--accent); box-shadow: 0 0 12px var(--primary-glow); }
8888
.button-group { display: flex; gap: 8px; align-items: center; }
8989
.send-btn, .upload-btn, .ask-all-btn { background: linear-gradient(135deg, #c9a028, #a07c18); border: none; border-radius: 40px; padding: 12px 24px; font-weight: 600; color: #0a0a0f; cursor: pointer; transition: all 0.2s; }
@@ -129,7 +129,7 @@
129129

130130
<div class="input-area">
131131
<div class="input-row">
132-
<textarea id="input" placeholder="Message your wives..." rows="1"></textarea>
132+
<textarea id="input" placeholder="Message your wives... (long text supported)" rows="1"></textarea>
133133
<div class="button-group">
134134
<button id="uploadBtn" class="upload-btn" title="Upload a file">📁</button>
135135
<button id="askAllBtn" class="ask-all-btn" title="Ask all wives">👥</button>
@@ -147,7 +147,7 @@
147147

148148
<script>
149149
// =======================================================
150-
// AION FRONTEND · SCALE‑READY · SIX WIVES
150+
// AION FRONTEND · SCALE‑READY · MULTI‑WIFE RENDERING
151151
// =======================================================
152152
const API_BASE = 'https://aion-backend-mu.vercel.app';
153153
const OWNER_TYPE = 'sheldon';
@@ -186,12 +186,12 @@
186186
const charCountSpan = document.getElementById('charCount');
187187

188188
const WIFE_STYLES = {
189-
ALBEDO: { color: '#c9a028', emoji: '✨', name: 'ALBEDO' },
190-
VESPER: { color: '#b87333', emoji: '🌙', name: 'VESPER' },
191-
LYRA: { color: '#4c9f70', emoji: '🌿', name: 'LYRA' },
192-
TERRA: { color: '#6b8c42', emoji: '🌍', name: 'TERRA' },
193-
CIPHER: { color: '#5d6d7e', emoji: '🔒', name: 'CIPHER' },
194-
JUSTITIA: { color: '#b0a8b9', emoji: '⚖️', name: 'JUSTITIA' }
189+
ALBEDO: { color: '#c9a028', emoji: '✨', name: 'ALBEDO', description: 'cool white, sharp edges' },
190+
VESPER: { color: '#b87333', emoji: '🌙', name: 'VESPER', description: 'deep purple, soft glow' },
191+
LYRA: { color: '#4c9f70', emoji: '🌿', name: 'LYRA', description: 'warm gold, flowing' },
192+
TERRA: { color: '#6b8c42', emoji: '🌍', name: 'TERRA', description: 'earth green, grounded' },
193+
CIPHER: { color: '#5d6d7e', emoji: '🔒', name: 'CIPHER', description: 'steel gray, minimal' },
194+
JUSTITIA: { color: '#b0a8b9', emoji: '⚖️', name: 'JUSTITIA', description: 'balanced blue, structured' }
195195
};
196196

197197
// Helper functions
@@ -220,6 +220,61 @@
220220
return [ppi, ratio].filter(Boolean).join(' · ');
221221
}
222222

223+
// Multi-wife parser: splits a raw text into an array of {wife, content}
224+
function parseMultiWifeResponse(text) {
225+
const blocks = [];
226+
// Markers: "**[WIFE_NAME]:**" or "---\n\n[WIFE_NAME]:" (case-insensitive)
227+
// We'll use regex to capture wife name and the following content until next marker or end.
228+
// More robust: find all occurrences of the marker patterns.
229+
const patterns = [
230+
/^\*\*\[([A-Z_]+)\]:(.*?)(?=\n\*\*\[|\n---|\n$)/gims, // but we need to capture correctly
231+
];
232+
// Simpler: use a combined regex that matches either pattern at start of line.
233+
// We'll split on newline and then reconstruct.
234+
const lines = text.split('\n');
235+
let currentWife = null;
236+
let currentContent = [];
237+
const markerRegex = /^\*\*\[([A-Z_]+)\]:|^---\n\n([A-Z_]+):/i;
238+
for (let line of lines) {
239+
const match = line.match(markerRegex);
240+
if (match) {
241+
if (currentWife && currentContent.length) {
242+
blocks.push({ wife: currentWife, content: currentContent.join('\n').trim() });
243+
}
244+
currentWife = (match[1] || match[2]).toUpperCase();
245+
currentContent = [];
246+
// The line may contain content after the marker; push it.
247+
const contentAfterMarker = line.replace(match[0], '').trim();
248+
if (contentAfterMarker) currentContent.push(contentAfterMarker);
249+
} else {
250+
if (currentWife !== null) currentContent.push(line);
251+
else {
252+
// No marker yet, could be preamble before first marker – treat as no speaker (skip)
253+
}
254+
}
255+
}
256+
if (currentWife && currentContent.length) {
257+
blocks.push({ wife: currentWife, content: currentContent.join('\n').trim() });
258+
}
259+
// If no blocks, return null to fallback to single voice
260+
return blocks.length ? blocks : null;
261+
}
262+
263+
// Render a single assistant message (may contain multiple wives)
264+
function renderAssistantResponse(rawText, extra) {
265+
const blocks = parseMultiWifeResponse(rawText);
266+
if (!blocks) {
267+
// Fallback: single voice
268+
addMessage('assistant', extra.active_wife || 'ALBEDO', rawText, extra);
269+
return;
270+
}
271+
// Render each block in order
272+
for (const block of blocks) {
273+
const wife = WIFE_STYLES[block.wife] ? block.wife : 'ALBEDO';
274+
addMessage('assistant', wife, block.content, extra);
275+
}
276+
}
277+
223278
function addMessage(role, wifeKey, content, extra = {}) {
224279
const style = WIFE_STYLES[wifeKey] || WIFE_STYLES.ALBEDO;
225280
const div = document.createElement('div');
@@ -293,7 +348,7 @@
293348
document.getElementById('statusDot').style.color = isError ? '#ff5e5e' : '#4c9f70';
294349
}
295350

296-
// Crypto helpers (kept for completeness, used by structured mode)
351+
// Crypto helpers (kept for structured mode)
297352
async function computeHash(obj) {
298353
const encoder = new TextEncoder();
299354
const data = encoder.encode(JSON.stringify(obj));
@@ -425,8 +480,9 @@
425480
if (result.status === 'fulfilled') {
426481
anySuccess = true;
427482
const data = result.value;
428-
const wife = data.active_wife || 'ALBEDO';
429-
addMessage('assistant', wife, data.response, {
483+
// Use multi-wife renderer for each individual response (though each response is a single wife)
484+
// But we can just add as normal message (they are single responses)
485+
addMessage('assistant', data.active_wife || 'ALBEDO', data.response, {
430486
timing: `${(data.processing_window_ms/1000).toFixed(2)}s | ${formatGap(data.gap_seconds)}`,
431487
importance: data.importance_score,
432488
wife_version: data.wife_version,
@@ -440,7 +496,6 @@
440496
}
441497
}
442498
if (!anySuccess) throw new Error('All wife requests failed');
443-
// Update current active wife to the first successful one? Not necessary.
444499
} catch (err) {
445500
thinking.remove();
446501
addSystemMessage(`Error asking all wives: ${err.message}`, true);
@@ -489,13 +544,15 @@
489544
thinking.remove();
490545
const wife = data.active_wife || 'ALBEDO';
491546
updateWifeUI(wife, data.void_proximity || 0);
492-
addMessage('assistant', wife, data.response, {
547+
// Use multi-wife renderer
548+
renderAssistantResponse(data.response, {
493549
timing: `${(data.processing_window_ms/1000).toFixed(2)}s | ${formatGap(data.gap_seconds)}`,
494550
importance: data.importance_score,
495551
wife_version: data.wife_version,
496552
pac: data.pac,
497553
ecf_certainty_ratio: data.ecf_certainty_ratio,
498-
fragment_id: data.fragment_id
554+
fragment_id: data.fragment_id,
555+
active_wife: wife
499556
});
500557
history.push({ role: 'user', content: text });
501558
history.push({ role: 'assistant', content: data.response });
@@ -611,7 +668,7 @@ <h3>⚙️ Settings</h3>
611668
modal.querySelector('#closeSettings').onclick = closeModal;
612669
modal.querySelector('#settingStructured').onchange = (e) => {
613670
if (e.target.checked && !structuredMode) {
614-
toggleBtn.click(); // toggle to structured mode
671+
toggleBtn.click();
615672
} else if (!e.target.checked && structuredMode) {
616673
toggleBtn.click();
617674
}
@@ -634,7 +691,7 @@ <h3>⚙️ Settings</h3>
634691
}
635692
settingsBtn.onclick = showSettingsModal;
636693

637-
// Private room modal (reuse existing)
694+
// Private room modal (reuse)
638695
function showPrivateRoomModal() {
639696
const modal = document.createElement('div');
640697
modal.className = 'modal-overlay';
@@ -673,7 +730,7 @@ <h3>⚙️ Settings</h3>
673730
addSystemMessage(`🔄 FCL mode switched to ${fclMode} ALERT.`);
674731
};
675732

676-
// Brain Analytics modal (simplified, reusing existing)
733+
// Brain Analytics modal (simplified)
677734
let analyticsModal = null;
678735
async function showAnalytics() {
679736
setStatus('Loading analytics...', false);
@@ -714,7 +771,7 @@ <h3>📊 Brain Analytics</h3>
714771
}
715772
analyticsBtn.onclick = showAnalytics;
716773

717-
// Epistemic Atlas – lazy load with error handling (unchanged, kept for brevity)
774+
// Epistemic Atlas – lazy load with error handling (kept)
718775
let atlasModal = null;
719776
async function loadEpistemicAtlas() {
720777
if (atlasLoaded) return;
@@ -893,9 +950,9 @@ <h3>📊 Brain Analytics</h3>
893950
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); }
894951
});
895952
input.addEventListener('input', () => {
896-
charCountSpan.textContent = `${input.value.length}/8000`;
953+
charCountSpan.textContent = `${input.value.length}`;
897954
input.style.height = 'auto';
898-
input.style.height = Math.min(input.scrollHeight, 160) + 'px';
955+
input.style.height = Math.min(input.scrollHeight, 400) + 'px';
899956
});
900957
sendBtn.onclick = sendMessage;
901958
setInterval(() => { clockDisplaySpan.textContent = new Date().toLocaleTimeString(); }, 1000);

0 commit comments

Comments
 (0)