diff --git a/VERSION b/VERSION index d21d277..af2dabf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.25.0 +0.25.1 diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 864abc5..8c67b0c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -393,50 +393,101 @@ Vanilla JavaScript, no framework. The frontend ships as static files served by n ``` src/ -├── index.html # Single-page app shell -├── sw.js # Service worker (offline cache) +├── index.html # Redirect stub → server-rendered surfaces +├── sw.js # Service worker (offline cache, BUILD_HASH) ├── manifest.json # PWA manifest ├── css/ -│ ├── styles.css # Core styles (CSS variables, light/dark themes) -│ └── memory.css # Memory settings + admin review panel styles +│ ├── variables.css # Theme vars, reset, base styles +│ ├── layout.css # App shell, workspace, sidebar, responsive +│ ├── primitives.css # Buttons, forms, toasts, toggles, badges, icon-btn +│ ├── modals.css # Modal system, debug, command palette, confirm +│ ├── chat.css # Chat area, markdown, input, files, lightbox +│ ├── panels.css # Side panel, preview, notes, graph +│ ├── surfaces.css # Admin, settings, editor, projects, notes layouts +│ ├── splash.css # Auth splash, PWA banner +│ ├── chat-pane.css # ChatPane component styles +│ ├── pane-container.css # PaneContainer resize/tab styles +│ ├── user-menu.css # UserMenu flyout styles +│ ├── editor-surface.css # Editor surface 3-pane layout +│ ├── channel-models.css # @mention autocomplete, model roster +│ ├── memory.css # Memory settings + admin review +│ ├── notifications.css # Notification dropdown + list +│ ├── notification-prefs.css # SMTP config, notification pref table +│ ├── persona-kb.css # Persona KB picker panel +│ ├── admin-surfaces.css # Admin surface management +│ └── tool-grants.css # Persona tool grants checkbox list ├── js/ +│ ├── ── Primitives (base.html, all surfaces) ── +│ ├── app-state.js # Global state (App, API refs) │ ├── api.js # HTTP client with token refresh -│ ├── app.js # Application state machine, startup, routing -│ ├── chat.js # Chat input abstraction, message send/receive -│ ├── channel-models.js # @mention autocomplete, channel model roster │ ├── events.js # Labeled event bus + WebSocket bridge -│ ├── debug.js # Debug panel, diagnostics, state export -│ ├── ui-core.js # DOM rendering, sidebar, modals, panels -│ ├── ui-format.js # Markdown rendering, @mention pills, code blocks -│ ├── ui-settings.js # Settings tabs, theme, appearance, teams -│ ├── ui-admin.js # Admin panel rendering -│ ├── admin-handlers.js # Admin CRUD operations + extension editors +│ ├── ui-primitives.js # esc(), componentMixin, Providers, Roles, +│ │ # renderCapBadges, renderProviderForm/List, +│ │ # renderRoleConfig, renderUsageDashboard, +│ │ # showConfirm, showPrompt, openModal/closeModal, +│ │ # Theme, mountAvatarUpload +│ ├── ui-format.js # Markdown rendering, code blocks, time formatting +│ ├── ui-core.js # DOM rendering, sidebar, navigation, toast +│ ├── pages.js # Page routing, splash, login +│ │ +│ ├── ── Components (base.html, all surfaces) ── +│ ├── user-menu.js # UserMenu template+factory component +│ ├── model-selector.js # ModelSelector template+factory component +│ ├── file-tree.js # FileTree template+factory component +│ ├── code-editor.js # CodeEditor template+factory component (CM6) +│ ├── note-editor.js # NoteEditor template+factory component +│ ├── chat-pane.js # ChatPane template+factory component +│ ├── pane-container.js # PaneContainer (resizable multi-pane layout) +│ ├── debug.js # Debug panel + diagnostics +│ ├── repl.js # Browser REPL console +│ │ +│ ├── ── Surface: Chat ── +│ ├── app.js # Chat surface boot, auth, WebSocket +│ ├── chat.js # Chat message send/receive, stream +│ ├── extensions.js # Extension framework + sandbox +│ ├── panels.js # Side panel registry +│ ├── ui-settings.js # Settings modal tabs (chat surface) +│ ├── ui-admin.js # Admin navigation + section routing +│ ├── admin-handlers.js # Admin CRUD + extension editors +│ ├── admin-scaffold.js # Admin section HTML scaffolding │ ├── settings-handlers.js # User settings CRUD, command palette │ ├── tokens.js # Input token counting + context budget -│ ├── attachments.js # File upload, paste-to-file, lightbox +│ ├── files.js # File upload, paste-to-file, lightbox │ ├── notes.js # Notes panel CRUD + graph + daily notes │ ├── note-graph.js # Canvas force-directed graph visualization -│ ├── projects-ui.js # Project sidebar, context menu, drag-and-drop -│ ├── knowledge.js # Knowledge base UI -│ ├── memory-ui.js # Memory settings tab + admin review panel +│ ├── projects-ui.js # Project sidebar, context menu, DnD +│ ├── channel-models.js # Channel model roster + @mention AC +│ ├── tools-toggle.js # Tool enable/disable popup +│ ├── knowledge-ui.js # Knowledge base picker + management +│ ├── persona-kb.js # Persona KB assignment panel +│ ├── memory-ui.js # Memory settings + admin review +│ ├── notifications.js # Notification bell + dropdown +│ ├── notification-prefs.js # SMTP config + notification prefs +│ │ +│ ├── ── Surface: Editor ── +│ ├── editor-surface.js # Editor 3-pane boot, workspace management +│ │ +│ ├── ── Surface: Admin ── +│ ├── admin-surfaces.js # Surface management (admin only) +│ │ +│ ├── ── Surface: Login ── +│ ├── pages-splash.js # Login/register splash page +│ │ │ └── __tests__/ # Node.js test suite (node --test) ├── editor/ # CM6 source (compiled at build time) │ ├── package.json # CM6 + language mode dependencies -│ ├── package-lock.json # Lockfile for npm ci │ ├── build.mjs # esbuild script → IIFE bundle │ ├── index.mjs # Bundle entrypoint (window.CM) │ ├── chat-input.mjs # Chat input factory (markdown, code blocks) │ ├── code-editor.mjs # Code editor factory (syntax, keybindings) │ ├── note-editor.mjs # Note editor factory (markdown + wikilinks) -│ ├── wikilink.mjs # CM6 wikilink extension (parse, decorate, autocomplete) -│ └── theme.mjs # Switchboard + chat input + note editor themes -└── vendor/ # Vendored libraries (local + CDN fallback) - ├── marked/ # Markdown renderer - ├── purify/ # DOMPurify (XSS protection) - ├── mermaid/ # Diagram renderer - ├── katex/ # Math renderer - └── codemirror/ # CM6 bundle (built by Docker) - └── codemirror.bundle.js # ~295KB min, ~90KB gzip +│ ├── wikilink.mjs # CM6 wikilink extension +│ └── theme.mjs # CM6 themes (dark/light) +└── vendor/ # Vendored libraries (loaded in base.html) + ├── marked.min.js # Markdown renderer + ├── purify.min.js # DOMPurify (XSS protection) + └── codemirror/ + └── codemirror.bundle.js # CM6 bundle (~295KB min, ~90KB gzip) ``` ### CM6 Integration diff --git a/docs/DESIGN-SURFACES.md b/docs/DESIGN-SURFACES.md index c42fba8..19d955c 100644 --- a/docs/DESIGN-SURFACES.md +++ b/docs/DESIGN-SURFACES.md @@ -1,8 +1,8 @@ # DESIGN — Surface & Extension Architecture -**Status:** Accepted +**Status:** Accepted (Phases 1–2 implemented in v0.25.1) **Scope:** Primitives, Components, Surfaces, Extension hooks, Themes -**Depends on:** v0.22.5 (Go template engine), v0.22.7 (ChatPane) +**Depends on:** v0.22.5 (Go template engine), v0.22.7 (ChatPane), v0.25.1 (audit) **Informs:** v0.22.8+, EXTENSIONS.md rewrite, ARCHITECTURE.md update, ICD-API, ICD-SURFACE --- @@ -159,7 +159,9 @@ Primitives.menu({ anchor: el, items: [...], onSelect: fn }) Primitives.dialog({ title: 'Confirm', body: el, onConfirm: fn }) ``` -Current locations: `ui-primitives.js`, `ui-primitives-additions.js`, +Current locations: `ui-primitives.js` (factory functions, `esc()`, +`createComponentRegistry()`, `componentMixin()`, `showConfirm()`, +`showPrompt()`, `Theme`, `mountAvatarUpload()`) and Go template components (`model-select.html`, `team-select.html`, `file-upload.html`). These converge into one coherent set. @@ -202,23 +204,42 @@ to interact with. ### Instance Pattern -Components use the factory pattern established by ChatPane: +Components use `createComponentRegistry()` and `componentMixin()` from +`ui-primitives.js` for shared lifecycle (instance tracking, event +listener cleanup, destroy): ```js -const pane = ChatPane.create({ - messagesEl: document.getElementById('editorChatMessages'), - inputEl: document.getElementById('editorChatInput'), - sendBtnEl: document.getElementById('editorSendBtn'), - channelId: workspaceChatId, - standalone: true, -}); +const ChatPane = { + ...createComponentRegistry('ChatPane'), -// Lifecycle -pane.renderMessages(msgs); -pane.streamResponse(resp, msgs); -pane.destroy(); + create(opts) { + const instance = componentMixin({ + id: opts.id || 'pane-' + Date.now(), + messagesEl: opts.messagesEl, + inputEl: opts.inputEl, + channelId: opts.channelId || null, + // ... domain-specific state + + // Component-specific teardown (called by mixin's destroy()) + _cleanup() { + if (this._cmView) { this._cmView.destroy(); this._cmView = null; } + }, + }, ChatPane); + + ChatPane._register(instance.id, instance); + return instance; + }, + + // Custom queries beyond .get(id) + forChannel(channelId) { /* ... */ }, +}; ``` +The mixin provides `_on(el, event, handler)` for tracked event binding +and `destroy()` which calls `_cleanup()` then removes all listeners and +unregisters from the registry. Components that need extra teardown define +`_cleanup()`. + Components can be instantiated multiple times on the same page (editor has a ChatPane, notes has a ChatPane — independent instances). @@ -567,7 +588,7 @@ accommodates it without redesign. b. Register hooks (pre-completion, post-render, etc.) c. Register surface injections for current surface d. Initialize tool bridges -5. Surface-specific JS runs (app.js for chat, editor-mode.js, etc.) +5. Surface-specific JS runs (app.js for chat, editor-surface.js, etc.) ``` `Extensions.boot()` replaces the current chat-specific @@ -672,8 +693,8 @@ post-render hooks use to discover display content from any extension. | Current State | Target State | |---------------|-------------| -| `ui-primitives.js` + `ui-primitives-additions.js` | Primitive catalog with stable factory API | -| `ChatPane.create()` (v0.22.7) | Component catalog with shared instance pattern | +| `ui-primitives.js` (merged, with `esc()`, `createComponentRegistry()`, `componentMixin()`) | ✅ Done (v0.25.1) | +| `ChatPane.create()` + 5 other components using shared mixin | ✅ Done (v0.25.1) | | 5 Go template routes | Surface registry (hardcoded core, manifest-driven extensions) | | `ctx.ui.replace()` / `ctx.ui.inject()` | Hook 6: Surface Injection with declared mount points | | `ctx.surfaces.register()` | Manifest `surfaces` field → page engine route registration | @@ -688,17 +709,22 @@ post-render hooks use to discover display content from any extension. This does not prescribe version numbers. It describes dependency order. -**Phase 1: Primitive consolidation** -- Audit `ui-primitives.js`, `ui-primitives-additions.js`, and Go - template components -- Define the primitive catalog and factory API -- Define the CSS custom property contract (theme API) -- Migrate existing callers to the consolidated API +**Phase 1: Primitive consolidation** ✅ (v0.25.1) +- `ui-primitives-additions.js` deleted, survivors merged into + `ui-primitives.js` +- `esc()` centralized (13 private copies eliminated) +- Badge system unified (24 scattered classes → grouped in primitives.css) +- CSS variable names normalized, duplicate selectors resolved +- `showConfirm()` is the sole confirm pattern (bare `confirm()` purged) -**Phase 2: Component formalization** -- ChatPane already exists (v0.22.7). Formalize the instance pattern. -- Extract NoteEditor, FileTree, ModelSelector as components -- Each component gets a Go template partial + JS hydration +**Phase 2: Component formalization** ✅ (v0.25.1) +- `createComponentRegistry()` + `componentMixin()` extracted +- 6 components (ChatPane, ModelSelector, UserMenu, CodeEditor, FileTree, + NoteEditor) use the shared mixin. ~100 lines of boilerplate eliminated. +- Each component has a Go template partial + JS hydration +- `surface-nav.js` deleted; navigation is native in `ui-core.js` +- Vendor scripts (`marked.min.js`, `purify.min.js`) and `ui-format.js` + moved to `base.html` (loaded once, available to all surfaces) **Phase 3: Extension hooks** - `Extensions.boot()` on every surface (v0.22.8) diff --git a/docs/SURFACES.md b/docs/SURFACES.md index 0f8e5a9..c88a426 100644 --- a/docs/SURFACES.md +++ b/docs/SURFACES.md @@ -1,6 +1,6 @@ # Surface Development Guide -**Version:** 0.25.0 +**Version:** 0.25.1 **Audience:** Anyone with admin access to a Chat Switchboard instance --- diff --git a/server/pages/templates/base.html b/server/pages/templates/base.html index 99718ca..eec530a 100644 --- a/server/pages/templates/base.html +++ b/server/pages/templates/base.html @@ -90,7 +90,9 @@ - + + + {{/* v0.25.0: Component scripts — available on all surfaces */}} @@ -156,6 +158,7 @@ +