@copilotkit/react-core 1.73.3 → 1.75.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.
@@ -1633,6 +1633,10 @@ function useRenderToolCall() {
1633
1633
  return renderToolCall;
1634
1634
  }
1635
1635
 
1636
+ //#endregion
1637
+ //#region package.json
1638
+ var version = "1.75.0";
1639
+
1636
1640
  //#endregion
1637
1641
  //#region src/v2/components/CopilotKitInspector.tsx
1638
1642
  const CopilotKitInspector = ({ core, openRequest, onVisibilityChange }) => {
@@ -1655,7 +1659,11 @@ const CopilotKitInspector = ({ core, openRequest, onVisibilityChange }) => {
1655
1659
  if (!mounted || !mountRef.current) return;
1656
1660
  mod.defineWebInspector?.();
1657
1661
  inspector = mountRef.current.ownerDocument.createElement(mod.WEB_INSPECTOR_TAG);
1658
- mod.configureWebInspectorElement(inspector, latestCoreRef.current);
1662
+ mod.configureWebInspectorElement(inspector, latestCoreRef.current, {
1663
+ development: process.env.NODE_ENV === "development",
1664
+ framework: "react",
1665
+ sdkVersion: version
1666
+ });
1659
1667
  inspector.addEventListener("cpk-inspector-visibility-change", handleVisibilityChange);
1660
1668
  mountRef.current.appendChild(inspector);
1661
1669
  inspectorRef.current = inspector;
@@ -3860,8 +3868,8 @@ function useRenderCustomMessages() {
3860
3868
  if (aHasAgent === (b.agentId !== void 0)) return 0;
3861
3869
  return aHasAgent ? -1 : 1;
3862
3870
  });
3871
+ if (!customMessageRenderers.length) return null;
3863
3872
  return function(params) {
3864
- if (!customMessageRenderers.length) return null;
3865
3873
  const { message, position } = params;
3866
3874
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3867
3875
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
@@ -6356,7 +6364,7 @@ function BoundInspectorButton({ inspectorButton, messageId, openInspector, ...pr
6356
6364
  })
6357
6365
  });
6358
6366
  }
6359
- function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, inspectorButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
6367
+ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, inspectorButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
6360
6368
  useKatexStyles();
6361
6369
  const { isInspectorEnabled, openInspector } = useCopilotKitInspector();
6362
6370
  const shortcutsHidden = useInspectorShortcutsHidden();
@@ -6392,7 +6400,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp,
6392
6400
  messages
6393
6401
  });
6394
6402
  const hasContent = !!(message.content && message.content.trim().length > 0);
6395
- const isLatestAssistantMessage = message.role === "assistant" && messages?.[messages.length - 1]?.id === message.id;
6403
+ const isLatestAssistantMessage = message.role === "assistant" && (isLatest ?? messages?.[messages.length - 1]?.id === message.id);
6396
6404
  const shouldShowToolbar = toolbarVisible && (hasContent || showInspectorShortcut) && !(isRunning && isLatestAssistantMessage);
6397
6405
  if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6398
6406
  "data-copilotkit": true,
@@ -6906,8 +6914,8 @@ function formatDuration(seconds) {
6906
6914
  if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
6907
6915
  return `${mins}m ${secs}s`;
6908
6916
  }
