@aleph-alpha/chat-kit 5.8.0 → 5.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/{CkHistory.vue_vue_type_script_setup_true_lang-DG96wNug.js → CkHistory.vue_vue_type_script_setup_true_lang-CEqJtMuI.js} +61 -40
  2. package/dist/adapters/responses-api.d.ts +1 -3
  3. package/dist/adapters/responses-api.d.ts.map +1 -1
  4. package/dist/adapters/responses-api.js +55 -65
  5. package/dist/chat-kit.css +1 -1
  6. package/dist/components/base/CkConversationLayout/CkConversationLayout.stories.d.ts +7 -0
  7. package/dist/components/base/CkConversationLayout/CkConversationLayout.stories.d.ts.map +1 -1
  8. package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts +3 -1
  9. package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts.map +1 -1
  10. package/dist/components/composed/CkConversation/CkConversation.stories.d.ts +23 -3
  11. package/dist/components/composed/CkConversation/CkConversation.stories.d.ts.map +1 -1
  12. package/dist/components/composed/CkConversation/CkConversation.vue.d.ts +17 -2
  13. package/dist/components/composed/CkConversation/CkConversation.vue.d.ts.map +1 -1
  14. package/dist/components/composed/CkHistory/CkHistory.vue.d.ts +1 -1
  15. package/dist/components/index.js +1 -1
  16. package/dist/index.js +1 -1
  17. package/package.json +3 -3
  18. package/src/adapters/arena.spec.ts +12 -18
  19. package/src/adapters/responses-api.spec.ts +6 -3
  20. package/src/adapters/responses-api.ts +80 -86
  21. package/src/components/base/CkConversationLayout/CkConversationLayout.spec.ts +209 -1
  22. package/src/components/base/CkConversationLayout/CkConversationLayout.stories.ts +84 -0
  23. package/src/components/base/CkConversationLayout/CkConversationLayout.vue +59 -21
  24. package/src/components/composed/CkConversation/CkConversation.spec.ts +96 -5
  25. package/src/components/composed/CkConversation/CkConversation.stories.ts +328 -4
  26. package/src/components/composed/CkConversation/CkConversation.vue +38 -8
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, openBlock, createBlock, unref, createElementBlock, createElementVNode, normalizeClass, renderSlot, createCommentVNode, mergeProps, withCtx, computed, createVNode, toDisplayString, ref, onBeforeUnmount, useSlots, onMounted, nextTick, onUnmounted, watch, Fragment, renderList, normalizeStyle, Transition, createStaticVNode, Teleport, withModifiers, toValue, h, toRefs, useId, createTextVNode, useAttrs, resolveDynamicComponent, useTemplateRef, onUpdated, createSlots, normalizeProps, guardReactiveProps, Comment, Text } from "vue";
2
- import { UiIcon, UiButton, UiFileType, UiPopover, UiPopoverTrigger, UiPopoverContent, UiTooltip, formatFileSize, UiDialog, UiDialogContent, UiDialogDescription, UiFieldLabel, UiToggleGroup, UiToggleGroupItem, UiField, UiTextarea, UiFileItem, UiProgress, Primitive, UiFloatActions, UiFloatActionItems, UiAvatar, UiAvatarImage, UiSpinner, UiAvatarFallback, UiSidebarPopoverMenu, UiSidebarPopoverMenuItem } from "@aleph-alpha/ui-library";
2
+ import { UiIcon, UiButton, UiFileType, UiPopover, UiPopoverTrigger, UiPopoverContent, UiTooltip, formatFileSize, UiDialog, UiDialogContent, UiDialogDescription, UiFieldLabel, UiToggleGroup, UiToggleGroupItem, UiField, UiTextarea, UiFileItem, UiProgress, Primitive, UiFloatActions, UiFloatActionItems, UiCodeBlock, UiAvatar, UiAvatarImage, UiSpinner, UiAvatarFallback, UiSidebarPopoverMenu, UiSidebarPopoverMenuItem } from "@aleph-alpha/ui-library";
3
3
  import { u as useChatKitLabels, d as defaultChatKitLabels, r as remarkCitations, b as useMarkdownParser } from "./useChatKitLabels-CMOr3Kjq.js";
