@timmeck/brain-core 2.36.32 → 2.36.33
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/command-center.html +146 -4
- package/dist/codegen/feature-recommender.d.ts +103 -0
- package/dist/codegen/feature-recommender.js +428 -0
- package/dist/codegen/feature-recommender.js.map +1 -0
- package/dist/codegen/index.d.ts +2 -0
- package/dist/codegen/index.js +1 -0
- package/dist/codegen/index.js.map +1 -1
- package/dist/cross-brain/client.d.ts +4 -1
- package/dist/cross-brain/client.js +23 -1
- package/dist/cross-brain/client.js.map +1 -1
- package/dist/dashboard/command-center-server.d.ts +2 -0
- package/dist/dashboard/command-center-server.js +14 -1
- package/dist/dashboard/command-center-server.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/research/research-orchestrator.d.ts +2 -0
- package/dist/research/research-orchestrator.js +22 -0
- package/dist/research/research-orchestrator.js.map +1 -1
- package/package.json +1 -1
package/command-center.html
CHANGED
|
@@ -231,6 +231,7 @@ canvas{display:block;width:100%;height:100%}
|
|
|
231
231
|
<div class="sidebar-brand">COMMAND CENTER<span>Brain Ecosystem</span></div>
|
|
232
232
|
<div class="nav-section">Views</div>
|
|
233
233
|
<div class="nav-item active" data-page="overview"><span class="nav-icon">🌍</span><span class="nav-label">Ecosystem</span></div>
|
|
234
|
+
<div class="nav-item" data-page="entity"><span class="nav-icon">👻</span><span class="nav-label" data-t="Bewusstsein">Bewusstsein</span></div>
|
|
234
235
|
<div class="nav-item" data-page="learning"><span class="nav-icon">🧠</span><span class="nav-label" data-t="Lern-Kreislauf">Lern-Kreislauf</span></div>
|
|
235
236
|
<div class="nav-item" data-page="trading"><span class="nav-icon">📈</span><span class="nav-label">Trading Flow</span></div>
|
|
236
237
|
<div class="nav-item" data-page="marketing"><span class="nav-icon">📣</span><span class="nav-label">Marketing Flow</span></div>
|
|
@@ -321,6 +322,18 @@ canvas{display:block;width:100%;height:100%}
|
|
|
321
322
|
</div>
|
|
322
323
|
</div>
|
|
323
324
|
|
|
325
|
+
<!-- ════ Page: Entity — Consciousness ═════════════════ -->
|
|
326
|
+
<div class="page" id="page-entity">
|
|
327
|
+
<div style="position:relative;height:calc(100vh - 160px);min-height:400px">
|
|
328
|
+
<canvas id="entityCanvas" style="position:absolute;top:0;left:0;width:100%;height:100%"></canvas>
|
|
329
|
+
<div style="position:absolute;bottom:20px;left:50%;transform:translateX(-50%);text-align:center;pointer-events:none">
|
|
330
|
+
<div id="entityMoodLabel" style="font-size:20px;font-weight:700;letter-spacing:2px;text-shadow:0 0 20px currentColor"></div>
|
|
331
|
+
<div id="entityScoreLabel" style="font-size:11px;color:var(--text-dim);margin-top:4px"></div>
|
|
332
|
+
</div>
|
|
333
|
+
<div id="entityDimChips" style="position:absolute;bottom:80px;left:50%;transform:translateX(-50%);display:flex;gap:8px;flex-wrap:wrap;justify-content:center;pointer-events:none"></div>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
|
|
324
337
|
<!-- ════ Page 2: Lern-Kreislauf ═════════════════════ -->
|
|
325
338
|
<div class="page" id="page-learning">
|
|
326
339
|
<div class="section">
|
|
@@ -691,7 +704,8 @@ canvas{display:block;width:100%;height:100%}
|
|
|
691
704
|
const state = {
|
|
692
705
|
ecosystem:null, engines:[], watchdog:[], plugins:[], borg:null, analytics:null,
|
|
693
706
|
llm:null, thoughts:[], connected:false, lastThoughtTime:0,
|
|
694
|
-
errors:null, selfmod:null, missions:null, knowledge:null, debates:null
|
|
707
|
+
errors:null, selfmod:null, missions:null, knowledge:null, debates:null,
|
|
708
|
+
emotional:null, attention:null
|
|
695
709
|
};
|
|
696
710
|
|
|
697
711
|
// ── i18n ──────────────────────────────────────────────────
|
|
@@ -784,7 +798,7 @@ const translations = { en: {
|
|
|
784
798
|
'Gesamt-Neustarts':'Total Restarts','Längste Laufzeit':'Longest Uptime','Dienste':'Services',
|
|
785
799
|
'Keine Plugins installiert':'No plugins installed','Geladen':'Loaded','Keine Engines':'No engines',
|
|
786
800
|
'Strategien':'Strategies','BORG AKTIV':'BORG ACTIVE','gesendet':'sent','empfangen':'received',
|
|
787
|
-
'Der Lern-Kreislauf':'The Learning Cycle','Aktivität & Missionen':'Activity & Missions',
|
|
801
|
+
'Der Lern-Kreislauf':'The Learning Cycle','Aktivität & Missionen':'Activity & Missions','Bewusstsein':'Consciousness',
|
|
788
802
|
}};
|
|
789
803
|
let currentLang = localStorage.getItem('brain-lang') || 'en';
|
|
790
804
|
function t(text) { if (currentLang === 'en' && translations.en[text]) return translations.en[text]; return text; }
|
|
@@ -810,13 +824,14 @@ function getLocale() { return currentLang === 'de' ? 'de-DE' : 'en-US'; }
|
|
|
810
824
|
// ── Navigation ────────────────────────────────────────────
|
|
811
825
|
function getTitle(page) {
|
|
812
826
|
const titles = {
|
|
813
|
-
overview:'Ecosystem Overview', learning:t('Der Lern-Kreislauf'), trading:'Trading Flow',
|
|
827
|
+
overview:'Ecosystem Overview', entity:t('Bewusstsein'), learning:t('Der Lern-Kreislauf'), trading:'Trading Flow',
|
|
814
828
|
marketing:'Marketing Flow', intelligence:t('Intelligenz'), crossbrain:'Cross-Brain & Borg', activity:t('Aktivität & Missionen'),
|
|
815
829
|
debates:'Debates & Challenges', infra:t('Infrastruktur')
|
|
816
830
|
}; return titles[page] || '';
|
|
817
831
|
}
|
|
818
832
|
const titles = {
|
|
819
833
|
overview:'Ecosystem Overview',
|
|
834
|
+
entity:'Bewusstsein',
|
|
820
835
|
learning:'Der Lern-Kreislauf',
|
|
821
836
|
trading:'Trading Flow',
|
|
822
837
|
marketing:'Marketing Flow',
|
|
@@ -854,6 +869,7 @@ function connectSSE() {
|
|
|
854
869
|
es.addEventListener('intelligence', e => { state.intelligence = JSON.parse(e.data); renderIntelligence(); });
|
|
855
870
|
es.addEventListener('knowledge', e => { state.knowledge = JSON.parse(e.data); renderKnowledge(); });
|
|
856
871
|
es.addEventListener('debates', e => { state.debates = JSON.parse(e.data); renderDebates(); });
|
|
872
|
+
es.addEventListener('emotional', e => { state.emotional = JSON.parse(e.data); });
|
|
857
873
|
es.onerror = () => { state.connected = false; updateConnection(); };
|
|
858
874
|
}
|
|
859
875
|
|
|
@@ -873,6 +889,7 @@ async function loadInitial() {
|
|
|
873
889
|
state.errors = data.errors; state.selfmod = data.selfmod;
|
|
874
890
|
state.missions = data.missions; state.knowledge = data.knowledge; state.repoAbsorber = data.repoAbsorber; state.intelligence = data.intelligence;
|
|
875
891
|
state.debates = data.debates;
|
|
892
|
+
state.emotional = data.emotional;
|
|
876
893
|
if (data.thoughts) { state.thoughts = data.thoughts; renderThoughts(); }
|
|
877
894
|
renderEcosystem(); renderEngines(); renderWatchdog(); renderPlugins();
|
|
878
895
|
renderBorg(); renderAnalytics(); renderLLM(); renderErrors();
|
|
@@ -1621,10 +1638,135 @@ function fmtUp(s) { if(s<60) return Math.round(s)+'s'; if(s<3600) return Math.ro
|
|
|
1621
1638
|
function formatK(n) { if(n>=1e6) return (n/1e6).toFixed(1)+'M'; if(n>=1e3) return (n/1e3).toFixed(1)+'K'; return String(n); }
|
|
1622
1639
|
function escHtml(s) { const d=document.createElement('div'); d.textContent=s; return d.innerHTML; }
|
|
1623
1640
|
|
|
1641
|
+
// ═══ THE ENTITY — CONSCIOUSNESS VISUALIZATION ═══
|
|
1642
|
+
var MOOD_COLORS = {
|
|
1643
|
+
flow:{r:0,g:229,b:255,name:'Flow'},excited:{r:255,g:215,b:0,name:'Excited'},
|
|
1644
|
+
anxious:{r:255,g:61,b:61,name:'Anxious'},reflective:{r:179,g:136,b:255,name:'Reflective'},
|
|
1645
|
+
bored:{r:110,g:122,b:138,name:'Bored'},determined:{r:224,g:230,b:240,name:'Determined'}
|
|
1646
|
+
};
|
|
1647
|
+
var entColor={r:179,g:136,b:255}, entTarget={r:179,g:136,b:255};
|
|
1648
|
+
var entParticles=[], entTentacles=[], entFloating=[];
|
|
1649
|
+
for(var ti=0;ti<10;ti++) entTentacles.push({angle:ti/10*Math.PI*2,phase:Math.random()*Math.PI*2,speed:0.3+Math.random()*0.4,lenMul:0.8+Math.random()*0.4,widMul:0.7+Math.random()*0.6});
|
|
1650
|
+
for(var pi=0;pi<80;pi++) entParticles.push({angle:Math.random()*Math.PI*2,dist:0.5+Math.random()*2.5,speed:0.1+Math.random()*0.3,size:0.5+Math.random()*1.5,phase:Math.random()*Math.PI*2,brightness:0.2+Math.random()*0.5});
|
|
1651
|
+
|
|
1652
|
+
function entLerp(a,b,t){return{r:a.r+(b.r-a.r)*t,g:a.g+(b.g-a.g)*t,b:a.b+(b.b-a.b)*t}}
|
|
1653
|
+
function entRgba(c,a){return'rgba('+Math.round(c.r)+','+Math.round(c.g)+','+Math.round(c.b)+','+a+')'}
|
|
1654
|
+
|
|
1655
|
+
function drawEntityCanvas(){
|
|
1656
|
+
var canvas=document.getElementById('entityCanvas');
|
|
1657
|
+
if(!canvas||canvas.offsetParent===null) return;
|
|
1658
|
+
var wrap=canvas.parentElement,dpr=window.devicePixelRatio||1;
|
|
1659
|
+
var ww=wrap.clientWidth,wh=wrap.clientHeight;
|
|
1660
|
+
if(ww<20||wh<20) return;
|
|
1661
|
+
if(Math.abs(canvas.width-ww*dpr)>2){canvas.width=ww*dpr;canvas.height=wh*dpr;canvas.style.width=ww+'px';canvas.style.height=wh+'px'}
|
|
1662
|
+
var ctx=canvas.getContext('2d');ctx.setTransform(dpr,0,0,dpr,0,0);
|
|
1663
|
+
var w=ww,h=wh,cx=w/2,cy=h/2,time=Date.now()/1000;
|
|
1664
|
+
var em=state.emotional||{},dim=em.dimensions||{};
|
|
1665
|
+
var mc=MOOD_COLORS[em.mood]||MOOD_COLORS.reflective;
|
|
1666
|
+
entTarget={r:mc.r,g:mc.g,b:mc.b};entColor=entLerp(entColor,entTarget,0.03);
|
|
1667
|
+
ctx.clearRect(0,0,w,h);
|
|
1668
|
+
// Breathing
|
|
1669
|
+
var breathSpeed=0.4+(dim.stress||0)*1.2,breathAmp=0.06+(dim.curiosity||0)*0.04;
|
|
1670
|
+
var breath=1+Math.sin(time*breathSpeed)*breathAmp;
|
|
1671
|
+
var minDim=Math.min(w,h),baseR=minDim*0.13;
|
|
1672
|
+
var activity=Math.min(1,(state.thoughts.length||0)/80);
|
|
1673
|
+
var entityR=baseR*breath*(0.85+activity*0.15);
|
|
1674
|
+
// Nebula
|
|
1675
|
+
var neb=ctx.createRadialGradient(cx,cy,entityR*0.5,cx,cy,minDim*0.45);
|
|
1676
|
+
neb.addColorStop(0,entRgba(entColor,0.04));neb.addColorStop(0.4,entRgba(entColor,0.015));neb.addColorStop(1,'rgba(5,8,16,0)');
|
|
1677
|
+
ctx.fillStyle=neb;ctx.fillRect(0,0,w,h);
|
|
1678
|
+
// Tentacles
|
|
1679
|
+
var curiosity=dim.curiosity||0.5,creativity=dim.creativity||0.5,stress=dim.stress||0;
|
|
1680
|
+
var tentLen=entityR*(1.5+curiosity*2+creativity*0.8),tentAlpha=0.12+(1-stress)*0.15;
|
|
1681
|
+
for(var t=0;t<entTentacles.length;t++){
|
|
1682
|
+
var tn=entTentacles[t],ba=tn.angle+Math.sin(time*tn.speed+tn.phase)*0.3,len=tentLen*tn.lenMul,wid=(3+creativity*4)*tn.widMul;
|
|
1683
|
+
var sx=cx+Math.cos(ba)*entityR*0.9,sy=cy+Math.sin(ba)*entityR*0.9;
|
|
1684
|
+
var w1=Math.sin(time*0.7+tn.phase*2)*0.4,w2=Math.cos(time*0.5+tn.phase*3)*0.5;
|
|
1685
|
+
var cp1x=cx+Math.cos(ba+w1)*(entityR+len*0.35),cp1y=cy+Math.sin(ba+w1)*(entityR+len*0.35);
|
|
1686
|
+
var cp2x=cx+Math.cos(ba+w2)*(entityR+len*0.7),cp2y=cy+Math.sin(ba+w2)*(entityR+len*0.7);
|
|
1687
|
+
var ex=cx+Math.cos(ba+w1*0.5+w2*0.3)*(entityR+len),ey=cy+Math.sin(ba+w1*0.5+w2*0.3)*(entityR+len);
|
|
1688
|
+
ctx.beginPath();ctx.moveTo(sx,sy);ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,ex,ey);
|
|
1689
|
+
var grad=ctx.createLinearGradient(sx,sy,ex,ey);grad.addColorStop(0,entRgba(entColor,tentAlpha));grad.addColorStop(0.6,entRgba(entColor,tentAlpha*0.4));grad.addColorStop(1,entRgba(entColor,0));
|
|
1690
|
+
ctx.strokeStyle=grad;ctx.lineWidth=wid;ctx.lineCap='round';ctx.stroke();
|
|
1691
|
+
ctx.beginPath();ctx.moveTo(sx,sy);ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,ex,ey);
|
|
1692
|
+
ctx.strokeStyle=entRgba({r:255,g:255,b:255},tentAlpha*0.3);ctx.lineWidth=1;ctx.stroke();
|
|
1693
|
+
}
|
|
1694
|
+
// Dimension Ring
|
|
1695
|
+
var ringR=entityR*2.8;
|
|
1696
|
+
var dNames=['frustration','curiosity','surprise','confidence','satisfaction','stress','momentum','creativity'];
|
|
1697
|
+
var dCols=['#ff3d3d','#40c4ff','#ffab40','#00ff88','#69f0ae','#ff6e40','#b2ff59','#ea80fc'];
|
|
1698
|
+
var arcL=(Math.PI*2)/dNames.length,gap=0.08;
|
|
1699
|
+
for(var di=0;di<dNames.length;di++){
|
|
1700
|
+
var dv=dim[dNames[di]]||0,startA=di*arcL-Math.PI/2+gap/2,endA=startA+arcL-gap;
|
|
1701
|
+
ctx.beginPath();ctx.arc(cx,cy,ringR,startA,endA);
|
|
1702
|
+
ctx.strokeStyle=dCols[di]+Math.round((0.08+dv*0.25)*255).toString(16).padStart(2,'0');
|
|
1703
|
+
ctx.lineWidth=2+dv*4;ctx.lineCap='round';ctx.stroke();
|
|
1704
|
+
if(dv>0.3){var la=(startA+endA)/2,lr=ringR+14;
|
|
1705
|
+
ctx.fillStyle=dCols[di]+'80';ctx.font='8px Segoe UI,sans-serif';ctx.textAlign='center';ctx.textBaseline='middle';
|
|
1706
|
+
ctx.fillText(dNames[di].substring(0,4).toUpperCase(),cx+Math.cos(la)*lr,cy+Math.sin(la)*lr);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
// Particles
|
|
1710
|
+
var momentum=dim.momentum||0;
|
|
1711
|
+
for(var p=0;p<entParticles.length;p++){
|
|
1712
|
+
var pt=entParticles[p];pt.angle+=(pt.speed*(0.5+momentum))*0.016;
|
|
1713
|
+
var pd=entityR*pt.dist+Math.sin(time*0.5+pt.phase)*entityR*0.2;
|
|
1714
|
+
var px=cx+Math.cos(pt.angle)*pd,py=cy+Math.sin(pt.angle)*pd;
|
|
1715
|
+
var pa=pt.brightness*(0.3+Math.sin(time*0.8+pt.phase)*0.2);
|
|
1716
|
+
ctx.beginPath();ctx.arc(px,py,pt.size,0,Math.PI*2);ctx.fillStyle=entRgba(entColor,pa);ctx.fill();
|
|
1717
|
+
}
|
|
1718
|
+
// Outer Glow
|
|
1719
|
+
var glowR=entityR*3.5,og=ctx.createRadialGradient(cx,cy,entityR*0.5,cx,cy,glowR);
|
|
1720
|
+
og.addColorStop(0,entRgba(entColor,0.35));og.addColorStop(0.2,entRgba(entColor,0.15));og.addColorStop(0.5,entRgba(entColor,0.05));og.addColorStop(1,entRgba(entColor,0));
|
|
1721
|
+
ctx.beginPath();ctx.arc(cx,cy,glowR,0,Math.PI*2);ctx.fillStyle=og;ctx.fill();
|
|
1722
|
+
// Main Orb
|
|
1723
|
+
var orbG=ctx.createRadialGradient(cx-entityR*0.25,cy-entityR*0.25,entityR*0.05,cx,cy,entityR);
|
|
1724
|
+
orbG.addColorStop(0,'rgba(255,255,255,0.95)');
|
|
1725
|
+
orbG.addColorStop(0.1,entRgba({r:Math.min(255,entColor.r+100),g:Math.min(255,entColor.g+100),b:Math.min(255,entColor.b+100)},0.9));
|
|
1726
|
+
orbG.addColorStop(0.4,entRgba(entColor,0.85));orbG.addColorStop(0.7,entRgba(entColor,0.6));orbG.addColorStop(1,entRgba(entColor,0.2));
|
|
1727
|
+
ctx.beginPath();ctx.arc(cx,cy,entityR,0,Math.PI*2);ctx.fillStyle=orbG;ctx.fill();
|
|
1728
|
+
ctx.beginPath();ctx.arc(cx,cy,entityR,0,Math.PI*2);ctx.strokeStyle=entRgba(entColor,0.3);ctx.lineWidth=1;ctx.stroke();
|
|
1729
|
+
// Inner Eye
|
|
1730
|
+
var eyeR=entityR*0.2;
|
|
1731
|
+
var eyeG=ctx.createRadialGradient(cx,cy,0,cx,cy,eyeR);
|
|
1732
|
+
eyeG.addColorStop(0,'rgba(255,255,255,0.95)');eyeG.addColorStop(0.4,'rgba(255,255,255,0.5)');eyeG.addColorStop(1,'rgba(255,255,255,0)');
|
|
1733
|
+
ctx.beginPath();ctx.arc(cx,cy,eyeR,0,Math.PI*2);ctx.fillStyle=eyeG;ctx.fill();
|
|
1734
|
+
// Floating thoughts
|
|
1735
|
+
var now=Date.now();
|
|
1736
|
+
for(var fi=entFloating.length-1;fi>=0;fi--){
|
|
1737
|
+
var ft=entFloating[fi],age=now-ft.born;
|
|
1738
|
+
if(age>ft.life){entFloating.splice(fi,1);continue}
|
|
1739
|
+
ft.dist+=ft.speed*0.016;var prog=age/ft.life;
|
|
1740
|
+
ft.alpha=prog<0.15?prog/0.15:prog>0.7?(1-prog)/0.3:1;ft.alpha*=0.7;
|
|
1741
|
+
var ftx=cx+Math.cos(ft.angle)*entityR*(1.5+ft.dist*2),fty=cy+Math.sin(ft.angle)*entityR*(1.5+ft.dist*2);
|
|
1742
|
+
ctx.fillStyle='rgba(200,200,255,'+ft.alpha*0.7+')';ctx.font='9px Segoe UI,sans-serif';ctx.textAlign='center';ctx.textBaseline='middle';
|
|
1743
|
+
ctx.fillText(ft.text,ftx,fty);
|
|
1744
|
+
}
|
|
1745
|
+
// Labels
|
|
1746
|
+
var moodInfo=MOOD_COLORS[em.mood]||MOOD_COLORS.reflective;
|
|
1747
|
+
var moodEl=document.getElementById('entityMoodLabel'),scoreEl=document.getElementById('entityScoreLabel');
|
|
1748
|
+
if(moodEl){moodEl.textContent=moodInfo.name;moodEl.style.color=entRgba(entColor,1)}
|
|
1749
|
+
if(scoreEl) scoreEl.textContent='Score: '+Math.round((em.score||0.5)*100)+'% | Valence: '+(em.valence||0).toFixed(2)+' | Arousal: '+(em.arousal||0).toFixed(2);
|
|
1750
|
+
// Dimension chips
|
|
1751
|
+
var chipEl=document.getElementById('entityDimChips');
|
|
1752
|
+
if(chipEl&&chipEl.childElementCount===0){
|
|
1753
|
+
var ch='';for(var ci=0;ci<dNames.length;ci++){
|
|
1754
|
+
ch+='<div style="background:rgba(10,14,26,0.7);border:1px solid '+dCols[ci]+'30;border-radius:6px;padding:4px 10px;font-size:9px;display:flex;gap:6px;align-items:center">'+
|
|
1755
|
+
'<span style="color:'+dCols[ci]+';text-transform:uppercase;letter-spacing:1px">'+dNames[ci].substring(0,5)+'</span>'+
|
|
1756
|
+
'<span id="entdim-'+dNames[ci]+'" style="color:var(--text-dim)">0%</span></div>';
|
|
1757
|
+
}chipEl.innerHTML=ch;
|
|
1758
|
+
}
|
|
1759
|
+
for(var ui=0;ui<dNames.length;ui++){var dvel=document.getElementById('entdim-'+dNames[ui]);if(dvel)dvel.textContent=Math.round((dim[dNames[ui]]||0)*100)+'%'}
|
|
1760
|
+
}
|
|
1761
|
+
function entityLoop(){drawEntityCanvas();requestAnimationFrame(entityLoop)}
|
|
1762
|
+
// Spawn floating thought on notable thoughts
|
|
1763
|
+
var origAddThought=addThought;
|
|
1764
|
+
addThought=function(t){origAddThought(t);if(t.significance==='notable'||t.significance==='breakthrough'){if(entFloating.length>=12)entFloating.shift();entFloating.push({text:(t.content||'').substring(0,40),angle:Math.random()*Math.PI*2,dist:0.2,speed:0.15+Math.random()*0.1,alpha:1,born:Date.now(),life:6000+Math.random()*4000})}};
|
|
1765
|
+
|
|
1624
1766
|
// ── Init ──────────────────────────────────────────────────
|
|
1625
1767
|
document.getElementById('langToggle').textContent = currentLang.toUpperCase();
|
|
1626
1768
|
updateStaticTexts();
|
|
1627
|
-
connectSSE(); loadInitial(); initCrossBrainCanvas();
|
|
1769
|
+
connectSSE(); loadInitial(); initCrossBrainCanvas(); entityLoop();
|
|
1628
1770
|
window.addEventListener('resize', () => { if(state.ecosystem?.brains) drawPeerGraph(state.ecosystem.brains); });
|
|
1629
1771
|
</script>
|
|
1630
1772
|
</body>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { FeatureExtractor } from './feature-extractor.js';
|
|
3
|
+
import type { RAGEngine } from '../rag/rag-engine.js';
|
|
4
|
+
import type { KnowledgeGraphEngine } from '../knowledge-graph/graph-engine.js';
|
|
5
|
+
import type { ThoughtStream } from '../consciousness/thought-stream.js';
|
|
6
|
+
export interface FeatureWish {
|
|
7
|
+
id: number;
|
|
8
|
+
need: string;
|
|
9
|
+
reason: string;
|
|
10
|
+
priority: number;
|
|
11
|
+
matchedFeatureId: number | null;
|
|
12
|
+
matchedFeatureName: string | null;
|
|
13
|
+
matchScore: number;
|
|
14
|
+
status: 'open' | 'matched' | 'adopted' | 'dismissed';
|
|
15
|
+
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface FeatureConnection {
|
|
19
|
+
id: number;
|
|
20
|
+
featureIdA: number;
|
|
21
|
+
featureIdB: number;
|
|
22
|
+
nameA: string;
|
|
23
|
+
nameB: string;
|
|
24
|
+
relationship: string;
|
|
25
|
+
strength: number;
|
|
26
|
+
reason: string;
|
|
27
|
+
}
|
|
28
|
+
export interface RecommendationResult {
|
|
29
|
+
wishesCreated: number;
|
|
30
|
+
connectionsFound: number;
|
|
31
|
+
matchesFound: number;
|
|
32
|
+
durationMs: number;
|
|
33
|
+
}
|
|
34
|
+
export interface FeatureRecommenderStatus {
|
|
35
|
+
totalWishes: number;
|
|
36
|
+
openWishes: number;
|
|
37
|
+
matchedWishes: number;
|
|
38
|
+
adoptedWishes: number;
|
|
39
|
+
totalConnections: number;
|
|
40
|
+
lastScanAt: string | null;
|
|
41
|
+
}
|
|
42
|
+
export declare class FeatureRecommender {
|
|
43
|
+
private readonly db;
|
|
44
|
+
private readonly log;
|
|
45
|
+
private featureExtractor;
|
|
46
|
+
private ragEngine;
|
|
47
|
+
private knowledgeGraph;
|
|
48
|
+
private thoughtStream;
|
|
49
|
+
private lastScanAt;
|
|
50
|
+
constructor(db: Database.Database);
|
|
51
|
+
setFeatureExtractor(fe: FeatureExtractor): void;
|
|
52
|
+
setRAGEngine(rag: RAGEngine): void;
|
|
53
|
+
setKnowledgeGraph(kg: KnowledgeGraphEngine): void;
|
|
54
|
+
setThoughtStream(ts: ThoughtStream): void;
|
|
55
|
+
private ensureTables;
|
|
56
|
+
/**
|
|
57
|
+
* Full recommendation cycle: detect needs → match features → build connections.
|
|
58
|
+
* Called periodically by ResearchOrchestrator.
|
|
59
|
+
*/
|
|
60
|
+
runCycle(): Promise<RecommendationResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Detect needs by analyzing Brain's own data (errors, tool usage, knowledge gaps).
|
|
63
|
+
*/
|
|
64
|
+
private detectNeeds;
|
|
65
|
+
/**
|
|
66
|
+
* Match open wishes against extracted features.
|
|
67
|
+
*/
|
|
68
|
+
private matchWishesToFeatures;
|
|
69
|
+
/**
|
|
70
|
+
* Build connections between extracted features based on tags and co-occurrence.
|
|
71
|
+
*/
|
|
72
|
+
private buildConnections;
|
|
73
|
+
/**
|
|
74
|
+
* Calculate how well a feature matches a need.
|
|
75
|
+
*/
|
|
76
|
+
private calculateMatchScore;
|
|
77
|
+
/**
|
|
78
|
+
* Get the feature wishlist (what Brain wants).
|
|
79
|
+
*/
|
|
80
|
+
getWishlist(status?: string): FeatureWish[];
|
|
81
|
+
/**
|
|
82
|
+
* Get connections for a specific feature (what goes well with it).
|
|
83
|
+
*/
|
|
84
|
+
getConnections(featureId?: number): FeatureConnection[];
|
|
85
|
+
/**
|
|
86
|
+
* Get "if you have X, you could also use Y" suggestions.
|
|
87
|
+
*/
|
|
88
|
+
getRelatedSuggestions(featureName: string): Array<{
|
|
89
|
+
feature: string;
|
|
90
|
+
relationship: string;
|
|
91
|
+
reason: string;
|
|
92
|
+
strength: number;
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Adopt a feature (mark wish as fulfilled).
|
|
96
|
+
*/
|
|
97
|
+
adoptFeature(wishId: number): void;
|
|
98
|
+
/**
|
|
99
|
+
* Dismiss a wish (not needed).
|
|
100
|
+
*/
|
|
101
|
+
dismissWish(wishId: number): void;
|
|
102
|
+
getStatus(): FeatureRecommenderStatus;
|
|
103
|
+
}
|