6909
- function CopilotChatReasoningMessage({ message, messages, isRunning, header, contentView, toggle, children, className, ...props }) {
6910
- const isLatest = messages?.[messages.length - 1]?.id === message.id;
6917
+ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: isLatestProp, header, contentView, toggle, children, className, ...props }) {
6918
+ const isLatest = isLatestProp ?? messages?.[messages.length - 1]?.id === message.id;
6911
6919
  const isStreaming = !!(isRunning && isLatest);
6912
6920
  const hasContent = !!(message.content && message.content.length > 0);
6913
6921
  const startTimeRef = (0, react.useRef)(null);
@@ -7132,6 +7140,32 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
7132
7140
  */
7133
7141
  const ScrollElementContext = react.default.createContext(null);
7134
7142
 
7143
+ //#endregion
7144
+ //#region src/v2/components/chat/scroll-pinned-context.ts
7145
+ /**
7146
+ * True while the pin-to-bottom behaviour is actively following the bottom of
7147
+ * the thread — i.e. `use-stick-to-bottom` will animate the scroll position to
7148
+ * the bottom the next time the content grows.
7149
+ *
7150
+ * Only CopilotChatView's pin-to-bottom branch provides this. The other scroll
7151
+ * modes leave it `false`, which is correct: nothing else writes the scroll
7152
+ * position on its own, so no one is competing with the virtualizer.
7153
+ *
7154
+ * Why this exists: the virtualizer and `use-stick-to-bottom` both write
7155
+ * `scrollTop` on the same element. The virtualizer writes it to compensate
7156
+ * when a row above the viewport turns out taller than its estimate, so that
7157
+ * what the reader is looking at does not shift. That compensation is essential
7158
+ * while the reader is scrolled up — and pointless while pinned to the bottom,
7159
+ * because the pin is about to move the scroll position anyway. Worse than
7160
+ * pointless: the compensation changes the virtual container's height, the pin
7161
+ * reads that as content growth and animates, the animation brings unmeasured
7162
+ * rows into view, they measure, and the two keep shoving each other.
7163
+ *
7164
+ * Consumed by CopilotChatMessageView to stand the virtualizer down while the
7165
+ * pin owns the scroll position.
7166
+ */
7167
+ const ScrollPinnedContext = react.default.createContext(false);
7168
+
7135
7169
  //#endregion
7136
7170
  //#region src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx
7137
7171
  /**
@@ -7276,24 +7310,31 @@ const INTELLIGENCE_TURN_HEAD = "__cpk_turn_head__";
7276
7310
  * emits exactly one `IntelligenceIndicator` per entry, keyed by the turn id and
7277
7311
  * positioned at the anchor; the per-turn key also lets every past turn keep its
7278
7312
  * own indicator in scroll-back.
7313
+ *
7314
+ * `visibleMessages` is what actually renders, when that differs from
7315
+ * `messages` (the chat's `transformMessages`). Turns are still read from the
7316
+ * full list, so hiding a user message does not merge its turn into the one
7317
+ * before it, and anchors are only chosen among visible messages. A message the
7318
+ * transform built itself joins the turn of the visible message before it.
7279
7319
  */
7280
- function getIntelligenceTurnAnchors(messages) {
7281
- const anchors = /* @__PURE__ */ new Map();
7320
+ function getIntelligenceTurnAnchors(messages, visibleMessages = messages) {
7321
+ const turnOfMessage = /* @__PURE__ */ new Map();
7282
7322
  let turnId = INTELLIGENCE_TURN_HEAD;
7283
- let anchorId = null;
7284
- const commit = () => {
7285
- if (anchorId !== null) anchors.set(anchorId, turnId);
7286
- anchorId = null;
7287
- };
7288
7323
  for (const m of messages) {
7289
- if (m.role === "user") {
7290
- commit();
7291
- turnId = m.id;
7292
- continue;
7324
+ if (m.role === "user") turnId = m.id;
7325
+ turnOfMessage.set(m.id, turnId);
7326
+ }
7327
+ const anchors = /* @__PURE__ */ new Map();
7328
+ const anchoredTurns = /* @__PURE__ */ new Set();
7329
+ let currentTurn = INTELLIGENCE_TURN_HEAD;
7330
+ for (const m of visibleMessages) {
7331
+ currentTurn = turnOfMessage.get(m.id) ?? currentTurn;
7332
+ if (m.role === "user") continue;
7333
+ if (!anchoredTurns.has(currentTurn) && messageHasMatchingToolCall(m)) {
7334
+ anchors.set(m.id, currentTurn);
7335
+ anchoredTurns.add(currentTurn);
7293
7336
  }
7294
- if (anchorId === null && messageHasMatchingToolCall(m)) anchorId = m.id;
7295
7337
  }
7296
- commit();
7297
7338
  return anchors;
7298
7339
  }
7299
7340
  /**
@@ -7439,11 +7480,12 @@ function resolveSlotComponent(slot, DefaultComponent) {
7439
7480
  /**
7440
7481
  * Memoized wrapper for assistant messages to prevent re-renders when other messages change.
7441
7482
  */
7442
- const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, AssistantMessageComponent, slotProps }) {
7483
+ const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, isLatest, AssistantMessageComponent, slotProps }) {
7443
7484
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssistantMessageComponent, {
7444
7485
  message,
7445
7486
  messages,
7446
7487
  isRunning,
7488
+ isLatest,
7447
7489
  ...slotProps
7448
7490
  });
