@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.
@@ -1745,6 +1745,10 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1745
1745
  return renderToolCall;
1746
1746
  }
1747
1747
 
1748
+ //#endregion
1749
+ //#region package.json
1750
+ var version = "1.75.0";
1751
+
1748
1752
  //#endregion
1749
1753
  //#region src/v2/components/CopilotKitInspector.tsx
1750
1754
  const CopilotKitInspector = ({ core, openRequest, onVisibilityChange }) => {
@@ -1767,7 +1771,11 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1767
1771
  if (!mounted || !mountRef.current) return;
1768
1772
  mod.defineWebInspector?.();
1769
1773
  inspector = mountRef.current.ownerDocument.createElement(mod.WEB_INSPECTOR_TAG);
1770
- mod.configureWebInspectorElement(inspector, latestCoreRef.current);
1774
+ mod.configureWebInspectorElement(inspector, latestCoreRef.current, {
1775
+ development: process.env.NODE_ENV === "development",
1776
+ framework: "react",
1777
+ sdkVersion: version
1778
+ });
1771
1779
  inspector.addEventListener("cpk-inspector-visibility-change", handleVisibilityChange);
1772
1780
  mountRef.current.appendChild(inspector);
1773
1781
  inspectorRef.current = inspector;
@@ -3876,8 +3884,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3876
3884
  if (aHasAgent === (b.agentId !== void 0)) return 0;
3877
3885
  return aHasAgent ? -1 : 1;
3878
3886
  });
3887
+ if (!customMessageRenderers.length) return null;
3879
3888
  return function(params) {
3880
- if (!customMessageRenderers.length) return null;
3881
3889
  const { message, position } = params;
3882
3890
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3883
3891
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
@@ -6372,7 +6380,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
6372
6380
  })
6373
6381
  });
6374
6382
  }
6375
- function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, inspectorButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
6383
+ 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 }) {
6376
6384
  useKatexStyles();
6377
6385
  const { isInspectorEnabled, openInspector } = useCopilotKitInspector();
6378
6386
  const shortcutsHidden = useInspectorShortcutsHidden();
@@ -6408,7 +6416,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
6408
6416
  messages
6409
6417
  });
6410
6418
  const hasContent = !!(message.content && message.content.trim().length > 0);
6411
- const isLatestAssistantMessage = message.role === "assistant" && messages?.[messages.length - 1]?.id === message.id;
6419
+ const isLatestAssistantMessage = message.role === "assistant" && (isLatest ?? messages?.[messages.length - 1]?.id === message.id);
6412
6420
  const shouldShowToolbar = toolbarVisible && (hasContent || showInspectorShortcut) && !(isRunning && isLatestAssistantMessage);
6413
6421
  if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6414
6422
  "data-copilotkit": true,
@@ -6922,8 +6930,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
6922
6930
  if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
6923
6931
  return `${mins}m ${secs}s`;
6924
6932
  }
