Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export const MessageResponseModelBadge: FC<{ className?: string }> = ({
return (
<span
className={cn(
"aui-response-model-badge inline-flex min-h-5 max-w-full items-center text-muted-foreground/80 text-xs font-medium leading-5 opacity-0 transition-opacity duration-150 group-hover/assistant-message:opacity-100 group-focus-within/assistant-message:opacity-100",
"aui-response-model-badge pointer-events-none relative inline-flex min-h-5 max-w-full cursor-text select-text items-center text-muted-foreground/80 text-xs font-medium leading-5 opacity-0 transition-opacity duration-150 after:absolute after:inset-x-0 after:top-full after:h-1 after:content-[''] hover:opacity-100 group-hover/assistant-message:pointer-events-auto group-hover/assistant-message:opacity-100 group-focus-within/assistant-message:pointer-events-auto group-focus-within/assistant-message:opacity-100",
className,
)}
title={providerLabel ? `${modelLabel} - ${providerLabel}` : modelLabel}
Expand Down
8 changes: 2 additions & 6 deletions studio/frontend/src/components/assistant-ui/reasoning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
/* eslint-disable react-refresh/only-export-components */

import { MarkdownText } from "@/components/assistant-ui/markdown-text";
import { MessageResponseModelBadge } from "@/components/assistant-ui/message-response-details-sheet";
import {
Collapsible,
CollapsibleContent,
Expand Down Expand Up @@ -393,15 +392,12 @@ const ReasoningGroupImpl: ReasoningGroupComponent = ({
>
<div className="flex min-w-0 items-center gap-2">
<ReasoningTrigger
className="min-w-0 flex-none"
className="min-w-0 flex-1"
active={isReasoningStreaming}
// Prefer server timing when available.
duration={persistedDuration || duration}
/>
<span className="hidden min-w-0 max-w-[12rem] group-hover/assistant-message:inline-flex group-focus-within/assistant-message:inline-flex sm:max-w-[16rem]">
<MessageResponseModelBadge className="min-w-0" />
</span>
<div className="ml-auto flex w-16 shrink-0 justify-end">
<div className="flex w-16 shrink-0 justify-end">
{isOpen && !isReasoningStreaming && (
<ReasoningCopyButton startIndex={startIndex} endIndex={endIndex} />
)}
Expand Down
11 changes: 3 additions & 8 deletions studio/frontend/src/components/assistant-ui/thread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3569,9 +3569,6 @@ const AssistantMessage: FC = () => {
const aui = useAui();
const messageId = useAuiState(({ message }) => message.id);
const messageContent = useAuiState(({ message }) => message.content);
const hasReasoningParts = useAuiState(({ message }) =>
message.parts.some((part) => part.type === "reasoning"),
);
const incognito = useChatRuntimeStore((s) => s.incognito);

// Use global store for editing state to ensure a single source of truth
Expand Down Expand Up @@ -3657,11 +3654,9 @@ const AssistantMessage: FC = () => {
</div>
) : (
<>
{!hasReasoningParts ? (
<div className="pointer-events-none relative h-0 min-w-0">
<MessageResponseModelBadge className="absolute -top-6 left-0 max-w-[min(22rem,100%)]" />
</div>
) : null}
<div className="pointer-events-none relative h-0 min-w-0">
<MessageResponseModelBadge className="absolute -top-6 left-0 max-w-[min(22rem,100%)]" />
</div>
<GeneratingIndicator />
<CancelledIndicator />
<DiffusionCanvas />
Expand Down
27 changes: 17 additions & 10 deletions tests/studio/test_chat_response_details_ui_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_response_details_sheet_uses_unsloth_sheet_and_key_sections():
assert f'label="{field}"' in src


def test_response_model_chip_is_user_configurable_and_rendered_in_metadata_rows():
def test_response_model_badge_is_user_configurable_and_rendered_once_per_message():
prefs_src = CHAT_PREFS_TS.read_text()
chat_tab_src = CHAT_TAB_TSX.read_text()
thread_src = THREAD_TSX.read_text()
Expand All @@ -55,17 +55,24 @@ def test_response_model_chip_is_user_configurable_and_rendered_in_metadata_rows(
assert "showResponseModel: saved?.showResponseModel ?? false" in prefs_src
assert "Show response model" in chat_tab_src
assert "setShowResponseModel" in chat_tab_src
assert "aui-response-model-badge inline-flex min-h-5" in DETAILS_TSX.read_text()
assert "leading-5" in DETAILS_TSX.read_text()
assert "group-hover/assistant-message:opacity-100" in DETAILS_TSX.read_text()
assert "MessageResponseModelBadge" in thread_src
assert "hasReasoningParts" in thread_src
details_src = DETAILS_TSX.read_text()
assert (
"aui-response-model-badge pointer-events-none relative inline-flex min-h-5" in details_src
)
assert "cursor-text select-text" in details_src
assert "leading-5" in details_src
assert "after:top-full after:h-1" in details_src
assert "hover:opacity-100" in details_src
assert "group-hover/assistant-message:opacity-100" in details_src
# Pointer events gated behind hover/focus so the hidden badge stays inert when idle.
assert "group-hover/assistant-message:pointer-events-auto" in details_src
assert "group-focus-within/assistant-message:pointer-events-auto" in details_src
assert thread_src.count("<MessageResponseModelBadge") == 1
assert "hasReasoningParts" not in thread_src
assert "group/assistant-message aui-assistant-message-root" in thread_src
assert "pointer-events-none relative h-0" in thread_src
assert "MessageResponseModelBadge" in reasoning_src
assert 'className="min-w-0 flex-none"' in reasoning_src
assert "hidden min-w-0 max-w-[12rem]" in reasoning_src
assert "group-hover/assistant-message:inline-flex" in reasoning_src
assert "MessageResponseModelBadge" not in reasoning_src
assert 'className="min-w-0 flex-1"' in reasoning_src


def test_response_details_metadata_is_persisted_without_backend_schema_change():
Expand Down
Loading