4
4
  const MINUTE = 60;
5
5
  const HOUR = 60 * MINUTE;
@@ -185,7 +185,7 @@ const _hoisted_1$e = { class: "ck-citation-card flex w-[22.5rem] max-w-[90vw] fl
185
185
  const _hoisted_2$8 = { class: "flex items-center gap-2" };
186
186
  const _hoisted_3$7 = ["title"];
187
187
  const _hoisted_4$7 = { class: "line-clamp-6 break-words text-sm leading-5 text-content-on-surface-secondary" };
188
- const _hoisted_5$5 = {
188
+ const _hoisted_5$4 = {
189
189
  key: 0,
190
190
  class: "text-sm leading-5 text-content-on-surface-muted"
191
191
  };
@@ -244,7 +244,7 @@ const _sfc_main$o = /* @__PURE__ */ defineComponent({
244
244
  }, 8, ["aria-label"])) : createCommentVNode("", true)
245
245
  ]),
246
246
  createElementVNode("p", _hoisted_4$7, toDisplayString(__props.snippet), 1),
247
- __props.locationLabel ? (openBlock(), createElementBlock("p", _hoisted_5$5, toDisplayString(__props.locationLabel), 1)) : createCommentVNode("", true)
247
+ __props.locationLabel ? (openBlock(), createElementBlock("p", _hoisted_5$4, toDisplayString(__props.locationLabel), 1)) : createCommentVNode("", true)
248
248
  ]);
249
249
  };
250
250
  }
@@ -388,18 +388,13 @@ const _hoisted_4$6 = {
388
388
  key: 1,
389
389
  class: "flex min-w-0 justify-start"
390
390
  };
