Files
weval-l99/meeting-rooms-populator.py
opus-wire 7f67eb6bdf auto-push
2026-04-18 14:33:55 +02:00

191 lines
7.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
WEVAL Meeting Rooms Auto-Populator — FIXED 18avr 2026
Pipeline: Paperclip → Registry → Enterprise → Meeting Rooms
Runs via cron every 6h30: updates room agents from live infrastructure data
FIX: regex updated to match enterprise-model.html actual agent format:
{n:'NAME',rm:'ROOM',d:'DESC',p:'...',...,F:0|1,...}
"""
import json, subprocess, re, os, datetime
LOG = []
def log(msg):
LOG.append(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}")
print(msg)
# 1. Read enterprise-model agents (source of truth for active agents)
def get_enterprise_agents():
try:
f = '/var/www/html/enterprise-model.html'
c = open(f).read()
agents = []
# Correct format: {n:'NAME',rm:'DEPT',d:'DESC',p:'PURPOSE',...F:0|1,...}
# rm = room/dept (ceo, sal, con, dev, qa, l99, sec, srv, ops, dock, mta, pha, saas, ai, wevia, plat, cron, dead, meet, lean, dir)
pattern = r"\{n:'([^']+)',rm:'([^']+)'[^}]*?F:(\d)"
for m in re.finditer(pattern, c):
agents.append({
'name': m.group(1),
'dept': m.group(2), # rm value (room/dept id)
'active': int(m.group(3))
})
return agents
except Exception as e:
log(f"ERR enterprise: {e}")
return []
# 2. Read registry for crons/pipelines
def get_registry():
try:
r = subprocess.run(['curl','-s','--max-time','5','http://localhost/api/registry.php'],
capture_output=True, text=True, timeout=10)
return json.loads(r.stdout) if r.stdout else {}
except:
return {}
# 3. Read Docker containers
def get_docker():
try:
r = subprocess.run(['docker','ps','--format','{{.Names}}'], capture_output=True, text=True, timeout=10)
return r.stdout.strip().split('\n') if r.stdout.strip() else []
except:
return []
# 4. Map agents to meeting rooms based on:
# (a) Direct room/dept alias mapping (rm value → room_id)
# (b) Keyword matching on name/description
#
# An agent CAN appear in multiple rooms.
# Direct rm (dept) → meeting_room mapping
DEPT_TO_ROOM = {
'ceo': ['strat', 'biz'], # strategy + business
'dir': ['strat'], # directors = strategic
'sal': ['biz'], # sales
'con': ['biz', 'strat'], # consultants
'sdlc': ['dev'], # dev pipeline
'dev': ['dev'], # dev lab
'qa': ['dev'], # QA
'l99': ['dev'], # L99 pilot
'sec': ['sec'], # security
'srv': ['infra'], # infra/servers
'ops': ['infra', 'transit'], # monitoring + transit
'dock': ['infra'], # Docker services
'mta': ['infra'], # mail transport
'pha': ['biz'], # pharma
'saas': ['biz'], # SaaS
'ai': ['ia'], # AI engine
'wevia': ['ia', 'strat'], # WEVIA core = IA + strategic
'plat': ['transit'], # platform transversal
'cron': ['transit', 'infra'], # crons = ops/transit
'meet': ['strat'], # meeting rooms = strategic
'lean': ['strat'], # lean = strategic
'dead': [], # archived — no room
'wire': ['transit'], # to wire = transit
'intg': ['transit'], # to integrate = transit
'dorm': ['transit'], # dormants = transit
}
ROOM_KEYWORDS = {
'strat': ['master','opus','life','blade','mirofish','maitre','chef','lead','ceo','strategy','director','weval','plan','visio'],
'infra': ['cortex','prometheus','kuma','sentinel','docker','infra','monitor','disk','server','pmta','kumo','ops','watchdog','guard'],
'dev': ['nonreg','l99','wedroid','wevcode','evomaster','langfuse','playwright','git','code','test','qa','debug','dev','claude','claw','goose','blueprint','forge'],
'sec': ['dark','crowd','authentik','aegis','vault','strix','nuclei','security','scan','sso','ban','rgpd','audit','verifier'],
'biz': ['paperclip','enterprise','ethica','crm','n8n','twenty','active','lead','pipeline','hcp','b2b','sales','proposal','contract','kaouther','marketing','revenue','stripe'],
'ia': ['ollama','qdrant','deerflow','dify','searx','supermemory','mastra','goose','skillsmith','aios','ai','llm','rag','cerebras','groq','gemini','cog','brain','anything','crewai','autogen','cognitive'],
'transit': ['scanner','factory','rnd','browser','mattermost','plausible','wiki','github','automation','backup','sync','relay','bridge','oss','archi'],
}
def assign_rooms(agents, docker_containers):
rooms = {k: [] for k in ROOM_KEYWORDS}
seen = {k: set() for k in ROOM_KEYWORDS}
for agent in agents:
name_lower = agent['name'].lower()
dept_lower = agent['dept'].lower()
added = False
# Strategy A: direct dept → room mapping
if dept_lower in DEPT_TO_ROOM:
for room_id in DEPT_TO_ROOM[dept_lower]:
if agent['name'] not in seen[room_id]:
rooms[room_id].append(agent)
seen[room_id].add(agent['name'])
added = True
# Strategy B: keyword fallback
for room_id, keywords in ROOM_KEYWORDS.items():
if agent['name'] in seen[room_id]:
continue
for kw in keywords:
if kw in name_lower or kw in dept_lower:
rooms[room_id].append(agent)
seen[room_id].add(agent['name'])
break
# Add Docker containers as infra/ia agents
docker_room_map = {
'prometheus': 'infra', 'node-exporter': 'infra', 'uptime-kuma': 'infra',
'loki': 'infra', 'plausible': 'transit',
'mattermost': 'transit', 'twenty': 'biz',
'searxng': 'ia', 'qdrant': 'ia', 'langfuse': 'ia',
'n8n': 'transit', 'authentik-server': 'sec', 'vaultwarden': 'sec',
'deerflow': 'ia', 'gitea': 'transit',
}
for container in docker_containers:
cname = container.strip().lower()
if not cname: continue
for key, room_id in docker_room_map.items():
if key in cname and f"[docker] {container}" not in seen[room_id]:
rooms[room_id].append({'name': f"[docker] {container}", 'dept': 'docker', 'active': 1})
seen[room_id].add(f"[docker] {container}")
break
return rooms
# 5. Generate meeting room JSON for the page to consume
def generate_meeting_data():
log("=== MEETING ROOMS AUTO-POPULATOR (FIXED 18avr) ===")
agents = get_enterprise_agents()
log(f"Enterprise: {len(agents)} agents")
registry = get_registry()
log(f"Registry: {len(registry)} sections" if isinstance(registry, dict) else "Registry: unavailable")
docker = get_docker()
log(f"Docker: {len(docker)} containers")
rooms = assign_rooms(agents, docker)
result = {
'timestamp': datetime.datetime.now().isoformat(),
'source': 'auto-populator-v2-fixed-18avr',
'enterprise_total_agents': len(agents),
'docker_total': len(docker),
'rooms': {}
}
for room_id, room_agents in rooms.items():
active_count = sum(1 for a in room_agents if a.get('active', 0) == 1)
result['rooms'][room_id] = {
'count': len(room_agents),
'agents': [a['name'] for a in room_agents[:25]], # cap 25/room (was 15)
'active': active_count,
'dead': len(room_agents) - active_count,
}
log(f" {room_id}: {len(room_agents)} agents ({active_count} active)")
out = '/var/www/html/api/meeting-rooms-data.json'
with open(out, 'w') as f:
json.dump(result, f, indent=2, ensure_ascii=False)
log(f"Output: {out}")
with open('/var/www/html/api/meeting-rooms-populator.log', 'w') as f:
f.write('\n'.join(LOG))
return result
if __name__ == '__main__':
generate_meeting_data()