@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.
Files changed (165) hide show
  1. package/dist/chat-protocol/events.d.ts +2 -8
  2. package/dist/chat-protocol/events.d.ts.map +1 -1
  3. package/dist/chat-protocol/index.cjs +0 -188
  4. package/dist/chat-protocol/index.cjs.map +1 -1
  5. package/dist/chat-protocol/index.js +0 -188
  6. package/dist/chat-protocol/index.js.map +1 -1
  7. package/dist/chat-protocol/nats-decoder.d.ts.map +1 -1
  8. package/dist/{chunk-5VCDP6UA.cjs → chunk-3FHWLQDG.cjs} +10 -10
  9. package/dist/{chunk-5VCDP6UA.cjs.map → chunk-3FHWLQDG.cjs.map} +1 -1
  10. package/dist/{chunk-RE3KVI2Q.js → chunk-3PDTGDOA.js} +5 -5
  11. package/dist/{chunk-5X7AJ67N.js → chunk-436G4DI4.js} +3 -3
  12. package/dist/{chunk-BLC4JOFC.cjs → chunk-4IIFSFJ3.cjs} +15 -15
  13. package/dist/{chunk-BLC4JOFC.cjs.map → chunk-4IIFSFJ3.cjs.map} +1 -1
  14. package/dist/{chunk-JR37UTA2.cjs → chunk-5O5JMGEN.cjs} +33 -33
  15. package/dist/{chunk-JR37UTA2.cjs.map → chunk-5O5JMGEN.cjs.map} +1 -1
  16. package/dist/{chunk-7A6J4JTW.js → chunk-6BFEJXMI.js} +3 -3
  17. package/dist/{chunk-S2UY2C4A.cjs → chunk-7WIKOL25.cjs} +10 -10
  18. package/dist/{chunk-S2UY2C4A.cjs.map → chunk-7WIKOL25.cjs.map} +1 -1
  19. package/dist/{chunk-DVMQV3M4.cjs → chunk-A5PXHMCJ.cjs} +69 -69
  20. package/dist/{chunk-DVMQV3M4.cjs.map → chunk-A5PXHMCJ.cjs.map} +1 -1
  21. package/dist/{chunk-RQ5PYSRJ.js → chunk-BLJEPNMJ.js} +4 -4
  22. package/dist/{chunk-4MVGFYRE.js → chunk-D7YISHXC.js} +190 -534
  23. package/dist/chunk-D7YISHXC.js.map +1 -0
  24. package/dist/{chunk-4S7GMJYA.cjs → chunk-DMQMRFGS.cjs} +21 -21
  25. package/dist/{chunk-4S7GMJYA.cjs.map → chunk-DMQMRFGS.cjs.map} +1 -1
  26. package/dist/{chunk-AIUIIGO3.cjs → chunk-DTQCZ6AR.cjs} +24 -24
  27. package/dist/{chunk-AIUIIGO3.cjs.map → chunk-DTQCZ6AR.cjs.map} +1 -1
  28. package/dist/{chunk-QKAUBYU5.cjs → chunk-E7NFHRLX.cjs} +3 -3
  29. package/dist/{chunk-QKAUBYU5.cjs.map → chunk-E7NFHRLX.cjs.map} +1 -1
  30. package/dist/{chunk-WFWWQO2I.js → chunk-F3YRPKUA.js} +2 -2
  31. package/dist/{chunk-EKKR5ZFB.cjs → chunk-G45RGWHF.cjs} +543 -887
  32. package/dist/chunk-G45RGWHF.cjs.map +1 -0
  33. package/dist/{chunk-ZRFSUCAH.js → chunk-HCWZP44O.js} +5 -3
  34. package/dist/{chunk-ZRFSUCAH.js.map → chunk-HCWZP44O.js.map} +1 -1
  35. package/dist/{chunk-NEI7XMCM.cjs → chunk-IGBNEPTD.cjs} +9 -9
  36. package/dist/{chunk-NEI7XMCM.cjs.map → chunk-IGBNEPTD.cjs.map} +1 -1
  37. package/dist/{chunk-3UJMZADA.cjs → chunk-KQ5JQVYL.cjs} +43 -43
  38. package/dist/{chunk-3UJMZADA.cjs.map → chunk-KQ5JQVYL.cjs.map} +1 -1
  39. package/dist/{chunk-FDWGO244.js → chunk-LODCKZ72.js} +2 -2
  40. package/dist/{chunk-ULOMJH7C.cjs → chunk-MF7TMFVB.cjs} +5 -5
  41. package/dist/{chunk-ULOMJH7C.cjs.map → chunk-MF7TMFVB.cjs.map} +1 -1
  42. package/dist/{chunk-DSXD77KX.cjs → chunk-MXCWOMNT.cjs} +3 -3
  43. package/dist/{chunk-DSXD77KX.cjs.map → chunk-MXCWOMNT.cjs.map} +1 -1
  44. package/dist/{chunk-E2QFZDCP.js → chunk-OKD7MX7Y.js} +5 -5
  45. package/dist/{chunk-OW3FUJ2I.js → chunk-P24OI2CD.js} +3 -3
  46. package/dist/{chunk-QSO24MEK.js → chunk-R2U2D7LU.js} +2 -2
  47. package/dist/{chunk-KQWI25NP.js → chunk-SI57FQZ2.js} +2 -2
  48. package/dist/{chunk-JQO47UHC.js → chunk-SVR75PFW.js} +5 -5
  49. package/dist/{chunk-UYHETUX3.cjs → chunk-UBSIENYF.cjs} +162 -160
  50. package/dist/chunk-UBSIENYF.cjs.map +1 -0
  51. package/dist/{chunk-OZRT3ZI3.js → chunk-V4WUSOGS.js} +3 -3
  52. package/dist/{chunk-UODM3HJC.js → chunk-VWNU2PFX.js} +3 -3
  53. package/dist/{chunk-SCVIBVFS.cjs → chunk-WQXWH7LF.cjs} +4 -4
  54. package/dist/{chunk-SCVIBVFS.cjs.map → chunk-WQXWH7LF.cjs.map} +1 -1
  55. package/dist/{chunk-7COFWOCJ.cjs → chunk-XNEPABUD.cjs} +22 -22
  56. package/dist/{chunk-7COFWOCJ.cjs.map → chunk-XNEPABUD.cjs.map} +1 -1
  57. package/dist/{chunk-QYDIVL4X.js → chunk-YB5DFQKD.js} +6 -6
  58. package/dist/components/case-studies/index.cjs +9 -9
  59. package/dist/components/case-studies/index.js +3 -3
  60. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  61. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  62. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  63. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
  64. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +1 -4
  65. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  66. package/dist/components/chat/hooks/use-slash-commands.d.ts +3 -3
  67. package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -1
  68. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +28 -2
  69. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  70. package/dist/components/chat/index.cjs +2 -2
  71. package/dist/components/chat/index.js +1 -1
  72. package/dist/components/chat/remark-strip-citations.d.ts.map +1 -1
  73. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -1
  74. package/dist/components/chat/tool-execution-display.d.ts.map +1 -1
  75. package/dist/components/chat/types/component.types.d.ts +0 -4
  76. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  77. package/dist/components/chat/types/message.types.d.ts +1 -35
  78. package/dist/components/chat/types/message.types.d.ts.map +1 -1
  79. package/dist/components/chat/types/unified-chat-state.types.d.ts +3 -3
  80. package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
  81. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  82. package/dist/components/contact/index.cjs +4 -4
  83. package/dist/components/contact/index.js +3 -3
  84. package/dist/components/docs/index.cjs +7 -7
  85. package/dist/components/docs/index.js +6 -6
  86. package/dist/components/embeds/index.cjs +4 -4
  87. package/dist/components/embeds/index.js +3 -3
  88. package/dist/components/faq/index.cjs +4 -4
  89. package/dist/components/faq/index.js +3 -3
  90. package/dist/components/features/index.cjs +3 -3
  91. package/dist/components/features/index.js +2 -2
  92. package/dist/components/help-center-pages/index.cjs +23 -23
  93. package/dist/components/help-center-pages/index.js +14 -14
  94. package/dist/components/index.cjs +36 -36
  95. package/dist/components/index.js +13 -13
  96. package/dist/components/meeting-scheduler/index.cjs +21 -21
  97. package/dist/components/meeting-scheduler/index.js +2 -2
  98. package/dist/components/navigation/index.cjs +6 -6
  99. package/dist/components/navigation/index.js +5 -5
  100. package/dist/components/onboarding-guides/index.cjs +6 -6
  101. package/dist/components/onboarding-guides/index.js +5 -5
  102. package/dist/components/tickets/index.cjs +7 -7
  103. package/dist/components/tickets/index.js +6 -6
  104. package/dist/components/ui/data-table/use-data-table.d.ts.map +1 -1
  105. package/dist/components/ui/hover-dropdown.d.ts.map +1 -1
  106. package/dist/components/ui/index.cjs +3 -3
  107. package/dist/components/ui/index.js +2 -2
  108. package/dist/index.cjs +7 -7
  109. package/dist/index.js +6 -6
  110. package/dist/utils/index.cjs.map +1 -1
  111. package/dist/utils/index.js.map +1 -1
  112. package/package.json +1 -2
  113. package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +0 -130
  114. package/src/chat-protocol/events.ts +1 -9
  115. package/src/chat-protocol/nats-decoder.ts +0 -7
  116. package/src/components/chat/__tests__/chat-message-list.test.tsx +0 -70
  117. package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +0 -86
  118. package/src/components/chat/chat-message-enhanced.tsx +13 -28
  119. package/src/components/chat/chat-message-list.tsx +22 -27
  120. package/src/components/chat/embeddable-chat.tsx +36 -55
  121. package/src/components/chat/entity-cards/dispatch.tsx +17 -86
  122. package/src/components/chat/hooks/use-nats-chat-adapter.ts +0 -7
  123. package/src/components/chat/hooks/use-slash-commands.ts +5 -9
  124. package/src/components/chat/hooks/use-sse-chat-adapter.ts +29 -2
  125. package/src/components/chat/remark-strip-citations.ts +3 -5
  126. package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +0 -56
  127. package/src/components/chat/stream/chat-stream-reducer.ts +0 -31
  128. package/src/components/chat/tool-execution-display.tsx +2 -5
  129. package/src/components/chat/types/component.types.ts +0 -4
  130. package/src/components/chat/types/message.types.ts +0 -39
  131. package/src/components/chat/types/unified-chat-state.types.ts +3 -4
  132. package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +0 -57
  133. package/src/components/chat/utils/process-historical-messages.ts +1 -19
  134. package/src/components/ui/__tests__/data-table-compiler-identity.test.tsx +74 -0
  135. package/src/components/ui/data-table/use-data-table.ts +36 -1
  136. package/src/components/ui/hover-dropdown.tsx +3 -8
  137. package/dist/chat-protocol/source-metadata.d.ts +0 -5
  138. package/dist/chat-protocol/source-metadata.d.ts.map +0 -1
  139. package/dist/chunk-4MVGFYRE.js.map +0 -1
  140. package/dist/chunk-EKKR5ZFB.cjs.map +0 -1
  141. package/dist/chunk-UYHETUX3.cjs.map +0 -1
  142. package/dist/components/chat/utils/chat-source-metadata.d.ts +0 -5
  143. package/dist/components/chat/utils/chat-source-metadata.d.ts.map +0 -1
  144. package/src/chat-protocol/__tests__/source-metadata.test.ts +0 -74
  145. package/src/chat-protocol/source-metadata.ts +0 -202
  146. package/src/components/chat/__tests__/embeddable-chat-sources.test.tsx +0 -411
  147. package/src/components/chat/__tests__/remark-strip-citations.test.ts +0 -52
  148. package/src/components/chat/__tests__/tool-execution-display.test.tsx +0 -93
  149. package/src/components/chat/entity-cards/__tests__/dispatch-video-refs.test.tsx +0 -74
  150. package/src/components/chat/hooks/__tests__/use-slash-commands.test.ts +0 -64
  151. package/src/components/chat/utils/chat-source-metadata.ts +0 -19
  152. /package/dist/{chunk-RE3KVI2Q.js.map → chunk-3PDTGDOA.js.map} +0 -0
  153. /package/dist/{chunk-5X7AJ67N.js.map → chunk-436G4DI4.js.map} +0 -0
  154. /package/dist/{chunk-7A6J4JTW.js.map → chunk-6BFEJXMI.js.map} +0 -0
  155. /package/dist/{chunk-RQ5PYSRJ.js.map → chunk-BLJEPNMJ.js.map} +0 -0
  156. /package/dist/{chunk-WFWWQO2I.js.map → chunk-F3YRPKUA.js.map} +0 -0
  157. /package/dist/{chunk-FDWGO244.js.map → chunk-LODCKZ72.js.map} +0 -0
  158. /package/dist/{chunk-E2QFZDCP.js.map → chunk-OKD7MX7Y.js.map} +0 -0
  159. /package/dist/{chunk-OW3FUJ2I.js.map → chunk-P24OI2CD.js.map} +0 -0
  160. /package/dist/{chunk-QSO24MEK.js.map → chunk-R2U2D7LU.js.map} +0 -0
  161. /package/dist/{chunk-KQWI25NP.js.map → chunk-SI57FQZ2.js.map} +0 -0
  162. /package/dist/{chunk-JQO47UHC.js.map → chunk-SVR75PFW.js.map} +0 -0
  163. /package/dist/{chunk-OZRT3ZI3.js.map → chunk-V4WUSOGS.js.map} +0 -0
  164. /package/dist/{chunk-UODM3HJC.js.map → chunk-VWNU2PFX.js.map} +0 -0
  165. /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 { ChatSource, MessageSegment, ScrollAnchor } from './message.types';
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
- /** Document citations for a Guide answer over SSE or NATS. */
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 { decodeNatsChunk, normalizeAskOptions } from '../../../chat-protocol/nats-decoder';
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
- return useReactTable<T>({
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. The first desktop click can arrive
166
- // after mouse-enter already opened the panel; pin it open instead of blindly
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
- const pinned = !clickPinnedRef.current;
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"}