Changeset 0.28.3.2 (#189)
This commit is contained in:
109
CHANGELOG.md
109
CHANGELOG.md
@@ -1,5 +1,114 @@
|
||||
# Changelog
|
||||
|
||||
## [0.28.3.5] — 2026-03-14
|
||||
|
||||
### Summary
|
||||
|
||||
Frontend decomposition Phase 4: ES module conversion. IIFE wrappers
|
||||
removed from all 47 JS files, `<script type="module">` applied across
|
||||
all templates. `sb.js` and vendor libs stay as classic scripts to
|
||||
guarantee availability before modules execute.
|
||||
|
||||
### Changed
|
||||
|
||||
#### Phase 4 — IIFE Removal
|
||||
- Removed `(function() { 'use strict'; ... })();` wrappers from 45
|
||||
standard-pattern JS files (3 lines per file: open, strict, close).
|
||||
- Removed `'use strict';` from 2 arrow-IIFE files (`knowledge-ui.js`,
|
||||
`tools-toggle.js`) — arrow IIFE retained (const binding pattern,
|
||||
harmless in module scope).
|
||||
- Removed leftover `'use strict';` from `persona-kb.js` (not caught
|
||||
by the main script due to blank line before directive).
|
||||
- Inner IIFEs preserved: `projects-ui.js` (visibility timer),
|
||||
`ui-primitives.js` (Providers/Roles factory constructors).
|
||||
- All 48 JS files pass `node --check` syntax validation.
|
||||
|
||||
#### Phase 4 — Template Module Conversion
|
||||
- All `<script src=".../js/*.js">` tags converted to
|
||||
`<script type="module" src="...">` across 6 template files:
|
||||
`base.html`, `surfaces/chat.html`, `surfaces/admin.html`,
|
||||
`surfaces/editor.html`, `surfaces/notes.html`,
|
||||
`surfaces/settings.html`.
|
||||
- Classic scripts retained for: `sb.js` (must be globally available
|
||||
before any module), vendor libs (`marked.min.js`, `purify.min.js`,
|
||||
`codemirror.bundle.js`), early theme script, `__BASE__`/`__VERSION__`
|
||||
hydration.
|
||||
- 3 inline scripts in `base.html` converted to `type="module"`:
|
||||
`API.loadTokens()`, Theme/appearance init + `handleLogout` fallback,
|
||||
UserMenu hydration.
|
||||
- `handleLogout` fallback: added `sb.register('handleLogout', handleLogout)`
|
||||
since function is now module-scoped (no longer on `window`).
|
||||
- UserMenu hydration: `handleLogout()` → `sb.call('handleLogout')`,
|
||||
`openDebugModal()` → `sb.call('openDebugModal')`.
|
||||
- Extension surface `main.js` → `type="module"`.
|
||||
- DOMContentLoaded inline scripts in surface templates stay classic
|
||||
(safe — modules execute before DOMContentLoaded fires).
|
||||
|
||||
### Fixed
|
||||
- CI: frontend test harness (`helpers.js`) now loads `sb.js` into VM
|
||||
context before other source files. Fixes 55 extension test failures
|
||||
(`ReferenceError: sb is not defined` at `events.js:334`).
|
||||
- `extensions.test.js`, `extensions-builtin.test.js`: `loadExtensions()`
|
||||
prepends `sb.js` load. Result: 219/219 tests pass.
|
||||
|
||||
### Not Changed
|
||||
- `sb.register()`/`sb.ns()` dual-write to `window[name]` stays —
|
||||
cross-file JS references (`API.listProjects()`, `UI.toast()`) still
|
||||
go through `window.*`. Removal requires `import`/`export` statements
|
||||
(Phase 5, future).
|
||||
- `login.html`, `workflow.html`, `workflow-landing.html` unchanged
|
||||
(standalone pages, no `sb.js`).
|
||||
|
||||
## [0.28.3.3] — 2026-03-14
|
||||
|
||||
### Summary
|
||||
|
||||
CI fix: frontend test harness missing `sb.js` in VM context. All 55
|
||||
extension test failures were the same root cause — `events.js` calls
|
||||
`sb.ns('Events', Events)` but the test VM never loaded `sb.js`.
|
||||
|
||||
### Fixed
|
||||
- `helpers.js`: `loadAppModules()` now loads `sb.js` before `app-state.js`
|
||||
(defensive — not currently broken but would fail if any passing test
|
||||
switched to using `loadAppModules` with source files that call `sb.*`).
|
||||
- `extensions.test.js`: `loadExtensions()` loads `sb.js` before `events.js`.
|
||||
- `extensions-builtin.test.js`: same fix.
|
||||
|
||||
**Result:** 219/219 tests pass (was 164/219).
|
||||
|
||||
## [0.28.3.2] — 2026-03-14
|
||||
|
||||
### Summary
|
||||
|
||||
Frontend decomposition Phase 3b: Go template `onclick` → `sb.call()`
|
||||
migration. All server-rendered onclick handlers in templates that load
|
||||
`sb.js` (via `base.html`) now route through the action registry. This
|
||||
clears the template gate for Phase 4 (ES module conversion).
|
||||
|
||||
### Changed
|
||||
|
||||
#### Phase 3b — Go Template onclick → sb.call()
|
||||
- Converted 72 `onclick="fn(args)"` handlers across 10 Go template
|
||||
files to use `sb.call('fn', args)` or `sb.callEvent(event, 'fn', args)`.
|
||||
- Templates converted: `base.html` (10), `surfaces/chat.html` (28),
|
||||
`surfaces/admin.html` (14), `surfaces/settings.html` (3),
|
||||
`admin/providers.html` (5), `admin/users.html` (3),
|
||||
`admin/roles.html` (1), `admin/routing.html` (3),
|
||||
`admin/teams.html` (4), `admin/settings.html` (1).
|
||||
- 4 onclick handlers intentionally left unconverted (inline DOM
|
||||
manipulation or Go template variable in element ID):
|
||||
- `this.parentElement.style.display='none'` (crash banner dismiss)
|
||||
- `event.stopPropagation()` (bare container click guard)
|
||||
- `document.getElementById('settingsTeamAddMember').style.display='none'`
|
||||
- `document.getElementById('{{.FieldName}}Input').click()`
|
||||
- 3 standalone pages excluded (no `sb.js`): `login.html`,
|
||||
`workflow.html`, `workflow-landing.html`.
|
||||
- Defensive `typeof` guards in `settings.html` onclick handlers
|
||||
(e.g. `if(typeof UI!=='undefined')UI.saveAppearance?.()`) replaced
|
||||
with clean `sb.call()` — registry silently logs unresolved actions.
|
||||
- `sb.js` comments updated: template gate cleared, dual-write removal
|
||||
deferred to Phase 4 (cross-file JS references still use `window.*`).
|
||||
|
||||
## [0.28.3.1] — 2026-03-14
|
||||
|
||||
### Summary
|
||||
|
||||
@@ -25,7 +25,7 @@ v0.9.x–v0.27.5 Foundation → Extensions → Surfaces → Auth ✅
|
||||
v0.28.0 Platform Polish
|
||||
├─ v0.28.1 Surfaces ICD audit ✅
|
||||
├─ v0.28.2 ICD audit — all domains ✅
|
||||
├─ v0.28.3 ICD close-out + FE decomp prep
|
||||
├─ v0.28.3 ICD close-out + FE decomp ✅
|
||||
├─ v0.28.4 Security tier (red team)
|
||||
├─ v0.28.5 Infrastructure
|
||||
│ (virtual scroll, KB auto-inject,
|
||||
@@ -179,8 +179,14 @@ decomposition groundwork.
|
||||
- [x] Phase 3: Action registry (`sb.js`) — 248 `window.*` exports replaced with
|
||||
`sb.register()`/`sb.ns()`. `sb.resolve()` centralized dispatch.
|
||||
`sb.call()` template bridge ready for Go template migration.
|
||||
- [ ] Phase 3b: Go template onclick → `sb.call()` migration (~50 handlers)
|
||||
- [ ] Phase 4: ES module conversion (remove IIFE wrappers, add import/export)
|
||||
- [x] Phase 3b: Go template onclick → `sb.call()` migration (72 handlers
|
||||
across 10 templates, 4 unconvertible inline DOM ops, 3 standalone
|
||||
pages excluded)
|
||||
- [x] Phase 4: ES module conversion — IIFE wrappers removed from all 47
|
||||
files, `<script type="module">` across all templates. `sb.js` +
|
||||
vendor stay classic. CI test harness fixed (sb.js in VM context).
|
||||
- [ ] Phase 5 (future): `import`/`export` statements, remove `window[name]`
|
||||
dual-write from `sb.register()`/`sb.ns()`
|
||||
|
||||
### v0.28.4 — Security Tier (ICD Runner Red Team)
|
||||
New `security` tier in ICD test runner. Multi-user fixtures already exist.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p class="section-hint">AI provider configurations. Each provider connects to an API endpoint.</p>
|
||||
|
||||
<div class="admin-toolbar">
|
||||
<button class="btn-small btn-primary" onclick="Pages.showProviderForm()">+ Add Provider</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.showProviderForm')">+ Add Provider</button>
|
||||
</div>
|
||||
|
||||
<div id="providerFormWrap" style="display:none;">
|
||||
@@ -34,8 +34,8 @@
|
||||
<td>{{.ModelCount}}</td>
|
||||
<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-secondary);">{{.Endpoint}}</td>
|
||||
<td>
|
||||
<button class="btn-small" onclick="Pages.syncProvider('{{.ID}}')">Sync</button>
|
||||
<button class="btn-small" onclick="Pages.editProvider('{{.ID}}')">Edit</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.syncProvider','{{.ID}}')">Sync</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.editProvider','{{.ID}}')">Edit</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
@@ -90,8 +90,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;margin-top:8px;">
|
||||
<button class="btn-small btn-primary" onclick="Pages.saveProvider()">Save</button>
|
||||
<button class="btn-small" onclick="Pages.hideProviderForm()">Cancel</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveProvider')">Save</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.hideProviderForm')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn-small btn-primary" onclick="Pages.saveRole('{{$roleName}}')">Save</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveRole','{{$roleName}}')">Save</button>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<p class="section-hint">Define rules for model selection, cost limits, and team-specific routing.</p>
|
||||
|
||||
<div style="margin-bottom:12px">
|
||||
<button class="btn-small btn-primary" onclick="Pages.showRoutingForm()">+ New Policy</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.showRoutingForm')">+ New Policy</button>
|
||||
</div>
|
||||
|
||||
<div id="routingPolicyForm" style="display:none" class="admin-inline-form">
|
||||
@@ -66,8 +66,8 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-row" style="gap:8px;margin-top:8px">
|
||||
<button class="btn-small btn-primary" onclick="Pages.saveRoutingPolicy()">Save</button>
|
||||
<button class="btn-small" onclick="Pages.hideRoutingForm()">Cancel</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveRoutingPolicy')">Save</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.hideRoutingForm')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
</div>
|
||||
|
||||
<div style="margin-top:16px;">
|
||||
<button class="btn-small btn-primary" onclick="Pages.saveSettings()">Save Settings</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveSettings')">Save Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p class="section-hint">Organize users into teams for scoped access to providers, personas, and policies.</p>
|
||||
|
||||
<div class="admin-toolbar">
|
||||
<button class="btn-small btn-primary" onclick="Pages.showTeamForm()">+ Create Team</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.showTeamForm')">+ Create Team</button>
|
||||
</div>
|
||||
|
||||
<div id="teamFormWrap" style="display:none;">
|
||||
@@ -24,8 +24,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;margin-top:8px;">
|
||||
<button class="btn-small btn-primary" onclick="Pages.saveTeam()">Save</button>
|
||||
<button class="btn-small" onclick="Pages.hideTeamForm()">Cancel</button>
|
||||
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveTeam')">Save</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.hideTeamForm')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@
|
||||
<td>{{.MemberCount}}</td>
|
||||
<td><span class="admin-badge admin-badge-{{if .IsActive}}active{{else}}inactive{{end}}">{{if .IsActive}}active{{else}}inactive{{end}}</span></td>
|
||||
<td>
|
||||
<button class="btn-small" onclick="Pages.editTeam('{{.ID}}','{{.Name}}','{{.Description}}')">Edit</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.editTeam','{{.ID}}','{{.Name}}','{{.Description}}')">Edit</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
<td><span class="admin-badge admin-badge-{{.Role}}">{{.Role}}</span></td>
|
||||
<td><span class="admin-badge admin-badge-{{if .IsActive}}active{{else}}inactive{{end}}">{{if .IsActive}}active{{else}}inactive{{end}}</span></td>
|
||||
<td>
|
||||
<button class="btn-small" onclick="Pages.editUserRole('{{.ID}}','{{.Username}}','{{.Role}}')">Role</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.editUserRole','{{.ID}}','{{.Username}}','{{.Role}}')">Role</button>
|
||||
{{if .IsActive}}
|
||||
<button class="btn-small" onclick="Pages.toggleUser('{{.ID}}',false)">Disable</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.toggleUser','{{.ID}}',false)">Disable</button>
|
||||
{{else}}
|
||||
<button class="btn-small" onclick="Pages.toggleUser('{{.ID}}',true)">Enable</button>
|
||||
<button class="btn-small" onclick="sb.call('Pages.toggleUser','{{.ID}}',true)">Enable</button>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -92,30 +92,30 @@
|
||||
</script>
|
||||
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/sb.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app-state.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/api.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app-state.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/api.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}">
|
||||
// Hydrate auth tokens for all surfaces (chat surface also calls this in init)
|
||||
API.loadTokens();
|
||||
</script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/events.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-primitives.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/events.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-primitives.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/vendor/marked.min.js"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/vendor/purify.min.js"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-format.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-core.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/pages.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-format.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-core.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/pages.js?v={{.Version}}"></script>
|
||||
{{/* v0.25.0: Component scripts — available on all surfaces */}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/user-menu.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/model-selector.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/file-tree.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/code-editor.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/note-editor.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/drag-resize.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/pane-container.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/user-menu.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/model-selector.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/file-tree.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/code-editor.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/note-editor.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/drag-resize.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/pane-container.js?v={{.Version}}"></script>
|
||||
|
||||
{{/* ── Universal init: theme + appearance for ALL surfaces ── */}}
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
<script type="module" nonce="{{.CSPNonce}}">
|
||||
// Theme must init on every surface, not just chat.
|
||||
if (typeof Theme !== 'undefined') Theme.init();
|
||||
// Appearance (zoom + font size) must restore on every surface.
|
||||
@@ -131,6 +131,8 @@
|
||||
if (typeof API !== 'undefined' && API.logout) API.logout();
|
||||
location.reload();
|
||||
}
|
||||
// Register fallback — app.js re-registers with a richer version.
|
||||
sb.register('handleLogout', handleLogout);
|
||||
</script>
|
||||
|
||||
{{if eq .Surface "chat"}}{{template "scripts-chat" .}}{{end}}
|
||||
@@ -140,7 +142,7 @@
|
||||
{{if eq .Surface "settings"}}{{template "scripts-settings" .}}{{end}}
|
||||
{{/* v0.27.0: Extension surface JS — loaded from /surfaces/{id}/js/main.js */}}
|
||||
{{if and .Manifest (eq .Manifest.Source "extension")}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/surfaces/{{.Surface}}/js/main.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/surfaces/{{.Surface}}/js/main.js?v={{.Version}}"></script>
|
||||
{{end}}
|
||||
|
||||
{{/* ── v0.28.0: Universal UserMenu hydration ──────────────────
|
||||
@@ -151,29 +153,28 @@
|
||||
richer behavior (team admin refresh). Chat migration to UserMenu
|
||||
component is tracked as tech debt (Pre-1.0 sweep).
|
||||
*/}}
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
(function () {
|
||||
if (typeof UserMenu === 'undefined') return;
|
||||
if (UserMenu.primary) return;
|
||||
if ((window.__SURFACE__ || '') === 'chat') return;
|
||||
|
||||
<script type="module" nonce="{{.CSPNonce}}">
|
||||
if (typeof UserMenu === 'undefined') { /* noop */ }
|
||||
else if (UserMenu.primary) { /* noop */ }
|
||||
else if ((window.__SURFACE__ || '') === 'chat') { /* noop */ }
|
||||
else {
|
||||
var btn = document.getElementById('userMenuBtn');
|
||||
if (!btn) return;
|
||||
if (btn) {
|
||||
var menu = UserMenu.create({ id: '' });
|
||||
UserMenu.primary = menu;
|
||||
menu.setUser(window.__USER__ || {});
|
||||
|
||||
var menu = UserMenu.create({ id: '' });
|
||||
UserMenu.primary = menu;
|
||||
menu.setUser(window.__USER__ || {});
|
||||
var user = window.__USER__ || {};
|
||||
menu.showAdmin(user.role === 'admin');
|
||||
|
||||
var user = window.__USER__ || {};
|
||||
menu.showAdmin(user.role === 'admin');
|
||||
|
||||
menu.bind({
|
||||
onSettings: function () { window.location.href = (window.__BASE__ || '') + '/settings'; },
|
||||
onAdmin: function () { window.location.href = (window.__BASE__ || '') + '/admin'; },
|
||||
onDebug: function () { if (typeof openDebugModal === 'function') openDebugModal(); },
|
||||
onSignout: function () { handleLogout(); },
|
||||
});
|
||||
})();
|
||||
menu.bind({
|
||||
onSettings: function () { window.location.href = (window.__BASE__ || '') + '/settings'; },
|
||||
onAdmin: function () { window.location.href = (window.__BASE__ || '') + '/admin'; },
|
||||
onDebug: function () { sb.call('openDebugModal'); },
|
||||
onSignout: function () { sb.call('handleLogout'); },
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{{/* ── Debug Log Modal (all surfaces) ───── */}}
|
||||
@@ -181,13 +182,13 @@
|
||||
<div class="modal modal-wide">
|
||||
<div class="modal-header">
|
||||
<h2>Debug Log</h2>
|
||||
<button class="modal-close" onclick="closeModal('debugModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','debugModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-tabs">
|
||||
<button class="debug-tab active" data-tab="console" onclick="switchDebugTab('console')">Console <span id="debugConsoleCount" class="badge">0</span></button>
|
||||
<button class="debug-tab" data-tab="network" onclick="switchDebugTab('network')">Network <span id="debugNetworkCount" class="badge">0</span></button>
|
||||
<button class="debug-tab" data-tab="state" onclick="switchDebugTab('state')">State</button>
|
||||
<button class="debug-tab" data-tab="repl" onclick="switchDebugTab('repl')">REPL</button>
|
||||
<button class="debug-tab active" data-tab="console" onclick="sb.call('switchDebugTab','console')">Console <span id="debugConsoleCount" class="badge">0</span></button>
|
||||
<button class="debug-tab" data-tab="network" onclick="sb.call('switchDebugTab','network')">Network <span id="debugNetworkCount" class="badge">0</span></button>
|
||||
<button class="debug-tab" data-tab="state" onclick="sb.call('switchDebugTab','state')">State</button>
|
||||
<button class="debug-tab" data-tab="repl" onclick="sb.call('switchDebugTab','repl')">REPL</button>
|
||||
</div>
|
||||
<div class="modal-body" style="padding:0;overflow:hidden;display:flex;flex-direction:column;min-height:0;">
|
||||
<div id="debugConsoleTab" class="debug-tab-content" style="display:flex;flex-direction:column;flex:1;min-height:0;">
|
||||
@@ -212,19 +213,19 @@
|
||||
</div>
|
||||
<div class="modal-footer" style="display:flex;justify-content:space-between;align-items:center;">
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn-danger btn-small" onclick="runDebugDiagnostics()">Diagnostics</button>
|
||||
<button class="btn-danger btn-small" onclick="purgeCache()">Purge Cache</button>
|
||||
<button class="btn-danger btn-small" onclick="sb.call('runDebugDiagnostics')">Diagnostics</button>
|
||||
<button class="btn-danger btn-small" onclick="sb.call('purgeCache')">Purge Cache</button>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn-secondary btn-small" onclick="clearDebugLog()">Clear</button>
|
||||
<button class="btn-secondary btn-small" onclick="copyDebugLog()">Copy</button>
|
||||
<button class="btn-secondary btn-small" onclick="exportDebugLog()">Export</button>
|
||||
<button class="btn-secondary btn-small" onclick="sb.call('clearDebugLog')">Clear</button>
|
||||
<button class="btn-secondary btn-small" onclick="sb.call('copyDebugLog')">Copy</button>
|
||||
<button class="btn-secondary btn-small" onclick="sb.call('exportDebugLog')">Export</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/debug.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/repl.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/debug.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/repl.js?v={{.Version}}"></script>
|
||||
<div id="toastContainer" class="toast-container"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<div class="modal" style="max-width:440px;">
|
||||
<div class="modal-header">
|
||||
<h2>Create User</h2>
|
||||
<button class="modal-close" onclick="closeModal('createUserModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','createUserModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label>Username</label><input type="text" id="adminNewUsername" placeholder="username" autocomplete="off"></div>
|
||||
@@ -87,7 +87,7 @@
|
||||
<div class="form-group"><label>Role</label><select id="adminNewRole"><option value="user">User</option><option value="admin">Admin</option></select></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('createUserModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','createUserModal')">Cancel</button>
|
||||
<button class="btn-md btn-primary" id="adminCreateUserBtn">Create User</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@
|
||||
<div class="modal" style="max-width:440px;">
|
||||
<div class="modal-header">
|
||||
<h2>Reset Password</h2>
|
||||
<button class="modal-close" onclick="closeModal('resetPwModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','resetPwModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p id="resetPwUser" style="font-weight:600;margin-bottom:8px;"></p>
|
||||
@@ -108,7 +108,7 @@
|
||||
<div class="form-group"><label>New Password</label><input type="password" id="resetPwInput" placeholder="min 8 chars" autocomplete="new-password"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('resetPwModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','resetPwModal')">Cancel</button>
|
||||
<button class="btn-md btn-danger" id="resetPwConfirmBtn">Reset Password & Destroy Vault</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,14 +119,14 @@
|
||||
<div class="modal" style="max-width:440px;">
|
||||
<div class="modal-header">
|
||||
<h2 id="approveUserTitle">Approve User</h2>
|
||||
<button class="modal-close" onclick="closeModal('approveUserModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','approveUserModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="approveUserId">
|
||||
<div id="approveTeamsList"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('approveUserModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','approveUserModal')">Cancel</button>
|
||||
<button class="btn-md btn-primary" id="approveUserSubmitBtn">Activate User</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -137,14 +137,14 @@
|
||||
<div class="modal" style="max-width:440px;">
|
||||
<div class="modal-header">
|
||||
<h2>Create Team</h2>
|
||||
<button class="modal-close" onclick="closeModal('createTeamModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','createTeamModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label>Name</label><input type="text" id="adminTeamName" placeholder="Team name"></div>
|
||||
<div class="form-group"><label>Description</label><input type="text" id="adminTeamDesc" placeholder="Optional description"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('createTeamModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','createTeamModal')">Cancel</button>
|
||||
<button class="btn-md btn-primary" id="adminCreateTeamBtn">Create Team</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,7 +155,7 @@
|
||||
<div class="modal" style="max-width:440px;">
|
||||
<div class="modal-header">
|
||||
<h2>Create Group</h2>
|
||||
<button class="modal-close" onclick="closeModal('createGroupModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','createGroupModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label>Name</label><input type="text" id="adminGroupName" placeholder="Group name"></div>
|
||||
@@ -166,7 +166,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('createGroupModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','createGroupModal')">Cancel</button>
|
||||
<button class="btn-md btn-primary" id="adminCreateGroupBtn">Create Group</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -177,11 +177,11 @@
|
||||
<div class="modal" style="max-width:520px;">
|
||||
<div class="modal-header">
|
||||
<h2 id="providerFormTitle">Add Provider</h2>
|
||||
<button class="modal-close" onclick="closeModal('providerFormModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','providerFormModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body" id="adminAddProviderForm"></div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('providerFormModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','providerFormModal')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -191,11 +191,11 @@
|
||||
<div class="modal" style="max-width:520px;">
|
||||
<div class="modal-header">
|
||||
<h2 id="personaFormTitle">Create Persona</h2>
|
||||
<button class="modal-close" onclick="closeModal('personaFormModal')">✕</button>
|
||||
<button class="modal-close" onclick="sb.call('closeModal','personaFormModal')">✕</button>
|
||||
</div>
|
||||
<div class="modal-body" id="adminAddPersonaForm"></div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-md btn-ghost" onclick="closeModal('personaFormModal')">Cancel</button>
|
||||
<button class="btn-md btn-ghost" onclick="sb.call('closeModal','personaFormModal')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -206,20 +206,20 @@
|
||||
|
||||
{{/* Scripts */}}
|
||||
{{define "scripts-admin"}}
|
||||
<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/admin-handlers.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/admin-handlers.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/settings-handlers.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/knowledge-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/persona-kb.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/memory-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/notifications.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/files.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/admin-scaffold.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/task-admin.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/admin-surfaces.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/persona-kb.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/notifications.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/admin-scaffold.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/task-admin.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/admin-surfaces.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// ── Admin navigation: don't pollute browser history ──
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
{{/* ── Scripts ─────────────────────────────── */}}
|
||||
{{define "scripts-editor"}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/vendor/codemirror/codemirror.bundle.js?v={{.Version}}" onerror="console.warn('[CM6] Bundle not available')"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/chat-pane.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/editor-surface.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/chat-pane.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/editor-surface.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app.js?v={{.Version}}"></script>
|
||||
{{end}}
|
||||
|
||||
@@ -24,21 +24,21 @@
|
||||
{{end}}
|
||||
|
||||
{{define "scripts-notes"}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/chat.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/files.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/channel-models.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/tokens.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/extensions.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/knowledge-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/persona-kb.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/memory-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/notifications.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/panels.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/chat.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/channel-models.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/extensions.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/knowledge-ui.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/persona-kb.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/notifications.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/panels.js?v={{.Version}}"></script>
|
||||
{{/* debug.js now loaded in base.html for all surfaces */}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/projects-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/app.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
// Notes surface boot: open notes panel in standalone mode
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
@@ -112,20 +112,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn-md btn-primary" onclick="if(typeof UI!=='undefined')UI.saveAppearance?.()">Save</button>
|
||||
<button class="btn-md btn-primary" onclick="sb.call('UI.saveAppearance')">Save</button>
|
||||
{{else if eq .Section "profile"}}
|
||||
<div class="settings-section">
|
||||
<h3>Profile</h3>
|
||||
<div class="form-group"><label>Display Name</label><input type="text" id="profileDisplayName" placeholder="Your display name"></div>
|
||||
<div class="form-group"><label>Email</label><input type="email" id="profileEmail" disabled></div>
|
||||
<button class="btn-md btn-primary" onclick="if(typeof Pages!=='undefined')Pages.saveProfile?.()">Save Profile</button>
|
||||
<button class="btn-md btn-primary" onclick="sb.call('Pages.saveProfile')">Save Profile</button>
|
||||
</div>
|
||||
<div class="settings-section" style="margin-top:20px;">
|
||||
<h3>Change Password</h3>
|
||||
<div class="form-group"><label>Current Password</label><input type="password" id="settingsCurrentPw" autocomplete="current-password"></div>
|
||||
<div class="form-group"><label>New Password</label><input type="password" id="settingsNewPw" autocomplete="new-password"></div>
|
||||
<div class="form-group"><label>Confirm New Password</label><input type="password" id="settingsConfirmPw" autocomplete="new-password"></div>
|
||||
<button class="btn-md btn-primary" onclick="if(typeof Pages!=='undefined')Pages.changePassword?.()">Update Password</button>
|
||||
<button class="btn-md btn-primary" onclick="sb.call('Pages.changePassword')">Update Password</button>
|
||||
</div>
|
||||
{{else if eq .Section "providers"}}
|
||||
<div id="userProvidersDisabled" style="display:none;">
|
||||
@@ -170,15 +170,15 @@
|
||||
|
||||
{{/* Scripts */}}
|
||||
{{define "scripts-settings"}}
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-settings.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/ui-settings.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/settings-handlers.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/task-settings.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/knowledge-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/persona-kb.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/memory-ui.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/notifications.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/notification-prefs.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/channel-models.js?v={{.Version}}"></script>
|
||||
<script type="module" nonce="{{.CSPNonce}}" src="{{.BasePath}}/js/task-settings.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/persona-kb.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/notifications.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/channel-models.js?v={{.Version}}"></script>
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const section = document.getElementById('settingsSection')?.dataset.section;
|
||||
|
||||
@@ -8,6 +8,7 @@ const vm = require('vm');
|
||||
*/
|
||||
function loadExtensions(overrides = {}) {
|
||||
const sandbox = createBrowserContext(overrides);
|
||||
loadSource(sandbox, 'sb.js');
|
||||
loadSource(sandbox, 'events.js');
|
||||
loadSource(sandbox, 'extensions.js');
|
||||
const ctx = vm.createContext(sandbox);
|
||||
|
||||
@@ -11,6 +11,7 @@ const vm = require('vm');
|
||||
*/
|
||||
function loadExtensions(overrides = {}) {
|
||||
const sandbox = createBrowserContext(overrides);
|
||||
loadSource(sandbox, 'sb.js');
|
||||
loadSource(sandbox, 'events.js');
|
||||
loadSource(sandbox, 'extensions.js');
|
||||
// Extract const globals from the vm context
|
||||
|
||||
@@ -116,6 +116,7 @@ function loadSource(sandbox, filename) {
|
||||
*/
|
||||
function loadAppModules(overrides = {}) {
|
||||
const sandbox = createBrowserContext(overrides);
|
||||
loadSource(sandbox, 'sb.js');
|
||||
loadSource(sandbox, 'app-state.js');
|
||||
loadSource(sandbox, 'api.js');
|
||||
loadSource(sandbox, 'app.js');
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Admin actions: user management, roles, model visibility,
|
||||
// personas, team management, global providers.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Admin Actions ────────────────────────────
|
||||
|
||||
@@ -918,4 +916,3 @@ sb.register('toggleUserRole', toggleUserRole);
|
||||
sb.register('updateTeamMember', updateTeamMember);
|
||||
sb.register('_closeExtEditForm', _closeExtEditForm);
|
||||
sb.register('saveAdminExtension', saveAdminExtension);
|
||||
})();
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// and calls the appropriate ADMIN_LOADERS[section]() from ui-admin.js.
|
||||
// Loaded only on the admin surface (/admin/:section).
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Each admin section loader (ui-admin.js) expects specific container
|
||||
// elements. SCAFFOLDING maps section name -> HTML to inject before
|
||||
@@ -386,4 +384,3 @@
|
||||
ADMIN_LOADERS[section]();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
//
|
||||
// Exports: window._loadAdminSurfaces
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
async function _loadAdminSurfaces() {
|
||||
const container = document.getElementById('adminSurfacesContent');
|
||||
@@ -199,4 +197,3 @@ async function _loadSurfaceList() {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.register('_loadAdminSurfaces', _loadAdminSurfaces);
|
||||
})();
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// Exports: window.API
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const BASE = window.__BASE__ || '';
|
||||
const _storageKey = BASE ? `sb_auth_${BASE.replace(/\//g, '')}` : 'sb_auth';
|
||||
@@ -994,4 +992,3 @@ const API = {
|
||||
};
|
||||
|
||||
sb.ns('API', API);
|
||||
})();
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
// Exports: window.App, window.fetchModels
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const App = {
|
||||
chats: [],
|
||||
@@ -139,4 +137,3 @@ async function fetchModels() {
|
||||
|
||||
sb.ns('App', App);
|
||||
sb.register('fetchModels', fetchModels);
|
||||
})();
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
// Exports: handleLogin, handleRegister, handleLogout, switchAuthTab,
|
||||
// startApp, initBanners
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
async function init() {
|
||||
console.log('🔀 Chat Switchboard initializing...');
|
||||
@@ -588,4 +586,3 @@ sb.register('handleLogout', handleLogout);
|
||||
sb.register('switchAuthTab', switchAuthTab);
|
||||
sb.register('startApp', startApp);
|
||||
sb.register('initBanners', initBanners);
|
||||
})();
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
//
|
||||
// Exports: window.ChannelModels
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const ChannelModels = {
|
||||
|
||||
@@ -437,4 +435,3 @@ function _shortName(fullName) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('ChannelModels', ChannelModels);
|
||||
})();
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
//
|
||||
// Exports: window.ChatPane
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const ChatPane = {
|
||||
...createComponentRegistry('ChatPane'),
|
||||
@@ -153,4 +151,3 @@ const ChatPane = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('ChatPane', ChatPane);
|
||||
})();
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// rejectWorkflowStage, _initChatListeners,
|
||||
// summarizeAndContinue, toggleChannelAutoCompact
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Chat Input Abstraction ──────────────────
|
||||
// Wraps CM6 editor (when available) or fallback textarea.
|
||||
@@ -1279,4 +1277,3 @@ sb.register('rejectWorkflowStage', rejectWorkflowStage);
|
||||
sb.register('_initChatListeners', _initChatListeners);
|
||||
sb.register('summarizeAndContinue', summarizeAndContinue);
|
||||
sb.register('toggleChannelAutoCompact', toggleChannelAutoCompact);
|
||||
})();
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
//
|
||||
// Exports: window.CodeEditor
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const CodeEditor = {
|
||||
...createComponentRegistry('CodeEditor'),
|
||||
@@ -332,4 +330,3 @@ function _ceDetectLanguage(path) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('CodeEditor', CodeEditor);
|
||||
})();
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//
|
||||
// Exports: window.DebugLog,window.openDebugModal,window.switchDebugTab,window.clearDebugLog,window.copyDebugLog,window.exportDebugLog,window.runDebugDiagnostics,window.purgeCache
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const DebugLog = {
|
||||
entries: [],
|
||||
@@ -676,4 +674,3 @@ sb.register('copyDebugLog', copyDebugLog);
|
||||
sb.register('exportDebugLog', exportDebugLog);
|
||||
sb.register('runDebugDiagnostics', runDebugDiagnostics);
|
||||
sb.register('purgeCache', purgeCache);
|
||||
})();
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
//
|
||||
// Exports: window.initDragResize
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Attach drag-resize behavior to a handle element.
|
||||
@@ -100,4 +98,3 @@ function _clientPos(e, isHoriz) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.register('initDragResize', initDragResize);
|
||||
})();
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
// (hidden) — this JS moves them into the right pane slots.
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if (window.__SURFACE__ !== 'editor') return;
|
||||
@@ -641,4 +639,3 @@
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
// Exports: window.Events
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const Events = {
|
||||
|
||||
@@ -332,4 +330,3 @@ const Events = {
|
||||
};
|
||||
|
||||
sb.ns('Events', Events);
|
||||
})();
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
//
|
||||
// Exports: window.Extensions
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const Extensions = {
|
||||
|
||||
@@ -489,4 +487,3 @@ const Extensions = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('Extensions', Extensions);
|
||||
})();
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
//
|
||||
// Exports: window.FileTree
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const FileTree = {
|
||||
...createComponentRegistry('FileTree'),
|
||||
@@ -269,4 +267,3 @@ function _ftFileIcon(name) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('FileTree', FileTree);
|
||||
})();
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
// Consumed by: chat.js (send flow), ui-core.js (message rendering),
|
||||
// ui-admin.js (storage tab)
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Constants ───────────────────────────────
|
||||
|
||||
@@ -857,4 +855,3 @@ sb.register('renderMessageFiles', renderMessageFiles);
|
||||
sb.register('unstageFile', unstageFile);
|
||||
sb.register('openLightbox', openLightbox);
|
||||
sb.register('downloadFile', downloadFile);
|
||||
})();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
//
|
||||
// Depends on: API (api.js), App (app.js)
|
||||
|
||||
'use strict';
|
||||
|
||||
const KnowledgeUI = (() => {
|
||||
console.debug('[KnowledgeUI] module loaded');
|
||||
@@ -553,3 +552,5 @@ const KnowledgeUI = (() => {
|
||||
openChannelPopup,
|
||||
};
|
||||
})();
|
||||
|
||||
sb.ns('KnowledgeUI', KnowledgeUI);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
//
|
||||
// Exports: window.MemoryUI
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const MemoryUI = {
|
||||
|
||||
@@ -370,4 +368,3 @@ function _debounce(fn, ms) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('MemoryUI', MemoryUI);
|
||||
})();
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
//
|
||||
// Exports: window.ModelSelector
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const ModelSelector = {
|
||||
...createComponentRegistry('ModelSelector'),
|
||||
@@ -175,4 +173,3 @@ const ModelSelector = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('ModelSelector', ModelSelector);
|
||||
})();
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
//
|
||||
// Exports: window.NoteEditor
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const NoteEditor = {
|
||||
...createComponentRegistry('NoteEditor'),
|
||||
@@ -441,4 +439,3 @@ const NoteEditor = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('NoteEditor', NoteEditor);
|
||||
})();
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
//
|
||||
// Exports: window.openNoteGraph,window.closeNoteGraph,window._render,window._graphResetZoom,window._graphToggleOrphans,window.invalidateNoteGraph
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var _graphData = null; // cached { nodes, edges, unresolved }
|
||||
var _graphState = null; // { panX, panY, zoom, animId, canvas, ctx }
|
||||
@@ -501,4 +499,3 @@ sb.register('_render', _render);
|
||||
sb.register('_graphResetZoom', _graphResetZoom);
|
||||
sb.register('_graphToggleOrphans', _graphToggleOrphans);
|
||||
sb.register('invalidateNoteGraph', invalidateNoteGraph);
|
||||
})();
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// ==========================================
|
||||
// Notes panel: editor, multi-select, folders, CRUD.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var _editingNoteId = null;
|
||||
var _notesSelectMode = false;
|
||||
@@ -973,4 +971,3 @@ sb.register('_navigateToLinkedNote', _navigateToLinkedNote);
|
||||
sb.register('toggleBacklinks', toggleBacklinks);
|
||||
sb.register('_toggleNoteSelectCb', _toggleNoteSelectCb);
|
||||
sb.register('_noteItemClick', _noteItemClick);
|
||||
})();
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
//
|
||||
// Exports: window.NotifPrefs
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const NotifPrefs = {
|
||||
_loaded: false,
|
||||
_prefs: [],
|
||||
@@ -169,4 +167,3 @@ NotifPrefs._getAdminSmtp = function() {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('NotifPrefs', NotifPrefs);
|
||||
})();
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
//
|
||||
// Exports: window.Notifications
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const Notifications = {
|
||||
|
||||
@@ -431,4 +429,3 @@ function _timeAgo(isoStr) {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('Notifications', Notifications);
|
||||
})();
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// ==========================================
|
||||
// v0.22.7: Splash init, login, register, animated grid.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
var base = window.__BASE__ || '';
|
||||
|
||||
Pages.initSplash = function() {
|
||||
@@ -186,4 +184,3 @@
|
||||
|
||||
function _val(id) { var el = document.getElementById(id); return el ? el.value.trim() : ''; }
|
||||
function _showErr(el, msg) { if (!el) return; el.textContent = msg; el.style.display = ''; }
|
||||
})();
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
// Exports: window.Pages, window._val (used by pages-splash.js)
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const Pages = {
|
||||
|
||||
@@ -349,4 +347,3 @@ async function _api(method, path, body) {
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('Pages', Pages);
|
||||
sb.register('_val', _val); // used by pages-splash.js
|
||||
})();
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
//
|
||||
// Exports: window.PaneContainer
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const PaneContainer = {
|
||||
_presets: {},
|
||||
@@ -589,4 +587,3 @@ PaneContainer.registerPreset('split', {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('PaneContainer', PaneContainer);
|
||||
})();
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
//
|
||||
// Exports: window.PanelRegistry,window.toggleSidePanelFullscreen,window._initWorkspaceResize,window._initPanelSwipe,window._initPanelResponsive,window._initPanelOverlay
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Panel Registry ──────────────────────────
|
||||
|
||||
@@ -454,4 +452,3 @@ sb.register('_initWorkspaceResize', _initWorkspaceResize);
|
||||
sb.register('_initPanelSwipe', _initPanelSwipe);
|
||||
sb.register('_initPanelResponsive', _initPanelResponsive);
|
||||
sb.register('_initPanelOverlay', _initPanelOverlay);
|
||||
})();
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
//
|
||||
// Exports: window.renderPersonaKBPicker,window.loadPersonaKBs,window.savePersonaKBs
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
// ── Persona-KB Picker ───────────────────────────
|
||||
|
||||
@@ -185,4 +181,3 @@ async function savePersonaKBs(personaId, kbPicker, apiPrefix) {
|
||||
sb.register('renderPersonaKBPicker', renderPersonaKBPicker);
|
||||
sb.register('loadPersonaKBs', loadPersonaKBs);
|
||||
sb.register('savePersonaKBs', savePersonaKBs);
|
||||
})();
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
// and drag-and-drop.
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
async function loadProjects() {
|
||||
try {
|
||||
@@ -1871,9 +1869,9 @@ async function deleteFolder(folderId) {
|
||||
const INTERVAL = 30000; // 30s
|
||||
let timer = null;
|
||||
async function beat() {
|
||||
if (!API.isAuthed) return;
|
||||
if (!window.API || !window.API.isAuthed) return;
|
||||
try {
|
||||
await API.presenceHeartbeat();
|
||||
await window.API.presenceHeartbeat();
|
||||
} catch (_) { /* non-critical */ }
|
||||
}
|
||||
function start() {
|
||||
@@ -2090,4 +2088,3 @@ sb.register('renameFolder', renameFolder);
|
||||
sb.register('_showAddParticipantSearch', _showAddParticipantSearch);
|
||||
sb.register('_addParticipant', _addParticipant);
|
||||
sb.register('_removeParticipant', _removeParticipant);
|
||||
})();
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
//
|
||||
// Exports: window.REPL
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const REPL = {
|
||||
|
||||
@@ -557,4 +555,3 @@ const REPL = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('REPL', REPL);
|
||||
})();
|
||||
|
||||
@@ -34,8 +34,9 @@ const sb = {
|
||||
/**
|
||||
* Register a standalone action function.
|
||||
* Also sets window[name] for backward compatibility with cross-file
|
||||
* direct calls. This side-effect is removed when files convert to
|
||||
* ES module imports (Phase 4).
|
||||
* direct calls. Template onclick handlers are fully migrated to sb.call()
|
||||
* (Phase 3b). This side-effect is removed in Phase 4 when files convert
|
||||
* to ES module imports.
|
||||
*/
|
||||
register(name, fn) {
|
||||
if (typeof fn !== 'function') {
|
||||
@@ -49,7 +50,8 @@ const sb = {
|
||||
/**
|
||||
* Register a namespace object (API, UI, App, etc.).
|
||||
* Methods are accessible via dot notation: sb.resolve('UI.toast').
|
||||
* Also sets window[name] for backward compatibility.
|
||||
* Also sets window[name] for backward compatibility with cross-file
|
||||
* direct calls (e.g. API.listProjects()). Removed in Phase 4.
|
||||
*/
|
||||
ns(name, obj) {
|
||||
if (obj == null || typeof obj !== 'object') {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Settings save, provider CRUD, avatar, command palette,
|
||||
// user model roles.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Settings ─────────────────────────────────
|
||||
|
||||
@@ -908,4 +906,3 @@ sb.register('toggleCmdPalette', toggleCmdPalette);
|
||||
sb.register('closeCmdPalette', closeCmdPalette);
|
||||
sb.register('_initSettingsListeners', _initSettingsListeners);
|
||||
sb.register('_initAdminSettingsToggles', _initAdminSettingsToggles);
|
||||
})();
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Admin section for managing scheduled tasks, run history, and global
|
||||
// task configuration. Registered as ADMIN_LOADERS.tasks in ui-admin.js.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var SCAFFOLD_HTML =
|
||||
'<div id="taskAdminTabs" style="display:flex;gap:8px;margin-bottom:16px">' +
|
||||
@@ -252,4 +250,3 @@
|
||||
|
||||
await loadTasks();
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// persona/model picker, budget config, and starter templates.
|
||||
// Loaded on the settings surface.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const PRESETS = [
|
||||
{ label: 'Every morning (6am)', cron: '0 6 * * *' },
|
||||
@@ -278,4 +276,3 @@
|
||||
sb.register('_loadSettingsTasks', function() {
|
||||
loadTaskList();
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Sidebar section showing user's scheduled tasks with status indicators.
|
||||
// Click opens the task's output channel. Same pattern as WorkflowQueue.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const TaskSidebar = {
|
||||
|
||||
@@ -141,4 +139,3 @@
|
||||
}
|
||||
}, 2200); // After WorkflowQueue (2000ms)
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
//
|
||||
// Exports: window.Tokens,window.updateInputTokens,window.updateContextWarning
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Token Estimation + Context Tracking ─────
|
||||
|
||||
@@ -167,4 +165,3 @@ function dismissContextWarning() {
|
||||
sb.ns('Tokens', Tokens);
|
||||
sb.register('updateInputTokens', updateInputTokens);
|
||||
sb.register('updateContextWarning', updateContextWarning);
|
||||
})();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// Categories expand to show individual tool toggles.
|
||||
// State persisted in localStorage, sent as disabled_tools[] in completion requests.
|
||||
|
||||
'use strict';
|
||||
|
||||
const ToolsToggle = (() => {
|
||||
const STORAGE_KEY = 'cs-disabled-tools';
|
||||
@@ -242,3 +241,5 @@ const ToolsToggle = (() => {
|
||||
|
||||
return { init, getDisabledTools, refresh };
|
||||
})();
|
||||
|
||||
sb.ns('ToolsToggle', ToolsToggle);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Fullscreen admin panel with category + section navigation.
|
||||
// All loadAdmin*() functions unchanged — same endpoints, same DOM IDs.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Category → Section mapping ────────────
|
||||
const ADMIN_SECTIONS = {
|
||||
@@ -1573,4 +1571,3 @@ Object.assign(UI, {
|
||||
sb.ns('ADMIN_SECTIONS', ADMIN_SECTIONS);
|
||||
sb.ns('ADMIN_LABELS', ADMIN_LABELS);
|
||||
sb.ns('ADMIN_LOADERS', ADMIN_LOADERS);
|
||||
})();
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
// window.toggleSummarizedHistory (onclick handler)
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Delegated Action Dispatcher ────────────────────
|
||||
// Buttons use data-action="fnName" data-args='[...]' instead of onclick.
|
||||
@@ -1651,4 +1649,3 @@ sb.register('_uiDispatch', _uiDispatch);
|
||||
sb.register('_toggleArchivedProjects', _toggleArchivedProjects);
|
||||
sb.register('_submitEditFromDOM', _submitEditFromDOM);
|
||||
sb.register('toggleSummarizedHistory', toggleSummarizedHistory);
|
||||
})();
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// popOutExtBlock (onclick handlers)
|
||||
// ==========================================
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Message Formatting ──────────────────────
|
||||
|
||||
@@ -610,4 +608,3 @@ sb.register('downloadCode', downloadCode);
|
||||
sb.register('popOutExtBlock', popOutExtBlock);
|
||||
sb.register('_copyCodeBlock', _copyCodeBlock);
|
||||
sb.register('_openNoteFromTool', _openNoteFromTool);
|
||||
})();
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
// openModal, closeModal, checkTabsOverflow, Theme, mountAvatarUpload
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════════════════
|
||||
// §0 CORE UTILITIES
|
||||
@@ -1133,4 +1131,3 @@ sb.register('closeModal', closeModal);
|
||||
sb.register('checkTabsOverflow', checkTabsOverflow);
|
||||
sb.ns('Theme', Theme);
|
||||
sb.register('mountAvatarUpload', mountAvatarUpload);
|
||||
})();
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
//
|
||||
// Exports: none (extends window.UI via Object.assign)
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Object.assign(UI, {
|
||||
// ── General Settings (Settings Surface) ──
|
||||
@@ -867,4 +865,3 @@ Object.assign(UI, {
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
//
|
||||
// Exports: window.UserMenu
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const UserMenu = {
|
||||
...createComponentRegistry('UserMenu'),
|
||||
@@ -139,4 +137,3 @@ const UserMenu = {
|
||||
|
||||
// ── Exports ─────────────────────────────────
|
||||
sb.ns('UserMenu', UserMenu);
|
||||
})();
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// Admin panel for managing workflow definitions, stages, and publishing.
|
||||
// Registered as ADMIN_LOADERS.workflows in ui-admin.js.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ── Scaffold HTML ────────────────────────
|
||||
// Injected directly into adminDynamic by the loader since SCAFFOLDING
|
||||
@@ -470,4 +468,3 @@
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
// publishing, instance lifecycle, and assignment queue operations.
|
||||
// Loaded after api.js on the chat and admin surfaces.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
if (typeof API === 'undefined') return;
|
||||
|
||||
// ── Workflow Definitions ────────────────
|
||||
|
||||
API.listWorkflows = function(teamId) {
|
||||
@@ -99,4 +95,3 @@
|
||||
API.completeAssignment = function(id) {
|
||||
return this._post(`/api/v1/workflow-assignments/${id}/complete`, {});
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
// 2. Claimed assignments from team queues
|
||||
// Loaded on the chat surface after workflow-api.js.
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const WorkflowQueue = {
|
||||
|
||||
@@ -198,4 +196,3 @@
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user