@aleph-alpha/chat-kit 4.0.0 → 5.0.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 (110) hide show
  1. package/dist/{CkInput.vue_vue_type_script_setup_true_lang-DJN-nZ2-.js → CkHistory.vue_vue_type_script_setup_true_lang-Bp9hXdH6.js} +434 -377
  2. package/dist/chat-kit.css +28 -6
  3. package/dist/components/base/CkAgentMessage/CkAgentMessage.stories.d.ts +14 -13
  4. package/dist/components/base/CkAgentMessage/CkAgentMessage.stories.d.ts.map +1 -1
  5. package/dist/components/base/CkAgentMessage/CkAgentMessage.vue.d.ts +8 -7
  6. package/dist/components/base/CkAgentMessage/CkAgentMessage.vue.d.ts.map +1 -1
  7. package/dist/components/base/CkAgentMessage/types.d.ts +16 -5
  8. package/dist/components/base/CkAgentMessage/types.d.ts.map +1 -1
  9. package/dist/components/base/CkAgentMessageHeader/CkAgentMessageHeader.stories.d.ts +16 -0
  10. package/dist/components/base/CkAgentMessageHeader/CkAgentMessageHeader.stories.d.ts.map +1 -0
  11. package/dist/components/base/CkAgentMessageHeader/CkAgentMessageHeader.vue.d.ts +21 -0
  12. package/dist/components/base/CkAgentMessageHeader/CkAgentMessageHeader.vue.d.ts.map +1 -0
  13. package/dist/components/base/CkAgentMessageHeader/index.d.ts +3 -0
  14. package/dist/components/base/CkAgentMessageHeader/index.d.ts.map +1 -0
  15. package/dist/components/base/CkAgentMessageHeader/types.d.ts +22 -0
  16. package/dist/components/base/CkAgentMessageHeader/types.d.ts.map +1 -0
  17. package/dist/components/base/CkCitation/CkCitation.stories.d.ts +6 -0
  18. package/dist/components/base/CkCitation/CkCitation.stories.d.ts.map +1 -1
  19. package/dist/components/base/CkCitation/CkCitation.vue.d.ts.map +1 -1
  20. package/dist/components/base/CkCitationCard/CkCitationCard.stories.d.ts +5 -4
  21. package/dist/components/base/CkCitationCard/CkCitationCard.stories.d.ts.map +1 -1
  22. package/dist/components/base/CkCitationCard/CkCitationCard.vue.d.ts.map +1 -1
  23. package/dist/components/base/CkFileItemsList/CkFileItemsList.stories.d.ts +15 -4
  24. package/dist/components/base/CkFileItemsList/CkFileItemsList.stories.d.ts.map +1 -1
  25. package/dist/components/base/CkFileItemsList/CkFileItemsList.vue.d.ts +2 -1
  26. package/dist/components/base/CkFileItemsList/CkFileItemsList.vue.d.ts.map +1 -1
  27. package/dist/components/base/CkFileItemsList/types.d.ts +17 -4
  28. package/dist/components/base/CkFileItemsList/types.d.ts.map +1 -1
  29. package/dist/components/base/CkHeaderActivityButton/CkHeaderActivityButton.stories.d.ts +19 -0
  30. package/dist/components/base/CkHeaderActivityButton/CkHeaderActivityButton.stories.d.ts.map +1 -0
  31. package/dist/components/base/CkHeaderActivityButton/CkHeaderActivityButton.vue.d.ts +22 -0
  32. package/dist/components/base/CkHeaderActivityButton/CkHeaderActivityButton.vue.d.ts.map +1 -0
  33. package/dist/components/base/CkHeaderActivityButton/index.d.ts +3 -0
  34. package/dist/components/base/CkHeaderActivityButton/index.d.ts.map +1 -0
  35. package/dist/components/base/CkHeaderActivityButton/types.d.ts +36 -0
  36. package/dist/components/base/CkHeaderActivityButton/types.d.ts.map +1 -0
  37. package/dist/components/base/CkPromptInput/CkPromptInput.stories.d.ts +6 -6
  38. package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts.map +1 -1
  39. package/dist/components/base/CkPromptInput/types.d.ts +4 -4
  40. package/dist/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue.d.ts.map +1 -1
  41. package/dist/components/base/CkPromptInputDisclaimer/types.d.ts +1 -1
  42. package/dist/components/base/CkPromptSendButton/CkPromptSendButton.vue.d.ts +1 -1
  43. package/dist/components/base/CkPromptSendButton/types.d.ts +1 -1
  44. package/dist/components/base/CkPromptStopButton/types.d.ts +1 -1
  45. package/dist/components/base/index.d.ts +4 -0
  46. package/dist/components/base/index.d.ts.map +1 -1
  47. package/dist/components/composed/CkConversation/CkConversation.vue.d.ts +13 -1
  48. package/dist/components/composed/CkConversation/CkConversation.vue.d.ts.map +1 -1
  49. package/dist/components/composed/CkConversation/types.d.ts +1 -1
  50. package/dist/components/composed/index.d.ts +0 -1
  51. package/dist/components/composed/index.d.ts.map +1 -1
  52. package/dist/components/index.d.ts +3 -3
  53. package/dist/components/index.d.ts.map +1 -1
  54. package/dist/components/index.js +26 -25
  55. package/dist/index.d.ts +2 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +27 -26
  58. package/package.json +1 -1
  59. package/src/components/base/CkAgentMessage/CkAgentMessage.spec.ts +12 -17
  60. package/src/components/base/CkAgentMessage/CkAgentMessage.stories.ts +124 -113
  61. package/src/components/base/CkAgentMessage/CkAgentMessage.vue +18 -16
  62. package/src/components/base/CkAgentMessage/types.ts +16 -5
  63. package/src/components/base/CkAgentMessageHeader/CkAgentMessageHeader.spec.ts +64 -0
  64. package/src/components/base/CkAgentMessageHeader/CkAgentMessageHeader.stories.ts +90 -0
  65. package/src/components/base/CkAgentMessageHeader/CkAgentMessageHeader.vue +47 -0
  66. package/src/components/base/CkAgentMessageHeader/index.ts +2 -0
  67. package/src/components/base/CkAgentMessageHeader/types.ts +21 -0
  68. package/src/components/base/CkCitation/CkCitation.stories.ts +12 -0
  69. package/src/components/base/CkCitation/CkCitation.vue +34 -9
  70. package/src/components/base/CkCitationCard/CkCitationCard.stories.ts +5 -4
  71. package/src/components/base/CkCitationCard/CkCitationCard.vue +2 -2
  72. package/src/components/base/CkConversationLayout/CkConversationLayout.vue +1 -1
  73. package/src/components/base/CkFileItemsList/CkFileItemsList.spec.ts +88 -13
  74. package/src/components/base/CkFileItemsList/CkFileItemsList.stories.ts +61 -13
  75. package/src/components/base/CkFileItemsList/CkFileItemsList.vue +153 -110
  76. package/src/components/base/CkFileItemsList/types.ts +17 -4
  77. package/src/components/base/CkHeaderActivityButton/CkHeaderActivityButton.spec.ts +50 -0
  78. package/src/components/base/CkHeaderActivityButton/CkHeaderActivityButton.stories.ts +102 -0
  79. package/src/components/base/CkHeaderActivityButton/CkHeaderActivityButton.vue +39 -0
  80. package/src/components/base/CkHeaderActivityButton/index.ts +2 -0
  81. package/src/components/base/CkHeaderActivityButton/types.ts +36 -0
  82. package/src/components/base/CkPromptInput/CkPromptInput.spec.ts +88 -0
  83. package/src/components/base/CkPromptInput/CkPromptInput.stories.ts +6 -6
  84. package/src/components/base/CkPromptInput/CkPromptInput.vue +63 -12
  85. package/src/components/base/CkPromptInput/types.ts +4 -4
  86. package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.spec.ts +1 -1
  87. package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue +1 -1
  88. package/src/components/base/CkPromptInputDisclaimer/types.ts +1 -1
  89. package/src/components/base/CkPromptSendButton/types.ts +1 -1
  90. package/src/components/base/CkPromptStopButton/types.ts +1 -1
  91. package/src/components/base/index.ts +7 -0
  92. package/src/components/composed/CkConversation/CkConversation.spec.ts +81 -6
  93. package/src/components/composed/CkConversation/CkConversation.vue +78 -35
  94. package/src/components/composed/CkConversation/types.ts +1 -1
  95. package/src/components/composed/index.ts +0 -1
  96. package/src/components/index.ts +6 -1
  97. package/src/index.ts +5 -1
  98. package/dist/components/composed/CkInput/CkInput.stories.d.ts +0 -43
  99. package/dist/components/composed/CkInput/CkInput.stories.d.ts.map +0 -1
  100. package/dist/components/composed/CkInput/CkInput.vue.d.ts +0 -50
  101. package/dist/components/composed/CkInput/CkInput.vue.d.ts.map +0 -1
  102. package/dist/components/composed/CkInput/index.d.ts +0 -3
  103. package/dist/components/composed/CkInput/index.d.ts.map +0 -1
  104. package/dist/components/composed/CkInput/types.d.ts +0 -55
  105. package/dist/components/composed/CkInput/types.d.ts.map +0 -1
  106. package/src/components/composed/CkInput/CkInput.spec.ts +0 -191
  107. package/src/components/composed/CkInput/CkInput.stories.ts +0 -434
  108. package/src/components/composed/CkInput/CkInput.vue +0 -106
  109. package/src/components/composed/CkInput/index.ts +0 -2
  110. package/src/components/composed/CkInput/types.ts +0 -55