391
- const _hoisted_5$4 = {
392
- key: 0,
393
- "data-message-row": "agent",
394
- class: "flex min-w-0 justify-start"
395
- };
396
391
  const _sfc_main$m = /* @__PURE__ */ defineComponent({
397
392
  ...{ name: "CkConversationLayout" },
398
393
  __name: "CkConversationLayout",
399
394
  props: {
400
395
  messages: {}
401
396
  },
402
- setup(__props) {
397
+ setup(__props, { expose: __expose }) {
403
398
  const props = __props;
404
399
  const slots = useSlots();
405
400
  const scrollContainerRef = ref(null);
@@ -475,26 +470,36 @@ const _sfc_main$m = /* @__PURE__ */ defineComponent({
475
470
  const lastUserTop = lastUserRow.offsetTop;
476
471
  const lastRowBottom = lastRow.offsetTop + lastRow.offsetHeight;
477
472
  const contentFromUserToEnd = lastRowBottom - lastUserTop;
478
- const gap = parseFloat(getComputedStyle(container).rowGap) || 0;
473
+ const topMargin = parseFloat(getComputedStyle(lastUserRow).marginTop) || 0;
479
474
  spacerHeight.value = Math.max(
480
475
  0,
481
- containerHeight.value - contentFromUserToEnd - gap
476
+ containerHeight.value - contentFromUserToEnd - topMargin
482
477
  );
483
478
  }
484
- function scrollUserMessageToTop() {
479
+ function scrollMessageToTop(index) {
485
480
  const container = scrollContainerRef.value;
486
481
  if (!container) return;
487
- hasBottomSpacer.value = true;
488
- spacerHeight.value = containerHeight.value;
482
+ const rows = container.querySelectorAll("[data-message-row]");
483
+ if (rows.length === 0) return;
484
+ const targetIndex = index ?? rows.length - 1;
485
+ const targetRow = rows[targetIndex];
486
+ if (!targetRow) return;
487
+ const topMargin = parseFloat(getComputedStyle(targetRow).marginTop) || 0;
488
+ const targetTop = targetRow.offsetTop - topMargin;
489
+ const lastRow = rows[rows.length - 1];
490
+ const contentBottom = lastRow.offsetTop + lastRow.offsetHeight;
491
+ const contentBelowTarget = contentBottom - targetTop;
492
+ const needsSpacer = contentBelowTarget < containerHeight.value;
493
+ if (needsSpacer) {
494
+ hasBottomSpacer.value = true;
495
+ spacerHeight.value = containerHeight.value - contentBelowTarget;
496
+ } else {
497
+ hasBottomSpacer.value = false;
498
+ spacerHeight.value = 0;
499
+ }
489
500
  nextTick(() => {
490
- const userRows = container.querySelectorAll(
491
- '[data-message-row="user"]'
492
- );
493
- const lastUserRow = userRows[userRows.length - 1];
494
- if (lastUserRow) {
495
- lastUserRow.scrollIntoView({ behavior: "smooth", block: "start" });
496
- }
497
- isAutoScrollEnabled.value = true;
501
+ container.scrollTo({ top: targetTop, behavior: "smooth" });
502
+ isAutoScrollEnabled.value = needsSpacer;
498
503
  });
499
504
  }
500
505
  function scrollToEndOfContent() {
@@ -516,7 +521,7 @@ const _sfc_main$m = /* @__PURE__ */ defineComponent({
516
521
  const lastMessage = props.messages[newLen - 1];
517
522
  if (lastMessage?.role === "user") {
518
523
  nextTick(() => {
519
- scrollUserMessageToTop();
524
+ scrollMessageToTop(newLen - 1);
520
525
  updateFades();
521
526
  });
522
527
  }
@@ -540,6 +545,7 @@ const _sfc_main$m = /* @__PURE__ */ defineComponent({
540
545
  },
541
546
  { deep: true }
542
547
  );
548
+ __expose({ scrollToMessage: scrollMessageToTop });
543
549
  return (_ctx, _cache) => {
544
550
  return openBlock(), createElementBlock("div", _hoisted_1$c, [
545
551
  createElementVNode("div", {
@@ -549,25 +555,29 @@ const _sfc_main$m = /* @__PURE__ */ defineComponent({
549
555
  createElementVNode("div", {
550
556
  ref_key: "scrollContainerRef",
551
557
  ref: scrollContainerRef,
552
- class: "relative flex min-h-0 flex-1 flex-col gap-8 overflow-y-auto",
558
+ class: "relative flex min-h-0 flex-1 flex-col overflow-y-auto",
553
559
  onScroll: handleScroll
554
560
  }, [
555
- (openBlock(true), createElementBlock(Fragment, null, renderList(__props.messages, (message) => {
561
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.messages, (message, index) => {
556
562
  return openBlock(), createElementBlock("div", {
557
563
  key: message.id,
558
564
  "data-message-row": message.role,
559
- class: "min-w-0"
565
+ class: normalizeClass(["min-w-0", index === 0 ? "mt-2xl" : "mt-3xl"])
560
566
  }, [
561
567
  message.role === "user" ? (openBlock(), createElementBlock("div", _hoisted_3$6, [
562
568
  renderSlot(_ctx.$slots, "user-message", { message })
563
569
  ])) : (openBlock(), createElementBlock("div", _hoisted_4$6, [
564
570
  renderSlot(_ctx.$slots, "agent-message", { message })
565
571
  ]))
566
- ], 8, _hoisted_2$7);
572
+ ], 10, _hoisted_2$7);
567
573
  }), 128)),
568
- _ctx.$slots["thread-footer"] ? (openBlock(), createElementBlock("div", _hoisted_5$4, [
574
+ _ctx.$slots["thread-footer"] ? (openBlock(), createElementBlock("div", {
575
+ key: 0,
576
+ "data-message-row": "agent",
577
+ class: normalizeClass(["flex min-w-0 justify-start", __props.messages.length === 0 ? "mt-2xl" : "mt-3xl"])
578
+ }, [
569
579
  renderSlot(_ctx.$slots, "thread-footer")
570
- ])) : createCommentVNode("", true),
580
+ ], 2)) : createCommentVNode("", true),
571
581
  hasBottomSpacer.value ? (openBlock(), createElementBlock("div", {
572
582
  key: 1,
573
583
  "aria-hidden": "true",
@@ -2579,7 +2589,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2579
2589
  agentLoadingImage: { default: "" },
2580
2590
  agentMarkdownClasses: {}
2581
2591
  },
2582
- setup(__props) {
2592
+ setup(__props, { expose: __expose }) {
2583
2593
  const props = __props;
2584
2594
  const slots = useSlots();
2585
2595
  const labels = useChatKitLabels();
@@ -2609,8 +2619,17 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2609
2619
  const slot = slots["agent-message-header-activity"];
2610
2620
  return slot ? slot({ message }).some((vnode) => !isVNodeEmpty(vnode)) : false;
2611
2621
  }
2622
+ const layoutRef = useTemplateRef("layoutRef");
2623
+ function scrollToMessage(index) {
2624
+ layoutRef.value?.scrollToMessage(index);
2625
+ }
2626
+ __expose({ scrollToMessage });
2612
2627
  return (_ctx, _cache) => {
2613
- return openBlock(), createBlock(_sfc_main$m, { messages: __props.messages }, createSlots({
2628
+ return openBlock(), createBlock(_sfc_main$m, {
2629
+ ref_key: "layoutRef",
2630
+ ref: layoutRef,
2631
+ messages: __props.messages
2632
+ }, createSlots({
2614
2633
  "user-message": withCtx(({ message }) => [
2615
2634
  createElementVNode("div", {
2616
2635
  class: normalizeClass({ "ml-8": hasIcon.value })
@@ -2647,15 +2666,17 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2647
2666
  createVNode(_sfc_main$g, {
2648
2667
  content: getMessageText(message),
2649
2668
  classes: __props.agentMarkdownClasses
2650
- }, createSlots({ _: 2 }, [
2651
- _ctx.$slots["agent-message-code-block"] ? {
2652
- name: "code-block",
2653
- fn: withCtx((codeBlockProps) => [
2654
- renderSlot(_ctx.$slots, "agent-message-code-block", normalizeProps(guardReactiveProps(codeBlockProps)))
2655
- ]),
2656
- key: "0"
2657
- } : void 0
2658
- ]), 1032, ["content", "classes"])
2669
+ }, {
2670
+ "code-block": withCtx((codeBlockProps) => [
2671
+ renderSlot(_ctx.$slots, "agent-message-code-block", normalizeProps(guardReactiveProps(codeBlockProps)), () => [
2672
+ createVNode(unref(UiCodeBlock), {
2673
+ code: codeBlockProps.code,
2674
+ language: codeBlockProps.language || "text"
2675
+ }, null, 8, ["code", "language"])
2676
+ ])
2677
+ ]),
2678
+ _: 3
2679
+ }, 8, ["content", "classes"])
2659
2680
  ])
2660
2681
  ]),
2661
2682
  _: 2
@@ -260,7 +260,5 @@ export interface ResponseConversationTree extends ConversationTree {
260
260
  * return type is assignable to `ConversationTree`, so you can pipe it
261
261
  * straight into `useMessageHandler().setTree(...)`.
262
262
  */
263
- export declare function responsesToTree(responses: StoredResponse[], opts?: {
264
- arenaWinners?: Record<string, string>;
265
- }): ResponseConversationTree;
263
+ export declare function responsesToTree(responses: StoredResponse[]): ResponseConversationTree;
266
264
  //# sourceMappingURL=responses-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"responses-api.d.ts","sourceRoot":"","sources":["../../src/adapters/responses-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"responses-api.d.ts","sourceRoot":"","sources":["../../src/adapters/responses-api.ts"],"names":[],"mappings":"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"}
@@ -101,41 +101,49 @@ function parseResponseAttachments(resp) {
101
101
  }
102
102
  return attachments;
103
103
  }
104
+ function toMessageAttachments(attachments) {
105
+ return attachments.map(
106
+ (a) => ({
107
+ name: a.fileName,
108
+ fileId: a.fileId,
109
+ fileName: a.fileName,
110
+ searchStoreId: a.searchStoreId,
111
+ ...a.documentId ? { documentId: a.documentId } : {}
112
+ })
113
+ );
114
+ }
115
+ function buildUserNode(resp, input, idx, responseAttachments, isFirstUserNode) {
116
+ const role = input.role;
117
+ const text = extractInputText(input.content);
118
+ const hasContent = text || responseAttachments?.length;
119
+ if (role !== "user" || !hasContent) return null;
120
+ const metadata = {
121
+ responseId: resp.id,
122
+ ...resp.model ? { model: resp.model } : {}
123
+ };
124
+ if (responseAttachments && isFirstUserNode) {
125
+ metadata.attachments = toMessageAttachments(responseAttachments);
126
+ }
127
+ return {
128
+ id: `user-${resp.id}-${idx}`,
129
+ role: "user",
130
+ content: [textPart(text)],
131
+ createdAt: new Date(resp.created_at * 1e3),
132
+ metadata
133
+ };
134
+ }
104
135
  function responseToMessageNodes(resp) {
105
136
  const nodes = [];
106
137
  const responseAttachments = parseResponseAttachments(resp);
107
- let userNodesPushed = 0;
108
- if (resp.request_input) {
109
- for (const [idx, input] of resp.request_input.entries()) {
110
- const role = input.role;
111
- const rawContent = input.content;
112
- const text = extractInputText(rawContent);
113
- const userContent = text || responseAttachments?.length;
114
- if (role !== "user" || !userContent) continue;
115
- const metadata = {
116
- responseId: resp.id,
117
- ...resp.model ? { model: resp.model } : {}
118
- };
119
- if (responseAttachments && userNodesPushed === 0) {
120
- metadata.attachments = responseAttachments.map(
121
- (a) => ({
122
- name: a.fileName,
123
- fileId: a.fileId,
124
- fileName: a.fileName,
125
- searchStoreId: a.searchStoreId,
126
- ...a.documentId ? { documentId: a.documentId } : {}
127
- })
128
- );
129
- }
130
- nodes.push({
131
- id: `user-${resp.id}-${idx}`,
132
- role: "user",
133
- content: [textPart(text)],
134
- createdAt: new Date(resp.created_at * 1e3),
135
- metadata
136
- });
137
- userNodesPushed += 1;
138
- }
138
+ for (const [idx, input] of resp.request_input?.entries() ?? []) {
139
+ const userNode = buildUserNode(
140
+ resp,
141
+ input,
142
+ idx,
143
+ responseAttachments,
144
+ nodes.length === 0
145
+ );
146
+ if (userNode) nodes.push(userNode);
139
147
  }
140
148
  const assistantParts = toAssistantParts(resp);
141
149
  if (assistantParts.length > 0) {
@@ -144,7 +152,12 @@ function responseToMessageNodes(resp) {
144
152
  role: "assistant",
145
153
  content: assistantParts,
146
154
  createdAt: new Date((resp.completed_at ?? resp.created_at) * 1e3),
147
- metadata: { responseId: resp.id }
155
+ // A stored response carries a single `model` covering both its input and
156
+ // output, so the assistant node gets the same model id as its user node.
157
+ metadata: {
158
+ responseId: resp.id,
159
+ ...resp.model ? { model: resp.model } : {}
160
+ }
148
161
  });
149
162
  }
150
163
  return nodes;
@@ -209,7 +222,7 @@ function linkResponse(state, resp) {
209
222
  }
210
223
  tailMessageByResponse.set(resp.id, chainParent);
211
224
  }
212
- function responsesToTree(responses, opts) {
225
+ function responsesToTree(responses) {
213
226
  if (responses.length === 0) {
214
227
  return { nodes: {}, rootId: null };
215
228
  }
@@ -225,7 +238,6 @@ function responsesToTree(responses, opts) {
225
238
  const rootId = collapseArenaComparisons(
226
239
  state.treeNodes,
227
240
  responses,
228
- opts?.arenaWinners ?? {},
229
241
  state.rootMessageId,
230
242
  state.userMessageByResponse
231
243
  );
@@ -247,27 +259,19 @@ function parseArenaMeta(resp) {
247
259
  return {
248
260
  matchupId: a.matchup_id,
249
261
  modelId: typeof a.model_id === "string" ? a.model_id : void 0,
250
- slot: typeof a.slot === "string" ? a.slot : void 0,
251
- slotSeed: typeof a.slot_seed === "string" ? a.slot_seed : void 0,
252
- variant: typeof a.variant === "string" ? a.variant : void 0
262
+ slot: typeof a.slot === "string" ? a.slot : void 0
253
263
  };
254
264
  }
255
- function collapseArenaComparisons(nodes, responses, arenaWinners, rootMessageId, userMessageByResponse) {
265
+ function collapseArenaComparisons(nodes, responses, rootMessageId, userMessageByResponse) {
256
266
  const userNodeFor = (responseId) => {
257
267
  const id = userMessageByResponse.get(responseId);
258
268
  return id ? nodes[id] : void 0;
259
269
  };
260
270
  let root = rootMessageId;
261
- for (const [matchupId, group] of groupResponsesByMatchup(responses)) {
271
+ for (const [, group] of groupResponsesByMatchup(responses)) {
262
272
  if (group.length < 2) continue;
263
273
  try {
264
- root = foldArenaGroup(
265
- nodes,
266
- group,
267
- arenaWinners[matchupId],
268
- userNodeFor,
269
- root
270
- );
274
+ root = foldArenaGroup(nodes, group, userNodeFor, root);
271
275
  } catch {
272
276
  }
273
277
  }
@@ -298,7 +302,8 @@ function stampLaneAssistant(nodes, resp) {
298
302
  const meta = parseArenaMeta(resp);
299
303
  const assistant = nodes[getAssistantNodeId(resp)];
300
304
  if (assistant && meta) {
301
- assistant.metadata.arena = { modelId: meta.modelId, slot: meta.slot };
305
+ assistant.metadata.arena = { slot: meta.slot };
306
+ delete assistant.metadata.model;
302
307
  }
303
308
  }
304
309
  function attachLane(canonicalUser, assistant) {
@@ -327,17 +332,7 @@ function activateForkNode(nodes, canonicalUser, sharedParentId, root) {
327
332
  }
328
333
  return root;
329
334
  }
330
- function applyArenaWinner(canonicalUser, group, winnerRespId) {
331
- if (!winnerRespId) return;
332
- const winnerResp = group.find((r) => r.id === winnerRespId);
333
- if (!winnerResp) return;
334
- const winnerAssistantId = getAssistantNodeId(winnerResp);
335
- const idx = canonicalUser.childrenIds.indexOf(winnerAssistantId);
336
- if (idx === -1) return;
337
- canonicalUser.comparisonWinnerId = winnerAssistantId;
338
- canonicalUser.activeChildIndex = idx;
339
- }
340
- function foldArenaGroup(nodes, group, winnerRespId, userNodeFor, root) {
335
+ function foldArenaGroup(nodes, group, userNodeFor, root) {
341
336
  const first = group[0];
342
337
  if (!first) return root;
343
338
  const canonicalUser = userNodeFor(first.id);
@@ -345,11 +340,7 @@ function foldArenaGroup(nodes, group, winnerRespId, userNodeFor, root) {
345
340
  const sharedParentId = canonicalUser.parentId;
346
341
  const forkMeta = parseArenaMeta(first);
347
342
  if (forkMeta) {
348
- canonicalUser.metadata.arena = {
349
- matchupId: forkMeta.matchupId,
350
- slotSeed: forkMeta.slotSeed,
351
- variant: forkMeta.variant
352
- };
343
+ canonicalUser.metadata.arena = { matchupId: forkMeta.matchupId };
353
344
  }
354
345
  let newRoot = root;
355
346
  for (const [i, resp] of group.entries()) {
@@ -372,7 +363,6 @@ function foldArenaGroup(nodes, group, winnerRespId, userNodeFor, root) {
372
363
  canonicalUser.childrenIds.sort((x, y) => compareLaneSlots(nodes, x, y));
373
364
  canonicalUser.comparing = true;
374
365
  newRoot = activateForkNode(nodes, canonicalUser, sharedParentId, newRoot);
375
- applyArenaWinner(canonicalUser, group, winnerRespId);
376
366
  return newRoot;
377
367
  }
378
368
  export {