110 lines
4.0 KiB
PHP
Executable File
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);
|
|
}
|