126 lines
5.9 KiB
PHP
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);
|