464b8572d3
health.php: Add azure_search check — calls /$count endpoint and
reports doc count in the index. Reads DBN_AZURE_SEARCH_{ENDPOINT,KEY,INDEX}.
corpus-search.php: Add azure mode — semantic + vector hybrid search
via Azure AI Search bnl-legal-v2. Embeds query with LiteLLM
nomic-embed-text; expands keepCats to include government-policy,
health-law, social-services, labour-law, immigration (previously
blocked by contamination workaround, now safe to include).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
113 lines
4.0 KiB
PHP
113 lines
4.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../includes/bootstrap.php';
|
|
require_once __DIR__ . '/../includes/AzureOpenAiGateway.php';
|
|
|
|
dbnToolsRequireMethod('GET');
|
|
dbnToolsRequireAuth();
|
|
|
|
$checks = [];
|
|
$checks['caveau_auth'] = [
|
|
'ok' => true,
|
|
'detail' => 'Tools login uses Caveau client_users for tenant ' . dbnToolsClientSlug(),
|
|
];
|
|
|
|
$azure = new DbnAzureOpenAiGateway();
|
|
$missingChat = $azure->missingChatConfig();
|
|
$missingEmbedding = $azure->missingEmbeddingConfig();
|
|
$checks['azure_chat_config'] = [
|
|
'ok' => !$missingChat,
|
|
'detail' => !$missingChat ? 'Configured' : 'Missing: ' . implode(', ', $missingChat),
|
|
];
|
|
$checks['azure_embedding_config'] = [
|
|
'ok' => !$missingEmbedding,
|
|
'detail' => !$missingEmbedding ? 'Configured' : 'Missing: ' . implode(', ', $missingEmbedding),
|
|
];
|
|
$checks['azure_reachability'] = [
|
|
'ok' => false,
|
|
'detail' => 'Not checked because chat config is incomplete',
|
|
];
|
|
if (!$missingChat) {
|
|
$reachable = $azure->ping(8);
|
|
$checks['azure_reachability'] = [
|
|
'ok' => $reachable,
|
|
'detail' => $reachable ? 'Azure chat deployment responded' : 'Azure chat deployment did not respond',
|
|
];
|
|
}
|
|
|
|
try {
|
|
$db = dbnToolsDb();
|
|
$db->query('SELECT 1');
|
|
$checks['db_connectivity'] = ['ok' => true, 'detail' => 'CaveauAI admin DB reachable'];
|
|
|
|
$client = dbnToolsFetchClient($db);
|
|
$checks['dobetter_client'] = [
|
|
'ok' => (bool)$client,
|
|
'detail' => $client ? 'Client id ' . $client['id'] . ' found' : 'Client slug ' . dbnToolsClientSlug() . ' not found',
|
|
];
|
|
|
|
$packageSlug = dbnToolsRequiredPackageSlug();
|
|
$package = dbnToolsFetchPackage($packageSlug, $db);
|
|
$checks['family_legal_package'] = [
|
|
'ok' => (bool)$package && !empty($package['is_active']),
|
|
'detail' => $package ? 'Package id ' . $package['id'] . ' found' : $packageSlug . ' package not found',
|
|
];
|
|
|
|
$subOk = $client && $package && dbnToolsHasActiveSubscription((int)$client['id'], (int)$package['id'], $db);
|
|
$checks['family_legal_subscription'] = [
|
|
'ok' => (bool)$subOk,
|
|
'detail' => $subOk ? 'Active subscription visible' : 'Active subscription not visible',
|
|
];
|
|
} catch (Throwable $e) {
|
|
$checks['db_connectivity'] = ['ok' => false, 'detail' => $e->getMessage()];
|
|
$checks['dobetter_client'] = ['ok' => false, 'detail' => 'Not checked'];
|
|
$checks['family_legal_package'] = ['ok' => false, 'detail' => 'Not checked'];
|
|
$checks['family_legal_subscription'] = ['ok' => false, 'detail' => 'Not checked'];
|
|
}
|
|
|
|
$searchEndpoint = rtrim((string)dbnToolsEnv('DBN_AZURE_SEARCH_ENDPOINT', ''), '/');
|
|
$searchKey = (string)dbnToolsEnv('DBN_AZURE_SEARCH_KEY', '');
|
|
$searchIndex = (string)dbnToolsEnv('DBN_AZURE_SEARCH_INDEX', '');
|
|
if ($searchEndpoint && $searchKey && $searchIndex) {
|
|
$countUrl = "$searchEndpoint/indexes/$searchIndex/docs/\$count?api-version=2024-05-01-preview";
|
|
$ch = curl_init($countUrl);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 8,
|
|
CURLOPT_HTTPHEADER => ["api-key: $searchKey"],
|
|
]);
|
|
$resp = curl_exec($ch);
|
|
$code = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
|
|
curl_close($ch);
|
|
$count = is_numeric(trim((string)$resp)) ? (int)trim($resp) : null;
|
|
$checks['azure_search'] = [
|
|
'ok' => $code === 200 && $count !== null,
|
|
'detail' => $code === 200 ? "$count docs in $searchIndex" : "HTTP $code",
|
|
];
|
|
} else {
|
|
$checks['azure_search'] = ['ok' => false, 'detail' => 'Azure Search env vars not configured'];
|
|
}
|
|
|
|
$logPath = dbnToolsMetadataLogPath();
|
|
$dir = dirname($logPath);
|
|
$checks['metadata_log'] = [
|
|
'ok' => is_dir($dir) && is_writable($dir),
|
|
'detail' => is_dir($dir) && is_writable($dir) ? 'Metadata directory is writable' : 'Metadata directory is not writable',
|
|
];
|
|
|
|
$ok = true;
|
|
foreach ($checks as $check) {
|
|
if (empty($check['ok'])) {
|
|
$ok = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
dbnToolsRespond([
|
|
'ok' => $ok,
|
|
'status' => $ok ? 'ok' : 'degraded',
|
|
'version' => DBN_TOOLS_VERSION,
|
|
'checks' => $checks,
|
|
], $ok ? 200 : 503);
|