| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <title>AI Research Multi-Agent System</title> |
| <style> |
| :root { |
| --bg: #07090f; |
| --panel: #0d1119; |
| --panel-2: #111722; |
| --line: #263044; |
| --line-soft: #192130; |
| --ink: #eef4ff; |
| --muted: #8996aa; |
| --blue: #4f9cff; |
| --cyan: #2de2e6; |
| --green: #4ade80; |
| --amber: #fbbf24; |
| --violet: #a78bfa; |
| --rose: #fb7185; |
| --sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; |
| --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; |
| } |
| |
| * { box-sizing: border-box; } |
| html, body { margin: 0; min-height: 100%; background: var(--bg); color: var(--ink); font-family: var(--sans); } |
| body { min-height: 100vh; overflow: hidden; } |
| button, input, select { font: inherit; } |
| button { color: inherit; } |
| |
| .app { height: 100vh; min-height: 680px; display: grid; grid-template-rows: 64px minmax(0, 1fr) 96px; } |
| .topbar { |
| display: grid; grid-template-columns: minmax(280px, 1fr) auto minmax(210px, 1fr); |
| align-items: center; gap: 24px; padding: 0 20px; |
| background: #0a0d14; border-bottom: 1px solid var(--line); |
| box-shadow: 0 8px 28px rgba(0,0,0,.25); z-index: 4; |
| } |
| .brand { display: flex; align-items: center; gap: 12px; min-width: 0; } |
| .brand-mark { width: 36px; height: 36px; position: relative; display: grid; place-items: center; color: var(--cyan); } |
| .brand-mark::before, .brand-mark::after { content: ""; position: absolute; border: 1px solid currentColor; transform: rotate(45deg); } |
| .brand-mark::before { width: 27px; height: 27px; opacity: .65; } |
| .brand-mark::after { width: 16px; height: 16px; animation: markPulse 2.4s ease-in-out infinite; } |
| .brand-core { width: 5px; height: 5px; background: currentColor; box-shadow: 0 0 14px currentColor; } |
| @keyframes markPulse { 50% { transform: rotate(135deg) scale(.72); opacity: .35; } } |
| .brand-copy { min-width: 0; } |
| .eyebrow { color: var(--cyan); font: 700 9px/1 var(--mono); letter-spacing: 1.8px; text-transform: uppercase; } |
| h1 { font-size: 16px; line-height: 1.2; margin: 5px 0 0; letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| |
| .header-metrics { display: flex; align-items: stretch; height: 42px; } |
| .header-metric { min-width: 86px; padding: 3px 14px; text-align: center; border-left: 1px solid var(--line-soft); } |
| .header-metric:last-child { border-right: 1px solid var(--line-soft); } |
| .metric-value { color: var(--ink); font: 700 17px/1.2 var(--mono); } |
| .metric-value.cyan { color: var(--cyan); } |
| .metric-value.green { color: var(--green); } |
| .metric-value.amber { color: var(--amber); } |
| .metric-label { color: var(--muted); font: 600 8px/1.3 var(--mono); letter-spacing: 1px; text-transform: uppercase; } |
| .system-state { justify-self: end; text-align: right; } |
| .live-row { display: flex; justify-content: flex-end; align-items: center; gap: 7px; color: var(--green); font: 700 10px/1 var(--mono); letter-spacing: .8px; } |
| .live-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 10px currentColor; animation: livePulse 1.5s ease-in-out infinite; } |
| @keyframes livePulse { 50% { opacity: .35; transform: scale(.75); } } |
| #clock { margin-top: 6px; color: var(--muted); font: 10px/1 var(--mono); } |
| |
| .workspace { display: grid; grid-template-columns: minmax(500px, 1.4fr) minmax(280px, .78fr) minmax(300px, .9fr); min-height: 0; } |
| .panel { min-width: 0; min-height: 0; background: var(--panel); border-right: 1px solid var(--line); display: flex; flex-direction: column; } |
| .panel:last-child { border-right: 0; } |
| .panel-title { height: 39px; padding: 0 13px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; flex: 0 0 auto; } |
| .panel-title h2 { margin: 0; color: #b9c5d7; font: 700 9px/1 var(--mono); letter-spacing: 1.45px; text-transform: uppercase; } |
| .panel-title h2::before { content: ""; display: inline-block; width: 5px; height: 5px; margin-right: 8px; border-radius: 1px; background: var(--cyan); box-shadow: 0 0 8px rgba(45,226,230,.7); vertical-align: 1px; } |
| .tiny-badge { border: 1px solid var(--line); border-radius: 12px; padding: 3px 7px; color: var(--muted); font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; } |
| |
| .supervisor-strip { margin: 10px 11px 0; min-height: 73px; border: 1px solid rgba(251,191,36,.55); background: #12140f; border-radius: 7px; display: grid; grid-template-columns: 48px 1fr auto; gap: 10px; align-items: center; padding: 9px 11px; position: relative; overflow: hidden; } |
| .supervisor-strip::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--amber); transform: scaleX(var(--supervisor-progress, 0)); transform-origin: left; transition: transform .2s linear; } |
| .supervisor-anim { width: 42px; height: 42px; position: relative; display: grid; place-items: center; } |
| .supervisor-anim span { position: absolute; border-radius: 50%; border: 1px solid var(--amber); } |
| .supervisor-anim span:nth-child(1) { inset: 2px; border-style: dashed; animation: orbit 5s linear infinite; } |
| .supervisor-anim span:nth-child(2) { inset: 8px; border-color: var(--violet); animation: orbit 2.8s linear reverse infinite; } |
| .supervisor-anim span:nth-child(3) { width: 7px; height: 7px; background: var(--amber); border: 0; box-shadow: 0 0 13px var(--amber); animation: coreBeat 1.1s ease-in-out infinite; } |
| @keyframes orbit { to { transform: rotate(360deg); } } |
| @keyframes coreBeat { 50% { transform: scale(.62); opacity: .55; } } |
| .supervisor-copy { min-width: 0; } |
| .supervisor-name { color: var(--amber); font-size: 12px; font-weight: 750; } |
| .supervisor-role { margin-top: 2px; color: var(--muted); font: 8px/1.2 var(--mono); text-transform: uppercase; letter-spacing: .8px; } |
| #supervisorDecision { margin-top: 7px; color: #dbe4f1; font: 10px/1.2 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| #supervisorDecision::before { content: "> "; color: var(--amber); } |
| .phase-pill { color: var(--amber); border: 1px solid rgba(251,191,36,.55); background: rgba(251,191,36,.07); border-radius: 10px; padding: 4px 7px; font: 700 8px/1 var(--mono); letter-spacing: .8px; } |
| |
| .topology { position: relative; flex: 1; min-height: 0; margin: 7px 8px 8px; border: 1px solid var(--line-soft); border-radius: 6px; overflow: hidden; background-color: #090d14; background-image: linear-gradient(rgba(79,156,255,.035) 1px, transparent 1px), linear-gradient(90deg, rgba(79,156,255,.035) 1px, transparent 1px); background-size: 28px 28px; } |
| .topology::after { content: "SIMULATION MODE / LOCAL STATE"; position: absolute; right: 10px; bottom: 8px; color: #39465a; font: 8px/1 var(--mono); letter-spacing: .7px; } |
| #workflowSvg { width: 100%; height: 100%; display: block; } |
| .route { fill: none; stroke: #2c3950; stroke-width: 1.5; stroke-dasharray: 5 7; } |
| .route.return { opacity: .55; } |
| .route-active { stroke: var(--cyan); animation: routeFlow 1s linear infinite; filter: url(#softGlow); } |
| @keyframes routeFlow { to { stroke-dashoffset: -24; } } |
| .node .node-shell { fill: #0e1520; stroke: #344158; stroke-width: 1.5; transition: stroke .25s, fill .25s; } |
| .node .node-ring { fill: none; stroke: #344158; stroke-width: 1; stroke-dasharray: 2 5; opacity: .45; } |
| .node text { font-family: var(--mono); text-anchor: middle; } |
| .node .node-name { fill: #eef4ff; font-size: 11px; font-weight: 700; } |
| .node .node-sub { fill: #748197; font-size: 8px; } |
| .node .node-glyph { fill: #b8c5d7; font-size: 17px; font-weight: 700; } |
| .node.active .node-shell { stroke: var(--node-color); fill: #101824; filter: url(#softGlow); } |
| .node.active .node-ring { stroke: var(--node-color); opacity: .9; animation: nodeOrbit 4s linear infinite; transform-box: fill-box; transform-origin: center; } |
| .node.done .node-shell { stroke: var(--green); } |
| .node.done .node-glyph { fill: var(--green); } |
| @keyframes nodeOrbit { to { transform: rotate(360deg); } } |
| .supervisor-node .node-shell { stroke: var(--amber); } |
| .supervisor-node .node-ring { stroke: var(--amber); animation: nodeOrbit 5s linear infinite; transform-box: fill-box; transform-origin: center; } |
| .supervisor-node.active .node-shell { fill: #18170e; filter: url(#amberGlow); } |
| .paper-packet { opacity: 0; pointer-events: none; } |
| .paper-packet rect { fill: #ecf8ff; stroke: var(--cyan); stroke-width: .8; } |
| .paper-packet line { stroke: #387283; stroke-width: .6; } |
| .topology[data-phase="discovery"] .search-packet { opacity: 1; } |
| .topology[data-phase="evaluation"] .eval-packet { opacity: 1; } |
| .topology[data-phase="reporting"] .report-packet { opacity: 1; } |
| .pulse-wave { fill: none; stroke: var(--amber); stroke-width: 1.2; opacity: 0; transform-origin: center; animation: wave 1.8s ease-out infinite; } |
| .pulse-wave.delay { animation-delay: .8s; } |
| @keyframes wave { 0% { opacity: .65; transform: scale(.55); } 100% { opacity: 0; transform: scale(1.35); } } |
| .source-chip { fill: #0e1520; stroke: #2f455b; } |
| .source-label { fill: var(--cyan); font: 700 9px var(--mono); text-anchor: middle; } |
| .source-sub { fill: #6f7d92; font: 7px var(--mono); text-anchor: middle; } |
| |
| .agents-body { padding: 9px; overflow: auto; flex: 1; scrollbar-width: thin; scrollbar-color: #344158 transparent; } |
| .agent-card { border: 1px solid var(--line); border-radius: 6px; background: #0b1018; margin-bottom: 7px; padding: 10px; transition: border-color .25s, background .25s; } |
| .agent-card.active { border-color: var(--agent-color); background: #101722; box-shadow: inset 3px 0 0 var(--agent-color); } |
| .agent-card.done { border-color: rgba(74,222,128,.55); } |
| .agent-head { display: grid; grid-template-columns: 31px 1fr auto; align-items: center; gap: 8px; } |
| .agent-icon { width: 31px; height: 31px; display: grid; place-items: center; border-radius: 5px; border: 1px solid var(--agent-color); color: var(--agent-color); font: 800 10px var(--mono); background: color-mix(in srgb, var(--agent-color) 8%, transparent); } |
| .agent-name { font-size: 11px; font-weight: 750; } |
| .agent-spec { color: var(--muted); font: 8px/1.4 var(--mono); margin-top: 2px; } |
| .status-badge { color: var(--muted); border: 1px solid var(--line); border-radius: 10px; padding: 3px 6px; font: 700 7px/1 var(--mono); letter-spacing: .65px; text-transform: uppercase; } |
| .active .status-badge { color: var(--agent-color); border-color: var(--agent-color); animation: statusBlink 1.2s ease-in-out infinite; } |
| .done .status-badge { color: var(--green); border-color: rgba(74,222,128,.6); } |
| @keyframes statusBlink { 50% { opacity: .45; } } |
| .agent-task { min-height: 14px; margin: 9px 0 7px; color: #b7c2d2; font: 9px/1.5 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| .progress { height: 3px; overflow: hidden; border-radius: 2px; background: #171f2c; } |
| .progress-fill { height: 100%; width: 0; border-radius: inherit; background: var(--agent-color); transition: width .18s linear; box-shadow: 0 0 8px color-mix(in srgb, var(--agent-color) 70%, transparent); } |
| .framework-mini { margin: 2px 0 8px; padding: 10px; border: 1px solid var(--line-soft); border-radius: 6px; } |
| .framework-mini-title { display: flex; justify-content: space-between; color: #c5d0df; font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; } |
| .framework-mini-title span:last-child { color: var(--violet); } |
| .weight-strip { display: flex; gap: 2px; height: 5px; margin-top: 8px; } |
| .weight-strip span { background: var(--violet); opacity: calc(.35 + var(--o)); border-radius: 1px; } |
| |
| .right-panel { overflow: hidden; } |
| .tabs { display: flex; border-bottom: 1px solid var(--line); flex: 0 0 auto; } |
| .tab { flex: 1; padding: 9px 7px; border: 0; border-right: 1px solid var(--line); border-bottom: 2px solid transparent; background: #0b1018; color: var(--muted); cursor: pointer; font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; } |
| .tab:last-child { border-right: 0; } |
| .tab.active { color: var(--cyan); border-bottom-color: var(--cyan); background: #0f151f; } |
| .tab-view { display: none; flex: 1; min-height: 0; overflow: auto; } |
| .tab-view.active { display: flex; flex-direction: column; } |
| .ranking { padding: 8px; flex: 1; min-height: 0; overflow: auto; } |
| .empty-state { height: 100%; min-height: 190px; display: grid; place-items: center; text-align: center; color: var(--muted); padding: 24px; } |
| .empty-radar { width: 60px; height: 60px; margin: 0 auto 13px; border: 1px solid #314057; border-radius: 50%; position: relative; } |
| .empty-radar::before, .empty-radar::after { content: ""; position: absolute; inset: 10px; border: 1px solid #263348; border-radius: 50%; } |
| .empty-radar::after { inset: 27px; border-color: var(--cyan); background: var(--cyan); box-shadow: 0 0 12px rgba(45,226,230,.6); } |
| .empty-title { color: #c8d2df; font-size: 12px; font-weight: 700; } |
| .empty-copy { max-width: 230px; margin-top: 5px; font: 9px/1.55 var(--mono); } |
| .paper-card { border: 1px solid var(--line-soft); background: #0a0f17; border-radius: 5px; padding: 9px 9px 8px; margin-bottom: 6px; animation: resultIn .35s ease both; } |
| @keyframes resultIn { from { opacity: 0; transform: translateY(7px); } } |
| .paper-row { display: grid; grid-template-columns: 22px minmax(0,1fr) 42px; gap: 7px; align-items: start; } |
| .paper-rank { color: var(--muted); font: 800 9px/1 var(--mono); padding-top: 2px; } |
| .paper-title { color: #dfe7f2; font-size: 10px; line-height: 1.25; font-weight: 650; } |
| .paper-meta { color: var(--muted); font: 8px/1.4 var(--mono); margin-top: 4px; } |
| .paper-score { text-align: right; color: var(--score-color); font: 800 15px/1 var(--mono); } |
| .paper-score span { display: block; margin-top: 3px; color: var(--muted); font-size: 7px; } |
| .score-track { margin-top: 8px; height: 3px; background: #171f2b; border-radius: 2px; overflow: hidden; } |
| .score-fill { height: 100%; width: var(--score); background: var(--score-color); border-radius: inherit; } |
| .framework-view { padding: 9px; } |
| .framework-note { padding: 9px; border: 1px solid var(--line-soft); background: #0a0f17; border-radius: 5px; color: var(--muted); font: 9px/1.5 var(--mono); } |
| .criterion { margin-top: 8px; } |
| .criterion-row { display: flex; justify-content: space-between; gap: 10px; color: #c9d4e2; font: 9px/1.3 var(--mono); } |
| .criterion-row strong { color: var(--violet); } |
| .criterion-track { height: 3px; margin-top: 5px; background: #171f2b; } |
| .criterion-track span { display: block; height: 100%; background: var(--violet); } |
| |
| .log-section { height: 174px; min-height: 120px; border-top: 1px solid var(--line); display: flex; flex-direction: column; flex: 0 0 auto; } |
| .log-head { height: 31px; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; color: var(--muted); font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; border-bottom: 1px solid var(--line-soft); } |
| .log-head span:last-child { color: var(--green); } |
| #eventLog { overflow: auto; flex: 1; padding: 6px 9px; font: 8px/1.6 var(--mono); scrollbar-width: thin; scrollbar-color: #344158 transparent; } |
| .log-line { display: grid; grid-template-columns: 54px 46px minmax(0,1fr); gap: 5px; border-bottom: 1px solid rgba(255,255,255,.025); padding: 1px 0; animation: logIn .25s ease; } |
| @keyframes logIn { from { opacity: 0; } } |
| .log-time { color: #59677c; } |
| .log-type { color: var(--log-color); font-weight: 700; } |
| .log-msg { color: #aebaca; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } |
| |
| .control-dock { display: grid; grid-template-columns: minmax(280px, 1fr) 185px 230px 255px; gap: 12px; align-items: center; padding: 11px 16px; background: #0a0d14; border-top: 1px solid var(--line); box-shadow: 0 -10px 26px rgba(0,0,0,.28); z-index: 4; } |
| .field label { display: block; color: var(--muted); font: 700 8px/1 var(--mono); text-transform: uppercase; letter-spacing: .8px; margin-bottom: 6px; } |
| .query-input { width: 100%; height: 36px; padding: 0 11px; border: 1px solid #344158; border-radius: 5px; background: #0d131d; color: var(--ink); outline: none; font: 10px var(--mono); } |
| .query-input:focus { border-color: var(--cyan); box-shadow: 0 0 0 2px rgba(45,226,230,.09); } |
| .paper-control { display: grid; grid-template-columns: 1fr 33px; gap: 8px; align-items: center; } |
| input[type="range"] { width: 100%; accent-color: var(--cyan); } |
| #paperLimitValue { height: 27px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 4px; color: var(--cyan); font: 800 10px var(--mono); } |
| .speed-group { display: flex; height: 36px; } |
| .speed-button { flex: 1; border: 1px solid var(--line); border-right: 0; background: #0d131d; color: var(--muted); cursor: pointer; font: 700 9px var(--mono); } |
| .speed-button:first-child { border-radius: 5px 0 0 5px; } |
| .speed-button:last-child { border-right: 1px solid var(--line); border-radius: 0 5px 5px 0; } |
| .speed-button.active { background: rgba(167,139,250,.12); color: var(--violet); border-color: var(--violet); } |
| .actions { display: grid; grid-template-columns: 1fr 38px 38px; gap: 7px; align-items: end; } |
| .button { height: 36px; border: 1px solid var(--line); border-radius: 5px; background: #111824; cursor: pointer; font: 750 9px var(--mono); letter-spacing: .45px; transition: transform .15s, border-color .15s; } |
| .button:hover { transform: translateY(-1px); border-color: #53627a; } |
| .button.primary { background: var(--cyan); color: #041014; border-color: var(--cyan); } |
| .button.primary.running { background: var(--amber); border-color: var(--amber); } |
| .button:disabled { cursor: not-allowed; opacity: .35; transform: none; } |
| .icon-button { font-size: 15px; padding: 0; } |
| .download-button { position: absolute; right: 10px; top: 48px; z-index: 2; height: 28px; padding: 0 9px; border: 1px solid rgba(74,222,128,.55); border-radius: 4px; background: #0c1812; color: var(--green); cursor: pointer; font: 700 8px var(--mono); display: none; } |
| .download-button.visible { display: block; } |
| .screen-reader { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; } |
| |
| @media (max-width: 1120px) { |
| body { overflow: auto; } |
| .app { height: auto; min-height: 100vh; grid-template-rows: auto auto auto; } |
| .topbar { min-height: 64px; grid-template-columns: 1fr auto; } |
| .header-metrics { display: none; } |
| .workspace { grid-template-columns: 1fr 340px; min-height: 760px; } |
| .right-panel { grid-column: 1 / -1; height: 480px; border-top: 1px solid var(--line); } |
| .control-dock { grid-template-columns: 1fr 160px 200px; } |
| .actions { grid-column: auto; } |
| .speed-field { display: none; } |
| } |
| @media (max-width: 760px) { |
| .topbar { grid-template-columns: 1fr; gap: 6px; padding: 12px 14px; } |
| .system-state { display: none; } |
| .workspace { display: block; } |
| .panel { border-right: 0; border-bottom: 1px solid var(--line); } |
| .workflow-panel { height: 680px; } |
| .agents-panel { height: 540px; } |
| .right-panel { height: 520px; } |
| .control-dock { grid-template-columns: 1fr 1fr; position: sticky; bottom: 0; } |
| .field:first-child { grid-column: 1 / -1; } |
| .actions { grid-column: 2; } |
| h1 { white-space: normal; } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="app"> |
| <header class="topbar"> |
| <div class="brand"> |
| <div class="brand-mark" aria-hidden="true"><div class="brand-core"></div></div> |
| <div class="brand-copy"> |
| <div class="eyebrow">Research intelligence lab</div> |
| <h1>AI Research Multi-Agent System</h1> |
| </div> |
| </div> |
| <div class="header-metrics" aria-label="System metrics"> |
| <div class="header-metric"><div class="metric-value cyan" id="papersFound">0</div><div class="metric-label">Discovered</div></div> |
| <div class="header-metric"><div class="metric-value" id="papersEvaluated">0</div><div class="metric-label">Evaluated</div></div> |
| <div class="header-metric"><div class="metric-value amber" id="avgScore">--</div><div class="metric-label">Avg AGI score</div></div> |
| <div class="header-metric"><div class="metric-value green" id="coverage">0%</div><div class="metric-label">Pipeline</div></div> |
| </div> |
| <div class="system-state"> |
| <div class="live-row"><span class="live-dot"></span><span id="systemState">SYSTEM READY</span></div> |
| <div id="clock">--:--:-- ET</div> |
| </div> |
| </header> |
|
|
| <main class="workspace"> |
| <section class="panel workflow-panel" aria-labelledby="workflowTitle"> |
| <div class="panel-title"><h2 id="workflowTitle">LangGraph workflow topology</h2><span class="tiny-badge">StateGraph</span></div> |
| <div class="supervisor-strip" id="supervisorStrip"> |
| <div class="supervisor-anim" aria-hidden="true"><span></span><span></span><span></span></div> |
| <div class="supervisor-copy"> |
| <div class="supervisor-name">Supervisor Agent</div> |
| <div class="supervisor-role">Phase routing / state coordination / report control</div> |
| <div id="supervisorDecision">Awaiting research objective</div> |
| </div> |
| <div class="phase-pill" id="phasePill">IDLE</div> |
| </div> |
|
|
| <div class="topology" id="topology" data-phase="idle"> |
| <svg id="workflowSvg" viewBox="0 0 720 500" role="img" aria-label="Animated multi-agent research workflow"> |
| <defs> |
| <filter id="softGlow"><feGaussianBlur stdDeviation="2.2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter> |
| <filter id="amberGlow"><feGaussianBlur stdDeviation="3.5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter> |
| <path id="pathSupervisorPlanner" d="M360 190 C290 145 255 112 188 91"/> |
| <path id="pathPlannerSupervisor" d="M185 112 C250 147 290 172 333 194"/> |
| <path id="pathSupervisorDiscovery" d="M348 221 C331 274 330 313 345 350"/> |
| <path id="pathDiscoverySupervisor" d="M378 349 C394 295 394 260 375 222"/> |
| <path id="pathSupervisorEvaluation" d="M389 207 C450 238 508 283 551 347"/> |
| <path id="pathEvaluationSupervisor" d="M564 339 C516 278 468 234 390 197"/> |
| <path id="pathSupervisorReport" d="M392 181 C455 149 503 119 550 93"/> |
| <path id="pathArxivDiscovery" d="M130 382 C207 389 265 383 326 375"/> |
| </defs> |
|
|
| <path class="route" id="routeSupervisorPlanner" d="M360 190 C290 145 255 112 188 91"/> |
| <path class="route return" id="routePlannerSupervisor" d="M185 112 C250 147 290 172 333 194"/> |
| <path class="route" id="routeSupervisorDiscovery" d="M348 221 C331 274 330 313 345 350"/> |
| <path class="route return" id="routeDiscoverySupervisor" d="M378 349 C394 295 394 260 375 222"/> |
| <path class="route" id="routeSupervisorEvaluation" d="M389 207 C450 238 508 283 551 347"/> |
| <path class="route return" id="routeEvaluationSupervisor" d="M564 339 C516 278 468 234 390 197"/> |
| <path class="route" id="routeSupervisorReport" d="M392 181 C455 149 503 119 550 93"/> |
| <path class="route" id="routeArxivDiscovery" d="M130 382 C207 389 265 383 326 375"/> |
|
|
| <g transform="translate(130 382)"> |
| <rect class="source-chip" x="-53" y="-23" width="106" height="46" rx="6"/> |
| <text class="source-label" y="-3">arXiv API</text> |
| <text class="source-sub" y="10">cs.AI / cs.LG / cs.CL</text> |
| </g> |
|
|
| <g class="node" id="node-planner" style="--node-color: var(--blue)" transform="translate(155 86)"> |
| <circle class="node-ring" r="48"/><rect class="node-shell" x="-43" y="-34" width="86" height="68" rx="8"/> |
| <text class="node-glyph" y="-9">PL</text><text class="node-name" y="10">PLANNER</text><text class="node-sub" y="24">execution plan</text> |
| </g> |
| <g class="node supervisor-node active" id="node-supervisor" style="--node-color: var(--amber)" transform="translate(360 195)"> |
| <circle class="pulse-wave" r="49"/><circle class="pulse-wave delay" r="49"/><circle class="node-ring" r="51"/> |
| <polygon class="node-shell" points="0,-43 37,-21 37,21 0,43 -37,21 -37,-21"/> |
| <text class="node-glyph" y="-9">SV</text><text class="node-name" y="10">SUPERVISOR</text><text class="node-sub" y="24">state router</text> |
| </g> |
| <g class="node" id="node-discovery" style="--node-color: var(--cyan)" transform="translate(360 378)"> |
| <circle class="node-ring" r="48"/><rect class="node-shell" x="-45" y="-34" width="90" height="68" rx="8"/> |
| <text class="node-glyph" y="-9">DS</text><text class="node-name" y="10">DISCOVERY</text><text class="node-sub" y="24">paper search</text> |
| </g> |
| <g class="node" id="node-evaluation" style="--node-color: var(--violet)" transform="translate(585 378)"> |
| <circle class="node-ring" r="48"/><rect class="node-shell" x="-46" y="-34" width="92" height="68" rx="8"/> |
| <text class="node-glyph" y="-9">EV</text><text class="node-name" y="10">EVALUATION</text><text class="node-sub" y="24">10 AGI criteria</text> |
| </g> |
| <g class="node" id="node-report" style="--node-color: var(--green)" transform="translate(585 86)"> |
| <circle class="node-ring" r="48"/><rect class="node-shell" x="-45" y="-34" width="90" height="68" rx="8"/> |
| <text class="node-glyph" y="-9">RP</text><text class="node-name" y="10">REPORT</text><text class="node-sub" y="24">ranked findings</text> |
| </g> |
|
|
| <g class="paper-packet search-packet"> |
| <rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/> |
| <animateMotion dur="2.7s" repeatCount="indefinite"><mpath href="#pathArxivDiscovery"/></animateMotion> |
| </g> |
| <g class="paper-packet search-packet"> |
| <rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/> |
| <animateMotion dur="2.7s" begin=".9s" repeatCount="indefinite"><mpath href="#pathArxivDiscovery"/></animateMotion> |
| </g> |
| <g class="paper-packet eval-packet"> |
| <rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/> |
| <animateMotion dur="2.4s" repeatCount="indefinite" path="M390 378 C455 378 505 378 538 378"/> |
| </g> |
| <g class="paper-packet eval-packet"> |
| <rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/> |
| <animateMotion dur="2.4s" begin=".8s" repeatCount="indefinite" path="M390 378 C455 378 505 378 538 378"/> |
| </g> |
| <g class="paper-packet report-packet"> |
| <rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/> |
| <animateMotion dur="2s" repeatCount="indefinite"><mpath href="#pathSupervisorReport"/></animateMotion> |
| </g> |
| </svg> |
| </div> |
| </section> |
|
|
| <section class="panel agents-panel" aria-labelledby="agentsTitle"> |
| <div class="panel-title"><h2 id="agentsTitle">Agent operations</h2><span class="tiny-badge" id="activeCount">0 active</span></div> |
| <div class="agents-body"> |
| <div class="agent-card" id="card-planner" style="--agent-color: var(--blue)"> |
| <div class="agent-head"><div class="agent-icon">PL</div><div><div class="agent-name">Planner Agent</div><div class="agent-spec">GPT-4o mini / structured JSON</div></div><span class="status-badge">Idle</span></div> |
| <div class="agent-task">Waiting for a research objective</div><div class="progress"><div class="progress-fill"></div></div> |
| </div> |
| <div class="agent-card" id="card-discovery" style="--agent-color: var(--cyan)"> |
| <div class="agent-head"><div class="agent-icon">DS</div><div><div class="agent-name">Discovery Agent</div><div class="agent-spec">arXiv 2.3.1 / validation tools</div></div><span class="status-badge">Idle</span></div> |
| <div class="agent-task">Standing by for execution plan</div><div class="progress"><div class="progress-fill"></div></div> |
| </div> |
| <div class="agent-card" id="card-evaluation" style="--agent-color: var(--violet)"> |
| <div class="agent-head"><div class="agent-icon">EV</div><div><div class="agent-name">Evaluation Agent</div><div class="agent-spec">Weighted AGI scoring / JSON repair</div></div><span class="status-badge">Idle</span></div> |
| <div class="agent-task">Waiting for validated papers</div><div class="progress"><div class="progress-fill"></div></div> |
| </div> |
| <div class="agent-card" id="card-report" style="--agent-color: var(--green)"> |
| <div class="agent-head"><div class="agent-icon">RP</div><div><div class="agent-name">Report Generator</div><div class="agent-spec">Executive synthesis / recommendations</div></div><span class="status-badge">Idle</span></div> |
| <div class="agent-task">Waiting for evaluation results</div><div class="progress"><div class="progress-fill"></div></div> |
| </div> |
| <div class="framework-mini"> |
| <div class="framework-mini-title"><span>AGI evaluation framework</span><span>10 dimensions</span></div> |
| <div class="weight-strip" title="Weights from the notebook"> |
| <span style="width:15%;--o:.9"></span><span style="width:15%;--o:.8"></span><span style="width:15%;--o:.7"></span><span style="width:12%;--o:.6"></span><span style="width:10%;--o:.5"></span><span style="width:10%;--o:.45"></span><span style="width:8%;--o:.4"></span><span style="width:8%;--o:.35"></span><span style="width:4%;--o:.3"></span><span style="width:3%;--o:.25"></span> |
| </div> |
| </div> |
| </div> |
| </section> |
|
|
| <section class="panel right-panel" aria-labelledby="intelligenceTitle"> |
| <div class="panel-title"><h2 id="intelligenceTitle">Research intelligence</h2><span class="tiny-badge" id="requestId">No request</span></div> |
| <button class="download-button" id="downloadReport" type="button">Download report</button> |
| <div class="tabs" role="tablist"> |
| <button class="tab active" type="button" role="tab" aria-selected="true" data-tab="results">Ranked papers</button> |
| <button class="tab" type="button" role="tab" aria-selected="false" data-tab="framework">Scoring framework</button> |
| </div> |
| <div class="tab-view active" id="view-results" role="tabpanel"> |
| <div class="ranking" id="ranking"> |
| <div class="empty-state"><div><div class="empty-radar"></div><div class="empty-title">Research queue ready</div><div class="empty-copy">Run the workflow to discover, validate, score, and rank simulated AGI papers.</div></div></div> |
| </div> |
| </div> |
| <div class="tab-view framework-view" id="view-framework" role="tabpanel"></div> |
| <div class="log-section"> |
| <div class="log-head"><span>Supervisor event stream</span><span id="logState">listening</span></div> |
| <div id="eventLog" aria-live="polite"></div> |
| </div> |
| </section> |
| </main> |
|
|
| <footer class="control-dock"> |
| <div class="field"> |
| <label for="queryInput">Research objective</label> |
| <input class="query-input" id="queryInput" value="Find AGI papers from Jan 1st 2026 to Jan 31st 2026" autocomplete="off"> |
| </div> |
| <div class="field"> |
| <label for="paperLimit">Maximum papers</label> |
| <div class="paper-control"><input id="paperLimit" type="range" min="5" max="15" value="10"><output id="paperLimitValue" for="paperLimit">10</output></div> |
| </div> |
| <div class="field speed-field"> |
| <label>Simulation speed</label> |
| <div class="speed-group" aria-label="Simulation speed"> |
| <button class="speed-button" type="button" data-speed="0.75">0.75x</button><button class="speed-button active" type="button" data-speed="1">1x</button><button class="speed-button" type="button" data-speed="2">2x</button> |
| </div> |
| </div> |
| <div class="field"> |
| <label>Pipeline control</label> |
| <div class="actions"> |
| <button class="button primary" id="runButton" type="button">Run research</button> |
| <button class="button icon-button" id="pauseButton" type="button" title="Pause simulation" aria-label="Pause simulation" disabled>II</button> |
| <button class="button icon-button" id="resetButton" type="button" title="Reset simulation" aria-label="Reset simulation">R</button> |
| </div> |
| </div> |
| </footer> |
| </div> |
|
|
| <script> |
| const CRITERIA = [ |
| ["Novel Problem Solving", 15], ["Few-Shot Learning", 15], ["Task Transfer", 15], |
| ["Abstract Reasoning", 12], ["Contextual Adaptation", 10], ["Multi-Rule Integration", 10], |
| ["Generalization Efficiency", 8], ["Meta-Learning", 8], ["World Modeling", 4], |
| ["Autonomous Goal Setting", 3] |
| ]; |
| |
| const PAPER_LIBRARY = [ |
| ["Adaptive World Models for Long-Horizon Generalization", "I. Chen, M. Alvarez", 82], |
| ["Compositional Transfer Across Unseen Task Families", "S. Rao, J. Kim", 76], |
| ["Learning Abstract Rules from Sparse Demonstrations", "L. Okafor, P. Singh", 72], |
| ["Self-Refining Memory for Continual Agent Learning", "E. Brooks, N. Patel", 68], |
| ["Multi-Modal Planning with Uncertain World States", "A. Laurent, R. Davis", 64], |
| ["Efficient Meta-Learning Through Latent Skill Graphs", "T. Wang, C. Foster", 59], |
| ["Context-Aware Tool Selection in Language Agents", "M. Hassan, Y. Ito", 55], |
| ["Benchmarking Cross-Domain Reasoning Under Shift", "V. Novak, D. Green", 49], |
| ["Few-Shot Policy Adaptation for Embodied Systems", "K. Mensah, F. Ruiz", 45], |
| ["Structured Retrieval for Scientific Question Answering", "B. Carter, Z. Li", 39], |
| ["Improving Long-Context Classification with Routing", "H. Park, S. Bell", 35], |
| ["Domain-Specific Agents for Automated Data Labeling", "R. Evans, G. Moore", 31], |
| ["Compact Representation Learning for Edge Inference", "N. Shah, D. Klein", 28], |
| ["Synthetic Preference Optimization for Dialogue", "J. Wilson, A. Nair", 25], |
| ["A Taxonomy of Modular AI Evaluation Protocols", "C. Young, P. Martin", 22] |
| ]; |
| |
| const PHASES = { |
| idle: { label: "IDLE", progress: 0 }, initialization: { label: "INITIALIZE", progress: 6 }, |
| planning: { label: "PLANNING", progress: 22 }, discovery: { label: "DISCOVERY", progress: 47 }, |
| evaluation: { label: "EVALUATION", progress: 76 }, reporting: { label: "REPORTING", progress: 92 }, |
| complete: { label: "COMPLETE", progress: 100 } |
| }; |
| |
| const state = { |
| phase: "idle", running: false, paused: false, speed: 1, phaseElapsed: 0, |
| lastTick: performance.now(), papersFound: 0, evaluated: 0, results: [], |
| limit: 10, requestId: "", report: "", phaseLogged: false |
| }; |
| |
| const el = id => document.getElementById(id); |
| const topology = el("topology"); |
| const runButton = el("runButton"); |
| const pauseButton = el("pauseButton"); |
| const ranking = el("ranking"); |
| |
| function formatTime() { |
| return new Intl.DateTimeFormat("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, timeZone: "America/New_York" }).format(new Date()) + " ET"; |
| } |
| |
| function addLog(type, message, color = "var(--cyan)") { |
| const row = document.createElement("div"); |
| row.className = "log-line"; |
| row.style.setProperty("--log-color", color); |
| row.innerHTML = `<span class="log-time">${formatTime().slice(0,8)}</span><span class="log-type">${type}</span><span class="log-msg"></span>`; |
| row.querySelector(".log-msg").textContent = message; |
| el("eventLog").prepend(row); |
| while (el("eventLog").children.length > 28) el("eventLog").lastChild.remove(); |
| } |
| |
| function setPhase(phase) { |
| state.phase = phase; |
| state.phaseElapsed = 0; |
| state.phaseLogged = false; |
| topology.dataset.phase = phase; |
| el("phasePill").textContent = PHASES[phase].label; |
| el("coverage").textContent = PHASES[phase].progress + "%"; |
| el("supervisorStrip").style.setProperty("--supervisor-progress", PHASES[phase].progress / 100); |
| updateTopology(); |
| updateCards(); |
| } |
| |
| function updateTopology() { |
| const activeMap = { planning: "planner", discovery: "discovery", evaluation: "evaluation", reporting: "report" }; |
| const doneByPhase = { |
| idle: [], initialization: [], planning: [], discovery: ["planner"], |
| evaluation: ["planner", "discovery"], reporting: ["planner", "discovery", "evaluation"], |
| complete: ["planner", "discovery", "evaluation", "report"] |
| }; |
| ["planner", "discovery", "evaluation", "report"].forEach(name => { |
| const node = el("node-" + name); |
| node.classList.toggle("active", activeMap[state.phase] === name); |
| node.classList.toggle("done", doneByPhase[state.phase].includes(name)); |
| }); |
| el("node-supervisor").classList.toggle("active", state.phase !== "idle" && state.phase !== "complete"); |
| document.querySelectorAll(".route").forEach(route => route.classList.remove("route-active")); |
| const routes = { |
| planning: ["routeSupervisorPlanner", "routePlannerSupervisor"], |
| discovery: ["routeSupervisorDiscovery", "routeArxivDiscovery", "routeDiscoverySupervisor"], |
| evaluation: ["routeSupervisorEvaluation", "routeEvaluationSupervisor"], |
| reporting: ["routeSupervisorReport"] |
| }; |
| (routes[state.phase] || []).forEach(id => el(id).classList.add("route-active")); |
| } |
| |
| function cardState(name, mode, task, progress) { |
| const card = el("card-" + name); |
| card.classList.remove("active", "done"); |
| if (mode !== "idle") card.classList.add(mode); |
| card.querySelector(".status-badge").textContent = mode === "active" ? "Working" : mode === "done" ? "Done" : "Idle"; |
| card.querySelector(".agent-task").textContent = task; |
| card.querySelector(".progress-fill").style.width = Math.max(0, Math.min(100, progress)) + "%"; |
| } |
| |
| function updateCards() { |
| const p = state.phaseElapsed; |
| const defaults = { |
| planner: ["idle", "Waiting for a research objective", 0], |
| discovery: ["idle", "Standing by for execution plan", 0], |
| evaluation: ["idle", "Waiting for validated papers", 0], |
| report: ["idle", "Waiting for evaluation results", 0] |
| }; |
| const order = ["planner", "discovery", "evaluation", "report"]; |
| const completed = { |
| discovery: ["planner"], evaluation: ["planner", "discovery"], |
| reporting: ["planner", "discovery", "evaluation"], complete: order |
| }[state.phase] || []; |
| completed.forEach(name => defaults[name] = ["done", name === "report" ? "Executive report generated" : "State returned to Supervisor", 100]); |
| |
| if (state.phase === "planning") defaults.planner = ["active", p < 1300 ? "Parsing objective and temporal constraints" : "Building keywords, categories, and success criteria", p / 32]; |
| if (state.phase === "discovery") defaults.discovery = ["active", state.papersFound < state.limit ? `Searching arXiv and validating metadata (${state.papersFound}/${state.limit})` : "Deduplicating and finalizing paper set", Math.min(100, p / 60)]; |
| if (state.phase === "evaluation") defaults.evaluation = ["active", `Scoring paper ${Math.min(state.evaluated + 1, state.limit)} of ${state.limit} across 10 AGI dimensions`, state.limit ? state.evaluated / state.limit * 100 : 0]; |
| if (state.phase === "reporting") defaults.report = ["active", p < 1500 ? "Ranking findings and computing distribution" : "Writing executive insights and recommendations", p / 28]; |
| |
| order.forEach(name => cardState(name, ...defaults[name])); |
| el("activeCount").textContent = ["planning", "discovery", "evaluation", "reporting"].includes(state.phase) ? "1 active" : "0 active"; |
| } |
| |
| function supervisorDecision(text) { el("supervisorDecision").textContent = text; } |
| |
| function scoreColor(score) { |
| if (score >= 70) return "var(--green)"; |
| if (score >= 40) return "var(--amber)"; |
| return "var(--rose)"; |
| } |
| |
| function renderRanking() { |
| if (!state.results.length) return; |
| ranking.innerHTML = ""; |
| [...state.results].sort((a,b) => b.score - a.score).forEach((paper, index) => { |
| const card = document.createElement("article"); |
| card.className = "paper-card"; |
| card.style.setProperty("--score", paper.score + "%"); |
| card.style.setProperty("--score-color", scoreColor(paper.score)); |
| card.innerHTML = `<div class="paper-row"><div class="paper-rank">#${String(index + 1).padStart(2, "0")}</div><div><div class="paper-title"></div><div class="paper-meta"></div></div><div class="paper-score">${paper.score}<span>/100</span></div></div><div class="score-track"><div class="score-fill"></div></div>`; |
| card.querySelector(".paper-title").textContent = paper.title; |
| card.querySelector(".paper-meta").textContent = paper.authors + " / arXiv / " + (paper.score >= 70 ? "High" : paper.score >= 40 ? "Medium" : "Low"); |
| ranking.appendChild(card); |
| }); |
| } |
| |
| function renderFramework() { |
| const view = el("view-framework"); |
| view.innerHTML = `<div class="framework-note">Each abstract is evaluated with a strict JSON-only prompt. Weighted scores are converted to a 0-100 AGI potential score. The data shown in this browser experience is simulated.</div>`; |
| CRITERIA.forEach(([name, weight]) => { |
| const item = document.createElement("div"); |
| item.className = "criterion"; |
| item.innerHTML = `<div class="criterion-row"><span></span><strong>${weight}%</strong></div><div class="criterion-track"><span style="width:${weight * 4}%"></span></div>`; |
| item.querySelector(".criterion-row span").textContent = name; |
| view.appendChild(item); |
| }); |
| } |
| |
| function advancePaperDiscovery() { |
| const target = Math.min(state.limit, Math.floor(state.phaseElapsed / 470)); |
| if (target > state.papersFound) { |
| for (let i = state.papersFound; i < target; i++) addLog("DISC", `Paper ${i + 1} received from arXiv and passed metadata validation`, "var(--cyan)"); |
| state.papersFound = target; |
| } |
| } |
| |
| function advanceEvaluation() { |
| const target = Math.min(state.limit, Math.floor(state.phaseElapsed / 680)); |
| if (target > state.evaluated) { |
| for (let i = state.evaluated; i < target; i++) { |
| const [title, authors, base] = PAPER_LIBRARY[i]; |
| const score = Math.max(10, Math.min(94, base + ((state.requestId.charCodeAt(3) + i * 3) % 5 - 2))); |
| state.results.push({ title, authors, score }); |
| addLog("EVAL", `${title.slice(0, 36)} scored ${score}/100`, scoreColor(score)); |
| } |
| state.evaluated = target; |
| renderRanking(); |
| } |
| } |
| |
| function calculateAverage() { |
| return state.results.length ? Math.round(state.results.reduce((sum, p) => sum + p.score, 0) / state.results.length) : 0; |
| } |
| |
| function generateReport() { |
| const sorted = [...state.results].sort((a,b) => b.score - a.score); |
| const high = sorted.filter(p => p.score >= 70).length; |
| const medium = sorted.filter(p => p.score >= 40 && p.score < 70).length; |
| const low = sorted.filter(p => p.score < 40).length; |
| const findings = sorted.slice(0,5).map((p,i) => `${i + 1}. ${p.title}\n Authors: ${p.authors}\n AGI Score: ${p.score}/100`).join("\n\n"); |
| state.report = `# AGI Research Analysis Report\n\n## Executive Summary\n\nResearch Objective: ${el("queryInput").value}\n\nPapers discovered: ${state.papersFound}\nPapers evaluated: ${state.evaluated}\nAverage AGI score: ${calculateAverage()}/100\n\n## AGI Potential Distribution\n\n- High AGI Potential: ${high}\n- Medium AGI Potential: ${medium}\n- Low AGI Potential: ${low}\n\n## Top Papers\n\n${findings}\n\n## Recommended Actions\n\n1. Deepen analysis of the highest-potential papers.\n2. Track developments from the leading research groups.\n3. Expand discovery to full-text analysis and additional sources.\n\n---\nGenerated by the AI Research Multi-Agent System simulation.\n`; |
| el("downloadReport").classList.add("visible"); |
| } |
| |
| function updateMetrics() { |
| el("papersFound").textContent = state.papersFound; |
| el("papersEvaluated").textContent = state.evaluated; |
| el("avgScore").textContent = state.results.length ? calculateAverage() : "--"; |
| el("systemState").textContent = state.paused ? "PIPELINE PAUSED" : state.running ? "PIPELINE ACTIVE" : state.phase === "complete" ? "RUN COMPLETE" : "SYSTEM READY"; |
| el("logState").textContent = state.paused ? "paused" : state.running ? "streaming" : "listening"; |
| } |
| |
| function runPhaseLogic() { |
| const p = state.phaseElapsed; |
| if (state.phase === "initialization") { |
| supervisorDecision("Assigning request ID and loading clean research state"); |
| if (!state.phaseLogged) { addLog("SUPV", "INITIALIZATION -> PLANNING", "var(--amber)"); state.phaseLogged = true; } |
| if (p >= 900) setPhase("planning"); |
| } else if (state.phase === "planning") { |
| supervisorDecision(p < 1300 ? "Planner is extracting dates and focus areas" : "Validating structured execution plan"); |
| if (!state.phaseLogged) { addLog("PLAN", "Parsing query into keywords, sources, dates, and success criteria", "var(--blue)"); state.phaseLogged = true; } |
| if (p >= 3200) { addLog("SUPV", "PLANNING -> DISCOVERY / execution plan accepted", "var(--amber)"); setPhase("discovery"); } |
| } else if (state.phase === "discovery") { |
| advancePaperDiscovery(); |
| supervisorDecision(state.papersFound < state.limit ? `Monitoring arXiv paper search / ${state.papersFound} validated` : "Reviewing deduplication and source validation summary"); |
| if (!state.phaseLogged) { addLog("TOOL", "arXiv search started across cs.AI, cs.LG, and cs.CL", "var(--cyan)"); state.phaseLogged = true; } |
| if (p >= Math.max(5400, state.limit * 470 + 800)) { addLog("SUPV", `DISCOVERY -> EVALUATION / ${state.papersFound} papers found`, "var(--amber)"); setPhase("evaluation"); } |
| } else if (state.phase === "evaluation") { |
| advanceEvaluation(); |
| supervisorDecision(state.evaluated < state.limit ? `Evaluating abstract ${state.evaluated + 1} of ${state.limit} with weighted AGI rubric` : "Checking score distribution and evaluation completeness"); |
| if (!state.phaseLogged) { addLog("MODEL", "JSON-only AGI evaluator initialized with 10 weighted parameters", "var(--violet)"); state.phaseLogged = true; } |
| if (p >= state.limit * 680 + 900) { addLog("SUPV", "EVALUATION -> COMPLETION / report requested", "var(--amber)"); setPhase("reporting"); } |
| } else if (state.phase === "reporting") { |
| supervisorDecision(p < 1500 ? "Sorting results and identifying high-potential papers" : "Generating executive summary and recommended actions"); |
| if (!state.phaseLogged) { addLog("RPRT", "Synthesizing ranked findings and score distribution", "var(--green)"); state.phaseLogged = true; } |
| if (p >= 2800) { |
| generateReport(); |
| setPhase("complete"); |
| state.running = false; |
| supervisorDecision(`Research complete / ${state.evaluated} papers scored / report ready`); |
| addLog("DONE", `Pipeline completed with average AGI score ${calculateAverage()}/100`, "var(--green)"); |
| runButton.textContent = "Run again"; |
| runButton.classList.remove("running"); |
| pauseButton.disabled = true; |
| } |
| } |
| updateCards(); |
| updateMetrics(); |
| } |
| |
| function tick(now) { |
| const delta = now - state.lastTick; |
| state.lastTick = now; |
| if (state.running && !state.paused) { |
| state.phaseElapsed += delta * state.speed; |
| runPhaseLogic(); |
| } |
| requestAnimationFrame(tick); |
| } |
| |
| function startSimulation() { |
| if (state.paused) { |
| state.paused = false; |
| pauseButton.textContent = "II"; |
| runButton.textContent = "Research running"; |
| addLog("SUPV", "Pipeline resumed", "var(--amber)"); |
| return; |
| } |
| if (state.running) return; |
| resetSimulation(false); |
| state.limit = Number(el("paperLimit").value); |
| state.requestId = "RQ-" + Math.random().toString(36).slice(2, 8).toUpperCase(); |
| el("requestId").textContent = state.requestId; |
| state.running = true; |
| runButton.textContent = "Research running"; |
| runButton.classList.add("running"); |
| pauseButton.disabled = false; |
| setPhase("initialization"); |
| addLog("START", `Research request ${state.requestId} accepted`, "var(--green)"); |
| updateMetrics(); |
| } |
| |
| function pauseSimulation() { |
| if (!state.running) return; |
| state.paused = !state.paused; |
| pauseButton.textContent = state.paused ? ">" : "II"; |
| runButton.textContent = state.paused ? "Resume research" : "Research running"; |
| if (state.paused) addLog("SUPV", "Pipeline paused by operator", "var(--amber)"); |
| updateMetrics(); |
| } |
| |
| function resetSimulation(log = true) { |
| state.running = false; state.paused = false; state.phaseElapsed = 0; |
| state.papersFound = 0; state.evaluated = 0; state.results = []; state.report = ""; state.requestId = ""; |
| el("requestId").textContent = "No request"; |
| el("downloadReport").classList.remove("visible"); |
| ranking.innerHTML = `<div class="empty-state"><div><div class="empty-radar"></div><div class="empty-title">Research queue ready</div><div class="empty-copy">Run the workflow to discover, validate, score, and rank simulated AGI papers.</div></div></div>`; |
| runButton.textContent = "Run research"; |
| runButton.classList.remove("running"); |
| pauseButton.textContent = "II"; |
| pauseButton.disabled = true; |
| setPhase("idle"); |
| supervisorDecision("Awaiting research objective"); |
| updateMetrics(); |
| if (log) addLog("RESET", "Research state cleared", "var(--muted)"); |
| } |
| |
| function downloadReport() { |
| const blob = new Blob([state.report], { type: "text/markdown" }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement("a"); |
| a.href = url; a.download = `agi-research-report-${state.requestId.toLowerCase()}.md`; a.click(); |
| URL.revokeObjectURL(url); |
| } |
| |
| el("paperLimit").addEventListener("input", event => el("paperLimitValue").textContent = event.target.value); |
| runButton.addEventListener("click", () => state.paused ? pauseSimulation() : startSimulation()); |
| pauseButton.addEventListener("click", pauseSimulation); |
| el("resetButton").addEventListener("click", () => resetSimulation(true)); |
| el("downloadReport").addEventListener("click", downloadReport); |
| document.querySelectorAll(".speed-button").forEach(button => button.addEventListener("click", () => { |
| document.querySelectorAll(".speed-button").forEach(b => b.classList.remove("active")); |
| button.classList.add("active"); state.speed = Number(button.dataset.speed); |
| addLog("SPEED", `Simulation speed set to ${button.textContent}`, "var(--violet)"); |
| })); |
| document.querySelectorAll(".tab").forEach(button => button.addEventListener("click", () => { |
| document.querySelectorAll(".tab").forEach(b => { b.classList.toggle("active", b === button); b.setAttribute("aria-selected", b === button); }); |
| document.querySelectorAll(".tab-view").forEach(view => view.classList.remove("active")); |
| el("view-" + button.dataset.tab).classList.add("active"); |
| })); |
| |
| renderFramework(); |
| el("clock").textContent = formatTime(); |
| setInterval(() => el("clock").textContent = formatTime(), 1000); |
| addLog("READY", "Supervisor online / all agents standing by", "var(--green)"); |
| requestAnimationFrame(tick); |
| </script> |
| </body> |
| </html> |
|
|