@copilotz/chat-adapter 0.9.23 → 0.9.24

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 CHANGED
@@ -629,6 +629,9 @@ async function fetchThreadMessagesPage(threadId, options, getRequestHeaders) {
629
629
  if (options?.before) {
630
630
  params.set("before", options.before);
631
631
  }
632
+ if (options?.after) {
633
+ params.set("after", options.after);
634
+ }
632
635
  const res = await fetch(
633
636
  apiUrl(`/v1/threads/${threadId}/messages?${params.toString()}`),
634
637
  {
@@ -1636,6 +1639,61 @@ var createEmptyMessagePageInfo = () => ({
1636
1639
  oldestMessageId: null,
1637
1640
  newestMessageId: null
1638
1641
  });
1642
+ var stringifyForCompare = (value) => {
1643
+ if (value === void 0) return "";
1644
+ try {
1645
+ return JSON.stringify(value) ?? "";
1646
+ } catch {
1647
+ return String(value);
1648
+ }
1649
+ };
1650
+ var getMessageSignature = (message) => JSON.stringify({
1651
+ id: message.id,
1652
+ role: message.role,
1653
+ content: message.content ?? "",
1654
+ isStreaming: message.isStreaming === true,
1655
+ isComplete: message.isComplete === true,
1656
+ attachments: stringifyForCompare(message.attachments),
1657
+ activity: stringifyForCompare(message.activity),
1658
+ metadata: stringifyForCompare(message.metadata),
1659
+ sender: message.sender ? {
1660
+ id: message.sender.id,
1661
+ type: message.sender.type,
1662
+ name: message.sender.name,
1663
+ agentId: message.sender.agentId
1664
+ } : null
1665
+ });
1666
+ var reconcileThreadMessages = (currentMessages, freshMessages) => {
1667
+ if (freshMessages.length === 0) {
1668
+ return { messages: currentMessages, changed: false };
1669
+ }
1670
+ if (currentMessages.length === 0) {
1671
+ return { messages: freshMessages, changed: true };
1672
+ }
1673
+ const freshById = new Map(freshMessages.map((message) => [message.id, message]));
1674
+ const seen = /* @__PURE__ */ new Set();
1675
+ let changed = false;
1676
+ const nextMessages = currentMessages.map((message) => {
1677
+ const fresh = freshById.get(message.id);
1678
+ if (!fresh) return message;
1679
+ seen.add(message.id);
1680
+ if (getMessageSignature(message) === getMessageSignature(fresh)) {
1681
+ return message;
1682
+ }
1683
+ changed = true;
1684
+ return fresh;
1685
+ });
1686
+ const appended = freshMessages.filter((message) => !seen.has(message.id));
1687
+ if (appended.length > 0) {
1688
+ changed = true;
1689
+ nextMessages.push(...appended);
1690
+ nextMessages.sort((a, b) => {
1691
+ const timestampDelta = (a.timestamp ?? 0) - (b.timestamp ?? 0);
1692
+ return timestampDelta !== 0 ? timestampDelta : a.id.localeCompare(b.id);
1693
+ });
1694
+ }
1695
+ return changed ? { messages: nextMessages, changed } : { messages: currentMessages, changed: false };
1696
+ };
1639
1697
  var createPendingAssistantActivity = () => ({
1640
1698
  items: [
1641
1699
  {
@@ -1895,6 +1953,34 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
1895
1953
  },
1896
1954
  [getRequestHeaders, prepareThreadMessages]
1897
1955
  );
1956
+ const refreshThreadMessages = useCallback2(
1957
+ async (threadId) => {
1958
+ const requestId = messagesRequestRef.current;
1959
+ try {
1960
+ const page = await fetchThreadMessagesPage(threadId, { limit: THREAD_MESSAGES_PAGE_SIZE }, getRequestHeaders);
1961
+ const { viewMessages, toolResultUpdates } = await prepareThreadMessages(page.data);
1962
+ if (messagesRequestRef.current !== requestId) return;
1963
+ persistedToolUpdatesRef.current = [
1964
+ ...persistedToolUpdatesRef.current,
1965
+ ...toolResultUpdates.filter((update) => !persistedToolUpdatesRef.current.some((current) => matchesToolResultUpdate(current, update)))
1966
+ ];
1967
+ const hydratedMessages = mergePersistedToolResults(viewMessages, persistedToolUpdatesRef.current);
1968
+ setMessages((prev) => {
1969
+ const reconciled = reconcileThreadMessages(prev, hydratedMessages);
1970
+ return reconciled.changed ? reconciled.messages : prev;
1971
+ });
1972
+ setMessagePageInfo((prev) => ({
1973
+ hasMoreBefore: prev.hasMoreBefore || page.pageInfo.hasMoreBefore,
1974
+ oldestMessageId: prev.oldestMessageId ?? page.pageInfo.oldestMessageId,
1975
+ newestMessageId: page.pageInfo.newestMessageId ?? prev.newestMessageId
1976
+ }));
1977
+ } catch (error) {
1978
+ if (isAbortError(error)) return;
1979
+ console.error(`Error refreshing messages for thread ${threadId}`, error);
1980
+ }
1981
+ },
1982
+ [getRequestHeaders, prepareThreadMessages]
1983
+ );
1898
1984
  const loadOlderMessages = useCallback2(async () => {
1899
1985
  const threadId = currentThreadIdRef.current;
1900
1986
  const pageInfo = messagePageInfoRef.current;
@@ -1939,6 +2025,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
1939
2025
  void (async () => {
1940
2026
  let delayMs = 2e3;
1941
2027
  let attempts = 0;
2028
+ await refreshThreadMessages(threadId);
1942
2029
  while (recoveryPollGenerationRef.current === generation) {
1943
2030
  await new Promise((resolve) => setTimeout(resolve, delayMs));
1944
2031
  if (recoveryPollGenerationRef.current !== generation) return;
@@ -1949,14 +2036,14 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
1949
2036
  if (activity.status === "running") {
1950
2037
  attempts += 1;
1951
2038
  if (attempts % 3 === 0) {
1952
- await loadThreadMessages(threadId);
2039
+ await refreshThreadMessages(threadId);
1953
2040
  }
1954
2041
  if (attempts >= 15) {
1955
2042
  delayMs = 5e3;
1956
2043
  }
1957
2044
  continue;
1958
2045
  }
1959
- await loadThreadMessages(threadId);
2046
+ await refreshThreadMessages(threadId);
1960
2047
  finalizeStreamingPlaceholders(activity.status);
1961
2048
  return;
1962
2049
  } catch (error) {
@@ -1969,7 +2056,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
1969
2056
  }
1970
2057
  })();
1971
2058
  },
1972
- [finalizeStreamingPlaceholders, getRequestHeaders, loadThreadMessages]
2059
+ [finalizeStreamingPlaceholders, getRequestHeaders, refreshThreadMessages]
1973
2060
  );
1974
2061
  const refreshThreadActivity = useCallback2(
1975
2062
  async (threadId) => {
@@ -1982,14 +2069,14 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
1982
2069
  }
1983
2070
  setIsRecoveringStream(false);
1984
2071
  if (activity.status === "failed") {
1985
- await loadThreadMessages(threadId);
2072
+ await refreshThreadMessages(threadId);
1986
2073
  }
1987
2074
  } catch (error) {
1988
2075
  if (isAbortError(error)) return;
1989
2076
  console.warn("Unable to load Copilotz thread activity", error);
1990
2077
  }
1991
2078
  },
1992
- [getRequestHeaders, loadThreadMessages, startThreadActivityRecovery]
2079
+ [getRequestHeaders, refreshThreadMessages, startThreadActivityRecovery]
1993
2080
  );
1994
2081
  const handleSelectThread = useCallback2(
1995
2082
  async (threadId) => {
@@ -2539,7 +2626,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
2539
2626
  startThreadActivityRecovery(activityThreadId);
2540
2627
  } else if (streamError || activity.status === "failed") {
2541
2628
  setIsRecoveringStream(false);
2542
- await loadThreadMessages(activityThreadId);
2629
+ await refreshThreadMessages(activityThreadId);
2543
2630
  }
2544
2631
  }
2545
2632
  } catch (activityError) {
@@ -2558,7 +2645,7 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
2558
2645
  }
2559
2646
  return currentAssistantId;
2560
2647
  },
2561
- [applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, fetchAndSetThreadsState, finalizeStreamingPlaceholders, getRequestHeaders, loadThreadMessages, startThreadActivityRecovery]
2648
+ [applyEventInterceptor, handleStreamMessageEvent, handleStreamAssetEvent, fetchAndSetThreadsState, finalizeStreamingPlaceholders, getRequestHeaders, refreshThreadMessages, startThreadActivityRecovery]
2562
2649
  );
