Changeset 0.22.7 (#149)

This commit is contained in:
2026-03-04 10:44:42 +00:00
parent d8e0664fa3
commit 389e47b0f9
62 changed files with 6820 additions and 1476 deletions

View File

@@ -200,9 +200,9 @@ async function handleSaveAdminSettings() {
const userProviders = document.getElementById('adminUserProvidersToggle').checked;
await API.adminUpdateSetting('allow_user_byok', { value: userProviders ? 'true' : 'false' });
// User presets → allow_user_personas policy
const userPresets = document.getElementById('adminUserPresetsToggle').checked;
await API.adminUpdateSetting('allow_user_personas', { value: userPresets ? 'true' : 'false' });
// User personas → allow_user_personas policy
const userPersonas = document.getElementById('adminUserPersonasToggle').checked;
await API.adminUpdateSetting('allow_user_personas', { value: userPersonas ? 'true' : 'false' });
// Default model → default_model policy
const defaultModel = document.getElementById('adminDefaultModel').value;
@@ -266,7 +266,7 @@ async function handleSaveAdminSettings() {
// Live-apply: refresh policies and dependent UI
await initBanners();
UI.checkUserProvidersAllowed();
UI.checkUserPresetsAllowed();
UI.checkUserPersonasAllowed();
fetchModels();
} catch (e) { UI.toast(e.message, 'error'); }
}
@@ -544,13 +544,13 @@ function _initSettingsListeners() {
document.getElementById('settingsTeamCancelMember')?.addEventListener('click', () => {
document.getElementById('settingsTeamAddMember').style.display = 'none';
});
var _teamPresetForm = null;
document.getElementById('settingsTeamAddPresetBtn')?.addEventListener('click', () => {
const container = document.getElementById('settingsTeamAddPreset');
var _teamPersonaForm = null;
document.getElementById('settingsTeamAddPersonaBtn')?.addEventListener('click', () => {
const container = document.getElementById('settingsTeamAddPersona');
container.style.display = '';
if (!_teamPresetForm) {
_teamPresetForm = renderPresetForm(container, {
prefix: 'teamPreset',
if (!_teamPersonaForm) {
_teamPersonaForm = renderPersonaForm(container, {
prefix: 'teamPersona',
showAvatar: true,
showProviderConfig: false,
showKBPicker: true,
@@ -561,29 +561,29 @@ function _initSettingsListeners() {
if (!vals.name) return UI.toast('Name required', 'error');
if (!vals.base_model_id) return UI.toast('Select a base model', 'error');
try {
const result = await API.teamCreatePreset(teamId, vals);
const presetId = result?.id;
if (presetId && vals._pendingAvatar) {
try { await API.adminUploadPresetAvatar(presetId, vals._pendingAvatar); }
catch (e) { console.warn('Team preset avatar upload failed:', e.message); }
const result = await API.teamCreatePersona(teamId, vals);
const personaId = result?.id;
if (personaId && vals._pendingAvatar) {
try { await API.adminUploadPersonaAvatar(personaId, vals._pendingAvatar); }
catch (e) { console.warn('Team persona avatar upload failed:', e.message); }
}
if (presetId && vals._kbValues) {
try { await API.teamSetPresetKBs(teamId, presetId, vals._kbValues); }
catch (e) { console.warn('Team preset KB binding failed:', e.message); }
if (personaId && vals._kbValues) {
try { await API.teamSetPresetKBs(teamId, personaId, vals._kbValues); }
catch (e) { console.warn('Team persona KB binding failed:', e.message); }
}
container.style.display = 'none';
_teamPresetForm.clearForm();
UI.toast('Team preset created');
await UI.loadTeamManagePresets(teamId);
_teamPersonaForm.clearForm();
UI.toast('Team persona created');
await UI.loadTeamManagePersonas(teamId);
await fetchModels();
} catch (e) { UI.toast(e.message, 'error'); }
},
onCancel: () => { container.style.display = 'none'; _teamPresetForm.clearForm(); }
onCancel: () => { container.style.display = 'none'; _teamPersonaForm.clearForm(); }
});
} else {
_teamPresetForm.clearForm();
_teamPersonaForm.clearForm();
}
UI.loadTeamPresetModelDropdown(UI._managingTeamId);
UI.loadTeamPersonaModelDropdown(UI._managingTeamId);
});
// Team — providers (primitive-based, initialized lazily via UI.loadTeamManageProviders)
@@ -595,13 +595,13 @@ function _initSettingsListeners() {
});
// User — personal presets
var _userPresetForm = null;
document.getElementById('userAddPresetBtn')?.addEventListener('click', () => {
const container = document.getElementById('userAddPresetForm');
var _userPersonaForm = null;
document.getElementById('userAddPersonaBtn')?.addEventListener('click', () => {
const container = document.getElementById('userAddPersonaForm');
container.style.display = container.style.display === 'none' ? '' : 'none';
if (!_userPresetForm) {
_userPresetForm = renderPresetForm(container, {
prefix: 'userPreset',
if (!_userPersonaForm) {
_userPersonaForm = renderPersonaForm(container, {
prefix: 'userPersona',
showAvatar: true,
showProviderConfig: false,
showKBPicker: true,
@@ -610,30 +610,30 @@ function _initSettingsListeners() {
if (!vals.name) return UI.toast('Name required', 'error');
if (!vals.base_model_id) return UI.toast('Select a base model', 'error');
try {
const result = await API.createUserPreset(vals);
const presetId = result?.id;
if (presetId && vals._pendingAvatar) {
try { await API.adminUploadPresetAvatar(presetId, vals._pendingAvatar); }
catch (e) { console.warn('User preset avatar upload failed:', e.message); }
const result = await API.createUserPersona(vals);
const personaId = result?.id;
if (personaId && vals._pendingAvatar) {
try { await API.adminUploadPersonaAvatar(personaId, vals._pendingAvatar); }
catch (e) { console.warn('User persona avatar upload failed:', e.message); }
}
if (presetId && vals._kbValues) {
try { await API.setUserPresetKBs(presetId, vals._kbValues); }
catch (e) { console.warn('User preset KB binding failed:', e.message); }
if (personaId && vals._kbValues) {
try { await API.setUserPresetKBs(personaId, vals._kbValues); }
catch (e) { console.warn('User persona KB binding failed:', e.message); }
}
container.style.display = 'none';
_userPresetForm.clearForm();
UI.toast('Preset created');
await UI.loadUserPresets();
_userPersonaForm.clearForm();
UI.toast('Persona created');
await UI.loadUserPersonas();
await fetchModels();
} catch (e) { UI.toast(e.message, 'error'); }
},
onCancel: () => { container.style.display = 'none'; _userPresetForm.clearForm(); }
onCancel: () => { container.style.display = 'none'; _userPersonaForm.clearForm(); }
});
}
const sel = _userPresetForm.getModelSelect();
const sel = _userPersonaForm.getModelSelect();
if (sel) {
sel.innerHTML = '<option value="">Select base model...</option>';
App.models.filter(m => !m.isPreset).forEach(m => {
App.models.filter(m => !m.isPersona).forEach(m => {
const opt = document.createElement('option');
opt.value = m.baseModelId || m.id;
opt.textContent = (m.name || m.id) + (m.provider ? ` (${m.provider})` : '');
@@ -648,7 +648,7 @@ function _initSettingsListeners() {
});
document.getElementById('adminBannerPreset')?.addEventListener('change', (e) => {
const preset = UI._bannerPresets[e.target.value];
if (preset) {
if (persona) {
document.getElementById('adminBannerText').value = preset.text || '';
document.getElementById('adminBannerBg').value = preset.bg || '#007a33';
document.getElementById('adminBannerBgHex').value = preset.bg || '#007a33';