6925
- function CopilotChatReasoningMessage({ message, messages, isRunning, header, contentView, toggle, children, className, ...props }) {
6926
- const isLatest = messages?.[messages.length - 1]?.id === message.id;
6933
+ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: isLatestProp, header, contentView, toggle, children, className, ...props }) {
6934
+ const isLatest = isLatestProp ?? messages?.[messages.length - 1]?.id === message.id;
6927
6935
  const isStreaming = !!(isRunning && isLatest);
6928
6936
  const hasContent = !!(message.content && message.content.length > 0);
6929
6937
  const startTimeRef = (0, react.useRef)(null);
@@ -7148,6 +7156,32 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7148
7156
  */
7149
7157
  const ScrollElementContext = react.default.createContext(null);
7150
7158
 
7159
+ //#endregion
7160
+ //#region src/v2/components/chat/scroll-pinned-context.ts
7161
+ /**
7162
+ * True while the pin-to-bottom behaviour is actively following the bottom of
7163
+ * the thread — i.e. `use-stick-to-bottom` will animate the scroll position to
7164
+ * the bottom the next time the content grows.
7165
+ *
7166
+ * Only CopilotChatView's pin-to-bottom branch provides this. The other scroll
7167
+ * modes leave it `false`, which is correct: nothing else writes the scroll
7168
+ * position on its own, so no one is competing with the virtualizer.
7169
+ *
7170
+ * Why this exists: the virtualizer and `use-stick-to-bottom` both write
7171
+ * `scrollTop` on the same element. The virtualizer writes it to compensate
7172
+ * when a row above the viewport turns out taller than its estimate, so that
7173
+ * what the reader is looking at does not shift. That compensation is essential
7174
+ * while the reader is scrolled up — and pointless while pinned to the bottom,
7175
+ * because the pin is about to move the scroll position anyway. Worse than
7176
+ * pointless: the compensation changes the virtual container's height, the pin
7177
+ * reads that as content growth and animates, the animation brings unmeasured
7178
+ * rows into view, they measure, and the two keep shoving each other.
7179
+ *
7180
+ * Consumed by CopilotChatMessageView to stand the virtualizer down while the
7181
+ * pin owns the scroll position.
7182
+ */
7183
+ const ScrollPinnedContext = react.default.createContext(false);
7184
+
7151
7185
  //#endregion
7152
7186
  //#region src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx
7153
7187
  /**
@@ -7292,24 +7326,31 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7292
7326
  * emits exactly one `IntelligenceIndicator` per entry, keyed by the turn id and
7293
7327
  * positioned at the anchor; the per-turn key also lets every past turn keep its
7294
7328
  * own indicator in scroll-back.
7329
+ *
7330
+ * `visibleMessages` is what actually renders, when that differs from
7331
+ * `messages` (the chat's `transformMessages`). Turns are still read from the
7332
+ * full list, so hiding a user message does not merge its turn into the one
7333
+ * before it, and anchors are only chosen among visible messages. A message the
7334
+ * transform built itself joins the turn of the visible message before it.
7295
7335
  */
7296
- function getIntelligenceTurnAnchors(messages) {
7297
- const anchors = /* @__PURE__ */ new Map();
7336
+ function getIntelligenceTurnAnchors(messages, visibleMessages = messages) {
7337
+ const turnOfMessage = /* @__PURE__ */ new Map();
7298
7338
  let turnId = INTELLIGENCE_TURN_HEAD;
7299
- let anchorId = null;
7300
- const commit = () => {
7301
- if (anchorId !== null) anchors.set(anchorId, turnId);
7302
- anchorId = null;
7303
- };
7304
7339
  for (const m of messages) {
7305
- if (m.role === "user") {
7306
- commit();
7307
- turnId = m.id;
7308
- continue;
7340
+ if (m.role === "user") turnId = m.id;
7341
+ turnOfMessage.set(m.id, turnId);
7342
+ }
7343
+ const anchors = /* @__PURE__ */ new Map();
7344
+ const anchoredTurns = /* @__PURE__ */ new Set();
7345
+ let currentTurn = INTELLIGENCE_TURN_HEAD;
7346
+ for (const m of visibleMessages) {
7347
+ currentTurn = turnOfMessage.get(m.id) ?? currentTurn;
7348
+ if (m.role === "user") continue;
7349
+ if (!anchoredTurns.has(currentTurn) && messageHasMatchingToolCall(m)) {
7350
+ anchors.set(m.id, currentTurn);
7351
+ anchoredTurns.add(currentTurn);
7309
7352
  }
7310
- if (anchorId === null && messageHasMatchingToolCall(m)) anchorId = m.id;
7311
7353
  }
7312
- commit();
7313
7354
  return anchors;
7314
7355
  }
7315
7356
  /**
@@ -7455,11 +7496,12 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7455
7496
  /**
7456
7497
  * Memoized wrapper for assistant messages to prevent re-renders when other messages change.
7457
7498
  */
7458
- const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, AssistantMessageComponent, slotProps }) {
7499
+ const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, isLatest, AssistantMessageComponent, slotProps }) {
7459
7500
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssistantMessageComponent, {
7460
7501
  message,
7461
7502
  messages,
7462
7503
  isRunning,
7504
+ isLatest,
7463
7505
  ...slotProps
7464
7506
  });
