Files
html/api/wevia-capabilities.php
2026-04-16 14:31:27 +02:00

216 lines
9.4 KiB
PHP

<?php
// Public access for list action
if (isset($_GET['action']) && $_GET['action'] === 'list') { /* allow */ } else
/**
* WEVIA Capabilities Orchestrator
* Wires ALL open-source tools into a unified API for WEVIA chatbot + apps
*
* Usage: POST /api/wevia-capabilities.php?cap=search|vector|monitor|screenshot|analytics|workflow
*
* Wired capabilities:
* - SearXNG (localhost:8888) → web search for WEVIA chatbot
* - Qdrant (localhost:6333) → vector memory / RAG for long-term user profiles
* - Uptime Kuma (localhost:3088) → health monitoring API
* - Plausible (localhost:8787) → analytics API
* - n8n (localhost:5678) → workflow automation
* - Ollama (localhost:11434) → local AI inference
* - Playwright/browser-use → visual testing + collecte de donnees
* - Loki → centralized logging
* - CrowdSec → threat intelligence
*/
header('Content-Type: application/json');
$cap = $_GET['cap'] ?? $_POST['cap'] ?? '';
$q = $_POST['q'] ?? $_GET['q'] ?? '';
$auth = $_SERVER['HTTP_X_WEVIA_KEY'] ?? $_POST['key'] ?? '';
// Auth check
if ($auth !== 'W3V1A_CAP_2026' && $cap !== 'health') {
http_response_code(401);
die(json_encode(['error' => 'unauthorized']));
}
function api($url, $method = 'GET', $body = null, $timeout = 8) {
$ch = curl_init($url);
$headers = ['Content-Type: application/json'];
if ($body) curl_setopt($ch, CURLOPT_POSTFIELDS, is_string($body) ? $body : json_encode($body));
if ($method !== 'GET') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt_array($ch, [CURLOPT_HTTPHEADER => $headers, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $timeout]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['code' => $code, 'data' => json_decode($r, true) ?: $r];
}
switch ($cap) {
// ═══ HEALTH CHECK ═══
case 'health':
$services = [
'searxng' => api('http://localhost:8888/healthz', 'GET', null, 3),
'qdrant' => api('http://localhost:6333/healthz', 'GET', null, 3),
'ollama' => api('https://api.groq.com/openai/v1/models', 'GET', null, 3),
'n8n' => api('http://localhost:5678/healthz', 'GET', null, 3),
'plausible'=> api('https://analytics.weval-consulting.com/api/health', 'GET', null, 5),
'kuma' => api('http://localhost:3088/api/entry', 'GET', null, 3),
'loki' => api('http://localhost:3100/ready', 'GET', null, 3),
'mattermost'=> api('http://localhost:8065/api/v4/system/ping', 'GET', null, 3),
'vaultwarden'=> api('http://localhost:8222/alive', 'GET', null, 3),
'ollama_local'=> api('http://localhost:11434/api/tags', 'GET', null, 3),
];
$up = 0;
foreach ($services as $k => &$s) {
$s['up'] = $s['code'] >= 200 && $s['code'] < 500;
if ($s['up']) $up++;
unset($s['data']); // compact
}
echo json_encode(['services' => $services, 'up' => $up, 'total' => count($services)]);
break;
// ═══ SEARXNG: Web search for WEVIA chatbot ═══
case 'search':
if (!$q) die(json_encode(['error' => 'no query']));
$r = api("http://localhost:8888/search?q=" . urlencode($q) . "&format=json&engines=google,bing,duckduckgo&language=fr", 'GET', null, 10);
$results = [];
foreach (($r['data']['results'] ?? []) as $i => $res) {
if ($i >= 5) break;
$results[] = ['title' => $res['title'] ?? '', 'url' => $res['url'] ?? '', 'content' => substr($res['content'] ?? '', 0, 200)];
}
echo json_encode(['results' => $results, 'count' => count($results)]);
break;
// ═══ QDRANT: Vector memory for user profiles + RAG ═══
case 'vector':
$action = $_POST['action'] ?? 'search';
$collection = $_POST['collection'] ?? 'wevia_memory';
if ($action === 'create_collection') {
$r = api("http://localhost:6333/collections/$collection", 'PUT', [
'vectors' => ['size' => 384, 'distance' => 'Cosine']
]);
echo json_encode($r);
} elseif ($action === 'upsert') {
$points = json_decode($_POST['points'] ?? '[]', true);
$r = api("http://localhost:6333/collections/$collection/points", 'PUT', ['points' => $points]);
echo json_encode($r);
} elseif ($action === 'search') {
$vector = json_decode($_POST['vector'] ?? '[]', true);
$r = api("http://localhost:6333/collections/$collection/points/search", 'POST', [
'vector' => $vector, 'limit' => intval($_POST['limit'] ?? 5), 'with_payload' => true
]);
echo json_encode($r);
}
break;
// ═══ OLLAMA: Local AI inference ═══
case 'ollama':
$model = $_POST['model'] ?? 'qwen3:8b';
$prompt = $_POST['prompt'] ?? $q;
if (!$prompt) die(json_encode(['error' => 'no prompt']));
$r = api('http://localhost:11434/api/generate', 'POST', [
'model' => $model, 'prompt' => $prompt, 'stream' => false,
'options' => ['temperature' => 0.7, 'num_predict' => 500]
], 30);
echo json_encode(['response' => $r['data']['response'] ?? '', 'model' => $model]);
break;
// ═══ N8N: Workflow automation trigger ═══
case 'workflow':
$webhook = $_POST['webhook'] ?? '';
$payload = json_decode($_POST['payload'] ?? '{}', true);
if (!$webhook) die(json_encode(['error' => 'no webhook URL']));
$r = api("http://localhost:5678/webhook/$webhook", 'POST', $payload);
echo json_encode($r);
break;
// ═══ PLAUSIBLE: Analytics API ═══
case 'analytics':
$site = $_POST['site'] ?? 'weval-consulting.com';
$period = $_POST['period'] ?? '7d';
$r = api("http://localhost:8787/api/v1/stats/aggregate?site_id=$site&period=$period&metrics=visitors,pageviews,bounce_rate", 'GET', null, 5);
echo json_encode($r);
break;
// ═══ SCREENSHOT: Playwright visual capture ═══
case 'screenshot':
$url = $_POST['url'] ?? '';
if (!$url) die(json_encode(['error' => 'no url']));
$slug = preg_replace('/[^a-z0-9]/', '-', strtolower(parse_url($url, PHP_URL_HOST) . parse_url($url, PHP_URL_PATH)));
$file = "/var/www/html/wevia-ia/screenshots/cap-$slug.png";
$cmd = "python3 -c \"
import asyncio
from playwright.async_api import async_playwright
async def s():
async with async_playwright() as p:
b=await p.chromium.launch(headless=True,args=['--no-sandbox','--ignore-certificate-errors'])
pg=await b.new_page()
await pg.goto('$url',timeout=12000)
await pg.wait_for_timeout(2000)
await pg.screenshot(path='$file',full_page=True)
await b.close()
asyncio.run(s())
\" 2>&1";
$out = shell_exec($cmd);
echo json_encode(['file' => str_replace('/var/www/html', '', $file), 'exists' => file_exists($file), 'size' => filesize($file) ?: 0]);
break;
// ═══ CROWDSEC: Threat intelligence ═══
case 'threats':
$out = shell_exec('sudo cscli alerts list -l 10 -o json 2>/dev/null');
echo $out ?: json_encode(['alerts' => [], 'note' => 'no alerts']);
break;
// ═══ LOKI: Log query ═══
case 'logs':
$query = $_POST['query'] ?? '{job="nginx"}';
$limit = intval($_POST['limit'] ?? 20);
$r = api("http://localhost:3100/loki/api/v1/query_range?query=" . urlencode($query) . "&limit=$limit", 'GET', null, 5);
echo json_encode($r);
break;
// === MATTERMOST: Team alerts ===
case 'alert':
$channel = $_POST['channel'] ?? 'town-square';
$text = $_POST['text'] ?? '';
if (!$text) die(json_encode(['error'=>'no text']));
$r = api('http://localhost:8065/hooks/wevia-alert', 'POST', ['channel'=>$channel, 'text'=>$text]);
echo json_encode($r);
break;
// === VAULTWARDEN: Secrets check ===
case 'vault':
$r = api('http://localhost:8222/alive', 'GET', null, 3);
echo json_encode(['alive'=>$r['code']===200]);
break;
// === OLLAMA S151: DR fallback inference ===
case 'ollama-local':
$model = $_POST['model'] ?? 'qwen3:4b';
$prompt = $_POST['prompt'] ?? $q;
if (!$prompt) die(json_encode(['error'=>'no prompt']));
$r = api('http://localhost:11434/api/generate', 'POST', [
'model'=>$model, 'prompt'=>$prompt, 'stream'=>false,
'options'=>['temperature'=>0.7, 'num_predict'=>500]
], 30);
echo json_encode(['response'=>$r['data']['response'] ?? '', 'model'=>$model, 'server'=>'S151-DR']);
break;
// === COGNITIVE: List active brain modules ===
case 'cognitive':
$modules = [];
foreach (glob('/var/www/weval/wevia-ia/cognitive-*.php') as $f) {
$b = basename($f, '.php');
$lines = count(file($f));
$modules[] = ['name'=>$b, 'lines'=>$lines, 'path'=>$f];
}
echo json_encode(['modules'=>$modules, 'count'=>count($modules)]);
break;
default:
echo json_encode([
'available' => ['health','search','vector','ollama','ollama-local','workflow','analytics','screenshot','threats','logs','alert','vault','cognitive'],
'usage' => 'POST /api/wevia-capabilities.php?cap=<capability>',
'auth' => 'Header X-WEVIA-KEY or POST key=...'
]);
}