@flamingo-stack/openframe-frontend-core 0.0.685-snapshot.20260929164409 → 0.0.685
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/dist/{chunk-DL67S7H4.cjs → chunk-5LJZPJHX.cjs} +59 -59
- package/dist/{chunk-DL67S7H4.cjs.map → chunk-5LJZPJHX.cjs.map} +1 -1
- package/dist/{chunk-IZ3WKG62.js → chunk-65KTXRBY.js} +6 -6
- package/dist/{chunk-IBKMIJ7Y.js → chunk-7XF63THA.js} +6 -6
- package/dist/{chunk-SI77HF4U.cjs → chunk-A3CSQB4A.cjs} +805 -1247
- package/dist/chunk-A3CSQB4A.cjs.map +1 -0
- package/dist/{chunk-5MUR43QD.cjs → chunk-B25CF3PO.cjs} +30 -30
- package/dist/{chunk-5MUR43QD.cjs.map → chunk-B25CF3PO.cjs.map} +1 -1
- package/dist/{chunk-32KBPEF7.js → chunk-B32YLOYQ.js} +4 -4
- package/dist/{chunk-OBLED7JY.cjs → chunk-B5N3AHPG.cjs} +81 -81
- package/dist/{chunk-OBLED7JY.cjs.map → chunk-B5N3AHPG.cjs.map} +1 -1
- package/dist/{chunk-QSRUYHTW.js → chunk-BZ2XOEHW.js} +3 -3
- package/dist/{chunk-XATA4OVO.cjs → chunk-C3B36OYZ.cjs} +3 -3
- package/dist/{chunk-XATA4OVO.cjs.map → chunk-C3B36OYZ.cjs.map} +1 -1
- package/dist/{chunk-V26TKJ4Z.cjs → chunk-CMQXPD5C.cjs} +28 -28
- package/dist/{chunk-V26TKJ4Z.cjs.map → chunk-CMQXPD5C.cjs.map} +1 -1
- package/dist/{chunk-QNWQQ4RT.cjs → chunk-DQOQ3KTP.cjs} +73 -78
- package/dist/chunk-DQOQ3KTP.cjs.map +1 -0
- package/dist/{chunk-5HVGOIAE.cjs → chunk-DWXWEGGO.cjs} +22 -22
- package/dist/{chunk-5HVGOIAE.cjs.map → chunk-DWXWEGGO.cjs.map} +1 -1
- package/dist/{chunk-6CMH53MP.cjs → chunk-EFBMNVSH.cjs} +15 -15
- package/dist/{chunk-6CMH53MP.cjs.map → chunk-EFBMNVSH.cjs.map} +1 -1
- package/dist/{chunk-DDFYKF3B.js → chunk-GHLGXFNU.js} +3 -3
- package/dist/{chunk-VDV7K5TD.js → chunk-GXV6UEVY.js} +3 -3
- package/dist/{chunk-AEAFQTVR.cjs → chunk-HMXUOLZR.cjs} +20 -20
- package/dist/{chunk-AEAFQTVR.cjs.map → chunk-HMXUOLZR.cjs.map} +1 -1
- package/dist/{chunk-2OD2PPNO.cjs → chunk-K2HZG4RM.cjs} +32 -32
- package/dist/{chunk-2OD2PPNO.cjs.map → chunk-K2HZG4RM.cjs.map} +1 -1
- package/dist/{chunk-JNDHXL2D.cjs → chunk-M4HYIXP6.cjs} +383 -384
- package/dist/chunk-M4HYIXP6.cjs.map +1 -0
- package/dist/{chunk-KTWJKCUB.js → chunk-N4Z6X5BV.js} +5 -5
- package/dist/{chunk-T2RHI676.js → chunk-O7LOZW4R.js} +5 -5
- package/dist/{chunk-ZHYYGIAI.cjs → chunk-P2ASEPA2.cjs} +6 -6
- package/dist/{chunk-ZHYYGIAI.cjs.map → chunk-P2ASEPA2.cjs.map} +1 -1
- package/dist/{chunk-CHRDLXXX.js → chunk-PSQKD6ZN.js} +3 -3
- package/dist/{chunk-GSJR33UP.cjs → chunk-QHLJSB2J.cjs} +12 -12
- package/dist/{chunk-GSJR33UP.cjs.map → chunk-QHLJSB2J.cjs.map} +1 -1
- package/dist/{chunk-CFL3EW4V.cjs → chunk-T4DUTP5C.cjs} +5 -5
- package/dist/{chunk-CFL3EW4V.cjs.map → chunk-T4DUTP5C.cjs.map} +1 -1
- package/dist/{chunk-22RSJ57Z.js → chunk-T6KWNJDW.js} +465 -470
- package/dist/chunk-T6KWNJDW.js.map +1 -0
- package/dist/{chunk-2FGFB2HY.cjs → chunk-TJI5V5BR.cjs} +7 -7
- package/dist/{chunk-2FGFB2HY.cjs.map → chunk-TJI5V5BR.cjs.map} +1 -1
- package/dist/{chunk-HLEXYTOE.js → chunk-TUG7IT6H.js} +2 -2
- package/dist/{chunk-DWCVA6XT.cjs → chunk-U3IXG7TR.cjs} +33 -33
- package/dist/{chunk-DWCVA6XT.cjs.map → chunk-U3IXG7TR.cjs.map} +1 -1
- package/dist/{chunk-WJ5XN4AL.js → chunk-UT333EOT.js} +4 -4
- package/dist/{chunk-OTV4W3YD.js → chunk-VDPCK437.js} +5 -6
- package/dist/{chunk-OTV4W3YD.js.map → chunk-VDPCK437.js.map} +1 -1
- package/dist/{chunk-5GK7TU2Q.js → chunk-WJK2EETW.js} +2 -2
- package/dist/{chunk-YPXXXX6R.js → chunk-XGX6JSEU.js} +1644 -2086
- package/dist/chunk-XGX6JSEU.js.map +1 -0
- package/dist/{chunk-XODE4YTG.js → chunk-XW7MUIW4.js} +3 -3
- package/dist/{chunk-N74MQ4HQ.js → chunk-Y7ZYOQNB.js} +3 -3
- package/dist/{chunk-2NUB5EMG.cjs → chunk-YCTVLN47.cjs} +10 -10
- package/dist/{chunk-2NUB5EMG.cjs.map → chunk-YCTVLN47.cjs.map} +1 -1
- package/dist/{chunk-TILC52ZF.js → chunk-ZF4Z36G4.js} +7 -7
- package/dist/components/case-studies/index.cjs +16 -16
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/ai-assistant-info.d.ts.map +1 -1
- package/dist/components/chat/approval-request-message.d.ts.map +1 -1
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/error-message-display.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +3 -21
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +0 -6
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +2 -20
- package/dist/components/chat/msp-organization-card.d.ts +1 -7
- package/dist/components/chat/msp-organization-card.d.ts.map +1 -1
- package/dist/components/chat/types/chat.types.d.ts +0 -13
- package/dist/components/chat/types/chat.types.d.ts.map +1 -1
- package/dist/components/chat/types/component.types.d.ts +1 -20
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +8 -8
- package/dist/components/docs/index.js +7 -7
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +5 -5
- package/dist/components/faq/index.js +4 -4
- package/dist/components/features/index.cjs +4 -4
- package/dist/components/features/index.js +3 -3
- package/dist/components/help-center-pages/index.cjs +91 -91
- package/dist/components/help-center-pages/index.js +15 -15
- package/dist/components/index.cjs +55 -73
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +15 -33
- package/dist/components/index.js.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +41 -41
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +7 -7
- package/dist/components/navigation/index.js +6 -6
- package/dist/components/onboarding-guides/index.cjs +7 -7
- package/dist/components/onboarding-guides/index.js +6 -6
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +8 -8
- package/dist/components/tickets/index.js +7 -7
- package/dist/components/ui/avatar-stack.d.ts +1 -5
- package/dist/components/ui/avatar-stack.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +4 -22
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +3 -21
- package/dist/components/ui/reopen-ticket-request-modal.d.ts +1 -4
- package/dist/components/ui/reopen-ticket-request-modal.d.ts.map +1 -1
- package/dist/index.cjs +9 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/ai-assistant-info.tsx +1 -7
- package/src/components/chat/approval-request-message.tsx +1 -6
- package/src/components/chat/chat-input.tsx +1 -26
- package/src/components/chat/chat-message-enhanced.tsx +142 -180
- package/src/components/chat/chat-message-list.tsx +164 -169
- package/src/components/chat/error-message-display.tsx +3 -21
- package/src/components/chat/index.ts +0 -6
- package/src/components/chat/msp-organization-card.tsx +0 -35
- package/src/components/chat/types/chat.types.ts +0 -15
- package/src/components/chat/types/component.types.ts +0 -20
- package/src/components/ui/avatar-stack.tsx +5 -15
- package/src/components/ui/reopen-ticket-request-modal.tsx +2 -6
- package/src/styles/ods-colors.css +0 -10
- package/src/styles/ods-effects.css +0 -13
- package/dist/chunk-22RSJ57Z.js.map +0 -1
- package/dist/chunk-JNDHXL2D.cjs.map +0 -1
- package/dist/chunk-QNWQQ4RT.cjs.map +0 -1
- package/dist/chunk-SI77HF4U.cjs.map +0 -1
- package/dist/chunk-YPXXXX6R.js.map +0 -1
- package/dist/components/chat/chat-appearance-context.d.ts +0 -9
- package/dist/components/chat/chat-appearance-context.d.ts.map +0 -1
- package/dist/components/chat/chat-nav-sidebar.d.ts +0 -50
- package/dist/components/chat/chat-nav-sidebar.d.ts.map +0 -1
- package/dist/components/chat/chat-top-navigation.d.ts +0 -29
- package/dist/components/chat/chat-top-navigation.d.ts.map +0 -1
- package/dist/components/chat/onboarding-carousel.d.ts +0 -29
- package/dist/components/chat/onboarding-carousel.d.ts.map +0 -1
- package/dist/components/chat/system-event-message.d.ts +0 -14
- package/dist/components/chat/system-event-message.d.ts.map +0 -1
- package/src/components/chat/__tests__/chat-appearance.test.tsx +0 -79
- package/src/components/chat/__tests__/onboarding-carousel.test.tsx +0 -56
- package/src/components/chat/chat-appearance-context.tsx +0 -15
- package/src/components/chat/chat-nav-sidebar.tsx +0 -163
- package/src/components/chat/chat-top-navigation.tsx +0 -109
- package/src/components/chat/onboarding-carousel.tsx +0 -162
- package/src/components/chat/system-event-message.tsx +0 -54
- package/src/components/ui/__tests__/avatar-stack.test.tsx +0 -25
- package/src/stories/FaeLayoutV2.stories.tsx +0 -150
- package/src/stories/FaeOnboardingV2.stories.tsx +0 -68
- package/src/stories/FaeThreadV2.stories.tsx +0 -192
- package/src/stories/fae-brand-decorator.tsx +0 -28
- /package/dist/{chunk-IZ3WKG62.js.map → chunk-65KTXRBY.js.map} +0 -0
- /package/dist/{chunk-IBKMIJ7Y.js.map → chunk-7XF63THA.js.map} +0 -0
- /package/dist/{chunk-32KBPEF7.js.map → chunk-B32YLOYQ.js.map} +0 -0
- /package/dist/{chunk-QSRUYHTW.js.map → chunk-BZ2XOEHW.js.map} +0 -0
- /package/dist/{chunk-DDFYKF3B.js.map → chunk-GHLGXFNU.js.map} +0 -0
- /package/dist/{chunk-VDV7K5TD.js.map → chunk-GXV6UEVY.js.map} +0 -0
- /package/dist/{chunk-KTWJKCUB.js.map → chunk-N4Z6X5BV.js.map} +0 -0
- /package/dist/{chunk-T2RHI676.js.map → chunk-O7LOZW4R.js.map} +0 -0
- /package/dist/{chunk-CHRDLXXX.js.map → chunk-PSQKD6ZN.js.map} +0 -0
- /package/dist/{chunk-HLEXYTOE.js.map → chunk-TUG7IT6H.js.map} +0 -0
- /package/dist/{chunk-WJ5XN4AL.js.map → chunk-UT333EOT.js.map} +0 -0
- /package/dist/{chunk-5GK7TU2Q.js.map → chunk-WJK2EETW.js.map} +0 -0
- /package/dist/{chunk-XODE4YTG.js.map → chunk-XW7MUIW4.js.map} +0 -0
- /package/dist/{chunk-N74MQ4HQ.js.map → chunk-Y7ZYOQNB.js.map} +0 -0
- /package/dist/{chunk-TILC52ZF.js.map → chunk-ZF4Z36G4.js.map} +0 -0
|
@@ -16,12 +16,10 @@ import {
|
|
|
16
16
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
17
17
|
import { cn } from '../../utils/cn';
|
|
18
18
|
import { Send01Icon, StopCircleIcon } from '../icons-v2-generated';
|
|
19
|
-
import { AvatarStack } from '../ui/avatar-stack';
|
|
20
19
|
import { Tag } from '../ui/tag';
|
|
21
20
|
import { ChatTypingIndicator } from './chat-typing-indicator';
|
|
22
21
|
import { SlashCommandSuggestions } from './slash-command-suggestions';
|
|
23
22
|
import type { ChatInputProps, ChatInputRef, MentionMeta, SlashCommandSummary } from './types';
|
|
24
|
-
import { CHAT_APPEARANCE } from './types/chat.types';
|
|
25
23
|
|
|
26
24
|
/** SHARED with `lib/config/slash-commands-config.ts` AND the chat-route slash
|
|
27
25
|
* dispatch parser. Keep all three in sync. */
|
|
@@ -166,9 +164,6 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
166
164
|
onStop,
|
|
167
165
|
sending = false,
|
|
168
166
|
awaitingResponse = false,
|
|
169
|
-
awaitingTeam,
|
|
170
|
-
awaitingTeamCount,
|
|
171
|
-
appearance = CHAT_APPEARANCE.CLASSIC,
|
|
172
167
|
placeholder = 'Enter your Request...',
|
|
173
168
|
reserveAvatarOffset: _reserveAvatarOffset,
|
|
174
169
|
disabled = false,
|
|
@@ -565,31 +560,11 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
565
560
|
className,
|
|
566
561
|
)}
|
|
567
562
|
>
|
|
568
|
-
{awaitingResponse
|
|
563
|
+
{awaitingResponse ? (
|
|
569
564
|
<div className="relative flex items-center justify-center gap-[var(--spacing-system-xs)] rounded-md border border-ods-border bg-ods-card px-[var(--spacing-system-s)] py-[var(--spacing-system-s)] transition-colors">
|
|
570
565
|
<ChatTypingIndicator size="sm" dotClassName="bg-ods-text-primary" />
|
|
571
566
|
<p className="text-ods-text-secondary text-h4">Waiting for Technician Response</p>
|
|
572
567
|
</div>
|
|
573
|
-
) : awaitingResponse ? (
|
|
574
|
-
// Hand-off bar (fae chat v2): who has the conversation now, and that a
|
|
575
|
-
// reply is on its way. Same 48px height as the editor row it replaces,
|
|
576
|
-
// so the thread above does not jump when the chat is handed off.
|
|
577
|
-
<div
|
|
578
|
-
role="status"
|
|
579
|
-
className="flex min-h-11 w-full items-center justify-center gap-[var(--spacing-system-xs)] rounded-md border border-ods-border bg-ods-bg p-[var(--spacing-system-sf)] md:min-h-12"
|
|
580
|
-
>
|
|
581
|
-
{awaitingTeam && awaitingTeam.length > 0 && (
|
|
582
|
-
<AvatarStack
|
|
583
|
-
people={awaitingTeam}
|
|
584
|
-
total={awaitingTeamCount}
|
|
585
|
-
size="xs"
|
|
586
|
-
ringClassName="ring-ods-bg"
|
|
587
|
-
label="Technicians"
|
|
588
|
-
/>
|
|
589
|
-
)}
|
|
590
|
-
<p className="min-w-0 truncate text-ods-text-primary text-h4">Handed off to your technical support team</p>
|
|
591
|
-
<ChatTypingIndicator size="sm" dotClassName="bg-ods-text-secondary" />
|
|
592
|
-
</div>
|
|
593
568
|
) : (
|
|
594
569
|
<div className="relative">
|
|
595
570
|
<SlashCommandSuggestions
|
|
@@ -11,7 +11,6 @@ import { SquareAvatar } from '../ui/square-avatar';
|
|
|
11
11
|
import { ApprovalBatchMessage } from './approval-batch-message';
|
|
12
12
|
import { ApprovalRequestMessage } from './approval-request-message';
|
|
13
13
|
import { AskDisplay } from './ask-display';
|
|
14
|
-
import { ChatAppearanceContext, useChatAppearance } from './chat-appearance-context';
|
|
15
14
|
import { ChatContextChipStrip } from './chat-context-picker';
|
|
16
15
|
import type { ChatRef } from './chat-ref.types';
|
|
17
16
|
import { ContextCompactionDisplay } from './context-compaction-display';
|
|
@@ -21,13 +20,11 @@ import { EscalationOfferMessage } from './escalation-offer-message';
|
|
|
21
20
|
import { remarkCardLinks } from './remark-card-links';
|
|
22
21
|
import { remarkMentionChips } from './remark-mention-chips';
|
|
23
22
|
import { remarkStripCitations } from './remark-strip-citations';
|
|
24
|
-
import { SystemEventMessage } from './system-event-message';
|
|
25
23
|
import { ThinkingDisplay } from './thinking-display';
|
|
26
24
|
import { TicketEscalatedMessage } from './ticket-escalated-message';
|
|
27
25
|
import { TicketEventMessage } from './ticket-event-message';
|
|
28
26
|
import { ToolExecutionDisplay } from './tool-execution-display';
|
|
29
27
|
import type { AskSegment, MessageSegment, MessageContent, ChatMessageEnhancedProps } from './types';
|
|
30
|
-
import { CHAT_APPEARANCE } from './types/chat.types';
|
|
31
28
|
|
|
32
29
|
/** Inline `@marker:id` mention token in the message body (sibling of the
|
|
33
30
|
* `[card://]` grammar) — used to filter out items rendered inline from the
|
|
@@ -97,7 +94,6 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
97
94
|
showAvatar = true,
|
|
98
95
|
assistantType,
|
|
99
96
|
approvalVariant,
|
|
100
|
-
appearance: appearanceProp,
|
|
101
97
|
authorType: authorTypeProp,
|
|
102
98
|
assistantIcon,
|
|
103
99
|
contextItems,
|
|
@@ -114,9 +110,6 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
114
110
|
) => {
|
|
115
111
|
const isUser = role === 'user';
|
|
116
112
|
const isError = role === 'error';
|
|
117
|
-
const inheritedAppearance = useChatAppearance();
|
|
118
|
-
const appearance = appearanceProp ?? inheritedAppearance;
|
|
119
|
-
const isV2 = appearance === CHAT_APPEARANCE.V2;
|
|
120
113
|
const authorType = authorTypeProp ?? (isUser ? 'user' : assistantType === 'mingo' ? 'mingo' : 'fae');
|
|
121
114
|
|
|
122
115
|
// Inline-card rendering uses a HOST-PROVIDED `renderEntityCard` function
|
|
@@ -525,8 +518,7 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
525
518
|
// (passing pre-joined initials like "PS" would collapse to one letter,
|
|
526
519
|
// since getFirstLastInitials treats it as a single word).
|
|
527
520
|
fallback: displayName,
|
|
528
|
-
|
|
529
|
-
size: isV2 ? ('xs' as const) : ('sm' as const),
|
|
521
|
+
size: 'sm' as const,
|
|
530
522
|
variant: 'round' as const,
|
|
531
523
|
// User avatar: compact 20×20 with 2px padding and a subtle gray fill
|
|
532
524
|
// (`bg-ods-card`) so the `border-ods-border` ring stays visible — the
|
|
@@ -544,32 +536,9 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
544
536
|
|
|
545
537
|
const isSystem = authorType === 'system';
|
|
546
538
|
|
|
547
|
-
// v2 draws a system line (e.g. a technician joining) as an in-thread
|
|
548
|
-
// receipt card rather than as an author row with no body.
|
|
549
|
-
if (isV2 && isSystem && name) {
|
|
550
|
-
return (
|
|
551
|
-
<div ref={ref} className={cn('relative py-[calc(var(--spacing-system-m)/2)]', className)} {...props}>
|
|
552
|
-
<ChatAppearanceContext.Provider value={appearance}>
|
|
553
|
-
<SystemEventMessage text={name} timestamp={timestamp} />
|
|
554
|
-
</ChatAppearanceContext.Provider>
|
|
555
|
-
</div>
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
539
|
return (
|
|
560
|
-
<
|
|
561
|
-
|
|
562
|
-
ref={ref}
|
|
563
|
-
className={cn(
|
|
564
|
-
'relative',
|
|
565
|
-
// v2 spaces messages 16px apart (spacing-system-m), split across the
|
|
566
|
-
// two neighbours' padding so blocks outside a row keep the rhythm.
|
|
567
|
-
isV2 ? 'py-[calc(var(--spacing-system-m)/2)]' : 'py-[var(--spacing-system-s)]',
|
|
568
|
-
className,
|
|
569
|
-
)}
|
|
570
|
-
{...props}
|
|
571
|
-
>
|
|
572
|
-
{/* Message Content — full panel width.
|
|
540
|
+
<div ref={ref} className={cn('relative py-[var(--spacing-system-s)]', className)} {...props}>
|
|
541
|
+
{/* Message Content — full panel width.
|
|
573
542
|
Avatar is INLINE in the name row below (2025-2026 chat
|
|
574
543
|
pattern — Claude.ai, ChatGPT, Gemini, Perplexity).
|
|
575
544
|
Legacy hanging-avatar layout (`absolute -left-16`) wasted
|
|
@@ -583,8 +552,8 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
583
552
|
layout per drawer-resize frame in Safari / the desktop WKWebView
|
|
584
553
|
vs ~9ms as grid (Chrome: ~2ms either way). Same gap and stretch,
|
|
585
554
|
no margin collapsing — visually identical. */}
|
|
586
|
-
|
|
587
|
-
|
|
555
|
+
<div className="grid min-w-0 grid-cols-1 gap-[var(--spacing-system-xxs)]">
|
|
556
|
+
{/* Avatar + Name + Timestamp Row.
|
|
588
557
|
Sizing rationale (per design-token measurements):
|
|
589
558
|
- Name uses `text-h3` = 14px mobile / 18px desktop.
|
|
590
559
|
- Avatar uses `SquareAvatar size="sm"` = 32px — the
|
|
@@ -600,161 +569,155 @@ const ChatMessageEnhanced = forwardRef<HTMLDivElement, ChatMessageEnhancedProps>
|
|
|
600
569
|
inside via `flex items-center justify-center` — they
|
|
601
570
|
should be sized at ~50-60% of the wrapper (h-4 w-4 =
|
|
602
571
|
16px works well for a 32px circle). */}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
'flex items-center',
|
|
606
|
-
isV2 ? 'gap-[var(--spacing-system-xxs)]' : 'gap-[var(--spacing-system-xs)]',
|
|
607
|
-
)}
|
|
608
|
-
>
|
|
609
|
-
{/* Avatar rules:
|
|
572
|
+
<div className="flex items-center gap-[var(--spacing-system-xs)]">
|
|
573
|
+
{/* Avatar rules:
|
|
610
574
|
- Assistant/Fae always show an avatar — host brand icon when no
|
|
611
575
|
image is supplied, else the filled SquareAvatar.
|
|
612
576
|
- User shows the SquareAvatar ONLY when an avatar image actually
|
|
613
577
|
arrived. With no user avatar we hide the block entirely (just
|
|
614
578
|
the name), instead of an initials placeholder. TEMPORARY —
|
|
615
579
|
restore the user placeholder when user avatars ship. */}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
580
|
+
{showAvatar &&
|
|
581
|
+
!isSystem &&
|
|
582
|
+
!(isUser && !avatar) &&
|
|
583
|
+
(!isUser && assistantIcon && !avatar ? (
|
|
584
|
+
// Host-supplied brand icon (e.g. Mingo): render it directly,
|
|
585
|
+
// no filled pill — the icon carries its own brand accent.
|
|
586
|
+
<div className="flex flex-shrink-0 items-center justify-center">{assistantIcon}</div>
|
|
587
|
+
) : (
|
|
588
|
+
<SquareAvatar {...avatarProps} />
|
|
589
|
+
))}
|
|
590
|
+
<span
|
|
591
|
+
className={cn(
|
|
592
|
+
'flex-1 !font-mono !font-medium text-h3',
|
|
593
|
+
authorType === 'system'
|
|
594
|
+
? 'text-ods-open-yellow'
|
|
595
|
+
: authorType === 'admin'
|
|
630
596
|
? 'text-ods-open-yellow'
|
|
631
|
-
: authorType === '
|
|
632
|
-
? 'text-ods-
|
|
633
|
-
: authorType === '
|
|
634
|
-
? 'text-ods-flamingo-
|
|
635
|
-
:
|
|
636
|
-
? 'text-ods-flamingo-pink'
|
|
637
|
-
: 'text-ods-text-secondary',
|
|
638
|
-
)}
|
|
639
|
-
>
|
|
640
|
-
{name || (isUser ? 'User' : assistantType === 'mingo' ? 'Mingo' : 'Fae')}
|
|
641
|
-
{!isSystem && !isV2 && ':'}
|
|
642
|
-
</span>
|
|
643
|
-
{timestamp && (
|
|
644
|
-
<span className="shrink-0 whitespace-nowrap text-ods-text-secondary text-h6">
|
|
645
|
-
{formatMessageTimestamp(timestamp)}
|
|
646
|
-
</span>
|
|
597
|
+
: authorType === 'mingo'
|
|
598
|
+
? 'text-ods-flamingo-cyan'
|
|
599
|
+
: authorType === 'fae'
|
|
600
|
+
? 'text-ods-flamingo-pink'
|
|
601
|
+
: 'text-ods-text-secondary',
|
|
647
602
|
)}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
// actively streaming segment: last segment of a message that
|
|
657
|
-
// is still typing. On completion `isTyping` flips false and
|
|
658
|
-
// the engine does one authoritative whole-document parse.
|
|
659
|
-
const segmentIsStreaming = index === segments.length - 1 && !!isTyping;
|
|
660
|
-
if (segment.type === 'text') {
|
|
661
|
-
return (
|
|
662
|
-
<div
|
|
663
|
-
key={index}
|
|
664
|
-
className={cn(
|
|
665
|
-
'w-full min-w-0 break-words text-h4',
|
|
666
|
-
isError ? 'text-ods-error' : 'text-ods-text-primary',
|
|
667
|
-
)}
|
|
668
|
-
>
|
|
669
|
-
{renderSegmentBody(index, segment.text, segmentIsStreaming)}
|
|
670
|
-
</div>
|
|
671
|
-
);
|
|
672
|
-
} else if (segment.type === 'ask') {
|
|
673
|
-
// Only the run's head draws — the tail segments are pages of
|
|
674
|
-
// the card already rendered above them.
|
|
675
|
-
const run = askRuns.get(index);
|
|
676
|
-
if (!run) return null;
|
|
677
|
-
return <AskDisplay key={index} cards={run} onSelect={onAskSelect} />;
|
|
678
|
-
} else if (segment.type === 'tool_execution') {
|
|
679
|
-
return (
|
|
680
|
-
<ToolExecutionDisplay
|
|
681
|
-
key={index}
|
|
682
|
-
message={segment.data}
|
|
683
|
-
assistantType={assistantType}
|
|
684
|
-
variant={approvalVariant}
|
|
685
|
-
/>
|
|
686
|
-
);
|
|
687
|
-
} else if (segment.type === 'approval_request') {
|
|
688
|
-
return (
|
|
689
|
-
<ApprovalRequestMessage
|
|
690
|
-
key={index}
|
|
691
|
-
data={segment.data}
|
|
692
|
-
status={segment.status}
|
|
693
|
-
resolvedByName={segment.resolvedByName}
|
|
694
|
-
onApprove={segment.onApprove}
|
|
695
|
-
onReject={segment.onReject}
|
|
696
|
-
assistantType={assistantType}
|
|
697
|
-
variant={approvalVariant}
|
|
698
|
-
/>
|
|
699
|
-
);
|
|
700
|
-
} else if (segment.type === 'approval_batch') {
|
|
701
|
-
return (
|
|
702
|
-
<ApprovalBatchMessage
|
|
703
|
-
key={index}
|
|
704
|
-
data={segment.data}
|
|
705
|
-
status={segment.status}
|
|
706
|
-
resolvedByName={segment.resolvedByName}
|
|
707
|
-
onApprove={segment.onApprove}
|
|
708
|
-
onReject={segment.onReject}
|
|
709
|
-
assistantType={assistantType}
|
|
710
|
-
variant={approvalVariant}
|
|
711
|
-
/>
|
|
712
|
-
);
|
|
713
|
-
} else if (segment.type === 'escalation_offer') {
|
|
714
|
-
return (
|
|
715
|
-
<EscalationOfferMessage
|
|
716
|
-
key={index}
|
|
717
|
-
data={segment.data}
|
|
718
|
-
status={segment.status}
|
|
719
|
-
resolvedByName={segment.resolvedByName}
|
|
720
|
-
onApprove={segment.onApprove}
|
|
721
|
-
onReject={segment.onReject}
|
|
722
|
-
/>
|
|
723
|
-
);
|
|
724
|
-
} else if (segment.type === 'ticket_escalated') {
|
|
725
|
-
return <TicketEscalatedMessage key={index} data={segment.data} timestamp={timestamp} />;
|
|
726
|
-
} else if (segment.type === 'ticket_event') {
|
|
727
|
-
// The card's own event time; the bubble timestamp is the
|
|
728
|
-
// turn's FIRST row and lags every later lifecycle event.
|
|
729
|
-
return (
|
|
730
|
-
<TicketEventMessage key={index} data={segment.data} timestamp={segment.occurredAt ?? timestamp} />
|
|
731
|
-
);
|
|
732
|
-
} else if (segment.type === 'error') {
|
|
733
|
-
return <ErrorMessageDisplay key={index} title={segment.title} details={segment.details} />;
|
|
734
|
-
} else if (segment.type === 'context_compaction') {
|
|
735
|
-
return <ContextCompactionDisplay key={index} status={segment.status} />;
|
|
736
|
-
} else if (segment.type === 'thinking') {
|
|
737
|
-
const isStreaming = index === segments.length - 1 && isTyping;
|
|
738
|
-
return <ThinkingDisplay key={index} text={segment.text} isStreaming={isStreaming} />;
|
|
739
|
-
}
|
|
740
|
-
return null;
|
|
741
|
-
})}
|
|
742
|
-
</div>
|
|
603
|
+
>
|
|
604
|
+
{name || (isUser ? 'User' : assistantType === 'mingo' ? 'Mingo' : 'Fae')}
|
|
605
|
+
{!isSystem && ':'}
|
|
606
|
+
</span>
|
|
607
|
+
{timestamp && (
|
|
608
|
+
<span className="shrink-0 whitespace-nowrap text-ods-text-secondary text-h6">
|
|
609
|
+
{formatMessageTimestamp(timestamp)}
|
|
610
|
+
</span>
|
|
743
611
|
)}
|
|
612
|
+
</div>
|
|
744
613
|
|
|
745
|
-
|
|
614
|
+
{/* Message segments — hidden for system messages without content */}
|
|
615
|
+
{(!isSystem || segments.length > 0) && (
|
|
616
|
+
<div className="grid grid-cols-1 gap-2">
|
|
617
|
+
{segments.map((segment, index) => {
|
|
618
|
+
// The engine's streaming path (atomic-block memoization +
|
|
619
|
+
// fence tail-completion + aria-live) applies ONLY to the
|
|
620
|
+
// actively streaming segment: last segment of a message that
|
|
621
|
+
// is still typing. On completion `isTyping` flips false and
|
|
622
|
+
// the engine does one authoritative whole-document parse.
|
|
623
|
+
const segmentIsStreaming = index === segments.length - 1 && !!isTyping;
|
|
624
|
+
if (segment.type === 'text') {
|
|
625
|
+
return (
|
|
626
|
+
<div
|
|
627
|
+
key={index}
|
|
628
|
+
className={cn(
|
|
629
|
+
'w-full min-w-0 break-words text-h4',
|
|
630
|
+
isError ? 'text-ods-error' : 'text-ods-text-primary',
|
|
631
|
+
)}
|
|
632
|
+
>
|
|
633
|
+
{renderSegmentBody(index, segment.text, segmentIsStreaming)}
|
|
634
|
+
</div>
|
|
635
|
+
);
|
|
636
|
+
} else if (segment.type === 'ask') {
|
|
637
|
+
// Only the run's head draws — the tail segments are pages of
|
|
638
|
+
// the card already rendered above them.
|
|
639
|
+
const run = askRuns.get(index);
|
|
640
|
+
if (!run) return null;
|
|
641
|
+
return <AskDisplay key={index} cards={run} onSelect={onAskSelect} />;
|
|
642
|
+
} else if (segment.type === 'tool_execution') {
|
|
643
|
+
return (
|
|
644
|
+
<ToolExecutionDisplay
|
|
645
|
+
key={index}
|
|
646
|
+
message={segment.data}
|
|
647
|
+
assistantType={assistantType}
|
|
648
|
+
variant={approvalVariant}
|
|
649
|
+
/>
|
|
650
|
+
);
|
|
651
|
+
} else if (segment.type === 'approval_request') {
|
|
652
|
+
return (
|
|
653
|
+
<ApprovalRequestMessage
|
|
654
|
+
key={index}
|
|
655
|
+
data={segment.data}
|
|
656
|
+
status={segment.status}
|
|
657
|
+
resolvedByName={segment.resolvedByName}
|
|
658
|
+
onApprove={segment.onApprove}
|
|
659
|
+
onReject={segment.onReject}
|
|
660
|
+
assistantType={assistantType}
|
|
661
|
+
variant={approvalVariant}
|
|
662
|
+
/>
|
|
663
|
+
);
|
|
664
|
+
} else if (segment.type === 'approval_batch') {
|
|
665
|
+
return (
|
|
666
|
+
<ApprovalBatchMessage
|
|
667
|
+
key={index}
|
|
668
|
+
data={segment.data}
|
|
669
|
+
status={segment.status}
|
|
670
|
+
resolvedByName={segment.resolvedByName}
|
|
671
|
+
onApprove={segment.onApprove}
|
|
672
|
+
onReject={segment.onReject}
|
|
673
|
+
assistantType={assistantType}
|
|
674
|
+
variant={approvalVariant}
|
|
675
|
+
/>
|
|
676
|
+
);
|
|
677
|
+
} else if (segment.type === 'escalation_offer') {
|
|
678
|
+
return (
|
|
679
|
+
<EscalationOfferMessage
|
|
680
|
+
key={index}
|
|
681
|
+
data={segment.data}
|
|
682
|
+
status={segment.status}
|
|
683
|
+
resolvedByName={segment.resolvedByName}
|
|
684
|
+
onApprove={segment.onApprove}
|
|
685
|
+
onReject={segment.onReject}
|
|
686
|
+
/>
|
|
687
|
+
);
|
|
688
|
+
} else if (segment.type === 'ticket_escalated') {
|
|
689
|
+
return <TicketEscalatedMessage key={index} data={segment.data} timestamp={timestamp} />;
|
|
690
|
+
} else if (segment.type === 'ticket_event') {
|
|
691
|
+
// The card's own event time; the bubble timestamp is the
|
|
692
|
+
// turn's FIRST row and lags every later lifecycle event.
|
|
693
|
+
return (
|
|
694
|
+
<TicketEventMessage key={index} data={segment.data} timestamp={segment.occurredAt ?? timestamp} />
|
|
695
|
+
);
|
|
696
|
+
} else if (segment.type === 'error') {
|
|
697
|
+
return <ErrorMessageDisplay key={index} title={segment.title} details={segment.details} />;
|
|
698
|
+
} else if (segment.type === 'context_compaction') {
|
|
699
|
+
return <ContextCompactionDisplay key={index} status={segment.status} />;
|
|
700
|
+
} else if (segment.type === 'thinking') {
|
|
701
|
+
const isStreaming = index === segments.length - 1 && isTyping;
|
|
702
|
+
return <ThinkingDisplay key={index} text={segment.text} isStreaming={isStreaming} />;
|
|
703
|
+
}
|
|
704
|
+
return null;
|
|
705
|
+
})}
|
|
706
|
+
</div>
|
|
707
|
+
)}
|
|
708
|
+
|
|
709
|
+
{/* Attached entity-context chips (user bubbles). Read-only — no
|
|
746
710
|
remove affordance once the message is sent (Figma 31:28709). */}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
</div>
|
|
711
|
+
{stripContextItems && stripContextItems.length > 0 && (
|
|
712
|
+
<ChatContextChipStrip
|
|
713
|
+
items={stripContextItems}
|
|
714
|
+
resolveIcon={resolveContextIcon}
|
|
715
|
+
renderItem={renderContextItem}
|
|
716
|
+
className="mt-2"
|
|
717
|
+
/>
|
|
718
|
+
)}
|
|
756
719
|
</div>
|
|
757
|
-
</
|
|
720
|
+
</div>
|
|
758
721
|
);
|
|
759
722
|
},
|
|
760
723
|
);
|
|
@@ -772,7 +735,6 @@ const MemoizedChatMessageEnhanced = memo(ChatMessageEnhanced, (prevProps, nextPr
|
|
|
772
735
|
prevProps.showAvatar === nextProps.showAvatar &&
|
|
773
736
|
prevProps.assistantType === nextProps.assistantType &&
|
|
774
737
|
prevProps.approvalVariant === nextProps.approvalVariant &&
|
|
775
|
-
prevProps.appearance === nextProps.appearance &&
|
|
776
738
|
prevProps.authorType === nextProps.authorType &&
|
|
777
739
|
prevProps.assistantIcon === nextProps.assistantIcon &&
|
|
778
740
|
prevProps.className === nextProps.className &&
|