@aleph-alpha/chat-kit 0.9.0 → 1.1.0

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 (263) hide show
  1. package/dist/{CkInput.vue_vue_type_script_setup_true_lang-DmcLXAgB.js → CkInput.vue_vue_type_script_setup_true_lang-DpYyyCgU.js} +481 -79
  2. package/dist/chat-kit.css +9 -14
  3. package/dist/components/base/CkAgentMessage/CkAgentMessage.stories.d.ts +20 -0
  4. package/dist/components/base/CkAgentMessage/CkAgentMessage.stories.d.ts.map +1 -1
  5. package/dist/components/base/CkAgentMessage/CkAgentMessage.vue.d.ts.map +1 -1
  6. package/dist/components/base/CkAgentMessage/index.d.ts +1 -0
  7. package/dist/components/base/CkAgentMessage/index.d.ts.map +1 -1
  8. package/dist/components/base/CkAgentMessage/types.d.ts +12 -0
  9. package/dist/components/base/CkAgentMessage/types.d.ts.map +1 -0
  10. package/dist/components/base/CkConversationLayout/CkConversationLayout.stories.d.ts +13 -0
  11. package/dist/components/base/CkConversationLayout/CkConversationLayout.stories.d.ts.map +1 -1
  12. package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts.map +1 -1
  13. package/dist/components/base/CkConversationLayout/types.d.ts +9 -2
  14. package/dist/components/base/CkConversationLayout/types.d.ts.map +1 -1
  15. package/dist/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.stories.d.ts +8 -0
  16. package/dist/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.stories.d.ts.map +1 -1
  17. package/dist/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.vue.d.ts +3 -15
  18. package/dist/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.vue.d.ts.map +1 -1
  19. package/dist/components/base/CkCopyMessageActionButton/index.d.ts +1 -0
  20. package/dist/components/base/CkCopyMessageActionButton/index.d.ts.map +1 -1
  21. package/dist/components/base/CkCopyMessageActionButton/types.d.ts +45 -0
  22. package/dist/components/base/CkCopyMessageActionButton/types.d.ts.map +1 -0
  23. package/dist/components/base/CkHistoryItem/CkHistoryItem.stories.d.ts +31 -0
  24. package/dist/components/base/CkHistoryItem/CkHistoryItem.stories.d.ts.map +1 -0
  25. package/dist/components/base/CkHistoryItem/CkHistoryItem.vue.d.ts +31 -0
  26. package/dist/components/base/CkHistoryItem/CkHistoryItem.vue.d.ts.map +1 -0
  27. package/dist/components/base/CkHistoryItem/activeIndicator.d.ts +15 -0
  28. package/dist/components/base/CkHistoryItem/activeIndicator.d.ts.map +1 -0
  29. package/dist/components/base/CkHistoryItem/index.d.ts +3 -0
  30. package/dist/components/base/CkHistoryItem/index.d.ts.map +1 -0
  31. package/dist/components/base/CkHistoryItem/types.d.ts +96 -0
  32. package/dist/components/base/CkHistoryItem/types.d.ts.map +1 -0
  33. package/dist/components/base/CkHistoryWrapper/CkHistoryWrapper.stories.d.ts +16 -0
  34. package/dist/components/base/CkHistoryWrapper/CkHistoryWrapper.stories.d.ts.map +1 -0
  35. package/dist/components/base/CkHistoryWrapper/CkHistoryWrapper.vue.d.ts +17 -0
  36. package/dist/components/base/CkHistoryWrapper/CkHistoryWrapper.vue.d.ts.map +1 -0
  37. package/dist/components/base/CkHistoryWrapper/index.d.ts +3 -0
  38. package/dist/components/base/CkHistoryWrapper/index.d.ts.map +1 -0
  39. package/dist/components/base/CkHistoryWrapper/types.d.ts +17 -0
  40. package/dist/components/base/CkHistoryWrapper/types.d.ts.map +1 -0
  41. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.d.ts +28 -0
  42. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.d.ts.map +1 -1
  43. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue.d.ts.map +1 -1
  44. package/dist/components/base/CkMarkdownRenderer/index.d.ts +1 -1
  45. package/dist/components/base/CkMarkdownRenderer/index.d.ts.map +1 -1
  46. package/dist/components/base/CkMarkdownRenderer/types.d.ts +16 -0
  47. package/dist/components/base/CkMarkdownRenderer/types.d.ts.map +1 -1
  48. package/dist/components/base/CkMessageActionButton/CkMessageActionButton.stories.d.ts +4 -0
  49. package/dist/components/base/CkMessageActionButton/CkMessageActionButton.stories.d.ts.map +1 -1
  50. package/dist/components/base/CkMessageActionButton/CkMessageActionButton.vue.d.ts +2 -5
  51. package/dist/components/base/CkMessageActionButton/CkMessageActionButton.vue.d.ts.map +1 -1
  52. package/dist/components/base/CkMessageActionButton/index.d.ts +1 -0
  53. package/dist/components/base/CkMessageActionButton/index.d.ts.map +1 -1
  54. package/dist/components/base/CkMessageActionButton/types.d.ts +22 -0
  55. package/dist/components/base/CkMessageActionButton/types.d.ts.map +1 -0
  56. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.stories.d.ts +12 -0
  57. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.stories.d.ts.map +1 -1
  58. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.vue.d.ts +2 -7
  59. package/dist/components/base/CkPromptActionButton/CkPromptActionButton.vue.d.ts.map +1 -1
  60. package/dist/components/base/CkPromptActionButton/index.d.ts +1 -0
  61. package/dist/components/base/CkPromptActionButton/index.d.ts.map +1 -1
  62. package/dist/components/base/CkPromptActionButton/types.d.ts +33 -0
  63. package/dist/components/base/CkPromptActionButton/types.d.ts.map +1 -0
  64. package/dist/components/base/CkPromptInput/CkPromptInput.stories.d.ts +17 -0
  65. package/dist/components/base/CkPromptInput/CkPromptInput.stories.d.ts.map +1 -1
  66. package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts +3 -9
  67. package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts.map +1 -1
  68. package/dist/components/base/CkPromptInput/index.d.ts +1 -0
  69. package/dist/components/base/CkPromptInput/index.d.ts.map +1 -1
  70. package/dist/components/base/CkPromptInput/types.d.ts +39 -0
  71. package/dist/components/base/CkPromptInput/types.d.ts.map +1 -0
  72. package/dist/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.stories.d.ts +12 -0
  73. package/dist/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.stories.d.ts.map +1 -1
  74. package/dist/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue.d.ts +2 -4
  75. package/dist/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue.d.ts.map +1 -1
  76. package/dist/components/base/CkPromptInputDisclaimer/index.d.ts +1 -0
  77. package/dist/components/base/CkPromptInputDisclaimer/index.d.ts.map +1 -1
  78. package/dist/components/base/CkPromptInputDisclaimer/types.d.ts +18 -0
  79. package/dist/components/base/CkPromptInputDisclaimer/types.d.ts.map +1 -0
  80. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.stories.d.ts +8 -0
  81. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.stories.d.ts.map +1 -1
  82. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.vue.d.ts +3 -6
  83. package/dist/components/base/CkPromptStopButton/CkPromptStopButton.vue.d.ts.map +1 -1
  84. package/dist/components/base/CkPromptStopButton/index.d.ts +1 -0
  85. package/dist/components/base/CkPromptStopButton/index.d.ts.map +1 -1
  86. package/dist/components/base/CkPromptStopButton/types.d.ts +28 -0
  87. package/dist/components/base/CkPromptStopButton/types.d.ts.map +1 -0
  88. package/dist/components/base/CkUserMessage/CkUserMessage.stories.d.ts +15 -0
  89. package/dist/components/base/CkUserMessage/CkUserMessage.stories.d.ts.map +1 -1
  90. package/dist/components/base/CkUserMessage/CkUserMessage.vue.d.ts.map +1 -1
  91. package/dist/components/base/CkUserMessage/types.d.ts +9 -2
  92. package/dist/components/base/CkUserMessage/types.d.ts.map +1 -1
  93. package/dist/components/base/icons/CkStopIcon.vue.d.ts.map +1 -1
  94. package/dist/components/base/index.d.ts +5 -1
  95. package/dist/components/base/index.d.ts.map +1 -1
  96. package/dist/components/composed/CkConversation/CkConversation.stories.d.ts +55 -0
  97. package/dist/components/composed/CkConversation/CkConversation.stories.d.ts.map +1 -1
  98. package/dist/components/composed/CkConversation/CkConversation.vue.d.ts.map +1 -1
  99. package/dist/components/composed/CkConversation/types.d.ts +25 -6
  100. package/dist/components/composed/CkConversation/types.d.ts.map +1 -1
  101. package/dist/components/composed/CkHistory/CkHistory.stories.d.ts +33 -0
  102. package/dist/components/composed/CkHistory/CkHistory.stories.d.ts.map +1 -0
  103. package/dist/components/composed/CkHistory/CkHistory.vue.d.ts +50 -0
  104. package/dist/components/composed/CkHistory/CkHistory.vue.d.ts.map +1 -0
  105. package/dist/components/composed/CkHistory/index.d.ts +3 -0
  106. package/dist/components/composed/CkHistory/index.d.ts.map +1 -0
  107. package/dist/components/composed/CkHistory/types.d.ts +71 -0
  108. package/dist/components/composed/CkHistory/types.d.ts.map +1 -0
  109. package/dist/components/composed/CkInput/CkInput.stories.d.ts +31 -1
  110. package/dist/components/composed/CkInput/CkInput.stories.d.ts.map +1 -1
  111. package/dist/components/composed/CkInput/CkInput.vue.d.ts +3 -12
  112. package/dist/components/composed/CkInput/CkInput.vue.d.ts.map +1 -1
  113. package/dist/components/composed/CkInput/index.d.ts +1 -0
  114. package/dist/components/composed/CkInput/index.d.ts.map +1 -1
  115. package/dist/components/composed/CkInput/types.d.ts +60 -0
  116. package/dist/components/composed/CkInput/types.d.ts.map +1 -0
  117. package/dist/components/composed/index.d.ts +2 -0
  118. package/dist/components/composed/index.d.ts.map +1 -1
  119. package/dist/components/index.d.ts +4 -4
  120. package/dist/components/index.d.ts.map +1 -1
  121. package/dist/components/index.js +14 -11
  122. package/dist/composables/index.d.ts +2 -0
  123. package/dist/composables/index.d.ts.map +1 -1
  124. package/dist/composables/index.js +3 -3
  125. package/dist/composables/useConversations.d.ts +72 -0
  126. package/dist/composables/useConversations.d.ts.map +1 -0
  127. package/dist/generateId-BHf0W4Rq.js +6 -0
  128. package/dist/handlers/index.js +2 -2
  129. package/dist/handlers/useChatKitLabels.d.ts +8 -0
  130. package/dist/handlers/useChatKitLabels.d.ts.map +1 -1
  131. package/dist/handlers/useMarkdownParser.d.ts.map +1 -1
  132. package/dist/helpers/conversationTree.d.ts.map +1 -1
  133. package/dist/helpers/index.d.ts +2 -0
  134. package/dist/helpers/index.d.ts.map +1 -1
  135. package/dist/helpers/secondsToDate.d.ts +6 -0
  136. package/dist/helpers/secondsToDate.d.ts.map +1 -0
  137. package/dist/helpers/toError.d.ts +7 -0
  138. package/dist/helpers/toError.d.ts.map +1 -0
  139. package/dist/index.d.ts +6 -6
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +20 -16
  142. package/dist/services/ChatService.d.ts.map +1 -1
  143. package/dist/services/MockChatService.d.ts.map +1 -1
  144. package/dist/services/index.d.ts +1 -1
  145. package/dist/services/index.d.ts.map +1 -1
  146. package/dist/services/index.js +4 -1
  147. package/dist/services/types.d.ts +53 -0
  148. package/dist/services/types.d.ts.map +1 -1
  149. package/dist/types.d.ts +13 -0
  150. package/dist/types.d.ts.map +1 -1
  151. package/dist/{useChatKitLabels-DNwoZ1x6.js → useChatKitLabels-Dvi2FmjE.js} +8 -2
  152. package/dist/useConversations-Ca242D2P.js +195 -0
  153. package/dist/{useMessageHandler-D7OdrrcB.js → useMessageHandler-uLHNac39.js} +1 -3
  154. package/package.json +5 -4
  155. package/src/components/base/CkAgentMessage/CkAgentMessage.spec.ts +91 -0
  156. package/src/components/base/CkAgentMessage/CkAgentMessage.stories.ts +215 -0
  157. package/src/components/base/CkAgentMessage/CkAgentMessage.vue +25 -0
  158. package/src/components/base/CkAgentMessage/index.ts +2 -0
  159. package/src/components/base/CkAgentMessage/types.ts +11 -0
  160. package/src/components/base/CkConversationLayout/CkConversationLayout.spec.ts +129 -0
  161. package/src/components/base/CkConversationLayout/CkConversationLayout.stories.ts +251 -0
  162. package/src/components/base/CkConversationLayout/CkConversationLayout.vue +206 -0
  163. package/src/components/base/CkConversationLayout/index.ts +2 -0
  164. package/src/components/base/CkConversationLayout/types.ts +18 -0
  165. package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.spec.ts +89 -0
  166. package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.stories.ts +70 -0
  167. package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.vue +110 -0
  168. package/src/components/base/CkCopyMessageActionButton/index.ts +2 -0
  169. package/src/components/base/CkCopyMessageActionButton/types.ts +43 -0
  170. package/src/components/base/CkHistoryItem/CkHistoryItem.spec.ts +42 -0
  171. package/src/components/base/CkHistoryItem/CkHistoryItem.stories.ts +230 -0
  172. package/src/components/base/CkHistoryItem/CkHistoryItem.vue +285 -0
  173. package/src/components/base/CkHistoryItem/activeIndicator.ts +15 -0
  174. package/src/components/base/CkHistoryItem/index.ts +2 -0
  175. package/src/components/base/CkHistoryItem/types.ts +111 -0
  176. package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.spec.ts +26 -0
  177. package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.stories.ts +149 -0
  178. package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.vue +36 -0
  179. package/src/components/base/CkHistoryWrapper/index.ts +2 -0
  180. package/src/components/base/CkHistoryWrapper/types.ts +16 -0
  181. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.spec.ts +348 -0
  182. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.ts +382 -0
  183. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue +89 -0
  184. package/src/components/base/CkMarkdownRenderer/defaultMarkdownClasses.ts +19 -0
  185. package/src/components/base/CkMarkdownRenderer/index.ts +5 -0
  186. package/src/components/base/CkMarkdownRenderer/types.ts +53 -0
  187. package/src/components/base/CkMessageActionButton/CkMessageActionButton.spec.ts +40 -0
  188. package/src/components/base/CkMessageActionButton/CkMessageActionButton.stories.ts +56 -0
  189. package/src/components/base/CkMessageActionButton/CkMessageActionButton.vue +23 -0
  190. package/src/components/base/CkMessageActionButton/index.ts +2 -0
  191. package/src/components/base/CkMessageActionButton/types.ts +21 -0
  192. package/src/components/base/CkPromptActionButton/CkPromptActionButton.spec.ts +52 -0
  193. package/src/components/base/CkPromptActionButton/CkPromptActionButton.stories.ts +126 -0
  194. package/src/components/base/CkPromptActionButton/CkPromptActionButton.vue +25 -0
  195. package/src/components/base/CkPromptActionButton/index.ts +2 -0
  196. package/src/components/base/CkPromptActionButton/types.ts +32 -0
  197. package/src/components/base/CkPromptInput/CkPromptInput.spec.ts +181 -0
  198. package/src/components/base/CkPromptInput/CkPromptInput.stories.ts +224 -0
  199. package/src/components/base/CkPromptInput/CkPromptInput.vue +104 -0
  200. package/src/components/base/CkPromptInput/index.ts +2 -0
  201. package/src/components/base/CkPromptInput/types.ts +39 -0
  202. package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.spec.ts +40 -0
  203. package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.stories.ts +103 -0
  204. package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue +16 -0
  205. package/src/components/base/CkPromptInputDisclaimer/index.ts +2 -0
  206. package/src/components/base/CkPromptInputDisclaimer/types.ts +17 -0
  207. package/src/components/base/CkPromptStopButton/CkPromptStopButton.spec.ts +64 -0
  208. package/src/components/base/CkPromptStopButton/CkPromptStopButton.stories.ts +81 -0
  209. package/src/components/base/CkPromptStopButton/CkPromptStopButton.vue +27 -0
  210. package/src/components/base/CkPromptStopButton/index.ts +2 -0
  211. package/src/components/base/CkPromptStopButton/types.ts +28 -0
  212. package/src/components/base/CkUserMessage/CkUserMessage.spec.ts +20 -0
  213. package/src/components/base/CkUserMessage/CkUserMessage.stories.ts +112 -0
  214. package/src/components/base/CkUserMessage/CkUserMessage.vue +19 -0
  215. package/src/components/base/CkUserMessage/index.ts +2 -0
  216. package/src/components/base/CkUserMessage/types.ts +14 -0
  217. package/src/components/base/icons/CkSendIcon.vue +22 -0
  218. package/src/components/base/icons/CkStopIcon.vue +18 -0
  219. package/src/components/base/icons/index.ts +2 -0
  220. package/src/components/base/index.ts +21 -0
  221. package/src/components/composed/CkConversation/CkConversation.spec.ts +439 -0
  222. package/src/components/composed/CkConversation/CkConversation.stories.ts +642 -0
  223. package/src/components/composed/CkConversation/CkConversation.vue +146 -0
  224. package/src/components/composed/CkConversation/index.ts +2 -0
  225. package/src/components/composed/CkConversation/types.ts +37 -0
  226. package/src/components/composed/CkHistory/CkHistory.spec.ts +327 -0
  227. package/src/components/composed/CkHistory/CkHistory.stories.ts +373 -0
  228. package/src/components/composed/CkHistory/CkHistory.vue +126 -0
  229. package/src/components/composed/CkHistory/index.ts +2 -0
  230. package/src/components/composed/CkHistory/types.ts +72 -0
  231. package/src/components/composed/CkInput/CkInput.spec.ts +191 -0
  232. package/src/components/composed/CkInput/CkInput.stories.ts +438 -0
  233. package/src/components/composed/CkInput/CkInput.vue +104 -0
  234. package/src/components/composed/CkInput/index.ts +2 -0
  235. package/src/components/composed/CkInput/types.ts +60 -0
  236. package/src/components/composed/index.ts +5 -0
  237. package/src/components/index.ts +34 -0
  238. package/src/composables/index.ts +9 -0
  239. package/src/composables/types.ts +36 -0
  240. package/src/composables/useChat.ts +18 -0
  241. package/src/composables/useConversations.spec.ts +557 -0
  242. package/src/composables/useConversations.ts +321 -0
  243. package/src/handlers/index.ts +9 -0
  244. package/src/handlers/useChatKitLabels.spec.ts +290 -0
  245. package/src/handlers/useChatKitLabels.ts +96 -0
  246. package/src/handlers/useMarkdownParser.spec.ts +112 -0
  247. package/src/handlers/useMarkdownParser.ts +47 -0
  248. package/src/handlers/useMessageHandler.spec.ts +535 -0
  249. package/src/handlers/useMessageHandler.ts +138 -0
  250. package/src/helpers/conversationTree.spec.ts +423 -0
  251. package/src/helpers/conversationTree.ts +117 -0
  252. package/src/helpers/generateId.ts +5 -0
  253. package/src/helpers/index.ts +4 -0
  254. package/src/helpers/secondsToDate.ts +7 -0
  255. package/src/helpers/toError.ts +8 -0
  256. package/src/index.ts +79 -0
  257. package/src/services/ChatService.ts +60 -0
  258. package/src/services/MockChatService.ts +47 -0
  259. package/src/services/index.ts +12 -0
  260. package/src/services/types.ts +92 -0
  261. package/src/test-setup.ts +12 -0
  262. package/src/test-utils/createTextPlugin.ts +9 -0
  263. package/src/types.ts +47 -0
