feat(tools): persona selector across standalone tools + dashboard chat
Wire the legal-domain persona picker into corpus, deep-research, korrespond and the dashboard chat. Each endpoint reads the chosen profile, resolves its packages against client 57, and scopes retrieval via package_ids (falling back to family when omitted). New dashboard tenants now subscribe to all DBN domain packages so persona switching survives the subscription intersection. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
let uploadFiles = [];
|
||||
let lastResult = null;
|
||||
let branchContext = null;
|
||||
let persona = '';
|
||||
|
||||
const SLICE_DEFS = [
|
||||
{ id: 'family_core', label: 'Family Law Core' },
|
||||
@@ -42,6 +43,8 @@
|
||||
slices: Array.from(document.querySelectorAll('.dr-slice')),
|
||||
langButtons: Array.from(document.querySelectorAll('#drLangSwitcher .lang-btn')),
|
||||
engineRadios: Array.from(document.querySelectorAll('input[name="drEngine"]')),
|
||||
personaControl: document.getElementById('drPersonaControl'),
|
||||
personaSelect: document.getElementById('drPersonaSelect'),
|
||||
subQ: document.getElementById('drSubQ'),
|
||||
subQVal: document.getElementById('drSubQValue'),
|
||||
chunkLimit: document.getElementById('drChunkLimit'),
|
||||
@@ -79,6 +82,7 @@
|
||||
bindUpload();
|
||||
bindModal();
|
||||
bindBranch();
|
||||
loadPersonas();
|
||||
els.form.addEventListener('submit', onSubmit);
|
||||
els.results.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.dr-branch-btn');
|
||||
@@ -325,6 +329,7 @@
|
||||
language: lang,
|
||||
controls: getControls(),
|
||||
};
|
||||
if (persona) payload.profile = persona;
|
||||
const _drDocIds = (document.getElementById('docPickerIds')?.value || '').split(',').map(Number).filter(Boolean);
|
||||
if (_drDocIds.length) payload.doc_ids = _drDocIds;
|
||||
if (branchContext) {
|
||||
@@ -644,6 +649,33 @@
|
||||
</div>`;
|
||||
}
|
||||
|
||||
async function loadPersonas() {
|
||||
if (!els.personaSelect) return;
|
||||
try {
|
||||
const r = await fetch('api/personas.php', { credentials: 'same-origin', headers: { Accept: 'application/json' } });
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (!r.ok || data.ok !== true || !Array.isArray(data.personas) || !data.personas.length) return;
|
||||
const fallback = data.default_persona || 'family';
|
||||
els.personaSelect.innerHTML = '';
|
||||
data.personas.forEach((p) => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = p.slug;
|
||||
opt.textContent = p.name || p.slug;
|
||||
els.personaSelect.appendChild(opt);
|
||||
});
|
||||
const saved = sessionStorage.getItem('dbnPersona');
|
||||
const initial = (saved && data.personas.some((p) => p.slug === saved)) ? saved
|
||||
: (data.personas.some((p) => p.slug === fallback) ? fallback : data.personas[0].slug);
|
||||
persona = initial;
|
||||
els.personaSelect.value = initial;
|
||||
els.personaSelect.addEventListener('change', () => {
|
||||
persona = els.personaSelect.value;
|
||||
sessionStorage.setItem('dbnPersona', persona);
|
||||
});
|
||||
els.personaControl?.classList.remove('is-hidden');
|
||||
} catch (_) { /* personas are optional UI sugar; ignore failures */ }
|
||||
}
|
||||
|
||||
function bindBranch() {
|
||||
if (!els.branchClear) return;
|
||||
els.branchClear.addEventListener('click', clearBranch);
|
||||
|
||||
Reference in New Issue
Block a user