Changeset 0.15.0 (#71)
This commit is contained in:
@@ -52,6 +52,26 @@ async function summarizeAndContinue() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Per-Channel Auto-Compaction Toggle ──────
|
||||
|
||||
async function toggleChannelAutoCompact(enabled) {
|
||||
const chatId = App.currentChatId;
|
||||
if (!chatId) return;
|
||||
const chat = App.chats.find(c => c.id === chatId);
|
||||
if (!chat) return;
|
||||
|
||||
// Update local state
|
||||
if (!chat.settings) chat.settings = {};
|
||||
chat.settings.auto_compaction = enabled;
|
||||
|
||||
// Persist to server (JSONB merge)
|
||||
try {
|
||||
await API.updateChannel(chatId, { settings: { auto_compaction: enabled } });
|
||||
} catch (e) {
|
||||
console.warn('Failed to save auto-compaction setting:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Chat Management ──────────────────────────
|
||||
|
||||
async function loadChats() {
|
||||
|
||||
@@ -58,13 +58,36 @@ function updateAvatarPreview(dataURI) {
|
||||
|
||||
// ── Settings Handlers ────────────────────────
|
||||
|
||||
function handleSaveSettings() {
|
||||
async function handleSaveSettings() {
|
||||
App.settings.model = document.getElementById('settingsModel').value || App.settings.model;
|
||||
App.settings.systemPrompt = document.getElementById('settingsSystemPrompt').value.trim();
|
||||
App.settings.maxTokens = parseInt(document.getElementById('settingsMaxTokens').value) || 0; // 0 = auto
|
||||
App.settings.temperature = parseFloat(document.getElementById('settingsTemp').value) || 0.7;
|
||||
App.settings.showThinking = document.getElementById('settingsThinking').checked;
|
||||
saveSettings();
|
||||
|
||||
// ── Save profile fields (display name, email) ──
|
||||
const displayName = document.getElementById('profileDisplayName').value.trim();
|
||||
const email = document.getElementById('profileEmail').value.trim();
|
||||
const profileUpdates = {};
|
||||
if (displayName !== (API.user?.display_name || '')) profileUpdates.display_name = displayName;
|
||||
if (email !== (API.user?.email || '')) profileUpdates.email = email;
|
||||
if (Object.keys(profileUpdates).length > 0) {
|
||||
try {
|
||||
const updated = await API.updateProfile(profileUpdates);
|
||||
// Sync local user object so sidebar/avatar reflect the change
|
||||
if (updated) {
|
||||
if (updated.display_name !== undefined) API.user.display_name = updated.display_name;
|
||||
if (updated.email !== undefined) API.user.email = updated.email;
|
||||
API.saveTokens();
|
||||
UI.updateUser();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Profile save failed:', e.message);
|
||||
UI.toast('Profile update failed: ' + e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
UI.updateModelSelector();
|
||||
UI.updateCapabilityBadges();
|
||||
UI.closeSettings();
|
||||
@@ -204,6 +227,20 @@ async function handleSaveAdminSettings() {
|
||||
};
|
||||
await API.adminUpdateSetting('search_config', { value: searchConfig });
|
||||
|
||||
// Auto-Compaction config → global_settings
|
||||
const compactionEnabled = document.getElementById('adminCompactionEnabled')?.checked || false;
|
||||
const compactionThreshold = parseInt(document.getElementById('adminCompactionThreshold')?.value) || 70;
|
||||
const compactionCooldown = parseInt(document.getElementById('adminCompactionCooldown')?.value) || 30;
|
||||
await API.adminUpdateSetting('auto_compaction', { value: {
|
||||
enabled: compactionEnabled,
|
||||
threshold: compactionThreshold,
|
||||
cooldown: compactionCooldown,
|
||||
}});
|
||||
// Scanner reads these individual keys each tick
|
||||
await API.adminUpdateSetting('auto_compaction_enabled', { value: compactionEnabled });
|
||||
await API.adminUpdateSetting('auto_compaction_threshold', { value: compactionThreshold / 100 });
|
||||
await API.adminUpdateSetting('auto_compaction_cooldown_minutes', { value: compactionCooldown });
|
||||
|
||||
UI.toast('Settings saved', 'success');
|
||||
// Live-apply: refresh policies and dependent UI
|
||||
await initBanners();
|
||||
@@ -233,6 +270,9 @@ function _initUserRolePrimitive() {
|
||||
return list.filter(c => c.scope === 'personal');
|
||||
},
|
||||
fetchModels: async () => {
|
||||
// Refresh App.models to ensure personal provider models are current.
|
||||
// Without this, newly added providers may not appear in the dropdown.
|
||||
await fetchModels();
|
||||
return App.models || [];
|
||||
},
|
||||
fetchRoles: async () => {
|
||||
@@ -591,6 +631,11 @@ function _initSettingsListeners() {
|
||||
document.getElementById('adminBannerBgHex')?.addEventListener('input', (e) => { if (/^#[0-9a-f]{6}$/i.test(e.target.value)) { document.getElementById('adminBannerBg').value = e.target.value; UI.updateBannerPreview(); }});
|
||||
document.getElementById('adminBannerFgHex')?.addEventListener('input', (e) => { if (/^#[0-9a-f]{6}$/i.test(e.target.value)) { document.getElementById('adminBannerFg').value = e.target.value; UI.updateBannerPreview(); }});
|
||||
|
||||
// Admin — auto-compaction controls
|
||||
document.getElementById('adminCompactionEnabled')?.addEventListener('change', (e) => {
|
||||
document.getElementById('compactionConfigFields').style.display = e.target.checked ? '' : 'none';
|
||||
});
|
||||
|
||||
// Admin — search provider controls
|
||||
document.getElementById('adminSearchProvider')?.addEventListener('change', (e) => {
|
||||
document.getElementById('searxngConfigFields').style.display = e.target.value === 'searxng' ? '' : 'none';
|
||||
|
||||
@@ -103,6 +103,16 @@ function updateContextWarning() {
|
||||
summarizeBtn.style.display = showSummarize ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
// Show auto-compact toggle next to summarize button
|
||||
const autoToggle = document.getElementById('autoCompactToggle');
|
||||
const autoCheck = document.getElementById('autoCompactCheck');
|
||||
if (autoToggle && autoCheck) {
|
||||
autoToggle.style.display = showSummarize ? 'inline-flex' : 'none';
|
||||
// Reflect current channel setting
|
||||
const chatSettings = chat?.settings || {};
|
||||
autoCheck.checked = chatSettings.auto_compaction !== false; // default: on
|
||||
}
|
||||
|
||||
if (pct >= 0.9 && !Tokens._warningDismissed) {
|
||||
warning.style.display = 'flex';
|
||||
warning.className = 'context-warning danger';
|
||||
|
||||
@@ -803,6 +803,19 @@ Object.assign(UI, {
|
||||
document.getElementById('searxngConfigFields').style.display =
|
||||
(searchCfg.provider === 'searxng') ? '' : 'none';
|
||||
|
||||
// Auto-Compaction (global_settings)
|
||||
const compactionCfg = getSetting('auto_compaction', {}) || {};
|
||||
const compactionEnabled = document.getElementById('adminCompactionEnabled');
|
||||
if (compactionEnabled) {
|
||||
compactionEnabled.checked = !!compactionCfg.enabled;
|
||||
document.getElementById('compactionConfigFields').style.display =
|
||||
compactionCfg.enabled ? '' : 'none';
|
||||
}
|
||||
const compThreshold = document.getElementById('adminCompactionThreshold');
|
||||
if (compThreshold) compThreshold.value = String(compactionCfg.threshold || 70);
|
||||
const compCooldown = document.getElementById('adminCompactionCooldown');
|
||||
if (compCooldown) compCooldown.value = String(compactionCfg.cooldown || 30);
|
||||
|
||||
if (vaultEl) {
|
||||
try {
|
||||
const vault = await API.adminGetVaultStatus();
|
||||
|
||||
@@ -361,10 +361,11 @@ const UI = {
|
||||
const meta = msg.metadata || {};
|
||||
const count = meta.summarized_count || '?';
|
||||
const model = meta.utility_model || 'utility model';
|
||||
const trigger = meta.trigger === 'auto' ? ' · auto' : '';
|
||||
return `
|
||||
<div class="message-summary" data-msg-id="${esc(msg.id || '')}">
|
||||
<div class="summary-header">
|
||||
<span>📝 Conversation summary (${count} messages, by ${esc(model)})</span>
|
||||
<span>📝 Conversation summary (${count} messages, by ${esc(model)}${trigger})</span>
|
||||
</div>
|
||||
<div class="msg-text">${formatMessage(msg.content)}</div>
|
||||
</div>`;
|
||||
|
||||
Reference in New Issue
Block a user