@copilotz/chat-ui 0.9.44 → 0.9.46
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 +65 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +65 -84
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -867,6 +867,10 @@ var hasRenderableAssistantBody = (message) => {
|
|
|
867
867
|
if (Array.isArray(message.attachments) && message.attachments.length > 0) return true;
|
|
868
868
|
return Boolean(message.activity?.items.length);
|
|
869
869
|
};
|
|
870
|
+
var filterActivity = (message, placement) => {
|
|
871
|
+
const items = message.activity?.items.filter((item) => placement === "after-content" ? item.kind === "tool" : item.kind !== "tool") ?? [];
|
|
872
|
+
return items.length > 0 ? { items } : void 0;
|
|
873
|
+
};
|
|
870
874
|
var defaultMarkdownComponents = {
|
|
871
875
|
code: ({ node, className, children, ...props }) => {
|
|
872
876
|
const inline = props.inline;
|
|
@@ -1133,6 +1137,7 @@ var MediaRenderer = (0, import_react2.memo)(function MediaRenderer2({ attachment
|
|
|
1133
1137
|
});
|
|
1134
1138
|
var arePropsEqual = (prevProps, nextProps) => {
|
|
1135
1139
|
if (prevProps.message !== nextProps.message) return false;
|
|
1140
|
+
if (prevProps.fragments !== nextProps.fragments) return false;
|
|
1136
1141
|
if (prevProps.isUser !== nextProps.isUser) return false;
|
|
1137
1142
|
if (prevProps.userAvatar !== nextProps.userAvatar) return false;
|
|
1138
1143
|
if (prevProps.userName !== nextProps.userName) return false;
|
|
@@ -1162,6 +1167,7 @@ var arePropsEqual = (prevProps, nextProps) => {
|
|
|
1162
1167
|
};
|
|
1163
1168
|
var Message = (0, import_react2.memo)(({
|
|
1164
1169
|
message,
|
|
1170
|
+
fragments,
|
|
1165
1171
|
isUser,
|
|
1166
1172
|
userAvatar,
|
|
1167
1173
|
userName = "Voc\xEA",
|
|
@@ -1194,12 +1200,15 @@ var Message = (0, import_react2.memo)(({
|
|
|
1194
1200
|
const [showActions, setShowActions] = (0, import_react2.useState)(false);
|
|
1195
1201
|
const [actionsFocused, setActionsFocused] = (0, import_react2.useState)(false);
|
|
1196
1202
|
const [copied, setCopied] = (0, import_react2.useState)(false);
|
|
1203
|
+
const sourceMessages = fragments?.length ? fragments : [message];
|
|
1204
|
+
const headerMessage = sourceMessages[0];
|
|
1205
|
+
const groupContent = sourceMessages.map((sourceMessage) => sourceMessage.content.trim()).filter(Boolean).join("\n\n");
|
|
1197
1206
|
const messageIsUser = isUser ?? message.role === "user";
|
|
1198
|
-
if (!hasRenderableAssistantBody
|
|
1207
|
+
if (!sourceMessages.some(hasRenderableAssistantBody)) {
|
|
1199
1208
|
return null;
|
|
1200
1209
|
}
|
|
1201
1210
|
const senderDisplay = resolveMessageSenderDisplay({
|
|
1202
|
-
sender:
|
|
1211
|
+
sender: headerMessage.sender,
|
|
1203
1212
|
fallbackName: messageIsUser ? userName : assistantName,
|
|
1204
1213
|
fallbackAvatar: messageIsUser ? void 0 : assistantAvatar,
|
|
1205
1214
|
fallbackAvatarUrl: messageIsUser ? userAvatar : void 0,
|
|
@@ -1209,17 +1218,17 @@ var Message = (0, import_react2.memo)(({
|
|
|
1209
1218
|
const normalizedPreviewChars = Math.max(longMessagePreviewChars, 1);
|
|
1210
1219
|
const normalizedChunkChars = Math.max(longMessageChunkChars, 1);
|
|
1211
1220
|
const previewOverride = typeof message.metadata?.previewContent === "string" ? message.metadata.previewContent : void 0;
|
|
1212
|
-
const canCollapseMessage = collapseLongMessages && !
|
|
1221
|
+
const canCollapseMessage = collapseLongMessages && sourceMessages.length === 1 && !sourceMessages.some((sourceMessage) => sourceMessage.isStreaming) && groupContent.length > normalizedPreviewChars && (!collapseLongMessagesForUserOnly || messageIsUser);
|
|
1213
1222
|
const isCollapsed = canCollapseMessage && !isExpanded;
|
|
1214
|
-
const contentToRender = isCollapsed ? getCollapsedPreview(
|
|
1223
|
+
const contentToRender = isCollapsed ? getCollapsedPreview(groupContent, normalizedPreviewChars, previewOverride) : groupContent;
|
|
1215
1224
|
const shouldRenderMarkdown = !isCollapsed && (!messageIsUser || renderUserMarkdown);
|
|
1216
1225
|
const horizontalOffsetClass = showAvatar ? messageIsUser ? compactMode ? "mr-9" : "mr-11" : compactMode ? "ml-9" : "ml-11" : "";
|
|
1217
1226
|
const handleCopy = async () => {
|
|
1218
1227
|
try {
|
|
1219
|
-
await navigator.clipboard.writeText(
|
|
1228
|
+
await navigator.clipboard.writeText(groupContent);
|
|
1220
1229
|
setCopied(true);
|
|
1221
1230
|
setTimeout(() => setCopied(false), 2e3);
|
|
1222
|
-
onAction?.({ action: "copy", messageId: message.id, content:
|
|
1231
|
+
onAction?.({ action: "copy", messageId: message.id, content: groupContent });
|
|
1223
1232
|
} catch (error) {
|
|
1224
1233
|
console.error("Failed to copy message:", error);
|
|
1225
1234
|
}
|
|
@@ -1265,7 +1274,7 @@ var Message = (0, import_react2.memo)(({
|
|
|
1265
1274
|
showAvatar && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `flex-shrink-0 ${compactMode ? "mt-1" : "mt-0"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1266
1275
|
MessageSenderAvatar,
|
|
1267
1276
|
{
|
|
1268
|
-
sender:
|
|
1277
|
+
sender: headerMessage.sender,
|
|
1269
1278
|
fallbackName: messageIsUser ? userName : assistantName,
|
|
1270
1279
|
fallbackAvatar: messageIsUser ? void 0 : assistantAvatar,
|
|
1271
1280
|
fallbackAvatarUrl: messageIsUser ? userAvatar : void 0,
|
|
@@ -1281,8 +1290,8 @@ var Message = (0, import_react2.memo)(({
|
|
|
1281
1290
|
children: senderDisplay.name
|
|
1282
1291
|
}
|
|
1283
1292
|
),
|
|
1284
|
-
showTimestamp && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(
|
|
1285
|
-
|
|
1293
|
+
showTimestamp && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(headerMessage.timestamp) }),
|
|
1294
|
+
sourceMessages.some((sourceMessage) => sourceMessage.isEdited) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Badge, { variant: "outline", className: "text-xs", children: "editado" })
|
|
1286
1295
|
] })
|
|
1287
1296
|
] }),
|
|
1288
1297
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"} ${horizontalOffsetClass}`, children: [
|
|
@@ -1327,25 +1336,42 @@ var Message = (0, import_react2.memo)(({
|
|
|
1327
1336
|
)
|
|
1328
1337
|
] })
|
|
1329
1338
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1339
|
+
sourceMessages.map((sourceMessage) => {
|
|
1340
|
+
const beforeContentActivity = filterActivity(sourceMessage, "before-content");
|
|
1341
|
+
const afterContentActivity = filterActivity(sourceMessage, "after-content");
|
|
1342
|
+
const fragmentContent = sourceMessages.length === 1 ? contentToRender : sourceMessage.content;
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react2.default.Fragment, { children: [
|
|
1344
|
+
!messageIsUser && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1345
|
+
AssistantActivity,
|
|
1346
|
+
{
|
|
1347
|
+
activity: beforeContentActivity,
|
|
1348
|
+
showActivity,
|
|
1349
|
+
showActivityDetails,
|
|
1350
|
+
labels
|
|
1351
|
+
}
|
|
1352
|
+
),
|
|
1353
|
+
fragmentContent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1354
|
+
StreamingText,
|
|
1355
|
+
{
|
|
1356
|
+
content: fragmentContent,
|
|
1357
|
+
isStreaming: sourceMessage.isStreaming,
|
|
1358
|
+
renderMarkdown: shouldRenderMarkdown,
|
|
1359
|
+
markdown,
|
|
1360
|
+
plainTextChunkChars: normalizedChunkChars
|
|
1361
|
+
}
|
|
1362
|
+
),
|
|
1363
|
+
!messageIsUser && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1364
|
+
AssistantActivity,
|
|
1365
|
+
{
|
|
1366
|
+
activity: afterContentActivity,
|
|
1367
|
+
showActivity,
|
|
1368
|
+
showActivityDetails,
|
|
1369
|
+
labels
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
sourceMessage.attachments && sourceMessage.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-3 space-y-2", children: sourceMessage.attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MediaRenderer, { attachment }, `${sourceMessage.id}:${index}`)) })
|
|
1373
|
+
] }, sourceMessage.id);
|
|
1374
|
+
}),
|
|
1349
1375
|
canCollapseMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1350
1376
|
Button,
|
|
1351
1377
|
{
|
|
@@ -1357,8 +1383,7 @@ var Message = (0, import_react2.memo)(({
|
|
|
1357
1383
|
onClick: handleToggleExpanded,
|
|
1358
1384
|
children: isCollapsed ? showMoreLabel : showLessLabel
|
|
1359
1385
|
}
|
|
1360
|
-
) })
|
|
1361
|
-
message.attachments && message.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "mt-3 space-y-2", children: message.attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MediaRenderer, { attachment }, index)) })
|
|
1386
|
+
) })
|
|
1362
1387
|
] }) }),
|
|
1363
1388
|
!isEditing && (enableCopy || canEdit) && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1364
1389
|
"div",
|
|
@@ -5925,72 +5950,27 @@ var getMessageSpeakerKey = (message) => {
|
|
|
5925
5950
|
}
|
|
5926
5951
|
return message.role;
|
|
5927
5952
|
};
|
|
5928
|
-
var getAssistantSpeakerTokens = (message) => {
|
|
5929
|
-
if (!message || message.role !== "assistant") return [];
|
|
5930
|
-
if (message.sender) {
|
|
5931
|
-
return Array.from(new Set([
|
|
5932
|
-
`${message.sender.type}:${message.sender.id}`,
|
|
5933
|
-
message.sender.agentId ? `agent:${message.sender.agentId}` : "",
|
|
5934
|
-
message.sender.externalId ? `external:${message.sender.externalId}` : ""
|
|
5935
|
-
].filter(Boolean).map((value) => value.toLowerCase())));
|
|
5936
|
-
}
|
|
5937
|
-
return ["assistant"];
|
|
5938
|
-
};
|
|
5939
|
-
var hasAssistantContent = (message) => message.role === "assistant" && (message.content.trim().length > 0 || Boolean(message.attachments?.length));
|
|
5940
|
-
var hasActivity = (message) => Boolean(message.activity?.items.length);
|
|
5941
5953
|
var canGroupMessages = (previous, next) => {
|
|
5942
5954
|
if (previous.role !== next.role) {
|
|
5943
5955
|
return false;
|
|
5944
5956
|
}
|
|
5945
5957
|
if (previous.role !== "assistant") {
|
|
5946
|
-
return
|
|
5947
|
-
}
|
|
5948
|
-
const previousTokens = getAssistantSpeakerTokens(previous);
|
|
5949
|
-
const nextTokens = getAssistantSpeakerTokens(next);
|
|
5950
|
-
if (!previousTokens.some((token) => nextTokens.includes(token))) return false;
|
|
5951
|
-
return !(hasAssistantContent(previous) && hasActivity(next));
|
|
5952
|
-
};
|
|
5953
|
-
var mergeGroupActivity = (messages) => {
|
|
5954
|
-
const merged = /* @__PURE__ */ new Map();
|
|
5955
|
-
for (const activity of messages.map((message) => message.activity).filter((activity2) => Boolean(activity2))) {
|
|
5956
|
-
for (const item of activity.items) merged.set(item.id, item);
|
|
5957
|
-
}
|
|
5958
|
-
return merged.size > 0 ? { items: Array.from(merged.values()) } : void 0;
|
|
5959
|
-
};
|
|
5960
|
-
var mergeMessageGroup = (messages) => {
|
|
5961
|
-
if (messages.length === 1) {
|
|
5962
|
-
return messages[0];
|
|
5958
|
+
return false;
|
|
5963
5959
|
}
|
|
5964
|
-
|
|
5965
|
-
const lastMessage = messages[messages.length - 1];
|
|
5966
|
-
const content = messages.map((message) => message.content.trim()).filter((value) => value.length > 0).join("\n\n");
|
|
5967
|
-
const attachments = messages.flatMap((message) => message.attachments ?? []);
|
|
5968
|
-
return {
|
|
5969
|
-
...lastMessage,
|
|
5970
|
-
id: lastMessage.id,
|
|
5971
|
-
content,
|
|
5972
|
-
timestamp: firstMessage.timestamp,
|
|
5973
|
-
attachments: attachments.length > 0 ? attachments : void 0,
|
|
5974
|
-
isStreaming: lastMessage.isStreaming,
|
|
5975
|
-
isComplete: lastMessage.isComplete,
|
|
5976
|
-
isEdited: messages.some((message) => message.isEdited),
|
|
5977
|
-
originalContent: void 0,
|
|
5978
|
-
editedAt: lastMessage.editedAt,
|
|
5979
|
-
activity: mergeGroupActivity(messages),
|
|
5980
|
-
sender: lastMessage.sender ?? firstMessage.sender,
|
|
5981
|
-
metadata: lastMessage.metadata
|
|
5982
|
-
};
|
|
5960
|
+
return getMessageSpeakerKey(previous) === getMessageSpeakerKey(next);
|
|
5983
5961
|
};
|
|
5984
5962
|
var groupMessagesForRender = (messages) => {
|
|
5985
5963
|
if (messages.length === 0) return [];
|
|
5986
5964
|
const groups = [];
|
|
5987
5965
|
let currentGroup = [messages[0]];
|
|
5988
5966
|
const flushGroup = () => {
|
|
5989
|
-
const
|
|
5967
|
+
const firstMessage = currentGroup[0];
|
|
5968
|
+
const lastMessage = currentGroup[currentGroup.length - 1];
|
|
5990
5969
|
groups.push({
|
|
5991
|
-
id:
|
|
5992
|
-
|
|
5993
|
-
|
|
5970
|
+
id: firstMessage.id,
|
|
5971
|
+
messages: currentGroup,
|
|
5972
|
+
primaryMessage: lastMessage,
|
|
5973
|
+
suggestionMessageId: lastMessage.id
|
|
5994
5974
|
});
|
|
5995
5975
|
};
|
|
5996
5976
|
for (let index = 1; index < messages.length; index++) {
|
|
@@ -6634,7 +6614,7 @@ var ChatUI = ({
|
|
|
6634
6614
|
},
|
|
6635
6615
|
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
6636
6616
|
const group = groupedMessages[virtualRow.index];
|
|
6637
|
-
const message = group.
|
|
6617
|
+
const message = group.primaryMessage;
|
|
6638
6618
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6639
6619
|
"div",
|
|
6640
6620
|
{
|
|
@@ -6656,6 +6636,7 @@ var ChatUI = ({
|
|
|
6656
6636
|
Message,
|
|
6657
6637
|
{
|
|
6658
6638
|
message,
|
|
6639
|
+
fragments: group.messages,
|
|
6659
6640
|
...messageProps,
|
|
6660
6641
|
isExpanded: Boolean(
|
|
6661
6642
|
expandedMessageIds[message.id]
|