@@ -0,0 +1,91 @@
1
+ import CkAgentMessage from './CkAgentMessage.vue';
2
+ import { render, screen } from '@testing-library/vue';
3
+
4
+ describe('CkAgentMessage', () => {
5
+ describe('header', () => {
6
+ it('displays custom header slot content', () => {
7
+ render(CkAgentMessage, {
8
+ slots: { header: 'Custom Header' },
9
+ });
10
+
11
+ expect(screen.getByText('Custom Header')).toBeInTheDocument();
12
+ });
13
+
14
+ it('hides the header section when no header slot is provided', () => {
15
+ const { container } = render(CkAgentMessage, {
16
+ slots: { default: 'Some content' },
17
+ });
18
+
19
+ expect(
20
+ container.querySelector('.text-sm.font-bold'),
21
+ ).not.toBeInTheDocument();
22
+ });
23
+ });
24
+
25
+ describe('content', () => {
26
+ it('displays message content from the default slot', () => {
27
+ render(CkAgentMessage, {
28
+ slots: { default: '<p>Agent response content</p>' },
29
+ });
30
+
31
+ expect(screen.getByText('Agent response content')).toBeInTheDocument();
32
+ });
33
+ });
34
+
35
+ describe('icon', () => {
36
+ it('displays the icon when provided via slot', () => {
37
+ render(CkAgentMessage, {
38
+ slots: { icon: '<img src="" alt="bot-icon" />' },
39
+ });
40
+
41
+ expect(screen.getByAltText('bot-icon')).toBeInTheDocument();
42
+ });
43
+
44
+ it('renders the icon container only when the icon slot is provided', () => {
45
+ const { container } = render(CkAgentMessage, {
46
+ slots: { icon: '<img src="" alt="bot-icon" />' },
47
+ });
48
+
49
+ expect(
50
+ container.querySelector(
51
+ '.flex.flex-shrink-0.items-center.justify-center',
52
+ ),
53
+ ).toBeInTheDocument();
54
+ });
55
+
56
+ it('does not render the icon container when no icon slot is provided', () => {
57
+ const { container } = render(CkAgentMessage, {
58
+ slots: { default: 'Some content' },
59
+ });
60
+
61
+ expect(
62
+ container.querySelector(
63
+ '.flex.flex-shrink-0.items-center.justify-center',
64
+ ),
65
+ ).not.toBeInTheDocument();
66
+ });
67
+ });
68
+
69
+ describe('footer', () => {
70
+ it('displays footer actions when the footer slot is provided', () => {
71
+ render(CkAgentMessage, {
72
+ slots: { footer: '<button>Copy</button><button>Retry</button>' },
73
+ });
74
+
75
+ expect(screen.getByText('Copy')).toBeInTheDocument();
76
+ expect(screen.getByText('Retry')).toBeInTheDocument();
77
+ });
78
+
79
+ it('does not display a footer area when no footer slot is provided', () => {
80
+ const { container } = render(CkAgentMessage, {
81
+ slots: { default: 'Some content' },
82
+ });
83
+
84
+ expect(screen.getByText('Some content')).toBeInTheDocument();
85
+ // Footer buttons should not exist
86
+ expect(screen.queryByRole('button')).not.toBeInTheDocument();
87
+ // The container should not have empty footer wrappers
88
+ expect(container.textContent).not.toBe('');
89
+ });
90
+ });
91
+ });
@@ -0,0 +1,215 @@
1
+ import CkAgentMessage from './CkAgentMessage.vue';
2
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
3
+
4
+ const meta: Meta<typeof CkAgentMessage> = {
5
+ title: 'Base/CkAgentMessage',
6
+ component: CkAgentMessage,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+
13
+ const defaultTemplateSource = `<script setup lang="ts">
14
+ import { CkAgentMessage } from '@aleph-alpha/chat-kit';
15
+ </script>
16
+
17
+ <template>
18
+ <CkAgentMessage>
19
+ <template #icon>
20
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
21
+ AI
22
+ </div>
23
+ </template>
24
+ <p>Based on a review of internal documents, here are the key lessons learned.</p>
25
+ </CkAgentMessage>
26
+ </template>`;
27
+
28
+ const withFooterActionsTemplateSource = `<script setup lang="ts">
29
+ import { CkAgentMessage } from '@aleph-alpha/chat-kit';
30
+ </script>
31
+
32
+ <template>
33
+ <CkAgentMessage>
34
+ <template #icon>
35
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
36
+ AI
37
+ </div>
38
+ </template>
39
+ <p>Research completed. Ask any follow-up questions as needed.</p>
40
+ <template #footer>
41
+ <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
42
+ <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
43
+ </template>
44
+ </CkAgentMessage>
45
+ </template>`;
46
+
47
+ const withRichContentTemplateSource = `<script setup lang="ts">
48
+ import { CkAgentMessage } from '@aleph-alpha/chat-kit';
49
+ </script>
50
+
51
+ <template>
52
+ <CkAgentMessage>
53
+ <template #icon>
54
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
55
+ AI
56
+ </div>
57
+ </template>
58
+ <div>
59
+ <p>Key lessons learned from the project:</p>
60
+ <ul class="mt-1 list-disc pl-4">
61
+ <li><strong>Stakeholder Involvement:</strong> Early and continuous stakeholder involvement.</li>
62
+ <li><strong>User Training:</strong> Hands-on training beats generic sessions.</li>
63
+ </ul>
64
+ </div>
65
+ <template #footer>
66
+ <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
67
+ </template>
68
+ </CkAgentMessage>
69
+ </template>`;
70
+
71
+ const withCustomHeaderTemplateSource = `<script setup lang="ts">
72
+ import { CkAgentMessage } from '@aleph-alpha/chat-kit';
73
+ </script>
74
+
75
+ <template>
76
+ <CkAgentMessage>
77
+ <template #icon>
78
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
79
+ AI
80
+ </div>
81
+ </template>
82
+ <template #header>
83
+ <span>Custom Agent</span>
84
+ <span class="text-core-content-quaternary ml-2 text-xs font-normal">v2.1</span>
85
+ </template>
86
+ <p>Hello! How can I assist you today?</p>
87
+ </CkAgentMessage>
88
+ </template>`;
89
+
90
+ const withoutIconTemplateSource = `<script setup lang="ts">
91
+ import { CkAgentMessage } from '@aleph-alpha/chat-kit';
92
+ </script>
93
+
94
+ <template>
95
+ <CkAgentMessage>
96
+ <p>A message from an agent without a custom icon.</p>
97
+ </CkAgentMessage>
98
+ </template>`;
99
+
100
+ /**
101
+ * Standard agent reply with an icon slot and a body slot. Use as the default
102
+ * layout for assistant messages in a conversation.
103
+ */
104
+ export const Default: Story = {
105
+ render: () => ({
106
+ components: { CkAgentMessage },
107
+ template: `
108
+ <CkAgentMessage>
109
+ <template #icon>
110
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
111
+ AI
112
+ </div>
113
+ </template>
114
+ <p>Based on a review of internal documents, here are the key lessons learned and best practices from the 'Digital Transformation Phase 1' project, broken down by category.</p>
115
+ </CkAgentMessage>
116
+ `,
117
+ }),
118
+ parameters: { docs: { source: { code: defaultTemplateSource } } },
119
+ };
120
+
121
+ /**
122
+ * Adds action buttons (copy, regenerate, etc.) via the `footer` slot.
123
+ * Use when messages need post-response interactions.
124
+ */
125
+ export const WithFooterActions: Story = {
126
+ render: () => ({
127
+ components: { CkAgentMessage },
128
+ template: `
129
+ <CkAgentMessage>
130
+ <template #icon>
131
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
132
+ AI
133
+ </div>
134
+ </template>
135
+ <p>Research completed. Ask any follow-up questions as needed.</p>
136
+ <template #footer>
137
+ <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
138
+ <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
139
+ </template>
140
+ </CkAgentMessage>
141
+ `,
142
+ }),
143
+ parameters: { docs: { source: { code: withFooterActionsTemplateSource } } },
144
+ };
145
+
146
+ /**
147
+ * Arbitrary rich content in the default slot — lists, bold text, etc.
148
+ * Use when you are rendering structured answers directly (rather than via CkMarkdownRenderer).
149
+ */
150
+ export const WithRichContent: Story = {
151
+ render: () => ({
152
+ components: { CkAgentMessage },
153
+ template: `
154
+ <CkAgentMessage>
155
+ <template #icon>
156
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
157
+ AI
158
+ </div>
159
+ </template>
160
+ <div>
161
+ <p>Based on a review of internal documents, here are the key lessons learned:</p>
162
+ <ul class="mt-1 list-disc pl-4">
163
+ <li><strong>Stakeholder Involvement:</strong> Early and continuous stakeholder involvement.</li>
164
+ <li><strong>User Training:</strong> Hands-on training was far more effective than generic sessions.</li>
165
+ </ul>
166
+ </div>
167
+ <template #footer>
168
+ <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
169
+ </template>
170
+ </CkAgentMessage>
171
+ `,
172
+ }),
173
+ parameters: { docs: { source: { code: withRichContentTemplateSource } } },
174
+ };
175
+
176
+ /**
177
+ * Replaces the default header row with a custom title/metadata block.
178
+ * Use to label the assistant (agent name, version, model) above the message body.
179
+ */
180
+ export const WithCustomHeader: Story = {
181
+ render: () => ({
182
+ components: { CkAgentMessage },
183
+ template: `
184
+ <CkAgentMessage>
185
+ <template #icon>
186
+ <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
187
+ AI
188
+ </div>
189
+ </template>
190
+ <template #header>
191
+ <span>Custom Agent</span>
192
+ <span class="text-core-content-quaternary ml-2 text-xs font-normal">v2.1</span>
193
+ </template>
194
+ <p>Hello! How can I assist you today?</p>
195
+ </CkAgentMessage>
196
+ `,
197
+ }),
198
+ parameters: { docs: { source: { code: withCustomHeaderTemplateSource } } },
199
+ };
200
+
201
+ /**
202
+ * Omits the icon slot. Use for minimalist conversations or systems where
203
+ * the assistant identity is conveyed elsewhere.
204
+ */
205
+ export const WithoutIcon: Story = {
206
+ render: () => ({
207
+ components: { CkAgentMessage },
208
+ template: `
209
+ <CkAgentMessage>
210
+ <p>A message from an agent without a custom icon.</p>
211
+ </CkAgentMessage>
212
+ `,
213
+ }),
214
+ parameters: { docs: { source: { code: withoutIconTemplateSource } } },
215
+ };
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ defineOptions({ name: 'CkAgentMessage' });
3
+ </script>
4
+
5
+ <template>
6
+ <div class="flex w-full items-start gap-2">
7
+ <div
8
+ v-if="$slots.icon"
9
+ class="flex flex-shrink-0 items-center justify-center"
10
+ >
11
+ <slot name="icon" />
12
+ </div>
13
+ <div class="text-core-content-primary flex min-w-0 flex-1 flex-col gap-2">
14
+ <span v-if="$slots.header" class="text-sm font-bold">
15
+ <slot name="header" />
16
+ </span>
17
+ <div>
18
+ <slot />
19
+ </div>
20
+ <div v-if="$slots.footer" class="flex items-center">
21
+ <slot name="footer" />
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as CkAgentMessage } from './CkAgentMessage.vue';
2
+ export type * from './types';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Layout for a single assistant (agent) turn in a conversation. Exposes
3
+ * `icon`, `header`, default content and `footer` slots for full control over
4
+ * each section while keeping consistent spacing and alignment.
5
+ *
6
+ * @category Messages
7
+ * @useCases render assistant reply, AI message layout, conversation turn, streaming message container
8
+ * @keywords agent, assistant, message, bubble, reply, ai, conversation
9
+ * @related CkUserMessage, CkConversation, CkMarkdownRenderer, CkCopyMessageActionButton
10
+ */
11
+ export type CkAgentMessageProps = Record<string, never>;
@@ -0,0 +1,129 @@
1
+ import CkConversationLayout from './CkConversationLayout.vue';
2
+ import { render, screen } from '@testing-library/vue';
3
+ import { type Component, defineComponent, h } from 'vue';
4
+
5
+ const messages = [
6
+ { role: 'user', content: 'Hello there' },
7
+ { role: 'agent', content: 'Hi! How can I help?' },
8
+ { role: 'user', content: 'Tell me a joke' },
9
+ { role: 'agent', content: 'Why did the chicken cross the road?' },
10
+ ];
11
+
12
+ /**
13
+ * Helper to render CkConversationLayout with standard slot markup.
14
+ * Each message is rendered as a <p> with its content as text and a test-id
15
+ * indicating the slot it was routed through (user-msg or agent-msg).
16
+ */
17
+ function renderLayout(
18
+ msgs: Array<{ role: string; content: string }> = messages,
19
+ ) {
20
+ // eslint-disable-next-line vue/one-component-per-file
21
+ const Wrapper = defineComponent({
22
+ setup() {
23
+ return () =>
24
+ h(
25
+ CkConversationLayout as unknown as Component,
26
+ { messages: msgs },
27
+ {
28
+ 'user-message': ({ message }: { message: (typeof msgs)[0] }) =>
29
+ h('p', { 'data-testid': 'user-msg' }, message.content),
30
+ 'agent-message': ({ message }: { message: (typeof msgs)[0] }) =>
31
+ h('p', { 'data-testid': 'agent-msg' }, message.content),
32
+ },
33
+ );
34
+ },
35
+ });
36
+
37
+ return render(Wrapper);
38
+ }
39
+
40
+ describe('CkConversationLayout', () => {
41
+ describe('message display', () => {
42
+ it('displays all provided messages', () => {
43
+ renderLayout();
44
+
45
+ for (const msg of messages) {
46
+ expect(screen.getByText(msg.content)).toBeInTheDocument();
47
+ }
48
+ });
49
+
50
+ it('shows no messages when the conversation is empty', () => {
51
+ renderLayout([]);
52
+
53
+ expect(screen.queryAllByTestId('user-msg')).toHaveLength(0);
54
+ expect(screen.queryAllByTestId('agent-msg')).toHaveLength(0);
55
+ });
56
+ });
57
+
58
+ describe('message routing', () => {
59
+ it('renders user messages through the user-message slot', () => {
60
+ renderLayout();
61
+
62
+ const userMessages = screen.getAllByTestId('user-msg');
63
+ expect(userMessages).toHaveLength(2);
64
+ expect(userMessages[0]).toHaveTextContent('Hello there');
65
+ expect(userMessages[1]).toHaveTextContent('Tell me a joke');
66
+ });
67
+
68
+ it('renders agent messages through the agent-message slot', () => {
69
+ renderLayout();
70
+
71
+ const agentMessages = screen.getAllByTestId('agent-msg');
72
+ expect(agentMessages).toHaveLength(2);
73
+ expect(agentMessages[0]).toHaveTextContent('Hi! How can I help?');
74
+ expect(agentMessages[1]).toHaveTextContent(
75
+ 'Why did the chicken cross the road?',
76
+ );
77
+ });
78
+ });
79
+
80
+ describe('message order', () => {
81
+ it('preserves the order of messages from the input array', () => {
82
+ renderLayout();
83
+
84
+ const allMessages = screen.getAllByTestId(/msg$/);
85
+ expect(allMessages).toHaveLength(4);
86
+ expect(allMessages[0]).toHaveTextContent('Hello there');
87
+ expect(allMessages[1]).toHaveTextContent('Hi! How can I help?');
88
+ expect(allMessages[2]).toHaveTextContent('Tell me a joke');
89
+ expect(allMessages[3]).toHaveTextContent(
90
+ 'Why did the chicken cross the road?',
91
+ );
92
+ });
93
+ });
94
+
95
+ describe('slot data', () => {
96
+ const customMessages = [
97
+ { role: 'user', content: 'Hi', id: '42', timestamp: '2026-02-13' },
98
+ ];
99
+
100
+ function renderCustomSlotWrapper() {
101
+ return h(
102
+ CkConversationLayout as unknown as Component,
103
+ { messages: customMessages },
104
+ {
105
+ 'user-message': ({
106
+ message,
107
+ }: {
108
+ message: (typeof customMessages)[0];
109
+ }) =>
110
+ h(
111
+ 'p',
112
+ null,
113
+ `${message.id}|${message.timestamp}|${message.content}`,
114
+ ),
115
+ 'agent-message': () => null,
116
+ },
117
+ );
118
+ }
119
+
120
+ it('provides the full message object including custom fields to scoped slots', () => {
121
+ // eslint-disable-next-line vue/one-component-per-file
122
+ const Wrapper = defineComponent({ setup: () => renderCustomSlotWrapper });
123
+
124
+ render(Wrapper);
125
+
126
+ expect(screen.getByText('42|2026-02-13|Hi')).toBeInTheDocument();
127
+ });
128
+ });
129
+ });