7465
7507
  }, (prevProps, nextProps) => {
@@ -7481,7 +7523,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7481
7523
  if (prevToolResults.length !== nextToolResults.length) return false;
7482
7524
  for (let i = 0; i < prevToolResults.length; i++) if (prevToolResults[i].content !== nextToolResults[i].content) return false;
7483
7525
  }
7484
- if (nextProps.messages[nextProps.messages.length - 1]?.id === nextProps.message.id && prevProps.isRunning !== nextProps.isRunning) return false;
7526
+ if ((prevProps.isRunning && prevProps.isLatest) !== (nextProps.isRunning && nextProps.isLatest)) return false;
7485
7527
  if (prevProps.AssistantMessageComponent !== nextProps.AssistantMessageComponent) return false;
7486
7528
  if (prevProps.slotProps !== nextProps.slotProps) return false;
7487
7529
  return true;
@@ -7515,20 +7557,19 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7515
7557
  /**
7516
7558
  * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.
7517
7559
  */
7518
- const MemoizedReasoningMessage = react.default.memo(function MemoizedReasoningMessage({ message, messages, isRunning, ReasoningMessageComponent, slotProps }) {
7560
+ const MemoizedReasoningMessage = react.default.memo(function MemoizedReasoningMessage({ message, messages, isRunning, isLatest, ReasoningMessageComponent, slotProps }) {
7519
7561
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningMessageComponent, {
7520
7562
  message,
7521
7563
  messages,
7522
7564
  isRunning,
7565
+ isLatest,
7523
7566
  ...slotProps
7524
7567
  });
7525
7568
  }, (prevProps, nextProps) => {
7526
7569
  if (prevProps.message.id !== nextProps.message.id) return false;
7527
7570
  if (prevProps.message.content !== nextProps.message.content) return false;
7528
- const prevIsLatest = prevProps.messages[prevProps.messages.length - 1]?.id === prevProps.message.id;
7529
- const nextIsLatest = nextProps.messages[nextProps.messages.length - 1]?.id === nextProps.message.id;
7530
- if (prevIsLatest !== nextIsLatest) return false;
7531
- if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning) return false;
7571
+ if (prevProps.isLatest !== nextProps.isLatest) return false;
7572
+ if (nextProps.isLatest && prevProps.isRunning !== nextProps.isRunning) return false;
7532
7573
  if (prevProps.ReasoningMessageComponent !== nextProps.ReasoningMessageComponent) return false;
7533
7574
  if (prevProps.slotProps !== nextProps.slotProps) return false;
7534
7575
  return true;
@@ -7612,7 +7653,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7612
7653
  return [...acc.values()];
7613
7654
  }
7614
7655
  const VIRTUALIZE_THRESHOLD = 50;
7615
- function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, children, className, ...props }) {
7656
+ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, transformMessages, children, className, ...props }) {
7657
+ const isPinnedToBottom = (0, react.useContext)(ScrollPinnedContext);
7616
7658
  const renderCustomMessage = useRenderCustomMessages();
7617
7659
  const { renderActivityMessage } = useRenderActivityMessage();
7618
7660
  const { copilotkit } = useCopilotKit();
@@ -7644,13 +7686,27 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7644
7686
  return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
7645
7687
  };
7646
7688
  const deduplicatedMessages = (0, react.useMemo)(() => deduplicateMessages(messages), [messages]);
