peon-mem 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.js +134 -3
- package/dist/embedding-store.d.ts +2 -0
- package/dist/embedding-store.js +52 -5
- package/dist/embeddings.d.ts +30 -0
- package/dist/embeddings.js +68 -5
- package/dist/monitor.js +224 -14
- package/dist/roundtable.d.ts +104 -0
- package/dist/roundtable.js +787 -0
- package/package.json +1 -1
package/dist/monitor.js
CHANGED
|
@@ -23,10 +23,12 @@ const CLIENT_SCRIPT = String.raw `
|
|
|
23
23
|
stale: "aged out — not recalled by default",
|
|
24
24
|
conflicted: "contradicts another belief"
|
|
25
25
|
};
|
|
26
|
-
var ROUTES = ["brain","projects","overview","memory","ops"];
|
|
26
|
+
var ROUTES = ["brain","projects","overview","memory","roundtable","ops"];
|
|
27
27
|
var ui = { project:"", filter:"all", search:null, focus:null, editing:null };
|
|
28
28
|
var latest = null, overview = null, network = null, dash = null, busy = false;
|
|
29
29
|
var ovLoadedAt = 0, netLoadedAt = 0, dashLoadedAt = 0, HEAVY_TTL = 12000;
|
|
30
|
+
var rtRuns = [], rtAgents = null, rtLoadedAt = 0, rtSelected = null, rtBusy = false, rtDrafts = {}, rtWorkTabs = {};
|
|
31
|
+
var rtStream = null, rtStreamProject = "";
|
|
30
32
|
// Load state for the heavy endpoints. Without this, a page renders its EMPTY state while data is
|
|
31
33
|
// still in flight — /network takes seconds on a large brain, so "No projects yet" was shown as
|
|
32
34
|
// fact for the whole wait, and stayed forever if the request failed (the catch was silent).
|
|
@@ -97,17 +99,19 @@ const CLIENT_SCRIPT = String.raw `
|
|
|
97
99
|
|
|
98
100
|
function renderRoute(force){
|
|
99
101
|
var r=currentRoute();
|
|
102
|
+
document.body.classList.toggle("room-theme",r==="roundtable");
|
|
100
103
|
ROUTES.forEach(function(x){ var p=EL("page-"+x); if(p) p.hidden=(x!==r); });
|
|
101
104
|
// The project dropdown is CONTEXT, not chrome: it only applies inside a project's
|
|
102
105
|
// Insights/Memory pages. Global pages (Neural Core / Sectors / Systems) hide it —
|
|
103
106
|
// switching projects there happens by picking a galaxy or a sector card.
|
|
104
|
-
var sw=EL("switcher"); if(sw) sw.hidden=!(r==="overview"||r==="memory");
|
|
107
|
+
var sw=EL("switcher"); if(sw) sw.hidden=!(r==="overview"||r==="memory"||r==="roundtable");
|
|
105
108
|
// Nav highlight: overview/memory belong under "projects".
|
|
106
|
-
["brain","projects","ops"].forEach(function(x){ var t=EL("nav-"+x); if(t) t.classList.toggle("on", x===r || ((r==="overview"||r==="memory")&&x==="projects")); });
|
|
109
|
+
["brain","projects","roundtable","ops"].forEach(function(x){ var t=EL("nav-"+x); if(t) t.classList.toggle("on", x===r || ((r==="overview"||r==="memory")&&x==="projects")); });
|
|
107
110
|
if(r==="brain"){ loadDashboard(force); renderBrainHome(); }
|
|
108
111
|
else if(r==="projects"){ loadNetwork(force); renderProjectsGrid(); }
|
|
109
112
|
else if(r==="overview"){ loadOverview(force); renderOverviewPage(); }
|
|
110
113
|
else if(r==="memory") renderMemoryPage();
|
|
114
|
+
else if(r==="roundtable") loadRoundtable(force);
|
|
111
115
|
else if(r==="ops") renderOpsPage();
|
|
112
116
|
}
|
|
113
117
|
|
|
@@ -674,6 +678,149 @@ const CLIENT_SCRIPT = String.raw `
|
|
|
674
678
|
renderProjectsGrid();
|
|
675
679
|
}
|
|
676
680
|
|
|
681
|
+
// ===== ROUNDTABLE (Codex + Claude in a shared, alternating conversation) =====
|
|
682
|
+
async function loadRoundtable(force){
|
|
683
|
+
if(!ui.project){ renderRoundtablePage(); return; }
|
|
684
|
+
if(!force&&rtStream&&rtStreamProject===ui.project)return;
|
|
685
|
+
var active=rtRuns.some(function(r){return r.status==="queued"||r.status==="running"||r.status==="executing";});
|
|
686
|
+
var ttl=active?1800:6000;
|
|
687
|
+
if(!force && (freshNow()-rtLoadedAt)<ttl){ if(!roomInputFocused())renderRoundtablePage(); return; }
|
|
688
|
+
rtLoadedAt=freshNow();
|
|
689
|
+
try{
|
|
690
|
+
var data=await Promise.all([
|
|
691
|
+
fetch("/roundtable/status",{cache:"no-store"}).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.json();}),
|
|
692
|
+
fetch("/roundtable/runs?projectPath="+encodeURIComponent(ui.project),{cache:"no-store"}).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.json();})
|
|
693
|
+
]);
|
|
694
|
+
rtAgents=data[0].agents||null; rtRuns=data[1].runs||[];
|
|
695
|
+
if(!rtSelected&&rtRuns.length) rtSelected=rtRuns[0].id;
|
|
696
|
+
connectRoundtableStream();
|
|
697
|
+
}catch(e){ rtAgents=null; }
|
|
698
|
+
if(!roomInputFocused())renderRoundtablePage();
|
|
699
|
+
}
|
|
700
|
+
function roomInputFocused(){var a=document.activeElement;return !!(a&&a.hasAttribute&&a.hasAttribute("data-rt-message-input"));}
|
|
701
|
+
function connectRoundtableStream(){
|
|
702
|
+
if(!ui.project||!window.EventSource)return;
|
|
703
|
+
if(rtStream&&rtStreamProject===ui.project)return;
|
|
704
|
+
if(rtStream)rtStream.close();
|
|
705
|
+
rtStreamProject=ui.project;rtStream=new EventSource("/roundtable/events?projectPath="+encodeURIComponent(ui.project));
|
|
706
|
+
rtStream.onmessage=function(event){
|
|
707
|
+
try{var run=JSON.parse(event.data),found=false;rtRuns=rtRuns.map(function(current){if(current.id===run.id){found=true;return run;}return current;});if(!found)rtRuns.unshift(run);rtRuns.sort(function(a,b){return b.createdAt.localeCompare(a.createdAt);});if(!rtSelected)rtSelected=run.id;if(!roomInputFocused())renderRoundtablePage();}catch(e){}
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
function renderRoundtablePage(){
|
|
711
|
+
var body=EL("rt-body"); if(!body) return;
|
|
712
|
+
if(!ui.project){ body.innerHTML='<div class="empty">Select a project first.</div>'; return; }
|
|
713
|
+
var ca=rtAgents&&rtAgents.codex, cl=rtAgents&&rtAgents.claude;
|
|
714
|
+
var team='<section class="rtstudio-card rtteam"><div class="rtstudio-label">Research team</div><div class="rtteammate codex"><div class="rtminiavatar">C</div><div>'+agentBadge("Codex",ca)+'<p>Builds, tests, and challenges Claude.</p></div></div><div class="rtteammate claude"><div class="rtminiavatar">C</div><div>'+agentBadge("Claude",cl)+'<p>Investigates independently, challenges Codex, and audits the evidence.</p></div></div><small>Both agents receive the same room transcript and thesis context.</small></section>';
|
|
715
|
+
var form='<details class="rtstudio-card rtstudio-new"><summary>Start a new conversation</summary><div class="rtnewbody"><div class="rtautodesc">Greet them, ask questions, explore ideas, or disagree. A conversation never approves or runs work.</div>'+
|
|
716
|
+
'<textarea id="rt-question" maxlength="4000" placeholder="Optional topic — leave blank for an open thesis discussion."></textarea>'+
|
|
717
|
+
'<div class="rtactions"><span class="mono" id="rt-msg">No implementation without approval.</span><button class="btn" id="rt-start"'+((!ca||!ca.available||!cl||!cl.available||rtBusy)?" disabled":"")+'>Start conversation</button></div></div></details>';
|
|
718
|
+
var chosen=rtRuns.find(function(r){return r.id===rtSelected;})||rtRuns[0];
|
|
719
|
+
var detail=chosen?roundtableRun(chosen):'<section class="panel"><div class="empty">No discussions yet. Start an autonomous roundtable when you are ready.</div></section>';
|
|
720
|
+
var history='<section class="rtstudio-card rtstudio-history"><div class="rtstudio-sectionhead"><span>Conversations</span><small>'+rtRuns.length+' saved</small></div><div class="rthistory">'+(rtRuns.length?rtRuns.slice(0,12).map(function(r){var label=r.mode==="autonomous"?"Autonomous agenda from Peon memory":r.question;return '<button class="rthist'+(chosen&&chosen.id===r.id?' on':'')+'" data-rt-run="'+esc(r.id)+'"><span>'+esc(clip(label,58))+'</span><small class="rtstate '+esc(r.status)+'">'+esc(r.status)+'</small></button>';}).join(""):'<div class="rtworkempty">No saved conversations yet.</div>')+'</div></section>';
|
|
721
|
+
var goal='<section class="rtstudio-card rtgoal"><span>Thesis objective</span><b>70% on Mini-Dev</b><strong>GPT-OSS-120B</strong><small>Produce at least one measurable, publishable contribution. Every implementation remains approval-gated.</small></section>';
|
|
722
|
+
var checkpoint=chosen?'<section class="rtstudio-card rtcheckpoint"><span>Current checkpoint</span><b>'+esc(chosen.liveSummary||"The room is ready for the next evidence-backed step.")+'</b><small>'+esc(chosen.status==="open"?"Discussion is open":stageLabel(chosen.stage||chosen.status))+'</small></section>':'';
|
|
723
|
+
var work=chosen?roundtableWorkbench(chosen):'<section class="rtworkbench"><div class="rtworkempty">Work activity will appear here once a conversation starts.</div></section>';
|
|
724
|
+
body.innerHTML='<div class="rtstudio"><aside class="rtstudio-nav">'+goal+team+checkpoint+form+history+'</aside><main class="rtstudio-main">'+detail+'</main><aside class="rtstudio-work">'+work+'</aside></div>';
|
|
725
|
+
var start=EL("rt-start"); if(start) start.addEventListener("click",startRoundtable);
|
|
726
|
+
var q=EL("rt-question"); if(q) q.addEventListener("keydown",function(e){if((e.metaKey||e.ctrlKey)&&e.key==="Enter") startRoundtable();});
|
|
727
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-run]"),function(b){b.addEventListener("click",function(){rtSelected=b.getAttribute("data-rt-run");renderRoundtablePage();});});
|
|
728
|
+
wireRoundtableActions();
|
|
729
|
+
var transcript=document.querySelector(".rtturns");if(transcript)transcript.scrollTop=transcript.scrollHeight;
|
|
730
|
+
}
|
|
731
|
+
function agentBadge(label,a){ var ok=a&&a.available; return '<span class="rtagent '+(ok?'ok':'bad')+'"><i></i><b>'+esc(label)+'</b><small>'+esc(a?a.label:"checking client")+'</small></span>'; }
|
|
732
|
+
function roundtableWorkbench(r){
|
|
733
|
+
var turns=r.turns||[], activities=(r.activities||[]).slice();
|
|
734
|
+
if(!activities.length){
|
|
735
|
+
turns.forEach(function(t){
|
|
736
|
+
if(t.agent==="user"||t.agent==="joint")return;
|
|
737
|
+
var content=String(t.content||""), type="", title="";
|
|
738
|
+
if(t.kind==="implementation"){type="code";title="Implementation report";}
|
|
739
|
+
else if(t.kind==="review"){type="review";title="Independent review reported";}
|
|
740
|
+
else if(t.kind==="verification"){type="test";title="Test or verification result";}
|
|
741
|
+
if(type)activities.push({id:t.id,agent:t.agent,type:type,title:title,detail:content,state:/\b(fail|blocking problem|error)\b/i.test(content)?"failed":"info",createdAt:t.createdAt,updatedAt:t.createdAt});
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
var tab=rtWorkTabs[r.id]||"all";
|
|
745
|
+
var filtered=activities.filter(function(a){if(tab==="all")return true;if(tab==="code")return a.type==="code"||a.type==="artifact";if(tab==="tests")return a.type==="test"||a.type==="review";return a.type==="result";}).slice(-10).reverse();
|
|
746
|
+
var hasImplementation=turns.some(function(t){return t.kind==="implementation";});
|
|
747
|
+
var hasReview=turns.some(function(t){return t.kind==="review";});
|
|
748
|
+
var hasVerification=turns.some(function(t){return t.kind==="verification";});
|
|
749
|
+
function phase(label,state){return '<span class="rtworkphase '+state+'"><i></i>'+label+'</span>';}
|
|
750
|
+
var phases=phase("Discuss",turns.length?"done":"waiting")+
|
|
751
|
+
phase("Build",r.stage==="implementation"?"active":hasImplementation?"done":"waiting")+
|
|
752
|
+
phase("Review",r.stage==="review"?"active":hasReview?"done":"waiting")+
|
|
753
|
+
phase("Verify",r.stage==="verification"?"active":hasVerification?"done":"waiting");
|
|
754
|
+
var current=r.stage==="implementation"?"Codex is editing the isolated workspace.":r.stage==="review"?"Claude is reviewing the work without editing it.":r.stage==="verification"?"Codex is fixing findings and running local checks.":r.status==="running"?"Codex and Claude are discussing. No code is being changed in this stage.":r.status==="open"?(hasVerification?"The room is open. Earlier implementation and review activity is saved below.":"The room is open. No approved coding task is running."):hasVerification?"Local implementation, review, and verification finished.":"No approved coding task is running. Discussion remains separate from implementation.";
|
|
755
|
+
var tabs=[["all","All activity"],["code","Code & files"],["tests","Tests & review"],["results","Results"]].map(function(x){return '<button class="'+(tab===x[0]?"on":"")+'" data-rt-work-tab="'+x[0]+'" data-rt-work-run="'+esc(r.id)+'">'+x[1]+'</button>';}).join("");
|
|
756
|
+
var items=filtered.length?filtered.map(function(a){var who=a.agent==="room"?"Room":String(a.agent||"room");var detail=String(a.detail||"");return '<article class="rtworkitem '+esc(a.state||"info")+'"><i></i><div><div class="rtworkitemhead"><b>'+esc(a.title||"Work update")+'</b><span>'+esc(who)+' · '+esc(tm(a.updatedAt||a.createdAt))+'</span></div>'+(detail?'<div class="rtworkbrief">'+esc(clip(detail.replace(/[#>*_|\[\]()]/g," ").replace(/\s+/g," "),220))+'</div><details><summary>Open full activity</summary><pre>'+esc(detail)+'</pre></details>':'')+'</div></article>';}).join(""):'<div class="rtworkempty">Nothing in this view yet. It will update automatically when the agents reach this stage.</div>';
|
|
757
|
+
return '<section class="rtworkbench"><div class="rtworkhead"><div><span>Live Work Bench</span><b>See what the agents are doing</b></div><small>'+(r.status==="running"||r.status==="executing"?'<i></i> Live':'Saved')+'</small></div><div class="rtworkflow">'+phases+'</div><div class="rtworknow">'+esc(current)+'</div><div class="rtworktabs">'+tabs+'</div><div class="rtworkfeed">'+items+'</div><div class="rtworksafe">Shows visible work, files, tests, reviews, and results. Private reasoning and secrets are never displayed.</div></section>';
|
|
758
|
+
}
|
|
759
|
+
function roundtableRun(r){
|
|
760
|
+
var stage=(r.status==="running"||r.status==="executing")?r.stage:r.status;
|
|
761
|
+
var turns=(r.turns||[]).map(function(t){var speaker=t.agent==="user"?"You":t.agent==="joint"?"Codex + Claude · agreed action":t.agent==="coordinator"?"Earlier room summary":t.agent;var content=String(t.content||"");var long=content.length>900;var message=long?'<div class="rtplain">'+esc(clip(content,520))+'</div><details class="rttechnical"><summary>Open the full detailed message</summary><pre>'+esc(content)+'</pre></details>':'<pre>'+esc(content)+'</pre>';return '<article class="rtturn '+esc(t.agent)+'"><div class="rtturnhead"><span>'+esc(speaker)+'</span><small>'+esc(tm(t.createdAt))+'</small></div>'+message+'</article>';}).join("");
|
|
762
|
+
if(r.status==="queued"||r.status==="running"||r.status==="executing") turns+='<div class="rtprogress"><i></i><span>'+esc(stageLabel(stage))+'</span></div>';
|
|
763
|
+
var canTalk=r.status==="open"||r.status==="awaiting_approval"||r.status==="complete"||r.status==="rejected"||r.status==="failed";
|
|
764
|
+
var talkHint=canTalk?"Talk normally. A greeting stays a greeting; a question becomes a real back-and-forth discussion.":"Codex and Claude are replying. You can keep writing here; Send becomes available when this step finishes.";
|
|
765
|
+
turns+='<div class="rtjoin"><b>Talk to the Thesis Room</b><span>'+esc(talkHint)+'</span><textarea maxlength="4000" data-rt-message-input="'+esc(r.id)+'" placeholder="Talk to Codex and Claude…">'+esc(rtDrafts[r.id]||"")+'</textarea><div><span class="mono">You · Codex · Claude</span><span class="rtjoinbuttons">'+(r.status==="open"?'<button class="btn ghost" data-rt-continue="'+esc(r.id)+'">Continue debate</button><button class="btn ghost" data-rt-propose="'+esc(r.id)+'">Ask for an agreed action</button>':'')+'<button class="btn" data-rt-message="'+esc(r.id)+'"'+(canTalk?'':' disabled')+'>Send to room</button></span></div></div>';
|
|
766
|
+
if(r.status==="awaiting_approval") turns+='<div class="rtapproval"><div><b>Suggested action ready</b><span>You can keep discussing, reject it, or approve implementation and local testing.</span></div><div><button class="btn ghost" data-rt-action="reject" data-rt-id="'+esc(r.id)+'">Reject</button><button class="btn" data-rt-action="approve" data-rt-id="'+esc(r.id)+'">Approve action</button></div></div>';
|
|
767
|
+
if(r.status==="complete"){var verified=(r.turns||[]).some(function(t){return t.kind==="verification";});turns+='<div class="rtapproved">'+(verified?'Implementation, independent review, and local verification are complete. External or paid runs remain separately approval-gated.':'The room paused without claiming agreement. Keep talking to resolve the open point; nothing has been approved or implemented.')+'</div>';}
|
|
768
|
+
if(r.status==="rejected") turns+='<div class="rtrejected">Rejected · kept in discussion history, not saved as a project decision.</div>';
|
|
769
|
+
if(r.error) turns+='<div class="rterror">'+esc(r.error)+'</div>';
|
|
770
|
+
var topic=r.mode==="autonomous"?"Agenda selected from Peon memory":r.question;
|
|
771
|
+
var quick='<div class="rtlivesummary"><span>Quick summary</span><b>'+esc(r.liveSummary||"A one-sentence summary will appear when the next debate turn arrives.")+'</b><small>This updates automatically. The full conversation stays below if you want the details.</small></div>';
|
|
772
|
+
return '<section class="panel rtconversation"><div class="rtchathead"><div><span>Shared room</span><h2>Thesis conversation</h2><small>'+esc(topic)+'</small></div><div class="rtchatpresence"><i class="codex"></i><b>Codex</b><i class="claude"></i><b>Claude</b><span class="rtstate '+esc(r.status)+'">'+esc(stage.replace("_"," "))+'</span></div></div>'+quick+'<div class="rtturns">'+turns+'</div></section>';
|
|
773
|
+
}
|
|
774
|
+
function wireRoundtableActions(){
|
|
775
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-action]"),function(b){b.addEventListener("click",function(){roundtableDecision(b.getAttribute("data-rt-id"),b.getAttribute("data-rt-action"));});});
|
|
776
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-message]"),function(b){b.addEventListener("click",function(){sendRoundtableMessage(b.getAttribute("data-rt-message"));});});
|
|
777
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-propose]"),function(b){b.addEventListener("click",function(){requestAgreedAction(b.getAttribute("data-rt-propose"));});});
|
|
778
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-continue]"),function(b){b.addEventListener("click",function(){continueRoomDebate(b.getAttribute("data-rt-continue"));});});
|
|
779
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-work-tab]"),function(b){b.addEventListener("click",function(){rtWorkTabs[b.getAttribute("data-rt-work-run")]=b.getAttribute("data-rt-work-tab");renderRoundtablePage();});});
|
|
780
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-rt-message-input]"),function(input){var id=input.getAttribute("data-rt-message-input");input.addEventListener("input",function(){rtDrafts[id]=input.value;});input.addEventListener("keydown",function(e){if((e.metaKey||e.ctrlKey)&&e.key==="Enter")sendRoundtableMessage(id);});});
|
|
781
|
+
}
|
|
782
|
+
async function roundtableDecision(id,action){
|
|
783
|
+
if(rtBusy||!id) return; rtBusy=true;
|
|
784
|
+
try{var res=await fetch("/roundtable/runs/"+encodeURIComponent(id)+"/"+action,{method:"POST",headers:{"content-type":"application/json"},body:"{}"});var out=await res.json();if(!res.ok)throw new Error(out.error||"Could not save decision");rtRuns=rtRuns.map(function(r){return r.id===id?out:r;});}
|
|
785
|
+
catch(e){var run=rtRuns.find(function(r){return r.id===id;});if(run)run.error=e.message||"Could not save decision";}
|
|
786
|
+
rtBusy=false;renderRoundtablePage();
|
|
787
|
+
}
|
|
788
|
+
async function requestAgreedAction(id){
|
|
789
|
+
if(rtBusy||!id)return;rtBusy=true;renderRoundtablePage();
|
|
790
|
+
try{var res=await fetch("/roundtable/runs/"+encodeURIComponent(id)+"/propose",{method:"POST",headers:{"content-type":"application/json"},body:"{}"});var out=await res.json();if(!res.ok)throw new Error(out.error||"Could not ask for an agreed action");rtRuns=rtRuns.map(function(r){return r.id===id?out:r;});rtSelected=id;}
|
|
791
|
+
catch(e){var run=rtRuns.find(function(r){return r.id===id;});if(run)run.error=e.message||"Could not ask for an agreed action";}
|
|
792
|
+
rtBusy=false;renderRoundtablePage();
|
|
793
|
+
}
|
|
794
|
+
async function continueRoomDebate(id){
|
|
795
|
+
if(rtBusy||!id)return;rtBusy=true;renderRoundtablePage();
|
|
796
|
+
try{var res=await fetch("/roundtable/runs/"+encodeURIComponent(id)+"/continue",{method:"POST",headers:{"content-type":"application/json"},body:"{}"});var out=await res.json();if(!res.ok)throw new Error(out.error||"Could not continue the debate");rtRuns=rtRuns.map(function(r){return r.id===id?out:r;});rtSelected=id;}
|
|
797
|
+
catch(e){var run=rtRuns.find(function(r){return r.id===id;});if(run)run.error=e.message||"Could not continue the debate";}
|
|
798
|
+
rtBusy=false;renderRoundtablePage();
|
|
799
|
+
}
|
|
800
|
+
async function sendRoundtableMessage(id){
|
|
801
|
+
if(rtBusy||!id)return;
|
|
802
|
+
var input=document.querySelector('[data-rt-message-input="'+CSS.escape(id)+'"]'), message=input?input.value.trim():"";
|
|
803
|
+
if(!message)return;
|
|
804
|
+
rtDrafts[id]=message;
|
|
805
|
+
rtBusy=true;renderRoundtablePage();
|
|
806
|
+
try{var res=await fetch("/roundtable/runs/"+encodeURIComponent(id)+"/message",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({message:message})});var out=await res.json();if(!res.ok)throw new Error(out.error||"Could not send message");delete rtDrafts[id];rtRuns=rtRuns.map(function(r){return r.id===id?out:r;});rtSelected=id;rtLoadedAt=0;}
|
|
807
|
+
catch(e){var run=rtRuns.find(function(r){return r.id===id;});if(run)run.error=e.message||"Could not send message";}
|
|
808
|
+
rtBusy=false;await loadRoundtable(true);
|
|
809
|
+
}
|
|
810
|
+
function stageLabel(s){ return s==="queued"?"Waiting for the current discussion…":s==="discussion"?"The shared room is active. Each agent sees and answers the full conversation…":s==="proposals"?"Codex and Claude are researching and forming independent proposals…":s==="critiques"?"They are reviewing each other’s proposals…":s==="synthesis"?"The room is forming one joint proposal for your approval…":s==="implementation"?"Approved: Codex is implementing and running local tests…":s==="review"?"Claude is independently reviewing the implementation…":s==="verification"?"Codex is addressing findings and verifying the result…":"Working…"; }
|
|
811
|
+
async function startRoundtable(){
|
|
812
|
+
if(rtBusy||!ui.project) return;
|
|
813
|
+
var q=EL("rt-question"), question=q?q.value.trim():"";
|
|
814
|
+
rtBusy=true; renderRoundtablePage();
|
|
815
|
+
try{
|
|
816
|
+
var body={projectPath:ui.project}; if(question) body.question=question;
|
|
817
|
+
var res=await fetch("/roundtable/runs",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(body)});
|
|
818
|
+
var out=await res.json(); if(!res.ok) throw new Error(out.error||"Could not start discussion");
|
|
819
|
+
rtSelected=out.id; rtRuns.unshift(out); if(q)q.value=""; rtLoadedAt=0;
|
|
820
|
+
}catch(e){ var msg=EL("rt-msg"); if(msg) msg.textContent=e.message||"Could not start discussion"; }
|
|
821
|
+
rtBusy=false; await loadRoundtable(true);
|
|
822
|
+
}
|
|
823
|
+
|
|
677
824
|
// ===== OPS (tokens + activity) =====
|
|
678
825
|
function renderOpsPage(){
|
|
679
826
|
/* health strip: serve latency/cost (24h telemetry) + STL daily self-check verdict */
|
|
@@ -704,7 +851,7 @@ const CLIENT_SCRIPT = String.raw `
|
|
|
704
851
|
|
|
705
852
|
// wire-up
|
|
706
853
|
window.addEventListener("hashchange",function(){ renderRoute(true); });
|
|
707
|
-
EL("switcher").addEventListener("change",function(e){ ui.project=e.target.value; ui.search=null; ui.focus=null; ui.editing=null; overview=null; renderRoute(true); });
|
|
854
|
+
EL("switcher").addEventListener("change",function(e){ ui.project=e.target.value; ui.search=null; ui.focus=null; ui.editing=null; overview=null; rtSelected=null; rtRuns=[]; rtLoadedAt=0; renderRoute(true); });
|
|
708
855
|
EL("go").addEventListener("click",runSearch);
|
|
709
856
|
EL("clear").addEventListener("click",function(){ ui.search=null; EL("q").value=""; EL("clear").hidden=true; renderMemoryPage(); });
|
|
710
857
|
EL("q").addEventListener("keydown",function(e){ if(e.key==="Enter") runSearch(); });
|
|
@@ -721,13 +868,13 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
721
868
|
<title>PEON // NEURAL HUD</title>
|
|
722
869
|
<style>
|
|
723
870
|
:root{
|
|
724
|
-
--bg:#
|
|
725
|
-
--line:rgba(
|
|
726
|
-
--ink:#
|
|
727
|
-
--cyan:#
|
|
728
|
-
--green:#
|
|
729
|
-
--blue:#
|
|
730
|
-
--amber:#
|
|
871
|
+
--bg:#0b0d0f; --bg2:#111519; --panel:rgba(22,26,29,.82); --panel2:rgba(17,21,24,.82);
|
|
872
|
+
--line:rgba(171,185,178,.16); --line2:rgba(171,185,178,.32);
|
|
873
|
+
--ink:#e6ebe7; --muted:#a2aba6; --faint:#6f7773;
|
|
874
|
+
--cyan:#87a99a; --cyan-soft:rgba(135,169,154,.11); --cyan-ink:#c4d6ce;
|
|
875
|
+
--green:#87b59b; --green-soft:rgba(135,181,155,.11); --green-ink:#c9ded1;
|
|
876
|
+
--blue:#9aa9b5; --blue-soft:rgba(154,169,181,.12); --violet:#aaa4bd;
|
|
877
|
+
--amber:#d2b878; --amber-soft:rgba(210,184,120,.12); --red:#cc817a;
|
|
731
878
|
--mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace; --r:4px;
|
|
732
879
|
--cham:polygon(10px 0,100% 0,100% calc(100% - 10px),calc(100% - 10px) 100%,0 100%,0 10px);
|
|
733
880
|
}
|
|
@@ -748,6 +895,30 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
748
895
|
body::after{content:""; position:fixed; left:0; right:0; top:-15%; height:26vh; z-index:98; pointer-events:none;
|
|
749
896
|
background:linear-gradient(180deg, transparent, rgba(89,227,255,.045) 55%, rgba(89,227,255,.09) 60%, transparent);
|
|
750
897
|
animation:scanroam 9s linear infinite;}
|
|
898
|
+
body.room-theme{
|
|
899
|
+
--bg:#1d1d1a;--bg2:#24231f;--panel:rgba(42,41,36,.96);--panel2:rgba(35,34,30,.96);
|
|
900
|
+
--line:rgba(226,218,196,.13);--line2:rgba(226,218,196,.28);
|
|
901
|
+
--ink:#f0ede3;--muted:#bbb4a4;--faint:#888174;
|
|
902
|
+
--cyan:#9aaa8d;--cyan-soft:rgba(154,170,141,.12);--cyan-ink:#d7ddcf;
|
|
903
|
+
--green:#9aaa8d;--green-soft:rgba(154,170,141,.12);--green-ink:#d7ddcf;
|
|
904
|
+
--blue:#a69d8c;--blue-soft:rgba(166,157,140,.12);--violet:#b7a8bd;
|
|
905
|
+
--amber:#c5a66f;--amber-soft:rgba(197,166,111,.12);--red:#c58478;
|
|
906
|
+
background:
|
|
907
|
+
radial-gradient(900px 560px at 50% -180px,rgba(154,170,141,.10),transparent 68%),
|
|
908
|
+
linear-gradient(rgba(226,218,196,.018) 1px,transparent 1px),
|
|
909
|
+
linear-gradient(90deg,rgba(226,218,196,.018) 1px,transparent 1px),#1d1d1a;
|
|
910
|
+
background-size:auto,48px 48px,48px 48px,auto;
|
|
911
|
+
}
|
|
912
|
+
body.room-theme::before{background:repeating-linear-gradient(0deg,rgba(244,237,218,.012) 0 1px,transparent 1px 4px)}
|
|
913
|
+
body.room-theme::after{display:none}
|
|
914
|
+
body.room-theme header{background:rgba(29,29,26,.96);box-shadow:0 12px 34px -24px rgba(0,0,0,.8)}
|
|
915
|
+
body.room-theme header::after{background:linear-gradient(90deg,transparent,rgba(154,170,141,.55),transparent);animation:none}
|
|
916
|
+
body.room-theme .logo{background:radial-gradient(circle at 44% 38%,#f1eee3,#aeb9a4 42%,#68745f 72%,#30352c);color:#252820;box-shadow:none}
|
|
917
|
+
body.room-theme .logo::before,body.room-theme .logo::after{border-color:rgba(180,192,168,.35);animation:none}
|
|
918
|
+
body.room-theme nav a{background:rgba(226,218,196,.03)}
|
|
919
|
+
body.room-theme nav a:hover{background:rgba(154,170,141,.10)}
|
|
920
|
+
body.room-theme nav a.on{background:rgba(154,170,141,.16);color:#f0ede3;box-shadow:none;text-shadow:none}
|
|
921
|
+
body.room-theme .switcher{background:#272620}
|
|
751
922
|
@keyframes scanroam{0%{transform:translateY(-30vh);} 100%{transform:translateY(160vh);}}
|
|
752
923
|
h1,h2,h3,p{margin:0;}
|
|
753
924
|
.mono{font-family:var(--mono); font-size:11px; letter-spacing:.02em;}
|
|
@@ -867,9 +1038,9 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
867
1038
|
.revacts{flex:none; display:flex; gap:6px;}
|
|
868
1039
|
|
|
869
1040
|
/* buttons / inputs */
|
|
870
|
-
.btn{padding:8px 16px; clip-path:var(--cham); background:linear-gradient(180deg, rgba(
|
|
871
|
-
color:#
|
|
872
|
-
box-shadow:0 0
|
|
1041
|
+
.btn{padding:8px 16px; clip-path:var(--cham); background:linear-gradient(180deg, rgba(135,169,154,.92), rgba(104,142,127,.92));
|
|
1042
|
+
color:#101713; font-weight:760; font-size:11.5px; letter-spacing:.1em; text-transform:uppercase; border:0; transition:all .15s;
|
|
1043
|
+
box-shadow:0 0 14px -7px rgba(135,169,154,.55);}
|
|
873
1044
|
.btn:hover{filter:brightness(1.12);} .btn:disabled{opacity:.45; cursor:not-allowed;}
|
|
874
1045
|
.btn.ghost{background:rgba(89,227,255,.06); color:var(--cyan-ink); border:1px solid var(--line2); box-shadow:none;}
|
|
875
1046
|
.btn.ghost:hover{background:rgba(89,227,255,.13);}
|
|
@@ -931,6 +1102,37 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
931
1102
|
.pcgo{font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--cyan); margin-top:10px; opacity:0; transition:opacity .15s; text-shadow:0 0 8px rgba(89,227,255,.6);}
|
|
932
1103
|
.pcard:hover .pcgo{opacity:1;}
|
|
933
1104
|
|
|
1105
|
+
/* thesis studio */
|
|
1106
|
+
.rtstudio{display:grid;grid-template-columns:250px minmax(520px,1fr) 360px;gap:14px;align-items:start;max-width:1640px;margin:0 auto}
|
|
1107
|
+
.rtstudio-main{min-width:0}.rtstudio-nav,.rtstudio-work{display:flex;flex-direction:column;gap:12px;min-width:0}.rtstudio-nav,.rtstudio-work{position:sticky;top:74px;max-height:calc(100vh - 92px);overflow:auto;padding-right:2px}
|
|
1108
|
+
.rtstudio-card{border:1px solid rgba(227,220,202,.12);border-radius:16px;background:rgba(38,37,32,.92);box-shadow:0 14px 32px -28px #000}
|
|
1109
|
+
.rtstudio-label,.rtstudio-sectionhead span,.rtcheckpoint>span{font:700 9px var(--mono);letter-spacing:.15em;text-transform:uppercase;color:#b8a578}
|
|
1110
|
+
.rtgoal{display:flex;flex-direction:column;gap:4px;padding:17px;background:linear-gradient(145deg,rgba(154,170,141,.13),rgba(197,166,111,.07))}.rtgoal b{font-size:23px;color:#f3efe4;letter-spacing:-.02em}.rtgoal strong{font:10px var(--mono);letter-spacing:.09em;color:#b9c6ae}.rtgoal small{margin-top:7px;color:var(--muted);font-size:11px;line-height:1.5}
|
|
1111
|
+
.rtteam{padding:14px}.rtteammate{display:grid;grid-template-columns:34px 1fr;gap:9px;align-items:center;padding:11px 0;border-bottom:1px solid rgba(255,255,255,.055)}.rtteammate:last-of-type{border-bottom:0}.rtteammate p{margin:4px 0 0;color:var(--faint);font-size:10px;line-height:1.4}.rtteam>small{display:block;margin-top:10px;color:var(--faint);font:9px/1.45 var(--mono)}
|
|
1112
|
+
.rtminiavatar{width:32px;height:32px;border-radius:10px;display:grid;place-items:center;background:#34372f;border:1px solid rgba(154,170,141,.35);color:#e9e5da;font:700 13px ui-sans-serif}.rtteammate.claude .rtminiavatar{background:#39333b;border-color:rgba(183,168,189,.38)}
|
|
1113
|
+
.rtagent{display:grid;grid-template-columns:8px auto;column-gap:7px;align-items:center}.rtagent i{width:7px;height:7px;border-radius:50%;grid-row:1/3;background:var(--faint)}.rtagent.ok i{background:var(--green);box-shadow:0 0 8px rgba(93,255,176,.65)}.rtagent.bad i{background:var(--red)}.rtagent b{font-size:11px;color:var(--ink)}.rtagent small{font:8.5px var(--mono);color:var(--faint)}
|
|
1114
|
+
.rtcheckpoint{padding:14px}.rtcheckpoint b{display:block;margin:8px 0;color:#dfdbcf;font-size:11.5px;line-height:1.5}.rtcheckpoint small{color:#9aaa8d;font:9px var(--mono);text-transform:uppercase;letter-spacing:.08em}
|
|
1115
|
+
.rtstudio-new{overflow:hidden}.rtstudio-new>summary{padding:13px 14px;color:#ddd5c3;font:700 10px var(--mono);letter-spacing:.08em;text-transform:uppercase;cursor:pointer}.rtnewbody{padding:0 14px 14px}.rtnewbody textarea{width:100%;min-height:78px;resize:vertical;padding:10px 11px;border:1px solid rgba(227,220,202,.13);border-radius:10px;background:#24231f;color:var(--ink);font:12px/1.5 ui-sans-serif}.rtnewbody textarea:focus{outline:none;border-color:#9aaa8d;box-shadow:0 0 0 3px rgba(154,170,141,.09)}
|
|
1116
|
+
.rtactions{display:flex;flex-direction:column;align-items:stretch;gap:8px;margin-top:9px}.rtactions .mono{color:var(--faint);font-size:8.5px}.rtautodesc{padding:9px 10px;border-left:2px solid #9aaa8d;background:rgba(154,170,141,.055);color:var(--muted);line-height:1.5;margin-bottom:9px;border-radius:0 8px 8px 0;font-size:10.5px}
|
|
1117
|
+
.rtstudio-history{padding:13px}.rtstudio-sectionhead{display:flex;align-items:center;justify-content:space-between;margin-bottom:9px}.rtstudio-sectionhead small{font:8px var(--mono);color:var(--faint)}.rthistory{display:flex;flex-direction:column;gap:5px}.rthist{display:flex;justify-content:space-between;align-items:center;gap:8px;text-align:left;padding:8px 9px;border:1px solid rgba(227,220,202,.09);border-radius:9px;background:#292823;color:var(--muted)}.rthist:hover,.rthist.on{border-color:rgba(154,170,141,.48);color:var(--ink);background:rgba(154,170,141,.08)}.rthist span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:10px}
|
|
1118
|
+
.rtstate{font:8px var(--mono);letter-spacing:.1em;text-transform:uppercase;padding:3px 7px;border-radius:999px;background:rgba(255,255,255,.06);color:var(--muted);white-space:nowrap}.rtstate.complete{background:var(--green-soft);color:var(--green-ink)}.rtstate.failed,.rtstate.rejected{background:rgba(255,122,112,.12);color:var(--red)}.rtstate.running,.rtstate.queued,.rtstate.executing{background:rgba(154,170,141,.14);color:#d7ddcf}.rtstate.awaiting_approval{background:var(--amber-soft);color:var(--amber)}.rtstate.open{background:rgba(154,170,141,.14);color:#d7ddcf}
|
|
1119
|
+
.rtconversation{border-radius:20px!important;background:rgba(35,34,30,.94)!important;padding:0!important;overflow:hidden;border-color:rgba(227,220,202,.13)!important}
|
|
1120
|
+
.rtchathead{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:16px 18px;border-bottom:1px solid rgba(227,220,202,.1);background:#292823}.rtchathead>div:first-child{min-width:0}.rtchathead span:first-child{color:#b8a578;font:700 8.5px var(--mono);letter-spacing:.15em;text-transform:uppercase}.rtchathead h2{margin:3px 0 2px;font-size:17px;color:#f0ece2}.rtchathead small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font-size:10px}.rtchatpresence{display:flex;align-items:center;gap:5px;flex:none}.rtchatpresence i{width:7px;height:7px;border-radius:50%}.rtchatpresence i.codex{background:#9aaa8d}.rtchatpresence i.claude{background:#b7a8bd;margin-left:6px}.rtchatpresence b{font:8.5px var(--mono);color:var(--muted)}.rtchatpresence .rtstate{margin-left:8px}
|
|
1121
|
+
.rtlivesummary{display:flex;flex-direction:column;gap:4px;margin:12px 14px 0;padding:12px 14px;border:1px solid rgba(197,166,111,.22);border-radius:12px;background:#302d25}.rtlivesummary span{color:#c5a66f;font:700 8.5px var(--mono);letter-spacing:.13em;text-transform:uppercase}.rtlivesummary b{color:#ebe6dc;font-size:12px;line-height:1.45}.rtlivesummary small{color:var(--faint);font-size:9.5px}
|
|
1122
|
+
.rtturns{display:flex;flex-direction:column;gap:12px;height:calc(100vh - 255px);min-height:560px;overflow-y:auto;padding:15px 15px 0;scroll-behavior:smooth}.rtturn{position:relative;flex:none;max-width:86%;border:1px solid rgba(227,220,202,.11);background:#2b2a25;border-radius:15px;overflow:hidden;box-shadow:0 9px 20px -20px #000}.rtturn.codex{align-self:flex-start;border-left:3px solid #9aaa8d;border-bottom-left-radius:4px}.rtturn.claude{align-self:flex-end;border-right:3px solid #b7a8bd;border-bottom-right-radius:4px}.rtturn.user{align-self:center;max-width:78%;border:1px solid rgba(197,166,111,.34);background:#332f26}.rtturn.joint,.rtturn.coordinator{align-self:center;max-width:92%;border:1px solid rgba(154,170,141,.34);background:#2c3029}
|
|
1123
|
+
.rtturnhead{display:flex;justify-content:space-between;gap:10px;padding:8px 11px;border-bottom:1px solid rgba(227,220,202,.08);font:700 9px var(--mono);letter-spacing:.09em;text-transform:uppercase;color:#bac7af}.rtturn.claude .rtturnhead{color:#c8bed0}.rtturn.user .rtturnhead{color:#d8bd86}.rtturn.joint .rtturnhead,.rtturn.coordinator .rtturnhead{color:var(--green-ink)}.rtturnhead small{color:var(--faint);font-size:8px}
|
|
1124
|
+
.rtturn pre,.rtplain{margin:0;padding:11px 13px;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--ink);font:12.5px/1.58 ui-sans-serif,system-ui}.rttechnical{margin:0 11px 11px;border-top:1px solid rgba(227,220,202,.09);padding-top:8px}.rttechnical summary{color:var(--muted);font-size:10px;cursor:pointer}.rttechnical pre{margin-top:7px;padding:10px;background:#23221e;border-radius:9px;color:#c8c2b4;font:10px/1.5 var(--mono)}
|
|
1125
|
+
.rtprogress{display:flex;align-items:center;gap:9px;padding:11px;color:var(--muted);font-family:var(--mono)}.rtprogress i{width:8px;height:8px;border-radius:50%;background:#9aaa8d;box-shadow:0 0 9px rgba(154,170,141,.8);animation:beat 1.1s infinite}.rterror{padding:11px 13px;color:#ffb0a8;background:rgba(255,122,112,.08);border:1px solid rgba(255,122,112,.24);font-family:var(--mono)}
|
|
1126
|
+
.rtapproval{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 14px;border:1px solid rgba(255,201,87,.34);background:var(--amber-soft);border-radius:12px}.rtapproval>div:first-child{display:flex;flex-direction:column}.rtapproval b{color:var(--amber);font-size:12px}.rtapproval span{color:var(--muted);font-size:11px}.rtapproval>div:last-child{display:flex;gap:8px;flex:none}
|
|
1127
|
+
.rtjoin{position:sticky;bottom:0;z-index:7;display:flex;flex:none;flex-direction:column;gap:7px;margin:4px -15px 0;padding:13px 15px 15px;border-top:1px solid rgba(197,166,111,.25);background:linear-gradient(180deg,rgba(43,41,35,.97),#2b2923);box-shadow:0 -18px 32px -30px #000}.rtjoin>b{color:#ead7ae;font-size:12px}.rtjoin>span{color:var(--muted);font-size:10px}.rtjoin textarea{width:100%;min-height:68px;max-height:180px;resize:vertical;padding:10px 12px;border:1px solid rgba(227,220,202,.15);border-radius:11px;background:#211f1b;color:var(--ink);font:12.5px/1.5 ui-sans-serif}.rtjoin textarea:focus{outline:none;border-color:#c5a66f;box-shadow:0 0 0 3px rgba(197,166,111,.08)}.rtjoin>div{display:flex;align-items:center;justify-content:space-between;gap:10px}.rtjoin .mono{color:var(--faint)}.rtjoinbuttons{display:flex;gap:7px;align-items:center;flex-wrap:wrap}
|
|
1128
|
+
.rtapproved,.rtrejected{padding:10px 12px;font:10px var(--mono);border-radius:10px}.rtapproved{color:var(--green-ink);background:var(--green-soft);border:1px solid rgba(93,255,176,.25)}.rtrejected{color:#ffb0a8;background:rgba(255,122,112,.08);border:1px solid rgba(255,122,112,.24)}
|
|
1129
|
+
.rtstudio-work .rtworkbench{margin:0;padding:15px;border:1px solid rgba(227,220,202,.13);border-radius:17px;background:#282823;box-shadow:0 14px 32px -28px #000}.rtworkhead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:13px}.rtworkhead>div{display:flex;flex-direction:column;gap:3px}.rtworkhead span{color:#aab99d;font:700 9px var(--mono);letter-spacing:.14em;text-transform:uppercase}.rtworkhead b{color:#f0ede3;font-size:14px}.rtworkhead small{display:flex;align-items:center;gap:7px;color:#cbd4c4;font:9px var(--mono);text-transform:uppercase;letter-spacing:.1em}.rtworkhead small i{width:7px;height:7px;border-radius:50%;background:#9aaa8d;box-shadow:0 0 8px rgba(154,170,141,.75);animation:beat 1.1s infinite}
|
|
1130
|
+
.rtworkflow{display:grid;grid-template-columns:repeat(4,1fr);gap:5px;margin-bottom:9px}.rtworkphase{display:flex;align-items:center;gap:5px;padding:7px;border:1px solid rgba(227,220,202,.1);border-radius:9px;color:var(--faint);font:8.5px var(--mono)}.rtworkphase i{width:6px;height:6px;border-radius:50%;background:#5b5a52}.rtworkphase.done{color:#cbd4c4;background:rgba(154,170,141,.07)}.rtworkphase.done i{background:#9aaa8d}.rtworkphase.active{color:#ead7ae;border-color:rgba(197,166,111,.36);background:rgba(197,166,111,.08)}.rtworkphase.active i{background:#c5a66f;box-shadow:0 0 8px rgba(197,166,111,.7);animation:beat 1.1s infinite}
|
|
1131
|
+
.rtworknow{padding:9px 10px;margin-bottom:9px;border-left:3px solid #9aaa8d;border-radius:0 8px 8px 0;background:rgba(154,170,141,.07);color:#d9d6cc;font-size:11px;line-height:1.45}.rtworktabs{display:flex;gap:5px;overflow:auto;margin-bottom:9px}.rtworktabs button{border:1px solid rgba(227,220,202,.1);border-radius:999px;background:#22221e;color:var(--muted);padding:5px 8px;font:8.5px var(--mono);white-space:nowrap}.rtworktabs button:hover,.rtworktabs button.on{border-color:rgba(197,166,111,.45);color:#f0e5cd;background:rgba(197,166,111,.09)}
|
|
1132
|
+
.rtworkfeed{display:flex;flex-direction:column;gap:7px;overflow:auto;padding-right:2px}.rtworkitem{display:grid;grid-template-columns:8px 1fr;gap:8px;padding:9px;border:1px solid rgba(255,255,255,.055);border-radius:10px;background:#23231f}.rtworkitem>i{width:7px;height:7px;border-radius:50%;margin-top:4px;background:#85847a}.rtworkitem.running>i{background:#c5a66f;box-shadow:0 0 8px rgba(197,166,111,.65);animation:beat 1.1s infinite}.rtworkitem.passed>i{background:#9aaa8d}.rtworkitem.failed>i{background:#d78a82}.rtworkitemhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.rtworkitemhead b{font-size:10.5px;color:#ebe7dd}.rtworkitemhead span{font:8px var(--mono);color:var(--faint);text-transform:capitalize}.rtworkbrief{margin-top:4px;color:var(--muted);font-size:10px;line-height:1.4}.rtworkitem details{margin-top:6px}.rtworkitem summary{color:#bdb5a5;font-size:9px;cursor:pointer}.rtworkitem pre{max-height:250px;overflow:auto;margin:7px 0 0;padding:9px;border-radius:8px;background:#1f1f1b;color:#c8c2b4;white-space:pre-wrap;font:9.5px/1.5 var(--mono)}.rtworkempty{padding:14px;text-align:center;color:var(--faint);font-size:10px;border:1px dashed rgba(227,220,202,.12);border-radius:9px}.rtworksafe{margin-top:9px;color:var(--faint);font:8.5px/1.4 var(--mono)}
|
|
1133
|
+
@media(max-width:1280px){.rtstudio{grid-template-columns:220px minmax(480px,1fr)}.rtstudio-work{position:static;grid-column:1/-1;max-height:none}.rtstudio-work .rtworkfeed{max-height:300px}}
|
|
1134
|
+
@media(max-width:820px){.rtstudio{grid-template-columns:1fr}.rtstudio-nav,.rtstudio-work{position:static;max-height:none}.rtstudio-main{grid-row:1}.rtstudio-nav{grid-row:2}.rtstudio-work{grid-row:3}.rtturns{height:auto;min-height:520px;max-height:75vh}.rtturn{max-width:96%}.rtturn.user{max-width:92%}.rtchathead{align-items:flex-start;flex-direction:column}.rtjoin>div,.rtapproval{align-items:stretch;flex-direction:column}.rtworkflow{grid-template-columns:1fr 1fr}.rtworkitemhead{align-items:flex-start;flex-direction:column;gap:2px}}
|
|
1135
|
+
|
|
934
1136
|
/* ops */
|
|
935
1137
|
.bignums{display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:16px;}
|
|
936
1138
|
.bignum{padding:15px 17px;}
|
|
@@ -1064,6 +1266,7 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
1064
1266
|
<nav>
|
|
1065
1267
|
<a id="nav-brain" href="#/brain">Neural Core</a>
|
|
1066
1268
|
<a id="nav-projects" href="#/projects">Sectors</a>
|
|
1269
|
+
<a id="nav-roundtable" href="#/roundtable">Thesis Room</a>
|
|
1067
1270
|
<a id="nav-ops" href="#/ops">Systems</a>
|
|
1068
1271
|
</nav>
|
|
1069
1272
|
<select class="switcher" id="switcher" aria-label="Active project"></select>
|
|
@@ -1130,6 +1333,13 @@ const DOCUMENT = String.raw `<!doctype html>
|
|
|
1130
1333
|
</div>
|
|
1131
1334
|
</section>
|
|
1132
1335
|
|
|
1336
|
+
<!-- SYSTEMS (ops) -->
|
|
1337
|
+
<section id="page-roundtable" hidden>
|
|
1338
|
+
<div class="pagehead">Thesis Room</div>
|
|
1339
|
+
<div class="pagesub">You, Codex, and Claude share one workspace for ongoing thesis research, discussion, decisions, and carefully approved experiments.</div>
|
|
1340
|
+
<div id="rt-body"><div class="empty">Connecting the two agents…</div></div>
|
|
1341
|
+
</section>
|
|
1342
|
+
|
|
1133
1343
|
<!-- SYSTEMS (ops) -->
|
|
1134
1344
|
<section id="page-ops" hidden>
|
|
1135
1345
|
<div class="pagehead">Systems</div>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { ProjectContext } from "./types.js";
|
|
2
|
+
export type RoundtableAgent = "codex" | "claude";
|
|
3
|
+
export type RoundtableAgentMode = "chat" | "research" | "implement" | "review" | "verify";
|
|
4
|
+
export type RoundtableStage = "queued" | "discussion" | "proposals" | "critiques" | "synthesis" | "implementation" | "review" | "verification" | "complete" | "failed";
|
|
5
|
+
export interface RoundtableTurn {
|
|
6
|
+
id: string;
|
|
7
|
+
agent: RoundtableAgent | "joint" | "user";
|
|
8
|
+
kind: "discussion" | "proposal" | "critique" | "recommendation" | "implementation" | "review" | "verification";
|
|
9
|
+
content: string;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RoundtableActivity {
|
|
13
|
+
id: string;
|
|
14
|
+
agent: RoundtableAgent | "room";
|
|
15
|
+
type: "status" | "code" | "test" | "review" | "result" | "artifact";
|
|
16
|
+
title: string;
|
|
17
|
+
detail?: string;
|
|
18
|
+
state: "running" | "passed" | "failed" | "info";
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface RoundtableRun {
|
|
23
|
+
id: string;
|
|
24
|
+
projectPath: string;
|
|
25
|
+
question: string;
|
|
26
|
+
mode: "autonomous" | "focused";
|
|
27
|
+
status: "queued" | "running" | "open" | "awaiting_approval" | "executing" | "complete" | "rejected" | "failed";
|
|
28
|
+
stage: RoundtableStage;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
updatedAt: string;
|
|
31
|
+
turns: RoundtableTurn[];
|
|
32
|
+
activities?: RoundtableActivity[];
|
|
33
|
+
liveSummary?: string;
|
|
34
|
+
synthesizedBy?: RoundtableAgent;
|
|
35
|
+
approvedAt?: string;
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface RoundtableAgentRunner {
|
|
39
|
+
run(agent: RoundtableAgent, prompt: string, projectPath: string, mode?: RoundtableAgentMode): Promise<string>;
|
|
40
|
+
availability(): Promise<Record<RoundtableAgent, {
|
|
41
|
+
available: boolean;
|
|
42
|
+
label: string;
|
|
43
|
+
}>>;
|
|
44
|
+
}
|
|
45
|
+
export interface RoundtableMemoryPort {
|
|
46
|
+
getContext(input: {
|
|
47
|
+
projectPath: string;
|
|
48
|
+
query?: string;
|
|
49
|
+
maxChars?: number;
|
|
50
|
+
}): Promise<ProjectContext>;
|
|
51
|
+
saveProposal(projectPath: string, question: string, proposal: string): Promise<void>;
|
|
52
|
+
saveDecision(projectPath: string, question: string, decision: string): Promise<void>;
|
|
53
|
+
saveResult(projectPath: string, question: string, result: string): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export interface RoundtableManagerOptions {
|
|
56
|
+
stateDir: string;
|
|
57
|
+
memory: RoundtableMemoryPort;
|
|
58
|
+
runner?: RoundtableAgentRunner;
|
|
59
|
+
now?: () => string;
|
|
60
|
+
}
|
|
61
|
+
export declare class RoundtableManager {
|
|
62
|
+
private readonly options;
|
|
63
|
+
private readonly runs;
|
|
64
|
+
private readonly subscribers;
|
|
65
|
+
private readonly runner;
|
|
66
|
+
private readonly now;
|
|
67
|
+
private queue;
|
|
68
|
+
private persistQueue;
|
|
69
|
+
constructor(options: RoundtableManagerOptions);
|
|
70
|
+
initialize(): Promise<void>;
|
|
71
|
+
availability(): Promise<Record<RoundtableAgent, {
|
|
72
|
+
available: boolean;
|
|
73
|
+
label: string;
|
|
74
|
+
}>>;
|
|
75
|
+
list(projectPath?: string): RoundtableRun[];
|
|
76
|
+
get(id: string): RoundtableRun | undefined;
|
|
77
|
+
subscribe(listener: (run: RoundtableRun) => void): () => void;
|
|
78
|
+
start(projectPath: string, rawQuestion?: string): Promise<RoundtableRun>;
|
|
79
|
+
approve(id: string): Promise<RoundtableRun>;
|
|
80
|
+
message(id: string, rawMessage: unknown): Promise<RoundtableRun>;
|
|
81
|
+
propose(id: string): Promise<RoundtableRun>;
|
|
82
|
+
continueDiscussion(id: string): Promise<RoundtableRun>;
|
|
83
|
+
reject(id: string): Promise<RoundtableRun>;
|
|
84
|
+
private execute;
|
|
85
|
+
private executeApproved;
|
|
86
|
+
private startActivity;
|
|
87
|
+
private addActivity;
|
|
88
|
+
private finishActivity;
|
|
89
|
+
private failRunningActivities;
|
|
90
|
+
private concludeAgreement;
|
|
91
|
+
private executeRevision;
|
|
92
|
+
private executeCasualReply;
|
|
93
|
+
private executeProposal;
|
|
94
|
+
private touch;
|
|
95
|
+
private emit;
|
|
96
|
+
private persist;
|
|
97
|
+
}
|
|
98
|
+
export declare class LocalSubscriptionRunner implements RoundtableAgentRunner {
|
|
99
|
+
availability(): Promise<Record<RoundtableAgent, {
|
|
100
|
+
available: boolean;
|
|
101
|
+
label: string;
|
|
102
|
+
}>>;
|
|
103
|
+
run(agent: RoundtableAgent, prompt: string, projectPath: string, mode?: RoundtableAgentMode): Promise<string>;
|
|
104
|
+
}
|