feat(web-console): unify spatial UI and chat reset

This commit is contained in:
Miayui
2026-09-14 18:48:11 +08:00
parent 58f1a2da42
commit 84a3cd73bb
16 changed files with 333 additions and 86 deletions
+53 -9
View File
@@ -13,15 +13,15 @@ def test_console_contains_ai_assistant_surface():
assert 'aria-label="AI助手对话"' in html
assert 'placeholder="向 AI助手提问或交代工作"' in html
assert 'aria-label="发送消息"' in html
assert 'href="/assistant-chat.css?v=codex-assistant-28"' in html
assert 'src="/assistant-chat.js?v=codex-assistant-32"' in html
assert 'href="/assistant-chat.css?v=codex-assistant-29"' in html
assert 'src="/assistant-chat.js?v=codex-assistant-33"' in html
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-v302"' in service_worker
assert '"/assistant-chat.css?v=codex-assistant-28"' in service_worker
assert '"/assistant-chat.js?v=codex-assistant-32"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v305"' in service_worker
assert '"/assistant-chat.css?v=codex-assistant-29"' in service_worker
assert '"/assistant-chat.js?v=codex-assistant-33"' in service_worker
def test_codex_frontend_uses_one_streaming_endpoint_and_agent_work_events():
@@ -121,7 +121,11 @@ def test_starting_a_new_codex_conversation_rotates_the_conversation_id():
script = (ROOT / "apps/web-console/assistant-chat.js").read_text(encoding="utf-8")
assert 'const CONVERSATION_STORAGE_KEY = "cognitive-agent.conversation-id"' in script
assert "function createConversationId()" in script
assert "sessionStorage.setItem(CONVERSATION_STORAGE_KEY, createConversationId())" in script
assert "const nextConversationId = createConversationId()" in script
assert (
"sessionStorage.setItem(CONVERSATION_STORAGE_KEY, nextConversationId)"
in script
)
def test_assistant_uses_the_shared_top_right_dock_and_opens_by_default():
@@ -137,7 +141,9 @@ def test_assistant_uses_the_shared_top_right_dock_and_opens_by_default():
assert 'trigger.setAttribute("aria-pressed", String(open))' in script
assert 'drawer.toggleAttribute("inert", !open)' in script
assert 'trigger.className = "assistant-drawer-toggle v2-panel-control-button"' in script
assert '($("#v2PanelControlDock") || document.body).append(trigger)' in script
assert 'const panelDock = $("#v2PanelControlDock")' in script
assert "panelDock.insertBefore(trigger, firstRightPanelToggle)" in script
assert "document.body.append(trigger)" in script
assert 'id = "assistantDrawerClose"' not in script
assert "setDrawerOpen(true)" in script
assert 'event.key === "Escape"' in script
@@ -252,8 +258,8 @@ def test_latest_same_name_mode_draft_retires_stale_card_and_lifecycle_clears_con
"async function tryModeProfileDraft", 1
)[0]
new_conversation_flow = assistant.split(
'if (!target?.closest("#newConversation")) return;', 1
)[1].split("}, true);", 1)[0]
"function resetConversation()", 1
)[1].split("function initialize()", 1)[0]
assert "card.dataset.assistantModeName !== nextName" in replace_flow
assert "card.dataset.assistantModeDraft === nextRequestId" in replace_flow
@@ -266,6 +272,32 @@ def test_latest_same_name_mode_draft_retires_stale_card_and_lifecycle_clears_con
assert ".assistant-mode-draft-status.superseded" in css
def test_new_conversation_resets_chat_in_place_and_keeps_panel_order_spatial():
app = (ROOT / "apps/web-console/app.js").read_text(encoding="utf-8")
assistant = (ROOT / "apps/web-console/assistant-chat.js").read_text(
encoding="utf-8"
)
reset_flow = assistant.split("function resetConversation()", 1)[1].split(
"function initialize()", 1
)[0]
app_flow = app.split("function startNewConversation", 1)[1].split(
"window.CognitiveAgentConsole", 1
)[0]
assert 'activeController.abort("new_conversation")' in reset_flow
assert "sessionStorage.removeItem(STORAGE_KEY)" in reset_flow
assert "renderInitialMessages()" in reset_flow
assert "setComposerPending(false)" in reset_flow
assert '"cognitive-agent:new-conversation"' in reset_flow
assert "window.location.reload()" not in app_flow
assert (
'window.addEventListener("cognitive-agent:new-conversation", '
"startNewConversation)"
) in app
assert 'const firstRightPanelToggle = $("[data-panel-toggle]", panelDock)' in assistant
assert "panelDock.insertBefore(trigger, firstRightPanelToggle)" in assistant
def test_assistant_composer_grows_to_a_cap_then_scrolls_its_own_content():
assistant = (ROOT / "apps/web-console/assistant-chat.js").read_text(encoding="utf-8")
css = (ROOT / "apps/web-console/assistant-chat.css").read_text(encoding="utf-8")
@@ -383,6 +415,18 @@ def test_chat_styles_include_accessible_responsive_and_reduced_motion_states():
assert "@media (prefers-reduced-motion: reduce)" in css
def test_dispatched_control_card_spans_the_full_assistant_message_row():
css = (ROOT / "apps/web-console/assistant-chat.css").read_text(encoding="utf-8")
layout = css.split("/* Compact command receipt", 1)[1].split(
"/* The function-mode strip", 1
)[0]
assert "grid-template-columns: 30px minmax(0, 1fr)" in layout
assert "display: contents" in layout
assert "grid-column: 1 / -1" in layout
assert "max-width: none" in layout
def test_assistant_does_not_restore_collapsed_sidebars_and_uses_mobile_overlays():
script = (ROOT / "apps/web-console/assistant-chat.js").read_text(encoding="utf-8")
css = (ROOT / "apps/web-console/assistant-chat.css").read_text(encoding="utf-8")
@@ -35,10 +35,10 @@ def test_energy_monitor_assets_are_versioned_and_cached() -> None:
):
assert asset in html
assert f'"{asset}"' in service_worker
assert html.index("/assistant-chat.js?v=codex-assistant-32") < html.index(
assert html.index("/assistant-chat.js?v=codex-assistant-33") < html.index(
"/energy-monitor.js?v=energy-monitor-4"
)
assert 'const CACHE_VERSION = "cognitive-agent-pad-v302"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v305"' in service_worker
def test_energy_monitor_uses_the_fifth_shared_dock_icon_and_starts_closed() -> None:
+2 -2
View File
@@ -42,13 +42,13 @@ def test_theme_asset_versions_are_consistent_with_the_pwa_shell() -> None:
for asset in (
"/styles.css?v=dual-seat-23",
"/console-v2.css?v=delivery-state-69",
"/self-extension.css?v=pet-settings-49",
"/self-extension.css?v=pet-settings-52",
"/speech-input.css?v=sensevoice-7",
"/codepen-glass-theme.css?v=creative-cloud-2",
):
assert asset in html
assert f'"{asset}"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v302"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v305"' in service_worker
def test_reference_glass_theme_covers_the_complete_workspace() -> None:
+2 -2
View File
@@ -60,8 +60,8 @@ def test_unified_console_exposes_device_id_based_nfc_authorization() -> None:
assert '.v2-nfc-command-list' in styles
assert '.v2-nfc-command-option' in styles
assert '.v2-nfc-select-all' in styles
assert 'self-extension.js?v=pet-settings-49' in html
assert 'self-extension.css?v=pet-settings-49' in html
assert 'self-extension.js?v=pet-settings-52' in html
assert 'self-extension.css?v=pet-settings-52' in html
def test_unified_console_exposes_gscu_tcp_configuration_and_actions() -> None:
@@ -1110,7 +1110,8 @@ def test_interactive_console_uses_one_top_right_icon_dock_for_all_five_panels()
assert 'data-lucide="car-front"' in console
assert 'data-lucide="usb"' in console
assert 'data-lucide="bot-message-square"' in assistant
assert '($("#v2PanelControlDock") || document.body).append(trigger)' in assistant
assert 'const panelDock = $("#v2PanelControlDock")' in assistant
assert "panelDock.insertBefore(trigger, firstRightPanelToggle)" in assistant
assert 'trigger.className = "assistant-drawer-toggle v2-panel-control-button"' in assistant
assert 'trigger.className = "energy-monitor-toggle v2-panel-control-button"' in energy
assert '$("#v2PanelControlDock").append(trigger)' in energy
@@ -12,7 +12,7 @@ def source(name: str) -> str:
def test_spatial_ui_contract_is_loaded_last_and_cached() -> None:
html = source("index.html")
service_worker = source("service-worker.js")
asset = "/ui-consistency.css?v=spatial-ui-4"
asset = "/ui-consistency.css?v=spatial-ui-5"
assert asset in html
assert f'"{asset}"' in service_worker
@@ -25,6 +25,10 @@ def test_same_kind_surfaces_share_geometry_tokens() -> None:
for token in (
"--ui-control-height-compact:",
"--ui-control-height:",
"--ui-font-card-title:",
"--ui-font-section-title:",
"--ui-font-panel-title:",
"--ui-inline-action-width:",
"--ui-radius-control:",
"--ui-radius-item:",
"--ui-radius-section:",
@@ -59,6 +63,7 @@ def test_same_kind_controls_share_sizes_and_focus_treatment() -> None:
"#v2PanelControlDock > .v2-panel-control-button",
".v2-mode-rail .mode-rail-actions > button",
".v2-device-adjust-toggle",
".v2-pet-settings-launch",
".v2-extension-nfc-launch",
".energy-trend-tabs button",
".mode-gallery-close",
@@ -71,6 +76,44 @@ def test_same_kind_controls_share_sizes_and_focus_treatment() -> None:
assert "outline: none" in styles
def test_panel_titles_and_extension_actions_share_type_and_size_tokens() -> None:
styles = source("ui-consistency.css")
for selector in (
".v2-operation-heading h2",
".joint-twin-shell .twin-heading h3",
".v2-device-sync-board > header h3",
".v2-extension-sync-heading h3",
".v2-device-card-focus strong",
".v2-nfc-inline strong",
".v2-extension-gateway strong",
):
assert selector in styles
assert "font-size: var(--ui-font-panel-title) !important" in styles
assert "font-size: var(--ui-font-card-title) !important" in styles
assert "grid-template-columns: repeat(2, minmax(0, 1fr))" in styles
assert "width: var(--ui-inline-action-width)" in styles
def test_pet_and_tcp_dialog_controls_keep_accessible_aligned_layout() -> None:
styles = source("self-extension.css")
extension = source("self-extension.js")
tcp_form = styles.split(".v2-gscu-config-form {", 1)[1].split("}", 1)[0]
tcp_submit = styles.split(
".v2-gscu-config-form > .v2-extension-primary {", 1
)[1].split("}", 1)[0]
assert ".v2-extension-dialog .v2-pet-card-region > header > button" in styles
assert "min-width: 104px" in styles
assert "align-items: end" in tcp_form
assert "height: 40px" in tcp_submit
assert "margin: 0" in tcp_submit
assert 'id="extensionGscuTcpHostHint"' in extension
assert 'id="extensionGscuTcpPortHint"' in extension
assert 'class="visually-hidden" id="extensionPetSettingsDescription"' in extension
def test_compact_sidebar_overrides_cannot_break_shared_geometry() -> None:
styles = source("ui-consistency.css")
+3 -3
View File
@@ -18,14 +18,14 @@ def test_vue_presentation_assets_are_local_ordered_and_cached() -> None:
presentation = "/vue-ui.js?v=vue-presentation-3"
assert html.index(runtime) < html.index(presentation) < html.index(
"/app.js?v=dual-seat-139"
"/app.js?v=dual-seat-140"
)
assert html.index(presentation) < html.index(
"/assistant-chat.js?v=codex-assistant-32"
"/assistant-chat.js?v=codex-assistant-33"
)
assert f'"{runtime}"' in service_worker
assert f'"{presentation}"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v302"' in service_worker
assert 'const CACHE_VERSION = "cognitive-agent-pad-v305"' in service_worker
assert "unpkg.com" not in html
assert "cdn.jsdelivr.net" not in html