7689
+ const renderedMessages = (0, react.useMemo)(() => transformMessages ? transformMessages(deduplicatedMessages) : deduplicatedMessages, [deduplicatedMessages, transformMessages]);
7690
+ const latestRenderedId = renderedMessages[renderedMessages.length - 1]?.id;
7691
+ const transformDuplicateId = (0, react.useMemo)(() => {
7692
+ if (process.env.NODE_ENV === "production" || !transformMessages) return;
7693
+ const seen = /* @__PURE__ */ new Set();
7694
+ for (const message of renderedMessages) {
7695
+ if (seen.has(message.id)) return message.id;
7696
+ seen.add(message.id);
7697
+ }
7698
+ }, [renderedMessages, transformMessages]);
7699
+ (0, react.useEffect)(() => {
7700
+ if (transformDuplicateId === void 0) return;
7701
+ 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.`);
7702
+ }, [transformDuplicateId]);
7647
7703
  const rowKeyStoreRef = (0, react.useRef)(null);
7648
7704
  rowKeyStoreRef.current ?? (rowKeyStoreRef.current = (0, _copilotkit_shared.createRowKeyStore)());
7649
7705
  const rowKeyStore = rowKeyStoreRef.current;
7650
- const rowRenderKeys = (0, react.useMemo)(() => (0, _copilotkit_shared.resolveRowRenderKeysById)(rowKeyStore, deduplicatedMessages), [rowKeyStore, deduplicatedMessages]);
7706
+ const rowRenderKeys = (0, react.useMemo)(() => (0, _copilotkit_shared.resolveRowRenderKeysById)(rowKeyStore, renderedMessages), [rowKeyStore, renderedMessages]);
7651
7707
  (0, react.useLayoutEffect)(() => {
7652
- (0, _copilotkit_shared.commitRowKeyStore)(rowKeyStore, deduplicatedMessages);
7653
- }, [rowKeyStore, deduplicatedMessages]);
7708
+ (0, _copilotkit_shared.commitRowKeyStore)(rowKeyStore, renderedMessages);
7709
+ }, [rowKeyStore, renderedMessages]);
7654
7710
  if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Merged ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
7655
7711
  const { Component: AssistantComponent, slotProps: assistantSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
7656
7712
  const agentId = config?.agentId;
@@ -7684,27 +7740,72 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7684
7740
  (0, react.useEffect)(() => {
7685
7741
  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.");
7686
7742
  }, [scrollElementFromCtx]);
7687
- const shouldVirtualize = !!scrollElement && !children && deduplicatedMessages.length > VIRTUALIZE_THRESHOLD;
7743
+ const shouldVirtualize = !!scrollElement && !children && renderedMessages.length > VIRTUALIZE_THRESHOLD;
7744
+ const childrenDisabledVirtualization = !!children && !!scrollElement && renderedMessages.length > VIRTUALIZE_THRESHOLD;
7745
+ const warnedChildrenRef = (0, react.useRef)(false);
7746
+ (0, react.useEffect)(() => {
7747
+ if (process.env.NODE_ENV === "production" || !childrenDisabledVirtualization || warnedChildrenRef.current) return;
7748
+ warnedChildrenRef.current = true;
7749
+ 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."));
7750
+ }, [
7751
+ childrenDisabledVirtualization,
7752
+ renderedMessages.length,
7753
+ transformMessages
7754
+ ]);
7755
+ const measuredRef = react.default.useRef({
7756
+ total: 0,
7757
+ sizes: /* @__PURE__ */ new Map()
7758
+ });
7759
+ const firstMessageId = deduplicatedMessages[0]?.id;
7760
+ const measuredThreadRef = react.default.useRef(firstMessageId);
7761
+ if (measuredThreadRef.current !== firstMessageId) {
7762
+ measuredThreadRef.current = firstMessageId;
7763
+ measuredRef.current = {
7764
+ total: 0,
7765
+ sizes: /* @__PURE__ */ new Map()
7766
+ };
7767
+ }
7768
+ const estimateRowSize = react.default.useCallback(() => {
7769
+ const { total, sizes } = measuredRef.current;
7770
+ return sizes.size > 0 ? Math.max(1, Math.round(total / sizes.size)) : 100;
7771
+ }, []);
7772
+ const measureRowElement = react.default.useCallback((el) => {
7773
+ const height = el?.getBoundingClientRect().height ?? 0;
7774
+ const index = Number(el?.dataset?.index);
7775
+ if (height > 0 && Number.isInteger(index)) {
7776
+ const { total, sizes } = measuredRef.current;
7777
+ measuredRef.current.total = total - (sizes.get(index) ?? 0) + height;
7778
+ sizes.set(index, height);
7779
+ }
7780
+ return height;
7781
+ }, []);
7782
+ const isPinnedToBottomRef = react.default.useRef(isPinnedToBottom);
7783
+ const shouldAdjustScrollOnResize = react.default.useCallback((item, _delta, instance) => {
7784
+ if (isPinnedToBottomRef.current) return false;
7785
+ const scrollAdjustments = instance.scrollAdjustments ?? 0;
7786
+ return item.start < (instance.scrollOffset ?? 0) + scrollAdjustments;
7787
+ }, []);
7688
7788
  const virtualizer = (0, _tanstack_react_virtual.useVirtualizer)({
7689
- count: shouldVirtualize ? deduplicatedMessages.length : 0,
7789
+ count: shouldVirtualize ? renderedMessages.length : 0,
7690
7790
  getScrollElement: () => scrollElement,
7691
- estimateSize: () => 100,
7791
+ estimateSize: estimateRowSize,
7692
7792
  overscan: 5,
7693
- measureElement: (el) => el?.getBoundingClientRect().height ?? 0,
7793
+ measureElement: measureRowElement,
7694
7794
  initialRect: {
7695
7795
  width: 0,
7696
7796
  height: 600
7697
7797
  }
7698
7798
  });
7699
- const firstMessageId = deduplicatedMessages[0]?.id;
7799
+ isPinnedToBottomRef.current = isPinnedToBottom;
7800
+ virtualizer.shouldAdjustScrollPositionOnItemSizeChange = shouldAdjustScrollOnResize;
7700
7801
  (0, react.useLayoutEffect)(() => {
7701
- if (!shouldVirtualize || !deduplicatedMessages.length) return;
7702
- virtualizer.scrollToIndex(deduplicatedMessages.length - 1, { align: "end" });
7802
+ if (!shouldVirtualize || !renderedMessages.length) return;
7803
+ virtualizer.scrollToIndex(renderedMessages.length - 1, { align: "end" });
7703
7804
  }, [shouldVirtualize, firstMessageId]);
7704
- const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages), [deduplicatedMessages]);
7805
+ const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages, renderedMessages), [deduplicatedMessages, renderedMessages]);
7705
7806
  const renderMessageBlock = (message) => {
7706
7807
  const elements = [];
7707
- const stateSnapshot = getStateSnapshotForMessage(message.id);
7808
+ const stateSnapshot = renderCustomMessage ? getStateSnapshotForMessage(message.id) : void 0;
7708
7809
  const rowKey = rowRenderKeys.get(message.id) ?? message.id;
7709
7810
  if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
7710
7811
  message,
@@ -7716,6 +7817,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7716
7817
  message,
7717
7818
  messages,
7718
7819
  isRunning,
7820
+ isLatest: message.id === latestRenderedId,
7719
7821
  AssistantMessageComponent: AssistantComponent,
7720
7822
  slotProps: assistantSlotPropsWithFeedback
7721
7823
  }, rowKey));
@@ -7732,6 +7834,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7732
7834
  message,
7733
7835
  messages,
7734
7836
  isRunning,
7837
+ isLatest: message.id === latestRenderedId,
7735
7838
  ReasoningMessageComponent: ReasoningComponent,
7736
7839
  slotProps: reasoningSlotProps
7737
7840
  }, rowKey));
@@ -7749,7 +7852,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7749
7852
  }, `intelligence-${intelligenceTurnId}`));
7750
7853
  return elements.filter(Boolean);
7751
7854
  };
7752
- const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
7855
+ const messageElements = shouldVirtualize ? [] : renderedMessages.flatMap(renderMessageBlock);
7753
7856
  if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7754
7857
  "data-copilotkit": true,
7755
7858
  style: { display: "contents" },
@@ -7760,7 +7863,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7760
7863
  interruptElement
7761
7864
  })
7762
7865
  });
7763
- const lastMessage = messages[messages.length - 1];
7866
+ const lastMessage = renderedMessages[renderedMessages.length - 1];
7764
7867
  const showCursor = isRunning && lastMessage?.role !== "reasoning";
7765
7868
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7766
7869
  "data-copilotkit": true,
@@ -7774,7 +7877,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7774
7877
  position: "relative"
7775
7878
  },
7776
7879
  children: virtualizer.getVirtualItems().map((virtualItem) => {
7777
- const message = deduplicatedMessages[virtualItem.index];
7880
+ const message = renderedMessages[virtualItem.index];
7778
7881
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7779
7882
  "data-index": virtualItem.index,
7780
7883
  ref: virtualizer.measureElement,
@@ -8341,7 +8444,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
8341
8444
  }
8342
8445
  (function(_CopilotChatView) {
8343
8446
  const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
8344
- const { isAtBottom, scrollToBottom, scrollRef } = (0, use_stick_to_bottom.useStickToBottomContext)();
8447
+ const { isAtBottom, scrollToBottom, scrollRef, state } = (0, use_stick_to_bottom.useStickToBottomContext)();
8345
8448
  const [scrollEl, setScrollEl] = (0, react.useState)(null);
8346
8449
  (0, react.useLayoutEffect)(() => {
8347
8450
  setScrollEl(scrollRef.current ?? null);
@@ -8349,25 +8452,28 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
8349
8452
  const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
8350
8453
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
8351
8454
  value: scrollEl,
8352
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8353
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
8354
- className: "cpk:overflow-y-auto cpk:overflow-x-hidden",
8355
- style: {
8356
- flex: "1 1 0%",
8357
- minHeight: 0
8358
- },
8359
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8360
- className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
8361
- children
8455
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollPinnedContext.Provider, {
8456
+ value: state.isAtBottom,
8457
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8458
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
8459
+ className: "cpk:overflow-y-auto cpk:overflow-x-hidden",
8460
+ style: {
8461
+ flex: "1 1 0%",
8462
+ minHeight: 0
8463
+ },
8464
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8465
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
8466
+ children
8467
+ })
8468
+ }),
8469
+ BoundFeather,
8470
+ !isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8471
+ className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
8472
+ style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
8473
+ children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
8362
8474
  })
8363
- }),
8364
- BoundFeather,
8365
- !isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8366
- className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
8367
- style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
8368
- children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
8369
- })
8370
- ] })
8475
+ ] })
8476
+ })
8371
8477
  });
8372
8478
  };
8373
8479
  const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
@@ -10055,7 +10161,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
10055
10161
  const { status, checkFeature } = useLicenseContext();
10056
10162
  const licensePresent = status === "valid" || status === "expiring";
10057
10163
  const featureLicensed = checkFeature("threads");
10058
- const licensed = licensePresent && featureLicensed;
10164
+ const licensed = status === "unknown" || licensePresent && featureLicensed;
10059
10165
  const licensePending = status === null;
10060
10166
  const providerAgentId = useDefaultAgentId();
10061
10167
  const resolvedAgentId = agentId ?? configuration?.agentId ?? providerAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;