@aleph-alpha/chat-kit 1.0.0 → 1.2.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.
- package/dist/{CkInput.vue_vue_type_script_setup_true_lang-744ZHsQU.js → CkInput.vue_vue_type_script_setup_true_lang-CRymGkQs.js} +24 -69
- package/dist/components/base/CkHistoryItem/CkHistoryItem.vue.d.ts +3 -4
- package/dist/components/base/CkHistoryItem/CkHistoryItem.vue.d.ts.map +1 -1
- package/dist/components/base/CkHistoryItem/types.d.ts +3 -2
- package/dist/components/base/CkHistoryItem/types.d.ts.map +1 -1
- package/dist/components/base/CkPromptStopButton/CkPromptStopButton.vue.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.d.ts.map +1 -1
- package/dist/composables/index.js +3 -2
- package/dist/composables/useConversationSessions.d.ts +29 -0
- package/dist/composables/useConversationSessions.d.ts.map +1 -0
- package/dist/handlers/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/purify.es-md74IFlY.js +1081 -0
- package/dist/{useChatKitLabels-Dvi2FmjE.js → useChatKitLabels-BmWmMyqX.js} +75 -1152
- package/dist/{useConversations-Ca242D2P.js → useConversationSessions-ulFhtpQr.js} +50 -2
- package/dist/{useMessageHandler-uLHNac39.js → useMessageHandler-BmBdu2EW.js} +4 -1
- package/package.json +5 -5
- package/src/components/base/CkAgentMessage/CkAgentMessage.spec.ts +91 -0
- package/src/components/base/CkAgentMessage/CkAgentMessage.stories.ts +215 -0
- package/src/components/base/CkAgentMessage/CkAgentMessage.vue +25 -0
- package/src/components/base/CkAgentMessage/index.ts +2 -0
- package/src/components/base/CkAgentMessage/types.ts +11 -0
- package/src/components/base/CkConversationLayout/CkConversationLayout.spec.ts +129 -0
- package/src/components/base/CkConversationLayout/CkConversationLayout.stories.ts +251 -0
- package/src/components/base/CkConversationLayout/CkConversationLayout.vue +206 -0
- package/src/components/base/CkConversationLayout/index.ts +2 -0
- package/src/components/base/CkConversationLayout/types.ts +18 -0
- package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.spec.ts +89 -0
- package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.stories.ts +70 -0
- package/src/components/base/CkCopyMessageActionButton/CkCopyMessageActionButton.vue +110 -0
- package/src/components/base/CkCopyMessageActionButton/index.ts +2 -0
- package/src/components/base/CkCopyMessageActionButton/types.ts +43 -0
- package/src/components/base/CkHistoryItem/CkHistoryItem.spec.ts +42 -0
- package/src/components/base/CkHistoryItem/CkHistoryItem.stories.ts +230 -0
- package/src/components/base/CkHistoryItem/CkHistoryItem.vue +285 -0
- package/src/components/base/CkHistoryItem/activeIndicator.ts +15 -0
- package/src/components/base/CkHistoryItem/index.ts +2 -0
- package/src/components/base/CkHistoryItem/types.ts +111 -0
- package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.spec.ts +26 -0
- package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.stories.ts +149 -0
- package/src/components/base/CkHistoryWrapper/CkHistoryWrapper.vue +36 -0
- package/src/components/base/CkHistoryWrapper/index.ts +2 -0
- package/src/components/base/CkHistoryWrapper/types.ts +16 -0
- package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.spec.ts +348 -0
- package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.ts +382 -0
- package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue +89 -0
- package/src/components/base/CkMarkdownRenderer/defaultMarkdownClasses.ts +19 -0
- package/src/components/base/CkMarkdownRenderer/index.ts +5 -0
- package/src/components/base/CkMarkdownRenderer/types.ts +53 -0
- package/src/components/base/CkMessageActionButton/CkMessageActionButton.spec.ts +40 -0
- package/src/components/base/CkMessageActionButton/CkMessageActionButton.stories.ts +56 -0
- package/src/components/base/CkMessageActionButton/CkMessageActionButton.vue +23 -0
- package/src/components/base/CkMessageActionButton/index.ts +2 -0
- package/src/components/base/CkMessageActionButton/types.ts +21 -0
- package/src/components/base/CkPromptActionButton/CkPromptActionButton.spec.ts +52 -0
- package/src/components/base/CkPromptActionButton/CkPromptActionButton.stories.ts +126 -0
- package/src/components/base/CkPromptActionButton/CkPromptActionButton.vue +25 -0
- package/src/components/base/CkPromptActionButton/index.ts +2 -0
- package/src/components/base/CkPromptActionButton/types.ts +32 -0
- package/src/components/base/CkPromptInput/CkPromptInput.spec.ts +181 -0
- package/src/components/base/CkPromptInput/CkPromptInput.stories.ts +224 -0
- package/src/components/base/CkPromptInput/CkPromptInput.vue +104 -0
- package/src/components/base/CkPromptInput/index.ts +2 -0
- package/src/components/base/CkPromptInput/types.ts +39 -0
- package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.spec.ts +40 -0
- package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.stories.ts +103 -0
- package/src/components/base/CkPromptInputDisclaimer/CkPromptInputDisclaimer.vue +16 -0
- package/src/components/base/CkPromptInputDisclaimer/index.ts +2 -0
- package/src/components/base/CkPromptInputDisclaimer/types.ts +17 -0
- package/src/components/base/CkPromptStopButton/CkPromptStopButton.spec.ts +64 -0
- package/src/components/base/CkPromptStopButton/CkPromptStopButton.stories.ts +81 -0
- package/src/components/base/CkPromptStopButton/CkPromptStopButton.vue +27 -0
- package/src/components/base/CkPromptStopButton/index.ts +2 -0
- package/src/components/base/CkPromptStopButton/types.ts +28 -0
- package/src/components/base/CkUserMessage/CkUserMessage.spec.ts +20 -0
- package/src/components/base/CkUserMessage/CkUserMessage.stories.ts +112 -0
- package/src/components/base/CkUserMessage/CkUserMessage.vue +19 -0
- package/src/components/base/CkUserMessage/index.ts +2 -0
- package/src/components/base/CkUserMessage/types.ts +14 -0
- package/src/components/base/icons/CkSendIcon.vue +22 -0
- package/src/components/base/icons/CkStopIcon.vue +18 -0
- package/src/components/base/icons/index.ts +2 -0
- package/src/components/base/index.ts +21 -0
- package/src/components/composed/CkConversation/CkConversation.spec.ts +439 -0
- package/src/components/composed/CkConversation/CkConversation.stories.ts +642 -0
- package/src/components/composed/CkConversation/CkConversation.vue +146 -0
- package/src/components/composed/CkConversation/index.ts +2 -0
- package/src/components/composed/CkConversation/types.ts +37 -0
- package/src/components/composed/CkHistory/CkHistory.spec.ts +327 -0
- package/src/components/composed/CkHistory/CkHistory.stories.ts +373 -0
- package/src/components/composed/CkHistory/CkHistory.vue +126 -0
- package/src/components/composed/CkHistory/index.ts +2 -0
- package/src/components/composed/CkHistory/types.ts +72 -0
- package/src/components/composed/CkInput/CkInput.spec.ts +191 -0
- package/src/components/composed/CkInput/CkInput.stories.ts +438 -0
- package/src/components/composed/CkInput/CkInput.vue +104 -0
- package/src/components/composed/CkInput/index.ts +2 -0
- package/src/components/composed/CkInput/types.ts +60 -0
- package/src/components/composed/index.ts +5 -0
- package/src/components/index.ts +34 -0
- package/src/composables/index.ts +15 -0
- package/src/composables/types.ts +36 -0
- package/src/composables/useChat.ts +18 -0
- package/src/composables/useConversationSessions.spec.ts +86 -0
- package/src/composables/useConversationSessions.ts +85 -0
- package/src/composables/useConversations.spec.ts +557 -0
- package/src/composables/useConversations.ts +321 -0
- package/src/handlers/index.ts +9 -0
- package/src/handlers/useChatKitLabels.spec.ts +290 -0
- package/src/handlers/useChatKitLabels.ts +96 -0
- package/src/handlers/useMarkdownParser.spec.ts +112 -0
- package/src/handlers/useMarkdownParser.ts +47 -0
- package/src/handlers/useMessageHandler.spec.ts +535 -0
- package/src/handlers/useMessageHandler.ts +138 -0
- package/src/helpers/conversationTree.spec.ts +423 -0
- package/src/helpers/conversationTree.ts +117 -0
- package/src/helpers/generateId.ts +5 -0
- package/src/helpers/index.ts +4 -0
- package/src/helpers/secondsToDate.ts +7 -0
- package/src/helpers/toError.ts +8 -0
- package/src/index.ts +86 -0
- package/src/services/ChatService.ts +60 -0
- package/src/services/MockChatService.ts +47 -0
- package/src/services/index.ts +12 -0
- package/src/services/types.ts +92 -0
- package/src/test-setup.ts +12 -0
- package/src/test-utils/createTextPlugin.ts +9 -0
- package/src/types.ts +47 -0
- package/dist/generateId-BHf0W4Rq.js +0 -6
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
import type { BaseMessage } from '../../../types';
|
|
2
|
+
import CkConversation from './CkConversation.vue';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
4
|
+
import { ref } from 'vue';
|
|
5
|
+
|
|
6
|
+
const now = new Date();
|
|
7
|
+
|
|
8
|
+
const markdownContent = [
|
|
9
|
+
'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.',
|
|
10
|
+
'',
|
|
11
|
+
'## Key Lessons Learned',
|
|
12
|
+
'',
|
|
13
|
+
'- **Stakeholder Involvement:** The most critical lesson was the need for early and continuous stakeholder involvement.',
|
|
14
|
+
'- **User Training:** Tailored, hands-on training was found to be far more effective than generic sessions.',
|
|
15
|
+
'- **Centralized Feedback:** Establishing a centralized feedback loop was identified as crucial.',
|
|
16
|
+
'',
|
|
17
|
+
'## Best Practices & Successes',
|
|
18
|
+
'',
|
|
19
|
+
'1. **Phased Rollout:** A major success was the phased rollout of tools and processes.',
|
|
20
|
+
'2. **Cross-team Collaboration:** Regular sync meetings across departments improved alignment.',
|
|
21
|
+
'',
|
|
22
|
+
'> **Note:** For detailed metrics, refer to the project dashboard.',
|
|
23
|
+
'',
|
|
24
|
+
'Here is a quick summary:',
|
|
25
|
+
'',
|
|
26
|
+
'| Category | Status | Impact |',
|
|
27
|
+
'| --- | --- | --- |',
|
|
28
|
+
'| Stakeholder Engagement | Completed | High |',
|
|
29
|
+
'| Training Programs | In Progress | Medium |',
|
|
30
|
+
'| Feedback Integration | Planned | High |',
|
|
31
|
+
].join('\n');
|
|
32
|
+
|
|
33
|
+
const sampleMessages: BaseMessage[] = [
|
|
34
|
+
{
|
|
35
|
+
id: '1',
|
|
36
|
+
role: 'user',
|
|
37
|
+
content: 'Hello! Can you help me with something?',
|
|
38
|
+
createdAt: now,
|
|
39
|
+
status: 'completed',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: '2',
|
|
43
|
+
role: 'assistant',
|
|
44
|
+
content: 'Of course! I am here to help. What would you like to know?',
|
|
45
|
+
createdAt: now,
|
|
46
|
+
status: 'completed',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: '3',
|
|
50
|
+
role: 'user',
|
|
51
|
+
content:
|
|
52
|
+
"Find the lessons learned and best practices from the 'Digital Transformation Phase 1' project, specifically focusing on process optimization and digital tool integration.",
|
|
53
|
+
createdAt: now,
|
|
54
|
+
status: 'completed',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: '4',
|
|
58
|
+
role: 'assistant',
|
|
59
|
+
content: markdownContent,
|
|
60
|
+
createdAt: now,
|
|
61
|
+
status: 'completed',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const meta: Meta<typeof CkConversation> = {
|
|
66
|
+
title: 'Composed/CkConversation',
|
|
67
|
+
component: CkConversation,
|
|
68
|
+
tags: ['autodocs'],
|
|
69
|
+
argTypes: {
|
|
70
|
+
messages: {
|
|
71
|
+
control: 'object',
|
|
72
|
+
description: 'Array of messages to render in chronological order.',
|
|
73
|
+
},
|
|
74
|
+
agentAvatarImage: {
|
|
75
|
+
control: 'text',
|
|
76
|
+
description: 'URL of the avatar image shown next to every agent message.',
|
|
77
|
+
},
|
|
78
|
+
agentAvatarFallback: {
|
|
79
|
+
control: 'text',
|
|
80
|
+
description: 'Fallback text/initials when no avatar image is provided.',
|
|
81
|
+
},
|
|
82
|
+
agentLoadingImage: {
|
|
83
|
+
control: 'text',
|
|
84
|
+
description:
|
|
85
|
+
'Avatar image used while an agent message is being generated.',
|
|
86
|
+
},
|
|
87
|
+
agentMarkdownClasses: {
|
|
88
|
+
control: 'object',
|
|
89
|
+
description:
|
|
90
|
+
'Per-tag class overrides for markdown rendered inside agent messages.',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
decorators: [
|
|
94
|
+
() => ({
|
|
95
|
+
template:
|
|
96
|
+
'<div style="height: 400px; border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden;"><story /></div>',
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default meta;
|
|
102
|
+
type Story = StoryObj<typeof meta>;
|
|
103
|
+
|
|
104
|
+
const defaultTemplateSource = `<script setup lang="ts">
|
|
105
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
106
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
107
|
+
|
|
108
|
+
const messages: BaseMessage[] = [
|
|
109
|
+
{ id: '1', role: 'user', content: 'Hello!', createdAt: new Date(), status: 'completed' },
|
|
110
|
+
{ id: '2', role: 'assistant', content: 'Hi there!', createdAt: new Date(), status: 'completed' },
|
|
111
|
+
];
|
|
112
|
+
</script>
|
|
113
|
+
|
|
114
|
+
<template>
|
|
115
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />
|
|
116
|
+
</template>`;
|
|
117
|
+
|
|
118
|
+
const withIconTemplateSource = `<script setup lang="ts">
|
|
119
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
120
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
121
|
+
|
|
122
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<template>
|
|
126
|
+
<CkConversation
|
|
127
|
+
:messages="messages"
|
|
128
|
+
agent-avatar-image="https://ui-avatars.com/api/?name=AI&background=6366f1&color=fff&size=64"
|
|
129
|
+
agent-avatar-fallback="AI"
|
|
130
|
+
style="height: 100%;"
|
|
131
|
+
/>
|
|
132
|
+
</template>`;
|
|
133
|
+
|
|
134
|
+
const withCustomAvatarFallbackTemplateSource = `<script setup lang="ts">
|
|
135
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
136
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
137
|
+
|
|
138
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<template>
|
|
142
|
+
<CkConversation :messages="messages" agent-avatar-fallback="WB" style="height: 100%;" />
|
|
143
|
+
</template>`;
|
|
144
|
+
|
|
145
|
+
const noIconTemplateSource = `<script setup lang="ts">
|
|
146
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
147
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
148
|
+
|
|
149
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
<template>
|
|
153
|
+
<CkConversation :messages="messages" style="height: 100%;" />
|
|
154
|
+
</template>`;
|
|
155
|
+
|
|
156
|
+
const withCustomIconTemplateSource = `<script setup lang="ts">
|
|
157
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
158
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
159
|
+
|
|
160
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
161
|
+
</script>
|
|
162
|
+
|
|
163
|
+
<template>
|
|
164
|
+
<CkConversation :messages="messages" style="height: 100%;">
|
|
165
|
+
<template #agent-message-icon>
|
|
166
|
+
<div class="bg-core-bg-tertiary flex size-8 items-center justify-center rounded-full text-xs">AI</div>
|
|
167
|
+
</template>
|
|
168
|
+
</CkConversation>
|
|
169
|
+
</template>`;
|
|
170
|
+
|
|
171
|
+
const withFooterActionsTemplateSource = `<script setup lang="ts">
|
|
172
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
173
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
174
|
+
|
|
175
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<template>
|
|
179
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
180
|
+
<template #agent-message-footer>
|
|
181
|
+
<button>Copy</button>
|
|
182
|
+
<button>Regenerate</button>
|
|
183
|
+
<button>Like</button>
|
|
184
|
+
<button>Dislike</button>
|
|
185
|
+
</template>
|
|
186
|
+
</CkConversation>
|
|
187
|
+
</template>`;
|
|
188
|
+
|
|
189
|
+
const withCustomUserContentTemplateSource = `<script setup lang="ts">
|
|
190
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
191
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
192
|
+
|
|
193
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
194
|
+
</script>
|
|
195
|
+
|
|
196
|
+
<template>
|
|
197
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
198
|
+
<template #user-message-content="{ message }">
|
|
199
|
+
<strong>{{ message.content }}</strong>
|
|
200
|
+
</template>
|
|
201
|
+
</CkConversation>
|
|
202
|
+
</template>`;
|
|
203
|
+
|
|
204
|
+
const withCustomAgentContentTemplateSource = `<script setup lang="ts">
|
|
205
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
206
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
207
|
+
|
|
208
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<template>
|
|
212
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
213
|
+
<template #agent-message-content="{ message }">
|
|
214
|
+
<div class="whitespace-pre-wrap font-mono text-sm">{{ message.content }}</div>
|
|
215
|
+
</template>
|
|
216
|
+
</CkConversation>
|
|
217
|
+
</template>`;
|
|
218
|
+
|
|
219
|
+
const streamingSimulationTemplateSource = `<script setup lang="ts">
|
|
220
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
221
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
222
|
+
import { ref } from 'vue';
|
|
223
|
+
|
|
224
|
+
const messages = ref<BaseMessage[]>([]);
|
|
225
|
+
|
|
226
|
+
function sendAndStream(): void {
|
|
227
|
+
messages.value = [
|
|
228
|
+
...messages.value,
|
|
229
|
+
{ id: '1', role: 'user', content: 'Tell me something.', createdAt: new Date(), status: 'completed' },
|
|
230
|
+
];
|
|
231
|
+
messages.value = [
|
|
232
|
+
...messages.value,
|
|
233
|
+
{ id: '2', role: 'assistant', content: '', createdAt: new Date(), status: 'sending' },
|
|
234
|
+
];
|
|
235
|
+
const reply = 'Key lessons learned from the project...';
|
|
236
|
+
let i = 0;
|
|
237
|
+
const interval = setInterval(() => {
|
|
238
|
+
i = Math.min(i + 3, reply.length);
|
|
239
|
+
const last = messages.value.length - 1;
|
|
240
|
+
messages.value[last] = { ...messages.value[last], content: reply.slice(0, i) };
|
|
241
|
+
if (i >= reply.length) clearInterval(interval);
|
|
242
|
+
}, 30);
|
|
243
|
+
}
|
|
244
|
+
</script>
|
|
245
|
+
|
|
246
|
+
<template>
|
|
247
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 400px;" />
|
|
248
|
+
<button @click="sendAndStream">Send + simulate stream</button>
|
|
249
|
+
</template>`;
|
|
250
|
+
|
|
251
|
+
const withCustomMarkdownClassesTemplateSource = `<script setup lang="ts">
|
|
252
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
253
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
254
|
+
|
|
255
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
256
|
+
const customClasses = {
|
|
257
|
+
h2: 'mt-6 mb-3 text-2xl font-bold',
|
|
258
|
+
p: 'my-2 leading-8 text-lg',
|
|
259
|
+
a: 'text-blue-600 underline',
|
|
260
|
+
};
|
|
261
|
+
</script>
|
|
262
|
+
|
|
263
|
+
<template>
|
|
264
|
+
<CkConversation
|
|
265
|
+
:messages="messages"
|
|
266
|
+
:agent-markdown-classes="customClasses"
|
|
267
|
+
agent-avatar-fallback="AI"
|
|
268
|
+
style="height: 100%;"
|
|
269
|
+
/>
|
|
270
|
+
</template>`;
|
|
271
|
+
|
|
272
|
+
const withCustomCodeBlockTemplateSource = `<script setup lang="ts">
|
|
273
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
274
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
275
|
+
|
|
276
|
+
const messages: BaseMessage[] = [/* ... */];
|
|
277
|
+
</script>
|
|
278
|
+
|
|
279
|
+
<template>
|
|
280
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
281
|
+
<template #agent-message-code-block="{ code, language }">
|
|
282
|
+
<div class="rounded-lg bg-black p-4 font-mono text-white">
|
|
283
|
+
<div class="mb-2 text-xs uppercase opacity-60">{{ language }}</div>
|
|
284
|
+
<code>{{ code }}</code>
|
|
285
|
+
</div>
|
|
286
|
+
</template>
|
|
287
|
+
</CkConversation>
|
|
288
|
+
</template>`;
|
|
289
|
+
|
|
290
|
+
const emptyTemplateSource = `<script setup lang="ts">
|
|
291
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
292
|
+
</script>
|
|
293
|
+
|
|
294
|
+
<template>
|
|
295
|
+
<CkConversation :messages="[]" style="height: 100%;" />
|
|
296
|
+
</template>`;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Drop-in conversation UI. Pass `messages` with `role`, `content`, and `status`
|
|
300
|
+
* fields and CkConversation renders user bubbles, assistant markdown, avatars,
|
|
301
|
+
* and a copy button on each reply.
|
|
302
|
+
*/
|
|
303
|
+
export const Default: Story = {
|
|
304
|
+
render: () => ({
|
|
305
|
+
components: { CkConversation },
|
|
306
|
+
setup() {
|
|
307
|
+
return { messages: sampleMessages };
|
|
308
|
+
},
|
|
309
|
+
template:
|
|
310
|
+
'<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />',
|
|
311
|
+
}),
|
|
312
|
+
parameters: { docs: { source: { code: defaultTemplateSource } } },
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Uses a remote avatar image (with fallback text). Use when you want a
|
|
317
|
+
* branded agent identity in each reply.
|
|
318
|
+
*/
|
|
319
|
+
export const WithIcon: Story = {
|
|
320
|
+
render: () => ({
|
|
321
|
+
components: { CkConversation },
|
|
322
|
+
setup() {
|
|
323
|
+
return { messages: sampleMessages };
|
|
324
|
+
},
|
|
325
|
+
template:
|
|
326
|
+
'<CkConversation :messages="messages" agent-avatar-image="https://ui-avatars.com/api/?name=AI&background=6366f1&color=fff&size=64" agent-avatar-fallback="AI" style="height: 100%;" />',
|
|
327
|
+
}),
|
|
328
|
+
parameters: { docs: { source: { code: withIconTemplateSource } } },
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Text-only avatar via `agent-avatar-fallback`. Use when you have no image
|
|
333
|
+
* and want to display initials instead.
|
|
334
|
+
*/
|
|
335
|
+
export const WithCustomAvatarFallback: Story = {
|
|
336
|
+
render: () => ({
|
|
337
|
+
components: { CkConversation },
|
|
338
|
+
setup() {
|
|
339
|
+
return { messages: sampleMessages };
|
|
340
|
+
},
|
|
341
|
+
template:
|
|
342
|
+
'<CkConversation :messages="messages" agent-avatar-fallback="WB" style="height: 100%;" />',
|
|
343
|
+
}),
|
|
344
|
+
parameters: {
|
|
345
|
+
docs: { source: { code: withCustomAvatarFallbackTemplateSource } },
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Hides the avatar completely. Use for minimalist chat surfaces where the
|
|
351
|
+
* assistant identity is conveyed elsewhere (e.g. surrounding header).
|
|
352
|
+
*/
|
|
353
|
+
export const NoIcon: Story = {
|
|
354
|
+
render: () => ({
|
|
355
|
+
components: { CkConversation },
|
|
356
|
+
setup() {
|
|
357
|
+
return { messages: sampleMessages };
|
|
358
|
+
},
|
|
359
|
+
template: '<CkConversation :messages="messages" style="height: 100%;" />',
|
|
360
|
+
}),
|
|
361
|
+
parameters: { docs: { source: { code: noIconTemplateSource } } },
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Replaces the default avatar with custom markup through the
|
|
366
|
+
* `#agent-message-icon` slot. Use to inject an emoji, Lottie animation, or
|
|
367
|
+
* your own branded icon.
|
|
368
|
+
*/
|
|
369
|
+
export const WithCustomIcon: Story = {
|
|
370
|
+
render: () => ({
|
|
371
|
+
components: { CkConversation },
|
|
372
|
+
setup() {
|
|
373
|
+
return { messages: sampleMessages };
|
|
374
|
+
},
|
|
375
|
+
template: `
|
|
376
|
+
<CkConversation :messages="messages" style="height: 100%;">
|
|
377
|
+
<template #agent-message-icon>
|
|
378
|
+
<div class="bg-core-bg-tertiary flex size-8 items-center justify-center rounded-full text-xs">🤖</div>
|
|
379
|
+
</template>
|
|
380
|
+
</CkConversation>
|
|
381
|
+
`,
|
|
382
|
+
}),
|
|
383
|
+
parameters: { docs: { source: { code: withCustomIconTemplateSource } } },
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Overrides `#agent-message-footer` to add custom action buttons (copy,
|
|
388
|
+
* regenerate, thumbs up/down) next to each assistant reply. Use to add
|
|
389
|
+
* feedback or follow-up actions.
|
|
390
|
+
*/
|
|
391
|
+
export const WithFooterActions: Story = {
|
|
392
|
+
render: () => ({
|
|
393
|
+
components: { CkConversation },
|
|
394
|
+
setup() {
|
|
395
|
+
return { messages: sampleMessages };
|
|
396
|
+
},
|
|
397
|
+
template: `
|
|
398
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
399
|
+
<template #agent-message-footer>
|
|
400
|
+
<button class="p-1 opacity-60 hover:opacity-100">📋</button>
|
|
401
|
+
<button class="p-1 opacity-60 hover:opacity-100">🔄</button>
|
|
402
|
+
<button class="p-1 opacity-60 hover:opacity-100">👍</button>
|
|
403
|
+
<button class="p-1 opacity-60 hover:opacity-100">👎</button>
|
|
404
|
+
</template>
|
|
405
|
+
</CkConversation>
|
|
406
|
+
`,
|
|
407
|
+
}),
|
|
408
|
+
parameters: { docs: { source: { code: withFooterActionsTemplateSource } } },
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Customizes the user message body via `#user-message-content`. Use to apply
|
|
413
|
+
* special typography, mentions, or attachments to user turns.
|
|
414
|
+
*/
|
|
415
|
+
export const WithCustomUserContent: Story = {
|
|
416
|
+
render: () => ({
|
|
417
|
+
components: { CkConversation },
|
|
418
|
+
setup() {
|
|
419
|
+
return { messages: sampleMessages };
|
|
420
|
+
},
|
|
421
|
+
template: `
|
|
422
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
423
|
+
<template #user-message-content="{ message }">
|
|
424
|
+
<strong>{{ message.content }}</strong>
|
|
425
|
+
</template>
|
|
426
|
+
</CkConversation>
|
|
427
|
+
`,
|
|
428
|
+
}),
|
|
429
|
+
parameters: {
|
|
430
|
+
docs: { source: { code: withCustomUserContentTemplateSource } },
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Replaces the default Markdown rendering with a custom layout via
|
|
436
|
+
* `#agent-message-content`. Use when you want raw content display or a
|
|
437
|
+
* different renderer.
|
|
438
|
+
*/
|
|
439
|
+
export const WithCustomAgentContent: Story = {
|
|
440
|
+
render: () => ({
|
|
441
|
+
components: { CkConversation },
|
|
442
|
+
setup() {
|
|
443
|
+
return { messages: sampleMessages };
|
|
444
|
+
},
|
|
445
|
+
template: `
|
|
446
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
447
|
+
<template #agent-message-content="{ message }">
|
|
448
|
+
<div style="white-space: pre-wrap; font-family: monospace; font-size: 13px;">{{ message.content }}</div>
|
|
449
|
+
</template>
|
|
450
|
+
</CkConversation>
|
|
451
|
+
`,
|
|
452
|
+
}),
|
|
453
|
+
parameters: {
|
|
454
|
+
docs: { source: { code: withCustomAgentContentTemplateSource } },
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* End-to-end streaming scenario: appending a new user message and then
|
|
460
|
+
* streaming an assistant reply chunk-by-chunk. Use as a reference for wiring
|
|
461
|
+
* up an LLM SDK that emits token deltas.
|
|
462
|
+
*/
|
|
463
|
+
export const StreamingSimulation: Story = {
|
|
464
|
+
render: () => ({
|
|
465
|
+
components: { CkConversation },
|
|
466
|
+
setup() {
|
|
467
|
+
const messages = ref<BaseMessage[]>([
|
|
468
|
+
{
|
|
469
|
+
id: '1',
|
|
470
|
+
role: 'user',
|
|
471
|
+
content: 'Hello!',
|
|
472
|
+
createdAt: now,
|
|
473
|
+
status: 'completed',
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: '2',
|
|
477
|
+
role: 'assistant',
|
|
478
|
+
content: 'Hi there!',
|
|
479
|
+
createdAt: now,
|
|
480
|
+
status: 'completed',
|
|
481
|
+
},
|
|
482
|
+
]);
|
|
483
|
+
|
|
484
|
+
let streamInterval: ReturnType<typeof setInterval> | null = null;
|
|
485
|
+
let charIndex = 0;
|
|
486
|
+
let nextId = 3;
|
|
487
|
+
|
|
488
|
+
function streamNextChunk(): void {
|
|
489
|
+
if (charIndex >= markdownContent.length) {
|
|
490
|
+
if (streamInterval) clearInterval(streamInterval);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
// eslint-disable-next-line sonarjs/pseudo-random
|
|
494
|
+
const chunkSize = Math.floor(Math.random() * 5) + 3;
|
|
495
|
+
charIndex = Math.min(charIndex + chunkSize, markdownContent.length);
|
|
496
|
+
const lastIdx = messages.value.length - 1;
|
|
497
|
+
messages.value[lastIdx] = {
|
|
498
|
+
...messages.value[lastIdx],
|
|
499
|
+
content: markdownContent.slice(0, charIndex),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function startStreaming(): void {
|
|
504
|
+
const id = String(nextId++);
|
|
505
|
+
messages.value = [
|
|
506
|
+
...messages.value,
|
|
507
|
+
{
|
|
508
|
+
id,
|
|
509
|
+
role: 'assistant',
|
|
510
|
+
content: '',
|
|
511
|
+
createdAt: new Date(),
|
|
512
|
+
status: 'sending',
|
|
513
|
+
},
|
|
514
|
+
];
|
|
515
|
+
charIndex = 0;
|
|
516
|
+
streamInterval = setInterval(streamNextChunk, 30);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function simulateStream(): void {
|
|
520
|
+
const id = String(nextId++);
|
|
521
|
+
messages.value = [
|
|
522
|
+
...messages.value,
|
|
523
|
+
{
|
|
524
|
+
id,
|
|
525
|
+
role: 'user',
|
|
526
|
+
content:
|
|
527
|
+
'Tell me about Digital Transformation Phase 1 lessons learned.',
|
|
528
|
+
createdAt: new Date(),
|
|
529
|
+
status: 'completed',
|
|
530
|
+
},
|
|
531
|
+
];
|
|
532
|
+
setTimeout(startStreaming, 500);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return { messages, simulateStream };
|
|
536
|
+
},
|
|
537
|
+
template: `
|
|
538
|
+
<div style="display: flex; flex-direction: column; height: 100%;">
|
|
539
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="flex: 1; min-height: 0;" />
|
|
540
|
+
<div style="padding: 8px; border-top: 1px solid #e0e0e0;">
|
|
541
|
+
<button @click="simulateStream" style="padding: 6px 16px; border-radius: 6px; background: #333; color: white; cursor: pointer;">
|
|
542
|
+
Send message + simulate stream
|
|
543
|
+
</button>
|
|
544
|
+
</div>
|
|
545
|
+
</div>
|
|
546
|
+
`,
|
|
547
|
+
}),
|
|
548
|
+
parameters: { docs: { source: { code: streamingSimulationTemplateSource } } },
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Overrides default Markdown element classes via `agent-markdown-classes`.
|
|
553
|
+
* Use to apply your design-system tokens to assistant replies without writing
|
|
554
|
+
* a custom renderer slot.
|
|
555
|
+
*/
|
|
556
|
+
export const WithCustomMarkdownClasses: Story = {
|
|
557
|
+
render: () => ({
|
|
558
|
+
components: { CkConversation },
|
|
559
|
+
setup() {
|
|
560
|
+
return {
|
|
561
|
+
messages: sampleMessages,
|
|
562
|
+
customClasses: {
|
|
563
|
+
h2: 'mt-6 mb-3 text-2xl font-bold',
|
|
564
|
+
p: 'my-2 leading-8 text-lg',
|
|
565
|
+
a: 'text-blue-600 underline',
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
},
|
|
569
|
+
template:
|
|
570
|
+
'<CkConversation :messages="messages" :agent-markdown-classes="customClasses" agent-avatar-fallback="AI" style="height: 100%;" />',
|
|
571
|
+
}),
|
|
572
|
+
parameters: {
|
|
573
|
+
docs: { source: { code: withCustomMarkdownClassesTemplateSource } },
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Integrates a custom code-block renderer (Shiki, Prism, etc.) via
|
|
579
|
+
* `#agent-message-code-block`. Use when you want syntax highlighting or
|
|
580
|
+
* inline copy buttons for assistant code.
|
|
581
|
+
*/
|
|
582
|
+
export const WithCustomCodeBlock: Story = {
|
|
583
|
+
render: () => ({
|
|
584
|
+
components: { CkConversation },
|
|
585
|
+
setup() {
|
|
586
|
+
const messages: BaseMessage[] = [
|
|
587
|
+
{
|
|
588
|
+
id: '1',
|
|
589
|
+
role: 'user',
|
|
590
|
+
content: 'Show me a code example',
|
|
591
|
+
createdAt: now,
|
|
592
|
+
status: 'completed',
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
id: '2',
|
|
596
|
+
role: 'assistant',
|
|
597
|
+
content: [
|
|
598
|
+
'Here is an example:',
|
|
599
|
+
'',
|
|
600
|
+
'```typescript',
|
|
601
|
+
'const greeting = "Hello, world!";',
|
|
602
|
+
'console.log(greeting);',
|
|
603
|
+
'```',
|
|
604
|
+
'',
|
|
605
|
+
'And another one:',
|
|
606
|
+
'',
|
|
607
|
+
'```python',
|
|
608
|
+
'def greet(name: str) -> str:',
|
|
609
|
+
' return f"Hello, {name}!"',
|
|
610
|
+
'```',
|
|
611
|
+
].join('\n'),
|
|
612
|
+
createdAt: now,
|
|
613
|
+
status: 'completed',
|
|
614
|
+
},
|
|
615
|
+
];
|
|
616
|
+
return { messages };
|
|
617
|
+
},
|
|
618
|
+
template: `
|
|
619
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
620
|
+
<template #agent-message-code-block="{ code, language }">
|
|
621
|
+
<div style="background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 8px; font-family: monospace; white-space: pre; margin: 8px 0;">
|
|
622
|
+
<div style="color: #888; font-size: 12px; margin-bottom: 8px; text-transform: uppercase;">{{ language }}</div>
|
|
623
|
+
<code>{{ code }}</code>
|
|
624
|
+
</div>
|
|
625
|
+
</template>
|
|
626
|
+
</CkConversation>
|
|
627
|
+
`,
|
|
628
|
+
}),
|
|
629
|
+
parameters: { docs: { source: { code: withCustomCodeBlockTemplateSource } } },
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Empty state — an initial view before the first turn. Use to show a welcome
|
|
634
|
+
* screen, quick prompts, or onboarding content above this surface.
|
|
635
|
+
*/
|
|
636
|
+
export const Empty: Story = {
|
|
637
|
+
render: () => ({
|
|
638
|
+
components: { CkConversation },
|
|
639
|
+
template: '<CkConversation :messages="[]" style="height: 100%;" />',
|
|
640
|
+
}),
|
|
641
|
+
parameters: { docs: { source: { code: emptyTemplateSource } } },
|
|
642
|
+
};
|