7449
7491
  }, (prevProps, nextProps) => {
@@ -7465,7 +7507,7 @@ const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMe
7465
7507
  if (prevToolResults.length !== nextToolResults.length) return false;
7466
7508
  for (let i = 0; i < prevToolResults.length; i++) if (prevToolResults[i].content !== nextToolResults[i].content) return false;
7467
7509
  }
7468
- if (nextProps.messages[nextProps.messages.length - 1]?.id === nextProps.message.id && prevProps.isRunning !== nextProps.isRunning) return false;
7510
+ if ((prevProps.isRunning && prevProps.isLatest) !== (nextProps.isRunning && nextProps.isLatest)) return false;
7469
7511
  if (prevProps.AssistantMessageComponent !== nextProps.AssistantMessageComponent) return false;
7470
7512
  if (prevProps.slotProps !== nextProps.slotProps) return false;
7471
7513
  return true;
@@ -7499,20 +7541,19 @@ const MemoizedActivityMessage = react.default.memo(function MemoizedActivityMess
7499
7541
  /**
7500
7542
  * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.
7501
7543
  */
7502
- const MemoizedReasoningMessage = react.default.memo(function MemoizedReasoningMessage({ message, messages, isRunning, ReasoningMessageComponent, slotProps }) {
7544
+ const MemoizedReasoningMessage = react.default.memo(function MemoizedReasoningMessage({ message, messages, isRunning, isLatest, ReasoningMessageComponent, slotProps }) {
7503
7545
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningMessageComponent, {
7504
7546
  message,
7505
7547
  messages,
7506
7548
  isRunning,
7549
+ isLatest,
7507
7550
  ...slotProps
7508
7551
  });
7509
7552
  }, (prevProps, nextProps) => {
7510
7553
  if (prevProps.message.id !== nextProps.message.id) return false;
7511
7554
  if (prevProps.message.content !== nextProps.message.content) return false;
7512
- const prevIsLatest = prevProps.messages[prevProps.messages.length - 1]?.id === prevProps.message.id;
7513
- const nextIsLatest = nextProps.messages[nextProps.messages.length - 1]?.id === nextProps.message.id;
7514
- if (prevIsLatest !== nextIsLatest) return false;
7515
- if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning) return false;
7555
+ if (prevProps.isLatest !== nextProps.isLatest) return false;
7556
+ if (nextProps.isLatest && prevProps.isRunning !== nextProps.isRunning) return false;
7516
7557
  if (prevProps.ReasoningMessageComponent !== nextProps.ReasoningMessageComponent) return false;
7517
7558
  if (prevProps.slotProps !== nextProps.slotProps) return false;
7518
7559
  return true;
@@ -7596,7 +7637,8 @@ function deduplicateMessages(messages) {
7596
7637
  return [...acc.values()];
7597
7638
  }
7598
7639
  const VIRTUALIZE_THRESHOLD = 50;
7599
- function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, children, className, ...props }) {
7640
+ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, transformMessages, children, className, ...props }) {
7641
+ const isPinnedToBottom = (0, react.useContext)(ScrollPinnedContext);
7600
7642
  const renderCustomMessage = useRenderCustomMessages();
7601
7643
  const { renderActivityMessage } = useRenderActivityMessage();
7602
7644
  const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
@@ -7628,13 +7670,27 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7628
7670
  return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
7629
7671
  };
7630
7672
  const deduplicatedMessages = (0, react.useMemo)(() => deduplicateMessages(messages), [messages]);
