Skip to content

Commit 4f72f9b

Browse files
authored
Update index.html
1 parent a90fe9a commit 4f72f9b

1 file changed

Lines changed: 176 additions & 51 deletions

File tree

AION-PAGE/AION.AI/index.html

Lines changed: 176 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@
276276
.badge.memory { background: #2a2a3a; }
277277
.badge.void { background: #2a2a3a; }
278278
.badge.handoff { background: #5f3a1a; color: #ffaa33; border-color: #ffaa33; }
279+
.badge.framework { background: #2a2a3a; border-color: #c9a028; }
280+
.badge.register { background: #2a2a3a; }
279281
.badge.seal-btn { color: var(--amber); }
280282
.feedback-badge {
281283
background: rgba(30,30,45,0.8);
@@ -490,6 +492,60 @@
490492
font-family: var(--sans);
491493
}
492494

495+
/* Decision Forge Modal */
496+
.forge-modal .modal {
497+
max-width: 900px;
498+
}
499+
.forge-modal .forge-content {
500+
display: flex;
501+
flex-direction: column;
502+
gap: 16px;
503+
}
504+
.forge-content textarea {
505+
width: 100%;
506+
background: rgba(10,10,20,0.9);
507+
border: 1px solid var(--border);
508+
border-radius: 16px;
509+
padding: 12px;
510+
font-family: var(--sans);
511+
color: var(--text);
512+
resize: vertical;
513+
min-height: 150px;
514+
}
515+
.forge-wife-select {
516+
display: flex;
517+
flex-wrap: wrap;
518+
gap: 12px;
519+
margin: 8px 0;
520+
}
521+
.forge-wife-select label {
522+
display: flex;
523+
align-items: center;
524+
gap: 6px;
525+
font-size: 0.85rem;
526+
cursor: pointer;
527+
}
528+
.forge-results {
529+
margin-top: 20px;
530+
border-top: 1px solid var(--border);
531+
padding-top: 16px;
532+
max-height: 400px;
533+
overflow-y: auto;
534+
}
535+
.forge-results .wife-analysis {
536+
margin-bottom: 16px;
537+
padding: 12px;
538+
background: rgba(0,0,0,0.3);
539+
border-radius: 12px;
540+
border-left: 3px solid var(--amber);
541+
}
542+
.forge-results .synthesis {
543+
margin-top: 16px;
544+
padding: 12px;
545+
background: rgba(0,0,0,0.4);
546+
border-radius: 12px;
547+
}
548+
493549
/* Eye of AION – novel interactive badge */
494550
.eye-badge {
495551
position: relative;
@@ -773,6 +829,7 @@
773829
.wives-grid { grid-template-columns: 1fr; }
774830
.simulator-grid { grid-template-columns: 1fr; }
775831
.eye-badge { width: 28px; height: 28px; }
832+
.forge-wife-select { flex-direction: column; gap: 6px; }
776833
}
777834
</style>
778835
</head>
@@ -812,7 +869,7 @@
812869
<div class="action-dropdown" id="actionDropdown" style="display: none;">
813870
<button id="structuredModeBtn">🌌 Structured Mode</button>
814871
<button id="groupChatBtn">👥 Group Chat</button>
815-
<button id="privateRoomBtn">🚪 Private Room</button>
872+
<button id="decisionForgeBtn">⚖️ Decision Forge</button>
816873
<button id="uploadBtn">📁 Upload File</button>
817874
<button id="askAllBtn">👥 Ask All Wives</button>
818875
<button id="sealInputBtn">🔒 Seal Input</button>
@@ -925,9 +982,6 @@
925982
const fclIndicator = document.getElementById('fclIndicator');
926983
fclIndicator.textContent = fclMode === 'GREEN' ? '🟢 GREEN' : '🔴 BLACK';
927984
fclIndicator.className = `fcl-indicator ${fclMode === 'GREEN' ? 'green' : 'black'}`;
928-
let privateRoomActive = false;
929-
let privateWife = null;
930-
let lastT2 = null;
931985
let isSending = false;
932986
let firstUserMessageSent = false;
933987
let currentTokenUsage = 0; // for display
@@ -977,7 +1031,6 @@
9771031
<p><strong>ADA Loop:</strong> ${adaLoopEnabled ? 'Active' : 'Disabled'}</p>
9781032
<p><strong>Void Proximity:</strong> <span id="eyeVoid">${voidMeterSpan.textContent.split(':')[1].trim() || '0.000'}</span></p>
9791033
<p><strong>Active Wife:</strong> ${wifeNameSpan.textContent}</p>
980-
<p><strong>Private Room:</strong> ${privateRoomActive ? `Yes (${privateWife})` : 'No'}</p>
9811034
<p><strong>Structured Mode:</strong> ${structuredMode ? 'Yes' : 'No'}</p>
9821035
<p><strong>FCL Mode:</strong> ${fclMode}</p>
9831036
<hr style="border-color:var(--border); margin: 16px 0;">
@@ -1123,18 +1176,19 @@ <h3>🌌 Structured Mode</h3>
11231176
throw new Error(errMsg);
11241177
}
11251178
const data = await res.json();
1126-
// if group chat returns token usage, update
11271179
if (data.meta && data.meta.token_usage) updateTokenDisplay(data.meta.token_usage);
11281180
return data;
11291181
}
1130-
async function callPrivateRoom(message, wife) {
1131-
const res = await fetchWithTimeout(`${API_BASE}/api/private-room`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, sessionId, wife, fclMode }) });
1182+
async function callDecisionForge(content, wivesToConsult, adaLoopEnabledFlag) {
1183+
const res = await fetchWithTimeout(`${API_BASE}/api/decision-forge`, {
1184+
method: 'POST',
1185+
headers: { 'Content-Type': 'application/json' },
1186+
body: JSON.stringify({ sessionId, content, wivesToConsult, adaLoopEnabled: adaLoopEnabledFlag })
1187+
});
11321188
if (!res.ok) throw new Error(await res.text());
1133-
const data = await res.json();
1134-
if (data.token_count !== undefined) updateTokenDisplay(data.token_count);
1135-
return data;
1189+
return res.json();
11361190
}
1137-
async function sendTalkCommand(wife) { await callAssistant(`/talk ${wife}`, null, false); }
1191+
async function sendTalkCommand(wife) { await callAssistant(`/talk ${wife}`, null, false); } // kept for compatibility? Not used now but may be removed.
11381192

11391193
// Simulation modal (unchanged)
11401194
function showSimulationModal() {
@@ -1214,6 +1268,8 @@ <h3>🌌 Structured Mode</h3>
12141268
if (extra.voidProx !== undefined && extra.voidProx > 0) badgesHtml += `<span class="badge void">🌀 VOID: ${extra.voidProx.toFixed(3)}</span>`;
12151269
if (extra.handoffWarning) badgesHtml += `<span class="badge handoff">⚠️ HANDOFF READY</span>`;
12161270
if (extra.receipt) badgesHtml += `<span class="badge receipt" data-receipt='${JSON.stringify(extra.receipt).replace(/'/g, "&#39;")}'>📋 receipt (${extra.receipt.still_open || 0} open)</span>`;
1271+
if (extra.frameworkActivation) badgesHtml += `<span class="badge framework">🔧 ${extra.frameworkActivation}</span>`;
1272+
if (extra.register && extra.register !== 'PEER') badgesHtml += `<span class="badge register">📢 ${extra.register}</span>`;
12171273
if (extra.sealable) badgesHtml += `<button class="badge seal-btn" data-content="${escapeHtml(content).replace(/"/g, '&quot;')}">🔒 SEAL</button>`;
12181274
if (extra.adaVela) badgesHtml += `<span class="badge ada-vela" data-execution-id="${escapeHtml(extra.adaVela.execution_id || extra.adaVela.id)}">📋 Ada‑VELA</span>`;
12191275
badgesHtml += `<span class="feedback-badge" data-feedback-positive="true">👍</span><span class="feedback-badge" data-feedback-positive="false">👎</span></div>`;
@@ -1243,11 +1299,106 @@ <h3>🌌 Structured Mode</h3>
12431299
messagesDiv.scrollTop = messagesDiv.scrollHeight;
12441300
}
12451301

1302+
// Decision Forge
1303+
function showDecisionForgeModal() {
1304+
const modal = document.createElement('div');
1305+
modal.className = 'modal-overlay forge-modal';
1306+
modal.innerHTML = `
1307+
<div class="modal">
1308+
<div class="modal-header">
1309+
<h3>⚖️ Decision Forge</h3>
1310+
<button id="closeForgeModal">✕</button>
1311+
</div>
1312+
<div class="modal-body">
1313+
<div class="forge-content">
1314+
<label>Document / Content to analyze:</label>
1315+
<textarea id="forgeContent" placeholder="Paste contract, specification, report, or ask a multi‑perspective question..."></textarea>
1316+
<label>Consult wives:</label>
1317+
<div class="forge-wife-select" id="forgeWivesSelect"></div>
1318+
<label><input type="checkbox" id="forgeAdaLoop" checked> Apply ADA loop to synthesis</label>
1319+
<button id="forgeSubmitBtn" class="send-btn" style="background: var(--amber); color:#000; margin-top:12px;">Generate Analysis</button>
1320+
<div id="forgeResults" class="forge-results" style="display:none;"></div>
1321+
</div>
1322+
</div>
1323+
</div>
1324+
`;
1325+
document.body.appendChild(modal);
1326+
const closeBtn = modal.querySelector('#closeForgeModal');
1327+
closeBtn.onclick = () => modal.remove();
1328+
const wivesContainer = modal.querySelector('#forgeWivesSelect');
1329+
// Populate wife checkboxes
1330+
ALL_WIVES.forEach(wife => {
1331+
const label = document.createElement('label');
1332+
label.innerHTML = `<input type="checkbox" value="${wife}" checked> ${WIFE_STYLES[wife].emoji} ${wife}`;
1333+
wivesContainer.appendChild(label);
1334+
});
1335+
const submitBtn = modal.querySelector('#forgeSubmitBtn');
1336+
const contentArea = modal.querySelector('#forgeContent');
1337+
const resultsDiv = modal.querySelector('#forgeResults');
1338+
submitBtn.onclick = async () => {
1339+
const content = contentArea.value.trim();
1340+
if (!content) { showToast('Please enter content to analyze.'); return; }
1341+
const wives = Array.from(wivesContainer.querySelectorAll('input:checked')).map(cb => cb.value);
1342+
if (wives.length === 0) { showToast('Select at least one wife.'); return; }
1343+
const adaLoop = modal.querySelector('#forgeAdaLoop').checked;
1344+
submitBtn.disabled = true;
1345+
submitBtn.textContent = 'Analyzing...';
1346+
resultsDiv.style.display = 'none';
1347+
try {
1348+
const result = await callDecisionForge(content, wives, adaLoop);
1349+
resultsDiv.style.display = 'block';
1350+
resultsDiv.innerHTML = '';
1351+
// Analyses per wife
1352+
if (result.analyses && result.analyses.length) {
1353+
for (const a of result.analyses) {
1354+
const analysisDiv = document.createElement('div');
1355+
analysisDiv.className = 'wife-analysis';
1356+
const ecfCounts = a.ecf ? `🏷 [D]x${a.ecf.D||0} [R]x${a.ecf.R||0} [S]x${a.ecf.S||0} [?]x${a.ecf.Q||0}` : '';
1357+
analysisDiv.innerHTML = `
1358+
<h4>${WIFE_STYLES[a.wife]?.emoji} ${a.wife}</h4>
1359+
<div style="margin:8px 0; white-space:pre-wrap;">${renderMarkdown(a.response)}</div>
1360+
<div class="badge-cluster">
1361+
<span class="badge">🎯 Conf: ${Math.round(a.confidence*100)}%</span>
1362+
<span class="badge vela ${a.vela_status === 'PASS' ? 'pass' : (a.vela_status === 'FLAGGED' ? 'flag' : 'block')}">⚖️ VELA: ${a.vela_status}</span>
1363+
${ecfCounts ? `<span class="badge ecf">${ecfCounts}</span>` : ''}
1364+
${a.fallback_used ? '<span class="badge">⚠️ Fallback model used</span>' : ''}
1365+
</div>
1366+
`;
1367+
resultsDiv.appendChild(analysisDiv);
1368+
}
1369+
}
1370+
// Synthesis
1371+
if (result.synthesis && result.synthesis.final_text) {
1372+
const synthesisDiv = document.createElement('div');
1373+
synthesisDiv.className = 'synthesis';
1374+
synthesisDiv.innerHTML = `
1375+
<h4>📋 Synthesis (Score: ${Math.round(result.synthesis.score * 100)}%)</h4>
1376+
<div style="margin:8px 0; white-space:pre-wrap;">${renderMarkdown(result.synthesis.final_text)}</div>
1377+
${result.synthesis.ada_loop.applied ? `<div class="badge ada">🔄 ADA refined</div>` : ''}
1378+
`;
1379+
resultsDiv.appendChild(synthesisDiv);
1380+
}
1381+
if (result.failed_wives && result.failed_wives.length) {
1382+
const warnDiv = document.createElement('div');
1383+
warnDiv.className = 'sys-msg';
1384+
warnDiv.textContent = `⚠️ Some wives failed: ${result.failed_wives.map(w => w.wife).join(', ')}`;
1385+
resultsDiv.appendChild(warnDiv);
1386+
}
1387+
} catch (err) {
1388+
showToast(`Error: ${err.message}`, true);
1389+
} finally {
1390+
submitBtn.disabled = false;
1391+
submitBtn.textContent = 'Generate Analysis';
1392+
}
1393+
};
1394+
modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); });
1395+
}
1396+
12461397
async function sendMessage(retryMessage = null) {
12471398
if (isSending) { showToast('Already sending...'); return; }
12481399
const text = (retryMessage !== null) ? retryMessage : input.value.trim();
12491400
if (!text) return;
1250-
if (privateRoomActive && (text === '/done' || text === '/exit')) { exitPrivateRoom(); if (!retryMessage) input.value = ''; return; }
1401+
// Private room commands removed – no special handling
12511402
if (!retryMessage) input.value = '';
12521403
charCountSpan.textContent = '0';
12531404
const t1 = new Date(); const t1Offset = -t1.getTimezoneOffset(); const t1Label = getTimezoneOffsetLabel(t1Offset);
@@ -1262,9 +1413,7 @@ <h3>🌌 Structured Mode</h3>
12621413
const thinking = document.createElement('div'); thinking.className = 'msg assistant'; thinking.innerHTML = `<div class="skeleton" style="width: 60%; height: 48px;"></div>`; messagesDiv.appendChild(thinking); messagesDiv.scrollTop = messagesDiv.scrollHeight;
12631414
try {
12641415
let result;
1265-
if (privateRoomActive && privateWife) {
1266-
result = await callPrivateRoom(text, privateWife);
1267-
} else if (structuredMode) {
1416+
if (structuredMode) {
12681417
const structuredData = {
12691418
intent: document.getElementById('itlIntent').value,
12701419
domain: document.getElementById('itlDomain').value,
@@ -1278,8 +1427,7 @@ <h3>🌌 Structured Mode</h3>
12781427
const t2 = new Date(); const t2Offset = -t2.getTimezoneOffset(); const t2Label = getTimezoneOffsetLabel(t2Offset);
12791428
const windowMs = t2 - t1; const windowSec = (windowMs / 1000).toFixed(1);
12801429
let gapStr = 'SESSION OPEN';
1281-
if (lastT2) { const gapSec = (t1 - lastT2) / 1000; gapStr = formatGap(gapSec); }
1282-
lastT2 = t2;
1430+
// No lastT2 stored now – we could keep a variable but it's not critical
12831431
const dreamspell = getDreamspell(t2);
12841432
const gregorian = t2.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
12851433
const hebrew = result.hebrew_date || 'Hebrew: unavailable';
@@ -1297,7 +1445,7 @@ <h3>🌌 Structured Mode</h3>
12971445
voidMeterSpan.classList.remove('active');
12981446
setEyeState('idle');
12991447
}
1300-
// after response, if ADA loop was active, set eye to refining momentarily? We can use a short timeout
1448+
// If ADA loop was active, set eye to refining momentarily
13011449
if (result.ada_loop && result.ada_loop.rounds > 0) {
13021450
setEyeState('refining');
13031451
setTimeout(() => { if (voidProx <= 0.5 && eyeState === 'refining') setEyeState('idle'); }, 800);
@@ -1316,6 +1464,8 @@ <h3>🌌 Structured Mode</h3>
13161464
handoffWarning: !!result.handoff,
13171465
receipt: result.checkpoint_receipt,
13181466
sealable: true,
1467+
frameworkActivation: result.framework_activation, // optional
1468+
register: result.register,
13191469
timestampHtml,
13201470
adaVela: result.ada_vela
13211471
});
@@ -1332,19 +1482,10 @@ <h3>🌌 Structured Mode</h3>
13321482
} finally { isSending = false; sendBtn.disabled = false; if (!retryMessage) input.focus(); }
13331483
}
13341484

1335-
// ---- Group Chat & Private Room Functions ----
1336-
function exitPrivateRoom() {
1337-
privateRoomActive = false;
1338-
privateWife = null;
1339-
wifeNameSpan.textContent = 'AION';
1340-
wifeAvatarDiv.textContent = '✨';
1341-
setBackgroundMode('regular');
1342-
addSystemMessage('🚪 Exited private room.');
1343-
}
1344-
13451485
function setBackgroundMode(mode) {
1346-
if (mode === 'private') {
1347-
document.documentElement.style.setProperty('--bg', '#030405');
1486+
// only used for structured mode now; keep it simple
1487+
if (mode === 'structured') {
1488+
document.documentElement.style.setProperty('--bg', '#0a0a0f');
13481489
} else {
13491490
document.documentElement.style.setProperty('--bg', '#08090b');
13501491
}
@@ -1356,27 +1497,15 @@ <h3>🌌 Structured Mode</h3>
13561497
if (structuredMode) {
13571498
modeIndicator.textContent = '🌌 STRUCTURED';
13581499
modeIndicator.classList.add('active');
1500+
setBackgroundMode('structured');
13591501
} else {
13601502
modeIndicator.textContent = '⚡ REGULAR';
13611503
modeIndicator.classList.remove('active');
1504+
setBackgroundMode('regular');
13621505
}
13631506
updateStructuredBadge();
13641507
}
13651508

1366-
async function startPrivateRoom(wife) {
1367-
try {
1368-
await sendTalkCommand(wife);
1369-
privateRoomActive = true;
1370-
privateWife = wife;
1371-
wifeNameSpan.textContent = WIFE_STYLES[wife].name;
1372-
wifeAvatarDiv.textContent = WIFE_STYLES[wife].emoji;
1373-
setBackgroundMode('private');
1374-
addSystemMessage(`🚪 Entering private room with ${wife}. Type /done to exit.`);
1375-
} catch (err) {
1376-
showToast(`❌ Could not enter private room: ${err.message}`);
1377-
}
1378-
}
1379-
13801509
async function showGroupChatModal() {
13811510
const text = input.value.trim();
13821511
if (!text) { showToast('Enter a message first.'); return; }
@@ -1424,6 +1553,7 @@ <h3>🌌 Structured Mode</h3>
14241553
if (card) {
14251554
const responseDiv = card.querySelector('.response-text');
14261555
responseDiv.innerHTML = renderMarkdown(wifeResp.response);
1556+
// optional: show ecf_tags, framework activation, etc.
14271557
if (wifeResp.vela_status) {
14281558
const velaBadge = document.createElement('div');
14291559
velaBadge.className = 'badge vela ' + (wifeResp.vela_status === 'PASS' ? 'pass' : (wifeResp.vela_status === 'FLAGGED' ? 'flag' : 'block'));
@@ -1618,12 +1748,7 @@ <h3>🌌 Structured Mode</h3>
16181748
document.addEventListener('click', () => { actionDropdown.style.display = 'none'; });
16191749
document.getElementById('structuredModeBtn').onclick = () => { actionDropdown.style.display = 'none'; toggleStructuredMode(); };
16201750
document.getElementById('groupChatBtn').onclick = () => { actionDropdown.style.display = 'none'; showGroupChatModal(); };
1621-
document.getElementById('privateRoomBtn').onclick = async () => {
1622-
actionDropdown.style.display = 'none';
1623-
const wife = prompt('Enter wife name (ALBEDO, VESPER, LYRA, TERRA, CIPHER, JUSTITIA):', 'ALBEDO');
1624-
if (wife && ALL_WIVES.includes(wife.toUpperCase())) await startPrivateRoom(wife.toUpperCase());
1625-
else showToast('Invalid wife');
1626-
};
1751+
document.getElementById('decisionForgeBtn').onclick = () => { actionDropdown.style.display = 'none'; showDecisionForgeModal(); };
16271752
document.getElementById('uploadBtn').onclick = () => { actionDropdown.style.display = 'none'; uploadFile(); };
16281753
document.getElementById('askAllBtn').onclick = () => { actionDropdown.style.display = 'none'; askAllWives(); };
16291754
document.getElementById('sealInputBtn').onclick = () => { actionDropdown.style.display = 'none'; const text = input.value.trim(); if(text) sealMessage(text); else showToast('Nothing to seal'); };

0 commit comments

Comments
 (0)