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:
@@ -12,31 +12,37 @@ final class DbnMcpRuntime
|
||||
$lang = self::langSchema();
|
||||
$text = ['type' => 'string', 'description' => 'Text to process.'];
|
||||
$useCase = ['type' => 'boolean', 'description' => 'Use private My Case context. Defaults to false.'];
|
||||
$persona = ['type' => 'string', 'description' => 'Legal persona/profile slug that scopes the corpus and answer style: family, child-welfare, immigration, labour, consumer-tenancy, or general. Defaults to family. Call dbn.list_personas for the live list.'];
|
||||
|
||||
return [
|
||||
self::tool('dbn.search_legal', 'Search DBN legal corpus', 'Search the DBN Norwegian family-law corpus.', [
|
||||
self::tool('dbn.search_legal', 'Search DBN legal corpus', 'Search the DBN Norwegian legal corpus, scoped by the chosen legal persona (family by default).', [
|
||||
'query' => ['type' => 'string', 'minLength' => 3],
|
||||
'language' => $lang,
|
||||
'limit' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 10],
|
||||
'corpus_scope' => ['type' => 'string', 'enum' => ['shared', 'private', 'both']],
|
||||
'profile' => $persona,
|
||||
], ['query']),
|
||||
self::tool('dbn.corpus_search', 'Advanced corpus search', 'Search the DBN legal corpus with a chosen retrieval mode (hybrid, bm25, vector, azure) and optional category filter.', [
|
||||
self::tool('dbn.corpus_search', 'Advanced corpus search', 'Search the DBN legal corpus with a chosen retrieval mode (hybrid, bm25, vector, azure) and optional category filter. The persona (profile) scopes the hybrid mode.', [
|
||||
'query' => ['type' => 'string', 'minLength' => 3],
|
||||
'language' => $lang,
|
||||
'mode' => ['type' => 'string', 'enum' => ['hybrid', 'bm25', 'vector', 'azure']],
|
||||
'limit' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 20],
|
||||
'category' => ['type' => 'string'],
|
||||
'profile' => $persona,
|
||||
], ['query']),
|
||||
self::tool('dbn.ask', 'Ask a legal question', 'Answer a legal preparation question with source-grounded DBN context.', [
|
||||
self::tool('dbn.ask', 'Ask a legal question', 'Answer a legal preparation question with source-grounded DBN context, using the chosen legal persona (model + corpus + style).', [
|
||||
'question' => ['type' => 'string', 'minLength' => 5],
|
||||
'language' => $lang,
|
||||
'use_case_context' => $useCase,
|
||||
'profile' => $persona,
|
||||
], ['question']),
|
||||
self::tool('dbn.list_personas', 'List legal personas', 'List the available DBN legal personas (saved caveauAI agent profiles). Pass a returned slug as the `profile` argument to search/ask tools.', []),
|
||||
self::tool('dbn.summarize', 'Summarize document', 'Summarize pasted case text with optional legal-corpus enrichment.', [
|
||||
'text' => $text,
|
||||
'language' => $lang,
|
||||
'use_legal_corpus' => ['type' => 'boolean'],
|
||||
'use_case_context' => $useCase,
|
||||
'profile' => $persona,
|
||||
], ['text']),
|
||||
self::tool('dbn.timeline', 'Extract timeline', 'Extract dates, hearings, milestones, and deadlines from case text.', [
|
||||
'text' => $text,
|
||||
@@ -162,6 +168,7 @@ final class DbnMcpRuntime
|
||||
'language' => self::language($args['language'] ?? 'en'),
|
||||
'limit' => (int)($args['limit'] ?? $args['top_k'] ?? 8),
|
||||
'corpus_scope' => self::corpusScope($args['corpus_scope'] ?? 'both'),
|
||||
'profile' => self::persona($args['profile'] ?? null),
|
||||
]),
|
||||
'dbn.corpus_search' => self::callJson('api/corpus-search.php', [
|
||||
'query' => (string)($args['query'] ?? ''),
|
||||
@@ -169,17 +176,21 @@ final class DbnMcpRuntime
|
||||
'mode' => in_array($args['mode'] ?? 'hybrid', ['hybrid', 'bm25', 'vector', 'azure'], true) ? (string)$args['mode'] : 'hybrid',
|
||||
'limit' => (int)($args['limit'] ?? 8),
|
||||
'category' => (string)($args['category'] ?? ''),
|
||||
'profile' => self::persona($args['profile'] ?? null),
|
||||
]),
|
||||
'dbn.ask' => self::callJson('api/ask.php', [
|
||||
'question' => (string)($args['question'] ?? ''),
|
||||
'language' => self::language($args['language'] ?? 'en'),
|
||||
'use_my_case' => !empty($args['use_case_context']),
|
||||
'profile' => self::persona($args['profile'] ?? null),
|
||||
]),
|
||||
'dbn.list_personas' => self::callGet('api/personas.php', []),
|
||||
'dbn.summarize' => self::callJson('api/summarize.php', [
|
||||
'text' => (string)($args['text'] ?? ''),
|
||||
'language' => self::language($args['language'] ?? 'en'),
|
||||
'slices' => !empty($args['use_legal_corpus']) ? ['family-legal'] : [],
|
||||
'use_my_case' => !empty($args['use_case_context']),
|
||||
'profile' => self::persona($args['profile'] ?? null),
|
||||
]),
|
||||
'dbn.timeline' => self::callJson('api/timeline.php', [
|
||||
'text' => (string)($args['text'] ?? ''),
|
||||
@@ -682,6 +693,13 @@ final class DbnMcpRuntime
|
||||
return in_array($value, ['shared', 'private', 'both'], true) ? (string)$value : 'both';
|
||||
}
|
||||
|
||||
/** Normalize a persona/profile slug ('' when absent → endpoint applies the default). */
|
||||
private static function persona(mixed $value): string
|
||||
{
|
||||
$slug = is_string($value) ? trim($value) : '';
|
||||
return preg_match('/^[a-z0-9-]{1,64}$/', $slug) === 1 ? $slug : '';
|
||||
}
|
||||
|
||||
private static function docType(mixed $value): string
|
||||
{
|
||||
$value = (string)$value;
|
||||
|
||||
Reference in New Issue
Block a user