Files
wevia-brain/kb-gateway.php
2026-04-12 23:01:36 +02:00

110 lines
4.0 KiB
PHP
Executable File

<?php
/**
* WEVIA KB Gateway — S88
* Bridges to S89 PostgreSQL for knowledge_base operations
* Runs on S88, connects to S89 PG remotely
*
* Endpoints:
* POST /wevia-kb-gateway.php?action=search&q=keyword
* POST /wevia-kb-gateway.php?action=stats
* POST /wevia-kb-gateway.php?action=ingest (with file upload)
*/
header('Content-Type: application/json');
// S89 PostgreSQL connection (remote)
define('PG_HOST', '127.0.0.1');
define('PG_PORT', '5432');
define('PG_DB', 'adx_system');
define('PG_USER', 'admin');
define('PG_PASS', 'admin123');
function getDb() {
static $pdo = null;
if (!$pdo) {
$dsn = "pgsql:host=" . PG_HOST . ";port=" . PG_PORT . ";dbname=" . PG_DB;
$pdo = new PDO($dsn, PG_USER, PG_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_TIMEOUT => 5
]);
}
return $pdo;
}
function respond($data, $code = 200) {
http_response_code($code);
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit;
}
$action = $_GET['action'] ?? $_POST['action'] ?? 'stats';
try {
$db = getDb();
switch ($action) {
case 'stats':
$r = $db->query("SELECT count(*) as total,
max(updated_at) as last_update,
count(DISTINCT section) as sections,
count(DISTINCT category) as categories
FROM knowledge_base");
$stats = $r->fetch(PDO::FETCH_ASSOC);
$bc = $db->query("SELECT count(*) as total FROM brain_config WHERE is_active=true");
$brainConfigs = $bc->fetch(PDO::FETCH_ASSOC);
respond([
'status' => 'ok',
'knowledge_base' => $stats,
'brain_configs' => $brainConfigs,
'server' => 'S88 gateway → S89 PG'
]);
break;
case 'search':
$q = $_GET['q'] ?? $_POST['q'] ?? '';
if (!$q) respond(['error' => 'Missing q parameter'], 400);
$limit = intval($_GET['limit'] ?? 10);
$stmt = $db->prepare("SELECT id, section, title, content, category,
similarity(title || ' ' || content, :q) as relevance
FROM knowledge_base
WHERE title || ' ' || content ILIKE :pattern
ORDER BY relevance DESC
LIMIT :lim");
$stmt->execute(['q' => $q, 'pattern' => "%$q%", 'lim' => $limit]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
respond(['status' => 'ok', 'query' => $q, 'count' => count($results), 'results' => $results]);
break;
case 'sections':
$r = $db->query("SELECT section, count(*) as entries FROM knowledge_base GROUP BY section ORDER BY entries DESC");
respond(['status' => 'ok', 'sections' => $r->fetchAll(PDO::FETCH_ASSOC)]);
break;
case 'ingest':
$title = $_POST['title'] ?? '';
$content = $_POST['content'] ?? '';
$section = $_POST['section'] ?? 'general';
$category = $_POST['category'] ?? 'manual';
if (!$title || !$content) respond(['error' => 'Missing title or content'], 400);
$stmt = $db->prepare("INSERT INTO knowledge_base (section, title, content, category, created_at, updated_at)
VALUES (:section, :title, :content, :category, NOW(), NOW()) RETURNING id");
$stmt->execute(['section' => $section, 'title' => $title, 'content' => $content, 'category' => $category]);
$id = $stmt->fetchColumn();
respond(['status' => 'ok', 'id' => $id, 'message' => "Entry ingested: $title"]);
break;
default:
respond(['error' => 'Unknown action', 'available' => ['stats','search','sections','ingest']], 400);
}
} catch (Exception $e) {
error_log("WEVIA_KB_GW: " . $e->getMessage());
respond(['error' => 'DB connection failed', 'detail' => $e->getMessage()], 500);
}