@flamingo-stack/openframe-frontend-core 0.0.589-1973.5571.2 → 0.0.589-2013.5572.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-CQNILR7U.js → chunk-3OCYNMZ5.js} +3 -3
  9. package/dist/{chunk-OAY342OE.js → chunk-4ZKAMPBX.js} +2 -2
  10. package/dist/{chunk-NHW2AM2X.cjs → chunk-5CHW7AMP.cjs} +10 -10
  11. package/dist/{chunk-NHW2AM2X.cjs.map → chunk-5CHW7AMP.cjs.map} +1 -1
  12. package/dist/{chunk-WZZSFOWG.js → chunk-5FNWOF46.js} +6 -6
  13. package/dist/{chunk-YEEMXD25.js → chunk-77Y7R243.js} +5 -5
  14. package/dist/{chunk-DVAAXDZV.cjs → chunk-A6X7EXP6.cjs} +10 -10
  15. package/dist/{chunk-DVAAXDZV.cjs.map → chunk-A6X7EXP6.cjs.map} +1 -1
  16. package/dist/{chunk-GOHHFX4O.cjs → chunk-ADANP3ZA.cjs} +33 -33
  17. package/dist/{chunk-GOHHFX4O.cjs.map → chunk-ADANP3ZA.cjs.map} +1 -1
  18. package/dist/{chunk-DPQGO4PH.cjs → chunk-BONXSRHZ.cjs} +21 -21
  19. package/dist/{chunk-DPQGO4PH.cjs.map → chunk-BONXSRHZ.cjs.map} +1 -1
  20. package/dist/{chunk-XTMNO7MC.cjs → chunk-C6RJRSIM.cjs} +3 -3
  21. package/dist/{chunk-XTMNO7MC.cjs.map → chunk-C6RJRSIM.cjs.map} +1 -1
  22. package/dist/{chunk-G4ND6ZZK.js → chunk-CJOWLRUU.js} +2 -2
  23. package/dist/{chunk-EJEHIAOV.js → chunk-CN36E4PK.js} +2 -2
  24. package/dist/{chunk-SPOIDC23.js → chunk-CNKVEVUN.js} +5 -5
  25. package/dist/{chunk-4MVGFYRE.js → chunk-D7YISHXC.js} +190 -534
  26. package/dist/chunk-D7YISHXC.js.map +1 -0
  27. package/dist/{chunk-NNRRRWCD.cjs → chunk-EGUU3QCU.cjs} +3 -3
  28. package/dist/{chunk-NNRRRWCD.cjs.map → chunk-EGUU3QCU.cjs.map} +1 -1
  29. package/dist/{chunk-HQKWJFFX.cjs → chunk-EGYX55HT.cjs} +159 -159
  30. package/dist/{chunk-HQKWJFFX.cjs.map → chunk-EGYX55HT.cjs.map} +1 -1
  31. package/dist/{chunk-XW4GOMK6.js → chunk-FQBR6SCA.js} +3 -3
  32. package/dist/{chunk-XIKSZSHC.cjs → chunk-FVRRYJ6P.cjs} +22 -22
  33. package/dist/{chunk-XIKSZSHC.cjs.map → chunk-FVRRYJ6P.cjs.map} +1 -1
  34. package/dist/{chunk-EKKR5ZFB.cjs → chunk-G45RGWHF.cjs} +543 -887
  35. package/dist/chunk-G45RGWHF.cjs.map +1 -0
  36. package/dist/{chunk-47NIV4FC.js → chunk-GKPY7VLK.js} +4 -4
  37. package/dist/{chunk-4VDGIODG.js → chunk-I5CJJFEJ.js} +3 -3
  38. package/dist/{chunk-FIEOWSXH.cjs → chunk-IYDHV2CS.cjs} +43 -43
  39. package/dist/{chunk-FIEOWSXH.cjs.map → chunk-IYDHV2CS.cjs.map} +1 -1
  40. package/dist/{chunk-MQFA5DXU.cjs → chunk-JDINUWND.cjs} +69 -69
  41. package/dist/{chunk-MQFA5DXU.cjs.map → chunk-JDINUWND.cjs.map} +1 -1
  42. package/dist/{chunk-NIHPN72N.cjs → chunk-KK3XU6YJ.cjs} +4 -4
  43. package/dist/{chunk-NIHPN72N.cjs.map → chunk-KK3XU6YJ.cjs.map} +1 -1
  44. package/dist/{chunk-GU5TWGAJ.js → chunk-KVNGYFFP.js} +3 -3
  45. package/dist/{chunk-GDHQTVBP.cjs → chunk-KWTV3KGY.cjs} +9 -9
  46. package/dist/{chunk-GDHQTVBP.cjs.map → chunk-KWTV3KGY.cjs.map} +1 -1
  47. package/dist/{chunk-YTVTZ7JO.js → chunk-LGBNHWDN.js} +3 -3
  48. package/dist/{chunk-T5FJOWHA.cjs → chunk-MENQLD57.cjs} +5 -5
  49. package/dist/{chunk-T5FJOWHA.cjs.map → chunk-MENQLD57.cjs.map} +1 -1
  50. package/dist/{chunk-QIHBS5PM.js → chunk-NIDPX52C.js} +5 -5
  51. package/dist/{chunk-HZ6VUTLA.js → chunk-NXZC6UTN.js} +2 -2
  52. package/dist/{chunk-627JVTID.cjs → chunk-PAUJQV3C.cjs} +15 -15
  53. package/dist/{chunk-627JVTID.cjs.map → chunk-PAUJQV3C.cjs.map} +1 -1
  54. package/dist/{chunk-PDFH7CXB.js → chunk-TOYHZHTK.js} +2 -2
  55. package/dist/{chunk-KH5KDKCE.cjs → chunk-WUCYI3BC.cjs} +24 -24
  56. package/dist/{chunk-KH5KDKCE.cjs.map → chunk-WUCYI3BC.cjs.map} +1 -1
  57. package/dist/components/case-studies/index.cjs +9 -9
  58. package/dist/components/case-studies/index.js +3 -3
  59. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  60. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  61. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  62. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -1
  63. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +1 -4
  64. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  65. package/dist/components/chat/hooks/use-slash-commands.d.ts +3 -3
  66. package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -1
  67. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +28 -2
  68. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  69. package/dist/components/chat/index.cjs +2 -2
  70. package/dist/components/chat/index.js +1 -1
  71. package/dist/components/chat/remark-strip-citations.d.ts.map +1 -1
  72. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -1
  73. package/dist/components/chat/tool-execution-display.d.ts.map +1 -1
  74. package/dist/components/chat/types/component.types.d.ts +0 -4
  75. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  76. package/dist/components/chat/types/message.types.d.ts +1 -35
  77. package/dist/components/chat/types/message.types.d.ts.map +1 -1
  78. package/dist/components/chat/types/unified-chat-state.types.d.ts +3 -3
  79. package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
  80. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  81. package/dist/components/contact/index.cjs +4 -4
  82. package/dist/components/contact/index.js +3 -3
  83. package/dist/components/docs/index.cjs +7 -7
  84. package/dist/components/docs/index.js +6 -6
  85. package/dist/components/embeds/index.cjs +4 -4
  86. package/dist/components/embeds/index.js +3 -3
  87. package/dist/components/faq/index.cjs +4 -4
  88. package/dist/components/faq/index.js +3 -3
  89. package/dist/components/features/index.cjs +3 -3
  90. package/dist/components/features/index.js +2 -2
  91. package/dist/components/help-center-pages/index.cjs +23 -23
  92. package/dist/components/help-center-pages/index.js +14 -14
  93. package/dist/components/index.cjs +36 -36
  94. package/dist/components/index.js +13 -13
  95. package/dist/components/meeting-scheduler/index.cjs +21 -21
  96. package/dist/components/meeting-scheduler/index.js +2 -2
  97. package/dist/components/navigation/index.cjs +6 -6
  98. package/dist/components/navigation/index.js +5 -5
  99. package/dist/components/onboarding-guides/index.cjs +6 -6
  100. package/dist/components/onboarding-guides/index.js +5 -5
  101. package/dist/components/tickets/index.cjs +7 -7
  102. package/dist/components/tickets/index.js +6 -6
  103. package/dist/components/ui/data-table/types.d.ts +13 -0
  104. package/dist/components/ui/data-table/types.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/data-table/.types.md +1 -1
  135. package/src/components/ui/data-table/types.ts +13 -0
  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/components/chat/utils/chat-source-metadata.d.ts +0 -5
  142. package/dist/components/chat/utils/chat-source-metadata.d.ts.map +0 -1
  143. package/src/chat-protocol/__tests__/source-metadata.test.ts +0 -74
  144. package/src/chat-protocol/source-metadata.ts +0 -202
  145. package/src/components/chat/__tests__/embeddable-chat-sources.test.tsx +0 -411
  146. package/src/components/chat/__tests__/remark-strip-citations.test.ts +0 -52
  147. package/src/components/chat/__tests__/tool-execution-display.test.tsx +0 -93
  148. package/src/components/chat/entity-cards/__tests__/dispatch-video-refs.test.tsx +0 -74
  149. package/src/components/chat/hooks/__tests__/use-slash-commands.test.ts +0 -64
  150. package/src/components/chat/utils/chat-source-metadata.ts +0 -19
  151. /package/dist/{chunk-CQNILR7U.js.map → chunk-3OCYNMZ5.js.map} +0 -0
  152. /package/dist/{chunk-OAY342OE.js.map → chunk-4ZKAMPBX.js.map} +0 -0
  153. /package/dist/{chunk-WZZSFOWG.js.map → chunk-5FNWOF46.js.map} +0 -0
  154. /package/dist/{chunk-YEEMXD25.js.map → chunk-77Y7R243.js.map} +0 -0
  155. /package/dist/{chunk-G4ND6ZZK.js.map → chunk-CJOWLRUU.js.map} +0 -0
  156. /package/dist/{chunk-EJEHIAOV.js.map → chunk-CN36E4PK.js.map} +0 -0
  157. /package/dist/{chunk-SPOIDC23.js.map → chunk-CNKVEVUN.js.map} +0 -0
  158. /package/dist/{chunk-XW4GOMK6.js.map → chunk-FQBR6SCA.js.map} +0 -0
  159. /package/dist/{chunk-47NIV4FC.js.map → chunk-GKPY7VLK.js.map} +0 -0
  160. /package/dist/{chunk-4VDGIODG.js.map → chunk-I5CJJFEJ.js.map} +0 -0
  161. /package/dist/{chunk-GU5TWGAJ.js.map → chunk-KVNGYFFP.js.map} +0 -0
  162. /package/dist/{chunk-YTVTZ7JO.js.map → chunk-LGBNHWDN.js.map} +0 -0
  163. /package/dist/{chunk-QIHBS5PM.js.map → chunk-NIDPX52C.js.map} +0 -0
  164. /package/dist/{chunk-HZ6VUTLA.js.map → chunk-NXZC6UTN.js.map} +0 -0
  165. /package/dist/{chunk-PDFH7CXB.js.map → chunk-TOYHZHTK.js.map} +0 -0
