292 lines
12 KiB
PHP
292 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* WEVIA Unified API v2 · TOUTES les 7 sources agents + déduplication
|
|
* Opus Yacine · 19avr2026
|
|
*/
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: no-store');
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
$action = $_GET['action'] ?? 'summary';
|
|
$QDRANT = 'http://127.0.0.1:6333';
|
|
|
|
function qdrant($url, $m='GET', $d=null) {
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>6, CURLOPT_CUSTOMREQUEST=>$m]);
|
|
if ($d) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($d)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); }
|
|
$r = curl_exec($ch); curl_close($ch);
|
|
return json_decode($r ?: '{}', true);
|
|
}
|
|
|
|
|
|
// === FAST PATH · Use truth-registry as single source if available (Yacine) ===
|
|
$TRUTH = @json_decode(@file_get_contents('/var/www/html/api/wevia-truth-registry.json'), true);
|
|
if ($TRUTH && !empty($TRUTH['agents']['count_unique'])) {
|
|
header('X-Source: truth-registry');
|
|
$action_in = $_GET['action'] ?? 'summary';
|
|
if ($action_in === 'summary') {
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'ts' => date('c'),
|
|
'source' => 'truth-registry',
|
|
'summary' => [
|
|
'agents' => [
|
|
'UNIQUE_DEDUP' => $TRUTH['agents']['count_unique'],
|
|
'total_with_overlaps' => $TRUTH['agents']['count_with_overlaps'],
|
|
'per_source' => $TRUTH['agents']['by_source'],
|
|
],
|
|
'intents' => [
|
|
'php_files' => $TRUTH['intents']['count'],
|
|
'arena_declared' => $TRUTH['intents']['arena_declared'],
|
|
'by_status' => $TRUTH['intents']['by_status'] ?? [],
|
|
'by_domain' => $TRUTH['intents']['by_domain'] ?? [],
|
|
],
|
|
'skills' => [
|
|
'TOTAL_ALL_SOURCES' => $TRUTH['skills']['TOTAL'],
|
|
'disk_dirs' => $TRUTH['skills']['sources']['disk_dirs'] ?? 0,
|
|
'qdrant_vectorized' => $TRUTH['skills']['sources']['qdrant_vectorized'] ?? 0,
|
|
'tools_registry' => $TRUTH['skills']['sources']['tools_registry'] ?? 0,
|
|
'arena_declared' => $TRUTH['skills']['sources']['arena_declared'] ?? 0,
|
|
'doctrines' => $TRUTH['doctrines']['count'] ?? 0,
|
|
],
|
|
'brains' => ['count' => $TRUTH['brains']['count']],
|
|
'dashboards' => $TRUTH['dashboards']['count'],
|
|
'apis' => $TRUTH['apis_php_count'] ?? 0,
|
|
],
|
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
if ($action_in === 'agents') {
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'ts' => date('c'),
|
|
'source' => 'truth-registry',
|
|
'agents' => array_map(function($a) {
|
|
return [
|
|
'name' => $a['name'],
|
|
'key' => $a['key'] ?? '',
|
|
'sources' => $a['sources'],
|
|
'sources_count' => count($a['sources']),
|
|
'category' => $a['meta']['category'] ?? ($a['meta']['role'] ?? '?'),
|
|
'role' => $a['meta']['role'] ?? $a['meta']['description'] ?? '',
|
|
'icon' => $a['meta']['icon'] ?? $a['meta']['emoji'] ?? '',
|
|
];
|
|
}, $TRUTH['agents']['items']),
|
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$out = ['ok'=>true, 'ts'=>date('c')];
|
|
|
|
// ============== AGENTS MULTI-SOURCE DÉDUPLIQUÉ ==============
|
|
$agents_by_name = []; // key = normalized name → metadata
|
|
$sources_counts = [];
|
|
|
|
function normalize_name($n) { return strtolower(trim(preg_replace('/[^a-z0-9]+/i', '_', $n), '_')); }
|
|
|
|
function add_agent(&$reg, $name, $source, $meta = []) {
|
|
if (!$name) return;
|
|
$key = normalize_name($name);
|
|
if (!isset($reg[$key])) {
|
|
$reg[$key] = ['name' => $name, 'sources' => [], 'meta' => $meta];
|
|
}
|
|
if (!in_array($source, $reg[$key]['sources'])) {
|
|
$reg[$key]['sources'][] = $source;
|
|
}
|
|
$reg[$key]['meta'] = array_merge($reg[$key]['meta'], $meta);
|
|
}
|
|
|
|
// Source 1: agent-avatars-v2.json (most complete · 148 agents)
|
|
$av2 = @json_decode(@file_get_contents('/var/www/html/api/agent-avatars-v2.json'), true);
|
|
$sources_counts['agent_avatars_v2'] = 0;
|
|
if (is_array($av2)) {
|
|
foreach ($av2 as $name => $meta) {
|
|
add_agent($agents_by_name, $name, 'agent_avatars_v2', is_array($meta) ? $meta : []);
|
|
$sources_counts['agent_avatars_v2']++;
|
|
}
|
|
}
|
|
|
|
// Source 2: agent-avatars.json (136 agents · older)
|
|
$av1 = @json_decode(@file_get_contents('/var/www/html/api/agent-avatars.json'), true);
|
|
$sources_counts['agent_avatars_v1'] = 0;
|
|
if (is_array($av1)) {
|
|
foreach ($av1 as $name => $meta) {
|
|
add_agent($agents_by_name, $name, 'agent_avatars_v1', is_array($meta) ? $meta : []);
|
|
$sources_counts['agent_avatars_v1']++;
|
|
}
|
|
}
|
|
|
|
// Source 3: wevia-agents-registry.json (47 categorized · categories metadata)
|
|
$reg_cat = @json_decode(@file_get_contents('/var/www/html/api/wevia-agents-registry.json'), true);
|
|
$sources_counts['wevia_agents_registry'] = $reg_cat['total'] ?? 0;
|
|
// Categories metadata used later
|
|
|
|
// Source 4: paperclip-agility-agents-registered.json (12 agents V71)
|
|
$pc_agility = @json_decode(@file_get_contents('/var/www/html/api/paperclip-agility-agents-registered.json'), true);
|
|
$sources_counts['paperclip_agility_v71'] = 0;
|
|
if (is_array($pc_agility) && isset($pc_agility['agents'])) {
|
|
foreach ($pc_agility['agents'] as $a) {
|
|
add_agent($agents_by_name, $a['name'] ?? '?', 'paperclip_agility_v71', ['category' => $a['category'] ?? 'agility', 'icon' => $a['icon'] ?? '🤖', 'role' => $a['role'] ?? '']);
|
|
$sources_counts['paperclip_agility_v71']++;
|
|
}
|
|
}
|
|
|
|
// Source 5: /api/*agent*.json files (11 files)
|
|
$sources_counts['api_agent_files'] = 0;
|
|
foreach (glob('/var/www/html/api/*agent*.json') as $f) {
|
|
$fname = basename($f, '.json');
|
|
// Skip the registries we already processed
|
|
if (in_array($fname, ['agent-avatars', 'agent-avatars-v2', 'wevia-agents-registry', 'paperclip-agility-agents-registered', 'wevia-agents-pack-status'])) continue;
|
|
add_agent($agents_by_name, $fname, 'api_agent_files', ['path' => str_replace('/var/www/html','',$f)]);
|
|
$sources_counts['api_agent_files']++;
|
|
}
|
|
|
|
// Source 6: /api/agent-stubs/*.php (50 stubs)
|
|
$sources_counts['agent_stubs'] = 0;
|
|
foreach (glob('/var/www/html/api/agent-stubs/*.php') as $f) {
|
|
$name = basename($f, '.php');
|
|
add_agent($agents_by_name, $name, 'agent_stubs', ['type' => 'stub_php']);
|
|
$sources_counts['agent_stubs']++;
|
|
}
|
|
|
|
// Source 7: /api/sub-agents/*.json (65 Claude sub-agents)
|
|
$sources_counts['claude_subagents'] = 0;
|
|
foreach (glob('/var/www/html/api/sub-agents/*.json') as $f) {
|
|
$data = @json_decode(@file_get_contents($f), true);
|
|
$name = $data['name'] ?? basename($f, '.json');
|
|
add_agent($agents_by_name, $name, 'claude_subagents', $data ?: []);
|
|
$sources_counts['claude_subagents']++;
|
|
}
|
|
|
|
// Source 8: Qdrant weval_agents_registry (if exists)
|
|
$qdrant_agents = qdrant("$QDRANT/collections/weval_agents_registry");
|
|
$sources_counts['qdrant_agents_vectorized'] = $qdrant_agents['result']['points_count'] ?? 0;
|
|
|
|
// Paperclip ecosystem reference (from disk)
|
|
$paperclip_dirs = glob('/opt/deer-flow/skills/weval/paperclip*', GLOB_ONLYDIR);
|
|
$sources_counts['paperclip_opt_catalog'] = is_array($paperclip_dirs) ? count($paperclip_dirs) : 0;
|
|
|
|
$agents_unique_count = count($agents_by_name);
|
|
|
|
// ============== INTENTS ==============
|
|
$intents = [];
|
|
foreach (glob('/var/www/html/api/wired-pending/intent-*.php') as $f) {
|
|
ob_start();
|
|
$info = @include $f;
|
|
ob_end_clean();
|
|
if (is_array($info)) {
|
|
$intents[] = [
|
|
'name' => $info['name'] ?? basename($f),
|
|
'domain' => $info['domain'] ?? 'general',
|
|
'status' => $info['status'] ?? '?',
|
|
'triggers' => array_slice($info['triggers'] ?? [], 0, 3),
|
|
'source' => $info['source'] ?? '?',
|
|
];
|
|
}
|
|
}
|
|
|
|
$arena = @json_decode(@file_get_contents('/var/www/html/api/arena-intent-registry.json'), true);
|
|
|
|
// ============== SKILLS ==============
|
|
$skills_disk = glob('/var/www/html/skills/*', GLOB_ONLYDIR);
|
|
$qdrant_skills = qdrant("$QDRANT/collections/weval_skills");
|
|
$qdrant_skills_count = $qdrant_skills['result']['points_count'] ?? 0;
|
|
$reg = @json_decode(@file_get_contents('/var/www/html/api/wevia-tool-registry.json'), true);
|
|
$tools_count = isset($reg['tools']) && is_array($reg['tools']) ? count($reg['tools']) : 0;
|
|
$arena_skills = $arena['total_skills'] ?? 0;
|
|
|
|
// Doctrines (58 mentioned in screenshots)
|
|
$doctrine_files = glob('/var/www/html/api/doctrine*.json');
|
|
$doctrines_count = is_array($doctrine_files) ? count($doctrine_files) : 0;
|
|
// Also check /opt/wevads/doctrines/
|
|
$doctrine_files2 = glob('/opt/wevads/doctrines/*.md');
|
|
if (is_array($doctrine_files2)) $doctrines_count += count($doctrine_files2);
|
|
|
|
// ============== BRAINS ==============
|
|
$brain_patterns = ['/var/www/html/api/*brain*.php', '/var/www/html/api/*brain*.json', '/var/www/html/api/*brain*.py'];
|
|
$brains = [];
|
|
foreach ($brain_patterns as $pat) {
|
|
foreach (glob($pat) as $f) {
|
|
$name = basename($f);
|
|
// Filter noise
|
|
if (strpos($name, 'playwright') !== false) continue;
|
|
if (strpos($name, 'screenshot') !== false) continue;
|
|
$brains[] = [
|
|
'name' => str_replace(['.php','.json','.py'], '', $name),
|
|
'path' => str_replace('/var/www/html','',$f),
|
|
'type' => pathinfo($f, PATHINFO_EXTENSION),
|
|
'size' => filesize($f),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Dashboards
|
|
$dash_paths = array_unique(array_merge(
|
|
glob('/var/www/html/wevia-*.html') ?: [],
|
|
glob('/var/www/html/agents-*.html') ?: [],
|
|
glob('/var/www/html/*-dashboard*.html') ?: [],
|
|
glob('/var/www/html/*-hub*.html') ?: [],
|
|
glob('/var/www/html/l99*.html') ?: [],
|
|
));
|
|
$dashboards_count = count($dash_paths);
|
|
|
|
// APIs
|
|
$apis_count = count(glob('/var/www/html/api/*.php') ?: []);
|
|
|
|
// ============== OUTPUT ==============
|
|
$out['summary'] = [
|
|
'agents' => [
|
|
'UNIQUE_DEDUP' => $agents_unique_count, // Real unique agents
|
|
'per_source' => $sources_counts,
|
|
'total_with_overlaps' => array_sum($sources_counts),
|
|
'note' => 'Agents dédupliqués par nom normalisé · fusion 7+ sources',
|
|
],
|
|
'intents' => [
|
|
'php_files' => count($intents),
|
|
'arena_declared' => $arena['total_intents'] ?? 0,
|
|
'by_status' => array_count_values(array_column($intents, 'status')),
|
|
'by_domain' => array_count_values(array_column($intents, 'domain')),
|
|
],
|
|
'skills' => [
|
|
'disk_dirs' => count($skills_disk),
|
|
'qdrant_vectorized' => $qdrant_skills_count,
|
|
'tools_registry' => $tools_count,
|
|
'arena_declared' => $arena_skills,
|
|
'doctrines' => $doctrines_count,
|
|
'TOTAL_ALL_SOURCES' => count($skills_disk) + $qdrant_skills_count + $tools_count + $arena_skills,
|
|
],
|
|
'brains' => [
|
|
'count' => count($brains),
|
|
'list' => $brains,
|
|
],
|
|
'dashboards' => $dashboards_count,
|
|
'apis' => $apis_count,
|
|
];
|
|
|
|
if ($action === 'agents') {
|
|
$agents_list = [];
|
|
foreach ($agents_by_name as $key => $a) {
|
|
$agents_list[] = [
|
|
'name' => $a['name'],
|
|
'key' => $key,
|
|
'sources' => $a['sources'],
|
|
'sources_count' => count($a['sources']),
|
|
'category' => $a['meta']['category'] ?? '?',
|
|
'role' => $a['meta']['role'] ?? $a['meta']['description'] ?? '',
|
|
'icon' => $a['meta']['icon'] ?? $a['meta']['emoji'] ?? '',
|
|
];
|
|
}
|
|
// Sort by sources_count desc (most referenced first), then alpha
|
|
usort($agents_list, function($a,$b) {
|
|
if ($a['sources_count'] !== $b['sources_count']) return $b['sources_count'] - $a['sources_count'];
|
|
return strcmp($a['name'], $b['name']);
|
|
});
|
|
$out['agents'] = $agents_list;
|
|
}
|
|
|
|
if ($action === 'intents') $out['intents_list'] = $intents;
|
|
if ($action === 'brains') $out['brains_list'] = $brains;
|
|
|
|
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|