diff --git a/apps/web-console/energy-monitor.css b/apps/web-console/energy-monitor.css index 5312b64..15219de 100644 --- a/apps/web-console/energy-monitor.css +++ b/apps/web-console/energy-monitor.css @@ -5,7 +5,7 @@ inset: 0; display: grid; place-items: center; - padding: 68px 20px 20px; + padding: 16px; background: color-mix(in oklch, var(--background) 58%, transparent); backdrop-filter: blur(6px) saturate(.9); -webkit-backdrop-filter: blur(6px) saturate(.9); @@ -17,8 +17,8 @@ } .console-v2 .energy-monitor-page { - width: min(1180px, 100%); - height: min(664px, 100%); + width: min(1480px, 100%); + height: min(900px, 100%); min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); diff --git a/apps/web-console/firmware-workbench-entry.css b/apps/web-console/firmware-workbench-entry.css index 7c766a2..71d67e6 100644 --- a/apps/web-console/firmware-workbench-entry.css +++ b/apps/web-console/firmware-workbench-entry.css @@ -4,7 +4,7 @@ inset: 0; display: grid; place-items: center; - padding: 68px 20px 20px; + padding: 16px; background: color-mix(in oklch, var(--background) 58%, transparent); backdrop-filter: blur(6px) saturate(.9); -webkit-backdrop-filter: blur(6px) saturate(.9); @@ -12,8 +12,8 @@ } .console-v2 .firmware-workbench-layer[hidden] { display: none !important; } .console-v2 .firmware-workbench-page { - width: min(1180px, 100%); - height: min(664px, 100%); + width: min(1480px, 100%); + height: min(900px, 100%); min-height: 0; display: grid; grid-template-rows: 76px minmax(0, 1fr); diff --git a/apps/web-console/firmware-workbench-entry.js b/apps/web-console/firmware-workbench-entry.js index cd652b2..25774bc 100644 --- a/apps/web-console/firmware-workbench-entry.js +++ b/apps/web-console/firmware-workbench-entry.js @@ -3,6 +3,17 @@ const state = { open: false, returnFocus: null, backgroundInert: [] }; + function currentWorkbenchTheme() { + return document.documentElement.dataset.glassTheme === "light" ? "light" : "dark"; + } + + function syncWorkbenchTheme(frame) { + frame?.contentWindow?.postMessage({ + type: "cognitive-agent:theme-change", + theme: currentWorkbenchTheme(), + }, window.location.origin); + } + function setBackgroundInert(inert) { const layer = document.querySelector("#firmwareWorkbenchLayer"); if (!layer) return; @@ -80,11 +91,19 @@ - + `; dock.append(trigger); document.body.append(layer); + const frame = document.querySelector(".firmware-workbench-frame", layer); + frame.src = `/firmware-workbench.html?embedded=1&theme=${currentWorkbenchTheme()}`; + frame.addEventListener("load", () => syncWorkbenchTheme(frame)); + window.addEventListener("cognitive-agent:theme-change", () => syncWorkbenchTheme(frame)); + new MutationObserver(() => syncWorkbenchTheme(frame)).observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-glass-theme"], + }); trigger.addEventListener("click", () => setOpen(!state.open)); document.querySelector("#firmwareWorkbenchClose", layer).addEventListener("click", () => setOpen(false)); layer.addEventListener("click", (event) => { if (event.target === layer) setOpen(false); }); diff --git a/apps/web-console/firmware-workbench-theme.js b/apps/web-console/firmware-workbench-theme.js new file mode 100644 index 0000000..656b450 --- /dev/null +++ b/apps/web-console/firmware-workbench-theme.js @@ -0,0 +1,65 @@ +(() => { + "use strict"; + + const STORAGE_KEY = "cognitive-agent.glass-theme"; + + function normalizeTheme(value) { + return value === "light" ? "light" : value === "dark" ? "dark" : ""; + } + + function themeFromCookie() { + try { + return normalizeTheme(document.cookie + .split(";") + .map((part) => part.trim()) + .find((part) => part.startsWith(`${STORAGE_KEY}=`)) + ?.slice(STORAGE_KEY.length + 1)); + } catch (_error) { + return ""; + } + } + + function resolveInitialTheme() { + const requested = normalizeTheme(new URLSearchParams(window.location.search).get("theme")); + if (requested) return requested; + try { + const parentTheme = normalizeTheme(window.parent?.document?.documentElement?.dataset?.glassTheme); + if (parentTheme) return parentTheme; + } catch (_error) { + // Standalone and cross-origin rendering continue with local preferences. + } + try { + const stored = normalizeTheme(localStorage.getItem(STORAGE_KEY)); + if (stored) return stored; + } catch (_error) { + // Storage may be unavailable in hardened browser contexts. + } + return themeFromCookie() || "dark"; + } + + function applyTheme(theme) { + const normalized = normalizeTheme(theme) || "dark"; + document.documentElement.dataset.glassTheme = normalized; + document.documentElement.style.colorScheme = normalized; + document.querySelector("#firmwareWorkbenchThemeColor") + ?.setAttribute("content", normalized === "dark" ? "#0f1526" : "#f3f6fb"); + return normalized; + } + + applyTheme(resolveInitialTheme()); + + window.addEventListener("storage", (event) => { + if (event.key === STORAGE_KEY) applyTheme(event.newValue); + }); + window.addEventListener("message", (event) => { + if (event.origin !== window.location.origin) return; + if (window.parent !== window && event.source !== window.parent) return; + if (event.data?.type !== "cognitive-agent:theme-change") return; + applyTheme(event.data.theme); + }); + + window.CognitiveAgentFirmwareWorkbenchTheme = Object.freeze({ + apply: applyTheme, + current: () => document.documentElement.dataset.glassTheme, + }); +})(); diff --git a/apps/web-console/firmware-workbench.css b/apps/web-console/firmware-workbench.css index 3f0a587..b335af6 100644 --- a/apps/web-console/firmware-workbench.css +++ b/apps/web-console/firmware-workbench.css @@ -341,7 +341,7 @@ th:nth-child(4) { width: 28%; } th:nth-child(5) { width: 8%; } th:nth-child(6) { .modal-backdrop { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 24px; background: rgba(31, 43, 61, .34); backdrop-filter: blur(4px); } .modal-backdrop[hidden] { display: none; } -.modal { width: min(780px, 100%); max-height: min(680px, calc(100dvh - 48px)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); } +.modal { width: min(1040px, 100%); max-height: min(820px, calc(100dvh - 48px)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); } .modal header, .modal footer { padding: 14px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--line); } .modal footer { justify-content: flex-end; border-top: 1px solid var(--line); border-bottom: 0; } .modal-body { overflow: auto; padding: 16px; } @@ -454,3 +454,155 @@ body.embedded .file-cell span { line-height: 1.15; } body.embedded .pipeline-card { overflow-x: auto; } body.embedded .pipeline-card .pipeline { width: 680px; } } + +/* The workbench is rendered in an iframe, so it owns a complete theme token + set instead of relying on custom properties from the parent document. */ +:root[data-glass-theme="dark"] { + color-scheme: dark; + --page: #090e1c; + --surface: #171e31; + --surface-soft: #11182a; + --line: #303a55; + --line-strong: #44516d; + --text: #edf2ff; + --muted: #9ba9c0; + --primary: #7aa3ff; + --primary-soft: #1b2b53; + --success: #55d4a1; + --success-soft: #12372d; + --warning: #f2bd68; + --danger: #ff8993; + --shadow: 0 26px 70px rgba(0, 0, 0, .42), 0 4px 18px rgba(0, 0, 0, .24); +} + +:root[data-glass-theme="dark"] body:not(.embedded) { + background: + radial-gradient(circle at 15% 8%, color-mix(in srgb, var(--primary) 18%, transparent), transparent 31%), + linear-gradient(145deg, #11182b 0%, var(--page) 100%); +} + +:root[data-glass-theme="dark"] body.embedded { background: transparent; } +:root[data-glass-theme="dark"] .shell, +:root[data-glass-theme="dark"] body.embedded .shell { + background: color-mix(in srgb, var(--surface-soft) 86%, var(--page)); + border-color: color-mix(in srgb, var(--line-strong) 78%, transparent); +} +:root[data-glass-theme="dark"] .topbar { + background: color-mix(in srgb, var(--surface) 94%, transparent); +} +:root[data-glass-theme="dark"] :is(.back-link, .icon-button, .button-secondary) { + color: var(--muted); + background: var(--surface); + border-color: var(--line-strong); +} +:root[data-glass-theme="dark"] :is(.back-link, .icon-button):hover { + color: var(--primary); + border-color: color-mix(in srgb, var(--primary) 50%, var(--line)); + background: var(--primary-soft); +} +:root[data-glass-theme="dark"] :is(.eyebrow, .section-kicker) { color: var(--muted); } +:root[data-glass-theme="dark"] :is(.environment-chip, .server-state) { + color: var(--muted); + background: var(--surface-soft); +} +:root[data-glass-theme="dark"] .server-state span { background: color-mix(in srgb, var(--muted) 72%, transparent); } +:root[data-glass-theme="dark"] .server-state.online, +:root[data-glass-theme="dark"] .status-badge[data-status="baseline"] { + border-color: color-mix(in srgb, var(--success) 44%, var(--line)); + background: var(--success-soft); +} +:root[data-glass-theme="dark"] .card { + box-shadow: 0 2px 10px rgba(0, 0, 0, .16); +} +:root[data-glass-theme="dark"] .command-card > label { color: var(--muted); } +:root[data-glass-theme="dark"] textarea:focus { background: var(--surface); } +:root[data-glass-theme="dark"] :is(select, option) { color: var(--text); background: var(--surface); } +:root[data-glass-theme="dark"] .prompt-templates button, +:root[data-glass-theme="dark"] .cap-tags span, +:root[data-glass-theme="dark"] .table-actions :is(button, a) { + color: var(--primary); + background: var(--primary-soft); + border-color: color-mix(in srgb, var(--primary) 34%, var(--line)); +} +:root[data-glass-theme="dark"] .capability-brief { + border-color: color-mix(in srgb, var(--primary) 25%, var(--line)); + background: color-mix(in srgb, var(--primary-soft) 44%, var(--surface-soft)); +} +:root[data-glass-theme="dark"] .capability-brief strong { color: var(--text); } +:root[data-glass-theme="dark"] .capability-brief > svg { color: var(--primary); } +:root[data-glass-theme="dark"] .pipeline-stage::after { background: var(--line); } +:root[data-glass-theme="dark"] .stage-node { + color: var(--muted); + border-color: var(--line-strong); + background: var(--surface); +} +:root[data-glass-theme="dark"] .pipeline-stage[data-status="success"] .stage-node { + border-color: color-mix(in srgb, var(--success) 62%, var(--line)); +} +:root[data-glass-theme="dark"] .pipeline-stage[data-status="failed"] .stage-node, +:root[data-glass-theme="dark"] .pipeline-stage[data-status="blocked"] .stage-node, +:root[data-glass-theme="dark"] .release-result[data-state="failed"], +:root[data-glass-theme="dark"] .status-badge[data-status="failed"], +:root[data-glass-theme="dark"] .status-badge[data-status="blocked"] { + color: var(--danger); + border-color: color-mix(in srgb, var(--danger) 44%, var(--line)); + background: color-mix(in srgb, var(--danger) 12%, var(--surface)); +} +:root[data-glass-theme="dark"] .pipeline-stage[data-status="canceled"] .stage-node { + color: var(--muted); + background: var(--surface-soft); +} +:root[data-glass-theme="dark"] .pipeline-stage[data-status="pending_confirmation"] .stage-node, +:root[data-glass-theme="dark"] .status-badge[data-status="ready"], +:root[data-glass-theme="dark"] .status-badge[data-status="pending_confirmation"] { + color: var(--warning); + border-color: color-mix(in srgb, var(--warning) 44%, var(--line)); + background: color-mix(in srgb, var(--warning) 12%, var(--surface)); +} +:root[data-glass-theme="dark"] .pipeline-stage[data-status="success"]::after { + background: color-mix(in srgb, var(--success) 64%, var(--line)); +} +:root[data-glass-theme="dark"] .release-result[data-state="success"], +:root[data-glass-theme="dark"] .status-badge[data-status="success"], +:root[data-glass-theme="dark"] .status-badge[data-status="published"] { + border-color: color-mix(in srgb, var(--success) 44%, var(--line)); + background: var(--success-soft); +} +:root[data-glass-theme="dark"] .result-icon { + color: var(--muted); + background: color-mix(in srgb, var(--surface-soft) 78%, var(--line)); +} +:root[data-glass-theme="dark"] .release-result[data-state="success"] .result-icon { + color: var(--success); + background: color-mix(in srgb, var(--success) 18%, var(--surface)); +} +:root[data-glass-theme="dark"] .metrics div { border-color: var(--line); } +:root[data-glass-theme="dark"] :is(.log-stream, .log-details) { background: var(--surface-soft); } +:root[data-glass-theme="dark"] .empty-state svg { color: var(--muted); } +:root[data-glass-theme="dark"] .empty-state strong { color: var(--text); } +:root[data-glass-theme="dark"] .log-entry, +:root[data-glass-theme="dark"] :is(.change-item, .test-item) { border-color: var(--line); } +:root[data-glass-theme="dark"] .log-time { color: var(--muted); } +:root[data-glass-theme="dark"] .log-dot { background: var(--muted); } +:root[data-glass-theme="dark"] .log-copy p { color: var(--muted); } +:root[data-glass-theme="dark"] .inspector-tabs { background: var(--surface); } +:root[data-glass-theme="dark"] .inspector-tabs button { color: var(--muted); } +:root[data-glass-theme="dark"] .inspector-tabs button.active { + color: var(--primary); + background: var(--surface-soft); +} +:root[data-glass-theme="dark"] :is(.build-output, .code-block) { color: var(--text); } +:root[data-glass-theme="dark"] .server-target strong { color: var(--text); } +:root[data-glass-theme="dark"] th { color: var(--muted); background: var(--surface); } +:root[data-glass-theme="dark"] td { color: var(--muted); border-color: var(--line); } +:root[data-glass-theme="dark"] :is(.software-name strong, .file-cell strong) { color: var(--text); } +:root[data-glass-theme="dark"] .table-actions .delete-action { + color: var(--danger); + background: color-mix(in srgb, var(--danger) 12%, var(--surface)); +} +:root[data-glass-theme="dark"] .modal-backdrop { background: rgba(2, 5, 14, .68); } +:root[data-glass-theme="dark"] .modal { background: var(--surface); } +:root[data-glass-theme="dark"] .diff-panel p { color: var(--muted); } +:root[data-glass-theme="dark"] .diff-panel.added { + border-color: color-mix(in srgb, var(--success) 42%, var(--line)); +} diff --git a/apps/web-console/firmware-workbench.html b/apps/web-console/firmware-workbench.html index 60ce069..2f851a9 100644 --- a/apps/web-console/firmware-workbench.html +++ b/apps/web-console/firmware-workbench.html @@ -3,11 +3,12 @@ - - + + 座椅固件开发工作台 · 511 工程 - + + diff --git a/apps/web-console/index.html b/apps/web-console/index.html index 38c2787..e81ffc1 100755 --- a/apps/web-console/index.html +++ b/apps/web-console/index.html @@ -33,7 +33,7 @@ document.documentElement.style.colorScheme = theme; })(); - + @@ -47,7 +47,7 @@ - +
diff --git a/apps/web-console/self-extension.css b/apps/web-console/self-extension.css index e304e19..40e725e 100644 --- a/apps/web-console/self-extension.css +++ b/apps/web-console/self-extension.css @@ -1493,7 +1493,7 @@ button.v2-extension-capability.preview { /* Dialogs ---------------------------------------------------------------- */ .v2-extension-dialog { - width: min(650px, calc(100vw - 40px)); + width: min(780px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); margin: auto; padding: 0; @@ -2307,7 +2307,7 @@ form > .v2-extension-primary { /* GSCU1B TCP runtime controls ------------------------------------------- */ .v2-gscu-tcp-dialog { - width: min(720px, calc(100vw - 30px)); + width: min(960px, calc(100vw - 30px)); } .v2-gscu-status { @@ -2934,9 +2934,9 @@ form > .v2-extension-primary { } .v2-nfc-dialog { - width: min(900px, calc(100vw - 28px)); - max-width: 900px; - max-height: min(860px, calc(100dvh - 28px)); + width: min(1180px, calc(100vw - 28px)); + max-width: 1180px; + max-height: min(900px, calc(100dvh - 28px)); padding: 0; overflow: auto; color: #203d3d; @@ -4596,8 +4596,8 @@ form > .v2-extension-primary { } .v2-pet-settings-dialog { - width: min(760px, calc(100vw - 32px)); - height: min(760px, calc(100dvh - 32px)); + width: min(980px, calc(100vw - 32px)); + height: min(860px, calc(100dvh - 32px)); max-height: calc(100dvh - 32px); overflow: hidden; } diff --git a/apps/web-console/service-worker.js b/apps/web-console/service-worker.js index 741c7d4..06f2eca 100644 --- a/apps/web-console/service-worker.js +++ b/apps/web-console/service-worker.js @@ -1,32 +1,33 @@ -const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"; +const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"; const SHELL_CACHE = `${CACHE_VERSION}-shell`; const RUNTIME_CACHE = `${CACHE_VERSION}-runtime`; const APP_SHELL = [ "/", "/index.html", - "/styles.css?v=dual-seat-23", + "/styles.css?v=dual-seat-24-dialog-size", "/network.js?v=android-pad-2", "/app.js?v=dual-seat-145-n7-dispatch", "/gesture-control.js?v=android-pad-9", "/pwa.js?v=android-pad-3", "/console-v2.css?v=delivery-state-69", "/console-v2.js?v=local-first-77-performance", - "/self-extension.css?v=pet-settings-52", + "/self-extension.css?v=pet-settings-54-dialog-size", "/self-extension.js?v=pet-settings-53-performance", "/speech-input.css?v=sensevoice-7", "/speech-input.js?v=sensevoice-13", "/speech-audio-worklet.js?v=sensevoice-5", "/assistant-chat.css?v=codex-assistant-29", "/assistant-chat.js?v=codex-assistant-34", - "/energy-monitor.css?v=energy-monitor-4", + "/energy-monitor.css?v=energy-monitor-5-dialog-size", "/energy-monitor.js?v=energy-monitor-5-performance", "/ui-consistency.css?v=spatial-ui-8", "/codepen-glass-theme.css?v=creative-cloud-6-performance", "/vue-ui.js?v=vue-presentation-3", - "/firmware-workbench-entry.css?v=1", - "/firmware-workbench-entry.js?v=2", + "/firmware-workbench-entry.css?v=2", + "/firmware-workbench-entry.js?v=3", "/firmware-workbench.html", - "/firmware-workbench.css?v=5", + "/firmware-workbench-theme.js?v=1", + "/firmware-workbench.css?v=6", "/firmware-workbench.js?v=3", "/assets/pets/self-extension-cat.png?v=3", "/assets/pets/self-extension-cat-entrance.png?v=3", diff --git a/apps/web-console/styles.css b/apps/web-console/styles.css index e46fe65..dc7cbcc 100755 --- a/apps/web-console/styles.css +++ b/apps/web-console/styles.css @@ -395,8 +395,9 @@ body.mode-editor-open { } .mode-gallery { - width: min(1080px, calc(100vw - 32px)); - max-height: min(680px, calc(100dvh - 32px)); + width: min(1320px, calc(100vw - 32px)); + height: min(860px, calc(100dvh - 32px)); + max-height: min(860px, calc(100dvh - 32px)); display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto; gap: 12px; @@ -863,7 +864,7 @@ body.mode-editor-open { } .mode-editor { - width: min(760px, calc(100vw - 28px)); + width: min(1040px, calc(100vw - 28px)); height: min(900px, calc(100dvh - 28px)); max-height: calc(100dvh - 28px); display: grid; diff --git a/apps/web-console/vite.config.js b/apps/web-console/vite.config.js index 5f3a5bc..8e837ff 100644 --- a/apps/web-console/vite.config.js +++ b/apps/web-console/vite.config.js @@ -30,6 +30,7 @@ const runtimeFiles = [ "assistant-chat.js", "energy-monitor.js", "firmware-workbench-entry.js", + "firmware-workbench-theme.js", "firmware-workbench.js", "firmware-workbench.html", "styles.css", diff --git a/tests/e2e/test_seat_web_api.py b/tests/e2e/test_seat_web_api.py index 053f8f4..3045a46 100755 --- a/tests/e2e/test_seat_web_api.py +++ b/tests/e2e/test_seat_web_api.py @@ -1017,7 +1017,7 @@ operations: ) as response: extension_script = response.read().decode("utf-8") with self.opener.open( - f"{self.base_url}/self-extension.css?v=pet-settings-52", timeout=3 + f"{self.base_url}/self-extension.css?v=pet-settings-54-dialog-size", timeout=3 ) as response: extension_styles = response.read().decode("utf-8").replace("\r\n", "\n") with self.opener.open( @@ -1029,7 +1029,7 @@ operations: ) as response: energy_script = response.read().decode("utf-8") with self.opener.open( - f"{self.base_url}/energy-monitor.css?v=energy-monitor-4", timeout=3 + f"{self.base_url}/energy-monitor.css?v=energy-monitor-5-dialog-size", timeout=3 ) as response: energy_styles = response.read().decode("utf-8") with self.opener.open( @@ -1385,18 +1385,19 @@ operations: self.assertIn('canvas.addEventListener("webglcontextlost"', app_script) self.assertIn('"cognitive-agent:module-change"', app_script) self.assertIn( - 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"', + 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"', service_worker, ) self.assertIn('/console-v2.css?v=delivery-state-69', service_worker) self.assertIn('/console-v2.js?v=local-first-77-performance', service_worker) self.assertIn('/assistant-chat.css?v=codex-assistant-29', service_worker) self.assertIn('/assistant-chat.js?v=codex-assistant-34', service_worker) - self.assertIn('/energy-monitor.css?v=energy-monitor-4', service_worker) + self.assertIn('/energy-monitor.css?v=energy-monitor-5-dialog-size', service_worker) self.assertIn('/energy-monitor.js?v=energy-monitor-5-performance', service_worker) self.assertIn('"/app.js?v=dual-seat-145-n7-dispatch"', service_worker) - self.assertIn('/firmware-workbench-entry.css?v=1', service_worker) - self.assertIn('/firmware-workbench-entry.js?v=2', service_worker) + self.assertIn('/firmware-workbench-entry.css?v=2', service_worker) + self.assertIn('/firmware-workbench-entry.js?v=3', service_worker) + self.assertIn('/firmware-workbench-theme.js?v=1', service_worker) self.assertIn('/firmware-workbench.html', service_worker) self.assertIn('"/speech-input.js?v=sensevoice-13"', service_worker) self.assertIn('"/speech-input.css?v=sensevoice-7"', service_worker) diff --git a/tests/unit/test_assistant_frontend_contract.py b/tests/unit/test_assistant_frontend_contract.py index 5609cf6..9dee616 100644 --- a/tests/unit/test_assistant_frontend_contract.py +++ b/tests/unit/test_assistant_frontend_contract.py @@ -27,7 +27,7 @@ def test_console_contains_ai_assistant_surface(): def test_codex_assistant_assets_are_versioned_together_in_the_service_worker(): service_worker = (ROOT / "apps/web-console/service-worker.js").read_text(encoding="utf-8") assert ( - 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"' + 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"' in service_worker ) assert '"/assistant-chat.css?v=codex-assistant-29"' in service_worker diff --git a/tests/unit/test_energy_monitor_frontend_contract.py b/tests/unit/test_energy_monitor_frontend_contract.py index 2b47cc6..885a603 100644 --- a/tests/unit/test_energy_monitor_frontend_contract.py +++ b/tests/unit/test_energy_monitor_frontend_contract.py @@ -31,7 +31,7 @@ def test_energy_monitor_assets_are_versioned_and_cached() -> None: service_worker = source("service-worker.js") for asset in ( - "/energy-monitor.css?v=energy-monitor-4", + "/energy-monitor.css?v=energy-monitor-5-dialog-size", "/energy-monitor.js?v=energy-monitor-5-performance", ): assert f'"{asset}"' in service_worker @@ -41,7 +41,7 @@ def test_energy_monitor_assets_are_versioned_and_cached() -> None: "/energy-monitor.js?v=energy-monitor-5-performance" ) assert ( - 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"' + 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"' in service_worker ) diff --git a/tests/unit/test_firmware_workbench_frontend_contract.py b/tests/unit/test_firmware_workbench_frontend_contract.py index 77a9227..1f05926 100644 --- a/tests/unit/test_firmware_workbench_frontend_contract.py +++ b/tests/unit/test_firmware_workbench_frontend_contract.py @@ -51,21 +51,59 @@ def test_workbench_exposes_artifact_actions_and_always_starts_a_new_task() -> No assert "已发布,待车机端下载升级" not in script assert 'id = "firmwareWorkbenchToggle"' in entry assert 'className = "firmware-workbench-layer"' in entry - assert "/firmware-workbench-entry.js?v=2" in index - assert "/firmware-workbench-entry.css?v=1" in index + assert "/firmware-workbench-entry.js?v=3" in index + assert "/firmware-workbench-entry.css?v=2" in index for asset in ( - "/firmware-workbench-entry.css?v=1", - "/firmware-workbench-entry.js?v=2", + "/firmware-workbench-entry.css?v=2", + "/firmware-workbench-entry.js?v=3", "/firmware-workbench.html", - "/firmware-workbench.css?v=5", + "/firmware-workbench-theme.js?v=1", + "/firmware-workbench.css?v=6", "/firmware-workbench.js?v=3", ): assert f'"{asset}"' in worker for runtime_file in ( "firmware-workbench-entry.js", "firmware-workbench-entry.css", + "firmware-workbench-theme.js", "firmware-workbench.html", "firmware-workbench.js", "firmware-workbench.css", ): assert f'"{runtime_file}"' in vite + + +def test_workbench_inherits_live_theme_and_uses_the_larger_dialog_frame() -> None: + html = source("firmware-workbench.html") + entry = source("firmware-workbench-entry.js") + entry_styles = source("firmware-workbench-entry.css") + workbench_styles = source("firmware-workbench.css") + theme = source("firmware-workbench-theme.js") + + assert 'content="light dark"' in html + assert 'id="firmwareWorkbenchThemeColor"' in html + assert '/firmware-workbench-theme.js?v=1' in html + assert 'data-glass-theme="dark"' in workbench_styles + assert 'window.parent?.document?.documentElement?.dataset?.glassTheme' in theme + assert 'event.data?.type !== "cognitive-agent:theme-change"' in theme + assert 'window.addEventListener("cognitive-agent:theme-change"' in entry + assert 'attributeFilter: ["data-glass-theme"]' in entry + assert 'width: min(1480px, 100%);' in entry_styles + assert 'height: min(900px, 100%);' in entry_styles + assert 'width: min(1040px, 100%);' in workbench_styles + assert 'max-height: min(820px, calc(100dvh - 48px));' in workbench_styles + + +def test_peer_dialogs_share_the_expanded_desktop_size_contract() -> None: + gallery = source("styles.css") + energy = source("energy-monitor.css") + extension = source("self-extension.css") + + assert 'width: min(1320px, calc(100vw - 32px));' in gallery + assert 'height: min(860px, calc(100dvh - 32px));' in gallery + assert 'width: min(1480px, 100%);' in energy + assert 'height: min(900px, 100%);' in energy + assert 'width: min(780px, calc(100vw - 32px));' in extension + assert 'width: min(960px, calc(100vw - 30px));' in extension + assert 'width: min(1180px, calc(100vw - 28px));' in extension + assert 'width: min(980px, calc(100vw - 32px));' in extension diff --git a/tests/unit/test_frontend_performance_contract.py b/tests/unit/test_frontend_performance_contract.py index 01ff6c6..5f14273 100644 --- a/tests/unit/test_frontend_performance_contract.py +++ b/tests/unit/test_frontend_performance_contract.py @@ -99,5 +99,5 @@ def test_performance_assets_have_a_new_cache_generation() -> None: ): assert asset in html assert f'"{asset}"' in worker - assert 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"' in worker + assert 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"' in worker assert '"/codepen-glass-theme.css?v=creative-cloud-6-performance"' in worker diff --git a/tests/unit/test_frontend_theme_contract.py b/tests/unit/test_frontend_theme_contract.py index 79458e7..d2ca653 100644 --- a/tests/unit/test_frontend_theme_contract.py +++ b/tests/unit/test_frontend_theme_contract.py @@ -45,16 +45,16 @@ def test_theme_asset_versions_are_consistent_with_the_pwa_shell() -> None: service_worker = source("service-worker.js") for source_asset, cached_asset in ( - ('import "../styles.css"', "/styles.css?v=dual-seat-23"), + ('import "../styles.css"', "/styles.css?v=dual-seat-24-dialog-size"), ('import "../console-v2.css"', "/console-v2.css?v=delivery-state-69"), - ('import "../self-extension.css"', "/self-extension.css?v=pet-settings-52"), + ('import "../self-extension.css"', "/self-extension.css?v=pet-settings-54-dialog-size"), ('import "../speech-input.css"', "/speech-input.css?v=sensevoice-7"), ('import "../codepen-glass-theme.css"', "/codepen-glass-theme.css?v=creative-cloud-6-performance"), ): assert source_asset in main assert f'"{cached_asset}"' in service_worker assert 'import "./styles/design-system.css"' in main - assert 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"' in service_worker + assert 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"' in service_worker def test_reference_glass_theme_covers_the_complete_workspace() -> None: diff --git a/tests/unit/test_vue_frontend_contract.py b/tests/unit/test_vue_frontend_contract.py index 236f916..5bf7ce9 100644 --- a/tests/unit/test_vue_frontend_contract.py +++ b/tests/unit/test_vue_frontend_contract.py @@ -31,7 +31,7 @@ def test_vue_vite_application_is_the_primary_frontend_entry() -> None: assert package["scripts"]["build"] == "vite build" assert 'import vue from "@vitejs/plugin-vue"' in vite assert 'outDir: outputRoot' in vite - assert 'const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge"' in service_worker + assert 'const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme"' in service_worker assert "unpkg.com" not in html assert "cdn.jsdelivr.net" not in html