@copilotz/chat-ui 0.5.0 → 0.6.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/index.cjs +99 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +99 -27
- package/dist/index.js.map +1 -1
- package/dist/styles.css +0 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -845,7 +845,6 @@ var arePropsEqual = (prevProps, nextProps) => {
|
|
|
845
845
|
if (prevProps.markdown !== nextProps.markdown) return false;
|
|
846
846
|
if (prevProps.isExpanded !== nextProps.isExpanded) return false;
|
|
847
847
|
if (prevProps.onToggleExpanded !== nextProps.onToggleExpanded) return false;
|
|
848
|
-
if (prevProps.isGrouped !== nextProps.isGrouped) return false;
|
|
849
848
|
if (prevProps.assistantAvatar !== nextProps.assistantAvatar) return false;
|
|
850
849
|
return true;
|
|
851
850
|
};
|
|
@@ -876,7 +875,6 @@ var Message = memo2(({
|
|
|
876
875
|
markdown,
|
|
877
876
|
isExpanded = false,
|
|
878
877
|
onToggleExpanded,
|
|
879
|
-
isGrouped = false,
|
|
880
878
|
agentOptions = []
|
|
881
879
|
}) => {
|
|
882
880
|
const [isEditing, setIsEditing] = useState2(false);
|
|
@@ -949,7 +947,7 @@ var Message = memo2(({
|
|
|
949
947
|
onMouseEnter: () => setShowActions(true),
|
|
950
948
|
onMouseLeave: () => setShowActions(false),
|
|
951
949
|
children: [
|
|
952
|
-
|
|
950
|
+
/* @__PURE__ */ jsxs3("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
953
951
|
showAvatar && /* @__PURE__ */ jsx8("div", { className: `flex-shrink-0 ${compactMode ? "mt-1" : "mt-0"}`, children: /* @__PURE__ */ jsx8(Avatar, { className: compactMode ? "h-6 w-6" : "h-8 w-8", children: messageIsUser ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
954
952
|
/* @__PURE__ */ jsx8(AvatarImage, { src: userAvatar, alt: userName }),
|
|
955
953
|
/* @__PURE__ */ jsx8(AvatarFallback, { className: "bg-primary text-primary-foreground", children: userName.charAt(0).toUpperCase() })
|
|
@@ -5029,6 +5027,81 @@ function getMessageSpeakerKey(message) {
|
|
|
5029
5027
|
}
|
|
5030
5028
|
return message.role;
|
|
5031
5029
|
}
|
|
5030
|
+
var mergeToolCalls = (activities) => {
|
|
5031
|
+
const merged = /* @__PURE__ */ new Map();
|
|
5032
|
+
for (const activity of activities) {
|
|
5033
|
+
if (!Array.isArray(activity.toolCalls)) continue;
|
|
5034
|
+
for (const toolCall of activity.toolCalls) {
|
|
5035
|
+
const key = toolCall.id || `${toolCall.name}:${JSON.stringify(toolCall.arguments ?? {})}`;
|
|
5036
|
+
merged.set(key, toolCall);
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
return merged.size > 0 ? Array.from(merged.values()) : void 0;
|
|
5040
|
+
};
|
|
5041
|
+
var mergeReasoning = (activities) => {
|
|
5042
|
+
const segments = activities.map((activity) => activity.reasoning?.trim()).filter((value) => Boolean(value));
|
|
5043
|
+
if (segments.length === 0) return void 0;
|
|
5044
|
+
return segments.filter((segment, index) => index === 0 || segment !== segments[index - 1]).join("\n\n");
|
|
5045
|
+
};
|
|
5046
|
+
var mergeGroupActivity = (messages) => {
|
|
5047
|
+
const activities = messages.map((message) => message.activity).filter((activity) => Boolean(activity));
|
|
5048
|
+
if (activities.length === 0) return void 0;
|
|
5049
|
+
const lastActivity = activities[activities.length - 1];
|
|
5050
|
+
const mergedReasoning = mergeReasoning(activities);
|
|
5051
|
+
const mergedToolCalls = mergeToolCalls(activities);
|
|
5052
|
+
return {
|
|
5053
|
+
...lastActivity,
|
|
5054
|
+
...mergedReasoning ? { reasoning: mergedReasoning } : {},
|
|
5055
|
+
...mergedToolCalls ? { toolCalls: mergedToolCalls } : {}
|
|
5056
|
+
};
|
|
5057
|
+
};
|
|
5058
|
+
var mergeMessageGroup = (messages) => {
|
|
5059
|
+
const firstMessage = messages[0];
|
|
5060
|
+
const lastMessage = messages[messages.length - 1];
|
|
5061
|
+
const content = messages.map((message) => message.content.trim()).filter((value) => value.length > 0).join("\n\n");
|
|
5062
|
+
const attachments = messages.flatMap((message) => message.attachments ?? []);
|
|
5063
|
+
return {
|
|
5064
|
+
...lastMessage,
|
|
5065
|
+
id: lastMessage.id,
|
|
5066
|
+
content,
|
|
5067
|
+
timestamp: firstMessage.timestamp,
|
|
5068
|
+
attachments: attachments.length > 0 ? attachments : void 0,
|
|
5069
|
+
isStreaming: lastMessage.isStreaming,
|
|
5070
|
+
isComplete: lastMessage.isComplete,
|
|
5071
|
+
isEdited: messages.some((message) => message.isEdited),
|
|
5072
|
+
originalContent: void 0,
|
|
5073
|
+
editedAt: lastMessage.editedAt,
|
|
5074
|
+
activity: mergeGroupActivity(messages),
|
|
5075
|
+
senderName: lastMessage.senderName ?? firstMessage.senderName,
|
|
5076
|
+
senderAgentId: lastMessage.senderAgentId ?? firstMessage.senderAgentId,
|
|
5077
|
+
metadata: lastMessage.metadata
|
|
5078
|
+
};
|
|
5079
|
+
};
|
|
5080
|
+
var groupMessagesForRender = (messages) => {
|
|
5081
|
+
if (messages.length === 0) return [];
|
|
5082
|
+
const groups = [];
|
|
5083
|
+
let currentGroup = [messages[0]];
|
|
5084
|
+
const flushGroup = () => {
|
|
5085
|
+
const mergedMessage = mergeMessageGroup(currentGroup);
|
|
5086
|
+
groups.push({
|
|
5087
|
+
id: mergedMessage.id,
|
|
5088
|
+
message: mergedMessage,
|
|
5089
|
+
suggestionMessageId: currentGroup[currentGroup.length - 1].id
|
|
5090
|
+
});
|
|
5091
|
+
};
|
|
5092
|
+
for (let index = 1; index < messages.length; index++) {
|
|
5093
|
+
const previous = currentGroup[currentGroup.length - 1];
|
|
5094
|
+
const next = messages[index];
|
|
5095
|
+
if (previous.role === next.role && getMessageSpeakerKey(previous) === getMessageSpeakerKey(next)) {
|
|
5096
|
+
currentGroup.push(next);
|
|
5097
|
+
continue;
|
|
5098
|
+
}
|
|
5099
|
+
flushGroup();
|
|
5100
|
+
currentGroup = [next];
|
|
5101
|
+
}
|
|
5102
|
+
flushGroup();
|
|
5103
|
+
return groups;
|
|
5104
|
+
};
|
|
5032
5105
|
var ChatUI = ({
|
|
5033
5106
|
messages = [],
|
|
5034
5107
|
threads = [],
|
|
@@ -5122,8 +5195,9 @@ var ChatUI = ({
|
|
|
5122
5195
|
}, [attachments]);
|
|
5123
5196
|
const [isCustomMounted, setIsCustomMounted] = useState9(false);
|
|
5124
5197
|
const [isCustomVisible, setIsCustomVisible] = useState9(false);
|
|
5198
|
+
const groupedMessages = useMemo6(() => groupMessagesForRender(messages), [messages]);
|
|
5125
5199
|
const virtualizer = useVirtualizer({
|
|
5126
|
-
count:
|
|
5200
|
+
count: groupedMessages.length,
|
|
5127
5201
|
getScrollElement: () => scrollAreaRef.current,
|
|
5128
5202
|
estimateSize: () => 100,
|
|
5129
5203
|
overscan: 5
|
|
@@ -5161,20 +5235,20 @@ var ChatUI = ({
|
|
|
5161
5235
|
}, [state.showSidebar, isMobile, config.customComponent]);
|
|
5162
5236
|
const prevMessageCountRef = useRef6(0);
|
|
5163
5237
|
useEffect11(() => {
|
|
5164
|
-
if (
|
|
5238
|
+
if (groupedMessages.length === 0) {
|
|
5165
5239
|
prevMessageCountRef.current = 0;
|
|
5166
5240
|
return;
|
|
5167
5241
|
}
|
|
5168
5242
|
if (prependSnapshotRef.current) {
|
|
5169
|
-
prevMessageCountRef.current =
|
|
5243
|
+
prevMessageCountRef.current = groupedMessages.length;
|
|
5170
5244
|
return;
|
|
5171
5245
|
}
|
|
5172
5246
|
const wasEmpty = prevMessageCountRef.current === 0;
|
|
5173
|
-
prevMessageCountRef.current =
|
|
5247
|
+
prevMessageCountRef.current = groupedMessages.length;
|
|
5174
5248
|
if (wasEmpty) {
|
|
5175
5249
|
requestAnimationFrame(() => {
|
|
5176
5250
|
requestAnimationFrame(() => {
|
|
5177
|
-
virtualizer.scrollToIndex(
|
|
5251
|
+
virtualizer.scrollToIndex(groupedMessages.length - 1, { align: "end" });
|
|
5178
5252
|
});
|
|
5179
5253
|
});
|
|
5180
5254
|
return;
|
|
@@ -5189,7 +5263,7 @@ var ChatUI = ({
|
|
|
5189
5263
|
viewport.scrollTop = viewport.scrollHeight;
|
|
5190
5264
|
}
|
|
5191
5265
|
});
|
|
5192
|
-
}, [
|
|
5266
|
+
}, [groupedMessages, state.isAtBottom, virtualizer]);
|
|
5193
5267
|
useEffect11(() => {
|
|
5194
5268
|
virtualizer.measure();
|
|
5195
5269
|
}, [expandedMessageIds, virtualizer]);
|
|
@@ -5199,13 +5273,13 @@ var ChatUI = ({
|
|
|
5199
5273
|
useEffect11(() => {
|
|
5200
5274
|
const snapshot = prependSnapshotRef.current;
|
|
5201
5275
|
if (!snapshot) return;
|
|
5202
|
-
if (
|
|
5276
|
+
if (groupedMessages.length <= snapshot.messageCount) {
|
|
5203
5277
|
if (!isLoadingOlderMessages) {
|
|
5204
5278
|
prependSnapshotRef.current = null;
|
|
5205
5279
|
}
|
|
5206
5280
|
return;
|
|
5207
5281
|
}
|
|
5208
|
-
if ((
|
|
5282
|
+
if ((groupedMessages[0]?.id ?? null) === snapshot.firstMessageId) {
|
|
5209
5283
|
if (!isLoadingOlderMessages) {
|
|
5210
5284
|
prependSnapshotRef.current = null;
|
|
5211
5285
|
}
|
|
@@ -5221,20 +5295,20 @@ var ChatUI = ({
|
|
|
5221
5295
|
prependSnapshotRef.current = null;
|
|
5222
5296
|
});
|
|
5223
5297
|
});
|
|
5224
|
-
}, [
|
|
5298
|
+
}, [groupedMessages, isLoadingOlderMessages, virtualizer]);
|
|
5225
5299
|
const requestOlderMessages = useCallback4(() => {
|
|
5226
5300
|
if (!onLoadOlderMessages || !hasMoreMessagesBefore || isLoadingOlderMessages) return;
|
|
5227
5301
|
const viewport = scrollAreaRef.current;
|
|
5228
5302
|
prependSnapshotRef.current = viewport ? {
|
|
5229
5303
|
scrollHeight: viewport.scrollHeight,
|
|
5230
5304
|
scrollTop: viewport.scrollTop,
|
|
5231
|
-
firstMessageId:
|
|
5232
|
-
messageCount:
|
|
5305
|
+
firstMessageId: groupedMessages[0]?.id ?? null,
|
|
5306
|
+
messageCount: groupedMessages.length
|
|
5233
5307
|
} : null;
|
|
5234
5308
|
onLoadOlderMessages();
|
|
5235
|
-
}, [hasMoreMessagesBefore, isLoadingOlderMessages,
|
|
5309
|
+
}, [groupedMessages, hasMoreMessagesBefore, isLoadingOlderMessages, onLoadOlderMessages]);
|
|
5236
5310
|
useEffect11(() => {
|
|
5237
|
-
const validMessageIds = new Set(
|
|
5311
|
+
const validMessageIds = new Set(groupedMessages.map((group) => group.id));
|
|
5238
5312
|
setExpandedMessageIds((prev) => {
|
|
5239
5313
|
const activeIds = Object.keys(prev);
|
|
5240
5314
|
const staleIds = activeIds.filter((messageId) => !validMessageIds.has(messageId));
|
|
@@ -5247,7 +5321,7 @@ var ChatUI = ({
|
|
|
5247
5321
|
});
|
|
5248
5322
|
return next;
|
|
5249
5323
|
});
|
|
5250
|
-
}, [
|
|
5324
|
+
}, [groupedMessages]);
|
|
5251
5325
|
const handleScroll = useCallback4((e) => {
|
|
5252
5326
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
|
5253
5327
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
@@ -5349,7 +5423,7 @@ var ChatUI = ({
|
|
|
5349
5423
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
5350
5424
|
const SuggestionIconComponents = [MessageSquare, Lightbulb2, Zap, HelpCircle];
|
|
5351
5425
|
const renderSuggestions = () => {
|
|
5352
|
-
if (
|
|
5426
|
+
if (groupedMessages.length > 0 || !suggestions.length) return null;
|
|
5353
5427
|
return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
5354
5428
|
/* @__PURE__ */ jsxs17("div", { className: "text-center mb-8", children: [
|
|
5355
5429
|
/* @__PURE__ */ jsx27("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ jsx27(Sparkles2, { className: "w-7 h-7 text-primary" }) }),
|
|
@@ -5514,7 +5588,7 @@ var ChatUI = ({
|
|
|
5514
5588
|
onScrollCapture: handleScroll,
|
|
5515
5589
|
style: { contain: "strict" },
|
|
5516
5590
|
children: /* @__PURE__ */ jsxs17("div", { className: "max-w-4xl mx-auto pb-4", children: [
|
|
5517
|
-
|
|
5591
|
+
groupedMessages.length > 0 && /* @__PURE__ */ jsx27("div", { className: "flex justify-center py-2", children: isLoadingOlderMessages ? /* @__PURE__ */ jsx27("span", { className: "text-xs text-muted-foreground", children: config.labels.loadingOlderMessages }) : hasMoreMessagesBefore ? /* @__PURE__ */ jsx27(
|
|
5518
5592
|
"button",
|
|
5519
5593
|
{
|
|
5520
5594
|
type: "button",
|
|
@@ -5523,7 +5597,7 @@ var ChatUI = ({
|
|
|
5523
5597
|
children: config.labels.loadOlderMessages
|
|
5524
5598
|
}
|
|
5525
5599
|
) : null }),
|
|
5526
|
-
isMessagesLoading ? renderMessageLoadingSkeleton() :
|
|
5600
|
+
isMessagesLoading ? renderMessageLoadingSkeleton() : groupedMessages.length === 0 ? renderSuggestions() : /* @__PURE__ */ jsx27(
|
|
5527
5601
|
"div",
|
|
5528
5602
|
{
|
|
5529
5603
|
style: {
|
|
@@ -5532,9 +5606,8 @@ var ChatUI = ({
|
|
|
5532
5606
|
position: "relative"
|
|
5533
5607
|
},
|
|
5534
5608
|
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
5535
|
-
const
|
|
5536
|
-
const
|
|
5537
|
-
const isGrouped = prevMessage !== null && prevMessage.role === message.role && getMessageSpeakerKey(prevMessage) === getMessageSpeakerKey(message);
|
|
5609
|
+
const group = groupedMessages[virtualRow.index];
|
|
5610
|
+
const message = group.message;
|
|
5538
5611
|
return /* @__PURE__ */ jsx27(
|
|
5539
5612
|
"div",
|
|
5540
5613
|
{
|
|
@@ -5547,20 +5620,19 @@ var ChatUI = ({
|
|
|
5547
5620
|
width: "100%",
|
|
5548
5621
|
transform: `translateY(${virtualRow.start}px)`
|
|
5549
5622
|
},
|
|
5550
|
-
children: /* @__PURE__ */ jsxs17("div", { className: virtualRow.index === 0 ? "" :
|
|
5623
|
+
children: /* @__PURE__ */ jsxs17("div", { className: virtualRow.index === 0 ? "" : "pt-4", children: [
|
|
5551
5624
|
/* @__PURE__ */ jsx27(
|
|
5552
5625
|
Message,
|
|
5553
5626
|
{
|
|
5554
5627
|
message,
|
|
5555
5628
|
...messageProps,
|
|
5556
|
-
isGrouped,
|
|
5557
5629
|
isExpanded: Boolean(expandedMessageIds[message.id])
|
|
5558
5630
|
}
|
|
5559
5631
|
),
|
|
5560
|
-
message.role === "assistant" && renderInlineSuggestions(
|
|
5632
|
+
message.role === "assistant" && renderInlineSuggestions(group.suggestionMessageId)
|
|
5561
5633
|
] })
|
|
5562
5634
|
},
|
|
5563
|
-
|
|
5635
|
+
group.id
|
|
5564
5636
|
);
|
|
5565
5637
|
})
|
|
5566
5638
|
}
|