229 lines
8.9 KiB
PHP
229 lines
8.9 KiB
PHP
<?php
|
|
/**
|
|
* WEVIA NL Query API · /api/wevia.php?q=...
|
|
* Répond à n'importe quelle question via truth-registry
|
|
* Source: /api/wevia-truth-registry.json (rebuild every 30min)
|
|
* Opus Yacine · 19avr2026
|
|
*/
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: no-store, max-age=0');
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
$q = $_GET['q'] ?? $_POST['q'] ?? '';
|
|
$q = trim(mb_strtolower($q));
|
|
$fmt = $_GET['format'] ?? 'json'; // json | text | html
|
|
|
|
$registry_path = '/var/www/html/api/wevia-truth-registry.json';
|
|
if (!file_exists($registry_path)) {
|
|
echo json_encode(['ok'=>false, 'error'=>'truth-registry not built · run wevia-truth-builder.php']);
|
|
exit;
|
|
}
|
|
|
|
$T = json_decode(file_get_contents($registry_path), true);
|
|
if (!$T) {
|
|
echo json_encode(['ok'=>false, 'error'=>'truth-registry corrupted']);
|
|
exit;
|
|
}
|
|
|
|
// Helper
|
|
function hay($haystack, $needles) {
|
|
foreach ((array)$needles as $n) {
|
|
if (stripos($haystack, $n) !== false) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$answer = null;
|
|
$matched_pattern = null;
|
|
|
|
// ============== PATTERN MATCHING ==============
|
|
|
|
// 1. Counts & numbers
|
|
if (hay($q, ['combien', 'how many', 'nombre de', 'count'])) {
|
|
if (hay($q, ['agent'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => $T['agents']['count_unique'] . ' agents uniques (dédupliqués sur ' . count($T['agents']['by_source']) . ' sources · ' . $T['agents']['count_with_overlaps'] . ' avec overlaps)',
|
|
'value' => $T['agents']['count_unique'],
|
|
'details' => $T['agents']['by_source'],
|
|
];
|
|
$matched_pattern = 'count_agents';
|
|
}
|
|
elseif (hay($q, ['intent'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => $T['intents']['count'] . ' intents wired (' . $T['intents']['arena_declared'] . ' arena declared)',
|
|
'value' => $T['intents']['count'],
|
|
'by_status' => $T['intents']['by_status'],
|
|
'by_domain' => $T['intents']['by_domain'],
|
|
];
|
|
$matched_pattern = 'count_intents';
|
|
}
|
|
elseif (hay($q, ['skill'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => number_format($T['skills']['TOTAL']) . ' skills TOTAL · 5 sources',
|
|
'value' => $T['skills']['TOTAL'],
|
|
'sources' => $T['skills']['sources'],
|
|
];
|
|
$matched_pattern = 'count_skills';
|
|
}
|
|
elseif (hay($q, ['brain'])) {
|
|
$answer = ['question' => $q, 'answer' => $T['brains']['count'] . ' brains', 'value' => $T['brains']['count']];
|
|
$matched_pattern = 'count_brains';
|
|
}
|
|
elseif (hay($q, ['doctrine'])) {
|
|
$answer = ['question' => $q, 'answer' => $T['doctrines']['count'] . ' doctrines', 'value' => $T['doctrines']['count'], 'items' => array_slice($T['doctrines']['items'], 0, 10)];
|
|
$matched_pattern = 'count_doctrines';
|
|
}
|
|
elseif (hay($q, ['dashboard', 'page'])) {
|
|
$answer = ['question' => $q, 'answer' => $T['dashboards']['count'] . ' dashboards HTML', 'value' => $T['dashboards']['count']];
|
|
$matched_pattern = 'count_dashboards';
|
|
}
|
|
elseif (hay($q, ['provider', 'llm', 'model'])) {
|
|
$answer = ['question' => $q, 'answer' => $T['providers']['declared_total'] . '/13 providers', 'value' => $T['providers']['declared_total']];
|
|
$matched_pattern = 'count_providers';
|
|
}
|
|
elseif (hay($q, ['api', 'endpoint'])) {
|
|
$answer = ['question' => $q, 'answer' => $T['apis_php_count'] . ' APIs PHP', 'value' => $T['apis_php_count']];
|
|
$matched_pattern = 'count_apis';
|
|
}
|
|
}
|
|
|
|
// 2. Score / autonomy / godmode
|
|
if (!$answer && hay($q, ['score', 'autonomy', 'autonomie', 'godmode'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => $T['autonomy_score'] . '/100 · ' . $T['autonomy_level'],
|
|
'value' => $T['autonomy_score'],
|
|
'level' => $T['autonomy_level'],
|
|
];
|
|
$matched_pattern = 'autonomy';
|
|
}
|
|
|
|
// 3. Find agent by name
|
|
if (!$answer && (hay($q, ['agent']) && !hay($q, ['combien', 'how many']))) {
|
|
$matches = [];
|
|
foreach ($T['agents']['items'] as $a) {
|
|
if (stripos($a['name'], $q) !== false || stripos($a['key'], $q) !== false ||
|
|
stripos(str_replace('agent', '', $q), $a['key']) !== false) {
|
|
$matches[] = $a;
|
|
}
|
|
}
|
|
// Extract keyword after "agent"
|
|
if (empty($matches) && preg_match('/agent\s+(\w+)/', $q, $m)) {
|
|
$kw = $m[1];
|
|
foreach ($T['agents']['items'] as $a) {
|
|
if (stripos($a['name'], $kw) !== false) $matches[] = $a;
|
|
}
|
|
}
|
|
if (!empty($matches)) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => count($matches) . ' agents trouvés',
|
|
'matches' => array_slice($matches, 0, 20),
|
|
];
|
|
$matched_pattern = 'find_agent';
|
|
}
|
|
}
|
|
|
|
// 4. Find intent by trigger
|
|
if (!$answer && hay($q, ['intent', 'trigger'])) {
|
|
$matches = [];
|
|
$kw = $q;
|
|
if (preg_match('/intent\s+([\w]+)/', $q, $m)) $kw = $m[1];
|
|
elseif (preg_match('/trigger\s+([\w]+)/', $q, $m)) $kw = $m[1];
|
|
foreach ($T['intents']['items'] as $i) {
|
|
$hay = strtolower($i['name'] . ' ' . implode(' ', $i['triggers'] ?? []) . ' ' . ($i['description'] ?? '') . ' ' . ($i['domain'] ?? ''));
|
|
if (stripos($hay, $kw) !== false) $matches[] = $i;
|
|
}
|
|
if (!empty($matches)) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => count($matches) . ' intents trouvés',
|
|
'matches' => array_slice($matches, 0, 15),
|
|
];
|
|
$matched_pattern = 'find_intent';
|
|
}
|
|
}
|
|
|
|
// 5. Status / health
|
|
if (!$answer && hay($q, ['status', 'etat', 'état', 'health', 'truth', 'consolidation'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => 'WEVIA Truth Registry · ' . $T['autonomy_level'],
|
|
'summary' => [
|
|
'agents' => $T['agents']['count_unique'],
|
|
'intents' => $T['intents']['count'],
|
|
'skills' => $T['skills']['TOTAL'],
|
|
'brains' => $T['brains']['count'],
|
|
'doctrines' => $T['doctrines']['count'],
|
|
'dashboards' => $T['dashboards']['count'],
|
|
'providers' => $T['providers']['declared_total'],
|
|
'qdrant_collections' => $T['qdrant']['collections_count'],
|
|
'qdrant_points' => $T['qdrant']['total_points'],
|
|
'nonreg' => $T['nonreg']['score'] . '/' . $T['nonreg']['total'],
|
|
'autonomy' => $T['autonomy_score'] . '/100 ' . $T['autonomy_level'],
|
|
],
|
|
'built_at' => $T['built_at'],
|
|
];
|
|
$matched_pattern = 'status';
|
|
}
|
|
|
|
// 6. List / what is available
|
|
if (!$answer && hay($q, ['list', 'liste', 'tous', 'all', 'what', 'quels'])) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => 'WEVIA capabilities summary',
|
|
'agents_total' => $T['agents']['count_unique'],
|
|
'intents_total' => $T['intents']['count'],
|
|
'skills_total' => $T['skills']['TOTAL'],
|
|
'top_agents' => array_slice(array_filter($T['agents']['items'], fn($a) => count($a['sources']) >= 3), 0, 20),
|
|
'arena_domains' => array_keys($T['intents']['arena_domains'] ?? []),
|
|
];
|
|
$matched_pattern = 'list';
|
|
}
|
|
|
|
// 7. DEFAULT · no match · return help
|
|
if (!$answer) {
|
|
$answer = [
|
|
'question' => $q,
|
|
'answer' => 'Question non reconnue · voici les patterns supportés',
|
|
'help' => [
|
|
'"combien d\'agents ?"' => 'Returns agent count + breakdown by source',
|
|
'"combien d\'intents ?"' => 'Returns intent count + by status/domain',
|
|
'"combien de skills ?"' => 'Returns skills total + 5 sources',
|
|
'"autonomy score"' => 'Returns autonomy score + GODMODE level',
|
|
'"status / etat / truth"' => 'Full WEVIA state summary',
|
|
'"agent X"' => 'Find agents matching X',
|
|
'"intent Y"' => 'Find intents matching Y',
|
|
'"list all"' => 'List top referenced agents + domains',
|
|
],
|
|
'examples' => [
|
|
'/api/wevia.php?q=combien+d\'agents',
|
|
'/api/wevia.php?q=status',
|
|
'/api/wevia.php?q=agent+cerebras',
|
|
'/api/wevia.php?q=intent+warmup',
|
|
],
|
|
'truth_registry' => '/api/wevia-truth-registry.json',
|
|
];
|
|
$matched_pattern = 'help';
|
|
}
|
|
|
|
$answer['matched_pattern'] = $matched_pattern;
|
|
$answer['ts'] = date('c');
|
|
$answer['registry_built_at'] = $T['built_at'];
|
|
|
|
// Output formats
|
|
if ($fmt === 'text') {
|
|
header('Content-Type: text/plain; charset=utf-8');
|
|
if (isset($answer['answer'])) echo "Q: " . ($q ?: '(no query)') . "\n";
|
|
echo "A: " . ($answer['answer'] ?? 'N/A') . "\n";
|
|
if (isset($answer['value'])) echo "V: " . $answer['value'] . "\n";
|
|
if (isset($answer['details'])) { echo "Details:\n"; foreach ($answer['details'] as $k=>$v) echo " · $k: $v\n"; }
|
|
if (isset($answer['summary'])) { echo "Summary:\n"; foreach ($answer['summary'] as $k=>$v) echo " · $k: " . (is_array($v) ? json_encode($v) : $v) . "\n"; }
|
|
exit;
|
|
}
|
|
|
|
echo json_encode(['ok'=>true] + $answer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|