Add nightly realm reports and observed bot activity explanations
Core tests / core (push) Successful in 59s
Core tests / core (push) Successful in 59s
This commit is contained in:
+3
-1
@@ -1,4 +1,5 @@
|
||||
'use client';
|
||||
import {RealmInsights} from './realm-insights';
|
||||
import {CommunityPanel,OperationsPanel} from './community-panel';
|
||||
import { useState,useEffect,useCallback } from 'react';
|
||||
import { LayoutDashboard,Users,BookOpen,Compass,Server,Activity,Brain,Sparkles,Plus,Play,Pause,ArrowRight,Shield,Terminal,ScrollText,Radio,RefreshCw,Heart,MapPin,Network,Copy,Send,House,Globe2,Moon,Sun,Skull,Clock3 } from 'lucide-react';
|
||||
@@ -17,7 +18,7 @@ import { Table,TableHeader,TableRow,TableHead,TableBody,TableCell } from '@/comp
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Toaster,toast } from 'sonner';
|
||||
import type { State,Bot,Recipe,RealmEvent,Activity as BotActivity } from '@/core/types';
|
||||
const NAV=[['Dashboard',LayoutDashboard],['World Monitor',Globe2],['Social Life',Heart],['System Health',Activity],['Realm Director',Compass],['World & Housing',House],['Bots',Users],['Bot Recipes',BookOpen],['Memory & Bonds',Heart],['Event Stream',Activity],['GM Console',Terminal],['Server & Models',Server]] as const;
|
||||
const NAV=[['Dashboard',LayoutDashboard],['World Monitor',Globe2],['Nightly Report',ScrollText],['Bot Activity',Clock3],['Social Life',Heart],['System Health',Activity],['Realm Director',Compass],['World & Housing',House],['Bots',Users],['Bot Recipes',BookOpen],['Memory & Bonds',Heart],['Event Stream',Activity],['GM Console',Terminal],['Server & Models',Server]] as const;
|
||||
const ACTIVITIES:BotActivity[]=['explore','quest','socialize','trade','rest'];
|
||||
function Choice({value,onChange,items,label}:{value:string;onChange:(v:string)=>void;items:{value:string;label:string}[];label:string}){return <Select value={value} onValueChange={onChange}><SelectTrigger aria-label={label}><SelectValue/></SelectTrigger><SelectContent>{items.map(i=><SelectItem key={i.value} value={i.value}>{i.label}</SelectItem>)}</SelectContent></Select>}
|
||||
const options=(items:string[])=>items.map(value=>({value,label:value}));
|
||||
@@ -42,6 +43,7 @@ export default function Home({readOnly=false}:{readOnly?:boolean}){
|
||||
<div className="page-heading"><div><div className="eyebrow">{page==='GM Console'?'THE WORLD IS YOUR SANDBOX':'AZEROTHAI CONTROL PLANE'}</div><h1>{page==='Dashboard'?'Your realm, alive.':page}</h1><p className="subtitle">{({'Dashboard':'The people, personalities, and stories that make your world.','World Monitor':'Watch Azeroth breathe: population, activity, systems, and the lives unfolding right now.','Realm Director':'Shape the adventure around you. Let your characters bring it to life.','World & Housing':'Homes, routines, simulation bands, and believable population flow.','Bots':'Give every character a purpose, then let their story unfold.','Bot Recipes':'Same model. Different personalities. A world of possibilities.','Memory & Bonds':'A shared history makes the next encounter matter.','Event Stream':'Follow the decisions and changes happening across your realm.','GM Console':'Pull up a chair. Put on the blue robe. Run your world.','Server & Models':'Connect the game engine and the minds behind your characters.'} as any)[page]}</p></div><div className="actions">{readOnly?<Button variant="outline" onClick={()=>void refresh()}><RefreshCw size={15}/>Refresh</Button>:page==='Bot Recipes'?<Button onClick={()=>{setRecipe(null);setRecipeOpen(true)}}><Plus size={16}/>Create recipe</Button>:<><Button variant="outline" disabled={busy} onClick={()=>void refresh()}><RefreshCw size={15}/>Refresh</Button><Button onClick={()=>setCreateOpen(true)}><Plus size={16}/>Create bot</Button></>}</div></div>
|
||||
{error&&<div className="notice" role="alert">{error} <Button variant="outline" onClick={()=>void refresh()}>Retry</Button></div>}
|
||||
{!state?<div className="stats">{[1,2,3,4].map(n=><Skeleton key={n} className="h-32"/>)}</div>:<>
|
||||
{(page==='Nightly Report'||page==='Bot Activity')&&<RealmInsights mode={page}/>}
|
||||
{page==='Dashboard'&&<><div className="stats">{[[Users,'Active bots',state.bots.filter(b=>b.status==='online'&&(state.settings.connector==='simulation'||b.autonomy?.managed)).length,'Online in the simulation'],[BookOpen,'Bot recipes',state.recipes.length,'Distinct ways to experience the world'],[Brain,'Memories',state.bots.reduce((n,b)=>n+b.memories.length,0),'Stories carried into future decisions'],[Network,'Relationships',state.bots.reduce((n,b)=>n+b.relationships.length,0),'Directed bonds between characters']].map(([Icon,label,value,note]:any)=><div className="panel stat" key={label}><div className="stat-label">{label}<Icon/></div><div className="stat-value">{value}</div><small>{label==='Active bots'&&state.settings.connector!=='simulation'?'Acknowledged by the game bridge':note}</small></div>)}</div><section className="panel director-strip"><div className="director-content"><Compass className="director-icon"/><div><div className="eyebrow">YOUR NEXT ADVENTURE</div><h2>{state.director.experience}</h2><p>{state.director.zone} · {state.director.brief}</p></div></div><Button variant="outline" onClick={()=>nav('Realm Director')}>{readOnly?'View realm direction':'Shape the experience'} <ArrowRight size={15}/></Button></section><div className="dashboard-grid"><Panel title="Your characters" icon={Users} action={<Button variant="ghost" size="sm" onClick={()=>nav('Bots')}>{readOnly?'View bots':'Manage bots'} <ArrowRight size={14}/></Button>}>{botTable(state.bots.slice(0,5))}</Panel><Panel title="Realm pulse" icon={Radio}><div className="panel-body">{Array.from(new Set(state.bots.filter(b=>b.status==='online').map(b=>b.zone))).map(zone=>{const n=state.bots.filter(b=>b.status==='online'&&b.zone===zone).length;return <div className="zone-row" key={zone}><span className="zone-label">{zone}</span><span className="bar"><i style={{width:`${n/Math.max(1,state.bots.filter(b=>b.status==='online').length)*100}%`}}/></span><span>{n}</span></div>})}<p className="fineprint">Bot locations from the selected connector. Simulation locations are illustrative.</p><div className="engine-box" style={{marginTop:25,marginBottom:0}}><Brain size={23}/><div><h3>{state.settings.provider==='deterministic'?'Personality simulator':state.settings.model}</h3><p>{state.settings.provider==='deterministic'?'No model required. Try a decision from any online bot.':'Local model selected. Each decision includes identity and memories.'}</p></div></div></div></Panel><Panel title="Recent activity" icon={Activity} action={<Button variant="ghost" size="sm" onClick={()=>nav('Event Stream')}>View stream <ArrowRight size={14}/></Button>}>{<Events events={state.events.slice(-5)}/>}</Panel><Panel title="The Game Master’s chair" icon={Shield}><div className="panel-body"><p className="list-muted">Set the scene. Announce a gathering. Move a character to the next chapter of their story.</p><div className="gm-preview"><span><GM> AzerothAI</span><p>Welcome to your world.</p><code>.announce An adventure awaits...</code></div><Button variant="outline" onClick={()=>nav('GM Console')}>Open GM console <Terminal size={15}/></Button></div></Panel></div></>}
|
||||
{page==='World Monitor'&&<WorldMonitor state={state} monitor={monitor} capabilities={capabilities} openBot={setBotId}/>}
|
||||
{page==='Bots'&&<><div className="toolbar"><Input aria-label="Search bots" placeholder="Search name, class, or location…" value={query} onChange={e=>setQuery(e.target.value)}/><Choice label="Bot status" value={filter} onChange={setFilter} items={options(['all','online','paused','offline','retired'])}/><small>{visible.length} characters</small></div><Panel title="Bot lifecycle" icon={Users}>{visible.length?botTable(visible):<div className="empty-note">No matching bots. Create a character or adjust your filters.</div>}</Panel></>}
|
||||
|
||||
Reference in New Issue
Block a user