7673
+ const renderedMessages = (0, react.useMemo)(() => transformMessages ? transformMessages(deduplicatedMessages) : deduplicatedMessages, [deduplicatedMessages, transformMessages]);
7674
+ const latestRenderedId = renderedMessages[renderedMessages.length - 1]?.id;
7675
+ const transformDuplicateId = (0, react.useMemo)(() => {
7676
+ if (process.env.NODE_ENV === "production" || !transformMessages) return;
7677
+ const seen = /* @__PURE__ */ new Set();
7678
+ for (const message of renderedMessages) {
7679
+ if (seen.has(message.id)) return message.id;
7680
+ seen.add(message.id);
7681
+ }
7682
+ }, [renderedMessages, transformMessages]);
7683
+ (0, react.useEffect)(() => {
7684
+ if (transformDuplicateId === void 0) return;
7685
+ console.warn(`[CopilotKit] CopilotChatMessageView: \`transformMessages\` returned more than one message with id "${transformDuplicateId}". Return each id at most once; a message you create needs its own id, stable across renders.`);
7686
+ }, [transformDuplicateId]);
7631
7687
  const rowKeyStoreRef = (0, react.useRef)(null);
7632
7688
  rowKeyStoreRef.current ??= (0, _copilotkit_shared.createRowKeyStore)();
7633
7689
  const rowKeyStore = rowKeyStoreRef.current;
7634
- const rowRenderKeys = (0, react.useMemo)(() => (0, _copilotkit_shared.resolveRowRenderKeysById)(rowKeyStore, deduplicatedMessages), [rowKeyStore, deduplicatedMessages]);
7690
+ const rowRenderKeys = (0, react.useMemo)(() => (0, _copilotkit_shared.resolveRowRenderKeysById)(rowKeyStore, renderedMessages), [rowKeyStore, renderedMessages]);
7635
7691
  (0, react.useLayoutEffect)(() => {
7636
- (0, _copilotkit_shared.commitRowKeyStore)(rowKeyStore, deduplicatedMessages);
7637
- }, [rowKeyStore, deduplicatedMessages]);
7692
+ (0, _copilotkit_shared.commitRowKeyStore)(rowKeyStore, renderedMessages);
7693
+ }, [rowKeyStore, renderedMessages]);
7638
7694
  if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Merged ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
