feat(tools): persona-driven multi-domain corpus + model routing

Generalize the family-locked legal tools into caveauAI persona profiles
(client 57 chat profiles, resolved in-process via the chat_profiles bridge).
Each tool accepts an optional `profile` slug that scopes the corpus package(s),
search method, system prompt and synthesis model; omitting it falls back to the
family-legal package so existing behaviour is unchanged.

- dbnToolsResolvePersona / dbnToolsListPersonas / dbnToolsBootChatProfiles in
  bootstrap.php; new api/personas.php + dbn.list_personas MCP tool.
- LegalTools search/ask/corpusContextForSummarize and the BvjAnalyzer /
  LegalAnalysis / translate paths take the persona's packages + prompt + model.
- Persona <select> on ask/search/summarize (populated from api/personas.php).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 20:49:58 +02:00
parent 5a0ef89dca
commit 662fbf7d6d
16 changed files with 404 additions and 58 deletions
+4 -1
View File
@@ -13,6 +13,9 @@ $mode = in_array($rawMode, ['hybrid', 'bm25', 'vector', 'azure'], true) ? $r
$language = dbnToolsNormalizeLanguage($input['language'] ?? 'en');
$limit = max(1, min(20, (int)($input['limit'] ?? 8)));
$category = isset($input['category']) && $input['category'] !== '' ? trim((string)$input['category']) : null;
$persona = (isset($input['profile']) && is_string($input['profile']) && trim($input['profile']) !== '')
? trim($input['profile'])
: null;
const EXCLUDED_DOMAIN = 'dobetternorge.no';
@@ -23,7 +26,7 @@ if (mb_strlen($query, 'UTF-8') < 3) {
try {
// ── HYBRID: delegate to the existing RAG pipeline ──────────────────────
if ($mode === 'hybrid') {
$result = (new DbnLegalToolsService())->search($query, $language, $limit, 'disabled', null);
$result = (new DbnLegalToolsService())->search($query, $language, $limit, 'disabled', null, 'both', $persona);
$hits = array_map(fn($h) => [
'title' => $h['title'] ?? '',
'category' => $h['category'] ?? '',