@dollhousemcp/mcp-server 2.0.26 → 2.0.27-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/elements/ensembles/EnsembleManager.d.ts +18 -0
- package/dist/elements/ensembles/EnsembleManager.d.ts.map +1 -1
- package/dist/elements/ensembles/EnsembleManager.js +37 -5
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +3 -3
- package/dist/logging/LogHooks.d.ts.map +1 -1
- package/dist/logging/LogHooks.js +33 -1
- package/dist/web/contentPipeline.d.ts +1 -0
- package/dist/web/contentPipeline.d.ts.map +1 -1
- package/dist/web/contentPipeline.js +48 -4
- package/dist/web/public/app.js +204 -83
- package/dist/web/public/index.html +18 -6
- package/dist/web/public/logs.css +157 -1
- package/dist/web/public/logs.js +56 -8
- package/dist/web/public/sessions.css +2 -1
- package/dist/web/public/styles.css +272 -20
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +18 -4
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +13 -3
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/web/public/app.js
CHANGED
|
@@ -105,6 +105,7 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
105
105
|
let activeSort = 'date-desc';
|
|
106
106
|
let activeSource = 'all'; // 'all' | 'collection' | 'portfolio'
|
|
107
107
|
let searchQuery = '';
|
|
108
|
+
const DOLLHOUSE_SERVER_VERSION = document.querySelector('meta[name="dollhouse-server-version"]')?.content || '';
|
|
108
109
|
const DOLLHOUSE_SESSION_ID = document.querySelector('meta[name="dollhouse-session-id"]')?.content || '';
|
|
109
110
|
const DOLLHOUSE_RUNTIME_SESSION_ID = document.querySelector('meta[name="dollhouse-runtime-session-id"]')?.content || '';
|
|
110
111
|
|
|
@@ -117,6 +118,10 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
117
118
|
.replaceAll("'", ''');
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
function normalizeInlineMetaText(value) {
|
|
122
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
123
|
+
}
|
|
124
|
+
|
|
120
125
|
function renderHeaderStatsMarkup(primaryMarkup) {
|
|
121
126
|
const sessionTitle = DOLLHOUSE_RUNTIME_SESSION_ID && DOLLHOUSE_RUNTIME_SESSION_ID !== DOLLHOUSE_SESSION_ID
|
|
122
127
|
? `Stable session ${DOLLHOUSE_SESSION_ID}; runtime ${DOLLHOUSE_RUNTIME_SESSION_ID}`
|
|
@@ -130,6 +135,96 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
130
135
|
return `${primaryMarkup}${sessionMarkup}`;
|
|
131
136
|
}
|
|
132
137
|
|
|
138
|
+
function updateFooterVersion() {
|
|
139
|
+
// Keep the running build visible in the fixed footer so operators can
|
|
140
|
+
// quickly confirm which console version a given tab or machine is serving.
|
|
141
|
+
const footerVersion = document.getElementById('footer-version');
|
|
142
|
+
if (!footerVersion) return;
|
|
143
|
+
footerVersion.textContent = `Version: ${DOLLHOUSE_SERVER_VERSION || 'unknown'}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function wireThemeToggle() {
|
|
147
|
+
const themeToggleBtn = document.getElementById('theme-toggle');
|
|
148
|
+
const themeToggleIcon = document.getElementById('theme-toggle-icon');
|
|
149
|
+
const themeToggleLbl = document.getElementById('theme-toggle-label');
|
|
150
|
+
const html = document.documentElement;
|
|
151
|
+
|
|
152
|
+
function applyTheme(theme) {
|
|
153
|
+
html.dataset.theme = theme;
|
|
154
|
+
const isDark = theme === 'dark';
|
|
155
|
+
if (themeToggleIcon) themeToggleIcon.textContent = isDark ? '☀' : '☾';
|
|
156
|
+
if (themeToggleLbl) themeToggleLbl.textContent = isDark ? 'Switch to light mode' : 'Switch to dark mode';
|
|
157
|
+
if (themeToggleBtn) themeToggleBtn.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode');
|
|
158
|
+
const hljsLight = document.getElementById('hljs-theme-light');
|
|
159
|
+
const hljsDark = document.getElementById('hljs-theme-dark');
|
|
160
|
+
if (hljsLight) hljsLight.disabled = isDark;
|
|
161
|
+
if (hljsDark) hljsDark.disabled = !isDark;
|
|
162
|
+
try { localStorage.setItem('color-scheme', theme); } catch {}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const saved = (() => { try { return localStorage.getItem('color-scheme'); } catch {} })();
|
|
166
|
+
const preferred = saved || (globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
167
|
+
applyTheme(preferred);
|
|
168
|
+
|
|
169
|
+
if (themeToggleBtn) {
|
|
170
|
+
themeToggleBtn.addEventListener('click', () => {
|
|
171
|
+
applyTheme(html.dataset.theme === 'dark' ? 'light' : 'dark');
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function wireViewToggle() {
|
|
177
|
+
const viewToggle = document.getElementById('view-toggle');
|
|
178
|
+
const elemGrid = document.getElementById('elements-grid');
|
|
179
|
+
let activeView = (() => { try { return localStorage.getItem('collection-view') || 'grid'; } catch { return 'grid'; } })();
|
|
180
|
+
|
|
181
|
+
function applyView(view) {
|
|
182
|
+
activeView = view;
|
|
183
|
+
if (elemGrid) elemGrid.dataset.view = view;
|
|
184
|
+
viewToggle?.querySelectorAll('.view-btn').forEach(btn => {
|
|
185
|
+
const on = btn.dataset.view === view;
|
|
186
|
+
btn.classList.toggle('active', on);
|
|
187
|
+
btn.setAttribute('aria-pressed', on);
|
|
188
|
+
});
|
|
189
|
+
try { localStorage.setItem('collection-view', view); } catch {}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
applyView(activeView);
|
|
193
|
+
|
|
194
|
+
viewToggle?.addEventListener('click', e => {
|
|
195
|
+
const btn = e.target.closest('[data-view]');
|
|
196
|
+
if (btn) applyView(btn.dataset.view);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function wireSortControls() {
|
|
201
|
+
const sortSelect = document.getElementById('sort-select');
|
|
202
|
+
if (!sortSelect) return;
|
|
203
|
+
sortSelect.value = activeSort;
|
|
204
|
+
sortSelect.addEventListener('change', e => {
|
|
205
|
+
activeSort = e.target.value;
|
|
206
|
+
applyFilters();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function wireSourceToggle() {
|
|
211
|
+
const sourceToggle = document.getElementById('source-toggle');
|
|
212
|
+
if (!sourceToggle) return;
|
|
213
|
+
sourceToggle.addEventListener('click', e => {
|
|
214
|
+
const btn = e.target.closest('[data-source]');
|
|
215
|
+
if (!btn) return;
|
|
216
|
+
activeSource = btn.dataset.source;
|
|
217
|
+
sourceToggle.querySelectorAll('[data-source]').forEach(b => {
|
|
218
|
+
const on = b.dataset.source === activeSource;
|
|
219
|
+
b.classList.toggle('active', on);
|
|
220
|
+
b.setAttribute('aria-pressed', on);
|
|
221
|
+
});
|
|
222
|
+
renderTypeFilters();
|
|
223
|
+
renderTopicFilters();
|
|
224
|
+
applyFilters();
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
133
228
|
// ── Bootstrap ──────────────────────────────────────────────────────────────
|
|
134
229
|
|
|
135
230
|
function mergeCollectionData(data) {
|
|
@@ -458,6 +553,7 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
458
553
|
const idx = pageStart + i; // absolute index into filteredElements
|
|
459
554
|
const unavailable = el._unavailable;
|
|
460
555
|
const compSummary = renderComponentSummary(el);
|
|
556
|
+
const author = normalizeInlineMetaText(el.author);
|
|
461
557
|
return `
|
|
462
558
|
<article
|
|
463
559
|
class="element-card"
|
|
@@ -483,7 +579,7 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
483
579
|
${compSummary}
|
|
484
580
|
<footer class="card-footer">
|
|
485
581
|
<div class="card-meta">
|
|
486
|
-
${
|
|
582
|
+
${author ? `<span class="meta-author">by ${escapeHtml(author)}</span>` : ''}
|
|
487
583
|
${el.version ? `<span class="meta-version">v${escapeHtml(el.version)}</span>` : ''}
|
|
488
584
|
${el.category ? `<span class="meta-category">${escapeHtml(el.category)}</span>` : ''}
|
|
489
585
|
${el.created ? `<span class="meta-date">${formatDate(el.created)}</span>` : ''}
|
|
@@ -682,9 +778,10 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
682
778
|
}
|
|
683
779
|
|
|
684
780
|
function setupModalMeta(element, modal) {
|
|
781
|
+
const author = normalizeInlineMetaText(element.author);
|
|
685
782
|
modal.querySelector('.modal-title').textContent = element.name;
|
|
686
783
|
modal.querySelector('.modal-type').textContent = capitalize(element.type);
|
|
687
|
-
modal.querySelector('.modal-author').textContent =
|
|
784
|
+
modal.querySelector('.modal-author').textContent = author ? `by ${author}` : '';
|
|
688
785
|
modal.querySelector('.modal-version').textContent = element.version ? `v${element.version}` : '';
|
|
689
786
|
const modalDate = modal.querySelector('.modal-date');
|
|
690
787
|
const modalSource = modal.querySelector('.modal-source');
|
|
@@ -1877,70 +1974,10 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
1877
1974
|
// ── Event wiring ───────────────────────────────────────────────────────────
|
|
1878
1975
|
|
|
1879
1976
|
document.addEventListener('DOMContentLoaded', () => {
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
const themeToggleLbl = document.getElementById('theme-toggle-label');
|
|
1885
|
-
const html = document.documentElement;
|
|
1886
|
-
|
|
1887
|
-
function applyTheme(theme) {
|
|
1888
|
-
html.dataset.theme = theme;
|
|
1889
|
-
const isDark = theme === 'dark';
|
|
1890
|
-
if (themeToggleIcon) themeToggleIcon.textContent = isDark ? '☀' : '☾';
|
|
1891
|
-
if (themeToggleLbl) themeToggleLbl.textContent = isDark ? 'Switch to light mode' : 'Switch to dark mode';
|
|
1892
|
-
if (themeToggleBtn) themeToggleBtn.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode');
|
|
1893
|
-
// Sync highlight.js theme
|
|
1894
|
-
const hljsLight = document.getElementById('hljs-theme-light');
|
|
1895
|
-
const hljsDark = document.getElementById('hljs-theme-dark');
|
|
1896
|
-
if (hljsLight) hljsLight.disabled = isDark;
|
|
1897
|
-
if (hljsDark) hljsDark.disabled = !isDark;
|
|
1898
|
-
try { localStorage.setItem('color-scheme', theme); } catch {}
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
// Restore saved preference; fall back to OS preference
|
|
1902
|
-
const saved = (() => { try { return localStorage.getItem('color-scheme'); } catch {} })();
|
|
1903
|
-
const preferred = saved || (globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
1904
|
-
applyTheme(preferred);
|
|
1905
|
-
|
|
1906
|
-
if (themeToggleBtn) {
|
|
1907
|
-
themeToggleBtn.addEventListener('click', () => {
|
|
1908
|
-
applyTheme(html.dataset.theme === 'dark' ? 'light' : 'dark');
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
|
|
1912
|
-
// View toggle
|
|
1913
|
-
const viewToggle = document.getElementById('view-toggle');
|
|
1914
|
-
const elemGrid = document.getElementById('elements-grid');
|
|
1915
|
-
let activeView = (() => { try { return localStorage.getItem('collection-view') || 'grid'; } catch { return 'grid'; } })();
|
|
1916
|
-
|
|
1917
|
-
function applyView(view) {
|
|
1918
|
-
activeView = view;
|
|
1919
|
-
if (elemGrid) elemGrid.dataset.view = view;
|
|
1920
|
-
viewToggle?.querySelectorAll('.view-btn').forEach(btn => {
|
|
1921
|
-
const on = btn.dataset.view === view;
|
|
1922
|
-
btn.classList.toggle('active', on);
|
|
1923
|
-
btn.setAttribute('aria-pressed', on);
|
|
1924
|
-
});
|
|
1925
|
-
try { localStorage.setItem('collection-view', view); } catch {}
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
|
-
applyView(activeView);
|
|
1929
|
-
|
|
1930
|
-
viewToggle?.addEventListener('click', e => {
|
|
1931
|
-
const btn = e.target.closest('[data-view]');
|
|
1932
|
-
if (btn) applyView(btn.dataset.view);
|
|
1933
|
-
});
|
|
1934
|
-
|
|
1935
|
-
// Sort
|
|
1936
|
-
const sortSelect = document.getElementById('sort-select');
|
|
1937
|
-
if (sortSelect) {
|
|
1938
|
-
sortSelect.value = activeSort;
|
|
1939
|
-
sortSelect.addEventListener('change', e => {
|
|
1940
|
-
activeSort = e.target.value;
|
|
1941
|
-
applyFilters();
|
|
1942
|
-
});
|
|
1943
|
-
}
|
|
1977
|
+
updateFooterVersion();
|
|
1978
|
+
wireThemeToggle();
|
|
1979
|
+
wireViewToggle();
|
|
1980
|
+
wireSortControls();
|
|
1944
1981
|
|
|
1945
1982
|
// Search
|
|
1946
1983
|
const searchInput = document.getElementById('search-input');
|
|
@@ -1975,29 +2012,16 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
1975
2012
|
}
|
|
1976
2013
|
});
|
|
1977
2014
|
|
|
1978
|
-
|
|
1979
|
-
const sourceToggle = document.getElementById('source-toggle');
|
|
1980
|
-
if (sourceToggle) {
|
|
1981
|
-
sourceToggle.addEventListener('click', e => {
|
|
1982
|
-
const btn = e.target.closest('[data-source]');
|
|
1983
|
-
if (!btn) return;
|
|
1984
|
-
activeSource = btn.dataset.source;
|
|
1985
|
-
sourceToggle.querySelectorAll('[data-source]').forEach(b => {
|
|
1986
|
-
const on = b.dataset.source === activeSource;
|
|
1987
|
-
b.classList.toggle('active', on);
|
|
1988
|
-
b.setAttribute('aria-pressed', on);
|
|
1989
|
-
});
|
|
1990
|
-
renderTypeFilters();
|
|
1991
|
-
renderTopicFilters();
|
|
1992
|
-
applyFilters();
|
|
1993
|
-
});
|
|
1994
|
-
}
|
|
2015
|
+
wireSourceToggle();
|
|
1995
2016
|
|
|
1996
2017
|
// Portfolio button
|
|
1997
2018
|
document.getElementById('btn-portfolio')?.addEventListener('click', loadLocalPortfolio);
|
|
1998
2019
|
|
|
1999
2020
|
// ── Tab switching ─────────────────────────────────────────────────────────
|
|
2000
2021
|
const consoleTabs = document.getElementById('console-tabs');
|
|
2022
|
+
const headerNavRow = document.querySelector('.header-nav-row');
|
|
2023
|
+
const consoleTabMenuToggle = document.getElementById('console-tab-menu-toggle');
|
|
2024
|
+
const consoleTabMenu = document.getElementById('console-tab-menu');
|
|
2001
2025
|
const tabInits = { logs: false, metrics: false, permissions: false, security: false };
|
|
2002
2026
|
|
|
2003
2027
|
const TAB_KEY = 'dollhousemcp-active-tab';
|
|
@@ -2082,8 +2106,71 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
2082
2106
|
p.hidden = p.id !== 'tab-' + tabName;
|
|
2083
2107
|
p.classList.toggle('active', p.id === 'tab-' + tabName);
|
|
2084
2108
|
});
|
|
2109
|
+
syncConsoleTabMenuSelection();
|
|
2110
|
+
closeConsoleTabMenu();
|
|
2111
|
+
scheduleConsoleTabOverflowCheck();
|
|
2085
2112
|
};
|
|
2086
2113
|
|
|
2114
|
+
function renderConsoleTabMenu() {
|
|
2115
|
+
if (!consoleTabs || !consoleTabMenu) return;
|
|
2116
|
+
consoleTabMenu.innerHTML = '';
|
|
2117
|
+
consoleTabs.querySelectorAll('.console-tab').forEach((btn) => {
|
|
2118
|
+
const item = document.createElement('button');
|
|
2119
|
+
item.type = 'button';
|
|
2120
|
+
item.className = 'console-tab-menu-item';
|
|
2121
|
+
item.dataset.tab = btn.dataset.tab || '';
|
|
2122
|
+
item.setAttribute('role', 'menuitem');
|
|
2123
|
+
item.textContent = btn.textContent || '';
|
|
2124
|
+
if (btn.classList.contains('active')) item.classList.add('active');
|
|
2125
|
+
consoleTabMenu.appendChild(item);
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
function syncConsoleTabMenuSelection() {
|
|
2130
|
+
if (!consoleTabs || !consoleTabMenu) return;
|
|
2131
|
+
const activeTab = consoleTabs.querySelector('.console-tab.active')?.dataset.tab || '';
|
|
2132
|
+
consoleTabMenu.querySelectorAll('.console-tab-menu-item').forEach((item) => {
|
|
2133
|
+
item.classList.toggle('active', item.dataset.tab === activeTab);
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
function closeConsoleTabMenu() {
|
|
2138
|
+
if (!consoleTabMenu || !consoleTabMenuToggle) return;
|
|
2139
|
+
consoleTabMenu.hidden = true;
|
|
2140
|
+
consoleTabMenuToggle.setAttribute('aria-expanded', 'false');
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
function tabsNeedOverflowMenu() {
|
|
2144
|
+
if (!consoleTabs) return false;
|
|
2145
|
+
const buttons = Array.from(consoleTabs.querySelectorAll('.console-tab'));
|
|
2146
|
+
if (buttons.length < 2) return false;
|
|
2147
|
+
const firstTop = buttons[0].offsetTop;
|
|
2148
|
+
return buttons.some((btn) => btn.offsetTop !== firstTop);
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
let consoleTabOverflowFrame = 0;
|
|
2152
|
+
function updateConsoleTabOverflow() {
|
|
2153
|
+
if (!consoleTabs || !headerNavRow || !consoleTabMenuToggle) return;
|
|
2154
|
+
headerNavRow.classList.remove('header-nav-row--collapsed');
|
|
2155
|
+
consoleTabMenuToggle.hidden = true;
|
|
2156
|
+
const shouldCollapse = tabsNeedOverflowMenu();
|
|
2157
|
+
if (shouldCollapse) {
|
|
2158
|
+
headerNavRow.classList.add('header-nav-row--collapsed');
|
|
2159
|
+
consoleTabMenuToggle.hidden = false;
|
|
2160
|
+
}
|
|
2161
|
+
if (!shouldCollapse) {
|
|
2162
|
+
closeConsoleTabMenu();
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
function scheduleConsoleTabOverflowCheck() {
|
|
2167
|
+
if (consoleTabOverflowFrame) cancelAnimationFrame(consoleTabOverflowFrame);
|
|
2168
|
+
consoleTabOverflowFrame = requestAnimationFrame(() => {
|
|
2169
|
+
consoleTabOverflowFrame = 0;
|
|
2170
|
+
updateConsoleTabOverflow();
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2087
2174
|
/**
|
|
2088
2175
|
* Parse the URL hash into tab name and query parameters.
|
|
2089
2176
|
* Supports fragment-query pattern: #tab?key=value&key=value
|
|
@@ -2218,6 +2305,15 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
2218
2305
|
// Handle hash changes for deep-linking (e.g., open_logs operation)
|
|
2219
2306
|
globalThis.addEventListener('hashchange', () => applyHashTab());
|
|
2220
2307
|
|
|
2308
|
+
renderConsoleTabMenu();
|
|
2309
|
+
syncConsoleTabMenuSelection();
|
|
2310
|
+
scheduleConsoleTabOverflowCheck();
|
|
2311
|
+
globalThis.addEventListener('resize', scheduleConsoleTabOverflowCheck);
|
|
2312
|
+
if (typeof ResizeObserver === 'function' && headerNavRow) {
|
|
2313
|
+
const tabOverflowObserver = new ResizeObserver(() => scheduleConsoleTabOverflowCheck());
|
|
2314
|
+
tabOverflowObserver.observe(headerNavRow);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2221
2317
|
if (consoleTabs) {
|
|
2222
2318
|
consoleTabs.addEventListener('click', (e) => {
|
|
2223
2319
|
const btn = e.target.closest('.console-tab');
|
|
@@ -2232,6 +2328,31 @@ globalThis.DollhouseConsoleUI.clearBanner = function(bannerId) {
|
|
|
2232
2328
|
});
|
|
2233
2329
|
}
|
|
2234
2330
|
|
|
2331
|
+
consoleTabMenuToggle?.addEventListener('click', () => {
|
|
2332
|
+
if (!consoleTabMenu) return;
|
|
2333
|
+
const willOpen = consoleTabMenu.hidden;
|
|
2334
|
+
consoleTabMenu.hidden = !willOpen;
|
|
2335
|
+
consoleTabMenuToggle.setAttribute('aria-expanded', willOpen ? 'true' : 'false');
|
|
2336
|
+
});
|
|
2337
|
+
|
|
2338
|
+
consoleTabMenu?.addEventListener('click', (e) => {
|
|
2339
|
+
const btn = e.target.closest('.console-tab-menu-item');
|
|
2340
|
+
if (!btn?.dataset.tab) return;
|
|
2341
|
+
const tab = btn.dataset.tab;
|
|
2342
|
+
switchToTab(tab);
|
|
2343
|
+
localStorage.setItem(TAB_KEY, tab);
|
|
2344
|
+
lazyInitTab(tab, tabInits);
|
|
2345
|
+
});
|
|
2346
|
+
|
|
2347
|
+
globalThis.addEventListener('click', (e) => {
|
|
2348
|
+
if (!consoleTabMenu || !consoleTabMenuToggle) return;
|
|
2349
|
+
if (consoleTabMenu.hidden) return;
|
|
2350
|
+
const target = e.target;
|
|
2351
|
+
if (!(target instanceof Element)) return;
|
|
2352
|
+
if (consoleTabMenu.contains(target) || consoleTabMenuToggle.contains(target)) return;
|
|
2353
|
+
closeConsoleTabMenu();
|
|
2354
|
+
});
|
|
2355
|
+
|
|
2235
2356
|
function lazyInitTab(tab, tabInits, params) {
|
|
2236
2357
|
const dc = globalThis.DollhouseConsole;
|
|
2237
2358
|
const module = dc?.[tab];
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
<meta name="dollhouse-runtime-session-id" content="{{DOLLHOUSE_RUNTIME_SESSION_ID}}">
|
|
19
19
|
<!-- Asset version — injected at request time for cache-busting local CSS/JS/img files. -->
|
|
20
20
|
<meta name="dollhouse-console-asset-version" content="{{DOLLHOUSE_ASSET_VERSION}}">
|
|
21
|
+
<link rel="icon" type="image/png" href="dollhouse-logo.png?v={{DOLLHOUSE_ASSET_VERSION}}">
|
|
22
|
+
<link rel="apple-touch-icon" href="dollhouse-logo.png?v={{DOLLHOUSE_ASSET_VERSION}}">
|
|
21
23
|
<link rel="stylesheet" href="fonts.css?v={{DOLLHOUSE_ASSET_VERSION}}">
|
|
22
24
|
<link rel="stylesheet" href="styles.css?v={{DOLLHOUSE_ASSET_VERSION}}">
|
|
23
25
|
<link rel="stylesheet" href="logs.css?v={{DOLLHOUSE_ASSET_VERSION}}">
|
|
@@ -41,7 +43,14 @@
|
|
|
41
43
|
<p class="site-tagline">Management Console</p>
|
|
42
44
|
</div>
|
|
43
45
|
</div>
|
|
44
|
-
<div class="header-
|
|
46
|
+
<div class="header-controls">
|
|
47
|
+
<div class="site-stats" id="stats" aria-live="polite"></div>
|
|
48
|
+
<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Switch to dark mode" title="Switch to dark mode">
|
|
49
|
+
<span class="theme-toggle-icon" id="theme-toggle-icon" aria-hidden="true">☾</span>
|
|
50
|
+
<span class="sr-only" id="theme-toggle-label">Switch to dark mode</span>
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="header-nav-row">
|
|
45
54
|
<nav class="console-tabs" id="console-tabs" aria-label="Console tabs">
|
|
46
55
|
<button class="console-tab" data-tab="setup">Setup</button>
|
|
47
56
|
<button class="console-tab" data-tab="security">Auth</button>
|
|
@@ -50,12 +59,14 @@
|
|
|
50
59
|
<button class="console-tab" data-tab="permissions">Permissions</button>
|
|
51
60
|
<button class="console-tab active" data-tab="portfolio">Portfolio</button>
|
|
52
61
|
</nav>
|
|
62
|
+
<div class="console-tab-menu-shell" id="console-tab-menu-shell">
|
|
63
|
+
<button class="console-tab-menu-toggle" id="console-tab-menu-toggle" type="button" hidden aria-haspopup="menu" aria-expanded="false" aria-controls="console-tab-menu">
|
|
64
|
+
<span class="console-tab-menu-icon" aria-hidden="true">☰</span>
|
|
65
|
+
<span class="console-tab-menu-label">Menu</span>
|
|
66
|
+
</button>
|
|
67
|
+
<div class="console-tab-menu" id="console-tab-menu" role="menu" hidden></div>
|
|
68
|
+
</div>
|
|
53
69
|
<div class="session-indicator" id="session-indicator" title="Active sessions"></div>
|
|
54
|
-
<div class="site-stats" id="stats" aria-live="polite"></div>
|
|
55
|
-
<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Switch to dark mode" title="Switch to dark mode">
|
|
56
|
-
<span class="theme-toggle-icon" id="theme-toggle-icon" aria-hidden="true">☾</span>
|
|
57
|
-
<span class="sr-only" id="theme-toggle-label">Switch to dark mode</span>
|
|
58
|
-
</button>
|
|
59
70
|
</div>
|
|
60
71
|
</header>
|
|
61
72
|
|
|
@@ -570,6 +581,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
|
|
|
570
581
|
<a href="https://github.com/DollhouseMCP/mcp-server" class="footer-link">GitHub Repository</a>
|
|
571
582
|
<a href="./collection-index.json" class="footer-link">JSON API</a>
|
|
572
583
|
<a href="https://dollhousemcp.com" class="footer-link">DollhouseMCP</a>
|
|
584
|
+
<span class="footer-version" id="footer-version" aria-live="polite" aria-atomic="true"></span>
|
|
573
585
|
<span class="footer-updated" id="footer-updated"></span>
|
|
574
586
|
<span class="footer-copyright">© 2026 DollhouseMCP</span>
|
|
575
587
|
</div>
|
package/dist/web/public/logs.css
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.log-viewer {
|
|
7
7
|
display: flex;
|
|
8
8
|
flex-direction: column;
|
|
9
|
-
height: calc(
|
|
9
|
+
height: calc(100dvh - var(--site-footer-height, 4.5rem) - 120px);
|
|
10
10
|
font-family: var(--font-mono);
|
|
11
11
|
font-size: 12.5px;
|
|
12
12
|
line-height: 1.5;
|
|
@@ -470,3 +470,159 @@
|
|
|
470
470
|
.log-jump-bottom:hover {
|
|
471
471
|
background: var(--signal-2);
|
|
472
472
|
}
|
|
473
|
+
|
|
474
|
+
@media (max-width: 48rem) {
|
|
475
|
+
.log-viewer {
|
|
476
|
+
height: calc(100dvh - var(--site-footer-height, 4.5rem) - 104px);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.log-controls {
|
|
480
|
+
padding: 10px;
|
|
481
|
+
gap: 10px;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.log-filter-group {
|
|
485
|
+
flex: 1 1 calc(50% - 10px);
|
|
486
|
+
min-width: 0;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.log-filter-group label {
|
|
490
|
+
flex-shrink: 0;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.log-controls select,
|
|
494
|
+
.log-controls input,
|
|
495
|
+
.log-search {
|
|
496
|
+
min-width: 0;
|
|
497
|
+
width: 100%;
|
|
498
|
+
max-width: none;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.log-status-bar {
|
|
502
|
+
flex-wrap: wrap;
|
|
503
|
+
row-gap: 6px;
|
|
504
|
+
padding: 8px 10px;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.log-entry-count {
|
|
508
|
+
margin-left: 0;
|
|
509
|
+
width: 100%;
|
|
510
|
+
order: 10;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.log-entry {
|
|
514
|
+
display: grid;
|
|
515
|
+
grid-template-columns: auto auto auto minmax(0, 1fr) auto;
|
|
516
|
+
grid-template-areas:
|
|
517
|
+
"checkbox time level source corr"
|
|
518
|
+
". message message message message";
|
|
519
|
+
align-items: start;
|
|
520
|
+
gap: 4px 8px;
|
|
521
|
+
padding: 6px 10px;
|
|
522
|
+
min-height: 74px;
|
|
523
|
+
white-space: normal;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.log-checkbox {
|
|
527
|
+
grid-area: checkbox;
|
|
528
|
+
margin-top: 1px;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.log-time {
|
|
532
|
+
grid-area: time;
|
|
533
|
+
width: auto;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.log-level {
|
|
537
|
+
grid-area: level;
|
|
538
|
+
width: auto;
|
|
539
|
+
min-width: 42px;
|
|
540
|
+
padding-inline: 6px;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.log-category {
|
|
544
|
+
display: none;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.log-source {
|
|
548
|
+
grid-area: source;
|
|
549
|
+
max-width: none;
|
|
550
|
+
min-width: 0;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
.log-corr-badge {
|
|
554
|
+
grid-area: corr;
|
|
555
|
+
width: auto;
|
|
556
|
+
justify-self: end;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.log-message {
|
|
560
|
+
grid-area: message;
|
|
561
|
+
white-space: normal;
|
|
562
|
+
overflow: hidden;
|
|
563
|
+
text-overflow: initial;
|
|
564
|
+
display: -webkit-box;
|
|
565
|
+
-webkit-line-clamp: 2;
|
|
566
|
+
-webkit-box-orient: vertical;
|
|
567
|
+
line-height: 1.45;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.log-detail-card {
|
|
571
|
+
width: min(680px, calc(100vw - 1rem));
|
|
572
|
+
max-height: calc(100vh - 1rem);
|
|
573
|
+
border-radius: 0.9rem;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.log-detail-card-header {
|
|
577
|
+
flex-wrap: wrap;
|
|
578
|
+
gap: 8px;
|
|
579
|
+
align-items: flex-start;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.log-detail-card-actions {
|
|
583
|
+
width: 100%;
|
|
584
|
+
justify-content: flex-end;
|
|
585
|
+
flex-wrap: wrap;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.log-detail-field {
|
|
589
|
+
flex-direction: column;
|
|
590
|
+
gap: 2px;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.log-detail-field-label {
|
|
594
|
+
min-width: 0;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.log-jump-bottom {
|
|
598
|
+
right: 12px;
|
|
599
|
+
bottom: 12px;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
@media (max-width: 32rem) {
|
|
604
|
+
.log-filter-group {
|
|
605
|
+
flex: 1 1 100%;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.log-entry {
|
|
609
|
+
grid-template-columns: auto auto minmax(0, 1fr) auto;
|
|
610
|
+
grid-template-areas:
|
|
611
|
+
"checkbox level source corr"
|
|
612
|
+
". time time time"
|
|
613
|
+
". message message message";
|
|
614
|
+
min-height: 96px;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.log-time {
|
|
618
|
+
color: var(--ink-700);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.log-source {
|
|
622
|
+
font-size: 10px;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.log-status-indicator {
|
|
626
|
+
width: 100%;
|
|
627
|
+
}
|
|
628
|
+
}
|