@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,19 @@
1
+ <script setup lang="ts">
2
+ import type { CkUserMessageProps } from './types';
3
+
4
+ defineOptions({ name: 'CkUserMessage' });
5
+
6
+ defineProps<CkUserMessageProps>();
7
+ </script>
8
+
9
+ <template>
10
+ <div
11
+ class="bg-background-surface-primary inline-flex max-w-[600px] flex-col items-end justify-start gap-4 rounded-xl p-6"
12
+ >
13
+ <div
14
+ class="text-content-on-surface-primary justify-start self-stretch text-base leading-6 font-normal"
15
+ >
16
+ <slot>{{ message }}</slot>
17
+ </div>
18
+ </div>
19
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as CkUserMessage } from './CkUserMessage.vue';
2
+ export type { CkUserMessageProps } from './types';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Bubble layout for a single user turn in a conversation. Renders the message
3
+ * text on the right side with a tokenized background and max-width; supports
4
+ * a default slot for custom inline content.
5
+ *
6
+ * @category Messages
7
+ * @useCases render user message bubble, conversation turn from user, chat input preview, right-aligned message
8
+ * @keywords user, message, bubble, chat, conversation, turn
9
+ * @related CkAgentMessage, CkConversation
10
+ */
11
+ export interface CkUserMessageProps {
12
+ /** Text content of the user message. Rendered inside the bubble when no default slot is provided. */
13
+ message?: string;
14
+ }
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ defineOptions({ name: 'CkSendIcon' });
3
+ </script>
4
+
5
+ <template>
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="16"
9
+ height="16"
10
+ viewBox="0 0 24 24"
11
+ fill="none"
12
+ stroke="currentColor"
13
+ stroke-width="2"
14
+ stroke-linecap="round"
15
+ stroke-linejoin="round"
16
+ >
17
+ <path
18
+ d="M3.714 3.048a.498.498 0 0 0-.683.627l2.843 7.627a2 2 0 0 1 0 1.396l-2.842 7.627a.498.498 0 0 0 .682.627l18-8.5a.5.5 0 0 0 0-.904z"
19
+ />
20
+ <path d="M6 12h16" />
21
+ </svg>
22
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ defineOptions({ name: 'CkStopIcon' });
3
+ </script>
4
+
5
+ <template>
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="16"
9
+ height="16"
10
+ viewBox="0 0 16 16"
11
+ fill="none"
12
+ >
13
+ <path
14
+ d="M13.3335 3.33301C13.3335 2.96482 13.035 2.66634 12.6668 2.66634H3.3335C2.96531 2.66634 2.66683 2.96482 2.66683 3.33301V12.6663C2.66683 13.0345 2.96531 13.333 3.3335 13.333H12.6668C13.035 13.333 13.3335 13.0345 13.3335 12.6663V3.33301ZM14.6668 12.6663C14.6668 13.7709 13.7714 14.6663 12.6668 14.6663H3.3335C2.22893 14.6663 1.3335 13.7709 1.3335 12.6663V3.33301C1.3335 2.22844 2.22893 1.33301 3.3335 1.33301H12.6668C13.7714 1.33301 14.6668 2.22844 14.6668 3.33301V12.6663Z"
15
+ fill="#1D1D1B"
16
+ />
17
+ </svg>
18
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as CkSendIcon } from './CkSendIcon.vue';
2
+ export { default as CkStopIcon } from './CkStopIcon.vue';
@@ -0,0 +1,21 @@
1
+ export { CkSendIcon, CkStopIcon } from './icons';
2
+ export { CkAgentMessage } from './CkAgentMessage';
3
+ export { CkConversationLayout } from './CkConversationLayout';
4
+ export type { CkConversationLayoutProps } from './CkConversationLayout';
5
+ export { CkCopyMessageActionButton } from './CkCopyMessageActionButton';
6
+ export { CkHistoryItem } from './CkHistoryItem';
7
+ export type { CkHistoryItemProps, CkHistoryItemEmits } from './CkHistoryItem';
8
+ export { CkHistoryWrapper } from './CkHistoryWrapper';
9
+ export type { CkHistoryWrapperProps } from './CkHistoryWrapper';
10
+ export { CkMarkdownRenderer } from './CkMarkdownRenderer';
11
+ export type {
12
+ CkMarkdownRendererProps,
13
+ CkMarkdownElementClasses,
14
+ } from './CkMarkdownRenderer';
15
+ export { CkMessageActionButton } from './CkMessageActionButton';
16
+ export { CkPromptActionButton } from './CkPromptActionButton';
17
+ export { CkPromptStopButton } from './CkPromptStopButton';
18
+ export { CkPromptInput } from './CkPromptInput';
19
+ export { CkPromptInputDisclaimer } from './CkPromptInputDisclaimer';
20
+ export { CkUserMessage } from './CkUserMessage';
21
+ export type { CkUserMessageProps } from './CkUserMessage';
@@ -0,0 +1,439 @@
1
+ import type { BaseMessage } from '../../../types';
2
+ import CkConversation from './CkConversation.vue';
3
+ import { defaultMarkdownClasses } from '../../base/CkMarkdownRenderer/defaultMarkdownClasses';
4
+ import { render, screen } from '@testing-library/vue';
5
+ import { h } from 'vue';
6
+
7
+ const now = new Date();
8
+
9
+ const messages: BaseMessage[] = [
10
+ {
11
+ id: '1',
12
+ role: 'user',
13
+ content: 'Hello there',
14
+ createdAt: now,
15
+ status: 'completed',
16
+ },
17
+ {
18
+ id: '2',
19
+ role: 'assistant',
20
+ content: 'Hi! How can I help?',
21
+ createdAt: now,
22
+ status: 'completed',
23
+ },
24
+ {
25
+ id: '3',
26
+ role: 'user',
27
+ content: 'Tell me a joke',
28
+ createdAt: now,
29
+ status: 'completed',
30
+ },
31
+ {
32
+ id: '4',
33
+ role: 'assistant',
34
+ content: 'Why did the chicken cross the road?',
35
+ createdAt: now,
36
+ status: 'completed',
37
+ },
38
+ ];
39
+
40
+ function agentMessage(overrides: Partial<BaseMessage> = {}): BaseMessage {
41
+ return {
42
+ id: '1',
43
+ role: 'assistant',
44
+ content: 'Hello',
45
+ createdAt: now,
46
+ status: 'completed',
47
+ ...overrides,
48
+ };
49
+ }
50
+
51
+ describe('CkConversation', () => {
52
+ describe('default rendering', () => {
53
+ it('displays all user messages', () => {
54
+ render(CkConversation, { props: { messages } });
55
+
56
+ expect(screen.getByText('Hello there')).toBeInTheDocument();
57
+ expect(screen.getByText('Tell me a joke')).toBeInTheDocument();
58
+ });
59
+
60
+ it('displays all agent messages', () => {
61
+ render(CkConversation, { props: { messages } });
62
+
63
+ expect(screen.getByText('Hi! How can I help?')).toBeInTheDocument();
64
+ expect(
65
+ screen.getByText('Why did the chicken cross the road?'),
66
+ ).toBeInTheDocument();
67
+ });
68
+ });
69
+
70
+ describe('agent icon', () => {
71
+ it('displays avatar fallback when agentAvatarFallback is provided', () => {
72
+ render(CkConversation, {
73
+ props: { messages: [agentMessage()], agentAvatarFallback: 'WB' },
74
+ });
75
+
76
+ expect(screen.getByText('WB')).toBeInTheDocument();
77
+ });
78
+
79
+ it('hides the icon area when no agentAvatarImage, no agentAvatarFallback, and no agent-message-icon slot', () => {
80
+ const { container } = render(CkConversation, {
81
+ props: { messages: [agentMessage()] },
82
+ });
83
+
84
+ // The icon container inside CkAgentMessage should not be rendered
85
+ const agentMessageEl = container.querySelector(
86
+ '.flex.w-full.items-start.gap-2',
87
+ );
88
+ expect(agentMessageEl).toBeInTheDocument();
89
+ // The flex-shrink-0 icon wrapper should not exist
90
+ expect(
91
+ agentMessageEl?.querySelector(
92
+ '.flex.flex-shrink-0.items-center.justify-center',
93
+ ),
94
+ ).not.toBeInTheDocument();
95
+ });
96
+
97
+ it('shows the icon area when agentAvatarFallback is provided', () => {
98
+ const { container } = render(CkConversation, {
99
+ props: { messages: [agentMessage()], agentAvatarFallback: 'AI' },
100
+ });
101
+
102
+ const agentMessageEl = container.querySelector(
103
+ '.flex.w-full.items-start.gap-2',
104
+ );
105
+ expect(
106
+ agentMessageEl?.querySelector(
107
+ '.flex.flex-shrink-0.items-center.justify-center',
108
+ ),
109
+ ).toBeInTheDocument();
110
+ });
111
+
112
+ it('shows the icon area when agentAvatarImage URL is provided', () => {
113
+ const { container } = render(CkConversation, {
114
+ props: {
115
+ messages: [agentMessage()],
116
+ agentAvatarImage: 'https://example.com/icon.png',
117
+ },
118
+ });
119
+
120
+ const agentMessageEl = container.querySelector(
121
+ '.flex.w-full.items-start.gap-2',
122
+ );
123
+ expect(
124
+ agentMessageEl?.querySelector(
125
+ '.flex.flex-shrink-0.items-center.justify-center',
126
+ ),
127
+ ).toBeInTheDocument();
128
+ });
129
+
130
+ it('shows the icon area when agent-message-icon slot is provided', () => {
131
+ const { container } = render(CkConversation, {
132
+ props: { messages: [agentMessage()] },
133
+ slots: {
134
+ 'agent-message-icon': '<span data-testid="custom-icon">🤖</span>',
135
+ },
136
+ });
137
+
138
+ expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
139
+ const agentMessageEl = container.querySelector(
140
+ '.flex.w-full.items-start.gap-2',
141
+ );
142
+ expect(
143
+ agentMessageEl?.querySelector(
144
+ '.flex.flex-shrink-0.items-center.justify-center',
145
+ ),
146
+ ).toBeInTheDocument();
147
+ });
148
+ });
149
+
150
+ describe('loading icon', () => {
151
+ it('shows UiSpinner by default when message is loading and icon area is visible', () => {
152
+ render(CkConversation, {
153
+ props: {
154
+ messages: [agentMessage({ status: 'started' })],
155
+ agentAvatarImage: 'avatar.png',
156
+ },
157
+ });
158
+
159
+ expect(screen.getByLabelText('Agent loading')).toBeInTheDocument();
160
+ expect(screen.queryByAltText('Agent avatar')).not.toBeInTheDocument();
161
+ });
162
+
163
+ it('shows agentLoadingImage instead of UiSpinner when provided', () => {
164
+ render(CkConversation, {
165
+ props: {
166
+ messages: [agentMessage({ status: 'started' })],
167
+ agentAvatarImage: 'avatar.png',
168
+ agentLoadingImage: 'loading.png',
169
+ },
170
+ });
171
+
172
+ const img = screen.getByAltText('Agent loading');
173
+ expect(img).toBeInTheDocument();
174
+ expect(img).toHaveAttribute('src', 'loading.png');
175
+ });
176
+
177
+ it('shows custom slot content instead of agentLoadingImage or UiSpinner', () => {
178
+ render(CkConversation, {
179
+ props: {
180
+ messages: [agentMessage({ status: 'sending' })],
181
+ agentAvatarImage: 'avatar.png',
182
+ agentLoadingImage: 'loading.png',
183
+ },
184
+ slots: {
185
+ 'agent-message-loading-icon':
186
+ '<span data-testid="custom-loader">Loading…</span>',
187
+ },
188
+ });
189
+
190
+ expect(screen.getByTestId('custom-loader')).toBeInTheDocument();
191
+ expect(screen.queryByAltText('Agent loading')).not.toBeInTheDocument();
192
+ });
193
+
194
+ it('shows the normal avatar icon when message is completed', () => {
195
+ render(CkConversation, {
196
+ props: {
197
+ messages: [agentMessage({ status: 'completed' })],
198
+ agentAvatarImage: 'avatar.png',
199
+ agentLoadingImage: 'loading.png',
200
+ },
201
+ });
202
+
203
+ expect(screen.getByAltText('Agent avatar')).toBeInTheDocument();
204
+ expect(screen.queryByAltText('Agent loading')).not.toBeInTheDocument();
205
+ });
206
+
207
+ it('shows UiSpinner for "sending" status as well', () => {
208
+ render(CkConversation, {
209
+ props: {
210
+ messages: [agentMessage({ status: 'sending' })],
211
+ agentAvatarImage: 'avatar.png',
212
+ },
213
+ });
214
+
215
+ expect(screen.getByLabelText('Agent loading')).toBeInTheDocument();
216
+ });
217
+ });
218
+
219
+ describe('slot overrides', () => {
220
+ it('allows replacing user message content via user-message-content slot', () => {
221
+ render(CkConversation, {
222
+ props: {
223
+ messages: [
224
+ {
225
+ id: '1',
226
+ role: 'user',
227
+ content: 'Original',
228
+ createdAt: now,
229
+ status: 'completed',
230
+ } as BaseMessage,
231
+ ],
232
+ },
233
+ slots: { 'user-message-content': 'Custom user content' },
234
+ });
235
+
236
+ expect(screen.getByText('Custom user content')).toBeInTheDocument();
237
+ expect(screen.queryByText('Original')).not.toBeInTheDocument();
238
+ });
239
+
240
+ it('allows replacing the entire user message via user-message slot', () => {
241
+ render(CkConversation, {
242
+ props: {
243
+ messages: [
244
+ {
245
+ id: '1',
246
+ role: 'user',
247
+ content: 'Original',
248
+ createdAt: now,
249
+ status: 'completed',
250
+ } as BaseMessage,
251
+ ],
252
+ },
253
+ slots: {
254
+ 'user-message': '<div data-testid="custom-user">Totally custom</div>',
255
+ },
256
+ });
257
+
258
+ expect(screen.getByTestId('custom-user')).toBeInTheDocument();
259
+ });
260
+
261
+ it('allows replacing agent content via agent-message-content slot', () => {
262
+ render(CkConversation, {
263
+ props: { messages: [agentMessage({ content: 'Original' })] },
264
+ slots: { 'agent-message-content': 'Rich agent content' },
265
+ });
266
+
267
+ expect(screen.getByText('Rich agent content')).toBeInTheDocument();
268
+ expect(screen.queryByText('Original')).not.toBeInTheDocument();
269
+ });
270
+
271
+ it('allows replacing the entire agent message via agent-message slot', () => {
272
+ render(CkConversation, {
273
+ props: { messages: [agentMessage({ content: 'Original' })] },
274
+ slots: {
275
+ 'agent-message':
276
+ '<div data-testid="custom-agent">Fully replaced</div>',
277
+ },
278
+ });
279
+
280
+ expect(screen.getByTestId('custom-agent')).toBeInTheDocument();
281
+ });
282
+
283
+ it('allows replacing the agent icon via agent-message-icon slot', () => {
284
+ render(CkConversation, {
285
+ props: { messages: [agentMessage()] },
286
+ slots: { 'agent-message-icon': '<img alt="custom-bot" />' },
287
+ });
288
+
289
+ expect(screen.getByAltText('custom-bot')).toBeInTheDocument();
290
+ });
291
+
292
+ it('allows adding a header via agent-message-header slot', () => {
293
+ render(CkConversation, {
294
+ props: { messages: [agentMessage()] },
295
+ slots: { 'agent-message-header': 'Custom Header' },
296
+ });
297
+
298
+ expect(screen.getByText('Custom Header')).toBeInTheDocument();
299
+ });
300
+
301
+ it('allows adding footer actions via agent-message-footer slot', () => {
302
+ render(CkConversation, {
303
+ props: { messages: [agentMessage()] },
304
+ slots: { 'agent-message-footer': '<button>Copy</button>' },
305
+ });
306
+
307
+ expect(screen.getByText('Copy')).toBeInTheDocument();
308
+ });
309
+ });
310
+
311
+ describe('empty conversation', () => {
312
+ it('renders nothing when messages array is empty', () => {
313
+ const { container } = render(CkConversation, { props: { messages: [] } });
314
+
315
+ // Only the scroll container should exist, with no message content
316
+ expect(container.querySelectorAll('[data-message-row]')).toHaveLength(0);
317
+ });
318
+ });
319
+
320
+ describe('markdown rendering', () => {
321
+ it('renders agent message content as markdown by default', () => {
322
+ const { container } = render(CkConversation, {
323
+ props: {
324
+ messages: [agentMessage({ content: 'This has **bold** text' })],
325
+ },
326
+ });
327
+
328
+ expect(container.querySelector('strong')?.textContent).toBe('bold');
329
+ });
330
+
331
+ it('renders markdown headings and lists', () => {
332
+ const { container } = render(CkConversation, {
333
+ props: {
334
+ messages: [
335
+ agentMessage({ content: '## Title\n\n- item one\n- item two' }),
336
+ ],
337
+ },
338
+ });
339
+
340
+ expect(container.querySelector('h2')?.textContent).toBe('Title');
341
+ expect(container.querySelectorAll('li')).toHaveLength(2);
342
+ });
343
+
344
+ it('applies default markdown classes to elements', () => {
345
+ const { container } = render(CkConversation, {
346
+ props: {
347
+ messages: [agentMessage({ content: 'A paragraph' })],
348
+ },
349
+ });
350
+
351
+ const p = container.querySelector('.markdown-renderer p');
352
+ expect(p).not.toBeNull();
353
+ expect(p?.className).toContain(defaultMarkdownClasses.p);
354
+ });
355
+
356
+ it('merges agentMarkdownClasses prop with defaults', () => {
357
+ const { container } = render(CkConversation, {
358
+ props: {
359
+ messages: [agentMessage({ content: 'A paragraph' })],
360
+ agentMarkdownClasses: { p: 'custom-paragraph' },
361
+ },
362
+ });
363
+
364
+ const p = container.querySelector('.markdown-renderer p');
365
+ expect(p?.className).toContain('custom-paragraph');
366
+ expect(p?.className).not.toContain(defaultMarkdownClasses.p);
367
+ });
368
+
369
+ it('preserves default classes for elements not overridden', () => {
370
+ const { container } = render(CkConversation, {
371
+ props: {
372
+ messages: [
373
+ agentMessage({
374
+ content:
375
+ '## Heading\n\nParagraph with [link](https://example.com)',
376
+ }),
377
+ ],
378
+ agentMarkdownClasses: { p: 'custom-paragraph' },
379
+ },
380
+ });
381
+
382
+ const h2 = container.querySelector('.markdown-renderer h2');
383
+ expect(h2?.className).toContain(defaultMarkdownClasses.h2);
384
+
385
+ const a = container.querySelector('.markdown-renderer a');
386
+ expect(a?.className).toContain(defaultMarkdownClasses.a);
387
+ });
388
+
389
+ it('does not render CkMarkdownRenderer when agent-message-content slot is provided', () => {
390
+ const { container } = render(CkConversation, {
391
+ props: { messages: [agentMessage({ content: '**bold**' })] },
392
+ slots: {
393
+ 'agent-message-content':
394
+ '<div data-testid="custom-content">Custom</div>',
395
+ },
396
+ });
397
+
398
+ expect(screen.getByTestId('custom-content')).toBeInTheDocument();
399
+ expect(container.querySelector('.markdown-renderer')).toBeNull();
400
+ });
401
+
402
+ it('forwards agent-message-code-block slot to CkMarkdownRenderer', () => {
403
+ const markdown = '```python\nprint("hello")\n```';
404
+
405
+ const { container } = render(CkConversation, {
406
+ props: { messages: [agentMessage({ content: markdown })] },
407
+ slots: {
408
+ 'agent-message-code-block': (props: {
409
+ code: string;
410
+ language: string;
411
+ }) =>
412
+ h(
413
+ 'div',
414
+ { class: 'custom-code', 'data-lang': props.language },
415
+ props.code,
416
+ ),
417
+ },
418
+ });
419
+
420
+ const custom = container.querySelector('.custom-code');
421
+ expect(custom).not.toBeNull();
422
+ expect(custom?.textContent).toContain('print("hello")');
423
+ expect(custom?.getAttribute('data-lang')).toBe('python');
424
+ expect(container.querySelector('pre > code')).toBeNull();
425
+ });
426
+
427
+ it('renders default code block when agent-message-code-block slot is not provided', () => {
428
+ const markdown = '```javascript\nconsole.log("hi");\n```';
429
+
430
+ const { container } = render(CkConversation, {
431
+ props: { messages: [agentMessage({ content: markdown })] },
432
+ });
433
+
434
+ const codeEl = container.querySelector('pre > code');
435
+ expect(codeEl).not.toBeNull();
436
+ expect(codeEl?.textContent).toContain('console.log("hi");');
437
+ });
438
+ });
439
+ });