@aleph-alpha/chat-kit 5.0.1 → 5.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/{CkHistory.vue_vue_type_script_setup_true_lang-CtQUc3m3.js → CkHistory.vue_vue_type_script_setup_true_lang-BxzHdcxY.js} +69 -48
- package/dist/chat-kit.css +14 -11
- package/dist/components/base/CkPromptInput/CkPromptInput.vue.d.ts.map +1 -1
- package/dist/components/composed/CkConversation/CkConversation.stories.d.ts +9 -8
- package/dist/components/composed/CkConversation/CkConversation.stories.d.ts.map +1 -1
- package/dist/components/composed/CkConversation/CkConversation.vue.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +7 -2
- package/src/components/base/CkPromptInput/CkPromptInput.vue +9 -5
- package/src/components/composed/CkConversation/CkConversation.spec.ts +32 -1
- package/src/components/composed/CkConversation/CkConversation.stories.ts +98 -92
- package/src/components/composed/CkConversation/CkConversation.vue +47 -15
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, openBlock, createBlock, unref, createElementBlock, createElementVNode, normalizeClass, renderSlot, createCommentVNode, mergeProps, withCtx, computed, createVNode, toDisplayString, ref, onBeforeUnmount, onMounted, nextTick, onUnmounted, watch, Fragment, renderList, normalizeStyle, Transition, createStaticVNode, Teleport, withModifiers, toValue, h, toRefs, useId, createTextVNode, useAttrs, useSlots, resolveDynamicComponent, useTemplateRef, onUpdated, createSlots, normalizeProps, guardReactiveProps } from "vue";
|
|
1
|
+
import { defineComponent, openBlock, createBlock, unref, createElementBlock, createElementVNode, normalizeClass, renderSlot, createCommentVNode, mergeProps, withCtx, computed, createVNode, toDisplayString, ref, onBeforeUnmount, onMounted, nextTick, onUnmounted, watch, Fragment, renderList, normalizeStyle, Transition, createStaticVNode, Teleport, withModifiers, toValue, h, toRefs, useId, createTextVNode, useAttrs, useSlots, resolveDynamicComponent, useTemplateRef, onUpdated, createSlots, normalizeProps, guardReactiveProps, Comment, Text } from "vue";
|
|
2
2
|
import { UiIcon, UiButton, UiFileType, UiPopover, UiPopoverTrigger, UiPopoverContent, UiTooltip, formatFileSize, UiDialog, UiDialogContent, UiDialogDescription, UiFieldLabel, UiToggleGroup, UiToggleGroupItem, UiField, UiTextarea, UiFileItem, UiProgress, Primitive, UiAvatar, UiAvatarImage, UiSpinner, UiAvatarFallback, UiSidebarPopoverMenu, UiSidebarPopoverMenuItem } from "@aleph-alpha/ui-library";
|
|
3
3
|
import { u as useChatKitLabels, d as defaultChatKitLabels, r as remarkCitations, a as useMarkdownParser } from "./useChatKitLabels-zMFV7aEz.js";
|
|
4
4
|
const MINUTE = 60;
|
|
@@ -45,7 +45,7 @@ const _sfc_main$s = /* @__PURE__ */ defineComponent({
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
-
const _hoisted_1$
|
|
48
|
+
const _hoisted_1$h = {
|
|
49
49
|
xmlns: "http://www.w3.org/2000/svg",
|
|
50
50
|
width: "16",
|
|
51
51
|
height: "16",
|
|
@@ -57,7 +57,7 @@ const _sfc_main$r = /* @__PURE__ */ defineComponent({
|
|
|
57
57
|
__name: "CkStopIcon",
|
|
58
58
|
setup(__props) {
|
|
59
59
|
return (_ctx, _cache) => {
|
|
60
|
-
return openBlock(), createElementBlock("svg", _hoisted_1$
|
|
60
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$h, [..._cache[0] || (_cache[0] = [
|
|
61
61
|
createElementVNode("path", {
|
|
62
62
|
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",
|
|
63
63
|
fill: "currentColor"
|
|
@@ -66,7 +66,7 @@ const _sfc_main$r = /* @__PURE__ */ defineComponent({
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
|
-
const _hoisted_1$
|
|
69
|
+
const _hoisted_1$g = {
|
|
70
70
|
key: 0,
|
|
71
71
|
"data-testid": "ck-agent-message-header",
|
|
72
72
|
class: "w-full min-w-0"
|
|
@@ -90,7 +90,7 @@ const _sfc_main$q = /* @__PURE__ */ defineComponent({
|
|
|
90
90
|
__props.bottomSeparator && "border-border-surface-default border-b"
|
|
91
91
|
])
|
|
92
92
|
}, [
|
|
93
|
-
_ctx.$slots.header ? (openBlock(), createElementBlock("div", _hoisted_1$
|
|
93
|
+
_ctx.$slots.header ? (openBlock(), createElementBlock("div", _hoisted_1$g, [
|
|
94
94
|
renderSlot(_ctx.$slots, "header")
|
|
95
95
|
])) : createCommentVNode("", true),
|
|
96
96
|
createElementVNode("div", _hoisted_2$a, [
|
|
@@ -103,7 +103,7 @@ const _sfc_main$q = /* @__PURE__ */ defineComponent({
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
|
-
const _hoisted_1$
|
|
106
|
+
const _hoisted_1$f = {
|
|
107
107
|
key: 0,
|
|
108
108
|
"data-testid": "ck-agent-message-header-icon",
|
|
109
109
|
class: "flex flex-shrink-0 items-center justify-center"
|
|
@@ -126,7 +126,7 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
|
|
|
126
126
|
_ctx.$slots.activity && "border-border-surface-default border-b py-4"
|
|
127
127
|
])
|
|
128
128
|
}, [
|
|
129
|
-
_ctx.$slots.icon ? (openBlock(), createElementBlock("div", _hoisted_1$
|
|
129
|
+
_ctx.$slots.icon ? (openBlock(), createElementBlock("div", _hoisted_1$f, [
|
|
130
130
|
renderSlot(_ctx.$slots, "icon")
|
|
131
131
|
])) : createCommentVNode("", true),
|
|
132
132
|
createElementVNode("span", _hoisted_2$9, [
|
|
@@ -181,7 +181,7 @@ const _sfc_main$o = /* @__PURE__ */ defineComponent({
|
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
183
|
});
|
|
184
|
-
const _hoisted_1$
|
|
184
|
+
const _hoisted_1$e = { class: "ck-citation-card flex w-[22.5rem] max-w-[90vw] flex-col gap-2 rounded-md bg-background-surface-floating px-6 pb-6 pt-4 shadow-md" };
|
|
185
185
|
const _hoisted_2$8 = { class: "flex items-center gap-2" };
|
|
186
186
|
const _hoisted_3$7 = ["title"];
|
|
187
187
|
const _hoisted_4$6 = { class: "line-clamp-6 break-words text-sm leading-5 text-content-on-surface-secondary" };
|
|
@@ -215,7 +215,7 @@ const _sfc_main$n = /* @__PURE__ */ defineComponent({
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
return (_ctx, _cache) => {
|
|
218
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
218
|
+
return openBlock(), createElementBlock("div", _hoisted_1$e, [
|
|
219
219
|
createElementVNode("div", _hoisted_2$8, [
|
|
220
220
|
createVNode(unref(UiFileType), {
|
|
221
221
|
filename: __props.fileName,
|
|
@@ -249,7 +249,7 @@ const _sfc_main$n = /* @__PURE__ */ defineComponent({
|
|
|
249
249
|
};
|
|
250
250
|
}
|
|
251
251
|
});
|
|
252
|
-
const _hoisted_1$
|
|
252
|
+
const _hoisted_1$d = ["aria-label"];
|
|
253
253
|
const CLOSE_DELAY_MS = 80;
|
|
254
254
|
const _sfc_main$m = /* @__PURE__ */ defineComponent({
|
|
255
255
|
...{
|
|
@@ -337,7 +337,7 @@ const _sfc_main$m = /* @__PURE__ */ defineComponent({
|
|
|
337
337
|
onKeydown: onTriggerKeydown,
|
|
338
338
|
onMouseenter: onPointerEnter,
|
|
339
339
|
onMouseleave: onPointerLeave
|
|
340
|
-
}, toDisplayString(__props.index), 43, _hoisted_1$
|
|
340
|
+
}, toDisplayString(__props.index), 43, _hoisted_1$d)
|
|
341
341
|
]),
|
|
342
342
|
_: 1
|
|
343
343
|
}),
|
|
@@ -378,7 +378,7 @@ const _export_sfc = (sfc, props) => {
|
|
|
378
378
|
return target;
|
|
379
379
|
};
|
|
380
380
|
const CkCitation = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["__scopeId", "data-v-73025da4"]]);
|
|
381
|
-
const _hoisted_1$
|
|
381
|
+
const _hoisted_1$c = ["data-message-row"];
|
|
382
382
|
const _hoisted_2$7 = {
|
|
383
383
|
key: 0,
|
|
384
384
|
class: "flex min-w-0 justify-end"
|
|
@@ -533,7 +533,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
|
|
|
533
533
|
])) : (openBlock(), createElementBlock("div", _hoisted_3$6, [
|
|
534
534
|
renderSlot(_ctx.$slots, "agent-message", { message })
|
|
535
535
|
]))
|
|
536
|
-
], 8, _hoisted_1$
|
|
536
|
+
], 8, _hoisted_1$c);
|
|
537
537
|
}), 128)),
|
|
538
538
|
hasBottomSpacer.value ? (openBlock(), createElementBlock("div", {
|
|
539
539
|
key: 0,
|
|
@@ -568,7 +568,7 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
|
|
|
568
568
|
};
|
|
569
569
|
}
|
|
570
570
|
});
|
|
571
|
-
const _hoisted_1$
|
|
571
|
+
const _hoisted_1$b = {
|
|
572
572
|
class: "sr-only",
|
|
573
573
|
"aria-live": "polite"
|
|
574
574
|
};
|
|
@@ -656,7 +656,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
656
656
|
]),
|
|
657
657
|
_: 1
|
|
658
658
|
}, 16, ["disabled"]),
|
|
659
|
-
createElementVNode("span", _hoisted_1$
|
|
659
|
+
createElementVNode("span", _hoisted_1$b, toDisplayString(copied.value ? __props.ariaLabelCopied : __props.ariaLabelCopy), 1)
|
|
660
660
|
]),
|
|
661
661
|
_: 1
|
|
662
662
|
}, 8, ["open", "content"]);
|
|
@@ -664,7 +664,7 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
664
664
|
}
|
|
665
665
|
});
|
|
666
666
|
const CkCopyMessageButton = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["__scopeId", "data-v-ba2e5f32"]]);
|
|
667
|
-
const _hoisted_1$
|
|
667
|
+
const _hoisted_1$a = {
|
|
668
668
|
width: "208",
|
|
669
669
|
height: "144",
|
|
670
670
|
viewBox: "0 0 208 144",
|
|
@@ -678,13 +678,13 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
|
|
|
678
678
|
__name: "CkDropZoneIllustration",
|
|
679
679
|
setup(__props) {
|
|
680
680
|
return (_ctx, _cache) => {
|
|
681
|
-
return openBlock(), createElementBlock("svg", _hoisted_1$
|
|
681
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$a, [..._cache[0] || (_cache[0] = [
|
|
682
682
|
createStaticVNode('<g clip-path="url(#ck-drop-zone-clip)"><path d="M0 71.5391C0 32.0292 32.0292 0 71.5391 0H135.739C175.249 0 207.278 32.0292 207.278 71.5391C207.278 111.049 175.249 143.078 135.739 143.078H71.5392C32.0292 143.078 0 111.049 0 71.5391Z" fill="#F2EBE8"></path><path d="M120.899 98.2608L134.973 45.7385C135.223 44.805 136.182 44.251 137.116 44.5011L172.976 54.1098C173.909 54.3599 174.463 55.3195 174.213 56.2531L160.14 108.775C159.89 109.709 158.93 110.263 157.997 110.013L122.137 100.404C121.203 100.154 120.649 99.1943 120.899 98.2608Z" fill="#FFCCBB" stroke="#333333"></path><g><path d="M153.839 69.86L144.18 67.2718C143.118 66.9871 142.015 67.6235 141.731 68.686L137.589 84.1409C137.305 85.2034 137.941 86.3056 139.004 86.5904L150.595 89.6962C151.657 89.9809 152.76 89.3445 153.044 88.282L156.668 74.759L153.839 69.86Z" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M153.839 69.86L153.063 72.7578C152.921 73.2891 153.239 73.8402 153.77 73.9825L156.668 74.759" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M143.783 76.4828L151.51 78.5534" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M143.006 79.3806L150.733 81.4511" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M142.23 82.2784L147.059 83.5725" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path></g><path d="M86.3795 98.2608L72.3062 45.7385C72.0561 44.805 71.0965 44.251 70.1629 44.5011L34.3029 54.1098C33.3694 54.3599 32.8153 55.3195 33.0655 56.2531L47.1388 108.775C47.3889 109.709 48.3485 110.263 49.2821 110.013L85.1421 100.404C86.0756 100.154 86.6297 99.1943 86.3795 98.2608Z" fill="#FFE9B5" stroke="#333333"></path><g><path d="M60.3294 76.0227L58.0001 67.3293C60.3057 66.7116 62.7623 67.035 64.8294 68.2284C66.8966 69.4219 68.405 71.3877 69.0228 73.6933L60.3294 76.0227Z" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M55.3303 68.8899C54.4077 69.3934 53.5755 70.0573 52.8752 70.8559C51.7015 72.1942 50.9511 73.8504 50.7187 75.6152C50.4864 77.38 50.7826 79.1741 51.5699 80.7706C52.3572 82.367 53.6002 83.6942 55.1417 84.5842C56.6833 85.4742 58.4541 85.8871 60.2304 85.7707C62.0066 85.6543 63.7084 85.0138 65.1206 83.9302C66.5328 82.8465 67.5919 81.3685 68.1641 79.6829C68.5135 78.6536 68.6717 77.5751 68.6371 76.4998" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path></g><path d="M76.5186 107.5L76.5185 35C76.5185 33.6193 77.6378 32.5 79.0185 32.5H128.519C129.899 32.5 131.019 33.6193 131.019 35V107.5C131.019 108.881 129.899 110 128.519 110H79.0186C77.6378 110 76.5186 108.881 76.5186 107.5Z" fill="#FFB3DD" stroke="#333333"></path><g><path d="M107.519 56.8335H95.519C94.419 56.8335 93.519 57.7335 93.519 58.8335V82.1665C93.519 83.2675 94.419 84.1665 95.519 84.1665H111.519C112.619 84.1665 113.519 83.2675 113.519 82.1665V64.8335L107.519 56.8335Z" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M107.519 56.8335V62.8335C107.519 63.9335 108.419 64.8335 109.519 64.8335H113.519" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M103.519 78.8335V70.8335" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path><path d="M99.519 74.8335L103.519 70.8335L107.519 74.8335" stroke="#1D1D1B" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"></path></g></g><defs><clipPath id="ck-drop-zone-clip"><rect width="208" height="144" fill="white"></rect></clipPath></defs>', 2)
|
|
683
683
|
])]);
|
|
684
684
|
};
|
|
685
685
|
}
|
|
686
686
|
});
|
|
687
|
-
const _hoisted_1$
|
|
687
|
+
const _hoisted_1$9 = ["aria-label"];
|
|
688
688
|
const _hoisted_2$6 = { class: "pointer-events-none flex h-full w-full flex-col items-center justify-center gap-4 text-content-on-surface-primary" };
|
|
689
689
|
const _hoisted_3$5 = { class: "flex flex-col items-center gap-1 text-center" };
|
|
690
690
|
const _hoisted_4$5 = { class: "body-16-bold" };
|
|
@@ -868,7 +868,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
868
868
|
])
|
|
869
869
|
], true)
|
|
870
870
|
])
|
|
871
|
-
], 40, _hoisted_1$
|
|
871
|
+
], 40, _hoisted_1$9)) : createCommentVNode("", true)
|
|
872
872
|
]),
|
|
873
873
|
_: 3
|
|
874
874
|
}),
|
|
@@ -887,7 +887,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
887
887
|
}
|
|
888
888
|
});
|
|
889
889
|
const CkDropZoneOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["__scopeId", "data-v-54119668"]]);
|
|
890
|
-
const _hoisted_1$
|
|
890
|
+
const _hoisted_1$8 = ["aria-label"];
|
|
891
891
|
const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
892
892
|
...{
|
|
893
893
|
name: "CkFeedbackButton"
|
|
@@ -996,7 +996,7 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
|
996
996
|
]),
|
|
997
997
|
_: 1
|
|
998
998
|
}, 8, ["content"])
|
|
999
|
-
], 8, _hoisted_1$
|
|
999
|
+
], 8, _hoisted_1$8);
|
|
1000
1000
|
};
|
|
1001
1001
|
}
|
|
1002
1002
|
});
|
|
@@ -1141,7 +1141,7 @@ const _sfc_main$f = defineComponent({
|
|
|
1141
1141
|
};
|
|
1142
1142
|
}
|
|
1143
1143
|
});
|
|
1144
|
-
const _hoisted_1$
|
|
1144
|
+
const _hoisted_1$7 = {
|
|
1145
1145
|
key: 0,
|
|
1146
1146
|
class: "flex min-h-0 flex-col gap-2"
|
|
1147
1147
|
};
|
|
@@ -1304,7 +1304,7 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
1304
1304
|
showResponseColumn.value ? "grid-cols-2" : "grid-cols-1"
|
|
1305
1305
|
])
|
|
1306
1306
|
}, [
|
|
1307
|
-
showResponseColumn.value ? (openBlock(), createElementBlock("section", _hoisted_1$
|
|
1307
|
+
showResponseColumn.value ? (openBlock(), createElementBlock("section", _hoisted_1$7, [
|
|
1308
1308
|
createVNode(unref(UiFieldLabel), null, {
|
|
1309
1309
|
default: withCtx(() => [
|
|
1310
1310
|
createTextVNode(toDisplayString(responseHeading.value), 1)
|
|
@@ -1422,7 +1422,7 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
1422
1422
|
};
|
|
1423
1423
|
}
|
|
1424
1424
|
});
|
|
1425
|
-
const _hoisted_1$
|
|
1425
|
+
const _hoisted_1$6 = ["aria-label"];
|
|
1426
1426
|
const _hoisted_2$4 = ["onClick"];
|
|
1427
1427
|
const _hoisted_3$3 = ["disabled", "aria-label"];
|
|
1428
1428
|
const _hoisted_4$3 = {
|
|
@@ -1577,7 +1577,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
1577
1577
|
}, 8, ["file", "size", "is-removable", "remove-label", "disabled", "onRemove"])
|
|
1578
1578
|
], 12, _hoisted_2$4);
|
|
1579
1579
|
}), 128))
|
|
1580
|
-
], 8, _hoisted_1$
|
|
1580
|
+
], 8, _hoisted_1$6)) : (openBlock(), createBlock(unref(UiPopover), {
|
|
1581
1581
|
key: 1,
|
|
1582
1582
|
open: isOpen.value,
|
|
1583
1583
|
"onUpdate:open": _cache[0] || (_cache[0] = ($event) => isOpen.value = $event)
|
|
@@ -1669,7 +1669,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
1669
1669
|
}
|
|
1670
1670
|
});
|
|
1671
1671
|
const CHAT_HISTORY_ACTIVE_INDICATOR_CLASS = "ui-active-indicator";
|
|
1672
|
-
const _hoisted_1$
|
|
1672
|
+
const _hoisted_1$5 = ["data-active"];
|
|
1673
1673
|
const _hoisted_2$3 = { class: "min-w-0 flex-1" };
|
|
1674
1674
|
const _hoisted_3$2 = { class: "truncate body-14-regular text-content-on-surface-primary" };
|
|
1675
1675
|
const _hoisted_4$2 = {
|
|
@@ -1927,7 +1927,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
|
|
|
1927
1927
|
}))
|
|
1928
1928
|
], 42, _hoisted_10))
|
|
1929
1929
|
], 34)) : createCommentVNode("", true)
|
|
1930
|
-
], 10, _hoisted_1$
|
|
1930
|
+
], 10, _hoisted_1$5);
|
|
1931
1931
|
};
|
|
1932
1932
|
}
|
|
1933
1933
|
});
|
|
@@ -1962,7 +1962,7 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|
|
1962
1962
|
};
|
|
1963
1963
|
}
|
|
1964
1964
|
});
|
|
1965
|
-
const _hoisted_1$
|
|
1965
|
+
const _hoisted_1$4 = ["disabled", "aria-expanded", "aria-label"];
|
|
1966
1966
|
const _hoisted_2$2 = { class: "min-w-0 max-w-[10rem] truncate" };
|
|
1967
1967
|
const _hoisted_3$1 = ["aria-label"];
|
|
1968
1968
|
const _hoisted_4$1 = ["aria-selected", "onClick"];
|
|
@@ -2024,7 +2024,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
2024
2024
|
class: "shrink-0",
|
|
2025
2025
|
"aria-hidden": "true"
|
|
2026
2026
|
})
|
|
2027
|
-
], 8, _hoisted_1$
|
|
2027
|
+
], 8, _hoisted_1$4)
|
|
2028
2028
|
]),
|
|
2029
2029
|
_: 1
|
|
2030
2030
|
}),
|
|
@@ -2157,7 +2157,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
|
2157
2157
|
};
|
|
2158
2158
|
}
|
|
2159
2159
|
});
|
|
2160
|
-
const _hoisted_1$
|
|
2160
|
+
const _hoisted_1$3 = { class: "ck-prompt-root flex flex-col gap-2" };
|
|
2161
2161
|
const _hoisted_2$1 = {
|
|
2162
2162
|
key: 0,
|
|
2163
2163
|
style: { "grid-area": "top" }
|
|
@@ -2254,12 +2254,12 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
2254
2254
|
onMounted(adjustHeight);
|
|
2255
2255
|
__expose({ focus, submit });
|
|
2256
2256
|
return (_ctx, _cache) => {
|
|
2257
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
2257
|
+
return openBlock(), createElementBlock("div", _hoisted_1$3, [
|
|
2258
2258
|
createElementVNode("form", {
|
|
2259
2259
|
class: normalizeClass([
|
|
2260
|
-
"border-border-surface-default bg-background-input-strong
|
|
2260
|
+
"ck-prompt-form border-border-surface-default bg-background-input-strong grid items-center gap-x-0 gap-y-5 border transition-[border-radius] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] ",
|
|
2261
2261
|
hasMultipleRows.value ? "rounded-2xl" : "rounded-3xl",
|
|
2262
|
-
isKeyboardFocused.value ? "border-border-surface-focus-ring ring-border-surface-focus-ring/40 ring-2" : "ck-prompt-
|
|
2262
|
+
isKeyboardFocused.value ? "border-border-surface-focus-ring ring-border-surface-focus-ring/40 ring-2" : "ck-prompt-shadow"
|
|
2263
2263
|
]),
|
|
2264
2264
|
style: normalizeStyle({
|
|
2265
2265
|
gridTemplateColumns: "auto 1fr auto",
|
|
@@ -2316,8 +2316,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
2316
2316
|
};
|
|
2317
2317
|
}
|
|
2318
2318
|
});
|
|
2319
|
-
const CkPromptInput = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-
|
|
2320
|
-
const _hoisted_1$
|
|
2319
|
+
const CkPromptInput = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-c6b78cec"]]);
|
|
2320
|
+
const _hoisted_1$2 = {
|
|
2321
2321
|
key: 0,
|
|
2322
2322
|
class: "text-center text-content-on-surface-muted text-xs font-normal leading-4"
|
|
2323
2323
|
};
|
|
@@ -2329,7 +2329,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
2329
2329
|
},
|
|
2330
2330
|
setup(__props) {
|
|
2331
2331
|
return (_ctx, _cache) => {
|
|
2332
|
-
return _ctx.$slots.default || __props.text ? (openBlock(), createElementBlock("p", _hoisted_1$
|
|
2332
|
+
return _ctx.$slots.default || __props.text ? (openBlock(), createElementBlock("p", _hoisted_1$2, [
|
|
2333
2333
|
renderSlot(_ctx.$slots, "default", {}, () => [
|
|
2334
2334
|
createTextVNode(toDisplayString(__props.text), 1)
|
|
2335
2335
|
])
|
|
@@ -2383,7 +2383,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
|
2383
2383
|
};
|
|
2384
2384
|
}
|
|
2385
2385
|
});
|
|
2386
|
-
const _hoisted_1 = { class: "inline-flex max-w-[536px] flex-col items-end justify-start gap-1" };
|
|
2386
|
+
const _hoisted_1$1 = { class: "inline-flex max-w-[536px] flex-col items-end justify-start gap-1" };
|
|
2387
2387
|
const _hoisted_2 = ["aria-expanded"];
|
|
2388
2388
|
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
2389
2389
|
...{ name: "CkUserMessage" },
|
|
@@ -2427,7 +2427,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
2427
2427
|
nextTick(measure);
|
|
2428
2428
|
});
|
|
2429
2429
|
return (_ctx, _cache) => {
|
|
2430
|
-
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
2430
|
+
return openBlock(), createElementBlock("div", _hoisted_1$1, [
|
|
2431
2431
|
createElementVNode("div", {
|
|
2432
2432
|
ref_key: "contentRef",
|
|
2433
2433
|
ref: contentRef,
|
|
@@ -2455,6 +2455,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
2455
2455
|
}
|
|
2456
2456
|
});
|
|
2457
2457
|
const CkUserMessage = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-c759a863"]]);
|
|
2458
|
+
const _hoisted_1 = {
|
|
2459
|
+
key: 1,
|
|
2460
|
+
class: "flex size-8 shrink-0 items-center justify-center rounded-2xl bg-background-surface-muted-subtle"
|
|
2461
|
+
};
|
|
2458
2462
|
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
2459
2463
|
...{ name: "CkConversation" },
|
|
2460
2464
|
__name: "CkConversation",
|
|
@@ -2482,6 +2486,19 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
2482
2486
|
function getMessageText(message) {
|
|
2483
2487
|
return message.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
2484
2488
|
}
|
|
2489
|
+
function isVNodeEmpty(vnode) {
|
|
2490
|
+
if (vnode.type === Comment) return true;
|
|
2491
|
+
if (vnode.type === Text) return String(vnode.children ?? "").trim() === "";
|
|
2492
|
+
if (vnode.type === Fragment) {
|
|
2493
|
+
const children = vnode.children;
|
|
2494
|
+
return !children || children.every(isVNodeEmpty);
|
|
2495
|
+
}
|
|
2496
|
+
return false;
|
|
2497
|
+
}
|
|
2498
|
+
function hasHeaderActivity(message) {
|
|
2499
|
+
const slot = slots["agent-message-header-activity"];
|
|
2500
|
+
return slot ? slot({ message }).some((vnode) => !isVNodeEmpty(vnode)) : false;
|
|
2501
|
+
}
|
|
2485
2502
|
return (_ctx, _cache) => {
|
|
2486
2503
|
return openBlock(), createBlock(_sfc_main$l, { messages: __props.messages }, {
|
|
2487
2504
|
"user-message": withCtx(({ message }) => [
|
|
@@ -2533,7 +2550,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
2533
2550
|
]),
|
|
2534
2551
|
_: 2
|
|
2535
2552
|
}, [
|
|
2536
|
-
hasIcon.value || _ctx.$slots["agent-message-header"] || _ctx.$slots["agent-message-header-content"] ||
|
|
2553
|
+
hasIcon.value || _ctx.$slots["agent-message-header"] || _ctx.$slots["agent-message-header-content"] || hasHeaderActivity(message) ? {
|
|
2537
2554
|
name: "header",
|
|
2538
2555
|
fn: withCtx(() => [
|
|
2539
2556
|
renderSlot(_ctx.$slots, "agent-message-header", { message }, () => [
|
|
@@ -2552,7 +2569,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
2552
2569
|
}, () => [
|
|
2553
2570
|
__props.agentLoadingImage ? (openBlock(), createBlock(unref(UiAvatar), {
|
|
2554
2571
|
key: 0,
|
|
2555
|
-
class: "size-
|
|
2572
|
+
class: "size-4 rounded-2xl bg-background-surface-muted-subtle"
|
|
2556
2573
|
}, {
|
|
2557
2574
|
default: withCtx(() => [
|
|
2558
2575
|
createVNode(unref(UiAvatarImage), {
|
|
@@ -2561,23 +2578,27 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
2561
2578
|
}, null, 8, ["src", "alt"])
|
|
2562
2579
|
]),
|
|
2563
2580
|
_: 1
|
|
2564
|
-
})) : (openBlock(),
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2581
|
+
})) : (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
2582
|
+
createVNode(unref(UiSpinner), {
|
|
2583
|
+
class: "size-4",
|
|
2584
|
+
"aria-label": unref(labels).agentLoadingAvatarAlt
|
|
2585
|
+
}, null, 8, ["aria-label"])
|
|
2586
|
+
]))
|
|
2569
2587
|
]) : renderSlot(_ctx.$slots, "agent-message-icon", {
|
|
2570
2588
|
key: 1,
|
|
2571
2589
|
message
|
|
2572
2590
|
}, () => [
|
|
2573
|
-
createVNode(unref(UiAvatar), { class: "size-8" }, {
|
|
2591
|
+
createVNode(unref(UiAvatar), { class: "size-8 rounded-2xl bg-background-surface-muted-subtle" }, {
|
|
2574
2592
|
default: withCtx(() => [
|
|
2575
2593
|
__props.agentAvatarImage ? (openBlock(), createBlock(unref(UiAvatarImage), {
|
|
2576
2594
|
key: 0,
|
|
2577
2595
|
src: __props.agentAvatarImage,
|
|
2578
2596
|
alt: unref(labels).agentAvatarAlt
|
|
2579
2597
|
}, null, 8, ["src", "alt"])) : createCommentVNode("", true),
|
|
2580
|
-
__props.agentAvatarFallback ? (openBlock(), createBlock(unref(UiAvatarFallback), {
|
|
2598
|
+
__props.agentAvatarFallback ? (openBlock(), createBlock(unref(UiAvatarFallback), {
|
|
2599
|
+
key: 1,
|
|
2600
|
+
class: "bg-background-surface-muted-subtle rounded-2xl"
|
|
2601
|
+
}, {
|
|
2581
2602
|
default: withCtx(() => [
|
|
2582
2603
|
createTextVNode(toDisplayString(__props.agentAvatarFallback), 1)
|
|
2583
2604
|
]),
|
|
@@ -2590,7 +2611,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
2590
2611
|
]),
|
|
2591
2612
|
key: "0"
|
|
2592
2613
|
} : void 0,
|
|
2593
|
-
|
|
2614
|
+
hasHeaderActivity(message) ? {
|
|
2594
2615
|
name: "activity",
|
|
2595
2616
|
fn: withCtx(() => [
|
|
2596
2617
|
renderSlot(_ctx.$slots, "agent-message-header-activity", { message })
|
package/dist/chat-kit.css
CHANGED
|
@@ -89,18 +89,21 @@
|
|
|
89
89
|
variant (≤320px container) and the Desktop variant (≥768px container) rather
|
|
90
90
|
than snapping at a breakpoint. Range = 768 − 320 = 448; each term is
|
|
91
91
|
`clamp(mobile, calc(mobile + (100cqw − 320px) × span / 448), desktop)`. */
|
|
92
|
-
.ck-prompt-root[data-v-
|
|
92
|
+
.ck-prompt-root[data-v-c6b78cec] {
|
|
93
93
|
container-type: inline-size;
|
|
94
94
|
}
|
|
95
|
-
|
|
96
|
-
/* Solea two-layer drop shadow — warm grey + subtle orange tint. Matches the
|
|
97
|
-
`shadow/md/{1,2}` tokens from the design system; the generic `shadow-md`
|
|
98
|
-
utility from preset-wind4 uses a cold black-based shadow instead. */
|
|
99
|
-
.ck-prompt-form[data-v-d828da46] {
|
|
95
|
+
.ck-prompt-form[data-v-c6b78cec] {
|
|
100
96
|
/* 8px (mobile) → 16px (desktop) */
|
|
101
97
|
padding: clamp(8px, calc(8px + (100cqw - 320px) * 8 / 448), 16px);
|
|
102
98
|
/* 52px → 68px (= 36px button + 2× padding) */
|
|
103
99
|
min-height: clamp(52px, calc(52px + (100cqw - 320px) * 16 / 448), 68px);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Solea two-layer drop shadow — warm grey + subtle orange tint. Matches the
|
|
103
|
+
`shadow/md/{1,2}` tokens from the design system; the generic `shadow-md`
|
|
104
|
+
utility from preset-wind4 uses a cold black-based shadow instead. Applied
|
|
105
|
+
only when the field is not keyboard-focused; the focus ring replaces it. */
|
|
106
|
+
.ck-prompt-shadow[data-v-c6b78cec] {
|
|
104
107
|
box-shadow:
|
|
105
108
|
0 4px 6px -2px rgba(112, 95, 90, 0.1),
|
|
106
109
|
0 6px 14px -2px rgba(248, 94, 43, 0.05);
|
|
@@ -109,7 +112,7 @@
|
|
|
109
112
|
/* 14px → 16px font, 20px → 24px line-height, 120px → 144px (6 lines) cap.
|
|
110
113
|
`adjustHeight` reads the resolved line-height from the DOM so the auto-grow
|
|
111
114
|
math tracks these fluid values. */
|
|
112
|
-
.ck-prompt-textarea[data-v-
|
|
115
|
+
.ck-prompt-textarea[data-v-c6b78cec] {
|
|
113
116
|
font-size: clamp(14px, calc(14px + (100cqw - 320px) * 2 / 448), 16px);
|
|
114
117
|
line-height: clamp(20px, calc(20px + (100cqw - 320px) * 4 / 448), 24px);
|
|
115
118
|
max-height: clamp(120px, calc(120px + (100cqw - 320px) * 24 / 448), 144px);
|
|
@@ -118,17 +121,17 @@
|
|
|
118
121
|
/* Slim styled scrollbar for the multi-line textarea — matches Figma's 4 px
|
|
119
122
|
muted-default track. Firefox uses the native `scrollbar-*` properties;
|
|
120
123
|
Chromium/WebKit needs the `::-webkit-scrollbar` pseudo-elements. */
|
|
121
|
-
.ck-prompt-textarea[data-v-
|
|
124
|
+
.ck-prompt-textarea[data-v-c6b78cec] {
|
|
122
125
|
scrollbar-width: thin;
|
|
123
126
|
scrollbar-color: rgba(166, 141, 133, 0.3) transparent;
|
|
124
127
|
}
|
|
125
|
-
.ck-prompt-textarea[data-v-
|
|
128
|
+
.ck-prompt-textarea[data-v-c6b78cec]::-webkit-scrollbar {
|
|
126
129
|
width: 4px;
|
|
127
130
|
}
|
|
128
|
-
.ck-prompt-textarea[data-v-
|
|
131
|
+
.ck-prompt-textarea[data-v-c6b78cec]::-webkit-scrollbar-track {
|
|
129
132
|
background: transparent;
|
|
130
133
|
}
|
|
131
|
-
.ck-prompt-textarea[data-v-
|
|
134
|
+
.ck-prompt-textarea[data-v-c6b78cec]::-webkit-scrollbar-thumb {
|
|
132
135
|
background: rgba(166, 141, 133, 0.3);
|
|
133
136
|
border-radius: 9999px;
|
|
134
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CkPromptInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/base/CkPromptInput/CkPromptInput.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CkPromptInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/base/CkPromptInput/CkPromptInput.vue"],"names":[],"mappings":"AA+QA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA8GlD,iBAAS,MAAM,IAAI,IAAI,CAKtB;AASD,iBAAS,KAAK,IAAI,IAAI,CAErB;AAkLD,QAAA,IAAI,OAAO,IAAU,EAAE,OAAO,IAAU,EAAE,OAAO;;;;CAAU,EAAE,OAAO,IAAW,CAAE;AACjF,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAClD;IAAE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GACnD;IAAE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GACpD;IAAE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAO9C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;6EAKd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -7,16 +7,11 @@ type Story = StoryObj<typeof meta>;
|
|
|
7
7
|
* Drop-in conversation UI. Pass `messages` with `role`, `content` (a list of
|
|
8
8
|
* text / tool / reasoning parts), and `status` fields and CkConversation
|
|
9
9
|
* renders user bubbles, assistant markdown, avatars, and a copy button on
|
|
10
|
-
* each reply.
|
|
10
|
+
* each reply. Here the assistant messages carry a `reasoning` part whose
|
|
11
|
+
* `text` is surfaced as the header (e.g. "Thought about …") via
|
|
12
|
+
* `#agent-message-header-content`.
|
|
11
13
|
*/
|
|
12
14
|
export declare const Default: Story;
|
|
13
|
-
/**
|
|
14
|
-
* Demonstrates a chain-of-thought assistant turn with reasoning and tool
|
|
15
|
-
* calls in `message.content`. By default only text parts are rendered, so
|
|
16
|
-
* use `#agent-message-content` to opt-in to a custom rendering of the
|
|
17
|
-
* non-text parts. The host owns the visual treatment for those segments.
|
|
18
|
-
*/
|
|
19
|
-
export declare const ChainOfThought: Story;
|
|
20
15
|
/**
|
|
21
16
|
* Uses a remote avatar image (with fallback text). Use when you want a
|
|
22
17
|
* branded agent identity in each reply.
|
|
@@ -38,6 +33,12 @@ export declare const NoIcon: Story;
|
|
|
38
33
|
* your own branded icon.
|
|
39
34
|
*/
|
|
40
35
|
export declare const WithCustomIcon: Story;
|
|
36
|
+
/**
|
|
37
|
+
* A conversation with an in-flight assistant reply. The final message's
|
|
38
|
+
* `status: 'sending'` swaps its avatar for the loading icon (a spinner by
|
|
39
|
+
* default; set `agent-loading-image` to show a custom loading avatar instead).
|
|
40
|
+
*/
|
|
41
|
+
export declare const WithLoadingIcon: Story;
|
|
41
42
|
/**
|
|
42
43
|
* Overrides `#agent-message-footer` to add real action buttons next to each
|
|
43
44
|
* assistant reply: `CkCopyMessageButton` for clipboard copy and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CkConversation.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkConversation/CkConversation.stories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CkConversation.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkConversation/CkConversation.stories.ts"],"names":[],"mappings":"AASA,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAwI3D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAkCrC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AA4SnC;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,KAerB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,KAYtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,KASpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,KAe5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,KAU7B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAmC/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAiBnC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAiBpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,KA4GjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,KAmBvC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAoDjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CkConversation.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkConversation/CkConversation.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CkConversation.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/composed/CkConversation/CkConversation.vue"],"names":[],"mappings":"AA6OA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,gBAAgB,CAAC;AAOtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAkBnD,KAAK,WAAW,GAAG;IACjB,gDAAgD;IAChD,cAAc,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1D,yDAAyD;IACzD,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAClE,iDAAiD;IACjD,eAAe,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3D,oCAAoC;IACpC,oBAAoB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,8EAA8E;IAC9E,4BAA4B,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,iFAAiF;IACjF,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAClE,6EAA6E;IAC7E,8BAA8B,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1E;;;;OAIG;IACH,+BAA+B,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3E;;;;OAIG;IACH,uBAAuB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,mDAAmD;IACnD,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,KAAK,IAAI,CAAC;IAClE,qEAAqE;IACrE,0BAA0B,EAAE,CAAC,KAAK,EAAE;QAClC,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;CACZ,CAAC;AA+WF,QAAA,MAAM,UAAU;;;;6EAGd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _, a, C, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y } from "../CkHistory.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
import { _, a, C, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y } from "../CkHistory.vue_vue_type_script_setup_true_lang-BxzHdcxY.js";
|
|
2
2
|
export {
|
|
3
3
|
_ as CkAgentMessage,
|
|
4
4
|
a as CkAgentMessageHeader,
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { u } from "./useMessageHandler-N50Yj-NU.js";
|
|
2
2
|
import { C, d, p, u as u2, a } from "./useChatKitLabels-zMFV7aEz.js";
|
|
3
3
|
import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-CyrVnbS9.js";
|
|
4
|
-
import { _, a as a3, C as C2, b as b2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q, r, s, t, u as u4, v, w, x, y, z } from "./CkHistory.vue_vue_type_script_setup_true_lang-
|
|
4
|
+
import { _, a as a3, C as C2, b as b2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q, r, s, t, u as u4, v, w, x, y, z } from "./CkHistory.vue_vue_type_script_setup_true_lang-BxzHdcxY.js";
|
|
5
5
|
export {
|
|
6
6
|
C as CHAT_KIT_LABELS,
|
|
7
7
|
_ as CkAgentMessage,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aleph-alpha/chat-kit",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Chat kit package for building chat interfaces with Vue",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -91,6 +91,8 @@
|
|
|
91
91
|
"@unocss/reset": "^66.6.2",
|
|
92
92
|
"@vitejs/plugin-vue": "^6.0.3",
|
|
93
93
|
"@vue/test-utils": "^2.4.6",
|
|
94
|
+
"concurrently": "9.2.1",
|
|
95
|
+
"http-server": "14.1.1",
|
|
94
96
|
"jsdom": "^25.0.1",
|
|
95
97
|
"storybook": "^10.2.17",
|
|
96
98
|
"pinia": "^3.0.3",
|
|
@@ -102,6 +104,7 @@
|
|
|
102
104
|
"vitest": "3.2.6",
|
|
103
105
|
"vue": "^3.5.27",
|
|
104
106
|
"vue-tsc": "^3.2.4",
|
|
107
|
+
"wait-on": "9.0.3",
|
|
105
108
|
"@aleph-alpha/eslint-config-frontend": "0.7.0",
|
|
106
109
|
"@aleph-alpha/prettier-config-frontend": "2.1.0",
|
|
107
110
|
"@aleph-alpha/tsconfig-frontend": "0.7.0"
|
|
@@ -114,6 +117,8 @@
|
|
|
114
117
|
"format": "prettier --write .",
|
|
115
118
|
"lint": "prettier --check . && eslint --fix src",
|
|
116
119
|
"storybook": "storybook dev -p 6007",
|
|
117
|
-
"build-storybook": "storybook build"
|
|
120
|
+
"build-storybook": "storybook build",
|
|
121
|
+
"test:storybook": "pnpm concurrently -k --ks SIGKILL -s command-test -n \"storybook,test\" \"pnpm http-server ../../dist/storybook/chat-kit --port 4401 --silent\" \"wait-on tcp:4401 && test-storybook --url http://127.0.0.1:4401\"",
|
|
122
|
+
"test:storybook:local": "pnpm build-storybook && pnpm concurrently -k --ks SIGKILL -s command-test -n \"storybook,test\" \"pnpm http-server storybook-static --port 4401 --silent\" \"wait-on tcp:4401 && test-storybook --url http://127.0.0.1:4401\""
|
|
118
123
|
}
|
|
119
124
|
}
|
|
@@ -160,11 +160,11 @@ defineExpose({ focus, submit });
|
|
|
160
160
|
<div class="ck-prompt-root flex flex-col gap-2">
|
|
161
161
|
<form
|
|
162
162
|
:class="[
|
|
163
|
-
'border-border-surface-default bg-background-input-strong
|
|
163
|
+
'ck-prompt-form border-border-surface-default bg-background-input-strong grid items-center gap-x-0 gap-y-5 border transition-[border-radius] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] ',
|
|
164
164
|
hasMultipleRows ? 'rounded-2xl' : 'rounded-3xl',
|
|
165
165
|
isKeyboardFocused
|
|
166
166
|
? 'border-border-surface-focus-ring ring-border-surface-focus-ring/40 ring-2'
|
|
167
|
-
: 'ck-prompt-
|
|
167
|
+
: 'ck-prompt-shadow',
|
|
168
168
|
]"
|
|
169
169
|
:style="{
|
|
170
170
|
gridTemplateColumns: 'auto 1fr auto',
|
|
@@ -222,14 +222,18 @@ defineExpose({ focus, submit });
|
|
|
222
222
|
container-type: inline-size;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
/* Solea two-layer drop shadow — warm grey + subtle orange tint. Matches the
|
|
226
|
-
`shadow/md/{1,2}` tokens from the design system; the generic `shadow-md`
|
|
227
|
-
utility from preset-wind4 uses a cold black-based shadow instead. */
|
|
228
225
|
.ck-prompt-form {
|
|
229
226
|
/* 8px (mobile) → 16px (desktop) */
|
|
230
227
|
padding: clamp(8px, calc(8px + (100cqw - 320px) * 8 / 448), 16px);
|
|
231
228
|
/* 52px → 68px (= 36px button + 2× padding) */
|
|
232
229
|
min-height: clamp(52px, calc(52px + (100cqw - 320px) * 16 / 448), 68px);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Solea two-layer drop shadow — warm grey + subtle orange tint. Matches the
|
|
233
|
+
`shadow/md/{1,2}` tokens from the design system; the generic `shadow-md`
|
|
234
|
+
utility from preset-wind4 uses a cold black-based shadow instead. Applied
|
|
235
|
+
only when the field is not keyboard-focused; the focus ring replaces it. */
|
|
236
|
+
.ck-prompt-shadow {
|
|
233
237
|
box-shadow:
|
|
234
238
|
0 4px 6px -2px rgba(112, 95, 90, 0.1),
|
|
235
239
|
0 6px 14px -2px rgba(248, 94, 43, 0.05);
|
|
@@ -2,7 +2,7 @@ import type { BaseMessage, MessageContent } from '../../../types';
|
|
|
2
2
|
import CkConversation from './CkConversation.vue';
|
|
3
3
|
import { defaultMarkdownClasses } from '../../base/CkMarkdownRenderer/defaultMarkdownClasses';
|
|
4
4
|
import { render, screen } from '@testing-library/vue';
|
|
5
|
-
import { h } from 'vue';
|
|
5
|
+
import { createCommentVNode, h } from 'vue';
|
|
6
6
|
|
|
7
7
|
const now = new Date();
|
|
8
8
|
|
|
@@ -404,6 +404,37 @@ describe('CkConversation', () => {
|
|
|
404
404
|
expect(screen.getByTestId('activity')).toBeInTheDocument();
|
|
405
405
|
});
|
|
406
406
|
|
|
407
|
+
it('shows the header divider when the activity slot renders content', () => {
|
|
408
|
+
render(CkConversation, {
|
|
409
|
+
props: { messages: [agentMessage()], agentAvatarFallback: 'AI' },
|
|
410
|
+
slots: {
|
|
411
|
+
'agent-message-header-activity': () =>
|
|
412
|
+
h('button', { 'data-testid': 'activity' }, '1 tool'),
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
expect(screen.getByTestId('activity')).toBeInTheDocument();
|
|
417
|
+
expect(
|
|
418
|
+
screen.getByTestId('ck-agent-message-header-row').className,
|
|
419
|
+
).toContain('border-b');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('omits the header divider when the activity slot renders nothing for a message', () => {
|
|
423
|
+
render(CkConversation, {
|
|
424
|
+
props: { messages: [agentMessage()], agentAvatarFallback: 'AI' },
|
|
425
|
+
slots: {
|
|
426
|
+
// Emulates a falsy `v-if` inside the slot (renders a comment node).
|
|
427
|
+
'agent-message-header-activity': () => createCommentVNode('v-if'),
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// The header still renders because of the avatar icon...
|
|
432
|
+
const row = screen.getByTestId('ck-agent-message-header-row');
|
|
433
|
+
// ...but there is no activity control and no divider.
|
|
434
|
+
expect(screen.queryByTestId('activity')).not.toBeInTheDocument();
|
|
435
|
+
expect(row.className).not.toContain('border-b');
|
|
436
|
+
});
|
|
437
|
+
|
|
407
438
|
it('allows adding footer actions via agent-message-footer slot', () => {
|
|
408
439
|
render(CkConversation, {
|
|
409
440
|
props: { messages: [agentMessage()] },
|
|
@@ -4,6 +4,7 @@ import type { CkFeedbackValue } from '../../base/CkFeedbackButton';
|
|
|
4
4
|
import type {
|
|
5
5
|
BaseMessage,
|
|
6
6
|
MessageContent,
|
|
7
|
+
MessageReasoningContent,
|
|
7
8
|
MessageTextContent,
|
|
8
9
|
} from '../../../types';
|
|
9
10
|
import CkConversation from './CkConversation.vue';
|
|
@@ -30,6 +31,15 @@ function getMessageText(message: BaseMessage): string {
|
|
|
30
31
|
.join('');
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
/** First reasoning trail found on a message, used as the header text. */
|
|
35
|
+
function getReasoningText(message: BaseMessage): string {
|
|
36
|
+
return (
|
|
37
|
+
message.content.find(
|
|
38
|
+
(c): c is MessageReasoningContent => c.type === 'reasoning',
|
|
39
|
+
)?.text ?? ''
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
const markdownContent = [
|
|
34
44
|
'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.',
|
|
35
45
|
'',
|
|
@@ -67,6 +77,12 @@ const sampleMessages: BaseMessage[] = [
|
|
|
67
77
|
id: '2',
|
|
68
78
|
role: 'assistant',
|
|
69
79
|
content: [
|
|
80
|
+
{
|
|
81
|
+
type: 'reasoning',
|
|
82
|
+
id: 'r-2',
|
|
83
|
+
status: 'completed',
|
|
84
|
+
text: 'Thought about how best to help',
|
|
85
|
+
},
|
|
70
86
|
text('Of course! I am here to help. What would you like to know?'),
|
|
71
87
|
],
|
|
72
88
|
createdAt: now,
|
|
@@ -86,19 +102,32 @@ const sampleMessages: BaseMessage[] = [
|
|
|
86
102
|
{
|
|
87
103
|
id: '4',
|
|
88
104
|
role: 'assistant',
|
|
89
|
-
content: [
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: 'reasoning',
|
|
108
|
+
id: 'r-4',
|
|
109
|
+
status: 'completed',
|
|
110
|
+
text: 'Thought about the lessons learned of the Digital Transformation Phase 1',
|
|
111
|
+
},
|
|
112
|
+
text(markdownContent),
|
|
113
|
+
],
|
|
90
114
|
createdAt: now,
|
|
91
115
|
status: 'completed',
|
|
92
116
|
},
|
|
93
117
|
];
|
|
94
118
|
|
|
95
|
-
|
|
119
|
+
/**
|
|
120
|
+
* A conversation whose final assistant turn is still being generated. The
|
|
121
|
+
* message `status` of `'sending'` (or `'started'`) drives the loading icon —
|
|
122
|
+
* a spinner by default, or `agentLoadingImage` when provided.
|
|
123
|
+
*/
|
|
124
|
+
const loadingMessages: BaseMessage[] = [
|
|
96
125
|
{
|
|
97
126
|
id: '1',
|
|
98
127
|
role: 'user',
|
|
99
128
|
content: [
|
|
100
129
|
text(
|
|
101
|
-
|
|
130
|
+
"Find the lessons learned from the 'Digital Transformation Phase 1' project.",
|
|
102
131
|
),
|
|
103
132
|
],
|
|
104
133
|
createdAt: now,
|
|
@@ -107,16 +136,11 @@ const chainOfThoughtMessages: BaseMessage[] = [
|
|
|
107
136
|
{
|
|
108
137
|
id: '2',
|
|
109
138
|
role: 'assistant',
|
|
110
|
-
createdAt: now,
|
|
111
|
-
status: 'completed',
|
|
112
139
|
content: [
|
|
113
|
-
{ type: '
|
|
114
|
-
{ type: 'tool', id: 't-1', name: 'finance_lookup' },
|
|
115
|
-
{ type: 'tool', id: 't-2', name: 'compare_periods' },
|
|
116
|
-
text(
|
|
117
|
-
'## Revenue summary\n\n- **Q3 2025:** **$48.2M** (+12% YoY)\n- **Q3 2024:** $43.0M\n\nThe biggest contributor was the EMEA segment, which grew **18%** year over year. North America was roughly flat.',
|
|
118
|
-
),
|
|
140
|
+
{ type: 'text', id: 'a-loading', text: '', status: 'in_progress' },
|
|
119
141
|
],
|
|
142
|
+
createdAt: now,
|
|
143
|
+
status: 'sending',
|
|
120
144
|
},
|
|
121
145
|
];
|
|
122
146
|
|
|
@@ -174,63 +198,27 @@ const messages: BaseMessage[] = [
|
|
|
174
198
|
{
|
|
175
199
|
id: '2',
|
|
176
200
|
role: 'assistant',
|
|
177
|
-
content: [
|
|
201
|
+
content: [
|
|
202
|
+
// A \`reasoning\` part carries the thinking trail shown in the header.
|
|
203
|
+
{ type: 'reasoning', id: 'r2', text: 'Thought about how best to help', status: 'completed' },
|
|
204
|
+
{ type: 'text', id: 't2', text: 'Hi there!', status: 'completed' },
|
|
205
|
+
],
|
|
178
206
|
createdAt: new Date(),
|
|
179
207
|
status: 'completed',
|
|
180
208
|
},
|
|
181
209
|
];
|
|
182
|
-
</script>
|
|
183
|
-
|
|
184
|
-
<template>
|
|
185
|
-
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />
|
|
186
|
-
</template>`;
|
|
187
210
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const messages: BaseMessage[] = [
|
|
193
|
-
{
|
|
194
|
-
id: '1',
|
|
195
|
-
role: 'user',
|
|
196
|
-
content: [{ type: 'text', id: 't1', text: 'Compare Q3 revenue.', status: 'completed' }],
|
|
197
|
-
createdAt: new Date(),
|
|
198
|
-
status: 'completed',
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
id: '2',
|
|
202
|
-
role: 'assistant',
|
|
203
|
-
createdAt: new Date(),
|
|
204
|
-
status: 'completed',
|
|
205
|
-
content: [
|
|
206
|
-
{ type: 'reasoning', id: 'r1', status: 'completed' },
|
|
207
|
-
{ type: 'tool', id: 'tl1', name: 'finance_lookup' },
|
|
208
|
-
{ type: 'tool', id: 'tl2', name: 'compare_periods' },
|
|
209
|
-
{ type: 'text', id: 't2', text: 'Q3 grew **12% YoY**.', status: 'completed' },
|
|
210
|
-
],
|
|
211
|
-
},
|
|
212
|
-
];
|
|
211
|
+
// Pull the reasoning trail off the message so it can be shown in the header.
|
|
212
|
+
function getReasoningText(message: BaseMessage): string {
|
|
213
|
+
return message.content.find((c) => c.type === 'reasoning')?.text ?? '';
|
|
214
|
+
}
|
|
213
215
|
</script>
|
|
214
216
|
|
|
215
217
|
<template>
|
|
216
218
|
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
217
|
-
<!--
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
part (text, tool, reasoning) and render them however you like.
|
|
221
|
-
-->
|
|
222
|
-
<template #agent-message-content="{ message }">
|
|
223
|
-
<div class="flex flex-col gap-2">
|
|
224
|
-
<template v-for="part in message.content" :key="part.id">
|
|
225
|
-
<span v-if="part.type === 'reasoning'" class="text-xs italic opacity-60">
|
|
226
|
-
Reasoning: {{ part.status }}
|
|
227
|
-
</span>
|
|
228
|
-
<span v-else-if="part.type === 'tool'" class="text-xs font-mono opacity-70">
|
|
229
|
-
⚙️ {{ part.name }}
|
|
230
|
-
</span>
|
|
231
|
-
<p v-else-if="part.type === 'text'">{{ part.text }}</p>
|
|
232
|
-
</template>
|
|
233
|
-
</div>
|
|
219
|
+
<!-- Surface the reasoning trail from the message data as the header. -->
|
|
220
|
+
<template #agent-message-header-content="{ message }">
|
|
221
|
+
{{ getReasoningText(message) }}
|
|
234
222
|
</template>
|
|
235
223
|
</CkConversation>
|
|
236
224
|
</template>`;
|
|
@@ -288,6 +276,33 @@ const messages: BaseMessage[] = [/* ... */];
|
|
|
288
276
|
</CkConversation>
|
|
289
277
|
</template>`;
|
|
290
278
|
|
|
279
|
+
const withLoadingIconTemplateSource = `<script setup lang="ts">
|
|
280
|
+
import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
281
|
+
import type { BaseMessage } from '@aleph-alpha/chat-kit';
|
|
282
|
+
|
|
283
|
+
const messages: BaseMessage[] = [
|
|
284
|
+
{
|
|
285
|
+
id: '1',
|
|
286
|
+
role: 'user',
|
|
287
|
+
content: [{ type: 'text', id: 't1', text: 'Find the lessons learned.', status: 'completed' }],
|
|
288
|
+
createdAt: new Date(),
|
|
289
|
+
status: 'completed',
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: '2',
|
|
293
|
+
role: 'assistant',
|
|
294
|
+
// A 'sending' / 'started' status renders the loading icon (spinner by default).
|
|
295
|
+
content: [{ type: 'text', id: 't2', text: '', status: 'in_progress' }],
|
|
296
|
+
createdAt: new Date(),
|
|
297
|
+
status: 'sending',
|
|
298
|
+
},
|
|
299
|
+
];
|
|
300
|
+
</script>
|
|
301
|
+
|
|
302
|
+
<template>
|
|
303
|
+
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />
|
|
304
|
+
</template>`;
|
|
305
|
+
|
|
291
306
|
const withFooterActionsTemplateSource = `<script setup lang="ts">
|
|
292
307
|
import { ref } from 'vue';
|
|
293
308
|
import {
|
|
@@ -470,51 +485,25 @@ import { CkConversation } from '@aleph-alpha/chat-kit';
|
|
|
470
485
|
* Drop-in conversation UI. Pass `messages` with `role`, `content` (a list of
|
|
471
486
|
* text / tool / reasoning parts), and `status` fields and CkConversation
|
|
472
487
|
* renders user bubbles, assistant markdown, avatars, and a copy button on
|
|
473
|
-
* each reply.
|
|
488
|
+
* each reply. Here the assistant messages carry a `reasoning` part whose
|
|
489
|
+
* `text` is surfaced as the header (e.g. "Thought about …") via
|
|
490
|
+
* `#agent-message-header-content`.
|
|
474
491
|
*/
|
|
475
492
|
export const Default: Story = {
|
|
476
493
|
render: () => ({
|
|
477
494
|
components: { CkConversation },
|
|
478
495
|
setup() {
|
|
479
|
-
return { messages: sampleMessages };
|
|
480
|
-
},
|
|
481
|
-
template:
|
|
482
|
-
'<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />',
|
|
483
|
-
}),
|
|
484
|
-
parameters: { docs: { source: { code: defaultTemplateSource } } },
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Demonstrates a chain-of-thought assistant turn with reasoning and tool
|
|
489
|
-
* calls in `message.content`. By default only text parts are rendered, so
|
|
490
|
-
* use `#agent-message-content` to opt-in to a custom rendering of the
|
|
491
|
-
* non-text parts. The host owns the visual treatment for those segments.
|
|
492
|
-
*/
|
|
493
|
-
export const ChainOfThought: Story = {
|
|
494
|
-
render: () => ({
|
|
495
|
-
components: { CkConversation },
|
|
496
|
-
setup() {
|
|
497
|
-
return { messages: chainOfThoughtMessages };
|
|
496
|
+
return { messages: sampleMessages, getReasoningText };
|
|
498
497
|
},
|
|
499
498
|
template: `
|
|
500
499
|
<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;">
|
|
501
|
-
<template #agent-message-content="{ message }">
|
|
502
|
-
|
|
503
|
-
<template v-for="part in message.content" :key="part.id">
|
|
504
|
-
<span v-if="part.type === 'reasoning'" style="font-size: 12px; font-style: italic; opacity: 0.6;">
|
|
505
|
-
Reasoning: {{ part.status }}
|
|
506
|
-
</span>
|
|
507
|
-
<span v-else-if="part.type === 'tool'" style="font-size: 12px; font-family: monospace; opacity: 0.7;">
|
|
508
|
-
⚙️ {{ part.name }}
|
|
509
|
-
</span>
|
|
510
|
-
<p v-else-if="part.type === 'text'" style="margin: 0;">{{ part.text }}</p>
|
|
511
|
-
</template>
|
|
512
|
-
</div>
|
|
500
|
+
<template #agent-message-header-content="{ message }">
|
|
501
|
+
{{ getReasoningText(message) }}
|
|
513
502
|
</template>
|
|
514
503
|
</CkConversation>
|
|
515
504
|
`,
|
|
516
505
|
}),
|
|
517
|
-
parameters: { docs: { source: { code:
|
|
506
|
+
parameters: { docs: { source: { code: defaultTemplateSource } } },
|
|
518
507
|
};
|
|
519
508
|
|
|
520
509
|
/**
|
|
@@ -588,6 +577,23 @@ export const WithCustomIcon: Story = {
|
|
|
588
577
|
parameters: { docs: { source: { code: withCustomIconTemplateSource } } },
|
|
589
578
|
};
|
|
590
579
|
|
|
580
|
+
/**
|
|
581
|
+
* A conversation with an in-flight assistant reply. The final message's
|
|
582
|
+
* `status: 'sending'` swaps its avatar for the loading icon (a spinner by
|
|
583
|
+
* default; set `agent-loading-image` to show a custom loading avatar instead).
|
|
584
|
+
*/
|
|
585
|
+
export const WithLoadingIcon: Story = {
|
|
586
|
+
render: () => ({
|
|
587
|
+
components: { CkConversation },
|
|
588
|
+
setup() {
|
|
589
|
+
return { messages: loadingMessages };
|
|
590
|
+
},
|
|
591
|
+
template:
|
|
592
|
+
'<CkConversation :messages="messages" agent-avatar-fallback="AI" style="height: 100%;" />',
|
|
593
|
+
}),
|
|
594
|
+
parameters: { docs: { source: { code: withLoadingIconTemplateSource } } },
|
|
595
|
+
};
|
|
596
|
+
|
|
591
597
|
/**
|
|
592
598
|
* Overrides `#agent-message-footer` to add real action buttons next to each
|
|
593
599
|
* assistant reply: `CkCopyMessageButton` for clipboard copy and
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
UiAvatarImage,
|
|
15
15
|
UiSpinner,
|
|
16
16
|
} from '@aleph-alpha/ui-library';
|
|
17
|
-
import { computed } from 'vue';
|
|
17
|
+
import { Comment, Fragment, Text, computed, type VNode } from 'vue';
|
|
18
18
|
|
|
19
19
|
defineOptions({ name: 'CkConversation' });
|
|
20
20
|
|
|
@@ -92,6 +92,30 @@ function getMessageText(message: BaseMessage): string {
|
|
|
92
92
|
.map((c) => c.text)
|
|
93
93
|
.join('');
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
/** Whether a rendered VNode tree is effectively empty (e.g. a falsy `v-if`). */
|
|
97
|
+
function isVNodeEmpty(vnode: VNode): boolean {
|
|
98
|
+
if (vnode.type === Comment) return true;
|
|
99
|
+
if (vnode.type === Text) return String(vnode.children ?? '').trim() === '';
|
|
100
|
+
if (vnode.type === Fragment) {
|
|
101
|
+
const children = vnode.children as VNode[] | null;
|
|
102
|
+
return !children || children.every(isVNodeEmpty);
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Whether the `agent-message-header-activity` slot renders real content for
|
|
109
|
+
* this message. Gates both the activity control and the header divider, so a
|
|
110
|
+
* host can toggle them per message with a `v-if` inside the slot instead of
|
|
111
|
+
* the divider being forced on for every message once the slot is defined.
|
|
112
|
+
*/
|
|
113
|
+
function hasHeaderActivity(message: BaseMessage): boolean {
|
|
114
|
+
const slot = slots['agent-message-header-activity'] as
|
|
115
|
+
| ((props: { message: BaseMessage }) => VNode[])
|
|
116
|
+
| undefined;
|
|
117
|
+
return slot ? slot({ message }).some((vnode) => !isVNodeEmpty(vnode)) : false;
|
|
118
|
+
}
|
|
95
119
|
</script>
|
|
96
120
|
|
|
97
121
|
<template>
|
|
@@ -116,7 +140,7 @@ function getMessageText(message: BaseMessage): string {
|
|
|
116
140
|
hasIcon ||
|
|
117
141
|
$slots['agent-message-header'] ||
|
|
118
142
|
$slots['agent-message-header-content'] ||
|
|
119
|
-
|
|
143
|
+
hasHeaderActivity(message)
|
|
120
144
|
"
|
|
121
145
|
#header
|
|
122
146
|
>
|
|
@@ -125,31 +149,42 @@ function getMessageText(message: BaseMessage): string {
|
|
|
125
149
|
<template v-if="hasIcon" #icon>
|
|
126
150
|
<template v-if="isLoading(message)">
|
|
127
151
|
<slot name="agent-message-loading-icon" :message="message">
|
|
128
|
-
<UiAvatar
|
|
152
|
+
<UiAvatar
|
|
153
|
+
v-if="agentLoadingImage"
|
|
154
|
+
class="size-4 rounded-2xl bg-background-surface-muted-subtle"
|
|
155
|
+
>
|
|
129
156
|
<UiAvatarImage
|
|
130
157
|
:src="agentLoadingImage"
|
|
131
158
|
:alt="labels.agentLoadingAvatarAlt"
|
|
132
159
|
/>
|
|
133
160
|
</UiAvatar>
|
|
134
|
-
<
|
|
161
|
+
<div
|
|
135
162
|
v-else
|
|
136
|
-
class="size-8"
|
|
137
|
-
|
|
138
|
-
|
|
163
|
+
class="flex size-8 shrink-0 items-center justify-center rounded-2xl bg-background-surface-muted-subtle"
|
|
164
|
+
>
|
|
165
|
+
<UiSpinner
|
|
166
|
+
class="size-4"
|
|
167
|
+
:aria-label="labels.agentLoadingAvatarAlt"
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
139
170
|
</slot>
|
|
140
171
|
</template>
|
|
141
172
|
|
|
142
173
|
<template v-else>
|
|
143
174
|
<slot name="agent-message-icon" :message="message">
|
|
144
|
-
<UiAvatar
|
|
175
|
+
<UiAvatar
|
|
176
|
+
class="size-8 rounded-2xl bg-background-surface-muted-subtle"
|
|
177
|
+
>
|
|
145
178
|
<UiAvatarImage
|
|
146
179
|
v-if="agentAvatarImage"
|
|
147
180
|
:src="agentAvatarImage"
|
|
148
181
|
:alt="labels.agentAvatarAlt"
|
|
149
182
|
/>
|
|
150
|
-
<UiAvatarFallback
|
|
151
|
-
agentAvatarFallback
|
|
152
|
-
|
|
183
|
+
<UiAvatarFallback
|
|
184
|
+
v-if="agentAvatarFallback"
|
|
185
|
+
class="bg-background-surface-muted-subtle rounded-2xl"
|
|
186
|
+
>{{ agentAvatarFallback }}</UiAvatarFallback
|
|
187
|
+
>
|
|
153
188
|
</UiAvatar>
|
|
154
189
|
</slot>
|
|
155
190
|
</template>
|
|
@@ -157,10 +192,7 @@ function getMessageText(message: BaseMessage): string {
|
|
|
157
192
|
|
|
158
193
|
<slot name="agent-message-header-content" :message="message" />
|
|
159
194
|
|
|
160
|
-
<template
|
|
161
|
-
v-if="$slots['agent-message-header-activity']"
|
|
162
|
-
#activity
|
|
163
|
-
>
|
|
195
|
+
<template v-if="hasHeaderActivity(message)" #activity>
|
|
164
196
|
<slot
|
|
165
197
|
name="agent-message-header-activity"
|
|
166
198
|
:message="message"
|