@@ -1,6 +1,8 @@
1
- import CkAgentMessage from './CkAgentMessage.vue';
2
- import { CkMarkdownRenderer } from '../CkMarkdownRenderer';
1
+ import { CkAgentMessageHeader } from '../CkAgentMessageHeader';
3
2
  import type { CkCitationSource } from '../CkCitation';
3
+ import { CkHeaderActivityButton } from '../CkHeaderActivityButton';
4
+ import { CkMarkdownRenderer } from '../CkMarkdownRenderer';
5
+ import CkAgentMessage from './CkAgentMessage.vue';
4
6
  import type { Meta, StoryObj } from '@storybook/vue3-vite';
5
7
 
6
8
  const meta: Meta<typeof CkAgentMessage> = {
@@ -12,106 +14,111 @@ const meta: Meta<typeof CkAgentMessage> = {
12
14
  export default meta;
13
15
  type Story = StoryObj<typeof meta>;
14
16
 
17
+ // Shared icon markup for the header slot (an agent avatar placeholder).
18
+ const ICON = `<template #icon>
19
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
20
+ </template>`;
21
+
15
22
  const defaultTemplateSource = `<script setup lang="ts">
16
- import { CkAgentMessage } from '@aleph-alpha/chat-kit';
23
+ import { CkAgentMessage, CkAgentMessageHeader } from '@aleph-alpha/chat-kit';
17
24
  </script>
18
25
 
19
26
  <template>
20
27
  <CkAgentMessage>
21
- <template #icon>
22
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
23
- AI
24
- </div>
28
+ <template #header>
29
+ <CkAgentMessageHeader>
30
+ <template #icon>
31
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
32
+ </template>
33
+ Thought about the lessons learned of the Digital Transformation Phase 1
34
+ </CkAgentMessageHeader>
25
35
  </template>
26
36
  <p>Based on a review of internal documents, here are the key lessons learned.</p>
27
37
  </CkAgentMessage>
28
38
  </template>`;
29
39
 
30
- const withFooterActionsTemplateSource = `<script setup lang="ts">
31
- import { CkAgentMessage } from '@aleph-alpha/chat-kit';
40
+ const withActivityHeaderTemplateSource = `<script setup lang="ts">
41
+ import {
42
+ CkAgentMessage,
43
+ CkAgentMessageHeader,
44
+ CkHeaderActivityButton,
45
+ } from '@aleph-alpha/chat-kit';
32
46
  </script>
33
47
 
34
48
  <template>
35
49
  <CkAgentMessage>
36
- <template #icon>
37
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
38
- AI
39
- </div>
40
- </template>
41
- <p>Research completed. Ask any follow-up questions as needed.</p>
42
- <template #footer>
43
- <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
44
- <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
50
+ <template #header>
51
+ <CkAgentMessageHeader>
52
+ <template #icon>
53
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
54
+ </template>
55
+ Thought about the lessons learned of the Digital Transformation Phase 1
56
+ <template #activity>
57
+ <CkHeaderActivityButton>1 tool, 42 sources</CkHeaderActivityButton>
58
+ </template>
59
+ </CkAgentMessageHeader>
45
60
  </template>
61
+ <p>Based on a review of internal documents, here are the key lessons learned.</p>
46
62
  </CkAgentMessage>
47
63
  </template>`;
48
64
 
49
- const withRichContentTemplateSource = `<script setup lang="ts">
50
- import { CkAgentMessage } from '@aleph-alpha/chat-kit';
65
+ const withFooterActionsTemplateSource = `<script setup lang="ts">
66
+ import { CkAgentMessage, CkAgentMessageHeader } from '@aleph-alpha/chat-kit';
51
67
  </script>
52
68
 
53
69
  <template>
54
70
  <CkAgentMessage>
55
- <template #icon>
56
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
57
- AI
58
- </div>
71
+ <template #header>
72
+ <CkAgentMessageHeader>
73
+ <template #icon>
74
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
75
+ </template>
76
+ Thought about the lessons learned of the Digital Transformation Phase 1
77
+ </CkAgentMessageHeader>
59
78
  </template>
60
- <div>
61
- <p>Key lessons learned from the project:</p>
62
- <ul class="mt-1 list-disc pl-4">
63
- <li><strong>Stakeholder Involvement:</strong> Early and continuous stakeholder involvement.</li>
64
- <li><strong>User Training:</strong> Hands-on training beats generic sessions.</li>
65
- </ul>
66
- </div>
79
+ <p>Research completed. Ask any follow-up questions as needed.</p>
67
80
  <template #footer>
68
81
  <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
82
+ <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
69
83
  </template>
70
84
  </CkAgentMessage>
71
85
  </template>`;
72
86
 
73
- const withCustomHeaderTemplateSource = `<script setup lang="ts">
87
+ const withoutHeaderTemplateSource = `<script setup lang="ts">
74
88
  import { CkAgentMessage } from '@aleph-alpha/chat-kit';
75
89
  </script>
76
90
 
77
91
  <template>
78
92
  <CkAgentMessage>
79
- <template #icon>
80
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
81
- AI
82
- </div>
83
- </template>
84
- <template #header>
85
- <span>Custom Agent</span>
86
- <span class="text-core-content-quaternary ml-2 text-xs font-normal">v2.1</span>
87
- </template>
88
- <p>Hello! How can I assist you today?</p>
93
+ <p>A message from an agent without a header.</p>
89
94
  </CkAgentMessage>
90
95
  </template>`;
91
96
 
92
- const withoutIconTemplateSource = `<script setup lang="ts">
97
+ const withoutBottomSeparatorTemplateSource = `<script setup lang="ts">
93
98
  import { CkAgentMessage } from '@aleph-alpha/chat-kit';
94
99
  </script>
95
100
 
96
101
  <template>
97
- <CkAgentMessage>
98
- <p>A message from an agent without a custom icon.</p>
102
+ <!-- bottomSeparator is true by default; disable it for the last message -->
103
+ <CkAgentMessage :bottom-separator="false">
104
+ <p>The last message in a conversation has no trailing separator.</p>
99
105
  </CkAgentMessage>
100
106
  </template>`;
101
107
 
102
108
  /**
103
- * Standard agent reply with an icon slot and a body slot. Use as the default
104
- * layout for assistant messages in a conversation.
109
+ * Standard agent reply: a full-width `CkAgentMessageHeader` (icon + text) in
110
+ * the `header` slot and the response body in the default slot.
105
111
  */
106
112
  export const Default: Story = {
107
113
  render: () => ({
108
- components: { CkAgentMessage },
114
+ components: { CkAgentMessage, CkAgentMessageHeader },
109
115
  template: `
110
116
  <CkAgentMessage>
111
- <template #icon>
112
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
113
- AI
114
- </div>
117
+ <template #header>
118
+ <CkAgentMessageHeader>
119
+ ${ICON}
120
+ Thought about the lessons learned of the Digital Transformation Phase 1
121
+ </CkAgentMessageHeader>
115
122
  </template>
116
123
  <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>
117
124
  </CkAgentMessage>
@@ -121,99 +128,99 @@ export const Default: Story = {
121
128
  };
122
129
 
123
130
  /**
124
- * Adds action buttons (copy, regenerate, etc.) via the `footer` slot.
125
- * Use when messages need post-response interactions.
131
+ * Header with an activity button. The activity slot adds vertical padding and a
132
+ * bottom border that separates the header from the message body.
126
133
  */
127
- export const WithFooterActions: Story = {
134
+ export const WithActivityHeader: Story = {
128
135
  render: () => ({
129
- components: { CkAgentMessage },
136
+ components: {
137
+ CkAgentMessage,
138
+ CkAgentMessageHeader,
139
+ CkHeaderActivityButton,
140
+ },
130
141
  template: `
131
142
  <CkAgentMessage>
132
- <template #icon>
133
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
134
- AI
135
- </div>
136
- </template>
137
- <p>Research completed. Ask any follow-up questions as needed.</p>
138
- <template #footer>
139
- <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
140
- <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
143
+ <template #header>
144
+ <CkAgentMessageHeader>
145
+ ${ICON}
146
+ Thought about the lessons learned of the Digital Transformation Phase 1
147
+ <template #activity>
148
+ <CkHeaderActivityButton>1 tool, 42 sources</CkHeaderActivityButton>
149
+ </template>
150
+ </CkAgentMessageHeader>
141
151
  </template>
152
+ <p>Based on a review of internal documents, here are the key lessons learned and best practices from the 'Digital Transformation Phase 1' project.</p>
142
153
  </CkAgentMessage>
143
154
  `,
144
155
  }),
145
- parameters: { docs: { source: { code: withFooterActionsTemplateSource } } },
156
+ parameters: { docs: { source: { code: withActivityHeaderTemplateSource } } },
146
157
  };
147
158
 
148
159
  /**
149
- * Arbitrary rich content in the default slot — lists, bold text, etc.
150
- * Use when you are rendering structured answers directly (rather than via CkMarkdownRenderer).
160
+ * Adds action buttons (copy, regenerate, etc.) via the `footer` slot.
161
+ * Use when messages need post-response interactions.
151
162
  */
152
- export const WithRichContent: Story = {
163
+ export const WithFooterActions: Story = {
153
164
  render: () => ({
154
- components: { CkAgentMessage },
165
+ components: { CkAgentMessage, CkAgentMessageHeader },
155
166
  template: `
156
167
  <CkAgentMessage>
157
- <template #icon>
158
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
159
- AI
160
- </div>
168
+ <template #header>
169
+ <CkAgentMessageHeader>
170
+ ${ICON}
171
+ Thought about the lessons learned of the Digital Transformation Phase 1
172
+ </CkAgentMessageHeader>
161
173
  </template>
162
- <div>
163
- <p>Based on a review of internal documents, here are the key lessons learned:</p>
164
- <ul class="mt-1 list-disc pl-4">
165
- <li><strong>Stakeholder Involvement:</strong> Early and continuous stakeholder involvement.</li>
166
- <li><strong>User Training:</strong> Hands-on training was far more effective than generic sessions.</li>
167
- </ul>
168
- </div>
174
+ <p>Research completed. Ask any follow-up questions as needed.</p>
169
175
  <template #footer>
170
176
  <button class="p-1 opacity-60 hover:opacity-100">Copy</button>
177
+ <button class="p-1 opacity-60 hover:opacity-100">Regenerate</button>
171
178
  </template>
172
179
  </CkAgentMessage>
173
180
  `,
174
181
  }),
175
- parameters: { docs: { source: { code: withRichContentTemplateSource } } },
182
+ parameters: { docs: { source: { code: withFooterActionsTemplateSource } } },
176
183
  };
177
184
 
178
185
  /**
179
- * Replaces the default header row with a custom title/metadata block.
180
- * Use to label the assistant (agent name, version, model) above the message body.
186
+ * Omits the header entirely. Use for minimalist conversations or systems where
187
+ * the assistant identity is conveyed elsewhere.
181
188
  */
182
- export const WithCustomHeader: Story = {
189
+ export const WithoutHeader: Story = {
183
190
  render: () => ({
184
191
  components: { CkAgentMessage },
185
192
  template: `
186
193
  <CkAgentMessage>
187
- <template #icon>
188
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
189
- AI
190
- </div>
191
- </template>
192
- <template #header>
193
- <span>Custom Agent</span>
194
- <span class="text-core-content-quaternary ml-2 text-xs font-normal">v2.1</span>
195
- </template>
196
- <p>Hello! How can I assist you today?</p>
194
+ <p>A message from an agent without a header.</p>
197
195
  </CkAgentMessage>
198
196
  `,
199
197
  }),
200
- parameters: { docs: { source: { code: withCustomHeaderTemplateSource } } },
198
+ parameters: { docs: { source: { code: withoutHeaderTemplateSource } } },
201
199
  };
202
200
 
203
201
  /**
204
- * Omits the icon slot. Use for minimalist conversations or systems where
205
- * the assistant identity is conveyed elsewhere.
202
+ * A bottom separator (border) is rendered by default to divide messages.
203
+ * `CkConversation` disables it on the last assistant message; set
204
+ * `:bottom-separator="false"` to do the same manually.
206
205
  */
207
- export const WithoutIcon: Story = {
206
+ export const WithoutBottomSeparator: Story = {
208
207
  render: () => ({
209
- components: { CkAgentMessage },
208
+ components: { CkAgentMessage, CkAgentMessageHeader },
210
209
  template: `
211
- <CkAgentMessage>
212
- <p>A message from an agent without a custom icon.</p>
210
+ <CkAgentMessage :bottom-separator="false">
211
+ <template #header>
212
+ <CkAgentMessageHeader>
213
+ ${ICON}
214
+ Thought about the lessons learned of the Digital Transformation Phase 1
215
+ </CkAgentMessageHeader>
216
+ </template>
217
+ <p>The last message in a conversation has no trailing separator.</p>
213
218
  </CkAgentMessage>
214
219
  `,
215
220
  }),
216
- parameters: { docs: { source: { code: withoutIconTemplateSource } } },
221
+ parameters: {
222
+ docs: { source: { code: withoutBottomSeparatorTemplateSource } },
223
+ },
217
224
  };
218
225
 
219
226
  const CITATIONS: CkCitationSource[] = [
@@ -243,7 +250,7 @@ const CITED_MARKDOWN = [
243
250
  ].join('\n');
244
251
 
245
252
  const withCitationsTemplateSource = `<script setup lang="ts">
246
- import { CkAgentMessage, CkMarkdownRenderer } from '@aleph-alpha/chat-kit';
253
+ import { CkAgentMessage, CkAgentMessageHeader, CkMarkdownRenderer } from '@aleph-alpha/chat-kit';
247
254
  import type { CkCitationSource } from '@aleph-alpha/chat-kit';
248
255
 
249
256
  // The reply body is markdown that contains inline [n] references.
@@ -280,10 +287,13 @@ function openSource(url: string) {
280
287
 
281
288
  <template>
282
289
  <CkAgentMessage>
283
- <template #icon>
284
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
285
- AI
286
- </div>
290
+ <template #header>
291
+ <CkAgentMessageHeader>
292
+ <template #icon>
293
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
294
+ </template>
295
+ Thought about the lessons learned of the Digital Transformation Phase 1
296
+ </CkAgentMessageHeader>
287
297
  </template>
288
298
  <CkMarkdownRenderer
289
299
  :content="content"
@@ -301,7 +311,7 @@ function openSource(url: string) {
301
311
  */
302
312
  export const WithCitations: Story = {
303
313
  render: () => ({
304
- components: { CkAgentMessage, CkMarkdownRenderer },
314
+ components: { CkAgentMessage, CkAgentMessageHeader, CkMarkdownRenderer },
305
315
  setup() {
306
316
  function openSource(url: string) {
307
317
  window.open(url, '_blank', 'noopener');
@@ -310,10 +320,11 @@ export const WithCitations: Story = {
310
320
  },
311
321
  template: `
312
322
  <CkAgentMessage>
313
- <template #icon>
314
- <div class="bg-core-bg-tertiary flex size-6 items-center justify-center rounded-full text-xs">
315
- AI
316
- </div>
323
+ <template #header>
324
+ <CkAgentMessageHeader>
325
+ ${ICON}
326
+ Thought about the lessons learned of the Digital Transformation Phase 1
327
+ </CkAgentMessageHeader>
317
328
  </template>
318
329
  <CkMarkdownRenderer
319
330
  :content="content"
@@ -1,24 +1,26 @@
1
1
  <script setup lang="ts">
2
+ import type { CkAgentMessageProps } from './types';
3
+
2
4
  defineOptions({ name: 'CkAgentMessage' });
5
+
6
+ withDefaults(defineProps<CkAgentMessageProps>(), {
7
+ bottomSeparator: true,
8
+ });
3
9
  </script>
4
10
 
5
11
  <template>
6
- <div class="flex w-full min-w-0 flex-col gap-6 pb-6">
7
- <div v-if="$slots.icon || $slots.header" class="flex items-start gap-3">
8
- <div
9
- v-if="$slots.icon"
10
- data-testid="ck-agent-message-icon"
11
- class="flex flex-shrink-0 justify-center"
12
- >
13
- <slot name="icon" />
14
- </div>
15
- <span
16
- v-if="$slots.header"
17
- data-testid="ck-agent-message-header"
18
- class="body-14-regular text-content-on-surface-muted min-w-0 flex-1 [word-break:break-word]"
19
- >
20
- <slot name="header" />
21
- </span>
12
+ <div
13
+ :class="[
14
+ 'flex w-full min-w-0 flex-col gap-6 pb-6',
15
+ bottomSeparator && 'border-border-surface-default border-b',
16
+ ]"
17
+ >
18
+ <div
19
+ v-if="$slots.header"
20
+ data-testid="ck-agent-message-header"
21
+ class="w-full min-w-0"
22
+ >
23
+ <slot name="header" />
22
24
  </div>
23
25
 
24
26
  <div class="text-content-on-surface-primary min-w-0 text-base leading-7">
@@ -1,11 +1,22 @@
1
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.
2
+ * Layout for a single assistant (agent) turn in a conversation. Exposes a
3
+ * full-width `header`, default content and `footer` slots for full control over
4
+ * each section while keeping consistent spacing and alignment. The agent icon
5
+ * now lives inside the header (see `CkAgentMessageHeader`), so the `header` slot
6
+ * spans the entire width.
5
7
  *
6
8
  * @category Messages
7
9
  * @useCases render assistant reply, AI message layout, conversation turn, streaming message container
8
10
  * @keywords agent, assistant, message, bubble, reply, ai, conversation
9
- * @related CkUserMessage, CkConversation, CkMarkdownRenderer, CkCopyMessageButton
11
+ * @related CkUserMessage, CkConversation, CkAgentMessageHeader, CkMarkdownRenderer, CkCopyMessageButton
10
12
  */
11
- export type CkAgentMessageProps = Record<string, never>;
13
+ export interface CkAgentMessageProps {
14
+ /**
15
+ * Whether to render a bottom border separating this message from the next
16
+ * one. `CkConversation` keeps this on for every message except the last
17
+ * assistant message, so it divides user/assistant pairs without a trailing
18
+ * line after the final pair.
19
+ * @default true
20
+ */
21
+ bottomSeparator?: boolean;
22
+ }
@@ -0,0 +1,64 @@
1
+ import CkAgentMessageHeader from './CkAgentMessageHeader.vue';
2
+ import { render, screen } from '@testing-library/vue';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ describe('CkAgentMessageHeader', () => {
6
+ it('renders the header text from the default slot', () => {
7
+ render(CkAgentMessageHeader, {
8
+ slots: { default: 'Thought about the lessons learned' },
9
+ });
10
+
11
+ expect(
12
+ screen.getByText('Thought about the lessons learned'),
13
+ ).toBeInTheDocument();
14
+ });
15
+
16
+ it('renders the icon slot when provided', () => {
17
+ render(CkAgentMessageHeader, {
18
+ slots: { icon: '<svg data-testid="agent-icon"></svg>' },
19
+ });
20
+
21
+ expect(screen.getByTestId('ck-agent-message-header-icon')).toContainElement(
22
+ screen.getByTestId('agent-icon'),
23
+ );
24
+ });
25
+
26
+ it('does not render the icon wrapper without an icon slot', () => {
27
+ render(CkAgentMessageHeader, { slots: { default: 'Header' } });
28
+
29
+ expect(
30
+ screen.queryByTestId('ck-agent-message-header-icon'),
31
+ ).not.toBeInTheDocument();
32
+ });
33
+
34
+ describe('with the activity slot', () => {
35
+ it('renders the activity slot and applies padding + bottom border', () => {
36
+ render(CkAgentMessageHeader, {
37
+ slots: {
38
+ default: 'Header',
39
+ activity: '<button data-testid="activity">Activity</button>',
40
+ },
41
+ });
42
+
43
+ expect(screen.getByTestId('activity')).toBeInTheDocument();
44
+
45
+ const header = screen.getByTestId('ck-agent-message-header-row');
46
+ expect(header.className).toContain('py-4');
47
+ expect(header.className).toContain('border-b');
48
+ });
49
+ });
50
+
51
+ describe('without the activity slot', () => {
52
+ it('omits the activity wrapper, padding and border', () => {
53
+ render(CkAgentMessageHeader, { slots: { default: 'Header' } });
54
+
55
+ expect(
56
+ screen.queryByTestId('ck-agent-message-header-activity'),
57
+ ).not.toBeInTheDocument();
58
+
59
+ const header = screen.getByTestId('ck-agent-message-header-row');
60
+ expect(header.className).not.toContain('py-4');
61
+ expect(header.className).not.toContain('border-b');
62
+ });
63
+ });
64
+ });
@@ -0,0 +1,90 @@
1
+ import { CkHeaderActivityButton } from '../CkHeaderActivityButton';
2
+ import CkAgentMessageHeader from './CkAgentMessageHeader.vue';
3
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
4
+
5
+ const meta: Meta<typeof CkAgentMessageHeader> = {
6
+ title: 'Base/CkAgentMessageHeader',
7
+ component: CkAgentMessageHeader,
8
+ tags: ['autodocs'],
9
+ decorators: [
10
+ () => ({
11
+ template:
12
+ '<div style="max-width: 640px; margin: 0 auto; padding: 24px;"><story /></div>',
13
+ }),
14
+ ],
15
+ };
16
+
17
+ export default meta;
18
+ type Story = StoryObj<typeof meta>;
19
+
20
+ const ICON = `<template #icon>
21
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
22
+ </template>`;
23
+
24
+ const withActivityTemplateSource = `<script setup lang="ts">
25
+ import { CkAgentMessageHeader, CkHeaderActivityButton } from '@aleph-alpha/chat-kit';
26
+ </script>
27
+
28
+ <template>
29
+ <CkAgentMessageHeader>
30
+ <template #icon>
31
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
32
+ </template>
33
+ Thought about the lessons learned of the Digital Transformation Phase 1
34
+ <template #activity>
35
+ <CkHeaderActivityButton @click="/* open activity panel */">
36
+ 1 tool, 42 sources
37
+ </CkHeaderActivityButton>
38
+ </template>
39
+ </CkAgentMessageHeader>
40
+ </template>`;
41
+
42
+ const withoutActivityTemplateSource = `<script setup lang="ts">
43
+ import { CkAgentMessageHeader } from '@aleph-alpha/chat-kit';
44
+ </script>
45
+
46
+ <template>
47
+ <CkAgentMessageHeader>
48
+ <template #icon>
49
+ <div class="bg-background-surface-muted-subtle flex size-8 items-center justify-center rounded-2xl text-xs">AA</div>
50
+ </template>
51
+ Thought about the lessons learned of the Digital Transformation Phase 1
52
+ </CkAgentMessageHeader>
53
+ </template>`;
54
+
55
+ /**
56
+ * Header with an activity button. The activity slot gives the row vertical
57
+ * padding and a bottom border separating it from the message body.
58
+ */
59
+ export const WithActivityButton: Story = {
60
+ render: () => ({
61
+ components: { CkAgentMessageHeader, CkHeaderActivityButton },
62
+ template: `
63
+ <CkAgentMessageHeader>
64
+ ${ICON}
65
+ Thought about the lessons learned of the Digital Transformation Phase 1
66
+ <template #activity>
67
+ <CkHeaderActivityButton>1 tool, 42 sources</CkHeaderActivityButton>
68
+ </template>
69
+ </CkAgentMessageHeader>
70
+ `,
71
+ }),
72
+ parameters: { docs: { source: { code: withActivityTemplateSource } } },
73
+ };
74
+
75
+ /**
76
+ * Header without an activity button — a compact icon + text row with no
77
+ * padding or bottom border.
78
+ */
79
+ export const WithoutActivityButton: Story = {
80
+ render: () => ({
81
+ components: { CkAgentMessageHeader },
82
+ template: `
83
+ <CkAgentMessageHeader>
84
+ ${ICON}
85
+ Thought about the lessons learned of the Digital Transformation Phase 1
86
+ </CkAgentMessageHeader>
87
+ `,
88
+ }),
89
+ parameters: { docs: { source: { code: withoutActivityTemplateSource } } },
90
+ };
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ defineOptions({ name: 'CkAgentMessageHeader' });
3
+
4
+ defineSlots<{
5
+ /** Leading agent avatar/icon. */
6
+ icon?: () => unknown;
7
+ /** Header text. Ellipsised on overflow (two lines on mobile, one on desktop). */
8
+ default?: () => unknown;
9
+ /**
10
+ * Optional activity control, typically a `CkHeaderActivityButton`. When
11
+ * present, the header gains vertical padding and a bottom border.
12
+ */
13
+ activity?: () => unknown;
14
+ }>();
15
+ </script>
16
+
17
+ <template>
18
+ <div
19
+ data-testid="ck-agent-message-header-row"
20
+ :class="[
21
+ 'flex w-full min-w-0 items-center gap-3',
22
+ $slots.activity && 'border-border-surface-default border-b py-4',
23
+ ]"
24
+ >
25
+ <div
26
+ v-if="$slots.icon"
27
+ data-testid="ck-agent-message-header-icon"
28
+ class="flex flex-shrink-0 items-center justify-center"
29
+ >
30
+ <slot name="icon" />
31
+ </div>
32
+
33
+ <span
34
+ class="body-14-regular text-content-on-surface-muted line-clamp-2 min-w-0 flex-1 md:line-clamp-1"
35
+ >
36
+ <slot />
37
+ </span>
38
+
39
+ <div
40
+ v-if="$slots.activity"
41
+ data-testid="ck-agent-message-header-activity"
42
+ class="flex flex-shrink-0 items-center"
43
+ >
44
+ <slot name="activity" />
45
+ </div>
46
+ </div>
47
+ </template>
@@ -0,0 +1,2 @@
1
+ export { default as CkAgentMessageHeader } from './CkAgentMessageHeader.vue';
2
+ export type * from './types';