Add v2 rewrite: monorepo with desktop and web apps, shared packages, docs, and wireframes

This commit is contained in:
2026-05-14 13:13:21 -04:00
parent 6d7eed9230
commit 379c07b50c
49 changed files with 11607 additions and 0 deletions

322
wireframe/app.js Normal file
View File

@@ -0,0 +1,322 @@
// ─── Agent data ───
const agentInfo = {
cr: { name: 'Company Research Agent', status: 'Completed · 100%', action: 'Company overview complete' },
fm: { name: 'Financial Modeling Agent', status: 'Running · 62% complete', action: 'Building revenue schedule…' },
sf: { name: 'SEC Filings Agent', status: 'Running · 45% complete', action: 'Extracting segment data from 10-K…' },
ec: { name: 'Earnings Call Agent', status: 'Running · 78% complete', action: 'Summarizing Q2 FY25 call…' },
ci: { name: 'Competitive Intel Agent', status: 'Queued · Waiting for SEC Filings', action: 'Queued' },
va: { name: 'Valuation Agent', status: 'Queued · Waiting for Financial Modeling', action: 'Queued' },
rk: { name: 'Risk Agent', status: 'Idle', action: 'Idle' },
mw: { name: 'Memo Writing Agent', status: 'Idle', action: 'Idle' },
pa: { name: 'Presentation Agent', status: 'Idle', action: 'Idle' },
mn: { name: 'Monitoring Agent', status: 'Idle', action: 'Idle' },
sv: { name: 'Source Verification Agent', status: 'Idle', action: 'Idle' },
rt: { name: 'Red Team Agent', status: 'Idle', action: 'Idle' },
ex: { name: 'Export Agent', status: 'Idle', action: 'Idle' },
qa: { name: 'Model QA Agent', status: 'Idle', action: 'Idle' },
};
const activeAgents = ['sf', 'fm', 'ec'];
let carouselIdx = 0;
// ─── Screen switching ───
function switchScreen(id, btn) {
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
document.getElementById('screen-' + id).classList.add('active');
document.querySelectorAll('.screen-tabs button').forEach(b => b.classList.remove('active'));
if (btn && btn.classList) btn.classList.add('active');
// Show/hide ticker group on home vs other screens
const tickerGroup = document.getElementById('tickerGroup');
const navBtn = document.getElementById('navOpenBtn');
if (id === 'home') {
if (tickerGroup) tickerGroup.style.display = 'none';
} else {
if (tickerGroup) tickerGroup.style.display = 'flex';
}
}
// ─── Collapsible nav (close completely) ───
function toggleNav(navId) {
const nav = document.getElementById(navId);
nav.classList.toggle('collapsed');
const btn = nav.querySelector('.collapse-btn');
if (nav.classList.contains('collapsed')) {
btn.textContent = '▶';
} else {
btn.textContent = '◀';
}
}
function openNav() {
const wsNav = document.getElementById('ws-nav');
const memoNav = document.getElementById('memo-nav');
[wsNav, memoNav].forEach(nav => {
if (nav && nav.classList.contains('collapsed')) {
nav.classList.remove('collapsed');
nav.querySelector('.collapse-btn').textContent = '◀';
}
});
}
// ─── Left nav button selection ───
document.querySelectorAll('#ws-nav button').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('#ws-nav button').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
// ─── Memo outline selection ───
document.querySelectorAll('.memo-outline li').forEach(li => {
li.addEventListener('click', function() {
document.querySelectorAll('.memo-outline li').forEach(l => l.classList.remove('active'));
this.classList.add('active');
});
});
// ─── Agent selection + detail panel ───
function selectAgent(tile, id) {
document.querySelectorAll('.agent-tile').forEach(t => t.classList.remove('selected'));
tile.classList.add('selected');
const detail = document.getElementById('agentDetail');
detail.classList.add('open');
document.getElementById('detailAgentName').textContent = agentInfo[id].name;
document.getElementById('detailAgentStatus').textContent = agentInfo[id].status;
}
function closeAgentDetail() {
document.getElementById('agentDetail').classList.remove('open');
document.querySelectorAll('.agent-tile').forEach(t => t.classList.remove('selected'));
}
// ─── Agent carousel ───
function updateCarousel() {
const agent = agentInfo[activeAgents[carouselIdx]];
document.getElementById('carouselName').textContent = agent.name;
document.getElementById('carouselAction').textContent = agent.action;
document.getElementById('carouselCounter').textContent = (carouselIdx + 1) + ' / ' + activeAgents.length;
document.getElementById('carouselPrev').disabled = carouselIdx === 0;
document.getElementById('carouselNext').disabled = carouselIdx === activeAgents.length - 1;
}
function carouselPrev() {
if (carouselIdx > 0) { carouselIdx--; updateCarousel(); }
}
function carouselNext() {
if (carouselIdx < activeAgents.length - 1) { carouselIdx++; updateCarousel(); }
}
updateCarousel();
// ─── Agent fullscreen overlay ───
function openAgentOverlay(agentId) {
const id = agentId || activeAgents[carouselIdx];
const agent = agentInfo[id];
document.getElementById('overlayAgentName').textContent = agent.name;
document.getElementById('overlayAgentStatus').textContent = agent.status;
// Activate the matching tab
document.querySelectorAll('.overlay-agent-tabs .oat-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.textContent.trim().includes(agent.name.split(' ')[0])) btn.classList.add('active');
});
document.getElementById('agentOverlay').classList.add('open');
}
function closeAgentOverlay() {
document.getElementById('agentOverlay').classList.remove('open');
}
// ─── Settings overlay ───
function openSettings() { document.getElementById('settingsOverlay').classList.add('open'); }
function closeSettings() { document.getElementById('settingsOverlay').classList.remove('open'); }
// ─── Settings nav ───
document.querySelectorAll('.settings-nav button').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.settings-nav button').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
// ─── Review mode + annotations ───
let reviewMode = false;
let annotationMode = null;
function toggleReviewMode() {
reviewMode = !reviewMode;
const btn = document.getElementById('reviewToggle');
btn.textContent = reviewMode ? 'Exit Review' : 'Review Mode';
btn.style.background = reviewMode ? 'var(--accent)' : '';
btn.style.color = reviewMode ? 'var(--surface)' : '';
btn.style.borderColor = reviewMode ? 'var(--accent)' : '';
if (!reviewMode) {
annotationMode = null;
document.querySelectorAll('#modeHighlightBtn,#modeCommentBtn,#modeBoxBtn').forEach(b => {
b.style.background = ''; b.style.color = ''; b.style.borderColor = '';
});
}
}
function setAnnotationMode(mode) {
annotationMode = mode;
const btns = { highlight: 'modeHighlightBtn', comment: 'modeCommentBtn', box: 'modeBoxBtn' };
Object.entries(btns).forEach(([m, bid]) => {
const b = document.getElementById(bid);
b.style.background = m === mode ? 'var(--accent)' : '';
b.style.color = m === mode ? 'var(--surface)' : '';
b.style.borderColor = m === mode ? 'var(--accent)' : '';
});
}
document.addEventListener('mouseup', function(e) {
const toolbar = document.getElementById('annotationToolbar');
if (!reviewMode || !e.target.closest('#screen-memo .center')) {
toolbar.classList.remove('open'); return;
}
const sel = window.getSelection();
if (sel && sel.toString().trim().length > 0) {
const range = sel.getRangeAt(0);
const rect = range.getBoundingClientRect();
const center = e.target.closest('.center');
const cRect = center.getBoundingClientRect();
toolbar.style.top = (rect.top - cRect.top - 36 + center.scrollTop) + 'px';
toolbar.style.left = (rect.left - cRect.left + center.scrollLeft) + 'px';
toolbar.classList.add('open');
} else {
toolbar.classList.remove('open');
}
});
function annotateHighlight() {
const sel = window.getSelection();
if (!sel || sel.toString().trim().length === 0) return;
const range = sel.getRangeAt(0);
const span = document.createElement('span');
span.className = 'highlight-annotation';
span.setAttribute('data-comment', 'Highlighted by reviewer');
try { range.surroundContents(span); } catch(e) { span.textContent = sel.toString(); range.deleteContents(); range.insertNode(span); }
sel.removeAllRanges();
document.getElementById('annotationToolbar').classList.remove('open');
}
function annotateComment() {
const comment = prompt('Add a review comment:');
if (!comment) return;
const sel = window.getSelection();
if (!sel || sel.toString().trim().length === 0) return;
const range = sel.getRangeAt(0);
const span = document.createElement('span');
span.className = 'highlight-annotation';
span.setAttribute('data-comment', comment);
try { range.surroundContents(span); } catch(e) { span.textContent = sel.toString(); range.deleteContents(); range.insertNode(span); }
sel.removeAllRanges();
document.getElementById('annotationToolbar').classList.remove('open');
}
function annotateStrikethrough() {
const sel = window.getSelection();
if (!sel || sel.toString().trim().length === 0) return;
const range = sel.getRangeAt(0);
const span = document.createElement('span');
span.style.textDecoration = 'line-through';
span.style.color = 'var(--red)';
span.style.opacity = '0.6';
try { range.surroundContents(span); } catch(e) { span.textContent = sel.toString(); range.deleteContents(); range.insertNode(span); }
sel.removeAllRanges();
document.getElementById('annotationToolbar').classList.remove('open');
}
function annotateBox() {
document.getElementById('annotationToolbar').classList.remove('open');
const center = document.querySelector('#screen-memo .center');
const overlay = document.createElement('div');
overlay.style.cssText = 'position:absolute;top:0;left:0;right:0;bottom:0;z-index:150;cursor:crosshair;';
center.style.position = 'relative';
center.appendChild(overlay);
let startX, startY;
overlay.addEventListener('mousedown', function(e) {
const rect = overlay.getBoundingClientRect();
startX = e.clientX - rect.left + center.scrollLeft;
startY = e.clientY - rect.top + center.scrollTop;
const box = document.createElement('div');
box.className = 'box-annotation';
box.style.left = startX + 'px'; box.style.top = startY + 'px';
box.style.width = '0px'; box.style.height = '0px';
center.appendChild(box);
function onMove(ev) {
const cx = ev.clientX - rect.left + center.scrollLeft;
const cy = ev.clientY - rect.top + center.scrollTop;
box.style.width = Math.abs(cx - startX) + 'px';
box.style.height = Math.abs(cy - startY) + 'px';
box.style.left = Math.min(cx, startX) + 'px';
box.style.top = Math.min(cy, startY) + 'px';
}
function onUp() {
overlay.remove();
const label = document.createElement('div');
label.className = 'box-label';
label.textContent = 'Review needed';
label.onclick = function() { const note = prompt('Add note:', label.textContent); if (note) label.textContent = note; };
box.appendChild(label);
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
}
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
});
}
// ─── Model tab switching ───
function switchModelTab(tab) {
const spreadsheet = document.querySelector('#screen-model .spreadsheet');
const spreadsheetInfo = spreadsheet ? spreadsheet.parentElement.querySelector('div:last-of-type') : null;
const chartsPanel = document.getElementById('chartsPanel');
const allTables = document.querySelectorAll('#screen-model .center > *');
if (tab === 'charts') {
// Hide spreadsheet area, show charts
const center = document.querySelector('#screen-model .center');
if (center) {
// Hide everything except charts panel
Array.from(center.children).forEach(child => {
if (child.id !== 'chartsPanel') child.style.display = 'none';
});
}
if (chartsPanel) chartsPanel.style.display = 'grid';
} else {
// Show spreadsheet area, hide charts
const center = document.querySelector('#screen-model .center');
if (center) {
Array.from(center.children).forEach(child => {
if (child.id !== 'chartsPanel') child.style.display = '';
});
}
if (chartsPanel) chartsPanel.style.display = 'none';
}
}
// ─── Overlay tab switching (new tab-based layout) ───
function switchOverlayTab(btn, id) {
document.querySelectorAll('.overlay-agent-tabs .oat-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const agent = agentInfo[id];
document.getElementById('overlayAgentName').textContent = agent.name;
document.getElementById('overlayAgentStatus').textContent = agent.status;
}
// ─── Dep tree tab switching ───
function switchDepTab(btn, ticker) {
btn.parentElement.querySelectorAll('button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
// Future: swap dep tree content per ticker
}
// ─── Profile editor ───
function openProfile() { document.getElementById('profileOverlay').classList.add('open'); }
function closeProfile() { document.getElementById('profileOverlay').classList.remove('open'); }
function saveProfile() {
const name = document.getElementById('profileName').value;
const initials = name.split(' ').map(w => w[0]).join('').toUpperCase().slice(0, 2);
document.querySelector('.topbar .avatar').textContent = initials;
document.getElementById('profileDisplayName').textContent = name;
document.querySelector('.profile-overlay .profile-avatar').textContent = initials;
closeProfile();
}
// ─── Init: hide ticker on home screen ───
document.getElementById('tickerGroup').style.display = 'none';