@copilotz/chat-adapter 0.9.43 → 0.9.44
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.js +101 -41
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1638,6 +1638,17 @@ var getStreamEventPayload = (event) => {
|
|
|
1638
1638
|
if (!isRecord2(event)) return event;
|
|
1639
1639
|
return "payload" in event ? event.payload : event;
|
|
1640
1640
|
};
|
|
1641
|
+
var getLlmAttemptId = (event) => {
|
|
1642
|
+
if (!isRecord2(event)) return null;
|
|
1643
|
+
const metadata = isRecord2(event.metadata) ? event.metadata : {};
|
|
1644
|
+
if (typeof metadata.llmAttemptId === "string" && metadata.llmAttemptId.trim().length > 0) {
|
|
1645
|
+
return metadata.llmAttemptId.trim();
|
|
1646
|
+
}
|
|
1647
|
+
if (event.subjectType === "llm_attempt" && typeof event.subjectId === "string" && event.subjectId.trim().length > 0) {
|
|
1648
|
+
return event.subjectId.trim();
|
|
1649
|
+
}
|
|
1650
|
+
return null;
|
|
1651
|
+
};
|
|
1641
1652
|
var isTerminalEmptyLlmResultEvent = (event) => {
|
|
1642
1653
|
if (!isRecord2(event) || event.type !== "LLM_RESULT") return false;
|
|
1643
1654
|
const payload = getStreamEventPayload(event);
|
|
@@ -1661,40 +1672,9 @@ var isSameThreadIdentity = (owner, current) => {
|
|
|
1661
1672
|
return ownerValues.some((value) => currentValues.has(value));
|
|
1662
1673
|
};
|
|
1663
1674
|
|
|
1664
|
-
// src/
|
|
1665
|
-
var
|
|
1666
|
-
var
|
|
1667
|
-
var isAbortError = (error) => error instanceof DOMException && error.name === "AbortError" || typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
1668
|
-
var getEventPayload = (event) => getStreamEventPayload(event);
|
|
1669
|
-
var getEventSenderType = (payload) => payload?.senderType || payload?.sender?.type;
|
|
1670
|
-
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1671
|
-
var normalizeThreadTag = (value) => {
|
|
1672
|
-
if (!isRecord3(value)) return null;
|
|
1673
|
-
const id = typeof value.id === "string" ? value.id.trim() : "";
|
|
1674
|
-
const name = typeof value.name === "string" ? value.name.trim() : "";
|
|
1675
|
-
const color = typeof value.color === "string" && value.color.trim() ? value.color.trim() : void 0;
|
|
1676
|
-
if (!id || !name) return null;
|
|
1677
|
-
return color ? { id, name, color } : { id, name };
|
|
1678
|
-
};
|
|
1679
|
-
var getThreadTagsFromMetadata = (metadata) => {
|
|
1680
|
-
if (!isRecord3(metadata) || !isRecord3(metadata.public)) return [];
|
|
1681
|
-
const tags = metadata.public.tags;
|
|
1682
|
-
if (!Array.isArray(tags)) return [];
|
|
1683
|
-
return tags.map(normalizeThreadTag).filter((tag) => !!tag);
|
|
1684
|
-
};
|
|
1685
|
-
var patchMetadataPublicTags = (metadata, tags) => ({
|
|
1686
|
-
...metadata ?? {},
|
|
1687
|
-
public: {
|
|
1688
|
-
...isRecord3(metadata?.public) ? metadata.public : {},
|
|
1689
|
-
tags
|
|
1690
|
-
}
|
|
1691
|
-
});
|
|
1692
|
-
var THREAD_MESSAGES_PAGE_SIZE = 50;
|
|
1693
|
-
var createEmptyMessagePageInfo = () => ({
|
|
1694
|
-
hasMoreBefore: false,
|
|
1695
|
-
oldestMessageId: null,
|
|
1696
|
-
newestMessageId: null
|
|
1697
|
-
});
|
|
1675
|
+
// src/messageReconciliation.ts
|
|
1676
|
+
var CLIENT_MESSAGE_ID_METADATA_KEY = "clientMessageId";
|
|
1677
|
+
var LLM_ATTEMPT_ID_METADATA_KEY = "llmAttemptId";
|
|
1698
1678
|
var stringifyForCompare = (value) => {
|
|
1699
1679
|
if (value === void 0) return "";
|
|
1700
1680
|
try {
|
|
@@ -1719,6 +1699,36 @@ var getMessageSignature = (message) => JSON.stringify({
|
|
|
1719
1699
|
agentId: message.sender.agentId
|
|
1720
1700
|
} : null
|
|
1721
1701
|
});
|
|
1702
|
+
var getMetadataString = (message, key) => {
|
|
1703
|
+
const value = message.metadata?.[key];
|
|
1704
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
1705
|
+
};
|
|
1706
|
+
var getCorrelationKeys = (message) => {
|
|
1707
|
+
const clientMessageId = getMetadataString(
|
|
1708
|
+
message,
|
|
1709
|
+
CLIENT_MESSAGE_ID_METADATA_KEY
|
|
1710
|
+
);
|
|
1711
|
+
const llmAttemptId = getMetadataString(
|
|
1712
|
+
message,
|
|
1713
|
+
LLM_ATTEMPT_ID_METADATA_KEY
|
|
1714
|
+
);
|
|
1715
|
+
return [
|
|
1716
|
+
...clientMessageId ? [`client-message:${message.role}:${clientMessageId}`] : [],
|
|
1717
|
+
...llmAttemptId ? [`llm-attempt:${message.role}:${llmAttemptId}`] : []
|
|
1718
|
+
];
|
|
1719
|
+
};
|
|
1720
|
+
var indexUniqueFreshCorrelations = (freshMessages) => {
|
|
1721
|
+
const messagesByCorrelation = /* @__PURE__ */ new Map();
|
|
1722
|
+
for (const message of freshMessages) {
|
|
1723
|
+
for (const key of getCorrelationKeys(message)) {
|
|
1724
|
+
messagesByCorrelation.set(
|
|
1725
|
+
key,
|
|
1726
|
+
messagesByCorrelation.has(key) ? null : message
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return messagesByCorrelation;
|
|
1731
|
+
};
|
|
1722
1732
|
var reconcileThreadMessages = (currentMessages, freshMessages) => {
|
|
1723
1733
|
if (freshMessages.length === 0) {
|
|
1724
1734
|
return { messages: currentMessages, changed: false };
|
|
@@ -1727,12 +1737,15 @@ var reconcileThreadMessages = (currentMessages, freshMessages) => {
|
|
|
1727
1737
|
return { messages: freshMessages, changed: true };
|
|
1728
1738
|
}
|
|
1729
1739
|
const freshById = new Map(freshMessages.map((message) => [message.id, message]));
|
|
1740
|
+
const freshByCorrelation = indexUniqueFreshCorrelations(freshMessages);
|
|
1730
1741
|
const seen = /* @__PURE__ */ new Set();
|
|
1731
1742
|
let changed = false;
|
|
1732
1743
|
const nextMessages = currentMessages.map((message) => {
|
|
1733
|
-
const
|
|
1744
|
+
const exactMatch = freshById.get(message.id);
|
|
1745
|
+
const correlatedMatch = exactMatch ? null : getCorrelationKeys(message).map((key) => freshByCorrelation.get(key)).find((candidate) => candidate !== null && candidate !== void 0 && !seen.has(candidate.id));
|
|
1746
|
+
const fresh = exactMatch ?? correlatedMatch;
|
|
1734
1747
|
if (!fresh) return message;
|
|
1735
|
-
seen.add(
|
|
1748
|
+
seen.add(fresh.id);
|
|
1736
1749
|
if (getMessageSignature(message) === getMessageSignature(fresh)) {
|
|
1737
1750
|
return message;
|
|
1738
1751
|
}
|
|
@@ -1750,6 +1763,41 @@ var reconcileThreadMessages = (currentMessages, freshMessages) => {
|
|
|
1750
1763
|
}
|
|
1751
1764
|
return changed ? { messages: nextMessages, changed } : { messages: currentMessages, changed: false };
|
|
1752
1765
|
};
|
|
1766
|
+
|
|
1767
|
+
// src/useCopilotzChat.ts
|
|
1768
|
+
var nowTs = () => Date.now();
|
|
1769
|
+
var generateId = () => globalThis.crypto?.randomUUID?.() ?? `id-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
1770
|
+
var isAbortError = (error) => error instanceof DOMException && error.name === "AbortError" || typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
1771
|
+
var getEventPayload = (event) => getStreamEventPayload(event);
|
|
1772
|
+
var getEventSenderType = (payload) => payload?.senderType || payload?.sender?.type;
|
|
1773
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1774
|
+
var normalizeThreadTag = (value) => {
|
|
1775
|
+
if (!isRecord3(value)) return null;
|
|
1776
|
+
const id = typeof value.id === "string" ? value.id.trim() : "";
|
|
1777
|
+
const name = typeof value.name === "string" ? value.name.trim() : "";
|
|
1778
|
+
const color = typeof value.color === "string" && value.color.trim() ? value.color.trim() : void 0;
|
|
1779
|
+
if (!id || !name) return null;
|
|
1780
|
+
return color ? { id, name, color } : { id, name };
|
|
1781
|
+
};
|
|
1782
|
+
var getThreadTagsFromMetadata = (metadata) => {
|
|
1783
|
+
if (!isRecord3(metadata) || !isRecord3(metadata.public)) return [];
|
|
1784
|
+
const tags = metadata.public.tags;
|
|
1785
|
+
if (!Array.isArray(tags)) return [];
|
|
1786
|
+
return tags.map(normalizeThreadTag).filter((tag) => !!tag);
|
|
1787
|
+
};
|
|
1788
|
+
var patchMetadataPublicTags = (metadata, tags) => ({
|
|
1789
|
+
...metadata ?? {},
|
|
1790
|
+
public: {
|
|
1791
|
+
...isRecord3(metadata?.public) ? metadata.public : {},
|
|
1792
|
+
tags
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
var THREAD_MESSAGES_PAGE_SIZE = 50;
|
|
1796
|
+
var createEmptyMessagePageInfo = () => ({
|
|
1797
|
+
hasMoreBefore: false,
|
|
1798
|
+
oldestMessageId: null,
|
|
1799
|
+
newestMessageId: null
|
|
1800
|
+
});
|
|
1753
1801
|
var createPendingAssistantActivity = () => ({
|
|
1754
1802
|
items: [
|
|
1755
1803
|
{
|
|
@@ -2453,7 +2501,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2453
2501
|
liveToolUpdatesRef.current.push(update);
|
|
2454
2502
|
}
|
|
2455
2503
|
};
|
|
2456
|
-
const finalizeActiveAssistantTurn = (finalAnswer) => {
|
|
2504
|
+
const finalizeActiveAssistantTurn = (finalAnswer, llmAttemptId) => {
|
|
2457
2505
|
if (!streamStillOwnsVisibleThread()) return;
|
|
2458
2506
|
setMessages((prev) => {
|
|
2459
2507
|
const currentIdx = prev.findIndex((message2) => message2.id === currentAssistantId && message2.role === "assistant");
|
|
@@ -2467,8 +2515,15 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2467
2515
|
})();
|
|
2468
2516
|
if (fallbackIdx < 0) return prev;
|
|
2469
2517
|
const message = prev[fallbackIdx];
|
|
2470
|
-
const
|
|
2471
|
-
|
|
2518
|
+
const correlatedMessage = llmAttemptId ? {
|
|
2519
|
+
...message,
|
|
2520
|
+
metadata: {
|
|
2521
|
+
...message.metadata ?? {},
|
|
2522
|
+
[LLM_ATTEMPT_ID_METADATA_KEY]: llmAttemptId
|
|
2523
|
+
}
|
|
2524
|
+
} : message;
|
|
2525
|
+
const nextMessage = finalizeAssistantMessage(correlatedMessage, finalAnswer);
|
|
2526
|
+
if (message.content === nextMessage.content && message.isStreaming === nextMessage.isStreaming && message.isComplete === nextMessage.isComplete && message.activity === nextMessage.activity && message.metadata === nextMessage.metadata) {
|
|
2472
2527
|
return prev;
|
|
2473
2528
|
}
|
|
2474
2529
|
const updated = [...prev];
|
|
@@ -2577,7 +2632,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2577
2632
|
}
|
|
2578
2633
|
if (type === "LLM_RESULT") {
|
|
2579
2634
|
const finalAnswer = typeof payload?.answer === "string" ? payload.answer : void 0;
|
|
2580
|
-
finalizeActiveAssistantTurn(finalAnswer);
|
|
2635
|
+
finalizeActiveAssistantTurn(finalAnswer, getLlmAttemptId(event));
|
|
2581
2636
|
if (isTerminalEmptyLlmResultEvent(event)) {
|
|
2582
2637
|
finalizeStreamingPlaceholders();
|
|
2583
2638
|
}
|
|
@@ -2762,13 +2817,17 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2762
2817
|
);
|
|
2763
2818
|
const currentMetadata = threadMetadataMapRef.current[conversationKey];
|
|
2764
2819
|
const pendingTitle = currentMetadata?.pendingTitle;
|
|
2820
|
+
const userMessageId = generateId();
|
|
2765
2821
|
const userMessage = {
|
|
2766
|
-
id:
|
|
2822
|
+
id: userMessageId,
|
|
2767
2823
|
role: "user",
|
|
2768
2824
|
content,
|
|
2769
2825
|
timestamp,
|
|
2770
2826
|
attachments: attachments.length > 0 ? attachments : void 0,
|
|
2771
2827
|
isComplete: true,
|
|
2828
|
+
metadata: {
|
|
2829
|
+
[CLIENT_MESSAGE_ID_METADATA_KEY]: userMessageId
|
|
2830
|
+
},
|
|
2772
2831
|
sender: resolveUserSender({
|
|
2773
2832
|
id: userId,
|
|
2774
2833
|
name: getCurrentUserDisplayName(userName, userId)
|
|
@@ -2817,6 +2876,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
|
|
|
2817
2876
|
userId,
|
|
2818
2877
|
userName: getCurrentUserDisplayName(userName, userId),
|
|
2819
2878
|
agentName: preferredAgentRef.current,
|
|
2879
|
+
metadata: userMessage.metadata,
|
|
2820
2880
|
assistantMessageId: assistantPlaceholder.id,
|
|
2821
2881
|
assistantSender,
|
|
2822
2882
|
preserveActiveRun,
|