Changeset 0.28.3.2 (#189)

This commit is contained in:
2026-03-14 16:46:16 +00:00
parent 205a770c74
commit fa6b04434a
66 changed files with 304 additions and 320 deletions

View File

@@ -25,19 +25,19 @@
<div class="splash-auth">
<div id="splashError" class="splash-error" style="display:none;"></div>
<div class="auth-tabs">
<button id="authTabLogin" class="auth-tab active" onclick="switchAuthTab('login')">Sign In</button>
<button id="authTabRegister" class="auth-tab" onclick="switchAuthTab('register')">Register</button>
<button id="authTabLogin" class="auth-tab active" onclick="sb.call('switchAuthTab','login')">Sign In</button>
<button id="authTabRegister" class="auth-tab" onclick="sb.call('switchAuthTab','register')">Register</button>
</div>
<div id="authLoginForm">
<input type="text" id="authLogin" placeholder="Username or email" autocomplete="username">
<input type="password" id="authPassword" placeholder="Password" autocomplete="current-password">
<button id="authLoginBtn" onclick="handleLogin()">Sign In</button>
<button id="authLoginBtn" onclick="sb.call('handleLogin')">Sign In</button>
</div>
<div id="authRegisterForm" style="display:none;">
<input type="text" id="authUsername" placeholder="Username" autocomplete="username">
<input type="text" id="authEmail" placeholder="Email" autocomplete="email">
<input type="password" id="authRegPassword" placeholder="Password" autocomplete="new-password">
<button id="authRegisterBtn" onclick="handleRegister()">Create Account</button>
<button id="authRegisterBtn" onclick="sb.call('handleRegister')">Create Account</button>
</div>
<div id="authError" class="auth-error"></div>
<div id="brandAuthFooter" class="auth-footer"></div>
@@ -80,7 +80,7 @@ window.addEventListener('unhandledrejection', function(e) {
<div id="sidebar" class="sidebar">
<div class="sidebar-top">
{{/* Brand — click toggles sidebar */}}
<div class="sb-brand" onclick="UI.toggleSidebar()" role="button" tabindex="0">
<div class="sb-brand" onclick="sb.call('UI.toggleSidebar')" role="button" tabindex="0">
<div id="brandSidebarLogo" class="sb-logo">
<img src="{{.BasePath}}/favicon-32.png" alt="" class="brand-logo-img">
</div>
@@ -89,7 +89,7 @@ window.addEventListener('unhandledrejection', function(e) {
</div>
{{/* New Chat button */}}
<button id="newChatBtn" class="sb-btn" onclick="newChat()" title="New chat">
<button id="newChatBtn" class="sb-btn" onclick="sb.call('newChat')" title="New chat">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
<span class="sb-label">New Chat</span>
</button>
@@ -118,11 +118,11 @@ window.addEventListener('unhandledrejection', function(e) {
<div id="sidebarNav" class="sidebar-nav sidebar-tab-panel" data-tab-panel="chats">
{{/* Projects section */}}
<div class="sb-section" id="sbSectionProjects">
<div class="sb-section-header" onclick="UI.toggleSidebarSection('projects')">
<div class="sb-section-header" onclick="sb.call('UI.toggleSidebarSection','projects')">
<span class="sb-section-arrow" id="sbArrowProjects"></span>
<span class="sb-section-label">Projects</span>
<button class="sb-section-add" title="New project"
onclick="event.stopPropagation();if(typeof createProject==='function')createProject();">
onclick="sb.callEvent(event,'createProject')">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
@@ -133,11 +133,11 @@ window.addEventListener('unhandledrejection', function(e) {
{{/* Channels section (DMs + named channels) */}}
<div class="sb-section" id="sbSectionChannels">
<div class="sb-section-header" onclick="UI.toggleSidebarSection('channels')">
<div class="sb-section-header" onclick="sb.call('UI.toggleSidebarSection','channels')">
<span class="sb-section-arrow" id="sbArrowChannels"></span>
<span class="sb-section-label">Channels</span>
<button class="sb-section-add" title="New channel"
onclick="event.stopPropagation();newChannelOrDM();">
onclick="sb.callEvent(event,'newChannelOrDM')">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
@@ -148,14 +148,14 @@ window.addEventListener('unhandledrejection', function(e) {
{{/* Chats section (personal AI chats + folders) */}}
<div class="sb-section" id="sbSectionChats">
<div class="sb-section-header" onclick="UI.toggleSidebarSection('chats')">
<div class="sb-section-header" onclick="sb.call('UI.toggleSidebarSection','chats')">
<span class="sb-section-arrow" id="sbArrowChats"></span>
<span class="sb-section-label">Chats</span>
<div class="sb-section-add-group" onclick="event.stopPropagation();">
<button class="sb-section-add" title="New chat" onclick="newChat();">
<button class="sb-section-add" title="New chat" onclick="sb.call('newChat');">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
<button class="sb-section-add" title="New folder" onclick="newFolder();">
<button class="sb-section-add" title="New folder" onclick="sb.call('newFolder');">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
</button>
</div>
@@ -223,12 +223,12 @@ window.addEventListener('unhandledrejection', function(e) {
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
</button>
{{/* Panel toggle */}}
<button id="panelToggleBtn" class="action-btn" title="Toggle side panel" onclick="if(typeof PanelRegistry!=='undefined')PanelRegistry.toggle('preview')">
<button id="panelToggleBtn" class="action-btn" title="Toggle side panel" onclick="sb.call('PanelRegistry.toggle','preview')">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="15" y1="3" x2="15" y2="21"/></svg>
</button>
{{/* Notification bell (inline, not fixed) */}}
<div id="notifWrap" class="notif-wrap">
<button class="notif-bell" onclick="Notifications.toggleDropdown()">
<button class="notif-bell" onclick="sb.call('Notifications.toggleDropdown')">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span id="notifBadge" class="notif-badge" style="display:none;">0</span>
</button>
@@ -318,10 +318,10 @@ window.addEventListener('unhandledrejection', function(e) {
<span id="sidePanelLabel" class="side-panel-label"></span>
<div class="side-panel-header-actions">
<span id="sidePanelPanelActions"></span>
<button id="sidePanelFullscreenBtn" class="side-panel-btn" title="Toggle fullscreen" onclick="toggleSidePanelFullscreen()">
<button id="sidePanelFullscreenBtn" class="side-panel-btn" title="Toggle fullscreen" onclick="sb.call('toggleSidePanelFullscreen')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
</button>
<button class="side-panel-btn" title="Close panel" onclick="PanelRegistry.closeAll()">
<button class="side-panel-btn" title="Close panel" onclick="sb.call('PanelRegistry.closeAll')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
@@ -345,7 +345,7 @@ window.addEventListener('unhandledrejection', function(e) {
<div id="sidePanelOverlay" class="side-panel-overlay" style="display:none;"></div>
{{/* ── Lightbox ────────────────────────────── */}}
<div id="lightbox" class="lightbox" onclick="closeLightbox()">
<div id="lightbox" class="lightbox" onclick="sb.call('closeLightbox')">
<img id="lightboxImg" src="" alt="">
</div>
@@ -377,14 +377,14 @@ window.addEventListener('unhandledrejection', function(e) {
<div id="teamAdminContent" class="team-admin-content" style="display:none;">
{{/* Tab bar */}}
<div id="teamAdminTabs" style="display:flex;gap:2px;padding:8px 16px;border-bottom:1px solid var(--border);flex-shrink:0;overflow-x:auto;">
<button class="admin-tab active" data-ttab="members" onclick="UI.switchTeamTab('members')">Members</button>
<button class="admin-tab" data-ttab="providers" onclick="UI.switchTeamTab('providers')">Providers</button>
<button class="admin-tab" data-ttab="personas" onclick="UI.switchTeamTab('personas')">Personas</button>
<button class="admin-tab" data-ttab="knowledge" onclick="UI.switchTeamTab('knowledge')">Knowledge</button>
<button class="admin-tab" data-ttab="groups" onclick="UI.switchTeamTab('groups')">Groups</button>
<button class="admin-tab" data-ttab="settings" onclick="UI.switchTeamTab('settings')">Settings</button>
<button class="admin-tab" data-ttab="usage" onclick="UI.switchTeamTab('usage')">Usage</button>
<button class="admin-tab" data-ttab="activity" onclick="UI.switchTeamTab('activity')">Activity</button>
<button class="admin-tab active" data-ttab="members" onclick="sb.call('UI.switchTeamTab','members')">Members</button>
<button class="admin-tab" data-ttab="providers" onclick="sb.call('UI.switchTeamTab','providers')">Providers</button>
<button class="admin-tab" data-ttab="personas" onclick="sb.call('UI.switchTeamTab','personas')">Personas</button>
<button class="admin-tab" data-ttab="knowledge" onclick="sb.call('UI.switchTeamTab','knowledge')">Knowledge</button>
<button class="admin-tab" data-ttab="groups" onclick="sb.call('UI.switchTeamTab','groups')">Groups</button>
<button class="admin-tab" data-ttab="settings" onclick="sb.call('UI.switchTeamTab','settings')">Settings</button>
<button class="admin-tab" data-ttab="usage" onclick="sb.call('UI.switchTeamTab','usage')">Usage</button>
<button class="admin-tab" data-ttab="activity" onclick="sb.call('UI.switchTeamTab','activity')">Activity</button>
</div>
{{/* Tab content panels */}}
@@ -482,8 +482,8 @@ window.addEventListener('unhandledrejection', function(e) {
<div class="form-group"><label>Config (JSON)</label><textarea id="rpConfig" rows="4">{}</textarea></div>
<div class="form-group"><label><input type="checkbox" id="rpActive" checked> Active</label></div>
<div style="display:flex;gap:8px;">
<button id="rpSaveBtn" class="btn-primary" onclick="Pages.saveRoutingPolicy()">Save</button>
<button id="rpCancelBtn" class="btn-secondary" onclick="Pages.hideRoutingForm()">Cancel</button>
<button id="rpSaveBtn" class="btn-primary" onclick="sb.call('Pages.saveRoutingPolicy')">Save</button>
<button id="rpCancelBtn" class="btn-secondary" onclick="sb.call('Pages.hideRoutingForm')">Cancel</button>
</div>
</div>
@@ -510,28 +510,28 @@ window.addEventListener('unhandledrejection', function(e) {
{{/* CM6 bundle — chat-specific (code input, extension editor) */}}
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/vendor/codemirror/codemirror.bundle.js?v={{$.Version}}" onerror="console.warn('[CM6] Bundle not available — falling back to textarea')"></script>
{{/* App JS — order matches index.html (minus api/events/ui-primitives/ui-format already in base) */}}
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/extensions.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/panels.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/ui-settings.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/ui-admin.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/tokens.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notes.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/note-graph.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/files.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/tools-toggle.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/knowledge-ui.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/memory-ui.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/persona-kb.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/extensions.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/panels.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/ui-settings.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/ui-admin.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/tokens.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notes.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/note-graph.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/files.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/tools-toggle.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/knowledge-ui.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/memory-ui.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/persona-kb.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/projects-ui.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/channel-models.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notification-prefs.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notifications.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/chat.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/channel-models.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notification-prefs.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/notifications.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/chat.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/settings-handlers.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/admin-handlers.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-api.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-admin.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-queue.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/task-sidebar.js?v={{$.Version}}"></script>
<script nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/app.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/admin-handlers.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-api.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-admin.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/workflow-queue.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/task-sidebar.js?v={{$.Version}}"></script>
<script type="module" nonce="{{$.CSPNonce}}" src="{{$.BasePath}}/js/app.js?v={{$.Version}}"></script>
{{end}}