@copilotz/chat-adapter 0.8.4 → 0.9.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.d.ts +4 -3
- package/dist/index.js +770 -797
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1039,11 +1039,13 @@ var resolveHydratedMessageSender = (message, options = {}) => {
|
|
|
1039
1039
|
});
|
|
1040
1040
|
}
|
|
1041
1041
|
if (type === "user") {
|
|
1042
|
+
const isCurrentUser = options.user?.id === externalId || options.user?.id === participantId || options.user?.id === storedId;
|
|
1043
|
+
const currentUserName = isCurrentUser ? clean(options.user?.name) : void 0;
|
|
1042
1044
|
return defined({
|
|
1043
1045
|
type: "user",
|
|
1044
1046
|
id: externalId,
|
|
1045
1047
|
externalId,
|
|
1046
|
-
name: displayName,
|
|
1048
|
+
name: currentUserName ?? displayName,
|
|
1047
1049
|
avatarUrl: clean(options.user?.avatarUrl),
|
|
1048
1050
|
participantId: participantId ?? storedId
|
|
1049
1051
|
});
|
|
@@ -1570,6 +1572,28 @@ var generateId = () => globalThis.crypto?.randomUUID?.() ?? `id-${Date.now()}-${
|
|
|
1570
1572
|
var isAbortError = (error) => error instanceof DOMException && error.name === "AbortError" || typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
1571
1573
|
var getEventPayload = (event) => event?.payload ?? event;
|
|
1572
1574
|
var getEventSenderType = (payload) => payload?.senderType || payload?.sender?.type;
|
|
1575
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1576
|
+
var normalizeThreadTag = (value) => {
|
|
1577
|
+
if (!isRecord2(value)) return null;
|
|
1578
|
+
const id = typeof value.id === "string" ? value.id.trim() : "";
|
|
1579
|
+
const name = typeof value.name === "string" ? value.name.trim() : "";
|
|
1580
|
+
const color = typeof value.color === "string" && value.color.trim() ? value.color.trim() : void 0;
|
|
1581
|
+
if (!id || !name) return null;
|
|
1582
|
+
return color ? { id, name, color } : { id, name };
|
|
1583
|
+
};
|
|
1584
|
+
var getThreadTagsFromMetadata = (metadata) => {
|
|
1585
|
+
if (!isRecord2(metadata) || !isRecord2(metadata.public)) return [];
|
|
1586
|
+
const tags = metadata.public.tags;
|
|
1587
|
+
if (!Array.isArray(tags)) return [];
|
|
1588
|
+
return tags.map(normalizeThreadTag).filter((tag) => !!tag);
|
|
1589
|
+
};
|
|
1590
|
+
var patchMetadataPublicTags = (metadata, tags) => ({
|
|
1591
|
+
...metadata ?? {},
|
|
1592
|
+
public: {
|
|
1593
|
+
...isRecord2(metadata?.public) ? metadata.public : {},
|
|
1594
|
+
tags
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1573
1597
|
var THREAD_MESSAGES_PAGE_SIZE = 50;
|
|
1574
1598
|
var createEmptyMessagePageInfo = () => ({
|
|
1575
1599
|
hasMoreBefore: false,
|
|
@@ -1577,35 +1601,18 @@ var createEmptyMessagePageInfo = () => ({
|
|
|
1577
1601
|
newestMessageId: null
|
|
1578
1602
|
});
|
|
1579
1603
|
var createPendingAssistantActivity = () => ({
|
|
1580
|
-
items: [
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1604
|
+
items: [
|
|
1605
|
+
{
|
|
1606
|
+
id: "thinking",
|
|
1607
|
+
kind: "thinking",
|
|
1608
|
+
status: "active",
|
|
1609
|
+
startedAt: nowTs()
|
|
1610
|
+
}
|
|
1611
|
+
]
|
|
1586
1612
|
});
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
userAvatar,
|
|
1591
|
-
assistantName,
|
|
1592
|
-
agentOptions = [],
|
|
1593
|
-
initialContext,
|
|
1594
|
-
bootstrap,
|
|
1595
|
-
defaultThreadName,
|
|
1596
|
-
onToolOutput,
|
|
1597
|
-
preferredAgentName,
|
|
1598
|
-
participants,
|
|
1599
|
-
targetAgentName,
|
|
1600
|
-
getRequestHeaders,
|
|
1601
|
-
eventInterceptor,
|
|
1602
|
-
runErrorInterceptor
|
|
1603
|
-
}) {
|
|
1604
|
-
const {
|
|
1605
|
-
state: urlState,
|
|
1606
|
-
setThreadId: setUrlThreadId,
|
|
1607
|
-
isEnabled: isUrlSyncEnabled
|
|
1608
|
-
} = useUrlState();
|
|
1613
|
+
var getCurrentUserDisplayName = (explicitName, fallbackId) => explicitName?.trim() || fallbackId;
|
|
1614
|
+
function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions = [], initialContext, bootstrap, defaultThreadName, onToolOutput, preferredAgentName, participants, targetAgentName, getRequestHeaders, eventInterceptor, runErrorInterceptor }) {
|
|
1615
|
+
const { state: urlState, setThreadId: setUrlThreadId, isEnabled: isUrlSyncEnabled } = useUrlState();
|
|
1609
1616
|
const [threads, setThreads] = useState2([]);
|
|
1610
1617
|
const [threadMetadataMap, setThreadMetadataMap] = useState2({});
|
|
1611
1618
|
const [threadExternalIdMap, setThreadExternalIdMap] = useState2({});
|
|
@@ -1660,42 +1667,51 @@ function useCopilotz({
|
|
|
1660
1667
|
setUserContextSeed((prev) => ({ ...prev, ...initialContext }));
|
|
1661
1668
|
}
|
|
1662
1669
|
}, [initialContext]);
|
|
1663
|
-
const processToolOutput = useCallback2(
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1670
|
+
const processToolOutput = useCallback2(
|
|
1671
|
+
(output) => {
|
|
1672
|
+
if (!output) return;
|
|
1673
|
+
const contextPatch = {};
|
|
1674
|
+
if (output.userContext && typeof output.userContext === "object") {
|
|
1675
|
+
Object.assign(contextPatch, output.userContext);
|
|
1676
|
+
}
|
|
1677
|
+
if (Object.keys(contextPatch).length > 0) {
|
|
1678
|
+
setUserContextSeed((prev) => ({ ...prev, ...contextPatch }));
|
|
1679
|
+
}
|
|
1680
|
+
onToolOutput?.(output);
|
|
1681
|
+
},
|
|
1682
|
+
[onToolOutput]
|
|
1683
|
+
);
|
|
1674
1684
|
const clearSpecialState = useCallback2(() => {
|
|
1675
1685
|
setSpecialState(null);
|
|
1676
1686
|
}, []);
|
|
1677
|
-
const applyEventInterceptor = useCallback2(
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1687
|
+
const applyEventInterceptor = useCallback2(
|
|
1688
|
+
(event) => {
|
|
1689
|
+
if (!eventInterceptor) return void 0;
|
|
1690
|
+
try {
|
|
1691
|
+
const result = eventInterceptor(event);
|
|
1692
|
+
if (result?.specialState) {
|
|
1693
|
+
setSpecialState(result.specialState);
|
|
1694
|
+
}
|
|
1695
|
+
return result;
|
|
1696
|
+
} catch (error) {
|
|
1697
|
+
console.error("Error in Copilotz event interceptor", error);
|
|
1698
|
+
return void 0;
|
|
1683
1699
|
}
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1700
|
+
},
|
|
1701
|
+
[eventInterceptor]
|
|
1702
|
+
);
|
|
1703
|
+
const getSpecialStateFromError = useCallback2(
|
|
1704
|
+
(error) => {
|
|
1705
|
+
if (!runErrorInterceptor) return null;
|
|
1706
|
+
try {
|
|
1707
|
+
return runErrorInterceptor(error) ?? null;
|
|
1708
|
+
} catch (interceptorError) {
|
|
1709
|
+
console.error("Error in Copilotz run error interceptor", interceptorError);
|
|
1710
|
+
return null;
|
|
1711
|
+
}
|
|
1712
|
+
},
|
|
1713
|
+
[runErrorInterceptor]
|
|
1714
|
+
);
|
|
1699
1715
|
const handleStreamMessageEvent = useCallback2((event) => {
|
|
1700
1716
|
const payload = getEventPayload(event);
|
|
1701
1717
|
if (!payload) return;
|
|
@@ -1756,6 +1772,7 @@ function useCopilotz({
|
|
|
1756
1772
|
updatedAt,
|
|
1757
1773
|
messageCount: typeof thread.metadata?.messageCount === "number" ? thread.metadata.messageCount : 0,
|
|
1758
1774
|
isArchived: thread.status === "archived",
|
|
1775
|
+
tags: getThreadTagsFromMetadata(thread.metadata),
|
|
1759
1776
|
metadata: thread.metadata ?? void 0
|
|
1760
1777
|
};
|
|
1761
1778
|
});
|
|
@@ -1783,56 +1800,61 @@ function useCopilotz({
|
|
|
1783
1800
|
setCurrentThreadExternalId(nextThreadId ? externalMap[nextThreadId] ?? null : null);
|
|
1784
1801
|
return nextThreadId;
|
|
1785
1802
|
}, []);
|
|
1786
|
-
const fetchAndSetThreadsState = useCallback2(
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
const requestId = messagesRequestRef.current + 1;
|
|
1807
|
-
messagesRequestRef.current = requestId;
|
|
1808
|
-
setIsMessagesLoading(true);
|
|
1809
|
-
setIsLoadingOlderMessages(false);
|
|
1810
|
-
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1811
|
-
persistedToolUpdatesRef.current = [];
|
|
1812
|
-
liveToolUpdatesRef.current = [];
|
|
1813
|
-
try {
|
|
1814
|
-
const page = await fetchThreadMessagesPage(
|
|
1815
|
-
threadId,
|
|
1816
|
-
{ limit: THREAD_MESSAGES_PAGE_SIZE },
|
|
1803
|
+
const fetchAndSetThreadsState = useCallback2(
|
|
1804
|
+
async (uid, preferredExternalId) => {
|
|
1805
|
+
try {
|
|
1806
|
+
const rawThreads = await fetchThreads(uid, getRequestHeaders);
|
|
1807
|
+
return updateThreadsState(rawThreads, preferredExternalId);
|
|
1808
|
+
} catch (error) {
|
|
1809
|
+
if (isAbortError(error)) return;
|
|
1810
|
+
console.error("Error loading threads", error);
|
|
1811
|
+
return null;
|
|
1812
|
+
}
|
|
1813
|
+
},
|
|
1814
|
+
[updateThreadsState, getRequestHeaders]
|
|
1815
|
+
);
|
|
1816
|
+
const prepareThreadMessages = useCallback2(
|
|
1817
|
+
async (rawMessages) => {
|
|
1818
|
+
return prepareHydratedMessages(rawMessages, {
|
|
1819
|
+
senderOptions: senderOptionsRef.current,
|
|
1820
|
+
createId: generateId,
|
|
1821
|
+
now: nowTs,
|
|
1822
|
+
onToolOutput: processToolOutput,
|
|
1817
1823
|
getRequestHeaders
|
|
1818
|
-
);
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
persistedToolUpdatesRef.current = [];
|
|
1824
|
+
});
|
|
1825
|
+
},
|
|
1826
|
+
[getRequestHeaders, processToolOutput]
|
|
1827
|
+
);
|
|
1828
|
+
const loadThreadMessages = useCallback2(
|
|
1829
|
+
async (threadId) => {
|
|
1830
|
+
const requestId = messagesRequestRef.current + 1;
|
|
1831
|
+
messagesRequestRef.current = requestId;
|
|
1832
|
+
setIsMessagesLoading(true);
|
|
1833
|
+
setIsLoadingOlderMessages(false);
|
|
1829
1834
|
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1835
|
+
persistedToolUpdatesRef.current = [];
|
|
1836
|
+
liveToolUpdatesRef.current = [];
|
|
1837
|
+
try {
|
|
1838
|
+
const page = await fetchThreadMessagesPage(threadId, { limit: THREAD_MESSAGES_PAGE_SIZE }, getRequestHeaders);
|
|
1839
|
+
const { viewMessages, toolResultUpdates } = await prepareThreadMessages(page.data);
|
|
1840
|
+
if (messagesRequestRef.current !== requestId) return;
|
|
1841
|
+
persistedToolUpdatesRef.current = toolResultUpdates;
|
|
1842
|
+
const hydratedMessages = mergePersistedToolResults(viewMessages, persistedToolUpdatesRef.current);
|
|
1843
|
+
setMessages(hydratedMessages);
|
|
1844
|
+
setMessagePageInfo(page.pageInfo);
|
|
1845
|
+
} catch (error) {
|
|
1846
|
+
if (isAbortError(error)) return;
|
|
1847
|
+
console.error(`Error loading messages for thread ${threadId}`, error);
|
|
1848
|
+
persistedToolUpdatesRef.current = [];
|
|
1849
|
+
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1850
|
+
} finally {
|
|
1851
|
+
if (messagesRequestRef.current === requestId) {
|
|
1852
|
+
setIsMessagesLoading(false);
|
|
1853
|
+
}
|
|
1833
1854
|
}
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1855
|
+
},
|
|
1856
|
+
[getRequestHeaders, prepareThreadMessages]
|
|
1857
|
+
);
|
|
1836
1858
|
const loadOlderMessages = useCallback2(async () => {
|
|
1837
1859
|
const threadId = currentThreadIdRef.current;
|
|
1838
1860
|
const pageInfo = messagePageInfoRef.current;
|
|
@@ -1843,21 +1865,11 @@ function useCopilotz({
|
|
|
1843
1865
|
const requestId = messagesRequestRef.current;
|
|
1844
1866
|
setIsLoadingOlderMessages(true);
|
|
1845
1867
|
try {
|
|
1846
|
-
const page = await fetchThreadMessagesPage(
|
|
1847
|
-
threadId,
|
|
1848
|
-
{ limit: THREAD_MESSAGES_PAGE_SIZE, before },
|
|
1849
|
-
getRequestHeaders
|
|
1850
|
-
);
|
|
1868
|
+
const page = await fetchThreadMessagesPage(threadId, { limit: THREAD_MESSAGES_PAGE_SIZE, before }, getRequestHeaders);
|
|
1851
1869
|
const { viewMessages, toolResultUpdates } = await prepareThreadMessages(page.data);
|
|
1852
1870
|
if (messagesRequestRef.current !== requestId) return;
|
|
1853
|
-
persistedToolUpdatesRef.current = [
|
|
1854
|
-
|
|
1855
|
-
...persistedToolUpdatesRef.current
|
|
1856
|
-
];
|
|
1857
|
-
setMessages((prev) => mergePersistedToolResults(
|
|
1858
|
-
prependUniqueMessages(viewMessages, prev),
|
|
1859
|
-
persistedToolUpdatesRef.current
|
|
1860
|
-
));
|
|
1871
|
+
persistedToolUpdatesRef.current = [...toolResultUpdates, ...persistedToolUpdatesRef.current];
|
|
1872
|
+
setMessages((prev) => mergePersistedToolResults(prependUniqueMessages(viewMessages, prev), persistedToolUpdatesRef.current));
|
|
1861
1873
|
setMessagePageInfo(page.pageInfo);
|
|
1862
1874
|
} catch (error) {
|
|
1863
1875
|
if (isAbortError(error)) return;
|
|
@@ -1868,15 +1880,18 @@ function useCopilotz({
|
|
|
1868
1880
|
}
|
|
1869
1881
|
}
|
|
1870
1882
|
}, [getRequestHeaders, prepareThreadMessages]);
|
|
1871
|
-
const handleSelectThread = useCallback2(
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1883
|
+
const handleSelectThread = useCallback2(
|
|
1884
|
+
async (threadId) => {
|
|
1885
|
+
setCurrentThreadId(threadId);
|
|
1886
|
+
setMessages([]);
|
|
1887
|
+
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1888
|
+
persistedToolUpdatesRef.current = [];
|
|
1889
|
+
const extMap = threadExternalIdMapRef.current;
|
|
1890
|
+
setCurrentThreadExternalId(extMap[threadId] ?? null);
|
|
1891
|
+
await loadThreadMessages(threadId);
|
|
1892
|
+
},
|
|
1893
|
+
[loadThreadMessages]
|
|
1894
|
+
);
|
|
1880
1895
|
const handleCreateThread = useCallback2((title) => {
|
|
1881
1896
|
messagesRequestRef.current += 1;
|
|
1882
1897
|
setIsMessagesLoading(false);
|
|
@@ -1892,7 +1907,10 @@ function useCopilotz({
|
|
|
1892
1907
|
metadata: { pendingTitle: title?.trim() || void 0 }
|
|
1893
1908
|
};
|
|
1894
1909
|
setThreads((prev) => [newThread, ...prev]);
|
|
1895
|
-
setThreadMetadataMap((prev) => ({
|
|
1910
|
+
setThreadMetadataMap((prev) => ({
|
|
1911
|
+
...prev,
|
|
1912
|
+
[id]: { pendingTitle: title?.trim() || void 0 }
|
|
1913
|
+
}));
|
|
1896
1914
|
setThreadExternalIdMap((prev) => ({ ...prev, [id]: id }));
|
|
1897
1915
|
setCurrentThreadId(id);
|
|
1898
1916
|
setCurrentThreadExternalId(id);
|
|
@@ -1900,89 +1918,117 @@ function useCopilotz({
|
|
|
1900
1918
|
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1901
1919
|
persistedToolUpdatesRef.current = [];
|
|
1902
1920
|
}, []);
|
|
1903
|
-
const handleRenameThread = useCallback2(
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
(prev) => prev.map((t) => t.id === threadId ? { ...t, title: trimmedTitle, updatedAt: nowTs() } : t)
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1921
|
+
const handleRenameThread = useCallback2(
|
|
1922
|
+
async (threadId, newTitle) => {
|
|
1923
|
+
const trimmedTitle = newTitle.trim();
|
|
1924
|
+
if (!trimmedTitle) return;
|
|
1925
|
+
setThreads((prev) => prev.map((t) => t.id === threadId ? { ...t, title: trimmedTitle, updatedAt: nowTs() } : t));
|
|
1926
|
+
const extMap = threadExternalIdMapRef.current;
|
|
1927
|
+
const isPlaceholder = extMap[threadId] === threadId;
|
|
1928
|
+
if (isPlaceholder) {
|
|
1929
|
+
setThreadMetadataMap((prev) => ({
|
|
1930
|
+
...prev,
|
|
1931
|
+
[threadId]: { ...prev[threadId], pendingTitle: trimmedTitle }
|
|
1932
|
+
}));
|
|
1933
|
+
} else {
|
|
1934
|
+
try {
|
|
1935
|
+
await updateThread(threadId, { name: trimmedTitle }, getRequestHeaders);
|
|
1936
|
+
} catch (error) {
|
|
1937
|
+
console.error("Failed to rename thread:", error);
|
|
1938
|
+
if (userId) {
|
|
1939
|
+
await fetchAndSetThreadsState(userId, currentThreadExternalIdRef.current);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
},
|
|
1944
|
+
[userId, fetchAndSetThreadsState, getRequestHeaders]
|
|
1945
|
+
);
|
|
1946
|
+
const handleArchiveThread = useCallback2(
|
|
1947
|
+
async (threadId) => {
|
|
1948
|
+
const thread = threadsRef.current.find((t) => t.id === threadId);
|
|
1949
|
+
if (!thread) return;
|
|
1950
|
+
const newArchivedStatus = !thread.isArchived;
|
|
1951
|
+
setThreads((prev) => prev.map((t) => t.id === threadId ? { ...t, isArchived: newArchivedStatus, updatedAt: nowTs() } : t));
|
|
1952
|
+
const extMap = threadExternalIdMapRef.current;
|
|
1953
|
+
const isPlaceholder = extMap[threadId] === threadId;
|
|
1954
|
+
if (!isPlaceholder) {
|
|
1955
|
+
try {
|
|
1956
|
+
await updateThread(threadId, { status: newArchivedStatus ? "archived" : "active" }, getRequestHeaders);
|
|
1957
|
+
} catch (error) {
|
|
1958
|
+
console.error("Failed to archive thread:", error);
|
|
1959
|
+
if (userId) {
|
|
1960
|
+
await fetchAndSetThreadsState(userId, currentThreadExternalIdRef.current);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
},
|
|
1965
|
+
[userId, fetchAndSetThreadsState, getRequestHeaders]
|
|
1966
|
+
);
|
|
1967
|
+
const handleUpdateThreadTags = useCallback2(
|
|
1968
|
+
async (threadId, tags) => {
|
|
1969
|
+
const extMap = threadExternalIdMapRef.current;
|
|
1970
|
+
const currentMetadata = threadMetadataMapRef.current[threadId];
|
|
1971
|
+
const nextMetadata = patchMetadataPublicTags(currentMetadata, tags);
|
|
1972
|
+
setThreads((prev) => prev.map((thread) => thread.id === threadId ? { ...thread, tags, metadata: nextMetadata, updatedAt: nowTs() } : thread));
|
|
1912
1973
|
setThreadMetadataMap((prev) => ({
|
|
1913
1974
|
...prev,
|
|
1914
|
-
[threadId]:
|
|
1975
|
+
[threadId]: nextMetadata
|
|
1915
1976
|
}));
|
|
1916
|
-
|
|
1977
|
+
const isPlaceholder = extMap[threadId] === threadId;
|
|
1978
|
+
if (isPlaceholder) return;
|
|
1917
1979
|
try {
|
|
1918
|
-
await updateThread(threadId, {
|
|
1980
|
+
await updateThread(threadId, { metadata: nextMetadata }, getRequestHeaders);
|
|
1919
1981
|
} catch (error) {
|
|
1920
|
-
console.error("Failed to
|
|
1982
|
+
console.error("Failed to update thread tags:", error);
|
|
1921
1983
|
if (userId) {
|
|
1922
1984
|
await fetchAndSetThreadsState(userId, currentThreadExternalIdRef.current);
|
|
1923
1985
|
}
|
|
1924
1986
|
}
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
(prev) => prev.
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1987
|
+
},
|
|
1988
|
+
[userId, fetchAndSetThreadsState, getRequestHeaders]
|
|
1989
|
+
);
|
|
1990
|
+
const handleDeleteThread = useCallback2(
|
|
1991
|
+
async (threadId) => {
|
|
1992
|
+
const extMap = threadExternalIdMapRef.current;
|
|
1993
|
+
const isPlaceholder = extMap[threadId] === threadId;
|
|
1994
|
+
setThreads((prev) => prev.filter((t) => t.id !== threadId));
|
|
1995
|
+
setThreadMetadataMap((prev) => {
|
|
1996
|
+
const next = { ...prev };
|
|
1997
|
+
delete next[threadId];
|
|
1998
|
+
return next;
|
|
1999
|
+
});
|
|
2000
|
+
setThreadExternalIdMap((prev) => {
|
|
2001
|
+
const next = { ...prev };
|
|
2002
|
+
delete next[threadId];
|
|
2003
|
+
return next;
|
|
2004
|
+
});
|
|
2005
|
+
if (currentThreadIdRef.current === threadId) {
|
|
2006
|
+
const remaining = threadsRef.current.filter((t) => t.id !== threadId);
|
|
2007
|
+
if (remaining.length > 0) {
|
|
2008
|
+
setCurrentThreadId(remaining[0].id);
|
|
2009
|
+
setCurrentThreadExternalId(extMap[remaining[0].id] ?? null);
|
|
2010
|
+
await loadThreadMessages(remaining[0].id);
|
|
2011
|
+
} else {
|
|
2012
|
+
setCurrentThreadId(null);
|
|
2013
|
+
setCurrentThreadExternalId(null);
|
|
2014
|
+
setMessages([]);
|
|
2015
|
+
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
2016
|
+
persistedToolUpdatesRef.current = [];
|
|
1943
2017
|
}
|
|
1944
2018
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
delete next[threadId];
|
|
1954
|
-
return next;
|
|
1955
|
-
});
|
|
1956
|
-
setThreadExternalIdMap((prev) => {
|
|
1957
|
-
const next = { ...prev };
|
|
1958
|
-
delete next[threadId];
|
|
1959
|
-
return next;
|
|
1960
|
-
});
|
|
1961
|
-
if (currentThreadIdRef.current === threadId) {
|
|
1962
|
-
const remaining = threadsRef.current.filter((t) => t.id !== threadId);
|
|
1963
|
-
if (remaining.length > 0) {
|
|
1964
|
-
setCurrentThreadId(remaining[0].id);
|
|
1965
|
-
setCurrentThreadExternalId(extMap[remaining[0].id] ?? null);
|
|
1966
|
-
await loadThreadMessages(remaining[0].id);
|
|
1967
|
-
} else {
|
|
1968
|
-
setCurrentThreadId(null);
|
|
1969
|
-
setCurrentThreadExternalId(null);
|
|
1970
|
-
setMessages([]);
|
|
1971
|
-
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
1972
|
-
persistedToolUpdatesRef.current = [];
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
if (!isPlaceholder) {
|
|
1976
|
-
try {
|
|
1977
|
-
await deleteThread(threadId, getRequestHeaders);
|
|
1978
|
-
} catch (error) {
|
|
1979
|
-
console.error("Failed to delete thread:", error);
|
|
1980
|
-
if (userId) {
|
|
1981
|
-
await fetchAndSetThreadsState(userId, currentThreadExternalIdRef.current);
|
|
2019
|
+
if (!isPlaceholder) {
|
|
2020
|
+
try {
|
|
2021
|
+
await deleteThread(threadId, getRequestHeaders);
|
|
2022
|
+
} catch (error) {
|
|
2023
|
+
console.error("Failed to delete thread:", error);
|
|
2024
|
+
if (userId) {
|
|
2025
|
+
await fetchAndSetThreadsState(userId, currentThreadExternalIdRef.current);
|
|
2026
|
+
}
|
|
1982
2027
|
}
|
|
1983
2028
|
}
|
|
1984
|
-
}
|
|
1985
|
-
|
|
2029
|
+
},
|
|
2030
|
+
[userId, fetchAndSetThreadsState, loadThreadMessages, getRequestHeaders]
|
|
2031
|
+
);
|
|
1986
2032
|
const handleStop = useCallback2(() => {
|
|
1987
2033
|
abortControllerRef.current?.abort();
|
|
1988
2034
|
abortControllerRef.current = null;
|
|
@@ -2005,514 +2051,533 @@ function useCopilotz({
|
|
|
2005
2051
|
...typeof payload.fileName === "string" ? { fileName: payload.fileName } : {},
|
|
2006
2052
|
...typeof payload.size === "number" ? { size: payload.size } : {}
|
|
2007
2053
|
};
|
|
2008
|
-
setMessages(
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2054
|
+
setMessages(
|
|
2055
|
+
(prev) => prev.map(
|
|
2056
|
+
(msg) => msg.id === assistantMessageId ? {
|
|
2057
|
+
...msg,
|
|
2058
|
+
attachments: [...msg.attachments || [], mediaAttachment]
|
|
2059
|
+
} : msg
|
|
2060
|
+
)
|
|
2061
|
+
);
|
|
2012
2062
|
}, []);
|
|
2013
|
-
const sendCopilotzMessage = useCallback2(
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2063
|
+
const sendCopilotzMessage = useCallback2(
|
|
2064
|
+
async (params) => {
|
|
2065
|
+
let currentAssistantId = params.assistantMessageId ?? generateId();
|
|
2066
|
+
let currentAssistantSender = params.assistantSender;
|
|
2067
|
+
params.onBeforeStart?.(currentAssistantId);
|
|
2068
|
+
let hasStreamProgress = false;
|
|
2069
|
+
const updateStreamingMessage = (partial, opts) => {
|
|
2070
|
+
if (partial && partial.length > 0) {
|
|
2071
|
+
hasStreamProgress = true;
|
|
2072
|
+
}
|
|
2073
|
+
const isReasoning = opts?.isReasoning ?? false;
|
|
2074
|
+
const nextSender = opts?.agent ? resolveAgentSender(opts.agent, senderOptionsRef.current) : currentAssistantSender;
|
|
2075
|
+
if (nextSender) {
|
|
2076
|
+
currentAssistantSender = nextSender;
|
|
2077
|
+
}
|
|
2078
|
+
const nextAgentKey = currentAssistantSender?.agentId ?? currentAssistantSender?.id ?? null;
|
|
2079
|
+
const applyUpdate = (msg) => {
|
|
2080
|
+
return {
|
|
2081
|
+
...updateAssistantMessageToken(msg, {
|
|
2082
|
+
partial,
|
|
2083
|
+
isReasoning
|
|
2084
|
+
}),
|
|
2085
|
+
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2086
|
+
};
|
|
2035
2087
|
};
|
|
2088
|
+
setMessages((prev) => {
|
|
2089
|
+
const idx = prev.findIndex((m) => m.id === currentAssistantId);
|
|
2090
|
+
if (idx >= 0 && canAttachToStreamingAssistant(prev[idx], nextAgentKey)) {
|
|
2091
|
+
const msg = prev[idx];
|
|
2092
|
+
const next = applyUpdate(msg);
|
|
2093
|
+
if (msg.content === next.content && msg.activity === next.activity && msg.isStreaming === next.isStreaming && msg.isComplete === next.isComplete) {
|
|
2094
|
+
return prev;
|
|
2095
|
+
}
|
|
2096
|
+
const updated = [...prev];
|
|
2097
|
+
updated[idx] = next;
|
|
2098
|
+
return updated;
|
|
2099
|
+
}
|
|
2100
|
+
const last = prev[prev.length - 1];
|
|
2101
|
+
if (canAttachToStreamingAssistant(last, nextAgentKey)) {
|
|
2102
|
+
currentAssistantId = last.id;
|
|
2103
|
+
const next = applyUpdate(last);
|
|
2104
|
+
if (last.content === next.content && last.activity === next.activity && last.isStreaming === next.isStreaming && last.isComplete === next.isComplete) {
|
|
2105
|
+
return prev;
|
|
2106
|
+
}
|
|
2107
|
+
const updated = [...prev];
|
|
2108
|
+
updated[prev.length - 1] = next;
|
|
2109
|
+
return updated;
|
|
2110
|
+
}
|
|
2111
|
+
const lastStreamingBelongsToDifferentAgent = Boolean(nextAgentKey) && last?.role === "assistant" && last.isStreaming && Boolean(messageAgentKey(last)) && messageAgentKey(last) !== nextAgentKey;
|
|
2112
|
+
if (!prev.length || prev[prev.length - 1].role !== "assistant" || !prev[prev.length - 1].isStreaming || lastStreamingBelongsToDifferentAgent) {
|
|
2113
|
+
const newId = generateId();
|
|
2114
|
+
currentAssistantId = newId;
|
|
2115
|
+
const base = {
|
|
2116
|
+
id: newId,
|
|
2117
|
+
role: "assistant",
|
|
2118
|
+
content: "",
|
|
2119
|
+
timestamp: nowTs(),
|
|
2120
|
+
isStreaming: true,
|
|
2121
|
+
isComplete: false,
|
|
2122
|
+
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2123
|
+
};
|
|
2124
|
+
return [...prev, applyUpdate(base)];
|
|
2125
|
+
}
|
|
2126
|
+
return prev;
|
|
2127
|
+
});
|
|
2036
2128
|
};
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2129
|
+
const finalizeCurrentAssistantBubble = () => {
|
|
2130
|
+
setMessages((prev) => {
|
|
2131
|
+
const idx = prev.findIndex((m) => m.id === currentAssistantId);
|
|
2132
|
+
if (idx < 0) return prev;
|
|
2040
2133
|
const msg = prev[idx];
|
|
2041
|
-
|
|
2042
|
-
if (msg.content === next.content && msg.activity === next.activity && msg.isStreaming === next.isStreaming && msg.isComplete === next.isComplete) {
|
|
2043
|
-
return prev;
|
|
2044
|
-
}
|
|
2134
|
+
if (!msg.isStreaming && msg.isComplete) return prev;
|
|
2045
2135
|
const updated = [...prev];
|
|
2046
|
-
updated[idx] =
|
|
2136
|
+
updated[idx] = closeAssistantMessage(msg);
|
|
2047
2137
|
return updated;
|
|
2138
|
+
});
|
|
2139
|
+
};
|
|
2140
|
+
const curThreadId = currentThreadIdRef.current;
|
|
2141
|
+
const applyLiveToolResultUpdate = (update) => {
|
|
2142
|
+
let matched = false;
|
|
2143
|
+
setMessages((prev) => {
|
|
2144
|
+
const next = applyToolResultUpdateToMessages(prev, update, {
|
|
2145
|
+
isStreaming: true,
|
|
2146
|
+
isComplete: false
|
|
2147
|
+
});
|
|
2148
|
+
matched = next.matched;
|
|
2149
|
+
return next.matched ? next.messages : prev;
|
|
2150
|
+
});
|
|
2151
|
+
if (!matched) {
|
|
2152
|
+
liveToolUpdatesRef.current.push(update);
|
|
2048
2153
|
}
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
const
|
|
2053
|
-
|
|
2154
|
+
};
|
|
2155
|
+
const finalizeActiveAssistantTurn = (finalAnswer) => {
|
|
2156
|
+
setMessages((prev) => {
|
|
2157
|
+
const currentIdx = prev.findIndex((message2) => message2.id === currentAssistantId && message2.role === "assistant");
|
|
2158
|
+
const fallbackIdx = currentIdx >= 0 ? currentIdx : (() => {
|
|
2159
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
2160
|
+
if (prev[i].role === "assistant" && prev[i].isStreaming) {
|
|
2161
|
+
return i;
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
return -1;
|
|
2165
|
+
})();
|
|
2166
|
+
if (fallbackIdx < 0) return prev;
|
|
2167
|
+
const message = prev[fallbackIdx];
|
|
2168
|
+
const nextMessage = finalizeAssistantMessage(message, finalAnswer);
|
|
2169
|
+
if (message.content === nextMessage.content && message.isStreaming === nextMessage.isStreaming && message.isComplete === nextMessage.isComplete && message.activity === nextMessage.activity) {
|
|
2054
2170
|
return prev;
|
|
2055
2171
|
}
|
|
2056
2172
|
const updated = [...prev];
|
|
2057
|
-
updated[
|
|
2173
|
+
updated[fallbackIdx] = nextMessage;
|
|
2174
|
+
currentAssistantId = nextMessage.id;
|
|
2058
2175
|
return updated;
|
|
2059
|
-
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2176
|
+
});
|
|
2177
|
+
};
|
|
2178
|
+
const toServerMessageFromEvent = async (event) => {
|
|
2179
|
+
if (!event) return null;
|
|
2180
|
+
const type = event?.type || "";
|
|
2181
|
+
const payload = event?.payload ?? event;
|
|
2182
|
+
if (type === "TOOL_CALL") {
|
|
2183
|
+
const parsedToolCall = extractLiveToolCall(payload);
|
|
2184
|
+
return {
|
|
2185
|
+
id: generateId(),
|
|
2186
|
+
threadId: curThreadId ?? "",
|
|
2187
|
+
senderType: "tool",
|
|
2067
2188
|
content: "",
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2189
|
+
toolCalls: [
|
|
2190
|
+
{
|
|
2191
|
+
id: parsedToolCall.id ?? generateId(),
|
|
2192
|
+
name: parsedToolCall.name,
|
|
2193
|
+
args: parsedToolCall.arguments,
|
|
2194
|
+
...parsedToolCall.result !== void 0 ? { output: parsedToolCall.result } : {},
|
|
2195
|
+
status: parsedToolCall.status
|
|
2196
|
+
}
|
|
2197
|
+
]
|
|
2072
2198
|
};
|
|
2073
|
-
return [...prev, applyUpdate(base)];
|
|
2074
2199
|
}
|
|
2075
|
-
return
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
const
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2200
|
+
return null;
|
|
2201
|
+
};
|
|
2202
|
+
const abortController = new AbortController();
|
|
2203
|
+
abortControllerRef.current?.abort();
|
|
2204
|
+
abortControllerRef.current = abortController;
|
|
2205
|
+
setIsStreaming(true);
|
|
2206
|
+
liveToolUpdatesRef.current = [];
|
|
2207
|
+
try {
|
|
2208
|
+
const normalizedUserMetadata = params.userMetadata ? JSON.parse(JSON.stringify(params.userMetadata)) : void 0;
|
|
2209
|
+
const contextSeed = userContextSeedRef.current;
|
|
2210
|
+
const contextMetadata = contextSeed ? JSON.parse(JSON.stringify(contextSeed)) : void 0;
|
|
2211
|
+
const requestContent = params.content && params.content.length > 0 ? params.content : "";
|
|
2212
|
+
const metadataKey = params.threadId ?? params.threadExternalId ?? void 0;
|
|
2213
|
+
const currentThreadMetadataMap = threadMetadataMapRef.current;
|
|
2214
|
+
const messageMetadata = metadataKey ? currentThreadMetadataMap[metadataKey]?.userContext : void 0;
|
|
2215
|
+
const threadMetadata = metadataKey ? currentThreadMetadataMap[metadataKey] : void 0;
|
|
2216
|
+
const mergedMetadata = {
|
|
2217
|
+
...messageMetadata ?? {},
|
|
2218
|
+
...params.metadata ?? {}
|
|
2219
|
+
};
|
|
2220
|
+
const finalMetadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : void 0;
|
|
2221
|
+
await runCopilotzStream({
|
|
2222
|
+
threadId: params.threadId ?? void 0,
|
|
2223
|
+
threadExternalId: params.threadExternalId ?? void 0,
|
|
2224
|
+
content: requestContent,
|
|
2225
|
+
user: {
|
|
2226
|
+
externalId: params.userId,
|
|
2227
|
+
name: params.userName ?? params.userId,
|
|
2228
|
+
metadata: {
|
|
2229
|
+
...contextMetadata ? contextMetadata : {},
|
|
2230
|
+
...normalizedUserMetadata ?? {}
|
|
2231
|
+
}
|
|
2232
|
+
},
|
|
2233
|
+
attachments: params.attachments,
|
|
2234
|
+
metadata: finalMetadata,
|
|
2235
|
+
threadMetadata: params.threadMetadata ?? threadMetadata,
|
|
2236
|
+
toolCalls: params.toolCalls,
|
|
2237
|
+
selectedAgent: params.agentName ?? preferredAgentRef.current ?? null,
|
|
2238
|
+
participants: participantsRef.current,
|
|
2239
|
+
targetAgent: targetAgentNameRef.current,
|
|
2240
|
+
getRequestHeaders,
|
|
2241
|
+
onToken: (token, _isComplete, raw, opts) => updateStreamingMessage(token, {
|
|
2242
|
+
...opts,
|
|
2243
|
+
agent: raw?.payload?.agent ?? raw?.agent ?? null
|
|
2244
|
+
}),
|
|
2245
|
+
onMessageEvent: async (event) => {
|
|
2246
|
+
const intercepted = applyEventInterceptor(event);
|
|
2247
|
+
if (intercepted?.handled) {
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
const type = event?.type || "";
|
|
2251
|
+
const payload = getEventPayload(event);
|
|
2252
|
+
if (type === "TOOL_RESULT") {
|
|
2253
|
+
processToolOutput(payload ?? {});
|
|
2254
|
+
applyLiveToolResultUpdate(extractLiveToolResultUpdate(payload ?? {}));
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2257
|
+
if (type === "LLM_RESULT") {
|
|
2258
|
+
const finalAnswer = typeof payload?.answer === "string" ? payload.answer : void 0;
|
|
2259
|
+
finalizeActiveAssistantTurn(finalAnswer);
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
if (type === "MESSAGE" || type === "NEW_MESSAGE") {
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
if (type === "TOOL_CALL") {
|
|
2266
|
+
const parsedToolCall = extractLiveToolCall(payload ?? {});
|
|
2267
|
+
const eventSender = resolveLiveEventSender(event, senderOptionsRef.current);
|
|
2268
|
+
currentAssistantSender = eventSender;
|
|
2269
|
+
const eventAgentKey = currentAssistantSender.agentId ?? currentAssistantSender.id;
|
|
2270
|
+
const callId = parsedToolCall.id ?? generateId();
|
|
2271
|
+
const toolName = parsedToolCall.name;
|
|
2272
|
+
const bufferedUpdates = liveToolUpdatesRef.current;
|
|
2273
|
+
const matchingUpdateIndex = bufferedUpdates.findIndex((upd) => matchesToolResultUpdate({ id: callId, name: toolName }, upd));
|
|
2274
|
+
const bufferedUpdate = matchingUpdateIndex >= 0 ? bufferedUpdates[matchingUpdateIndex] : void 0;
|
|
2275
|
+
if (matchingUpdateIndex >= 0) {
|
|
2276
|
+
bufferedUpdates.splice(matchingUpdateIndex, 1);
|
|
2277
|
+
}
|
|
2278
|
+
const initialStatus = bufferedUpdate ? bufferedUpdate.status : parsedToolCall.status;
|
|
2279
|
+
const initialResult = bufferedUpdate && bufferedUpdate.result !== void 0 ? bufferedUpdate.result : parsedToolCall.result;
|
|
2280
|
+
const endTime = bufferedUpdate?.endTime;
|
|
2281
|
+
setMessages(
|
|
2282
|
+
(prev) => (() => {
|
|
2283
|
+
const canHostActivity = (message) => {
|
|
2284
|
+
if (!message) return false;
|
|
2285
|
+
return message.role === "assistant" && message.isStreaming && message.content.trim().length === 0 && !message.attachments?.length;
|
|
2286
|
+
};
|
|
2287
|
+
const appendToolCall = (msg) => ({
|
|
2288
|
+
...appendAssistantToolCall(msg, {
|
|
2289
|
+
id: callId,
|
|
2290
|
+
name: toolName,
|
|
2291
|
+
arguments: parsedToolCall.arguments,
|
|
2292
|
+
...initialResult !== void 0 ? { result: initialResult } : {},
|
|
2293
|
+
status: initialStatus,
|
|
2294
|
+
startTime: Date.now(),
|
|
2295
|
+
...endTime !== void 0 ? { endTime } : {}
|
|
2296
|
+
})
|
|
2297
|
+
});
|
|
2298
|
+
const currentIdx = prev.findIndex((message) => message.id === currentAssistantId && message.role === "assistant" && message.isStreaming && canHostActivity(message));
|
|
2299
|
+
if (currentIdx >= 0) {
|
|
2300
|
+
const next = [...prev];
|
|
2301
|
+
next[currentIdx] = appendToolCall({
|
|
2302
|
+
...next[currentIdx],
|
|
2303
|
+
isStreaming: true,
|
|
2304
|
+
isComplete: false,
|
|
2305
|
+
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2306
|
+
});
|
|
2307
|
+
return next;
|
|
2308
|
+
}
|
|
2309
|
+
const last = prev[prev.length - 1];
|
|
2310
|
+
if (canHostActivity(last) && canAttachToStreamingAssistant(last, eventAgentKey)) {
|
|
2311
|
+
currentAssistantId = last.id;
|
|
2312
|
+
const next = [...prev];
|
|
2313
|
+
next[prev.length - 1] = appendToolCall({
|
|
2314
|
+
...last,
|
|
2315
|
+
isStreaming: true,
|
|
2316
|
+
isComplete: false,
|
|
2317
|
+
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2318
|
+
});
|
|
2319
|
+
return next;
|
|
2320
|
+
}
|
|
2321
|
+
const newId = generateId();
|
|
2322
|
+
currentAssistantId = newId;
|
|
2323
|
+
return [
|
|
2324
|
+
...prev,
|
|
2325
|
+
appendToolCall({
|
|
2326
|
+
id: newId,
|
|
2327
|
+
role: "assistant",
|
|
2328
|
+
content: "",
|
|
2329
|
+
timestamp: nowTs(),
|
|
2330
|
+
isStreaming: true,
|
|
2331
|
+
isComplete: false,
|
|
2332
|
+
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2333
|
+
})
|
|
2334
|
+
];
|
|
2335
|
+
})()
|
|
2336
|
+
);
|
|
2337
|
+
hasStreamProgress = true;
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
const sm = await toServerMessageFromEvent(event);
|
|
2341
|
+
if (sm) {
|
|
2342
|
+
const viewMsg = convertServerMessage(sm, {
|
|
2343
|
+
senderOptions: senderOptionsRef.current,
|
|
2344
|
+
createId: generateId,
|
|
2345
|
+
now: nowTs
|
|
2346
|
+
});
|
|
2347
|
+
finalizeCurrentAssistantBubble();
|
|
2348
|
+
setMessages((prev) => [...prev, viewMsg]);
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2351
|
+
handleStreamMessageEvent(event);
|
|
2352
|
+
},
|
|
2353
|
+
onAssetEvent: async (payload) => {
|
|
2354
|
+
const intercepted = applyEventInterceptor({
|
|
2355
|
+
type: "ASSET_CREATED",
|
|
2356
|
+
payload
|
|
2357
|
+
});
|
|
2358
|
+
if (intercepted?.handled) {
|
|
2359
|
+
return;
|
|
2360
|
+
}
|
|
2361
|
+
await (async () => {
|
|
2362
|
+
if (!hasStreamProgress) return;
|
|
2363
|
+
handleStreamAssetEvent(payload, currentAssistantId);
|
|
2364
|
+
})();
|
|
2365
|
+
},
|
|
2366
|
+
signal: abortController.signal
|
|
2096
2367
|
});
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2368
|
+
} finally {
|
|
2369
|
+
setIsStreaming(false);
|
|
2370
|
+
setMessages((prev) => {
|
|
2371
|
+
const hasStreaming = prev.some((msg) => msg.isStreaming);
|
|
2372
|
+
if (!hasStreaming) return prev;
|
|
2373
|
+
return prev.map((msg) => msg.isStreaming ? closeAssistantMessage(msg) : msg);
|
|
2374
|
+
});
|
|
2375
|
+
abortControllerRef.current = null;
|
|
2102
2376
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2377
|
+
return currentAssistantId;
|
|
2378
|
+
},
|
|
2379
|
+
[applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, getRequestHeaders]
|
|
2380
|
+
);
|
|
2381
|
+
const handleSendMessage = useCallback2(
|
|
2382
|
+
async (content, attachments = []) => {
|
|
2383
|
+
if (!content.trim() && attachments.length === 0) return;
|
|
2384
|
+
if (!userId) return;
|
|
2385
|
+
const timestamp = nowTs();
|
|
2386
|
+
const curThreadId = currentThreadIdRef.current;
|
|
2387
|
+
const curThreadExtId = currentThreadExternalIdRef.current;
|
|
2388
|
+
const existingThreadId = curThreadId ?? void 0;
|
|
2389
|
+
const extMap = threadExternalIdMapRef.current;
|
|
2390
|
+
const isPlaceholderThread = existingThreadId ? extMap[existingThreadId] === existingThreadId : false;
|
|
2391
|
+
const threadIdForSend = isPlaceholderThread ? void 0 : existingThreadId;
|
|
2392
|
+
let effectiveThreadExternalId = curThreadExtId ?? (isPlaceholderThread ? existingThreadId : void 0);
|
|
2393
|
+
if (!threadIdForSend) {
|
|
2394
|
+
if (!effectiveThreadExternalId) {
|
|
2395
|
+
effectiveThreadExternalId = generateId();
|
|
2120
2396
|
}
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
return updated;
|
|
2125
|
-
});
|
|
2126
|
-
};
|
|
2127
|
-
const toServerMessageFromEvent = async (event) => {
|
|
2128
|
-
if (!event) return null;
|
|
2129
|
-
const type = event?.type || "";
|
|
2130
|
-
const payload = event?.payload ?? event;
|
|
2131
|
-
if (type === "TOOL_CALL") {
|
|
2132
|
-
const parsedToolCall = extractLiveToolCall(payload);
|
|
2133
|
-
return {
|
|
2134
|
-
id: generateId(),
|
|
2135
|
-
threadId: curThreadId ?? "",
|
|
2136
|
-
senderType: "tool",
|
|
2137
|
-
content: "",
|
|
2138
|
-
toolCalls: [{
|
|
2139
|
-
id: parsedToolCall.id ?? generateId(),
|
|
2140
|
-
name: parsedToolCall.name,
|
|
2141
|
-
args: parsedToolCall.arguments,
|
|
2142
|
-
...parsedToolCall.result !== void 0 ? { output: parsedToolCall.result } : {},
|
|
2143
|
-
status: parsedToolCall.status
|
|
2144
|
-
}]
|
|
2145
|
-
};
|
|
2397
|
+
setCurrentThreadExternalId(effectiveThreadExternalId);
|
|
2398
|
+
} else if (curThreadExtId !== (effectiveThreadExternalId ?? null)) {
|
|
2399
|
+
setCurrentThreadExternalId(effectiveThreadExternalId ?? null);
|
|
2146
2400
|
}
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
const messageMetadata = metadataKey ? currentThreadMetadataMap[metadataKey]?.userContext : void 0;
|
|
2162
|
-
const threadMetadata = metadataKey ? currentThreadMetadataMap[metadataKey] : void 0;
|
|
2163
|
-
const mergedMetadata = {
|
|
2164
|
-
...messageMetadata ?? {},
|
|
2165
|
-
...params.metadata ?? {}
|
|
2401
|
+
const conversationKey = threadIdForSend ?? effectiveThreadExternalId;
|
|
2402
|
+
const currentMetadata = threadMetadataMapRef.current[conversationKey];
|
|
2403
|
+
const pendingTitle = currentMetadata?.pendingTitle;
|
|
2404
|
+
const userMessage = {
|
|
2405
|
+
id: generateId(),
|
|
2406
|
+
role: "user",
|
|
2407
|
+
content,
|
|
2408
|
+
timestamp,
|
|
2409
|
+
attachments: attachments.length > 0 ? attachments : void 0,
|
|
2410
|
+
isComplete: true,
|
|
2411
|
+
sender: resolveUserSender({
|
|
2412
|
+
id: userId,
|
|
2413
|
+
name: getCurrentUserDisplayName(userName, userId)
|
|
2414
|
+
})
|
|
2166
2415
|
};
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
content: requestContent,
|
|
2172
|
-
user: {
|
|
2173
|
-
externalId: params.userId,
|
|
2174
|
-
name: params.userName ?? params.userId,
|
|
2175
|
-
metadata: {
|
|
2176
|
-
...contextMetadata ? contextMetadata : {},
|
|
2177
|
-
...normalizedUserMetadata ?? {}
|
|
2178
|
-
}
|
|
2416
|
+
const assistantSender = targetAgentNameRef.current ? resolveAgentSender(
|
|
2417
|
+
{
|
|
2418
|
+
id: targetAgentNameRef.current,
|
|
2419
|
+
name: targetAgentNameRef.current
|
|
2179
2420
|
},
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2421
|
+
senderOptionsRef.current
|
|
2422
|
+
) : preferredAgentRef.current ? resolveAgentSender({ id: preferredAgentRef.current, name: preferredAgentRef.current }, senderOptionsRef.current) : resolveAssistantFallbackSender(senderOptionsRef.current);
|
|
2423
|
+
const assistantPlaceholder = {
|
|
2424
|
+
id: generateId(),
|
|
2425
|
+
role: "assistant",
|
|
2426
|
+
content: "",
|
|
2427
|
+
timestamp: timestamp + 1,
|
|
2428
|
+
isStreaming: true,
|
|
2429
|
+
isComplete: false,
|
|
2430
|
+
sender: assistantSender,
|
|
2431
|
+
activity: createPendingAssistantActivity()
|
|
2432
|
+
};
|
|
2433
|
+
setMessages((prev) => [...prev, userMessage, assistantPlaceholder]);
|
|
2434
|
+
setSpecialState(null);
|
|
2435
|
+
if (!threadsRef.current.some((t) => t.id === conversationKey)) {
|
|
2436
|
+
const newThread = {
|
|
2437
|
+
id: conversationKey,
|
|
2438
|
+
title: content.slice(0, 40) || "Nova conversa",
|
|
2439
|
+
createdAt: timestamp,
|
|
2440
|
+
updatedAt: timestamp,
|
|
2441
|
+
messageCount: 0
|
|
2442
|
+
};
|
|
2443
|
+
setThreads((prev) => [newThread, ...prev]);
|
|
2444
|
+
setThreadMetadataMap((prev) => ({ ...prev, [conversationKey]: {} }));
|
|
2445
|
+
setThreadExternalIdMap((prev) => ({
|
|
2446
|
+
...prev,
|
|
2447
|
+
[conversationKey]: effectiveThreadExternalId ?? null
|
|
2448
|
+
}));
|
|
2449
|
+
}
|
|
2450
|
+
try {
|
|
2451
|
+
await sendCopilotzMessage({
|
|
2452
|
+
threadId: threadIdForSend,
|
|
2453
|
+
threadExternalId: effectiveThreadExternalId,
|
|
2454
|
+
content,
|
|
2455
|
+
attachments,
|
|
2456
|
+
userId,
|
|
2457
|
+
userName: getCurrentUserDisplayName(userName, userId),
|
|
2458
|
+
agentName: preferredAgentRef.current,
|
|
2459
|
+
assistantMessageId: assistantPlaceholder.id,
|
|
2460
|
+
assistantSender,
|
|
2461
|
+
// Include pending title for new threads
|
|
2462
|
+
threadMetadata: pendingTitle ? { name: pendingTitle } : void 0
|
|
2463
|
+
});
|
|
2464
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
2465
|
+
await fetchAndSetThreadsState(userId, effectiveThreadExternalId ?? existingThreadId ?? null);
|
|
2466
|
+
} catch (error) {
|
|
2467
|
+
if (isAbortError(error)) return;
|
|
2468
|
+
console.error("Error sending Copilotz message", error);
|
|
2469
|
+
const nextSpecialState = getSpecialStateFromError(error);
|
|
2470
|
+
if (nextSpecialState) {
|
|
2471
|
+
setSpecialState(nextSpecialState);
|
|
2472
|
+
setMessages((prev) => prev.filter((msg) => !msg.isStreaming));
|
|
2473
|
+
return;
|
|
2474
|
+
}
|
|
2475
|
+
setMessages((prev) => {
|
|
2476
|
+
const finalized = prev.map((msg) => msg.isStreaming ? closeAssistantMessage(msg) : msg);
|
|
2477
|
+
if (finalized.some(hasVisibleAssistantOutput)) {
|
|
2478
|
+
return finalized;
|
|
2210
2479
|
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2480
|
+
for (let i = finalized.length - 1; i >= 0; i--) {
|
|
2481
|
+
const message = finalized[i];
|
|
2482
|
+
if (message.role !== "assistant") continue;
|
|
2483
|
+
const updated = [...finalized];
|
|
2484
|
+
updated[i] = {
|
|
2485
|
+
...message,
|
|
2486
|
+
content: "Desculpe, ocorreu um erro ao gerar a resposta. Por favor, tente novamente.",
|
|
2487
|
+
isStreaming: false,
|
|
2488
|
+
isComplete: true,
|
|
2489
|
+
sender: message.sender ?? resolveAssistantFallbackSender(senderOptionsRef.current)
|
|
2490
|
+
};
|
|
2491
|
+
return updated;
|
|
2213
2492
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
const matchingUpdateIndex = bufferedUpdates.findIndex((upd) => matchesToolResultUpdate({ id: callId, name: toolName }, upd));
|
|
2225
|
-
const bufferedUpdate = matchingUpdateIndex >= 0 ? bufferedUpdates[matchingUpdateIndex] : void 0;
|
|
2226
|
-
if (matchingUpdateIndex >= 0) {
|
|
2227
|
-
bufferedUpdates.splice(matchingUpdateIndex, 1);
|
|
2493
|
+
return [
|
|
2494
|
+
...finalized,
|
|
2495
|
+
{
|
|
2496
|
+
id: generateId(),
|
|
2497
|
+
role: "assistant",
|
|
2498
|
+
content: "Desculpe, ocorreu um erro ao gerar a resposta. Por favor, tente novamente.",
|
|
2499
|
+
timestamp: nowTs(),
|
|
2500
|
+
isStreaming: false,
|
|
2501
|
+
isComplete: true,
|
|
2502
|
+
sender: resolveAssistantFallbackSender(senderOptionsRef.current)
|
|
2228
2503
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
const endTime = bufferedUpdate?.endTime;
|
|
2232
|
-
setMessages(
|
|
2233
|
-
(prev) => (() => {
|
|
2234
|
-
const canHostActivity = (message) => {
|
|
2235
|
-
if (!message) return false;
|
|
2236
|
-
return message.role === "assistant" && message.isStreaming && message.content.trim().length === 0 && !message.attachments?.length;
|
|
2237
|
-
};
|
|
2238
|
-
const appendToolCall = (msg) => ({
|
|
2239
|
-
...appendAssistantToolCall(msg, {
|
|
2240
|
-
id: callId,
|
|
2241
|
-
name: toolName,
|
|
2242
|
-
arguments: parsedToolCall.arguments,
|
|
2243
|
-
...initialResult !== void 0 ? { result: initialResult } : {},
|
|
2244
|
-
status: initialStatus,
|
|
2245
|
-
startTime: Date.now(),
|
|
2246
|
-
...endTime !== void 0 ? { endTime } : {}
|
|
2247
|
-
})
|
|
2248
|
-
});
|
|
2249
|
-
const currentIdx = prev.findIndex((message) => message.id === currentAssistantId && message.role === "assistant" && message.isStreaming && canHostActivity(message));
|
|
2250
|
-
if (currentIdx >= 0) {
|
|
2251
|
-
const next = [...prev];
|
|
2252
|
-
next[currentIdx] = appendToolCall({
|
|
2253
|
-
...next[currentIdx],
|
|
2254
|
-
isStreaming: true,
|
|
2255
|
-
isComplete: false,
|
|
2256
|
-
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2257
|
-
});
|
|
2258
|
-
return next;
|
|
2259
|
-
}
|
|
2260
|
-
const last = prev[prev.length - 1];
|
|
2261
|
-
if (canHostActivity(last) && canAttachToStreamingAssistant(
|
|
2262
|
-
last,
|
|
2263
|
-
eventAgentKey
|
|
2264
|
-
)) {
|
|
2265
|
-
currentAssistantId = last.id;
|
|
2266
|
-
const next = [...prev];
|
|
2267
|
-
next[prev.length - 1] = appendToolCall({
|
|
2268
|
-
...last,
|
|
2269
|
-
isStreaming: true,
|
|
2270
|
-
isComplete: false,
|
|
2271
|
-
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2272
|
-
});
|
|
2273
|
-
return next;
|
|
2274
|
-
}
|
|
2275
|
-
const newId = generateId();
|
|
2276
|
-
currentAssistantId = newId;
|
|
2277
|
-
return [
|
|
2278
|
-
...prev,
|
|
2279
|
-
appendToolCall({
|
|
2280
|
-
id: newId,
|
|
2281
|
-
role: "assistant",
|
|
2282
|
-
content: "",
|
|
2283
|
-
timestamp: nowTs(),
|
|
2284
|
-
isStreaming: true,
|
|
2285
|
-
isComplete: false,
|
|
2286
|
-
...currentAssistantSender ? { sender: currentAssistantSender } : {}
|
|
2287
|
-
})
|
|
2288
|
-
];
|
|
2289
|
-
})()
|
|
2290
|
-
);
|
|
2291
|
-
hasStreamProgress = true;
|
|
2292
|
-
return;
|
|
2293
|
-
}
|
|
2294
|
-
const sm = await toServerMessageFromEvent(event);
|
|
2295
|
-
if (sm) {
|
|
2296
|
-
const viewMsg = convertServerMessage(sm, {
|
|
2297
|
-
senderOptions: senderOptionsRef.current,
|
|
2298
|
-
createId: generateId,
|
|
2299
|
-
now: nowTs
|
|
2300
|
-
});
|
|
2301
|
-
finalizeCurrentAssistantBubble();
|
|
2302
|
-
setMessages((prev) => [...prev, viewMsg]);
|
|
2303
|
-
return;
|
|
2304
|
-
}
|
|
2305
|
-
handleStreamMessageEvent(event);
|
|
2306
|
-
},
|
|
2307
|
-
onAssetEvent: async (payload) => {
|
|
2308
|
-
const intercepted = applyEventInterceptor({ type: "ASSET_CREATED", payload });
|
|
2309
|
-
if (intercepted?.handled) {
|
|
2310
|
-
return;
|
|
2311
|
-
}
|
|
2312
|
-
await (async () => {
|
|
2313
|
-
if (!hasStreamProgress) return;
|
|
2314
|
-
handleStreamAssetEvent(payload, currentAssistantId);
|
|
2315
|
-
})();
|
|
2316
|
-
},
|
|
2317
|
-
signal: abortController.signal
|
|
2318
|
-
});
|
|
2319
|
-
} finally {
|
|
2320
|
-
setIsStreaming(false);
|
|
2321
|
-
setMessages((prev) => {
|
|
2322
|
-
const hasStreaming = prev.some((msg) => msg.isStreaming);
|
|
2323
|
-
if (!hasStreaming) return prev;
|
|
2324
|
-
return prev.map((msg) => msg.isStreaming ? closeAssistantMessage(msg) : msg);
|
|
2325
|
-
});
|
|
2326
|
-
abortControllerRef.current = null;
|
|
2327
|
-
}
|
|
2328
|
-
return currentAssistantId;
|
|
2329
|
-
}, [applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, getRequestHeaders]);
|
|
2330
|
-
const handleSendMessage = useCallback2(async (content, attachments = []) => {
|
|
2331
|
-
if (!content.trim() && attachments.length === 0) return;
|
|
2332
|
-
if (!userId) return;
|
|
2333
|
-
const timestamp = nowTs();
|
|
2334
|
-
const curThreadId = currentThreadIdRef.current;
|
|
2335
|
-
const curThreadExtId = currentThreadExternalIdRef.current;
|
|
2336
|
-
const existingThreadId = curThreadId ?? void 0;
|
|
2337
|
-
const extMap = threadExternalIdMapRef.current;
|
|
2338
|
-
const isPlaceholderThread = existingThreadId ? extMap[existingThreadId] === existingThreadId : false;
|
|
2339
|
-
const threadIdForSend = isPlaceholderThread ? void 0 : existingThreadId;
|
|
2340
|
-
let effectiveThreadExternalId = curThreadExtId ?? (isPlaceholderThread ? existingThreadId : void 0);
|
|
2341
|
-
if (!threadIdForSend) {
|
|
2342
|
-
if (!effectiveThreadExternalId) {
|
|
2343
|
-
effectiveThreadExternalId = generateId();
|
|
2344
|
-
}
|
|
2345
|
-
setCurrentThreadExternalId(effectiveThreadExternalId);
|
|
2346
|
-
} else if (curThreadExtId !== (effectiveThreadExternalId ?? null)) {
|
|
2347
|
-
setCurrentThreadExternalId(effectiveThreadExternalId ?? null);
|
|
2348
|
-
}
|
|
2349
|
-
const conversationKey = threadIdForSend ?? effectiveThreadExternalId;
|
|
2350
|
-
const currentMetadata = threadMetadataMapRef.current[conversationKey];
|
|
2351
|
-
const pendingTitle = currentMetadata?.pendingTitle;
|
|
2352
|
-
const userMessage = {
|
|
2353
|
-
id: generateId(),
|
|
2354
|
-
role: "user",
|
|
2355
|
-
content,
|
|
2356
|
-
timestamp,
|
|
2357
|
-
attachments: attachments.length > 0 ? attachments : void 0,
|
|
2358
|
-
isComplete: true,
|
|
2359
|
-
sender: resolveUserSender({
|
|
2360
|
-
id: userId,
|
|
2361
|
-
name: userContextSeedRef.current?.profile?.full_name ?? userId
|
|
2362
|
-
})
|
|
2363
|
-
};
|
|
2364
|
-
const assistantSender = targetAgentNameRef.current ? resolveAgentSender(
|
|
2365
|
-
{ id: targetAgentNameRef.current, name: targetAgentNameRef.current },
|
|
2366
|
-
senderOptionsRef.current
|
|
2367
|
-
) : preferredAgentRef.current ? resolveAgentSender(
|
|
2368
|
-
{ id: preferredAgentRef.current, name: preferredAgentRef.current },
|
|
2369
|
-
senderOptionsRef.current
|
|
2370
|
-
) : resolveAssistantFallbackSender(senderOptionsRef.current);
|
|
2371
|
-
const assistantPlaceholder = {
|
|
2372
|
-
id: generateId(),
|
|
2373
|
-
role: "assistant",
|
|
2374
|
-
content: "",
|
|
2375
|
-
timestamp: timestamp + 1,
|
|
2376
|
-
isStreaming: true,
|
|
2377
|
-
isComplete: false,
|
|
2378
|
-
sender: assistantSender,
|
|
2379
|
-
activity: createPendingAssistantActivity()
|
|
2380
|
-
};
|
|
2381
|
-
setMessages((prev) => [...prev, userMessage, assistantPlaceholder]);
|
|
2382
|
-
setSpecialState(null);
|
|
2383
|
-
if (!threadsRef.current.some((t) => t.id === conversationKey)) {
|
|
2384
|
-
const newThread = {
|
|
2385
|
-
id: conversationKey,
|
|
2386
|
-
title: content.slice(0, 40) || "Nova conversa",
|
|
2387
|
-
createdAt: timestamp,
|
|
2388
|
-
updatedAt: timestamp,
|
|
2389
|
-
messageCount: 0
|
|
2390
|
-
};
|
|
2391
|
-
setThreads((prev) => [newThread, ...prev]);
|
|
2392
|
-
setThreadMetadataMap((prev) => ({ ...prev, [conversationKey]: {} }));
|
|
2393
|
-
setThreadExternalIdMap((prev) => ({ ...prev, [conversationKey]: effectiveThreadExternalId ?? null }));
|
|
2394
|
-
}
|
|
2395
|
-
try {
|
|
2396
|
-
await sendCopilotzMessage({
|
|
2397
|
-
threadId: threadIdForSend,
|
|
2398
|
-
threadExternalId: effectiveThreadExternalId,
|
|
2399
|
-
content,
|
|
2400
|
-
attachments,
|
|
2401
|
-
userId,
|
|
2402
|
-
// userName can be anything, but let's try to find it in context or just fallback
|
|
2403
|
-
userName: userContextSeedRef.current?.profile?.full_name ?? userId,
|
|
2404
|
-
agentName: preferredAgentRef.current,
|
|
2405
|
-
assistantMessageId: assistantPlaceholder.id,
|
|
2406
|
-
assistantSender,
|
|
2407
|
-
// Include pending title for new threads
|
|
2408
|
-
threadMetadata: pendingTitle ? { name: pendingTitle } : void 0
|
|
2409
|
-
});
|
|
2410
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
2411
|
-
await fetchAndSetThreadsState(userId, effectiveThreadExternalId ?? existingThreadId ?? null);
|
|
2412
|
-
} catch (error) {
|
|
2413
|
-
if (isAbortError(error)) return;
|
|
2414
|
-
console.error("Error sending Copilotz message", error);
|
|
2415
|
-
const nextSpecialState = getSpecialStateFromError(error);
|
|
2416
|
-
if (nextSpecialState) {
|
|
2417
|
-
setSpecialState(nextSpecialState);
|
|
2418
|
-
setMessages((prev) => prev.filter((msg) => !msg.isStreaming));
|
|
2419
|
-
return;
|
|
2504
|
+
];
|
|
2505
|
+
});
|
|
2420
2506
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2507
|
+
},
|
|
2508
|
+
[userId, fetchAndSetThreadsState, loadThreadMessages, sendCopilotzMessage, getSpecialStateFromError]
|
|
2509
|
+
);
|
|
2510
|
+
const bootstrapConversation = useCallback2(
|
|
2511
|
+
async (uid) => {
|
|
2512
|
+
if (!bootstrap?.initialToolCalls && !bootstrap?.initialMessage) return;
|
|
2513
|
+
const bootstrapThreadExternalId = generateId();
|
|
2514
|
+
setCurrentThreadId(bootstrapThreadExternalId);
|
|
2515
|
+
setCurrentThreadExternalId(bootstrapThreadExternalId);
|
|
2516
|
+
setThreadExternalIdMap((prev) => ({
|
|
2517
|
+
...prev,
|
|
2518
|
+
[bootstrapThreadExternalId]: bootstrapThreadExternalId
|
|
2519
|
+
}));
|
|
2520
|
+
setThreadMetadataMap((prev) => ({
|
|
2521
|
+
...prev,
|
|
2522
|
+
[bootstrapThreadExternalId]: {}
|
|
2523
|
+
}));
|
|
2524
|
+
const assistantSender = preferredAgentRef.current ? resolveAgentSender({ id: preferredAgentRef.current, name: preferredAgentRef.current }, senderOptionsRef.current) : resolveAssistantFallbackSender(senderOptionsRef.current);
|
|
2525
|
+
const assistantMessageId = generateId();
|
|
2526
|
+
setMessages([
|
|
2527
|
+
{
|
|
2528
|
+
id: assistantMessageId,
|
|
2529
|
+
role: "assistant",
|
|
2530
|
+
content: "",
|
|
2531
|
+
timestamp: nowTs(),
|
|
2532
|
+
isStreaming: true,
|
|
2533
|
+
isComplete: false,
|
|
2534
|
+
sender: assistantSender,
|
|
2535
|
+
activity: createPendingAssistantActivity()
|
|
2425
2536
|
}
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2537
|
+
]);
|
|
2538
|
+
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
2539
|
+
persistedToolUpdatesRef.current = [];
|
|
2540
|
+
setSpecialState(null);
|
|
2541
|
+
try {
|
|
2542
|
+
await sendCopilotzMessage({
|
|
2543
|
+
threadExternalId: bootstrapThreadExternalId,
|
|
2544
|
+
content: bootstrap.initialMessage || "",
|
|
2545
|
+
toolCalls: bootstrap.initialToolCalls,
|
|
2546
|
+
userId: uid,
|
|
2547
|
+
userName: getCurrentUserDisplayName(userName, uid),
|
|
2548
|
+
agentName: preferredAgentRef.current,
|
|
2549
|
+
assistantMessageId,
|
|
2550
|
+
assistantSender,
|
|
2551
|
+
threadMetadata: {
|
|
2552
|
+
name: defaultThreadName || "Main Thread"
|
|
2553
|
+
}
|
|
2554
|
+
});
|
|
2555
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
2556
|
+
await fetchAndSetThreadsState(uid, bootstrapThreadExternalId);
|
|
2557
|
+
} catch (error) {
|
|
2558
|
+
if (isAbortError(error)) return;
|
|
2559
|
+
console.error("Error bootstrapping conversation", error);
|
|
2560
|
+
const nextSpecialState = getSpecialStateFromError(error);
|
|
2561
|
+
if (nextSpecialState) {
|
|
2562
|
+
setSpecialState(nextSpecialState);
|
|
2563
|
+
setMessages([]);
|
|
2564
|
+
return;
|
|
2438
2565
|
}
|
|
2439
|
-
|
|
2440
|
-
...finalized,
|
|
2566
|
+
setMessages([
|
|
2441
2567
|
{
|
|
2442
2568
|
id: generateId(),
|
|
2443
2569
|
role: "assistant",
|
|
2444
|
-
content: "
|
|
2570
|
+
content: "N\xE3o foi poss\xEDvel iniciar a conversa. Tente novamente mais tarde.",
|
|
2445
2571
|
timestamp: nowTs(),
|
|
2446
2572
|
isStreaming: false,
|
|
2447
2573
|
isComplete: true,
|
|
2448
2574
|
sender: resolveAssistantFallbackSender(senderOptionsRef.current)
|
|
2449
2575
|
}
|
|
2450
|
-
];
|
|
2451
|
-
});
|
|
2452
|
-
}
|
|
2453
|
-
}, [userId, fetchAndSetThreadsState, loadThreadMessages, sendCopilotzMessage, getSpecialStateFromError]);
|
|
2454
|
-
const bootstrapConversation = useCallback2(async (uid) => {
|
|
2455
|
-
if (!bootstrap?.initialToolCalls && !bootstrap?.initialMessage) return;
|
|
2456
|
-
const bootstrapThreadExternalId = generateId();
|
|
2457
|
-
setCurrentThreadId(bootstrapThreadExternalId);
|
|
2458
|
-
setCurrentThreadExternalId(bootstrapThreadExternalId);
|
|
2459
|
-
setThreadExternalIdMap((prev) => ({ ...prev, [bootstrapThreadExternalId]: bootstrapThreadExternalId }));
|
|
2460
|
-
setThreadMetadataMap((prev) => ({ ...prev, [bootstrapThreadExternalId]: {} }));
|
|
2461
|
-
const assistantSender = preferredAgentRef.current ? resolveAgentSender(
|
|
2462
|
-
{ id: preferredAgentRef.current, name: preferredAgentRef.current },
|
|
2463
|
-
senderOptionsRef.current
|
|
2464
|
-
) : resolveAssistantFallbackSender(senderOptionsRef.current);
|
|
2465
|
-
const assistantMessageId = generateId();
|
|
2466
|
-
setMessages([{
|
|
2467
|
-
id: assistantMessageId,
|
|
2468
|
-
role: "assistant",
|
|
2469
|
-
content: "",
|
|
2470
|
-
timestamp: nowTs(),
|
|
2471
|
-
isStreaming: true,
|
|
2472
|
-
isComplete: false,
|
|
2473
|
-
sender: assistantSender,
|
|
2474
|
-
activity: createPendingAssistantActivity()
|
|
2475
|
-
}]);
|
|
2476
|
-
setMessagePageInfo(createEmptyMessagePageInfo());
|
|
2477
|
-
persistedToolUpdatesRef.current = [];
|
|
2478
|
-
setSpecialState(null);
|
|
2479
|
-
try {
|
|
2480
|
-
await sendCopilotzMessage({
|
|
2481
|
-
threadExternalId: bootstrapThreadExternalId,
|
|
2482
|
-
content: bootstrap.initialMessage || "",
|
|
2483
|
-
toolCalls: bootstrap.initialToolCalls,
|
|
2484
|
-
userId: uid,
|
|
2485
|
-
agentName: preferredAgentRef.current,
|
|
2486
|
-
assistantMessageId,
|
|
2487
|
-
assistantSender,
|
|
2488
|
-
threadMetadata: {
|
|
2489
|
-
name: defaultThreadName || "Main Thread"
|
|
2490
|
-
}
|
|
2491
|
-
});
|
|
2492
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
2493
|
-
await fetchAndSetThreadsState(uid, bootstrapThreadExternalId);
|
|
2494
|
-
} catch (error) {
|
|
2495
|
-
if (isAbortError(error)) return;
|
|
2496
|
-
console.error("Error bootstrapping conversation", error);
|
|
2497
|
-
const nextSpecialState = getSpecialStateFromError(error);
|
|
2498
|
-
if (nextSpecialState) {
|
|
2499
|
-
setSpecialState(nextSpecialState);
|
|
2500
|
-
setMessages([]);
|
|
2501
|
-
return;
|
|
2576
|
+
]);
|
|
2502
2577
|
}
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
role: "assistant",
|
|
2507
|
-
content: "N\xE3o foi poss\xEDvel iniciar a conversa. Tente novamente mais tarde.",
|
|
2508
|
-
timestamp: nowTs(),
|
|
2509
|
-
isStreaming: false,
|
|
2510
|
-
isComplete: true,
|
|
2511
|
-
sender: resolveAssistantFallbackSender(senderOptionsRef.current)
|
|
2512
|
-
}
|
|
2513
|
-
]);
|
|
2514
|
-
}
|
|
2515
|
-
}, [fetchAndSetThreadsState, loadThreadMessages, sendCopilotzMessage, bootstrap, defaultThreadName, getSpecialStateFromError]);
|
|
2578
|
+
},
|
|
2579
|
+
[fetchAndSetThreadsState, loadThreadMessages, sendCopilotzMessage, bootstrap, defaultThreadName, getSpecialStateFromError]
|
|
2580
|
+
);
|
|
2516
2581
|
const reset = useCallback2(() => {
|
|
2517
2582
|
messagesRequestRef.current += 1;
|
|
2518
2583
|
setThreads([]);
|
|
@@ -2561,7 +2626,10 @@ function useCopilotz({
|
|
|
2561
2626
|
const metadata = threadMetadataMap[currentThreadId];
|
|
2562
2627
|
if (!metadata) return;
|
|
2563
2628
|
if (metadata.userContext && typeof metadata.userContext === "object") {
|
|
2564
|
-
setUserContextSeed((prev) => ({
|
|
2629
|
+
setUserContextSeed((prev) => ({
|
|
2630
|
+
...prev,
|
|
2631
|
+
...metadata.userContext
|
|
2632
|
+
}));
|
|
2565
2633
|
}
|
|
2566
2634
|
}, [currentThreadId, threadMetadataMap]);
|
|
2567
2635
|
return {
|
|
@@ -2580,6 +2648,7 @@ function useCopilotz({
|
|
|
2580
2648
|
selectThread: handleSelectThread,
|
|
2581
2649
|
renameThread: handleRenameThread,
|
|
2582
2650
|
archiveThread: handleArchiveThread,
|
|
2651
|
+
updateThreadTags: handleUpdateThreadTags,
|
|
2583
2652
|
deleteThread: handleDeleteThread,
|
|
2584
2653
|
stopGeneration: handleStop,
|
|
2585
2654
|
fetchAndSetThreadsState,
|
|
@@ -2591,39 +2660,7 @@ function useCopilotz({
|
|
|
2591
2660
|
|
|
2592
2661
|
// src/CopilotzChat.tsx
|
|
2593
2662
|
import { jsx } from "react/jsx-runtime";
|
|
2594
|
-
var CopilotzChat = ({
|
|
2595
|
-
userId,
|
|
2596
|
-
userName,
|
|
2597
|
-
userAvatar,
|
|
2598
|
-
userEmail,
|
|
2599
|
-
initialContext,
|
|
2600
|
-
bootstrap,
|
|
2601
|
-
config: userConfig,
|
|
2602
|
-
callbacks: userCallbacks,
|
|
2603
|
-
customComponent,
|
|
2604
|
-
onToolOutput,
|
|
2605
|
-
onCurrentThreadIdChange,
|
|
2606
|
-
onLogout,
|
|
2607
|
-
onViewProfile,
|
|
2608
|
-
onAddMemory,
|
|
2609
|
-
onUpdateMemory,
|
|
2610
|
-
onDeleteMemory,
|
|
2611
|
-
userMenuSections,
|
|
2612
|
-
userMenuAdditionalItems,
|
|
2613
|
-
suggestions,
|
|
2614
|
-
agentOptions = [],
|
|
2615
|
-
selectedAgentId = null,
|
|
2616
|
-
onSelectAgent,
|
|
2617
|
-
participantIds,
|
|
2618
|
-
onParticipantsChange,
|
|
2619
|
-
targetAgentId = null,
|
|
2620
|
-
onTargetAgentChange,
|
|
2621
|
-
getRequestHeaders,
|
|
2622
|
-
className,
|
|
2623
|
-
eventInterceptor,
|
|
2624
|
-
runErrorInterceptor,
|
|
2625
|
-
renderSpecialState
|
|
2626
|
-
}) => {
|
|
2663
|
+
var CopilotzChat = ({ userId, userName, userAvatar, userEmail, initialContext, bootstrap, config: userConfig, callbacks: userCallbacks, customComponent, onToolOutput, onCurrentThreadIdChange, onLogout, onViewProfile, onAddMemory, onUpdateMemory, onDeleteMemory, userMenuSections, userMenuAdditionalItems, suggestions, agentOptions = [], selectedAgentId = null, onSelectAgent, participantIds, onParticipantsChange, targetAgentId = null, onTargetAgentChange, getRequestHeaders, className, eventInterceptor, runErrorInterceptor, renderSpecialState }) => {
|
|
2627
2664
|
const selectedAgent = agentOptions.find((agent) => agent.id === selectedAgentId) || null;
|
|
2628
2665
|
const participantAgentIds = useMemo(() => {
|
|
2629
2666
|
if (!participantIds || participantIds.length === 0) return null;
|
|
@@ -2634,26 +2671,7 @@ var CopilotzChat = ({
|
|
|
2634
2671
|
if (!targetAgentId) return null;
|
|
2635
2672
|
return targetAgentId;
|
|
2636
2673
|
}, [targetAgentId]);
|
|
2637
|
-
const {
|
|
2638
|
-
messages,
|
|
2639
|
-
isMessagesLoading,
|
|
2640
|
-
isLoadingOlderMessages,
|
|
2641
|
-
messagePageInfo,
|
|
2642
|
-
threads,
|
|
2643
|
-
currentThreadId,
|
|
2644
|
-
isStreaming,
|
|
2645
|
-
specialState,
|
|
2646
|
-
clearSpecialState,
|
|
2647
|
-
userContextSeed,
|
|
2648
|
-
sendMessage,
|
|
2649
|
-
createThread,
|
|
2650
|
-
selectThread,
|
|
2651
|
-
renameThread,
|
|
2652
|
-
archiveThread,
|
|
2653
|
-
deleteThread: deleteThread2,
|
|
2654
|
-
stopGeneration,
|
|
2655
|
-
loadOlderMessages
|
|
2656
|
-
} = useCopilotz({
|
|
2674
|
+
const { messages, isMessagesLoading, isLoadingOlderMessages, messagePageInfo, threads, currentThreadId, isStreaming, specialState, clearSpecialState, userContextSeed, sendMessage, createThread, selectThread, renameThread, archiveThread, updateThreadTags, deleteThread: deleteThread2, stopGeneration, loadOlderMessages } = useCopilotz({
|
|
2657
2675
|
userId,
|
|
2658
2676
|
userName,
|
|
2659
2677
|
userAvatar,
|
|
@@ -2674,17 +2692,7 @@ var CopilotzChat = ({
|
|
|
2674
2692
|
onCurrentThreadIdChange?.(currentThreadId);
|
|
2675
2693
|
}, [currentThreadId, onCurrentThreadIdChange]);
|
|
2676
2694
|
const chatCallbacks = useMemo(() => {
|
|
2677
|
-
const {
|
|
2678
|
-
onSendMessage: _1,
|
|
2679
|
-
onStopGeneration: _2,
|
|
2680
|
-
onCreateThread: _3,
|
|
2681
|
-
onSelectThread: _4,
|
|
2682
|
-
onRenameThread: _5,
|
|
2683
|
-
onArchiveThread: _6,
|
|
2684
|
-
onDeleteThread: _7,
|
|
2685
|
-
onCopyMessage: _8,
|
|
2686
|
-
...restUserCallbacks
|
|
2687
|
-
} = userCallbacks || {};
|
|
2695
|
+
const { onSendMessage: _1, onStopGeneration: _2, onCreateThread: _3, onSelectThread: _4, onRenameThread: _5, onArchiveThread: _6, onDeleteThread: _7, onUpdateThreadTags: _8, onCopyMessage: _9, ...restUserCallbacks } = userCallbacks || {};
|
|
2688
2696
|
return {
|
|
2689
2697
|
...restUserCallbacks,
|
|
2690
2698
|
onSendMessage: (content, attachments) => {
|
|
@@ -2711,6 +2719,10 @@ var CopilotzChat = ({
|
|
|
2711
2719
|
void archiveThread(threadId);
|
|
2712
2720
|
userCallbacks?.onArchiveThread?.(threadId);
|
|
2713
2721
|
},
|
|
2722
|
+
onUpdateThreadTags: (threadId, tags) => {
|
|
2723
|
+
void updateThreadTags(threadId, tags);
|
|
2724
|
+
userCallbacks?.onUpdateThreadTags?.(threadId, tags);
|
|
2725
|
+
},
|
|
2714
2726
|
onDeleteThread: (threadId) => {
|
|
2715
2727
|
void deleteThread2(threadId);
|
|
2716
2728
|
userCallbacks?.onDeleteThread?.(threadId);
|
|
@@ -2726,18 +2738,7 @@ var CopilotzChat = ({
|
|
|
2726
2738
|
onLogout,
|
|
2727
2739
|
onViewProfile
|
|
2728
2740
|
};
|
|
2729
|
-
}, [
|
|
2730
|
-
sendMessage,
|
|
2731
|
-
stopGeneration,
|
|
2732
|
-
createThread,
|
|
2733
|
-
selectThread,
|
|
2734
|
-
renameThread,
|
|
2735
|
-
archiveThread,
|
|
2736
|
-
deleteThread2,
|
|
2737
|
-
userCallbacks,
|
|
2738
|
-
onLogout,
|
|
2739
|
-
onViewProfile
|
|
2740
|
-
]);
|
|
2741
|
+
}, [sendMessage, stopGeneration, createThread, selectThread, renameThread, archiveThread, updateThreadTags, deleteThread2, userCallbacks, onLogout, onViewProfile]);
|
|
2741
2742
|
const mergedConfig = useMemo(() => {
|
|
2742
2743
|
const base = userConfig || {};
|
|
2743
2744
|
if (!customComponent) {
|
|
@@ -2754,53 +2755,25 @@ var CopilotzChat = ({
|
|
|
2754
2755
|
}, [userConfig, customComponent]);
|
|
2755
2756
|
const effectiveUserName = userName || userId;
|
|
2756
2757
|
const effectiveUserAvatar = userAvatar;
|
|
2757
|
-
const userProp = useMemo(
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2758
|
+
const userProp = useMemo(
|
|
2759
|
+
() => ({
|
|
2760
|
+
id: userId,
|
|
2761
|
+
name: effectiveUserName,
|
|
2762
|
+
email: userEmail,
|
|
2763
|
+
avatar: effectiveUserAvatar
|
|
2764
|
+
}),
|
|
2765
|
+
[userId, effectiveUserName, userEmail, effectiveUserAvatar]
|
|
2766
|
+
);
|
|
2767
|
+
const assistantProp = useMemo(
|
|
2768
|
+
() => ({
|
|
2769
|
+
name: userConfig?.branding?.title,
|
|
2770
|
+
avatar: userConfig?.branding?.avatar,
|
|
2771
|
+
description: userConfig?.branding?.subtitle
|
|
2772
|
+
}),
|
|
2773
|
+
[userConfig?.branding?.title, userConfig?.branding?.avatar, userConfig?.branding?.subtitle]
|
|
2774
|
+
);
|
|
2772
2775
|
const specialStateContent = specialState ? renderSpecialState?.(specialState, { clear: clearSpecialState }) : null;
|
|
2773
|
-
return /* @__PURE__ */ jsx(ChatUserContextProvider, { initial: userContextSeed, children: specialStateContent ?? /* @__PURE__ */ jsx(
|
|
2774
|
-
ChatUI,
|
|
2775
|
-
{
|
|
2776
|
-
messages,
|
|
2777
|
-
isMessagesLoading,
|
|
2778
|
-
isLoadingOlderMessages,
|
|
2779
|
-
hasMoreMessagesBefore: messagePageInfo.hasMoreBefore,
|
|
2780
|
-
onLoadOlderMessages: loadOlderMessages,
|
|
2781
|
-
threads,
|
|
2782
|
-
currentThreadId,
|
|
2783
|
-
config: mergedConfig,
|
|
2784
|
-
callbacks: chatCallbacks,
|
|
2785
|
-
isGenerating: isStreaming,
|
|
2786
|
-
suggestions,
|
|
2787
|
-
agentOptions,
|
|
2788
|
-
selectedAgentId,
|
|
2789
|
-
onSelectAgent,
|
|
2790
|
-
participantIds,
|
|
2791
|
-
onParticipantsChange,
|
|
2792
|
-
targetAgentId,
|
|
2793
|
-
onTargetAgentChange,
|
|
2794
|
-
user: userProp,
|
|
2795
|
-
assistant: assistantProp,
|
|
2796
|
-
onAddMemory,
|
|
2797
|
-
onUpdateMemory,
|
|
2798
|
-
onDeleteMemory,
|
|
2799
|
-
userMenuSections,
|
|
2800
|
-
userMenuAdditionalItems,
|
|
2801
|
-
className
|
|
2802
|
-
}
|
|
2803
|
-
) });
|
|
2776
|
+
return /* @__PURE__ */ jsx(ChatUserContextProvider, { initial: userContextSeed, children: specialStateContent ?? /* @__PURE__ */ jsx(ChatUI, { messages, isMessagesLoading, isLoadingOlderMessages, hasMoreMessagesBefore: messagePageInfo.hasMoreBefore, onLoadOlderMessages: loadOlderMessages, threads, currentThreadId, config: mergedConfig, callbacks: chatCallbacks, isGenerating: isStreaming, suggestions, agentOptions, selectedAgentId, onSelectAgent, participantIds, onParticipantsChange, targetAgentId, onTargetAgentChange, user: userProp, assistant: assistantProp, onAddMemory, onUpdateMemory, onDeleteMemory, userMenuSections, userMenuAdditionalItems, className }) });
|
|
2804
2777
|
};
|
|
2805
2778
|
export {
|
|
2806
2779
|
CopilotzChat,
|