2563
2650
  const handleSendMessage = useCallback2(
2564
2651
  async (content, attachments = []) => {
@@ -2869,7 +2956,7 @@ var CopilotzChat = ({ userId, userName, userAvatar, userEmail, initialContext, b
2869
2956
  if (!targetAgentId) return null;
2870
2957
  return targetAgentId;
2871
2958
  }, [targetAgentId]);
2872
- const { messages, isMessagesLoading, isLoadingOlderMessages, messagePageInfo, threads, currentThreadId, isStreaming, activityNotice, specialState, clearSpecialState, userContextSeed, sendMessage, createThread, selectThread, renameThread, archiveThread, updateThreadTags, editMessage, deleteThread: deleteThread2, stopGeneration, loadOlderMessages } = useCopilotz({
2959
+ const { messages, isMessagesLoading, isLoadingOlderMessages, messagePageInfo, threads, currentThreadId, isStreaming, isRecoveringStream, activityNotice, specialState, clearSpecialState, userContextSeed, sendMessage, createThread, selectThread, renameThread, archiveThread, updateThreadTags, editMessage, deleteThread: deleteThread2, stopGeneration, loadOlderMessages } = useCopilotz({
2873
2960
  userId,
2874
2961
  userName,
2875
2962
  userAvatar,
@@ -2970,7 +3057,7 @@ var CopilotzChat = ({ userId, userName, userAvatar, userEmail, initialContext, b
2970
3057
  [userConfig?.branding?.title, userConfig?.branding?.avatar, userConfig?.branding?.subtitle]
2971
3058
  );
2972
3059
  const specialStateContent = specialState ? renderSpecialState?.(specialState, { clear: clearSpecialState }) : null;
2973
- return /* @__PURE__ */ jsx(ChatUserContextProvider, { initial: userContextSeed, children: specialStateContent ?? /* @__PURE__ */ jsx(ChatUI, { messages, isMessagesLoading, isLoadingOlderMessages, hasMoreMessagesBefore: messagePageInfo.hasMoreBefore, activityNotice, 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 }) });
3060
+ return /* @__PURE__ */ jsx(ChatUserContextProvider, { initial: userContextSeed, children: specialStateContent ?? /* @__PURE__ */ jsx(ChatUI, { messages, isMessagesLoading, isLoadingOlderMessages, hasMoreMessagesBefore: messagePageInfo.hasMoreBefore, activityNotice, isBackgroundRefreshingMessages: isRecoveringStream, 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 }) });
2974
3061
  };
2975
3062
  export {
2976
3063
  CopilotzChat,