- Add apaw-state-api Flask service (landing/api/server.py) that serves agent fit scores, best models, and explanations from real-fit.db - Add nginx proxy rule: /api/state → apaw-state-api:8080 - Add fit-score drill-down modal (click heatmap cell → score breakdown + explanation) in api.js, styles.css, and index.html - Add real-fit-recalc.py script for offline score recalculation from stored SQLite responses - Add real-fit-engine.py (evaluation engine) and sync-dashboard-data.py - Add Dockerfile ENTRYPOINT + entrypoint.sh for landing container - Add docker-compose.ollama.yml for local Ollama inference - Update kilo.jsonc command models and agent-versions.json - Regenerate index.standalone.html with latest dashboard data - Add .gitignore entries for __pycache__, runtime data, and backups
123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Sync dashboard data — generates dashboard-data.json from evolution.json (real data)."""
|
|
import json, os
|
|
from datetime import datetime, timezone
|
|
|
|
def build_dashboard_data():
|
|
# Load real evolution data
|
|
with open('agent-evolution/data/evolution.json') as f:
|
|
evo = json.load(f)
|
|
|
|
# Load model benchmarks for supplemental info
|
|
try:
|
|
with open('agent-evolution/data/model-benchmarks-verified.json') as f:
|
|
bm = json.load(f)
|
|
except:
|
|
bm = {'models': []}
|
|
|
|
# Build model lookup
|
|
bench_map = {}
|
|
for m in bm.get('models', []):
|
|
mid = m.get('id', '')
|
|
if mid:
|
|
bench_map[f'ollama-cloud/{mid}'] = {
|
|
'swe': m.get('swe_bench'),
|
|
'name': m.get('name', mid),
|
|
'params': m.get('parameters', ''),
|
|
'ctx': m.get('context_window', '')
|
|
}
|
|
|
|
agents = []
|
|
for name, a in evo.get('agents', {}).items():
|
|
c = a.get('current', {})
|
|
if not c.get('model'):
|
|
continue
|
|
model = c['model']
|
|
b = c.get('benchmark', {})
|
|
fit = b.get('fit_score', 0)
|
|
if_ = b.get('instruction_following', 0)
|
|
model_short = model.replace('ollama-cloud/', '')
|
|
b_info = bench_map.get(model, {})
|
|
|
|
# Get latest model change from history
|
|
history = a.get('history', [])
|
|
latest_change = None
|
|
for h in reversed(history):
|
|
if h.get('type') == 'model_change':
|
|
latest_change = h
|
|
break
|
|
|
|
agents.append({
|
|
'name': name,
|
|
'model': model,
|
|
'mode': c.get('mode', 'subagent'),
|
|
'description': c.get('description', ''),
|
|
'category': c.get('category', 'General'),
|
|
'color': c.get('color', '#8B5CF6'),
|
|
'provider': c.get('provider', 'Ollama'),
|
|
'variant': c.get('variant', ''),
|
|
'fit_score': fit,
|
|
'instruction_following': if_,
|
|
'swe_bench': b_info.get('swe'),
|
|
'model_short': model_short,
|
|
'model_name': b_info.get('name', model_short),
|
|
'model_params': b_info.get('params', ''),
|
|
'model_ctx': b_info.get('ctx', ''),
|
|
'recommendations': len(c.get('recommendations', [])),
|
|
'history_count': len(history),
|
|
'latest_change': latest_change
|
|
})
|
|
|
|
# Build model summary from REAL agent assignments
|
|
models = {}
|
|
for a in agents:
|
|
ms = a['model_short']
|
|
if ms not in models:
|
|
models[ms] = {
|
|
'fit_agents': [], # fit scores of agents on this model
|
|
'name': a['model_name'],
|
|
'params': a['model_params'],
|
|
'ctx': a['model_ctx'],
|
|
'agents': 0,
|
|
'commands': 0,
|
|
'avg_fit': 0
|
|
}
|
|
models[ms]['agents'] += 1
|
|
models[ms]['fit_agents'].append(a['fit_score'])
|
|
|
|
# Calculate averages
|
|
for ms, m in models.items():
|
|
fits = m['fit_agents']
|
|
m['avg_fit'] = round(sum(fits) / len(fits), 1) if fits else 0
|
|
m['min_fit'] = min(fits) if fits else 0
|
|
m['max_fit'] = max(fits) if fits else 0
|
|
del m['fit_agents']
|
|
|
|
# Model distribution
|
|
from collections import Counter
|
|
model_dist = Counter(a['model'] for a in agents)
|
|
|
|
return {
|
|
'generated': datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z'),
|
|
'source': 'evolution.json',
|
|
'total_agents': len(agents),
|
|
'total_models': len(models),
|
|
'agents': agents,
|
|
'models': models,
|
|
'model_distribution': dict(model_dist)
|
|
}
|
|
|
|
if __name__ == '__main__':
|
|
data = build_dashboard_data()
|
|
out = 'agent-evolution/data/dashboard-data.json'
|
|
os.makedirs(os.path.dirname(out), exist_ok=True)
|
|
with open(out, 'w') as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
print(f'Written {out}: {len(data["agents"])} agents, {len(data["models"])} models')
|
|
print('Sample agents:')
|
|
for a in data['agents'][:5]:
|
|
print(f' {a["name"]:25} fit={a["fit_score"]:3d} if={a["instruction_following"]:3d} {a["model_short"]:25}')
|
|
print('Models:')
|
|
for ms, m in sorted(data['models'].items(), key=lambda x: -x[1]['agents']):
|
|
print(f' {ms:20} avg_fit={m["avg_fit"]:5.1f} agents={m["agents"]}')
|