@flamingo-stack/openframe-frontend-core 0.0.587-1973.5528.1 → 0.0.587-2000.5532.1
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/chat-protocol/events.d.ts +2 -8
- package/dist/chat-protocol/events.d.ts.map +1 -1
- package/dist/chat-protocol/index.cjs +0 -188
- package/dist/chat-protocol/index.cjs.map +1 -1
- package/dist/chat-protocol/index.js +0 -188
- package/dist/chat-protocol/index.js.map +1 -1
- package/dist/chat-protocol/nats-decoder.d.ts.map +1 -1
- package/dist/{chunk-5VCDP6UA.cjs → chunk-3FHWLQDG.cjs} +10 -10
- package/dist/{chunk-5VCDP6UA.cjs.map → chunk-3FHWLQDG.cjs.map} +1 -1
- package/dist/{chunk-RE3KVI2Q.js → chunk-3PDTGDOA.js} +5 -5
- package/dist/{chunk-5X7AJ67N.js → chunk-436G4DI4.js} +3 -3
- package/dist/{chunk-BLC4JOFC.cjs → chunk-4IIFSFJ3.cjs} +15 -15
- package/dist/{chunk-BLC4JOFC.cjs.map → chunk-4IIFSFJ3.cjs.map} +1 -1
- package/dist/{chunk-JR37UTA2.cjs → chunk-5O5JMGEN.cjs} +33 -33
- package/dist/{chunk-JR37UTA2.cjs.map → chunk-5O5JMGEN.cjs.map} +1 -1
- package/dist/{chunk-7A6J4JTW.js → chunk-6BFEJXMI.js} +3 -3
- package/dist/{chunk-S2UY2C4A.cjs → chunk-7WIKOL25.cjs} +10 -10
- package/dist/{chunk-S2UY2C4A.cjs.map → chunk-7WIKOL25.cjs.map} +1 -1
- package/dist/{chunk-DVMQV3M4.cjs → chunk-A5PXHMCJ.cjs} +69 -69
- package/dist/{chunk-DVMQV3M4.cjs.map → chunk-A5PXHMCJ.cjs.map} +1 -1
- package/dist/{chunk-RQ5PYSRJ.js → chunk-BLJEPNMJ.js} +4 -4
- package/dist/{chunk-4MVGFYRE.js → chunk-D7YISHXC.js} +190 -534
- package/dist/chunk-D7YISHXC.js.map +1 -0
- package/dist/{chunk-4S7GMJYA.cjs → chunk-DMQMRFGS.cjs} +21 -21
- package/dist/{chunk-4S7GMJYA.cjs.map → chunk-DMQMRFGS.cjs.map} +1 -1
- package/dist/{chunk-AIUIIGO3.cjs → chunk-DTQCZ6AR.cjs} +24 -24
- package/dist/{chunk-AIUIIGO3.cjs.map → chunk-DTQCZ6AR.cjs.map} +1 -1
- package/dist/{chunk-QKAUBYU5.cjs → chunk-E7NFHRLX.cjs} +3 -3
- package/dist/{chunk-QKAUBYU5.cjs.map → chunk-E7NFHRLX.cjs.map} +1 -1
- package/dist/{chunk-WFWWQO2I.js → chunk-F3YRPKUA.js} +2 -2
- package/dist/{chunk-EKKR5ZFB.cjs → chunk-G45RGWHF.cjs} +543 -887
- package/dist/chunk-G45RGWHF.cjs.map +1 -0
- package/dist/{chunk-ZRFSUCAH.js → chunk-HCWZP44O.js} +5 -3
- package/dist/{chunk-ZRFSUCAH.js.map → chunk-HCWZP44O.js.map} +1 -1
- package/dist/{chunk-NEI7XMCM.cjs → chunk-IGBNEPTD.cjs} +9 -9
- package/dist/{chunk-NEI7XMCM.cjs.map → chunk-IGBNEPTD.cjs.map} +1 -1
- package/dist/{chunk-3UJMZADA.cjs → chunk-KQ5JQVYL.cjs} +43 -43
- package/dist/{chunk-3UJMZADA.cjs.map → chunk-KQ5JQVYL.cjs.map} +1 -1
- package/dist/{chunk-FDWGO244.js → chunk-LODCKZ72.js} +2 -2
- package/dist/{chunk-ULOMJH7C.cjs → chunk-MF7TMFVB.cjs} +5 -5
- package/dist/{chunk-ULOMJH7C.cjs.map → chunk-MF7TMFVB.cjs.map} +1 -1
- package/dist/{chunk-DSXD77KX.cjs → chunk-MXCWOMNT.cjs} +3 -3
- package/dist/{chunk-DSXD77KX.cjs.map → chunk-MXCWOMNT.cjs.map} +1 -1
- package/dist/{chunk-E2QFZDCP.js → chunk-OKD7MX7Y.js} +5 -5
- package/dist/{chunk-OW3FUJ2I.js → chunk-P24OI2CD.js} +3 -3
- package/dist/{chunk-QSO24MEK.js → chunk-R2U2D7LU.js} +2 -2
- package/dist/{chunk-KQWI25NP.js → chunk-SI57FQZ2.js} +2 -2
- package/dist/{chunk-JQO47UHC.js → chunk-SVR75PFW.js} +5 -5
- package/dist/{chunk-UYHETUX3.cjs → chunk-UBSIENYF.cjs} +162 -160
- package/dist/chunk-UBSIENYF.cjs.map +1 -0
- package/dist/{chunk-OZRT3ZI3.js → chunk-V4WUSOGS.js} +3 -3
- package/dist/{chunk-UODM3HJC.js → chunk-VWNU2PFX.js} +3 -3
- package/dist/{chunk-SCVIBVFS.cjs → chunk-WQXWH7LF.cjs} +4 -4
- package/dist/{chunk-SCVIBVFS.cjs.map → chunk-WQXWH7LF.cjs.map} +1 -1
- package/dist/{chunk-7COFWOCJ.cjs → chunk-XNEPABUD.cjs} +22 -22
- package/dist/{chunk-7COFWOCJ.cjs.map → chunk-XNEPABUD.cjs.map} +1 -1
- package/dist/{chunk-QYDIVL4X.js → chunk-YB5DFQKD.js} +6 -6
- package/dist/components/case-studies/index.cjs +9 -9
- package/dist/components/case-studies/index.js +3 -3
- 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/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +1 -4
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-slash-commands.d.ts +3 -3
- package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +28 -2
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/remark-strip-citations.d.ts.map +1 -1
- package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -1
- package/dist/components/chat/tool-execution-display.d.ts.map +1 -1
- package/dist/components/chat/types/component.types.d.ts +0 -4
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/chat/types/message.types.d.ts +1 -35
- package/dist/components/chat/types/message.types.d.ts.map +1 -1
- package/dist/components/chat/types/unified-chat-state.types.d.ts +3 -3
- package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +4 -4
- package/dist/components/embeds/index.js +3 -3
- package/dist/components/faq/index.cjs +4 -4
- package/dist/components/faq/index.js +3 -3
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/index.cjs +36 -36
- package/dist/components/index.js +13 -13
- package/dist/components/meeting-scheduler/index.cjs +21 -21
- package/dist/components/meeting-scheduler/index.js +2 -2
- package/dist/components/navigation/index.cjs +6 -6
- package/dist/components/navigation/index.js +5 -5
- package/dist/components/onboarding-guides/index.cjs +6 -6
- package/dist/components/onboarding-guides/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/data-table/use-data-table.d.ts.map +1 -1
- package/dist/components/ui/hover-dropdown.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +3 -3
- package/dist/components/ui/index.js +2 -2
- package/dist/index.cjs +7 -7
- package/dist/index.js +6 -6
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -2
- package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +0 -130
- package/src/chat-protocol/events.ts +1 -9
- package/src/chat-protocol/nats-decoder.ts +0 -7
- package/src/components/chat/__tests__/chat-message-list.test.tsx +0 -70
- package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +0 -86
- package/src/components/chat/chat-message-enhanced.tsx +13 -28
- package/src/components/chat/chat-message-list.tsx +22 -27
- package/src/components/chat/embeddable-chat.tsx +36 -55
- package/src/components/chat/entity-cards/dispatch.tsx +17 -86
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +0 -7
- package/src/components/chat/hooks/use-slash-commands.ts +5 -9
- package/src/components/chat/hooks/use-sse-chat-adapter.ts +29 -2
- package/src/components/chat/remark-strip-citations.ts +3 -5
- package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +0 -56
- package/src/components/chat/stream/chat-stream-reducer.ts +0 -31
- package/src/components/chat/tool-execution-display.tsx +2 -5
- package/src/components/chat/types/component.types.ts +0 -4
- package/src/components/chat/types/message.types.ts +0 -39
- package/src/components/chat/types/unified-chat-state.types.ts +3 -4
- package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +0 -57
- package/src/components/chat/utils/process-historical-messages.ts +1 -19
- package/src/components/ui/__tests__/data-table-compiler-identity.test.tsx +74 -0
- package/src/components/ui/data-table/use-data-table.ts +36 -1
- package/src/components/ui/hover-dropdown.tsx +3 -8
- package/dist/chat-protocol/source-metadata.d.ts +0 -5
- package/dist/chat-protocol/source-metadata.d.ts.map +0 -1
- package/dist/chunk-4MVGFYRE.js.map +0 -1
- package/dist/chunk-EKKR5ZFB.cjs.map +0 -1
- package/dist/chunk-UYHETUX3.cjs.map +0 -1
- package/dist/components/chat/utils/chat-source-metadata.d.ts +0 -5
- package/dist/components/chat/utils/chat-source-metadata.d.ts.map +0 -1
- package/src/chat-protocol/__tests__/source-metadata.test.ts +0 -74
- package/src/chat-protocol/source-metadata.ts +0 -202
- package/src/components/chat/__tests__/embeddable-chat-sources.test.tsx +0 -411
- package/src/components/chat/__tests__/remark-strip-citations.test.ts +0 -52
- package/src/components/chat/__tests__/tool-execution-display.test.tsx +0 -93
- package/src/components/chat/entity-cards/__tests__/dispatch-video-refs.test.tsx +0 -74
- package/src/components/chat/hooks/__tests__/use-slash-commands.test.ts +0 -64
- package/src/components/chat/utils/chat-source-metadata.ts +0 -19
- /package/dist/{chunk-RE3KVI2Q.js.map → chunk-3PDTGDOA.js.map} +0 -0
- /package/dist/{chunk-5X7AJ67N.js.map → chunk-436G4DI4.js.map} +0 -0
- /package/dist/{chunk-7A6J4JTW.js.map → chunk-6BFEJXMI.js.map} +0 -0
- /package/dist/{chunk-RQ5PYSRJ.js.map → chunk-BLJEPNMJ.js.map} +0 -0
- /package/dist/{chunk-WFWWQO2I.js.map → chunk-F3YRPKUA.js.map} +0 -0
- /package/dist/{chunk-FDWGO244.js.map → chunk-LODCKZ72.js.map} +0 -0
- /package/dist/{chunk-E2QFZDCP.js.map → chunk-OKD7MX7Y.js.map} +0 -0
- /package/dist/{chunk-OW3FUJ2I.js.map → chunk-P24OI2CD.js.map} +0 -0
- /package/dist/{chunk-QSO24MEK.js.map → chunk-R2U2D7LU.js.map} +0 -0
- /package/dist/{chunk-KQWI25NP.js.map → chunk-SI57FQZ2.js.map} +0 -0
- /package/dist/{chunk-JQO47UHC.js.map → chunk-SVR75PFW.js.map} +0 -0
- /package/dist/{chunk-OZRT3ZI3.js.map → chunk-V4WUSOGS.js.map} +0 -0
- /package/dist/{chunk-UODM3HJC.js.map → chunk-VWNU2PFX.js.map} +0 -0
- /package/dist/{chunk-QYDIVL4X.js.map → chunk-YB5DFQKD.js.map} +0 -0
|
@@ -195,8 +195,6 @@ export interface ChatMessageEnhancedProps extends Omit<HTMLAttributes<HTMLDivEle
|
|
|
195
195
|
* back to plain text title-only.
|
|
196
196
|
*/
|
|
197
197
|
renderEntityCard?: (reference: ChatRef) => ReactNode;
|
|
198
|
-
/** Enriched references associated with this assistant answer. */
|
|
199
|
-
refs?: ChatRef[];
|
|
200
198
|
/**
|
|
201
199
|
* Host-provided anchor component for markdown links. When supplied, the
|
|
202
200
|
* `<a>` override in the markdown renderer delegates to this component
|
|
@@ -306,8 +304,6 @@ export interface ChatMessageListProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
306
304
|
* ChatMessageEnhanced; the host sends the received label as the user's next
|
|
307
305
|
* message. Omit to render ask cards read-only. */
|
|
308
306
|
onAskSelect?: (label: string) => void;
|
|
309
|
-
/** Renders content owned by one message directly after that message. */
|
|
310
|
-
renderAfterMessage?: (message: Message, index: number) => ReactNode;
|
|
311
307
|
}
|
|
312
308
|
|
|
313
309
|
export interface ChatMessageListRef {
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Contains all message structures, segments, and content types
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { ChatRef } from '../chat-ref.types';
|
|
7
6
|
import type { AssistantType, AuthorType, ChatApprovalStatus, MessageOwner } from './chat.types';
|
|
8
7
|
|
|
9
8
|
// ========== Message Type Definitions ==========
|
|
@@ -11,8 +10,6 @@ import type { AssistantType, AuthorType, ChatApprovalStatus, MessageOwner } from
|
|
|
11
10
|
export const MESSAGE_TYPE = {
|
|
12
11
|
TEXT: 'TEXT',
|
|
13
12
|
THINKING: 'THINKING',
|
|
14
|
-
GUIDE: 'GUIDE',
|
|
15
|
-
SOURCES: 'SOURCES',
|
|
16
13
|
ASK: 'ASK',
|
|
17
14
|
EXECUTING_TOOL: 'EXECUTING_TOOL',
|
|
18
15
|
EXECUTED_TOOL: 'EXECUTED_TOOL',
|
|
@@ -49,26 +46,6 @@ export const SCROLL_ANCHOR = { TOP: 'top', BOTTOM: 'bottom' } as const;
|
|
|
49
46
|
|
|
50
47
|
export type ScrollAnchor = (typeof SCROLL_ANCHOR)[keyof typeof SCROLL_ANCHOR];
|
|
51
48
|
|
|
52
|
-
export interface ChatSource {
|
|
53
|
-
index: number;
|
|
54
|
-
name: string;
|
|
55
|
-
path: string;
|
|
56
|
-
documentType: string;
|
|
57
|
-
externalUrl?: string;
|
|
58
|
-
targetPlatform?: string | null;
|
|
59
|
-
id?: string;
|
|
60
|
-
items?: Array<{
|
|
61
|
-
id: string;
|
|
62
|
-
documentType: string;
|
|
63
|
-
name: string;
|
|
64
|
-
externalUrl?: string;
|
|
65
|
-
targetPlatform?: string | null;
|
|
66
|
-
path?: string | null;
|
|
67
|
-
}>;
|
|
68
|
-
sourceRepo?: string;
|
|
69
|
-
label?: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
49
|
// ========== Tool Execution Types ==========
|
|
73
50
|
|
|
74
51
|
export interface ToolExecutionData {
|
|
@@ -414,16 +391,6 @@ export interface ThinkingMessageData extends MessageDataBase {
|
|
|
414
391
|
text?: string;
|
|
415
392
|
}
|
|
416
393
|
|
|
417
|
-
export interface GuideMessageData extends MessageDataBase {
|
|
418
|
-
type: 'GUIDE';
|
|
419
|
-
payload?: Record<string, unknown>;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
export interface SourcesMessageData extends MessageDataBase {
|
|
423
|
-
type: 'SOURCES';
|
|
424
|
-
payload?: Record<string, unknown>;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
394
|
/** Persisted `ASK` row (GraphQL `AskData`). `text` is the intro sentence, which
|
|
428
395
|
* history replays as a text segment ahead of the card — same split the live
|
|
429
396
|
* `ASK` chunk carries. */
|
|
@@ -565,8 +532,6 @@ export interface ContextCompactionEndMessageData extends MessageDataBase {
|
|
|
565
532
|
export type MessageData =
|
|
566
533
|
| TextMessageData
|
|
567
534
|
| ThinkingMessageData
|
|
568
|
-
| GuideMessageData
|
|
569
|
-
| SourcesMessageData
|
|
570
535
|
| AskMessageData
|
|
571
536
|
| ExecutingToolMessageData
|
|
572
537
|
| ExecutedToolMessageData
|
|
@@ -611,8 +576,6 @@ export interface ProcessedMessage {
|
|
|
611
576
|
authorType?: AuthorType;
|
|
612
577
|
timestamp: Date;
|
|
613
578
|
avatar?: string;
|
|
614
|
-
sources?: ChatSource[];
|
|
615
|
-
refs?: ChatRef[];
|
|
616
579
|
/** Persisted last-chunk stream sequence carried through from
|
|
617
580
|
* `HistoricalMessage.lastChunkStreamSeq` (for assistant turns: the MAX
|
|
618
581
|
* across the grouped rows). Hosts stamp it onto the rendered message's
|
|
@@ -635,8 +598,6 @@ export interface Message {
|
|
|
635
598
|
authorType?: AuthorType;
|
|
636
599
|
timestamp?: Date;
|
|
637
600
|
avatar?: string | null;
|
|
638
|
-
sources?: ChatSource[];
|
|
639
|
-
refs?: ChatRef[];
|
|
640
601
|
/** Highest CONTENT chunk streamSeq that composed this message. Stamped on
|
|
641
602
|
* realtime synthetics so `mergeHistoryWithRealtime` can decide history
|
|
642
603
|
* coverage per-message (see `MergeableChatMessage.streamSeq`). */
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import type { ChatRef } from '../chat-ref.types';
|
|
20
|
+
import type { ChatSource } from '../hooks/use-sse-chat-adapter';
|
|
20
21
|
import type { ChatAttachment } from '../utils/chat-attachment-markdown';
|
|
21
22
|
import type { AuthorType } from './chat.types';
|
|
22
23
|
import type { DialogItem } from './component.types';
|
|
23
24
|
import type { ChatContextItem } from './context-item.types';
|
|
24
|
-
import type {
|
|
25
|
+
import type { MessageSegment, ScrollAnchor } from './message.types';
|
|
25
26
|
|
|
26
27
|
// ─── Per-dialog token usage (Mingo backend telemetry) ────────────────────────
|
|
27
28
|
|
|
@@ -168,11 +169,9 @@ export interface UnifiedChatMessage {
|
|
|
168
169
|
*/
|
|
169
170
|
timestamp?: Date | string | number;
|
|
170
171
|
|
|
171
|
-
/**
|
|
172
|
+
/** Guide/SSE-only: document citations. Undefined in Mingo mode. */
|
|
172
173
|
sources?: ChatSource[];
|
|
173
174
|
|
|
174
|
-
refs?: ChatRef[];
|
|
175
|
-
|
|
176
175
|
/**
|
|
177
176
|
* Per-message viewport-positioning hint. Common to both modes; the
|
|
178
177
|
* message-list reads it to override default tail-on-stream behaviour
|
|
@@ -391,60 +391,3 @@ describe('processHistoricalMessages — ASK rows', () => {
|
|
|
391
391
|
expect(processHistoricalMessages(dialog).messages).toEqual([]);
|
|
392
392
|
});
|
|
393
393
|
});
|
|
394
|
-
|
|
395
|
-
describe('processHistoricalMessages — Mingo source metadata', () => {
|
|
396
|
-
it.each(['GUIDE', 'SOURCES'] as const)('restores %s metadata on the same assistant turn', type => {
|
|
397
|
-
const dialog: HistoricalMessage[] = [
|
|
398
|
-
{
|
|
399
|
-
id: 'a1',
|
|
400
|
-
chatType: 'ADMIN_AI_CHAT',
|
|
401
|
-
createdAt: '2026-07-19T09:00:05Z',
|
|
402
|
-
owner: { type: 'ASSISTANT' },
|
|
403
|
-
messageData: [
|
|
404
|
-
{
|
|
405
|
-
type,
|
|
406
|
-
payload: {
|
|
407
|
-
sources: [
|
|
408
|
-
{
|
|
409
|
-
index: 1,
|
|
410
|
-
name: 'Install agent',
|
|
411
|
-
path: 'docs/install.md',
|
|
412
|
-
documentType: 'markdown',
|
|
413
|
-
},
|
|
414
|
-
],
|
|
415
|
-
videos: [
|
|
416
|
-
{
|
|
417
|
-
ref: '[card://video:mux-9b6586b494]',
|
|
418
|
-
title: 'Community demo',
|
|
419
|
-
url: 'https://stream.mux.com/playback-id.m3u8',
|
|
420
|
-
metadata: { videoUrl: 'https://stream.mux.com/playback-id.m3u8' },
|
|
421
|
-
},
|
|
422
|
-
],
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
{ type: 'TEXT', text: 'Install the agent [1]. [card://video:mux-9b6586b494]' },
|
|
426
|
-
],
|
|
427
|
-
},
|
|
428
|
-
];
|
|
429
|
-
|
|
430
|
-
expect(processHistoricalMessages(dialog).messages[0]).toMatchObject({
|
|
431
|
-
role: 'assistant',
|
|
432
|
-
sources: [
|
|
433
|
-
{
|
|
434
|
-
index: 1,
|
|
435
|
-
name: 'Install agent',
|
|
436
|
-
path: 'docs/install.md',
|
|
437
|
-
documentType: 'markdown',
|
|
438
|
-
},
|
|
439
|
-
],
|
|
440
|
-
refs: [
|
|
441
|
-
{
|
|
442
|
-
type: 'video',
|
|
443
|
-
id: 'mux-9b6586b494',
|
|
444
|
-
metadata: { videoUrl: 'https://stream.mux.com/playback-id.m3u8' },
|
|
445
|
-
},
|
|
446
|
-
],
|
|
447
|
-
content: [{ type: 'text', text: 'Install the agent [1]. [card://video:mux-9b6586b494]' }],
|
|
448
|
-
});
|
|
449
|
-
});
|
|
450
|
-
});
|
|
@@ -33,8 +33,7 @@ import {
|
|
|
33
33
|
} from '../../../chat-protocol/events';
|
|
34
34
|
// One normalizer for ask rows, shared with the live decoder — history and the
|
|
35
35
|
// stream must agree on which options are usable.
|
|
36
|
-
import {
|
|
37
|
-
import type { ChatRef } from '../chat-ref.types';
|
|
36
|
+
import { normalizeAskOptions } from '../../../chat-protocol/nats-decoder';
|
|
38
37
|
import { applyApprovalStatusToSegment } from '../stream/message-mutations';
|
|
39
38
|
import {
|
|
40
39
|
MESSAGE_TYPE,
|
|
@@ -47,10 +46,8 @@ import {
|
|
|
47
46
|
type MessageProcessingOptions,
|
|
48
47
|
type MessageData,
|
|
49
48
|
type MessageOwner,
|
|
50
|
-
type ChatSource,
|
|
51
49
|
} from '../types';
|
|
52
50
|
import { approvalDisplaysInline } from './approval-display';
|
|
53
|
-
import { mergeChatRefs, mergeChatSources } from './chat-source-metadata';
|
|
54
51
|
import { type MessageSegmentAccumulator, createMessageSegmentAccumulator } from './message-segment-accumulator';
|
|
55
52
|
import { getCommandText } from './tool-call-helpers';
|
|
56
53
|
|
|
@@ -124,10 +121,6 @@ export function decodeHistoricalMessageData(data: MessageData): ChatStreamEvent
|
|
|
124
121
|
}
|
|
125
122
|
return null;
|
|
126
123
|
|
|
127
|
-
case MESSAGE_TYPE.GUIDE:
|
|
128
|
-
case MESSAGE_TYPE.SOURCES:
|
|
129
|
-
return decodeNatsChunk({ type: data.type, payload: data.payload });
|
|
130
|
-
|
|
131
124
|
// Same completeness gate as the live decoder (`decodeNatsChunk`): a
|
|
132
125
|
// persisted row without a question or without options is not a card the
|
|
133
126
|
// user can answer, so it replays as nothing rather than as empty chrome.
|
|
@@ -598,8 +591,6 @@ export function processHistoricalMessages(
|
|
|
598
591
|
// MAX persisted seq across the rows grouped into the current assistant turn
|
|
599
592
|
// — carried onto the flushed message's streamSeq for per-role merge coverage.
|
|
600
593
|
let currentAssistantStreamSeq: number | undefined;
|
|
601
|
-
let currentAssistantSources: ChatSource[] | undefined;
|
|
602
|
-
let currentAssistantRefs: ChatRef[] | undefined;
|
|
603
594
|
|
|
604
595
|
/**
|
|
605
596
|
* Flush the current assistant message to processedMessages.
|
|
@@ -617,8 +608,6 @@ export function processHistoricalMessages(
|
|
|
617
608
|
authorType: assistantType,
|
|
618
609
|
timestamp: currentAssistantTimestamp || new Date(),
|
|
619
610
|
avatar: assistantAvatar,
|
|
620
|
-
...(currentAssistantSources ? { sources: currentAssistantSources } : {}),
|
|
621
|
-
...(currentAssistantRefs ? { refs: currentAssistantRefs } : {}),
|
|
622
611
|
...(currentAssistantStreamSeq !== undefined ? { streamSeq: currentAssistantStreamSeq } : {}),
|
|
623
612
|
});
|
|
624
613
|
accumulator.resetSegments();
|
|
@@ -634,8 +623,6 @@ export function processHistoricalMessages(
|
|
|
634
623
|
currentAssistantTimestamp = null;
|
|
635
624
|
lastAssistantId = null;
|
|
636
625
|
currentAssistantStreamSeq = undefined;
|
|
637
|
-
currentAssistantSources = undefined;
|
|
638
|
-
currentAssistantRefs = undefined;
|
|
639
626
|
};
|
|
640
627
|
|
|
641
628
|
messages.forEach((msg, index) => {
|
|
@@ -702,11 +689,6 @@ export function processHistoricalMessages(
|
|
|
702
689
|
messageDataArray.forEach(data => {
|
|
703
690
|
const event = decodeHistoricalMessageData(data);
|
|
704
691
|
if (!event) return;
|
|
705
|
-
if (event.type === 'sources') {
|
|
706
|
-
currentAssistantSources = mergeChatSources(currentAssistantSources, event.sources);
|
|
707
|
-
if (event.refs) currentAssistantRefs = mergeChatRefs(currentAssistantRefs, event.refs);
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
692
|
applyHistoryEvent(
|
|
711
693
|
event,
|
|
712
694
|
accumulator,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ColumnDef, Table } from '@tanstack/react-table';
|
|
2
|
+
import { render, renderHook, screen } from '@testing-library/react';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { DataTable } from '../data-table';
|
|
6
|
+
import { useDataTable } from '../data-table/use-data-table';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What this pins down: `useDataTable` must hand back a NEW reference on every
|
|
10
|
+
* render, because `useReactTable` creates one instance for the life of the
|
|
11
|
+
* component and mutates it in place.
|
|
12
|
+
*
|
|
13
|
+
* Everything inside `<DataTable>` reads its rows back out of that instance
|
|
14
|
+
* through context, so a caller compiled by the React Compiler caches
|
|
15
|
+
* `<DataTable table={table}>` and its children on the table's identity — which
|
|
16
|
+
* never changes — and a table that gains rows renders nothing new. On an
|
|
17
|
+
* infinite-scroll table that is a request loop: the sentinel never moves down,
|
|
18
|
+
* so `DataTable.InfiniteFooter` keeps asking for the next page.
|
|
19
|
+
*
|
|
20
|
+
* `CachedTable` below stands in for that compiled caller. `memo` bails out on
|
|
21
|
+
* identical props exactly like the compiler's `if ($[n] !== table)` guard.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
interface Row {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const COLUMNS: ColumnDef<Row>[] = [{ accessorKey: 'name', header: 'Name', cell: ({ row }) => row.original.name }];
|
|
30
|
+
|
|
31
|
+
const getRowId = (row: Row) => row.id;
|
|
32
|
+
|
|
33
|
+
function rows(count: number): Row[] {
|
|
34
|
+
return Array.from({ length: count }, (_, i) => ({ id: `r${i}`, name: `row-${i}` }));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const CachedTable = memo(function CachedTableImpl({ table }: { table: Table<Row> }) {
|
|
38
|
+
return (
|
|
39
|
+
<DataTable table={table}>
|
|
40
|
+
<DataTable.Body<Row> />
|
|
41
|
+
</DataTable>
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
function TableHost({ data }: { data: Row[] }) {
|
|
46
|
+
const table = useDataTable<Row>({ data, columns: COLUMNS, getRowId });
|
|
47
|
+
return <CachedTable table={table} />;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe('useDataTable identity', () => {
|
|
51
|
+
it('lets a consumer memoized on the table render rows that arrived later', () => {
|
|
52
|
+
const { rerender } = render(<TableHost data={rows(2)} />);
|
|
53
|
+
expect(screen.getAllByText(/^row-\d$/)).toHaveLength(2);
|
|
54
|
+
|
|
55
|
+
rerender(<TableHost data={rows(4)} />);
|
|
56
|
+
expect(screen.getAllByText(/^row-\d$/)).toHaveLength(4);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('forwards reads and writes to the single underlying instance', () => {
|
|
60
|
+
const { result, rerender } = renderHook(({ data }) => useDataTable<Row>({ data, columns: COLUMNS, getRowId }), {
|
|
61
|
+
initialProps: { data: rows(3) },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const first = result.current;
|
|
65
|
+
expect(first.getRowModel().rows).toHaveLength(3);
|
|
66
|
+
// A write through one handle must be visible through the next one.
|
|
67
|
+
first.setOptions(prev => ({ ...prev, meta: { probed: true } }));
|
|
68
|
+
|
|
69
|
+
rerender({ data: rows(5) });
|
|
70
|
+
expect(result.current).not.toBe(first);
|
|
71
|
+
expect(result.current.getRowModel().rows).toHaveLength(5);
|
|
72
|
+
expect(result.current.options.meta).toEqual({ probed: true });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -98,7 +98,12 @@ export function useDataTable<T>({
|
|
|
98
98
|
getFilteredRowModel: getFilteredRowModelOverride,
|
|
99
99
|
...rest
|
|
100
100
|
}: UseDataTableOptions<T>): Table<T> {
|
|
101
|
-
|
|
101
|
+
// Opted out of the React Compiler on purpose — see the handle published at the
|
|
102
|
+
// end of this function. Nothing here is worth memoizing anyway: `setOptions`
|
|
103
|
+
// runs on every render regardless.
|
|
104
|
+
'use no memo';
|
|
105
|
+
|
|
106
|
+
const table = useReactTable<T>({
|
|
102
107
|
...rest,
|
|
103
108
|
getCoreRowModel: coreRowModelFactory as TableOptions<T>['getCoreRowModel'],
|
|
104
109
|
getSortedRowModel: clientSideSorting
|
|
@@ -110,4 +115,34 @@ export function useDataTable<T>({
|
|
|
110
115
|
manualSorting: manualSorting ?? !clientSideSorting,
|
|
111
116
|
manualFiltering: manualFiltering ?? !clientSideFiltering,
|
|
112
117
|
});
|
|
118
|
+
|
|
119
|
+
// A fresh handle per render, and the reason this hook doesn't just return
|
|
120
|
+
// `useReactTable`'s value.
|
|
121
|
+
//
|
|
122
|
+
// `useReactTable` creates ONE instance for the life of the component and
|
|
123
|
+
// mutates it in place, so its identity is the same object whether a page of
|
|
124
|
+
// rows just arrived or nothing happened at all. Every consumer reads rows and
|
|
125
|
+
// state back out of that instance through context (`DataTable.Body`,
|
|
126
|
+
// `.Header`, `.RowCount`, `.CursorFooter`) — which worked only because the
|
|
127
|
+
// caller re-rendered and rebuilt their elements.
|
|
128
|
+
//
|
|
129
|
+
// Under the React Compiler it stops working, because the compiler caches on
|
|
130
|
+
// identity: `<DataTable table={table}>` and its children get cached on
|
|
131
|
+
// `table`, and inside the compiled `DataTableBody` the entire body —
|
|
132
|
+
// `table.getRowModel().rows` included — sits behind a `$[n] !== table` guard.
|
|
133
|
+
// A table that gains rows then renders nothing new. On an infinite-scroll
|
|
134
|
+
// table that is a loop: the sentinel never moves down, so
|
|
135
|
+
// `DataTable.InfiniteFooter` asks for the next page forever.
|
|
136
|
+
//
|
|
137
|
+
// The proxy forwards every read, write and TanStack mutation to that single
|
|
138
|
+
// instance, so nothing about the table's behaviour changes — only its
|
|
139
|
+
// identity, which is what puts it back inside React's reactive graph.
|
|
140
|
+
//
|
|
141
|
+
// The `use no memo` at the top of this hook is what keeps it a FRESH handle:
|
|
142
|
+
// without it the compiler caches this very object on `table` and hands back
|
|
143
|
+
// the same one forever, i.e. the bug. Keying a `useMemo` on
|
|
144
|
+
// `getRowModel()`/`getState()` instead is not better — `useReactTable`
|
|
145
|
+
// rebuilds `options.state` on every render anyway, so it would republish just
|
|
146
|
+
// as often while reading as though it did not.
|
|
147
|
+
return new Proxy(table, {});
|
|
113
148
|
}
|
|
@@ -106,7 +106,6 @@ export function HoverDropdown({
|
|
|
106
106
|
}: HoverDropdownProps) {
|
|
107
107
|
const [open, setOpen] = useState(false);
|
|
108
108
|
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
109
|
-
const clickPinnedRef = useRef(false);
|
|
110
109
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
111
110
|
const panelRef = useRef<HTMLDivElement>(null);
|
|
112
111
|
|
|
@@ -157,22 +156,18 @@ export function HoverDropdown({
|
|
|
157
156
|
}, []);
|
|
158
157
|
|
|
159
158
|
const hide = useCallback(() => {
|
|
160
|
-
if (clickPinnedRef.current) return;
|
|
161
159
|
timeoutRef.current = setTimeout(() => setOpen(false), hideDelay);
|
|
162
160
|
}, [hideDelay]);
|
|
163
161
|
|
|
164
162
|
// Click handler — touch / mobile (no hover) + desktop users who
|
|
165
|
-
// expect clicking a chip to open a menu.
|
|
166
|
-
//
|
|
167
|
-
// toggling it closed. A second click closes it. `stopPropagation` prevents the click
|
|
163
|
+
// expect clicking a chip to open a menu. Toggles the dropdown state
|
|
164
|
+
// so a second click closes it. `stopPropagation` prevents the click
|
|
168
165
|
// from bubbling to ancestor handlers (the chip's parent message
|
|
169
166
|
// bubble shouldn't react to chip clicks).
|
|
170
167
|
const toggle = useCallback((e: React.MouseEvent) => {
|
|
171
168
|
e.stopPropagation();
|
|
172
169
|
clearTimeout(timeoutRef.current);
|
|
173
|
-
|
|
174
|
-
clickPinnedRef.current = pinned;
|
|
175
|
-
setOpen(pinned);
|
|
170
|
+
setOpen(prev => !prev);
|
|
176
171
|
}, []);
|
|
177
172
|
|
|
178
173
|
// Every hook is above this line: an `items` list that goes from empty to
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { ChatRef } from '../components/chat/chat-ref.types';
|
|
2
|
-
import type { SourcesEvent } from './events';
|
|
3
|
-
export declare function isSourceMetadataCardRef(ref: ChatRef): boolean;
|
|
4
|
-
export declare function sourceMetadataEvent(payload: unknown): SourcesEvent | null;
|
|
5
|
-
//# sourceMappingURL=source-metadata.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"source-metadata.d.ts","sourceRoot":"","sources":["../../src/chat-protocol/source-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAK7C,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE7D;AAmLD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAazE"}
|