Changeset 0.22.8 (#150)

This commit is contained in:
2026-03-04 16:06:12 +00:00
parent 389e47b0f9
commit 7e26a2a261
114 changed files with 3700 additions and 7572 deletions

View File

@@ -1,17 +1,11 @@
// ==========================================
// Chat Switchboard Chat Surface Application
// Chat Switchboard Application (Chat Surface)
// ==========================================
// Chat-specific init, boot, auth, listener dispatch.
// App state, fetchModels, resolveCapabilities defined in app-state.js.
// Domain logic in chat.js, notes.js, settings-handlers.js, admin-handlers.js.
// ── Chat Surface Model Load ────────────────
// Wraps shared fetchModels() with chat-specific UI updates.
async function fetchModelsAndUpdateUI() {
await fetchModels();
UI.updateModelSelector();
UI.updateCapabilityBadges();
}
// Boot, auth, init, listener dispatch.
// Shared state (App) and model loading (fetchModels) live in app-state.js
// (loaded by base.html for all surfaces).
// Domain logic lives in chat.js, notes.js, settings-handlers.js,
// admin-handlers.js. UI rendering in ui-*.js files.
async function init() {
console.log('🔀 Chat Switchboard initializing...');
@@ -57,7 +51,15 @@ async function init() {
}
if (API.isAuthed) {
await startApp();
try {
await startApp();
} catch (e) {
console.error('💥 startApp crashed:', e);
// Surface the error visibly (crash banner from chat.html)
const b = document.getElementById('crashBanner');
const d = document.getElementById('crashDetail');
if (b && d) { b.style.display = ''; d.textContent += 'startApp: ' + e.message + '\n' + (e.stack || '') + '\n'; }
}
} else {
showSplash(health);
}
@@ -80,7 +82,12 @@ async function startApp() {
await loadChats();
await loadProjects();
await loadProjectChannelPositions(); // v0.19.2: load channel order per project
await fetchModelsAndUpdateUI();
await fetchModels();
// app-state.js fetchModels populates App.models; UI updates are surface-specific
if (typeof UI !== 'undefined') {
UI.updateModelSelector();
UI.updateCapabilityBadges();
}
// Guard: if token was invalidated during startup (401 → refresh fail → clearTokens),
// kick back to login instead of rendering a broken UI.
@@ -91,7 +98,7 @@ async function startApp() {
}
await initBanners();
initAttachments();
initFiles();
if (typeof ToolsToggle !== 'undefined') ToolsToggle.init();
if (typeof REPL !== 'undefined') REPL.init(); // v0.21.3: admin-gated REPL tab
if (typeof KnowledgeUI !== 'undefined') {
@@ -232,7 +239,8 @@ function updateTabArrows(tabs) {
function showSplash(health) {
// v0.22.6: Server-rendered architecture uses /login page.
// Redirect instead of showing the SPA splash gate.
// Clear stale cookie so the redirect sticks (no loop).
document.cookie = 'sb_token=; path=/; max-age=0';
const base = window.__BASE__ || '';
window.location.href = base + '/login';
}
@@ -324,7 +332,7 @@ function initListeners() {
_initSettingsListeners(); // from settings-handlers.js
_initAdminListeners(); // from admin-handlers.js
_initNotesListeners(); // from notes.js
_initAttachmentListeners(); // from attachments.js
_initFileListeners(); // from files.js
_registerPreviewPanel(); // from ui-format.js — register preview with PanelRegistry
_registerNotesPanel(); // from notes.js — register notes with PanelRegistry
_registerProjectPanel(); // from projects-ui.js — register project detail panel
@@ -563,20 +571,16 @@ async function initBanners() {
root.style.setProperty('--banner-fg', banner.fg || '#ffffff');
const text = banner.text || '';
const pos = banner.position || 'both';
if (pos === 'top' || pos === 'both') {
const el = document.getElementById('bannerTop');
el.textContent = text;
el.classList.add('active');
root.style.setProperty('--banner-top-height', '22px');
}
if (pos === 'bottom' || pos === 'both') {
const el = document.getElementById('bannerBottom');
el.textContent = text;
el.classList.add('active');
root.style.setProperty('--banner-bottom-height', '22px');
}
const top = document.getElementById('bannerTop');
top.textContent = text;
top.classList.add('active');
root.style.setProperty('--banner-top-height', '22px');
const bot = document.getElementById('bannerBottom');
bot.textContent = text;
bot.classList.add('active');
root.style.setProperty('--banner-bottom-height', '22px');
} catch (e) {
// Banners are optional — non-admin users may not have access to settings
console.debug('Banner init skipped:', e.message);