7639
7695
  const { Component: AssistantComponent, slotProps: assistantSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
7640
7696
  const agentId = config?.agentId;
@@ -7668,27 +7724,72 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7668
7724
  (0, react.useEffect)(() => {
7669
7725
  if (process.env.NODE_ENV !== "production" && scrollElementFromCtx && scrollElementFromCtx.clientHeight === 0) console.warn("[CopilotKit] Chat scroll container has clientHeight=0 — virtualization disabled. Ensure the chat is rendered in a visible container with a non-zero height.");
7670
7726
  }, [scrollElementFromCtx]);
7671
- const shouldVirtualize = !!scrollElement && !children && deduplicatedMessages.length > VIRTUALIZE_THRESHOLD;
7727
+ const shouldVirtualize = !!scrollElement && !children && renderedMessages.length > VIRTUALIZE_THRESHOLD;
7728
+ const childrenDisabledVirtualization = !!children && !!scrollElement && renderedMessages.length > VIRTUALIZE_THRESHOLD;
7729
+ const warnedChildrenRef = (0, react.useRef)(false);
7730
+ (0, react.useEffect)(() => {
7731
+ if (process.env.NODE_ENV === "production" || !childrenDisabledVirtualization || warnedChildrenRef.current) return;
7732
+ warnedChildrenRef.current = true;
7733
+ console.warn(`[CopilotKit] CopilotChatMessageView: the \`children\` render prop disables virtualization, so all ${renderedMessages.length} messages are mounted. ` + (transformMessages ? "`transformMessages` keeps virtualization on by itself; drop `children` to use it." : "To reshape the list and keep virtualization, use `transformMessages` instead."));
7734
+ }, [
7735
+ childrenDisabledVirtualization,
7736
+ renderedMessages.length,
7737
+ transformMessages
7738
+ ]);
7739
+ const measuredRef = react.default.useRef({
7740
+ total: 0,
7741
+ sizes: /* @__PURE__ */ new Map()
7742
+ });
7743
+ const firstMessageId = deduplicatedMessages[0]?.id;
7744
+ const measuredThreadRef = react.default.useRef(firstMessageId);
7745
+ if (measuredThreadRef.current !== firstMessageId) {
7746
+ measuredThreadRef.current = firstMessageId;
7747
+ measuredRef.current = {
7748
+ total: 0,
7749
+ sizes: /* @__PURE__ */ new Map()
7750
+ };
7751
+ }
7752
+ const estimateRowSize = react.default.useCallback(() => {
7753
+ const { total, sizes } = measuredRef.current;
7754
+ return sizes.size > 0 ? Math.max(1, Math.round(total / sizes.size)) : 100;
7755
+ }, []);
7756
+ const measureRowElement = react.default.useCallback((el) => {
7757
+ const height = el?.getBoundingClientRect().height ?? 0;
7758
+ const index = Number(el?.dataset?.index);
7759
+ if (height > 0 && Number.isInteger(index)) {
7760
+ const { total, sizes } = measuredRef.current;
7761
+ measuredRef.current.total = total - (sizes.get(index) ?? 0) + height;
7762
+ sizes.set(index, height);
7763
+ }
7764
+ return height;
7765
+ }, []);
7766
+ const isPinnedToBottomRef = react.default.useRef(isPinnedToBottom);
7767
+ const shouldAdjustScrollOnResize = react.default.useCallback((item, _delta, instance) => {
7768
+ if (isPinnedToBottomRef.current) return false;
7769
+ const scrollAdjustments = instance.scrollAdjustments ?? 0;
7770
+ return item.start < (instance.scrollOffset ?? 0) + scrollAdjustments;
7771
+ }, []);
7672
7772
  const virtualizer = (0, _tanstack_react_virtual.useVirtualizer)({
7673
- count: shouldVirtualize ? deduplicatedMessages.length : 0,
7773
+ count: shouldVirtualize ? renderedMessages.length : 0,
7674
7774
  getScrollElement: () => scrollElement,
7675
- estimateSize: () => 100,
7775
+ estimateSize: estimateRowSize,
7676
7776
  overscan: 5,
7677
- measureElement: (el) => el?.getBoundingClientRect().height ?? 0,
7777
+ measureElement: measureRowElement,
7678
7778
  initialRect: {
7679
7779
  width: 0,
7680
7780
  height: 600
7681
7781
  }
7682
7782
  });
7683
- const firstMessageId = deduplicatedMessages[0]?.id;
7783
+ isPinnedToBottomRef.current = isPinnedToBottom;
7784
+ virtualizer.shouldAdjustScrollPositionOnItemSizeChange = shouldAdjustScrollOnResize;
7684
7785
  (0, react.useLayoutEffect)(() => {
7685
- if (!shouldVirtualize || !deduplicatedMessages.length) return;
7686
- virtualizer.scrollToIndex(deduplicatedMessages.length - 1, { align: "end" });
7786
+ if (!shouldVirtualize || !renderedMessages.length) return;
7787
+ virtualizer.scrollToIndex(renderedMessages.length - 1, { align: "end" });
7687
7788
  }, [shouldVirtualize, firstMessageId]);
7688
- const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages), [deduplicatedMessages]);
7789
+ const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages, renderedMessages), [deduplicatedMessages, renderedMessages]);
7689
7790
  const renderMessageBlock = (message) => {
7690
7791
  const elements = [];
7691
- const stateSnapshot = getStateSnapshotForMessage(message.id);
7792
+ const stateSnapshot = renderCustomMessage ? getStateSnapshotForMessage(message.id) : void 0;
7692
7793
  const rowKey = rowRenderKeys.get(message.id) ?? message.id;
7693
7794
  if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
7694
7795
  message,
@@ -7700,6 +7801,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7700
7801
  message,
7701
7802
  messages,
7702
7803
  isRunning,
7804
+ isLatest: message.id === latestRenderedId,
7703
7805
  AssistantMessageComponent: AssistantComponent,
7704
7806
  slotProps: assistantSlotPropsWithFeedback
7705
7807
  }, rowKey));
@@ -7716,6 +7818,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7716
7818
  message,
7717
7819
  messages,
7718
7820
  isRunning,
7821
+ isLatest: message.id === latestRenderedId,
7719
7822
  ReasoningMessageComponent: ReasoningComponent,
