216 lines
9.4 KiB
PHP
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=...'
|
|
]);
|
|
}
|