@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.
@@ -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">&#x1F30D;</span><span class="nav-label">Ecosystem</span></div>
234
+ <div class="nav-item" data-page="entity"><span class="nav-icon">&#x1F47B;</span><span class="nav-label" data-t="Bewusstsein">Bewusstsein</span></div>
234
235
  <div class="nav-item" data-page="learning"><span class="nav-icon">&#x1F9E0;</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">&#x1F4C8;</span><span class="nav-label">Trading Flow</span></div>
236
237
  <div class="nav-item" data-page="marketing"><span class="nav-icon">&#x1F4E3;</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
+ }