@@ -1,52 +0,0 @@
1
- import type { Root } from 'mdast';
2
- import { unified } from 'unified';
3
- import { describe, expect, it } from 'vitest';
4
- import { remarkStripCitations } from '../remark-strip-citations';
5
-
6
- describe('remarkStripCitations', () => {
7
- it('removes a citation-only list without leaving broken punctuation', () => {
8
- const tree: Root = {
9
- type: 'root',
10
- children: [
11
- {
12
- type: 'paragraph',
13
- children: [{ type: 'text', value: 'Sources [1], [2], and [3] are cited.' }],
14
- },
15
- ],
16
- };
17
-
18
- const result = unified().use(remarkStripCitations).runSync(tree);
19
-
20
- expect(result).toMatchObject({
21
- children: [
22
- {
23
- children: [{ type: 'text', value: 'Sources are cited.' }],
24
- },
25
- ],
26
- });
27
- });
28
-
29
- it('keeps prose punctuation while removing individual citations', () => {
30
- const tree: Root = {
31
- type: 'root',
32
- children: [
33
- {
34
- type: 'paragraph',
35
- children: [
36
- { type: 'text', value: 'Install on Windows [1], verify the service [2], and confirm Devices [3].' },
37
- ],
38
- },
39
- ],
40
- };
41
-
42
- const result = unified().use(remarkStripCitations).runSync(tree);
43
-
44
- expect(result).toMatchObject({
45
- children: [
46
- {
47
- children: [{ type: 'text', value: 'Install on Windows, verify the service, and confirm Devices.' }],
48
- },
49
- ],
50
- });
51
- });
52
- });
@@ -1,93 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
3
- import { decodeNatsChunk } from '../../../chat-protocol/nats-decoder';
4
- import { createChatStreamReducer } from '../stream/chat-stream-reducer';
5
- import { ToolExecutionDisplay } from '../tool-execution-display';
6
- import type { ToolExecutionData } from '../types';
7
-
8
- const execution = (overrides: Partial<ToolExecutionData>): ToolExecutionData => ({
9
- type: 'EXECUTING_TOOL',
10
- integratedToolType: 'OPENFRAME',
11
- toolFunction: 'search_docs',
12
- ...overrides,
13
- });
14
-
15
- beforeAll(() => {
16
- vi.stubGlobal(
17
- 'ResizeObserver',
18
- class {
19
- observe(): void {}
20
- disconnect(): void {}
21
- unobserve(): void {}
22
- },
23
- );
24
- });
25
-
26
- afterAll(() => {
27
- vi.unstubAllGlobals();
28
- });
29
-
30
- describe('ToolExecutionDisplay remote read activity', () => {
31
- it('keeps a completed remote read concise through the real wire pipeline', () => {
32
- const reducer = createChatStreamReducer({ transport: 'nats' });
33
- for (const chunk of [
34
- {
35
- type: 'EXECUTING_TOOL',
36
- integratedToolType: null,
37
- toolFunction: 'remote_read',
38
- title: 'Searching product documentation',
39
- parameters: null,
40
- toolExecutionRequestId: 'remote-read-1',
41
- },
42
- {
43
- type: 'EXECUTED_TOOL',
44
- integratedToolType: null,
45
- toolFunction: 'remote_read',
46
- result: null,
47
- success: true,
48
- toolExecutionRequestId: 'remote-read-1',
49
- },
50
- ]) {
51
- const event = decodeNatsChunk(chunk);
52
- if (event) reducer.apply(event);
53
- }
54
- const toolSegment = reducer.state.messages
55
- .flatMap(message => message.segments ?? [])
56
- .find(segment => segment.type === 'tool_execution');
57
-
58
- expect(toolSegment?.type).toBe('tool_execution');
59
- if (toolSegment?.type !== 'tool_execution') return;
60
- render(<ToolExecutionDisplay message={toolSegment.data} />);
61
-
62
- expect(screen.getByText('Searching product documentation')).toBeInTheDocument();
63
- expect(screen.queryByRole('button')).not.toBeInTheDocument();
64
- expect(screen.queryByText('Remote read')).not.toBeInTheDocument();
65
- });
66
-
67
- it('keeps a typed local tool expandable when its body is absent', () => {
68
- render(
69
- <ToolExecutionDisplay
70
- message={execution({
71
- integratedToolType: 'OPENFRAME',
72
- toolTitle: 'Refresh device inventory',
73
- })}
74
- />,
75
- );
76
-
77
- expect(screen.getByRole('button')).toBeInTheDocument();
78
- });
79
-
80
- it('keeps a backend-described remote read concise while running', () => {
81
- render(
82
- <ToolExecutionDisplay
83
- message={execution({
84
- integratedToolType: undefined,
85
- toolTitle: 'Searching product documentation',
86
- })}
87
- />,
88
- );
89
-
90
- expect(screen.getByText('Searching product documentation')).toBeInTheDocument();
91
- expect(screen.queryByRole('button')).not.toBeInTheDocument();
92
- });
93
- });
@@ -1,74 +0,0 @@
1
- import React from 'react';
2
- import { describe, expect, it } from 'vitest';
3
- import type { ChatRef } from '../../chat-ref.types';
4
- import { BlockCard } from '../block-card';
5
- import { ChatVideoEntityCard } from '../chat-video-entity-card';
6
- import { renderChatInlineEntityCard } from '../dispatch';
7
-
8
- describe('renderChatInlineEntityCard video refs', () => {
9
- it.each([
10
- {
11
- id: 'MdFJNoJeqZQ',
12
- url: 'https://www.youtube.com/watch?v=MdFJNoJeqZQ',
13
- metadata: { youtubeUrl: 'MdFJNoJeqZQ' },
14
- },
15
- {
16
- id: 'mux-9b6586b494',
17
- url: 'https://stream.mux.com/playback-id.m3u8',
18
- metadata: { videoUrl: 'https://stream.mux.com/playback-id.m3u8' },
19
- },
20
- {
21
- id: 'mp4-1b2047dc1b',
22
- url: 'https://cdn.example.test/product-overview.mp4',
23
- metadata: { videoUrl: 'https://cdn.example.test/product-overview.mp4' },
24
- },
25
- ])('passes playable metadata for $id to the video card', ({ id, url, metadata }) => {
26
- const ref: ChatRef = { type: 'video', id, title: 'Video', url, metadata };
27
-
28
- const result = renderChatInlineEntityCard(ref);
29
-
30
- expect(React.isValidElement(result)).toBe(true);
31
- const block = result as React.ReactElement<React.ComponentProps<typeof BlockCard>>;
32
- expect(block.type).toBe(BlockCard);
33
- const video = block.props.children as React.ReactElement<React.ComponentProps<typeof ChatVideoEntityCard>>;
34
- expect(video.type).toBe(ChatVideoEntityCard);
35
- expect(video.props.chatRef.metadata).toMatchObject(metadata);
36
- });
37
-
38
- it('lets a validated top-level URL override conflicting route metadata', () => {
39
- const ref: ChatRef = {
40
- type: 'video',
41
- id: 'mux-9b6586b494',
42
- title: 'Video',
43
- url: 'https://stream.mux.com/trusted-playback.m3u8',
44
- metadata: {
45
- videoUrl: 'https://cdn.example.test/untrusted.mp4',
46
- youtubeUrl: 'untrustedId',
47
- },
48
- };
49
-
50
- const result = renderChatInlineEntityCard(ref);
51
- const block = result as React.ReactElement<React.ComponentProps<typeof BlockCard>>;
52
- const video = block.props.children as React.ReactElement<React.ComponentProps<typeof ChatVideoEntityCard>>;
53
-
54
- expect(video.props.chatRef.metadata).toEqual({
55
- videoUrl: 'https://stream.mux.com/trusted-playback.m3u8',
56
- });
57
- });
58
-
59
- it('keeps a direct-video URL direct when its query mentions a YouTube URL', () => {
60
- const directUrl = 'https://cdn.example.test/product-overview.mp4?source=youtube.com/watch?v=MdFJNoJeqZQ';
61
- const ref: ChatRef = {
62
- type: 'video',
63
- id: 'mp4-direct',
64
- title: 'Product overview',
65
- url: directUrl,
66
- };
67
-
68
- const result = renderChatInlineEntityCard(ref);
69
- const block = result as React.ReactElement<React.ComponentProps<typeof BlockCard>>;
70
- const video = block.props.children as React.ReactElement<React.ComponentProps<typeof ChatVideoEntityCard>>;
71
-
72
- expect(video.props.chatRef.metadata).toEqual({ videoUrl: directUrl });
73
- });
74
- });
@@ -1,64 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest';
2
- import type { SlashCommandSummary } from '../../types/component.types';
3
-
4
- const { embedAuthedFetchMock } = vi.hoisted(() => ({
5
- embedAuthedFetchMock: vi.fn(),
6
- }));
7
-
8
- vi.mock('../../../../utils/embed-authed-fetch', () => ({
9
- embedAuthedFetch: embedAuthedFetchMock,
10
- }));
11
-
12
- import { fetchSlashCommands } from '../use-slash-commands';
13
-
14
- const command = (id: string): SlashCommandSummary => ({
15
- id,
16
- description: `${id} description`,
17
- actions: [{ id: 'browse', label: 'Recent' }],
18
- });
19
-
20
- const commandsUrl = 'https://hub.example/api/docs/commands';
21
-
22
- describe('fetchSlashCommands', () => {
23
- beforeEach(() => {
24
- embedAuthedFetchMock.mockReset();
25
- });
26
-
27
- it('fetches the full registry and filters normalized prefixes locally', async () => {
28
- embedAuthedFetchMock.mockResolvedValue({
29
- ok: true,
30
- json: () => Promise.resolve({ commands: [command('roadmap'), command('webinars')] }),
31
- });
32
-
33
- const commands = await fetchSlashCommands(' W ', undefined, commandsUrl);
34
-
35
- expect(commands.map(({ id }) => id)).toEqual(['webinars']);
36
- expect(embedAuthedFetchMock).toHaveBeenCalledTimes(1);
37
- const [requestedUrl] = embedAuthedFetchMock.mock.calls[0] as [string];
38
- expect(new URL(requestedUrl).search).toBe('');
39
- });
40
-
41
- it('returns every command for an empty prefix', async () => {
42
- const registry = [command('roadmap'), command('webinars')];
43
- embedAuthedFetchMock.mockResolvedValue({
44
- ok: true,
45
- json: () => Promise.resolve({ commands: registry }),
46
- });
47
-
48
- await expect(fetchSlashCommands('', undefined, commandsUrl)).resolves.toEqual(registry);
49
- });
50
-
51
- it('caps non-empty prefix matches at ten commands', async () => {
52
- embedAuthedFetchMock.mockResolvedValue({
53
- ok: true,
54
- json: () =>
55
- Promise.resolve({
56
- commands: Array.from({ length: 12 }, (_, index) => command(`webinar-${index}`)),
57
- }),
58
- });
59
-
60
- const commands = await fetchSlashCommands('webinar', undefined, commandsUrl);
61
-
62
- expect(commands).toHaveLength(10);
63
- });
64
- });
@@ -1,19 +0,0 @@
1
- import type { ChatRef } from '../chat-ref.types';
2
- import type { ChatSource } from '../types/message.types';
3
-
4
- export function mergeChatSources(current: ChatSource[] | undefined, incoming: ChatSource[]): ChatSource[] {
5
- const sourcesByIndex = new Map((current ?? []).map(source => [source.index, source]));
6
- incoming.forEach(source => {
7
- if (!sourcesByIndex.has(source.index)) sourcesByIndex.set(source.index, source);
8
- });
9
- return Array.from(sourcesByIndex.values());
10
- }
11
-
12
- export function mergeChatRefs(current: ChatRef[] | undefined, incoming: ChatRef[]): ChatRef[] {
13
- const refsByIdentity = new Map((current ?? []).map(ref => [`${ref.type}:${ref.id}`, ref]));
14
- incoming.forEach(ref => {
15
- const identity = `${ref.type}:${ref.id}`;
16
- if (!refsByIdentity.has(identity)) refsByIdentity.set(identity, ref);
17
- });
18
- return Array.from(refsByIdentity.values());
19
- }