7720
7823
  slotProps: reasoningSlotProps
7721
7824
  }, rowKey));
@@ -7733,7 +7836,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7733
7836
  }, `intelligence-${intelligenceTurnId}`));
7734
7837
  return elements.filter(Boolean);
7735
7838
  };
7736
- const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
7839
+ const messageElements = shouldVirtualize ? [] : renderedMessages.flatMap(renderMessageBlock);
7737
7840
  if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7738
7841
  "data-copilotkit": true,
7739
7842
  style: { display: "contents" },
@@ -7744,7 +7847,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7744
7847
  interruptElement
7745
7848
  })
7746
7849
  });
7747
- const lastMessage = messages[messages.length - 1];
7850
+ const lastMessage = renderedMessages[renderedMessages.length - 1];
7748
7851
  const showCursor = isRunning && lastMessage?.role !== "reasoning";
7749
7852
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7750
7853
  "data-copilotkit": true,
@@ -7758,7 +7861,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
7758
7861
  position: "relative"
7759
7862
  },
7760
7863
  children: virtualizer.getVirtualItems().map((virtualItem) => {
7761
- const message = deduplicatedMessages[virtualItem.index];
7864
+ const message = renderedMessages[virtualItem.index];
7762
7865
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7763
7866
  "data-index": virtualItem.index,
7764
7867
  ref: virtualizer.measureElement,
@@ -8325,7 +8428,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
8325
8428
  }
8326
8429
  (function(_CopilotChatView) {
8327
8430
  const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
8328
- const { isAtBottom, scrollToBottom, scrollRef } = (0, use_stick_to_bottom.useStickToBottomContext)();
8431
+ const { isAtBottom, scrollToBottom, scrollRef, state } = (0, use_stick_to_bottom.useStickToBottomContext)();
8329
8432
  const [scrollEl, setScrollEl] = (0, react.useState)(null);
8330
8433
  (0, react.useLayoutEffect)(() => {
8331
8434
  setScrollEl(scrollRef.current ?? null);
@@ -8333,25 +8436,28 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
8333
8436
  const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
8334
8437
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
8335
8438
  value: scrollEl,
8336
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8337
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
8338
- className: "cpk:overflow-y-auto cpk:overflow-x-hidden",
8339
- style: {
8340
- flex: "1 1 0%",
8341
- minHeight: 0
8342
- },
8343
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8344
- className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
8345
- children
8439
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollPinnedContext.Provider, {
8440
+ value: state.isAtBottom,
8441
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8442
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
8443
+ className: "cpk:overflow-y-auto cpk:overflow-x-hidden",
8444
+ style: {
8445
+ flex: "1 1 0%",
8446
+ minHeight: 0
8447
+ },
8448
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8449
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
8450
+ children
8451
+ })
8452
+ }),
8453
+ BoundFeather,
8454
+ !isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8455
+ className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
8456
+ style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
8457
+ children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
8346
8458
  })
8347
- }),
8348
- BoundFeather,
8349
- !isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8350
- className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
8351
- style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
8352
- children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
8353
- })
8354
- ] })
8459
+ ] })
8460
+ })
8355
8461
  });
8356
8462
  };
8357
8463
  const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
@@ -10039,7 +10145,7 @@ function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed
10039
10145
  const { status, checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
10040
10146
  const licensePresent = status === "valid" || status === "expiring";
10041
10147
  const featureLicensed = checkFeature("threads");
10042
- const licensed = licensePresent && featureLicensed;
10148
+ const licensed = status === "unknown" || licensePresent && featureLicensed;
10043
10149
  const licensePending = status === null;
10044
10150
  const providerAgentId = (0, _copilotkit_react_core_v2_context.useDefaultAgentId)();
10045
10151
  const resolvedAgentId = agentId ?? configuration?.agentId ?? providerAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
@@ -13009,4 +13115,4 @@ Object.defineProperty(exports, 'useToast', {
13009
13115
  return useToast;
13010
13116
  }
13011
13117
  });
13012
- //# sourceMappingURL=copilotkit-D_c2dJ9t.cjs.map
13118
+ //# sourceMappingURL=copilotkit-D2emzYuj.cjs.map