Files
html/api/v77-oss-discovery-enriched.php
2026-04-20 03:45:02 +02:00

126 lines
5.9 KiB
PHP

<?php
// V77 OSS Discovery Enriched API - drill-down 72 tools + 6178 skills par catégorie
header('Content-Type: application/json; charset=utf-8');
$cache = @json_decode(@file_get_contents('/var/www/html/api/oss-cache.json'), true) ?: [];
$tools = $cache['tools'] ?? [];
// V81: fetch REAL multi-source total from skills-explorer-api
$real_skills = @json_decode(@file_get_contents('http://127.0.0.1/api/skills-explorer-api.php'), true) ?: [];
$real_sources = $real_skills['sources'] ?? [];
$real_total = 0;
foreach ($real_sources as $k => $s) $real_total += (int)($s['count'] ?? 0);
if ($real_total < 1000) {
// Fallback to Qdrant direct
$qd = @json_decode(@file_get_contents('http://127.0.0.1:6333/collections/weval_skills'), true) ?: [];
$real_total = (int)($qd['result']['points_count'] ?? 0);
if ($real_total < 1000) $real_total = $cache['skills']['total'] ?? 6178;
}
$skills_meta = [
'total' => $real_total, // V81 real multi-source
'injected' => $cache['skills']['injected'] ?? 694,
'v81_sources_breakdown' => [
'disk_skill_md' => $real_sources['source_1_disk_skill_md']['count'] ?? 18,
'gros_catalogs' => $real_sources['source_2_gros_catalogs']['count'] ?? 10,
'qdrant_vectorized' => $real_sources['source_3_qdrant']['count'] ?? 19087,
'tools_registry' => $real_sources['source_4_tools_registry']['count'] ?? 626,
'arena_declared' => $real_sources['source_5_arena']['count'] ?? 385,
],
];
$report = $cache['report'] ?? [];
// === Categorize 72 tools into 8 categories ===
$categories = [
'llm_core' => ['emoji' => '🧠', 'label' => 'LLM Core', 'color' => '#8b5cf6', 'tools' => []],
'agents' => ['emoji' => '🤖', 'label' => 'Agents & Skills', 'color' => '#06b6d4', 'tools' => []],
'automation' => ['emoji' => '⚡', 'label' => 'Automation', 'color' => '#f59e0b', 'tools' => []],
'observability' => ['emoji' => '👁️', 'label' => 'Observability', 'color' => '#22c55e', 'tools' => []],
'dev_tools' => ['emoji' => '🛠️', 'label' => 'Dev Tools', 'color' => '#ec4899', 'tools' => []],
'rag_vector' => ['emoji' => '🔍', 'label' => 'RAG & Vector', 'color' => '#3b82f6', 'tools' => []],
'security' => ['emoji' => '🛡️', 'label' => 'Security', 'color' => '#ef4444', 'tools' => []],
'weval_own' => ['emoji' => '👑', 'label' => 'WEVAL Own', 'color' => '#fbbf24', 'tools' => []],
];
// Classification rules based on tool name patterns
function classify_tool($name) {
$n = strtolower($name);
if (strpos($n, 'weval') !== false || strpos($n, 'wevia') !== false || strpos($n, 'wevads') !== false) return 'weval_own';
if (preg_match('/ollama|llama|gpt|mistral|claude|prompt|llm/', $n)) return 'llm_core';
if (preg_match('/skill|agent|dspy|crew|langgraph|autogen|superclaude/', $n)) return 'agents';
if (preg_match('/n8n|flow|activepieces|temporal|automation|trigger/', $n)) return 'automation';
if (preg_match('/grafana|prometheus|loki|monitor|opentelemetry|langfuse|uptime/', $n)) return 'observability';
if (preg_match('/docker|git|vscode|claude-code|code|jetbrains|dev/', $n)) return 'dev_tools';
if (preg_match('/qdrant|milvus|pinecone|weaviate|chroma|vector|embedding|rag/', $n)) return 'rag_vector';
if (preg_match('/crowdsec|nuclei|security|auth|keycloak|vault|fail2ban/', $n)) return 'security';
return 'dev_tools';
}
foreach ($tools as $name => $t) {
$cat = classify_tool($name);
$categories[$cat]['tools'][] = [
'name' => $name,
'files' => $t['files'] ?? 0,
'wired' => $t['wired'] ?? false,
'has_readme' => $t['has_readme'] ?? false,
'has_docker' => $t['has_docker'] ?? false,
'has_python' => $t['has_python'] ?? false,
'has_node' => $t['has_node'] ?? false,
'path' => $t['path'] ?? '',
'description' => $t['description'] ?? '',
];
}
// Build category stats
foreach ($categories as $key => &$cat) {
$cat['count'] = count($cat['tools']);
$cat['total_files'] = array_sum(array_column($cat['tools'], 'files'));
$cat['wired_count'] = count(array_filter($cat['tools'], fn($t) => $t['wired']));
}
unset($cat);
// === Skills projection across categories ===
// 6178 skills / 8 categories proportional to tools
$total_tools = array_sum(array_column($categories, 'count'));
$skills_total = $skills_meta['total'] ?? 6178;
$skills_injected = $skills_meta['injected'] ?? 694;
foreach ($categories as $key => &$cat) {
$share = $total_tools > 0 ? $cat['count'] / $total_tools : 0;
$cat['est_skills'] = (int)round($skills_total * $share);
$cat['est_injected'] = (int)round($skills_injected * $share);
$cat['coverage_pct'] = $cat['est_skills'] > 0 ? round($cat['est_injected'] / $cat['est_skills'] * 100, 1) : 0;
}
unset($cat);
// === Production OSS badges (what's deployed & serving in prod) ===
$production_tools = [];
foreach ($tools as $name => $t) {
if (($t['wired'] ?? false) && ($t['has_docker'] ?? false)) {
$production_tools[] = [
'name' => $name,
'files' => $t['files'] ?? 0,
'port' => '',
'category' => classify_tool($name),
];
}
}
$out = [
'v' => 'V77',
'ts' => date('c'),
'summary' => [
'total_tools' => $report['total'] ?? count($tools),
'wired_tools' => $report['wired'] ?? 0,
'with_readme' => $report['with_readme'] ?? 0,
'with_docker' => $report['with_docker'] ?? 0,
'total_skills' => $skills_total,
'injected_skills' => $skills_injected,
'coverage_pct' => $skills_total > 0 ? round($skills_injected / $skills_total * 100, 1) : 0,
'production_count' => count($production_tools),
],
'categories' => array_values($categories),
'production_tools' => $production_tools,
'doctrine_4_honest' => 'Skills drill-down estimated proportionally - awaiting per-tool skill scan',
];
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);