@copilotkitnext/react 1.52.0-next.5 → 1.52.0-next.7

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.
Files changed (159) hide show
  1. package/dist/components/WildcardToolCallRender.cjs +13 -13
  2. package/dist/components/WildcardToolCallRender.cjs.map +1 -1
  3. package/dist/components/WildcardToolCallRender.mjs +13 -13
  4. package/dist/components/WildcardToolCallRender.mjs.map +1 -1
  5. package/dist/components/chat/CopilotChat.cjs.map +1 -1
  6. package/dist/components/chat/CopilotChat.mjs.map +1 -1
  7. package/dist/components/chat/CopilotChatAssistantMessage.cjs +36 -28
  8. package/dist/components/chat/CopilotChatAssistantMessage.cjs.map +1 -1
  9. package/dist/components/chat/CopilotChatAssistantMessage.mjs +37 -29
  10. package/dist/components/chat/CopilotChatAssistantMessage.mjs.map +1 -1
  11. package/dist/components/chat/CopilotChatAudioRecorder.cjs +2 -2
  12. package/dist/components/chat/CopilotChatAudioRecorder.cjs.map +1 -1
  13. package/dist/components/chat/CopilotChatAudioRecorder.mjs +2 -2
  14. package/dist/components/chat/CopilotChatAudioRecorder.mjs.map +1 -1
  15. package/dist/components/chat/CopilotChatInput.cjs +59 -51
  16. package/dist/components/chat/CopilotChatInput.cjs.map +1 -1
  17. package/dist/components/chat/CopilotChatInput.d.cts.map +1 -1
  18. package/dist/components/chat/CopilotChatInput.d.mts.map +1 -1
  19. package/dist/components/chat/CopilotChatInput.mjs +59 -51
  20. package/dist/components/chat/CopilotChatInput.mjs.map +1 -1
  21. package/dist/components/chat/CopilotChatMessageView.cjs +28 -10
  22. package/dist/components/chat/CopilotChatMessageView.cjs.map +1 -1
  23. package/dist/components/chat/CopilotChatMessageView.d.cts +1 -0
  24. package/dist/components/chat/CopilotChatMessageView.d.cts.map +1 -1
  25. package/dist/components/chat/CopilotChatMessageView.d.mts +1 -0
  26. package/dist/components/chat/CopilotChatMessageView.d.mts.map +1 -1
  27. package/dist/components/chat/CopilotChatMessageView.mjs +29 -11
  28. package/dist/components/chat/CopilotChatMessageView.mjs.map +1 -1
  29. package/dist/components/chat/CopilotChatReasoningMessage.cjs +24 -20
  30. package/dist/components/chat/CopilotChatReasoningMessage.cjs.map +1 -1
  31. package/dist/components/chat/CopilotChatReasoningMessage.d.cts.map +1 -1
  32. package/dist/components/chat/CopilotChatReasoningMessage.d.mts.map +1 -1
  33. package/dist/components/chat/CopilotChatReasoningMessage.mjs +25 -21
  34. package/dist/components/chat/CopilotChatReasoningMessage.mjs.map +1 -1
  35. package/dist/components/chat/CopilotChatSuggestionPill.cjs +6 -5
  36. package/dist/components/chat/CopilotChatSuggestionPill.cjs.map +1 -1
  37. package/dist/components/chat/CopilotChatSuggestionPill.mjs +6 -5
  38. package/dist/components/chat/CopilotChatSuggestionPill.mjs.map +1 -1
  39. package/dist/components/chat/CopilotChatSuggestionView.cjs +24 -12
  40. package/dist/components/chat/CopilotChatSuggestionView.cjs.map +1 -1
  41. package/dist/components/chat/CopilotChatSuggestionView.d.cts.map +1 -1
  42. package/dist/components/chat/CopilotChatSuggestionView.d.mts.map +1 -1
  43. package/dist/components/chat/CopilotChatSuggestionView.mjs +25 -13
  44. package/dist/components/chat/CopilotChatSuggestionView.mjs.map +1 -1
  45. package/dist/components/chat/CopilotChatToggleButton.cjs +7 -6
  46. package/dist/components/chat/CopilotChatToggleButton.cjs.map +1 -1
  47. package/dist/components/chat/CopilotChatToggleButton.d.cts.map +1 -1
  48. package/dist/components/chat/CopilotChatToggleButton.d.mts.map +1 -1
  49. package/dist/components/chat/CopilotChatToggleButton.mjs +7 -6
  50. package/dist/components/chat/CopilotChatToggleButton.mjs.map +1 -1
  51. package/dist/components/chat/CopilotChatUserMessage.cjs +29 -24
  52. package/dist/components/chat/CopilotChatUserMessage.cjs.map +1 -1
  53. package/dist/components/chat/CopilotChatUserMessage.d.cts.map +1 -1
  54. package/dist/components/chat/CopilotChatUserMessage.d.mts.map +1 -1
  55. package/dist/components/chat/CopilotChatUserMessage.mjs +30 -25
  56. package/dist/components/chat/CopilotChatUserMessage.mjs.map +1 -1
  57. package/dist/components/chat/CopilotChatView.cjs +45 -35
  58. package/dist/components/chat/CopilotChatView.cjs.map +1 -1
  59. package/dist/components/chat/CopilotChatView.d.cts +1 -1
  60. package/dist/components/chat/CopilotChatView.d.cts.map +1 -1
  61. package/dist/components/chat/CopilotChatView.d.mts +1 -1
  62. package/dist/components/chat/CopilotChatView.d.mts.map +1 -1
  63. package/dist/components/chat/CopilotChatView.mjs +45 -35
  64. package/dist/components/chat/CopilotChatView.mjs.map +1 -1
  65. package/dist/components/chat/CopilotModalHeader.cjs +8 -8
  66. package/dist/components/chat/CopilotModalHeader.cjs.map +1 -1
  67. package/dist/components/chat/CopilotModalHeader.d.cts.map +1 -1
  68. package/dist/components/chat/CopilotModalHeader.d.mts.map +1 -1
  69. package/dist/components/chat/CopilotModalHeader.mjs +8 -8
  70. package/dist/components/chat/CopilotModalHeader.mjs.map +1 -1
  71. package/dist/components/chat/CopilotPopupView.cjs +20 -15
  72. package/dist/components/chat/CopilotPopupView.cjs.map +1 -1
  73. package/dist/components/chat/CopilotPopupView.d.cts.map +1 -1
  74. package/dist/components/chat/CopilotPopupView.d.mts.map +1 -1
  75. package/dist/components/chat/CopilotPopupView.mjs +20 -15
  76. package/dist/components/chat/CopilotPopupView.mjs.map +1 -1
  77. package/dist/components/chat/CopilotSidebarView.cjs +54 -43
  78. package/dist/components/chat/CopilotSidebarView.cjs.map +1 -1
  79. package/dist/components/chat/CopilotSidebarView.d.cts.map +1 -1
  80. package/dist/components/chat/CopilotSidebarView.d.mts.map +1 -1
  81. package/dist/components/chat/CopilotSidebarView.mjs +55 -44
  82. package/dist/components/chat/CopilotSidebarView.mjs.map +1 -1
  83. package/dist/components/ui/button.cjs +42 -42
  84. package/dist/components/ui/button.cjs.map +1 -1
  85. package/dist/components/ui/button.mjs +42 -42
  86. package/dist/components/ui/button.mjs.map +1 -1
  87. package/dist/components/ui/dropdown-menu.cjs +7 -6
  88. package/dist/components/ui/dropdown-menu.cjs.map +1 -1
  89. package/dist/components/ui/dropdown-menu.mjs +7 -6
  90. package/dist/components/ui/dropdown-menu.mjs.map +1 -1
  91. package/dist/components/ui/tooltip.cjs +3 -2
  92. package/dist/components/ui/tooltip.cjs.map +1 -1
  93. package/dist/components/ui/tooltip.mjs +3 -2
  94. package/dist/components/ui/tooltip.mjs.map +1 -1
  95. package/dist/hooks/index.cjs +1 -0
  96. package/dist/hooks/index.d.cts +2 -1
  97. package/dist/hooks/index.d.mts +2 -1
  98. package/dist/hooks/index.mjs +1 -0
  99. package/dist/hooks/use-component.cjs +18 -5
  100. package/dist/hooks/use-component.cjs.map +1 -1
  101. package/dist/hooks/use-component.d.cts +21 -7
  102. package/dist/hooks/use-component.d.cts.map +1 -1
  103. package/dist/hooks/use-component.d.mts +21 -7
  104. package/dist/hooks/use-component.d.mts.map +1 -1
  105. package/dist/hooks/use-component.mjs +18 -5
  106. package/dist/hooks/use-component.mjs.map +1 -1
  107. package/dist/hooks/use-default-render-tool.cjs +2 -2
  108. package/dist/hooks/use-default-render-tool.cjs.map +1 -1
  109. package/dist/hooks/use-default-render-tool.d.cts +3 -3
  110. package/dist/hooks/use-default-render-tool.d.cts.map +1 -1
  111. package/dist/hooks/use-default-render-tool.d.mts +3 -3
  112. package/dist/hooks/use-default-render-tool.d.mts.map +1 -1
  113. package/dist/hooks/use-default-render-tool.mjs +2 -2
  114. package/dist/hooks/use-default-render-tool.mjs.map +1 -1
  115. package/dist/hooks/use-interrupt.cjs +171 -0
  116. package/dist/hooks/use-interrupt.cjs.map +1 -0
  117. package/dist/hooks/use-interrupt.d.cts +102 -0
  118. package/dist/hooks/use-interrupt.d.cts.map +1 -0
  119. package/dist/hooks/use-interrupt.d.mts +102 -0
  120. package/dist/hooks/use-interrupt.d.mts.map +1 -0
  121. package/dist/hooks/use-interrupt.mjs +170 -0
  122. package/dist/hooks/use-interrupt.mjs.map +1 -0
  123. package/dist/hooks/use-render-tool.cjs +15 -9
  124. package/dist/hooks/use-render-tool.cjs.map +1 -1
  125. package/dist/hooks/use-render-tool.d.cts +9 -9
  126. package/dist/hooks/use-render-tool.d.cts.map +1 -1
  127. package/dist/hooks/use-render-tool.d.mts +9 -9
  128. package/dist/hooks/use-render-tool.d.mts.map +1 -1
  129. package/dist/hooks/use-render-tool.mjs +15 -9
  130. package/dist/hooks/use-render-tool.mjs.map +1 -1
  131. package/dist/index.cjs +2 -0
  132. package/dist/index.d.cts +3 -1
  133. package/dist/index.d.mts +3 -1
  134. package/dist/index.mjs +2 -1
  135. package/dist/index.umd.js +625 -342
  136. package/dist/index.umd.js.map +1 -1
  137. package/dist/lib/react-core.cjs +13 -0
  138. package/dist/lib/react-core.cjs.map +1 -1
  139. package/dist/lib/react-core.d.cts +8 -0
  140. package/dist/lib/react-core.d.cts.map +1 -1
  141. package/dist/lib/react-core.d.mts +8 -0
  142. package/dist/lib/react-core.d.mts.map +1 -1
  143. package/dist/lib/react-core.mjs +13 -0
  144. package/dist/lib/react-core.mjs.map +1 -1
  145. package/dist/lib/utils.cjs +2 -1
  146. package/dist/lib/utils.cjs.map +1 -1
  147. package/dist/lib/utils.mjs +3 -2
  148. package/dist/lib/utils.mjs.map +1 -1
  149. package/dist/styles.css +1 -1
  150. package/dist/types/index.d.cts +2 -1
  151. package/dist/types/index.d.mts +2 -1
  152. package/dist/types/interrupt.d.cts +17 -0
  153. package/dist/types/interrupt.d.cts.map +1 -0
  154. package/dist/types/interrupt.d.mts +17 -0
  155. package/dist/types/interrupt.d.mts.map +1 -0
  156. package/eslint-rules/README.md +52 -0
  157. package/eslint-rules/require-cpk-prefix.mjs +375 -0
  158. package/eslint.config.mjs +17 -0
  159. package/package.json +8 -7
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatMessageView.cjs","names":["React","useRenderCustomMessages","useRenderActivityMessage","useCopilotKit","useCopilotChatConfiguration","CopilotChatAssistantMessage","isReactComponentType","CopilotChatUserMessage","CopilotChatReasoningMessage","renderSlot"],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"sourcesContent":["import React, { useEffect, useReducer } from \"react\";\nimport { WithSlots, renderSlot, isReactComponentType } from \"@/lib/slots\";\nimport CopilotChatAssistantMessage from \"./CopilotChatAssistantMessage\";\nimport CopilotChatUserMessage from \"./CopilotChatUserMessage\";\nimport CopilotChatReasoningMessage from \"./CopilotChatReasoningMessage\";\nimport {\n ActivityMessage,\n AssistantMessage,\n Message,\n ReasoningMessage,\n UserMessage,\n} from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useRenderActivityMessage, useRenderCustomMessages } from \"@/hooks\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useCopilotChatConfiguration } from \"@/providers/CopilotChatConfigurationProvider\";\n\n/**\n * Memoized wrapper for assistant messages to prevent re-renders when other messages change.\n */\nconst MemoizedAssistantMessage = React.memo(\n function MemoizedAssistantMessage({\n message,\n messages,\n isRunning,\n AssistantMessageComponent,\n slotProps,\n }: {\n message: AssistantMessage;\n messages: Message[];\n isRunning: boolean;\n AssistantMessageComponent: typeof CopilotChatAssistantMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }) {\n return (\n <AssistantMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Compare tool calls if present\n const prevToolCalls = prevProps.message.toolCalls;\n const nextToolCalls = nextProps.message.toolCalls;\n if (prevToolCalls?.length !== nextToolCalls?.length) return false;\n if (prevToolCalls && nextToolCalls) {\n for (let i = 0; i < prevToolCalls.length; i++) {\n const prevTc = prevToolCalls[i];\n const nextTc = nextToolCalls[i];\n if (!prevTc || !nextTc) return false;\n if (prevTc.id !== nextTc.id) return false;\n if (prevTc.function.arguments !== nextTc.function.arguments)\n return false;\n }\n }\n\n // Check if tool results changed for this message's tool calls\n // Tool results are separate messages with role=\"tool\" that reference tool call IDs\n if (prevToolCalls && prevToolCalls.length > 0) {\n const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));\n\n const prevToolResults = prevProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n const nextToolResults = nextProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n\n // If number of tool results changed, re-render\n if (prevToolResults.length !== nextToolResults.length) return false;\n\n // If any tool result content changed, re-render\n for (let i = 0; i < prevToolResults.length; i++) {\n if (\n (prevToolResults[i] as any).content !==\n (nextToolResults[i] as any).content\n )\n return false;\n }\n }\n\n // Only care about isRunning if this message is CURRENTLY the latest\n // (we don't need to re-render just because a message stopped being the latest)\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.AssistantMessageComponent !==\n nextProps.AssistantMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for user messages to prevent re-renders when other messages change.\n */\nconst MemoizedUserMessage = React.memo(\n function MemoizedUserMessage({\n message,\n UserMessageComponent,\n slotProps,\n }: {\n message: UserMessage;\n UserMessageComponent: typeof CopilotChatUserMessage;\n slotProps?: Partial<React.ComponentProps<typeof CopilotChatUserMessage>>;\n }) {\n return <UserMessageComponent message={message} {...slotProps} />;\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent)\n return false;\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n return true;\n },\n);\n\n/**\n * Memoized wrapper for activity messages to prevent re-renders when other messages change.\n */\nconst MemoizedActivityMessage = React.memo(\n function MemoizedActivityMessage({\n message,\n renderActivityMessage,\n }: {\n message: ActivityMessage;\n renderActivityMessage: (\n message: ActivityMessage,\n ) => React.ReactElement | null;\n }) {\n return renderActivityMessage(message);\n },\n (prevProps, nextProps) => {\n // Message ID changed = different message, must re-render\n if (prevProps.message.id !== nextProps.message.id) return false;\n\n // Activity type changed = must re-render\n if (prevProps.message.activityType !== nextProps.message.activityType)\n return false;\n\n // Compare content using JSON.stringify (native code, handles deep comparison)\n if (\n JSON.stringify(prevProps.message.content) !==\n JSON.stringify(nextProps.message.content)\n )\n return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.\n */\nconst MemoizedReasoningMessage = React.memo(\n function MemoizedReasoningMessage({\n message,\n messages,\n isRunning,\n ReasoningMessageComponent,\n slotProps,\n }: {\n message: ReasoningMessage;\n messages: Message[];\n isRunning: boolean;\n ReasoningMessageComponent: typeof CopilotChatReasoningMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }) {\n return (\n <ReasoningMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Re-render when \"latest\" status changes (e.g. reasoning message is no longer the last message\n // because a text message was added after it — this transitions isStreaming from true to false)\n const prevIsLatest =\n prevProps.messages[prevProps.messages.length - 1]?.id ===\n prevProps.message.id;\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (prevIsLatest !== nextIsLatest) return false;\n\n // Only care about isRunning if this message is CURRENTLY the latest\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.ReasoningMessageComponent !==\n nextProps.ReasoningMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for custom messages to prevent re-renders when other messages change.\n */\nconst MemoizedCustomMessage = React.memo(\n function MemoizedCustomMessage({\n message,\n position,\n renderCustomMessage,\n }: {\n message: Message;\n position: \"before\" | \"after\";\n renderCustomMessage: (params: {\n message: Message;\n position: \"before\" | \"after\";\n }) => React.ReactElement | null;\n stateSnapshot?: unknown;\n }) {\n return renderCustomMessage({ message, position });\n },\n (prevProps, nextProps) => {\n // Only re-render if the message or position changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.position !== nextProps.position) return false;\n // Compare message content - for assistant messages this is a string, for others may differ\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.message.role !== nextProps.message.role) return false;\n // Compare state snapshot - custom renderers may depend on state\n if (\n JSON.stringify(prevProps.stateSnapshot) !==\n JSON.stringify(nextProps.stateSnapshot)\n )\n return false;\n // Note: We don't compare renderCustomMessage function reference because it changes\n // frequently. The message and state comparison is sufficient to determine if a re-render is needed.\n return true;\n },\n);\n\nexport type CopilotChatMessageViewProps = Omit<\n WithSlots<\n {\n assistantMessage: typeof CopilotChatAssistantMessage;\n userMessage: typeof CopilotChatUserMessage;\n reasoningMessage: typeof CopilotChatReasoningMessage;\n cursor: typeof CopilotChatMessageView.Cursor;\n },\n {\n isRunning?: boolean;\n messages?: Message[];\n } & React.HTMLAttributes<HTMLDivElement>\n >,\n \"children\"\n> & {\n children?: (props: {\n isRunning: boolean;\n messages: Message[];\n messageElements: React.ReactElement[];\n }) => React.ReactElement;\n};\n\nexport function CopilotChatMessageView({\n messages = [],\n assistantMessage,\n userMessage,\n reasoningMessage,\n cursor,\n isRunning = false,\n children,\n className,\n ...props\n}: CopilotChatMessageViewProps) {\n const renderCustomMessage = useRenderCustomMessages();\n const { renderActivityMessage } = useRenderActivityMessage();\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n // Subscribe to state changes so custom message renderers re-render when state updates.\n useEffect(() => {\n if (!config?.agentId) return;\n const agent = copilotkit.getAgent(config.agentId);\n if (!agent) return;\n\n const subscription = agent.subscribe({\n onStateChanged: forceUpdate,\n });\n return () => subscription.unsubscribe();\n }, [config?.agentId, copilotkit, forceUpdate]);\n\n // Helper to get state snapshot for a message (used for memoization)\n const getStateSnapshotForMessage = (messageId: string): unknown => {\n if (!config) return undefined;\n const resolvedRunId =\n copilotkit.getRunIdForMessage(\n config.agentId,\n config.threadId,\n messageId,\n ) ??\n copilotkit\n .getRunIdsForThread(config.agentId, config.threadId)\n .slice(-1)[0];\n if (!resolvedRunId) return undefined;\n return copilotkit.getStateByRun(\n config.agentId,\n config.threadId,\n resolvedRunId,\n );\n };\n\n const messageElements: React.ReactElement[] = messages\n .flatMap((message) => {\n const elements: (React.ReactElement | null | undefined)[] = [];\n const stateSnapshot = getStateSnapshotForMessage(message.id);\n\n // Render custom message before (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-before`}\n message={message}\n position=\"before\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n // Render the main message using memoized wrappers to prevent unnecessary re-renders\n if (message.role === \"assistant\") {\n // Determine the component and props from slot value\n let AssistantComponent = CopilotChatAssistantMessage;\n let assistantSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatAssistantMessage>>\n | undefined;\n\n if (isReactComponentType(assistantMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n AssistantComponent =\n assistantMessage as typeof CopilotChatAssistantMessage;\n } else if (typeof assistantMessage === \"string\") {\n // className string\n assistantSlotProps = { className: assistantMessage };\n } else if (assistantMessage && typeof assistantMessage === \"object\") {\n // Props object\n assistantSlotProps = assistantMessage as Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }\n\n elements.push(\n <MemoizedAssistantMessage\n key={message.id}\n message={message as AssistantMessage}\n messages={messages}\n isRunning={isRunning}\n AssistantMessageComponent={AssistantComponent}\n slotProps={assistantSlotProps}\n />,\n );\n } else if (message.role === \"user\") {\n // Determine the component and props from slot value\n let UserComponent = CopilotChatUserMessage;\n let userSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatUserMessage>>\n | undefined;\n\n if (isReactComponentType(userMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n UserComponent = userMessage as typeof CopilotChatUserMessage;\n } else if (typeof userMessage === \"string\") {\n // className string\n userSlotProps = { className: userMessage };\n } else if (userMessage && typeof userMessage === \"object\") {\n // Props object\n userSlotProps = userMessage as Partial<\n React.ComponentProps<typeof CopilotChatUserMessage>\n >;\n }\n\n elements.push(\n <MemoizedUserMessage\n key={message.id}\n message={message as UserMessage}\n UserMessageComponent={UserComponent}\n slotProps={userSlotProps}\n />,\n );\n } else if (message.role === \"activity\") {\n // Use memoized wrapper to prevent re-renders when other messages change\n const activityMsg = message as ActivityMessage;\n elements.push(\n <MemoizedActivityMessage\n key={message.id}\n message={activityMsg}\n renderActivityMessage={renderActivityMessage}\n />,\n );\n } else if (message.role === \"reasoning\") {\n // Determine the component and props from slot value\n let ReasoningComponent = CopilotChatReasoningMessage;\n let reasoningSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatReasoningMessage>>\n | undefined;\n\n if (isReactComponentType(reasoningMessage)) {\n ReasoningComponent =\n reasoningMessage as typeof CopilotChatReasoningMessage;\n } else if (typeof reasoningMessage === \"string\") {\n reasoningSlotProps = { className: reasoningMessage };\n } else if (reasoningMessage && typeof reasoningMessage === \"object\") {\n reasoningSlotProps = reasoningMessage as Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }\n\n elements.push(\n <MemoizedReasoningMessage\n key={message.id}\n message={message as ReasoningMessage}\n messages={messages}\n isRunning={isRunning}\n ReasoningMessageComponent={ReasoningComponent}\n slotProps={reasoningSlotProps}\n />,\n );\n }\n\n // Render custom message after (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-after`}\n message={message}\n position=\"after\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n return elements;\n })\n .filter(Boolean) as React.ReactElement[];\n\n if (children) {\n return children({ messageElements, messages, isRunning });\n }\n\n // Hide the chat-level loading cursor when the last message is a reasoning\n // message — the reasoning card already shows its own loading indicator.\n const lastMessage = messages[messages.length - 1];\n const showCursor = isRunning && lastMessage?.role !== \"reasoning\";\n\n return (\n <div className={twMerge(\"flex flex-col\", className)} {...props}>\n {messageElements}\n {showCursor && (\n <div className=\"mt-2\">\n {renderSlot(cursor, CopilotChatMessageView.Cursor, {})}\n </div>\n )}\n </div>\n );\n}\n\nCopilotChatMessageView.Cursor = function Cursor({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={twMerge(\n \"w-[11px] h-[11px] rounded-full bg-foreground animate-pulse-cursor ml-1\",\n className,\n )}\n {...props}\n />\n );\n};\n\nexport default CopilotChatMessageView;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CopilotChatMessageView.cjs","names":["React","useRenderCustomMessages","useRenderActivityMessage","useCopilotKit","useCopilotChatConfiguration","CopilotChatAssistantMessage","isReactComponentType","CopilotChatUserMessage","CopilotChatReasoningMessage","renderSlot"],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"sourcesContent":["import React, { useEffect, useReducer, useState } from \"react\";\nimport { WithSlots, renderSlot, isReactComponentType } from \"@/lib/slots\";\nimport CopilotChatAssistantMessage from \"./CopilotChatAssistantMessage\";\nimport CopilotChatUserMessage from \"./CopilotChatUserMessage\";\nimport CopilotChatReasoningMessage from \"./CopilotChatReasoningMessage\";\nimport {\n ActivityMessage,\n AssistantMessage,\n Message,\n ReasoningMessage,\n UserMessage,\n} from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useRenderActivityMessage, useRenderCustomMessages } from \"@/hooks\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useCopilotChatConfiguration } from \"@/providers/CopilotChatConfigurationProvider\";\n\n/**\n * Memoized wrapper for assistant messages to prevent re-renders when other messages change.\n */\nconst MemoizedAssistantMessage = React.memo(\n function MemoizedAssistantMessage({\n message,\n messages,\n isRunning,\n AssistantMessageComponent,\n slotProps,\n }: {\n message: AssistantMessage;\n messages: Message[];\n isRunning: boolean;\n AssistantMessageComponent: typeof CopilotChatAssistantMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }) {\n return (\n <AssistantMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Compare tool calls if present\n const prevToolCalls = prevProps.message.toolCalls;\n const nextToolCalls = nextProps.message.toolCalls;\n if (prevToolCalls?.length !== nextToolCalls?.length) return false;\n if (prevToolCalls && nextToolCalls) {\n for (let i = 0; i < prevToolCalls.length; i++) {\n const prevTc = prevToolCalls[i];\n const nextTc = nextToolCalls[i];\n if (!prevTc || !nextTc) return false;\n if (prevTc.id !== nextTc.id) return false;\n if (prevTc.function.arguments !== nextTc.function.arguments)\n return false;\n }\n }\n\n // Check if tool results changed for this message's tool calls\n // Tool results are separate messages with role=\"tool\" that reference tool call IDs\n if (prevToolCalls && prevToolCalls.length > 0) {\n const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));\n\n const prevToolResults = prevProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n const nextToolResults = nextProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n\n // If number of tool results changed, re-render\n if (prevToolResults.length !== nextToolResults.length) return false;\n\n // If any tool result content changed, re-render\n for (let i = 0; i < prevToolResults.length; i++) {\n if (\n (prevToolResults[i] as any).content !==\n (nextToolResults[i] as any).content\n )\n return false;\n }\n }\n\n // Only care about isRunning if this message is CURRENTLY the latest\n // (we don't need to re-render just because a message stopped being the latest)\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.AssistantMessageComponent !==\n nextProps.AssistantMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for user messages to prevent re-renders when other messages change.\n */\nconst MemoizedUserMessage = React.memo(\n function MemoizedUserMessage({\n message,\n UserMessageComponent,\n slotProps,\n }: {\n message: UserMessage;\n UserMessageComponent: typeof CopilotChatUserMessage;\n slotProps?: Partial<React.ComponentProps<typeof CopilotChatUserMessage>>;\n }) {\n return <UserMessageComponent message={message} {...slotProps} />;\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent)\n return false;\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n return true;\n },\n);\n\n/**\n * Memoized wrapper for activity messages to prevent re-renders when other messages change.\n */\nconst MemoizedActivityMessage = React.memo(\n function MemoizedActivityMessage({\n message,\n renderActivityMessage,\n }: {\n message: ActivityMessage;\n renderActivityMessage: (\n message: ActivityMessage,\n ) => React.ReactElement | null;\n }) {\n return renderActivityMessage(message);\n },\n (prevProps, nextProps) => {\n // Message ID changed = different message, must re-render\n if (prevProps.message.id !== nextProps.message.id) return false;\n\n // Activity type changed = must re-render\n if (prevProps.message.activityType !== nextProps.message.activityType)\n return false;\n\n // Compare content using JSON.stringify (native code, handles deep comparison)\n if (\n JSON.stringify(prevProps.message.content) !==\n JSON.stringify(nextProps.message.content)\n )\n return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.\n */\nconst MemoizedReasoningMessage = React.memo(\n function MemoizedReasoningMessage({\n message,\n messages,\n isRunning,\n ReasoningMessageComponent,\n slotProps,\n }: {\n message: ReasoningMessage;\n messages: Message[];\n isRunning: boolean;\n ReasoningMessageComponent: typeof CopilotChatReasoningMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }) {\n return (\n <ReasoningMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Re-render when \"latest\" status changes (e.g. reasoning message is no longer the last message\n // because a text message was added after it — this transitions isStreaming from true to false)\n const prevIsLatest =\n prevProps.messages[prevProps.messages.length - 1]?.id ===\n prevProps.message.id;\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (prevIsLatest !== nextIsLatest) return false;\n\n // Only care about isRunning if this message is CURRENTLY the latest\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.ReasoningMessageComponent !==\n nextProps.ReasoningMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for custom messages to prevent re-renders when other messages change.\n */\nconst MemoizedCustomMessage = React.memo(\n function MemoizedCustomMessage({\n message,\n position,\n renderCustomMessage,\n }: {\n message: Message;\n position: \"before\" | \"after\";\n renderCustomMessage: (params: {\n message: Message;\n position: \"before\" | \"after\";\n }) => React.ReactElement | null;\n stateSnapshot?: unknown;\n }) {\n return renderCustomMessage({ message, position });\n },\n (prevProps, nextProps) => {\n // Only re-render if the message or position changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.position !== nextProps.position) return false;\n // Compare message content - for assistant messages this is a string, for others may differ\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.message.role !== nextProps.message.role) return false;\n // Compare state snapshot - custom renderers may depend on state\n if (\n JSON.stringify(prevProps.stateSnapshot) !==\n JSON.stringify(nextProps.stateSnapshot)\n )\n return false;\n // Note: We don't compare renderCustomMessage function reference because it changes\n // frequently. The message and state comparison is sufficient to determine if a re-render is needed.\n return true;\n },\n);\n\nexport type CopilotChatMessageViewProps = Omit<\n WithSlots<\n {\n assistantMessage: typeof CopilotChatAssistantMessage;\n userMessage: typeof CopilotChatUserMessage;\n reasoningMessage: typeof CopilotChatReasoningMessage;\n cursor: typeof CopilotChatMessageView.Cursor;\n },\n {\n isRunning?: boolean;\n messages?: Message[];\n } & React.HTMLAttributes<HTMLDivElement>\n >,\n \"children\"\n> & {\n children?: (props: {\n isRunning: boolean;\n messages: Message[];\n messageElements: React.ReactElement[];\n interruptElement: React.ReactElement | null;\n }) => React.ReactElement;\n};\n\nexport function CopilotChatMessageView({\n messages = [],\n assistantMessage,\n userMessage,\n reasoningMessage,\n cursor,\n isRunning = false,\n children,\n className,\n ...props\n}: CopilotChatMessageViewProps) {\n const renderCustomMessage = useRenderCustomMessages();\n const { renderActivityMessage } = useRenderActivityMessage();\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n // Subscribe to state changes so custom message renderers re-render when state updates.\n useEffect(() => {\n if (!config?.agentId) return;\n const agent = copilotkit.getAgent(config.agentId);\n if (!agent) return;\n\n const subscription = agent.subscribe({\n onStateChanged: forceUpdate,\n });\n return () => subscription.unsubscribe();\n }, [config?.agentId, copilotkit, forceUpdate]);\n\n // Subscribe to interrupt element changes for in-chat rendering.\n const [interruptElement, setInterruptElement] =\n useState<React.ReactElement | null>(null);\n useEffect(() => {\n setInterruptElement(copilotkit.interruptElement);\n const subscription = copilotkit.subscribe({\n onInterruptElementChanged: ({ interruptElement }) => {\n setInterruptElement(interruptElement);\n },\n });\n return () => subscription.unsubscribe();\n }, [copilotkit]);\n\n // Helper to get state snapshot for a message (used for memoization)\n const getStateSnapshotForMessage = (messageId: string): unknown => {\n if (!config) return undefined;\n const resolvedRunId =\n copilotkit.getRunIdForMessage(\n config.agentId,\n config.threadId,\n messageId,\n ) ??\n copilotkit\n .getRunIdsForThread(config.agentId, config.threadId)\n .slice(-1)[0];\n if (!resolvedRunId) return undefined;\n return copilotkit.getStateByRun(\n config.agentId,\n config.threadId,\n resolvedRunId,\n );\n };\n\n const messageElements: React.ReactElement[] = messages\n .flatMap((message) => {\n const elements: (React.ReactElement | null | undefined)[] = [];\n const stateSnapshot = getStateSnapshotForMessage(message.id);\n\n // Render custom message before (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-before`}\n message={message}\n position=\"before\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n // Render the main message using memoized wrappers to prevent unnecessary re-renders\n if (message.role === \"assistant\") {\n // Determine the component and props from slot value\n let AssistantComponent = CopilotChatAssistantMessage;\n let assistantSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatAssistantMessage>>\n | undefined;\n\n if (isReactComponentType(assistantMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n AssistantComponent =\n assistantMessage as typeof CopilotChatAssistantMessage;\n } else if (typeof assistantMessage === \"string\") {\n // className string\n assistantSlotProps = { className: assistantMessage };\n } else if (assistantMessage && typeof assistantMessage === \"object\") {\n // Props object\n assistantSlotProps = assistantMessage as Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }\n\n elements.push(\n <MemoizedAssistantMessage\n key={message.id}\n message={message as AssistantMessage}\n messages={messages}\n isRunning={isRunning}\n AssistantMessageComponent={AssistantComponent}\n slotProps={assistantSlotProps}\n />,\n );\n } else if (message.role === \"user\") {\n // Determine the component and props from slot value\n let UserComponent = CopilotChatUserMessage;\n let userSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatUserMessage>>\n | undefined;\n\n if (isReactComponentType(userMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n UserComponent = userMessage as typeof CopilotChatUserMessage;\n } else if (typeof userMessage === \"string\") {\n // className string\n userSlotProps = { className: userMessage };\n } else if (userMessage && typeof userMessage === \"object\") {\n // Props object\n userSlotProps = userMessage as Partial<\n React.ComponentProps<typeof CopilotChatUserMessage>\n >;\n }\n\n elements.push(\n <MemoizedUserMessage\n key={message.id}\n message={message as UserMessage}\n UserMessageComponent={UserComponent}\n slotProps={userSlotProps}\n />,\n );\n } else if (message.role === \"activity\") {\n // Use memoized wrapper to prevent re-renders when other messages change\n const activityMsg = message as ActivityMessage;\n elements.push(\n <MemoizedActivityMessage\n key={message.id}\n message={activityMsg}\n renderActivityMessage={renderActivityMessage}\n />,\n );\n } else if (message.role === \"reasoning\") {\n // Determine the component and props from slot value\n let ReasoningComponent = CopilotChatReasoningMessage;\n let reasoningSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatReasoningMessage>>\n | undefined;\n\n if (isReactComponentType(reasoningMessage)) {\n ReasoningComponent =\n reasoningMessage as typeof CopilotChatReasoningMessage;\n } else if (typeof reasoningMessage === \"string\") {\n reasoningSlotProps = { className: reasoningMessage };\n } else if (reasoningMessage && typeof reasoningMessage === \"object\") {\n reasoningSlotProps = reasoningMessage as Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }\n\n elements.push(\n <MemoizedReasoningMessage\n key={message.id}\n message={message as ReasoningMessage}\n messages={messages}\n isRunning={isRunning}\n ReasoningMessageComponent={ReasoningComponent}\n slotProps={reasoningSlotProps}\n />,\n );\n }\n\n // Render custom message after (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-after`}\n message={message}\n position=\"after\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n return elements;\n })\n .filter(Boolean) as React.ReactElement[];\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({ messageElements, messages, isRunning, interruptElement })}\n </div>\n );\n }\n\n // Hide the chat-level loading cursor when the last message is a reasoning\n // message — the reasoning card already shows its own loading indicator.\n const lastMessage = messages[messages.length - 1];\n const showCursor = isRunning && lastMessage?.role !== \"reasoning\";\n\n return (\n <div\n data-copilotkit\n className={twMerge(\"cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {messageElements}\n {interruptElement}\n {showCursor && (\n <div className=\"cpk:mt-2\">\n {renderSlot(cursor, CopilotChatMessageView.Cursor, {})}\n </div>\n )}\n </div>\n );\n}\n\nCopilotChatMessageView.Cursor = function Cursor({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={twMerge(\n \"cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1\",\n className,\n )}\n {...props}\n />\n );\n};\n\nexport default CopilotChatMessageView;\n"],"mappings":"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"}
@@ -20,6 +20,7 @@ type CopilotChatMessageViewProps = Omit<WithSlots<{
20
20
  isRunning: boolean;
21
21
  messages: Message[];
22
22
  messageElements: React.ReactElement[];
23
+ interruptElement: React.ReactElement | null;
23
24
  }) => React.ReactElement;
24
25
  };
25
26
  declare function CopilotChatMessageView({
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatMessageView.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"mappings":";;;;;;;;;KAgRY,2BAAA,GAA8B,IAAA,CACxC,SAAA;EAEI,gBAAA,SAAyB,2BAAA;EACzB,WAAA,SAAoB,sBAAA;EACpB,gBAAA,SAAyB,2BAAA;EACzB,MAAA,SAAe,sBAAA,CAAuB,MAAA;AAAA;EAGtC,SAAA;EACA,QAAA,GAAW,OAAA;AAAA,IACT,KAAA,CAAM,cAAA,CAAe,cAAA;EAI3B,QAAA,IAAY,KAAA;IACV,SAAA;IACA,QAAA,EAAU,OAAA;IACV,eAAA,EAAiB,KAAA,CAAM,YAAA;EAAA,MACnB,KAAA,CAAM,YAAA;AAAA;AAAA,iBAGE,sBAAA,CAAA;EACd,QAAA;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,2BAAA,GAA2B,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAVd,sBAAA;EAAA;;;KAgNb,KAAA,CAAM,cAAA,CAAe,cAAA,MAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
1
+ {"version":3,"file":"CopilotChatMessageView.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"mappings":";;;;;;;;;KAgRY,2BAAA,GAA8B,IAAA,CACxC,SAAA;EAEI,gBAAA,SAAyB,2BAAA;EACzB,WAAA,SAAoB,sBAAA;EACpB,gBAAA,SAAyB,2BAAA;EACzB,MAAA,SAAe,sBAAA,CAAuB,MAAA;AAAA;EAGtC,SAAA;EACA,QAAA,GAAW,OAAA;AAAA,IACT,KAAA,CAAM,cAAA,CAAe,cAAA;EAI3B,QAAA,IAAY,KAAA;IACV,SAAA;IACA,QAAA,EAAU,OAAA;IACV,eAAA,EAAiB,KAAA,CAAM,YAAA;IACvB,gBAAA,EAAkB,KAAA,CAAM,YAAA;EAAA,MACpB,KAAA,CAAM,YAAA;AAAA;AAAA,iBAGE,sBAAA,CAAA;EACd,QAAA;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,2BAAA,GAA2B,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAVd,sBAAA;EAAA;;;KAsOb,KAAA,CAAM,cAAA,CAAe,cAAA,MAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
@@ -20,6 +20,7 @@ type CopilotChatMessageViewProps = Omit<WithSlots<{
20
20
  isRunning: boolean;
21
21
  messages: Message[];
22
22
  messageElements: React.ReactElement[];
23
+ interruptElement: React.ReactElement | null;
23
24
  }) => React.ReactElement;
24
25
  };
25
26
  declare function CopilotChatMessageView({
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatMessageView.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"mappings":";;;;;;;;;KAgRY,2BAAA,GAA8B,IAAA,CACxC,SAAA;EAEI,gBAAA,SAAyB,2BAAA;EACzB,WAAA,SAAoB,sBAAA;EACpB,gBAAA,SAAyB,2BAAA;EACzB,MAAA,SAAe,sBAAA,CAAuB,MAAA;AAAA;EAGtC,SAAA;EACA,QAAA,GAAW,OAAA;AAAA,IACT,KAAA,CAAM,cAAA,CAAe,cAAA;EAI3B,QAAA,IAAY,KAAA;IACV,SAAA;IACA,QAAA,EAAU,OAAA;IACV,eAAA,EAAiB,KAAA,CAAM,YAAA;EAAA,MACnB,KAAA,CAAM,YAAA;AAAA;AAAA,iBAGE,sBAAA,CAAA;EACd,QAAA;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,2BAAA,GAA2B,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAVd,sBAAA;EAAA;;;KAgNb,KAAA,CAAM,cAAA,CAAe,cAAA,MAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
1
+ {"version":3,"file":"CopilotChatMessageView.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"mappings":";;;;;;;;;KAgRY,2BAAA,GAA8B,IAAA,CACxC,SAAA;EAEI,gBAAA,SAAyB,2BAAA;EACzB,WAAA,SAAoB,sBAAA;EACpB,gBAAA,SAAyB,2BAAA;EACzB,MAAA,SAAe,sBAAA,CAAuB,MAAA;AAAA;EAGtC,SAAA;EACA,QAAA,GAAW,OAAA;AAAA,IACT,KAAA,CAAM,cAAA,CAAe,cAAA;EAI3B,QAAA,IAAY,KAAA;IACV,SAAA;IACA,QAAA,EAAU,OAAA;IACV,eAAA,EAAiB,KAAA,CAAM,YAAA;IACvB,gBAAA,EAAkB,KAAA,CAAM,YAAA;EAAA,MACpB,KAAA,CAAM,YAAA;AAAA;AAAA,iBAGE,sBAAA,CAAA;EACd,QAAA;EACA,gBAAA;EACA,WAAA;EACA,gBAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,2BAAA,GAA2B,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAVd,sBAAA;EAAA;;;KAsOb,KAAA,CAAM,cAAA,CAAe,cAAA,MAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
@@ -7,7 +7,7 @@ import "../../hooks/index.mjs";
7
7
  import CopilotChatAssistantMessage_default from "./CopilotChatAssistantMessage.mjs";
8
8
  import CopilotChatUserMessage_default from "./CopilotChatUserMessage.mjs";
9
9
  import CopilotChatReasoningMessage_default from "./CopilotChatReasoningMessage.mjs";
10
- import React, { useEffect, useReducer } from "react";
10
+ import React, { useEffect, useReducer, useState } from "react";
11
11
  import { twMerge } from "tailwind-merge";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
13
 
@@ -127,6 +127,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
127
127
  copilotkit,
128
128
  forceUpdate
129
129
  ]);
130
+ const [interruptElement, setInterruptElement] = useState(null);
131
+ useEffect(() => {
132
+ setInterruptElement(copilotkit.interruptElement);
133
+ const subscription = copilotkit.subscribe({ onInterruptElementChanged: ({ interruptElement }) => {
134
+ setInterruptElement(interruptElement);
135
+ } });
136
+ return () => subscription.unsubscribe();
137
+ }, [copilotkit]);
130
138
  const getStateSnapshotForMessage = (messageId) => {
131
139
  if (!config) return void 0;
132
140
  const resolvedRunId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId) ?? copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
@@ -194,25 +202,35 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
194
202
  }, `${message.id}-custom-after`));
195
203
  return elements;
196
204
  }).filter(Boolean);
197
- if (children) return children({
198
- messageElements,
199
- messages,
200
- isRunning
205
+ if (children) return /* @__PURE__ */ jsx("div", {
206
+ "data-copilotkit": true,
207
+ style: { display: "contents" },
208
+ children: children({
209
+ messageElements,
210
+ messages,
211
+ isRunning,
212
+ interruptElement
213
+ })
201
214
  });
202
215
  const lastMessage = messages[messages.length - 1];
203
216
  const showCursor = isRunning && lastMessage?.role !== "reasoning";
204
217
  return /* @__PURE__ */ jsxs("div", {
205
- className: twMerge("flex flex-col", className),
218
+ "data-copilotkit": true,
219
+ className: twMerge("cpk:flex cpk:flex-col", className),
206
220
  ...props,
207
- children: [messageElements, showCursor && /* @__PURE__ */ jsx("div", {
208
- className: "mt-2",
209
- children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
210
- })]
221
+ children: [
222
+ messageElements,
223
+ interruptElement,
224
+ showCursor && /* @__PURE__ */ jsx("div", {
225
+ className: "cpk:mt-2",
226
+ children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
227
+ })
228
+ ]
211
229
  });
212
230
  }
213
231
  CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
214
232
  return /* @__PURE__ */ jsx("div", {
215
- className: twMerge("w-[11px] h-[11px] rounded-full bg-foreground animate-pulse-cursor ml-1", className),
233
+ className: twMerge("cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1", className),
216
234
  ...props
217
235
  });
218
236
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatMessageView.mjs","names":["CopilotChatAssistantMessage","CopilotChatUserMessage","CopilotChatReasoningMessage"],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"sourcesContent":["import React, { useEffect, useReducer } from \"react\";\nimport { WithSlots, renderSlot, isReactComponentType } from \"@/lib/slots\";\nimport CopilotChatAssistantMessage from \"./CopilotChatAssistantMessage\";\nimport CopilotChatUserMessage from \"./CopilotChatUserMessage\";\nimport CopilotChatReasoningMessage from \"./CopilotChatReasoningMessage\";\nimport {\n ActivityMessage,\n AssistantMessage,\n Message,\n ReasoningMessage,\n UserMessage,\n} from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useRenderActivityMessage, useRenderCustomMessages } from \"@/hooks\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useCopilotChatConfiguration } from \"@/providers/CopilotChatConfigurationProvider\";\n\n/**\n * Memoized wrapper for assistant messages to prevent re-renders when other messages change.\n */\nconst MemoizedAssistantMessage = React.memo(\n function MemoizedAssistantMessage({\n message,\n messages,\n isRunning,\n AssistantMessageComponent,\n slotProps,\n }: {\n message: AssistantMessage;\n messages: Message[];\n isRunning: boolean;\n AssistantMessageComponent: typeof CopilotChatAssistantMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }) {\n return (\n <AssistantMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Compare tool calls if present\n const prevToolCalls = prevProps.message.toolCalls;\n const nextToolCalls = nextProps.message.toolCalls;\n if (prevToolCalls?.length !== nextToolCalls?.length) return false;\n if (prevToolCalls && nextToolCalls) {\n for (let i = 0; i < prevToolCalls.length; i++) {\n const prevTc = prevToolCalls[i];\n const nextTc = nextToolCalls[i];\n if (!prevTc || !nextTc) return false;\n if (prevTc.id !== nextTc.id) return false;\n if (prevTc.function.arguments !== nextTc.function.arguments)\n return false;\n }\n }\n\n // Check if tool results changed for this message's tool calls\n // Tool results are separate messages with role=\"tool\" that reference tool call IDs\n if (prevToolCalls && prevToolCalls.length > 0) {\n const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));\n\n const prevToolResults = prevProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n const nextToolResults = nextProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n\n // If number of tool results changed, re-render\n if (prevToolResults.length !== nextToolResults.length) return false;\n\n // If any tool result content changed, re-render\n for (let i = 0; i < prevToolResults.length; i++) {\n if (\n (prevToolResults[i] as any).content !==\n (nextToolResults[i] as any).content\n )\n return false;\n }\n }\n\n // Only care about isRunning if this message is CURRENTLY the latest\n // (we don't need to re-render just because a message stopped being the latest)\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.AssistantMessageComponent !==\n nextProps.AssistantMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for user messages to prevent re-renders when other messages change.\n */\nconst MemoizedUserMessage = React.memo(\n function MemoizedUserMessage({\n message,\n UserMessageComponent,\n slotProps,\n }: {\n message: UserMessage;\n UserMessageComponent: typeof CopilotChatUserMessage;\n slotProps?: Partial<React.ComponentProps<typeof CopilotChatUserMessage>>;\n }) {\n return <UserMessageComponent message={message} {...slotProps} />;\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent)\n return false;\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n return true;\n },\n);\n\n/**\n * Memoized wrapper for activity messages to prevent re-renders when other messages change.\n */\nconst MemoizedActivityMessage = React.memo(\n function MemoizedActivityMessage({\n message,\n renderActivityMessage,\n }: {\n message: ActivityMessage;\n renderActivityMessage: (\n message: ActivityMessage,\n ) => React.ReactElement | null;\n }) {\n return renderActivityMessage(message);\n },\n (prevProps, nextProps) => {\n // Message ID changed = different message, must re-render\n if (prevProps.message.id !== nextProps.message.id) return false;\n\n // Activity type changed = must re-render\n if (prevProps.message.activityType !== nextProps.message.activityType)\n return false;\n\n // Compare content using JSON.stringify (native code, handles deep comparison)\n if (\n JSON.stringify(prevProps.message.content) !==\n JSON.stringify(nextProps.message.content)\n )\n return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.\n */\nconst MemoizedReasoningMessage = React.memo(\n function MemoizedReasoningMessage({\n message,\n messages,\n isRunning,\n ReasoningMessageComponent,\n slotProps,\n }: {\n message: ReasoningMessage;\n messages: Message[];\n isRunning: boolean;\n ReasoningMessageComponent: typeof CopilotChatReasoningMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }) {\n return (\n <ReasoningMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Re-render when \"latest\" status changes (e.g. reasoning message is no longer the last message\n // because a text message was added after it — this transitions isStreaming from true to false)\n const prevIsLatest =\n prevProps.messages[prevProps.messages.length - 1]?.id ===\n prevProps.message.id;\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (prevIsLatest !== nextIsLatest) return false;\n\n // Only care about isRunning if this message is CURRENTLY the latest\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.ReasoningMessageComponent !==\n nextProps.ReasoningMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for custom messages to prevent re-renders when other messages change.\n */\nconst MemoizedCustomMessage = React.memo(\n function MemoizedCustomMessage({\n message,\n position,\n renderCustomMessage,\n }: {\n message: Message;\n position: \"before\" | \"after\";\n renderCustomMessage: (params: {\n message: Message;\n position: \"before\" | \"after\";\n }) => React.ReactElement | null;\n stateSnapshot?: unknown;\n }) {\n return renderCustomMessage({ message, position });\n },\n (prevProps, nextProps) => {\n // Only re-render if the message or position changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.position !== nextProps.position) return false;\n // Compare message content - for assistant messages this is a string, for others may differ\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.message.role !== nextProps.message.role) return false;\n // Compare state snapshot - custom renderers may depend on state\n if (\n JSON.stringify(prevProps.stateSnapshot) !==\n JSON.stringify(nextProps.stateSnapshot)\n )\n return false;\n // Note: We don't compare renderCustomMessage function reference because it changes\n // frequently. The message and state comparison is sufficient to determine if a re-render is needed.\n return true;\n },\n);\n\nexport type CopilotChatMessageViewProps = Omit<\n WithSlots<\n {\n assistantMessage: typeof CopilotChatAssistantMessage;\n userMessage: typeof CopilotChatUserMessage;\n reasoningMessage: typeof CopilotChatReasoningMessage;\n cursor: typeof CopilotChatMessageView.Cursor;\n },\n {\n isRunning?: boolean;\n messages?: Message[];\n } & React.HTMLAttributes<HTMLDivElement>\n >,\n \"children\"\n> & {\n children?: (props: {\n isRunning: boolean;\n messages: Message[];\n messageElements: React.ReactElement[];\n }) => React.ReactElement;\n};\n\nexport function CopilotChatMessageView({\n messages = [],\n assistantMessage,\n userMessage,\n reasoningMessage,\n cursor,\n isRunning = false,\n children,\n className,\n ...props\n}: CopilotChatMessageViewProps) {\n const renderCustomMessage = useRenderCustomMessages();\n const { renderActivityMessage } = useRenderActivityMessage();\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n // Subscribe to state changes so custom message renderers re-render when state updates.\n useEffect(() => {\n if (!config?.agentId) return;\n const agent = copilotkit.getAgent(config.agentId);\n if (!agent) return;\n\n const subscription = agent.subscribe({\n onStateChanged: forceUpdate,\n });\n return () => subscription.unsubscribe();\n }, [config?.agentId, copilotkit, forceUpdate]);\n\n // Helper to get state snapshot for a message (used for memoization)\n const getStateSnapshotForMessage = (messageId: string): unknown => {\n if (!config) return undefined;\n const resolvedRunId =\n copilotkit.getRunIdForMessage(\n config.agentId,\n config.threadId,\n messageId,\n ) ??\n copilotkit\n .getRunIdsForThread(config.agentId, config.threadId)\n .slice(-1)[0];\n if (!resolvedRunId) return undefined;\n return copilotkit.getStateByRun(\n config.agentId,\n config.threadId,\n resolvedRunId,\n );\n };\n\n const messageElements: React.ReactElement[] = messages\n .flatMap((message) => {\n const elements: (React.ReactElement | null | undefined)[] = [];\n const stateSnapshot = getStateSnapshotForMessage(message.id);\n\n // Render custom message before (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-before`}\n message={message}\n position=\"before\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n // Render the main message using memoized wrappers to prevent unnecessary re-renders\n if (message.role === \"assistant\") {\n // Determine the component and props from slot value\n let AssistantComponent = CopilotChatAssistantMessage;\n let assistantSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatAssistantMessage>>\n | undefined;\n\n if (isReactComponentType(assistantMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n AssistantComponent =\n assistantMessage as typeof CopilotChatAssistantMessage;\n } else if (typeof assistantMessage === \"string\") {\n // className string\n assistantSlotProps = { className: assistantMessage };\n } else if (assistantMessage && typeof assistantMessage === \"object\") {\n // Props object\n assistantSlotProps = assistantMessage as Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }\n\n elements.push(\n <MemoizedAssistantMessage\n key={message.id}\n message={message as AssistantMessage}\n messages={messages}\n isRunning={isRunning}\n AssistantMessageComponent={AssistantComponent}\n slotProps={assistantSlotProps}\n />,\n );\n } else if (message.role === \"user\") {\n // Determine the component and props from slot value\n let UserComponent = CopilotChatUserMessage;\n let userSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatUserMessage>>\n | undefined;\n\n if (isReactComponentType(userMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n UserComponent = userMessage as typeof CopilotChatUserMessage;\n } else if (typeof userMessage === \"string\") {\n // className string\n userSlotProps = { className: userMessage };\n } else if (userMessage && typeof userMessage === \"object\") {\n // Props object\n userSlotProps = userMessage as Partial<\n React.ComponentProps<typeof CopilotChatUserMessage>\n >;\n }\n\n elements.push(\n <MemoizedUserMessage\n key={message.id}\n message={message as UserMessage}\n UserMessageComponent={UserComponent}\n slotProps={userSlotProps}\n />,\n );\n } else if (message.role === \"activity\") {\n // Use memoized wrapper to prevent re-renders when other messages change\n const activityMsg = message as ActivityMessage;\n elements.push(\n <MemoizedActivityMessage\n key={message.id}\n message={activityMsg}\n renderActivityMessage={renderActivityMessage}\n />,\n );\n } else if (message.role === \"reasoning\") {\n // Determine the component and props from slot value\n let ReasoningComponent = CopilotChatReasoningMessage;\n let reasoningSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatReasoningMessage>>\n | undefined;\n\n if (isReactComponentType(reasoningMessage)) {\n ReasoningComponent =\n reasoningMessage as typeof CopilotChatReasoningMessage;\n } else if (typeof reasoningMessage === \"string\") {\n reasoningSlotProps = { className: reasoningMessage };\n } else if (reasoningMessage && typeof reasoningMessage === \"object\") {\n reasoningSlotProps = reasoningMessage as Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }\n\n elements.push(\n <MemoizedReasoningMessage\n key={message.id}\n message={message as ReasoningMessage}\n messages={messages}\n isRunning={isRunning}\n ReasoningMessageComponent={ReasoningComponent}\n slotProps={reasoningSlotProps}\n />,\n );\n }\n\n // Render custom message after (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-after`}\n message={message}\n position=\"after\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n return elements;\n })\n .filter(Boolean) as React.ReactElement[];\n\n if (children) {\n return children({ messageElements, messages, isRunning });\n }\n\n // Hide the chat-level loading cursor when the last message is a reasoning\n // message — the reasoning card already shows its own loading indicator.\n const lastMessage = messages[messages.length - 1];\n const showCursor = isRunning && lastMessage?.role !== \"reasoning\";\n\n return (\n <div className={twMerge(\"flex flex-col\", className)} {...props}>\n {messageElements}\n {showCursor && (\n <div className=\"mt-2\">\n {renderSlot(cursor, CopilotChatMessageView.Cursor, {})}\n </div>\n )}\n </div>\n );\n}\n\nCopilotChatMessageView.Cursor = function Cursor({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={twMerge(\n \"w-[11px] h-[11px] rounded-full bg-foreground animate-pulse-cursor ml-1\",\n className,\n )}\n {...props}\n />\n );\n};\n\nexport default CopilotChatMessageView;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CopilotChatMessageView.mjs","names":["CopilotChatAssistantMessage","CopilotChatUserMessage","CopilotChatReasoningMessage"],"sources":["../../../src/components/chat/CopilotChatMessageView.tsx"],"sourcesContent":["import React, { useEffect, useReducer, useState } from \"react\";\nimport { WithSlots, renderSlot, isReactComponentType } from \"@/lib/slots\";\nimport CopilotChatAssistantMessage from \"./CopilotChatAssistantMessage\";\nimport CopilotChatUserMessage from \"./CopilotChatUserMessage\";\nimport CopilotChatReasoningMessage from \"./CopilotChatReasoningMessage\";\nimport {\n ActivityMessage,\n AssistantMessage,\n Message,\n ReasoningMessage,\n UserMessage,\n} from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useRenderActivityMessage, useRenderCustomMessages } from \"@/hooks\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useCopilotChatConfiguration } from \"@/providers/CopilotChatConfigurationProvider\";\n\n/**\n * Memoized wrapper for assistant messages to prevent re-renders when other messages change.\n */\nconst MemoizedAssistantMessage = React.memo(\n function MemoizedAssistantMessage({\n message,\n messages,\n isRunning,\n AssistantMessageComponent,\n slotProps,\n }: {\n message: AssistantMessage;\n messages: Message[];\n isRunning: boolean;\n AssistantMessageComponent: typeof CopilotChatAssistantMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }) {\n return (\n <AssistantMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Compare tool calls if present\n const prevToolCalls = prevProps.message.toolCalls;\n const nextToolCalls = nextProps.message.toolCalls;\n if (prevToolCalls?.length !== nextToolCalls?.length) return false;\n if (prevToolCalls && nextToolCalls) {\n for (let i = 0; i < prevToolCalls.length; i++) {\n const prevTc = prevToolCalls[i];\n const nextTc = nextToolCalls[i];\n if (!prevTc || !nextTc) return false;\n if (prevTc.id !== nextTc.id) return false;\n if (prevTc.function.arguments !== nextTc.function.arguments)\n return false;\n }\n }\n\n // Check if tool results changed for this message's tool calls\n // Tool results are separate messages with role=\"tool\" that reference tool call IDs\n if (prevToolCalls && prevToolCalls.length > 0) {\n const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));\n\n const prevToolResults = prevProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n const nextToolResults = nextProps.messages.filter(\n (m) => m.role === \"tool\" && toolCallIds.has((m as any).toolCallId),\n );\n\n // If number of tool results changed, re-render\n if (prevToolResults.length !== nextToolResults.length) return false;\n\n // If any tool result content changed, re-render\n for (let i = 0; i < prevToolResults.length; i++) {\n if (\n (prevToolResults[i] as any).content !==\n (nextToolResults[i] as any).content\n )\n return false;\n }\n }\n\n // Only care about isRunning if this message is CURRENTLY the latest\n // (we don't need to re-render just because a message stopped being the latest)\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.AssistantMessageComponent !==\n nextProps.AssistantMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for user messages to prevent re-renders when other messages change.\n */\nconst MemoizedUserMessage = React.memo(\n function MemoizedUserMessage({\n message,\n UserMessageComponent,\n slotProps,\n }: {\n message: UserMessage;\n UserMessageComponent: typeof CopilotChatUserMessage;\n slotProps?: Partial<React.ComponentProps<typeof CopilotChatUserMessage>>;\n }) {\n return <UserMessageComponent message={message} {...slotProps} />;\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent)\n return false;\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n return true;\n },\n);\n\n/**\n * Memoized wrapper for activity messages to prevent re-renders when other messages change.\n */\nconst MemoizedActivityMessage = React.memo(\n function MemoizedActivityMessage({\n message,\n renderActivityMessage,\n }: {\n message: ActivityMessage;\n renderActivityMessage: (\n message: ActivityMessage,\n ) => React.ReactElement | null;\n }) {\n return renderActivityMessage(message);\n },\n (prevProps, nextProps) => {\n // Message ID changed = different message, must re-render\n if (prevProps.message.id !== nextProps.message.id) return false;\n\n // Activity type changed = must re-render\n if (prevProps.message.activityType !== nextProps.message.activityType)\n return false;\n\n // Compare content using JSON.stringify (native code, handles deep comparison)\n if (\n JSON.stringify(prevProps.message.content) !==\n JSON.stringify(nextProps.message.content)\n )\n return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for reasoning messages to prevent re-renders when other messages change.\n */\nconst MemoizedReasoningMessage = React.memo(\n function MemoizedReasoningMessage({\n message,\n messages,\n isRunning,\n ReasoningMessageComponent,\n slotProps,\n }: {\n message: ReasoningMessage;\n messages: Message[];\n isRunning: boolean;\n ReasoningMessageComponent: typeof CopilotChatReasoningMessage;\n slotProps?: Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }) {\n return (\n <ReasoningMessageComponent\n message={message}\n messages={messages}\n isRunning={isRunning}\n {...slotProps}\n />\n );\n },\n (prevProps, nextProps) => {\n // Only re-render if this specific message changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.message.content !== nextProps.message.content) return false;\n\n // Re-render when \"latest\" status changes (e.g. reasoning message is no longer the last message\n // because a text message was added after it — this transitions isStreaming from true to false)\n const prevIsLatest =\n prevProps.messages[prevProps.messages.length - 1]?.id ===\n prevProps.message.id;\n const nextIsLatest =\n nextProps.messages[nextProps.messages.length - 1]?.id ===\n nextProps.message.id;\n if (prevIsLatest !== nextIsLatest) return false;\n\n // Only care about isRunning if this message is CURRENTLY the latest\n if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning)\n return false;\n\n // Check if component reference changed\n if (\n prevProps.ReasoningMessageComponent !==\n nextProps.ReasoningMessageComponent\n )\n return false;\n\n // Check if slot props changed\n if (prevProps.slotProps !== nextProps.slotProps) return false;\n\n return true;\n },\n);\n\n/**\n * Memoized wrapper for custom messages to prevent re-renders when other messages change.\n */\nconst MemoizedCustomMessage = React.memo(\n function MemoizedCustomMessage({\n message,\n position,\n renderCustomMessage,\n }: {\n message: Message;\n position: \"before\" | \"after\";\n renderCustomMessage: (params: {\n message: Message;\n position: \"before\" | \"after\";\n }) => React.ReactElement | null;\n stateSnapshot?: unknown;\n }) {\n return renderCustomMessage({ message, position });\n },\n (prevProps, nextProps) => {\n // Only re-render if the message or position changed\n if (prevProps.message.id !== nextProps.message.id) return false;\n if (prevProps.position !== nextProps.position) return false;\n // Compare message content - for assistant messages this is a string, for others may differ\n if (prevProps.message.content !== nextProps.message.content) return false;\n if (prevProps.message.role !== nextProps.message.role) return false;\n // Compare state snapshot - custom renderers may depend on state\n if (\n JSON.stringify(prevProps.stateSnapshot) !==\n JSON.stringify(nextProps.stateSnapshot)\n )\n return false;\n // Note: We don't compare renderCustomMessage function reference because it changes\n // frequently. The message and state comparison is sufficient to determine if a re-render is needed.\n return true;\n },\n);\n\nexport type CopilotChatMessageViewProps = Omit<\n WithSlots<\n {\n assistantMessage: typeof CopilotChatAssistantMessage;\n userMessage: typeof CopilotChatUserMessage;\n reasoningMessage: typeof CopilotChatReasoningMessage;\n cursor: typeof CopilotChatMessageView.Cursor;\n },\n {\n isRunning?: boolean;\n messages?: Message[];\n } & React.HTMLAttributes<HTMLDivElement>\n >,\n \"children\"\n> & {\n children?: (props: {\n isRunning: boolean;\n messages: Message[];\n messageElements: React.ReactElement[];\n interruptElement: React.ReactElement | null;\n }) => React.ReactElement;\n};\n\nexport function CopilotChatMessageView({\n messages = [],\n assistantMessage,\n userMessage,\n reasoningMessage,\n cursor,\n isRunning = false,\n children,\n className,\n ...props\n}: CopilotChatMessageViewProps) {\n const renderCustomMessage = useRenderCustomMessages();\n const { renderActivityMessage } = useRenderActivityMessage();\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n // Subscribe to state changes so custom message renderers re-render when state updates.\n useEffect(() => {\n if (!config?.agentId) return;\n const agent = copilotkit.getAgent(config.agentId);\n if (!agent) return;\n\n const subscription = agent.subscribe({\n onStateChanged: forceUpdate,\n });\n return () => subscription.unsubscribe();\n }, [config?.agentId, copilotkit, forceUpdate]);\n\n // Subscribe to interrupt element changes for in-chat rendering.\n const [interruptElement, setInterruptElement] =\n useState<React.ReactElement | null>(null);\n useEffect(() => {\n setInterruptElement(copilotkit.interruptElement);\n const subscription = copilotkit.subscribe({\n onInterruptElementChanged: ({ interruptElement }) => {\n setInterruptElement(interruptElement);\n },\n });\n return () => subscription.unsubscribe();\n }, [copilotkit]);\n\n // Helper to get state snapshot for a message (used for memoization)\n const getStateSnapshotForMessage = (messageId: string): unknown => {\n if (!config) return undefined;\n const resolvedRunId =\n copilotkit.getRunIdForMessage(\n config.agentId,\n config.threadId,\n messageId,\n ) ??\n copilotkit\n .getRunIdsForThread(config.agentId, config.threadId)\n .slice(-1)[0];\n if (!resolvedRunId) return undefined;\n return copilotkit.getStateByRun(\n config.agentId,\n config.threadId,\n resolvedRunId,\n );\n };\n\n const messageElements: React.ReactElement[] = messages\n .flatMap((message) => {\n const elements: (React.ReactElement | null | undefined)[] = [];\n const stateSnapshot = getStateSnapshotForMessage(message.id);\n\n // Render custom message before (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-before`}\n message={message}\n position=\"before\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n // Render the main message using memoized wrappers to prevent unnecessary re-renders\n if (message.role === \"assistant\") {\n // Determine the component and props from slot value\n let AssistantComponent = CopilotChatAssistantMessage;\n let assistantSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatAssistantMessage>>\n | undefined;\n\n if (isReactComponentType(assistantMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n AssistantComponent =\n assistantMessage as typeof CopilotChatAssistantMessage;\n } else if (typeof assistantMessage === \"string\") {\n // className string\n assistantSlotProps = { className: assistantMessage };\n } else if (assistantMessage && typeof assistantMessage === \"object\") {\n // Props object\n assistantSlotProps = assistantMessage as Partial<\n React.ComponentProps<typeof CopilotChatAssistantMessage>\n >;\n }\n\n elements.push(\n <MemoizedAssistantMessage\n key={message.id}\n message={message as AssistantMessage}\n messages={messages}\n isRunning={isRunning}\n AssistantMessageComponent={AssistantComponent}\n slotProps={assistantSlotProps}\n />,\n );\n } else if (message.role === \"user\") {\n // Determine the component and props from slot value\n let UserComponent = CopilotChatUserMessage;\n let userSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatUserMessage>>\n | undefined;\n\n if (isReactComponentType(userMessage)) {\n // Custom component (function, forwardRef, memo, etc.)\n UserComponent = userMessage as typeof CopilotChatUserMessage;\n } else if (typeof userMessage === \"string\") {\n // className string\n userSlotProps = { className: userMessage };\n } else if (userMessage && typeof userMessage === \"object\") {\n // Props object\n userSlotProps = userMessage as Partial<\n React.ComponentProps<typeof CopilotChatUserMessage>\n >;\n }\n\n elements.push(\n <MemoizedUserMessage\n key={message.id}\n message={message as UserMessage}\n UserMessageComponent={UserComponent}\n slotProps={userSlotProps}\n />,\n );\n } else if (message.role === \"activity\") {\n // Use memoized wrapper to prevent re-renders when other messages change\n const activityMsg = message as ActivityMessage;\n elements.push(\n <MemoizedActivityMessage\n key={message.id}\n message={activityMsg}\n renderActivityMessage={renderActivityMessage}\n />,\n );\n } else if (message.role === \"reasoning\") {\n // Determine the component and props from slot value\n let ReasoningComponent = CopilotChatReasoningMessage;\n let reasoningSlotProps:\n | Partial<React.ComponentProps<typeof CopilotChatReasoningMessage>>\n | undefined;\n\n if (isReactComponentType(reasoningMessage)) {\n ReasoningComponent =\n reasoningMessage as typeof CopilotChatReasoningMessage;\n } else if (typeof reasoningMessage === \"string\") {\n reasoningSlotProps = { className: reasoningMessage };\n } else if (reasoningMessage && typeof reasoningMessage === \"object\") {\n reasoningSlotProps = reasoningMessage as Partial<\n React.ComponentProps<typeof CopilotChatReasoningMessage>\n >;\n }\n\n elements.push(\n <MemoizedReasoningMessage\n key={message.id}\n message={message as ReasoningMessage}\n messages={messages}\n isRunning={isRunning}\n ReasoningMessageComponent={ReasoningComponent}\n slotProps={reasoningSlotProps}\n />,\n );\n }\n\n // Render custom message after (using memoized wrapper)\n if (renderCustomMessage) {\n elements.push(\n <MemoizedCustomMessage\n key={`${message.id}-custom-after`}\n message={message}\n position=\"after\"\n renderCustomMessage={renderCustomMessage}\n stateSnapshot={stateSnapshot}\n />,\n );\n }\n\n return elements;\n })\n .filter(Boolean) as React.ReactElement[];\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({ messageElements, messages, isRunning, interruptElement })}\n </div>\n );\n }\n\n // Hide the chat-level loading cursor when the last message is a reasoning\n // message — the reasoning card already shows its own loading indicator.\n const lastMessage = messages[messages.length - 1];\n const showCursor = isRunning && lastMessage?.role !== \"reasoning\";\n\n return (\n <div\n data-copilotkit\n className={twMerge(\"cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {messageElements}\n {interruptElement}\n {showCursor && (\n <div className=\"cpk:mt-2\">\n {renderSlot(cursor, CopilotChatMessageView.Cursor, {})}\n </div>\n )}\n </div>\n );\n}\n\nCopilotChatMessageView.Cursor = function Cursor({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={twMerge(\n \"cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1\",\n className,\n )}\n {...props}\n />\n );\n};\n\nexport default CopilotChatMessageView;\n"],"mappings":"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"}
@@ -58,16 +58,20 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, header, con
58
58
  isOpen,
59
59
  children: boundContent
60
60
  });
61
- if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: children({
62
- header: boundHeader,
63
- contentView: boundContent,
64
- toggle: boundToggle,
65
- message,
66
- messages,
67
- isRunning
68
- }) });
61
+ if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
62
+ "data-copilotkit": true,
63
+ style: { display: "contents" },
64
+ children: children({
65
+ header: boundHeader,
66
+ contentView: boundContent,
67
+ toggle: boundToggle,
68
+ message,
69
+ messages,
70
+ isRunning
71
+ })
72
+ });
69
73
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
70
- className: (0, tailwind_merge.twMerge)("my-1", className),
74
+ className: (0, tailwind_merge.twMerge)("cpk:my-1", className),
71
75
  "data-message-id": message.id,
72
76
  ...props,
73
77
  children: [boundHeader, boundToggle]
@@ -78,44 +82,44 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, header, con
78
82
  const isExpandable = !!hasContent;
79
83
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
80
84
  type: "button",
81
- className: (0, tailwind_merge.twMerge)("inline-flex items-center gap-1 py-1 text-sm text-muted-foreground transition-colors select-none", isExpandable ? "hover:text-foreground cursor-pointer" : "cursor-default", className),
85
+ className: (0, tailwind_merge.twMerge)("cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none", isExpandable ? "cpk:hover:text-foreground cpk:cursor-pointer" : "cpk:cursor-default", className),
82
86
  "aria-expanded": isExpandable ? isOpen : void 0,
83
87
  ...headerProps,
84
88
  children: [
85
89
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
86
- className: "font-medium",
90
+ className: "cpk:font-medium",
87
91
  children: label
88
92
  }),
89
93
  isStreaming && !hasContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
90
- className: "inline-flex items-center ml-1",
91
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground animate-pulse" })
94
+ className: "cpk:inline-flex cpk:items-center cpk:ml-1",
95
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse" })
92
96
  }),
93
97
  headerChildren,
94
- isExpandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: (0, tailwind_merge.twMerge)("size-3.5 shrink-0 transition-transform duration-200", isOpen && "rotate-90") })
98
+ isExpandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: (0, tailwind_merge.twMerge)("cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200", isOpen && "cpk:rotate-90") })
95
99
  ]
96
100
  });
97
101
  };
98
102
  _CopilotChatReasoningMessage.Content = ({ isStreaming, hasContent, className, children: contentChildren, ...contentProps }) => {
99
103
  if (!hasContent && !isStreaming) return null;
100
104
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
101
- className: (0, tailwind_merge.twMerge)("pb-2 pt-1", className),
105
+ className: (0, tailwind_merge.twMerge)("cpk:pb-2 cpk:pt-1", className),
102
106
  ...contentProps,
103
107
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
104
- className: "text-sm text-muted-foreground",
108
+ className: "cpk:text-sm cpk:text-muted-foreground",
105
109
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(streamdown.Streamdown, { children: typeof contentChildren === "string" ? contentChildren : "" }), isStreaming && hasContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
106
- className: "inline-flex items-center ml-1 align-middle",
107
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "w-2 h-2 rounded-full bg-muted-foreground animate-pulse-cursor" })
110
+ className: "cpk:inline-flex cpk:items-center cpk:ml-1 cpk:align-middle",
111
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cpk:w-2 cpk:h-2 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse-cursor" })
108
112
  })]
109
113
  })
110
114
  });
111
115
  };
112
116
  _CopilotChatReasoningMessage.Toggle = ({ isOpen, className, children: toggleChildren, ...toggleProps }) => {
113
117
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
114
- className: (0, tailwind_merge.twMerge)("grid transition-[grid-template-rows] duration-200 ease-in-out", className),
118
+ className: (0, tailwind_merge.twMerge)("cpk:grid cpk:transition-[grid-template-rows] cpk:duration-200 cpk:ease-in-out", className),
115
119
  style: { gridTemplateRows: isOpen ? "1fr" : "0fr" },
116
120
  ...toggleProps,
117
121
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
118
- className: "overflow-hidden",
122
+ className: "cpk:overflow-hidden",
119
123
  children: toggleChildren
120
124
  })
121
125
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatReasoningMessage.cjs","names":["renderSlot","ChevronRight","Streamdown"],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"sourcesContent":["import { ReasoningMessage, Message } from \"@ag-ui/core\";\nimport { useState, useEffect, useRef } from \"react\";\nimport { ChevronRight } from \"lucide-react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Streamdown } from \"streamdown\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\n\nexport type CopilotChatReasoningMessageProps = WithSlots<\n {\n header: typeof CopilotChatReasoningMessage.Header;\n contentView: typeof CopilotChatReasoningMessage.Content;\n toggle: typeof CopilotChatReasoningMessage.Toggle;\n },\n {\n message: ReasoningMessage;\n messages?: Message[];\n isRunning?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\n/**\n * Formats an elapsed duration (in seconds) to a human-readable string.\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 1) return \"a few seconds\";\n if (seconds < 60) return `${Math.round(seconds)} seconds`;\n const mins = Math.floor(seconds / 60);\n const secs = Math.round(seconds % 60);\n if (secs === 0) return `${mins} minute${mins > 1 ? \"s\" : \"\"}`;\n return `${mins}m ${secs}s`;\n}\n\nexport function CopilotChatReasoningMessage({\n message,\n messages,\n isRunning,\n header,\n contentView,\n toggle,\n children,\n className,\n ...props\n}: CopilotChatReasoningMessageProps) {\n const isLatest = messages?.[messages.length - 1]?.id === message.id;\n const isStreaming = !!(isRunning && isLatest);\n const hasContent = !!(message.content && message.content.length > 0);\n\n // Track elapsed time while streaming\n const startTimeRef = useRef<number | null>(null);\n const [elapsed, setElapsed] = useState(0);\n\n useEffect(() => {\n if (isStreaming && startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n\n if (!isStreaming && startTimeRef.current !== null) {\n // Final snapshot of elapsed time\n setElapsed((Date.now() - startTimeRef.current) / 1000);\n return;\n }\n\n if (!isStreaming) return;\n\n // Tick every second while streaming\n const timer = setInterval(() => {\n if (startTimeRef.current !== null) {\n setElapsed((Date.now() - startTimeRef.current) / 1000);\n }\n }, 1000);\n return () => clearInterval(timer);\n }, [isStreaming]);\n\n // Default to open while streaming, auto-collapse when streaming ends\n const [isOpen, setIsOpen] = useState(isStreaming);\n\n useEffect(() => {\n if (isStreaming) {\n setIsOpen(true);\n } else {\n // Auto-collapse when reasoning finishes\n setIsOpen(false);\n }\n }, [isStreaming]);\n\n const label = isStreaming\n ? \"Thinking…\"\n : `Thought for ${formatDuration(elapsed)}`;\n\n const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {\n isOpen,\n label,\n hasContent,\n isStreaming,\n onClick: hasContent ? () => setIsOpen((prev) => !prev) : undefined,\n });\n\n const boundContent = renderSlot(\n contentView,\n CopilotChatReasoningMessage.Content,\n {\n isStreaming,\n hasContent,\n children: message.content,\n },\n );\n\n const boundToggle = renderSlot(toggle, CopilotChatReasoningMessage.Toggle, {\n isOpen,\n children: boundContent,\n });\n\n if (children) {\n return (\n <>\n {children({\n header: boundHeader,\n contentView: boundContent,\n toggle: boundToggle,\n message,\n messages,\n isRunning,\n })}\n </>\n );\n }\n\n return (\n <div\n className={twMerge(\"my-1\", className)}\n data-message-id={message.id}\n {...props}\n >\n {boundHeader}\n {boundToggle}\n </div>\n );\n}\n\nexport namespace CopilotChatReasoningMessage {\n export const Header: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n isOpen?: boolean;\n label?: string;\n hasContent?: boolean;\n isStreaming?: boolean;\n }\n > = ({\n isOpen,\n label = \"Thoughts\",\n hasContent,\n isStreaming,\n className,\n children: headerChildren,\n ...headerProps\n }) => {\n const isExpandable = !!hasContent;\n\n return (\n <button\n type=\"button\"\n className={twMerge(\n \"inline-flex items-center gap-1 py-1 text-sm text-muted-foreground transition-colors select-none\",\n isExpandable\n ? \"hover:text-foreground cursor-pointer\"\n : \"cursor-default\",\n className,\n )}\n aria-expanded={isExpandable ? isOpen : undefined}\n {...headerProps}\n >\n <span className=\"font-medium\">{label}</span>\n {isStreaming && !hasContent && (\n <span className=\"inline-flex items-center ml-1\">\n <span className=\"w-1.5 h-1.5 rounded-full bg-muted-foreground animate-pulse\" />\n </span>\n )}\n {headerChildren}\n {isExpandable && (\n <ChevronRight\n className={twMerge(\n \"size-3.5 shrink-0 transition-transform duration-200\",\n isOpen && \"rotate-90\",\n )}\n />\n )}\n </button>\n );\n };\n\n export const Content: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n isStreaming?: boolean;\n hasContent?: boolean;\n }\n > = ({\n isStreaming,\n hasContent,\n className,\n children: contentChildren,\n ...contentProps\n }) => {\n // Don't render the content area at all when there's nothing to show\n if (!hasContent && !isStreaming) return null;\n\n return (\n <div className={twMerge(\"pb-2 pt-1\", className)} {...contentProps}>\n <div className=\"text-sm text-muted-foreground\">\n <Streamdown>\n {typeof contentChildren === \"string\" ? contentChildren : \"\"}\n </Streamdown>\n {isStreaming && hasContent && (\n <span className=\"inline-flex items-center ml-1 align-middle\">\n <span className=\"w-2 h-2 rounded-full bg-muted-foreground animate-pulse-cursor\" />\n </span>\n )}\n </div>\n </div>\n );\n };\n\n export const Toggle: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n isOpen?: boolean;\n }\n > = ({ isOpen, className, children: toggleChildren, ...toggleProps }) => {\n return (\n <div\n className={twMerge(\n \"grid transition-[grid-template-rows] duration-200 ease-in-out\",\n className,\n )}\n style={{ gridTemplateRows: isOpen ? \"1fr\" : \"0fr\" }}\n {...toggleProps}\n >\n <div className=\"overflow-hidden\">{toggleChildren}</div>\n </div>\n );\n };\n}\n\nCopilotChatReasoningMessage.Header.displayName =\n \"CopilotChatReasoningMessage.Header\";\nCopilotChatReasoningMessage.Content.displayName =\n \"CopilotChatReasoningMessage.Content\";\nCopilotChatReasoningMessage.Toggle.displayName =\n \"CopilotChatReasoningMessage.Toggle\";\n\nexport default CopilotChatReasoningMessage;\n"],"mappings":";;;;;;;;;;;;AAuBA,SAAS,eAAe,SAAyB;AAC/C,KAAI,UAAU,EAAG,QAAO;AACxB,KAAI,UAAU,GAAI,QAAO,GAAG,KAAK,MAAM,QAAQ,CAAC;CAChD,MAAM,OAAO,KAAK,MAAM,UAAU,GAAG;CACrC,MAAM,OAAO,KAAK,MAAM,UAAU,GAAG;AACrC,KAAI,SAAS,EAAG,QAAO,GAAG,KAAK,SAAS,OAAO,IAAI,MAAM;AACzD,QAAO,GAAG,KAAK,IAAI,KAAK;;AAG1B,SAAgB,4BAA4B,EAC1C,SACA,UACA,WACA,QACA,aACA,QACA,UACA,WACA,GAAG,SACgC;CACnC,MAAM,WAAW,WAAW,SAAS,SAAS,IAAI,OAAO,QAAQ;CACjE,MAAM,cAAc,CAAC,EAAE,aAAa;CACpC,MAAM,aAAa,CAAC,EAAE,QAAQ,WAAW,QAAQ,QAAQ,SAAS;CAGlE,MAAM,iCAAqC,KAAK;CAChD,MAAM,CAAC,SAAS,kCAAuB,EAAE;AAEzC,4BAAgB;AACd,MAAI,eAAe,aAAa,YAAY,KAC1C,cAAa,UAAU,KAAK,KAAK;AAGnC,MAAI,CAAC,eAAe,aAAa,YAAY,MAAM;AAEjD,eAAY,KAAK,KAAK,GAAG,aAAa,WAAW,IAAK;AACtD;;AAGF,MAAI,CAAC,YAAa;EAGlB,MAAM,QAAQ,kBAAkB;AAC9B,OAAI,aAAa,YAAY,KAC3B,aAAY,KAAK,KAAK,GAAG,aAAa,WAAW,IAAK;KAEvD,IAAK;AACR,eAAa,cAAc,MAAM;IAChC,CAAC,YAAY,CAAC;CAGjB,MAAM,CAAC,QAAQ,iCAAsB,YAAY;AAEjD,4BAAgB;AACd,MAAI,YACF,WAAU,KAAK;MAGf,WAAU,MAAM;IAEjB,CAAC,YAAY,CAAC;CAEjB,MAAM,QAAQ,cACV,cACA,eAAe,eAAe,QAAQ;CAE1C,MAAM,cAAcA,yBAAW,QAAQ,4BAA4B,QAAQ;EACzE;EACA;EACA;EACA;EACA,SAAS,mBAAmB,WAAW,SAAS,CAAC,KAAK,GAAG;EAC1D,CAAC;CAEF,MAAM,eAAeA,yBACnB,aACA,4BAA4B,SAC5B;EACE;EACA;EACA,UAAU,QAAQ;EACnB,CACF;CAED,MAAM,cAAcA,yBAAW,QAAQ,4BAA4B,QAAQ;EACzE;EACA,UAAU;EACX,CAAC;AAEF,KAAI,SACF,QACE,mFACG,SAAS;EACR,QAAQ;EACR,aAAa;EACb,QAAQ;EACR;EACA;EACA;EACD,CAAC,GACD;AAIP,QACE,4CAAC;EACC,uCAAmB,QAAQ,UAAU;EACrC,mBAAiB,QAAQ;EACzB,GAAI;aAEH,aACA;GACG;;;wCAYH,EACH,QACA,QAAQ,YACR,YACA,aACA,WACA,UAAU,gBACV,GAAG,kBACC;EACJ,MAAM,eAAe,CAAC,CAAC;AAEvB,SACE,4CAAC;GACC,MAAK;GACL,uCACE,mGACA,eACI,yCACA,kBACJ,UACD;GACD,iBAAe,eAAe,SAAS;GACvC,GAAI;;IAEJ,2CAAC;KAAK,WAAU;eAAe;MAAa;IAC3C,eAAe,CAAC,cACf,2CAAC;KAAK,WAAU;eACd,2CAAC,UAAK,WAAU,+DAA+D;MAC1E;IAER;IACA,gBACC,2CAACC,6BACC,uCACE,uDACA,UAAU,YACX,GACD;;IAEG;;yCASR,EACH,aACA,YACA,WACA,UAAU,iBACV,GAAG,mBACC;AAEJ,MAAI,CAAC,cAAc,CAAC,YAAa,QAAO;AAExC,SACE,2CAAC;GAAI,uCAAmB,aAAa,UAAU;GAAE,GAAI;aACnD,4CAAC;IAAI,WAAU;eACb,2CAACC,mCACE,OAAO,oBAAoB,WAAW,kBAAkB,KAC9C,EACZ,eAAe,cACd,2CAAC;KAAK,WAAU;eACd,2CAAC,UAAK,WAAU,kEAAkE;MAC7E;KAEL;IACF;;wCAQL,EAAE,QAAQ,WAAW,UAAU,gBAAgB,GAAG,kBAAkB;AACvE,SACE,2CAAC;GACC,uCACE,iEACA,UACD;GACD,OAAO,EAAE,kBAAkB,SAAS,QAAQ,OAAO;GACnD,GAAI;aAEJ,2CAAC;IAAI,WAAU;cAAmB;KAAqB;IACnD;;;AAKZ,4BAA4B,OAAO,cACjC;AACF,4BAA4B,QAAQ,cAClC;AACF,4BAA4B,OAAO,cACjC;AAEF,0CAAe"}
1
+ {"version":3,"file":"CopilotChatReasoningMessage.cjs","names":["renderSlot","ChevronRight","Streamdown"],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"sourcesContent":["import { ReasoningMessage, Message } from \"@ag-ui/core\";\nimport { useState, useEffect, useRef } from \"react\";\nimport { ChevronRight } from \"lucide-react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Streamdown } from \"streamdown\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\n\nexport type CopilotChatReasoningMessageProps = WithSlots<\n {\n header: typeof CopilotChatReasoningMessage.Header;\n contentView: typeof CopilotChatReasoningMessage.Content;\n toggle: typeof CopilotChatReasoningMessage.Toggle;\n },\n {\n message: ReasoningMessage;\n messages?: Message[];\n isRunning?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\n/**\n * Formats an elapsed duration (in seconds) to a human-readable string.\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 1) return \"a few seconds\";\n if (seconds < 60) return `${Math.round(seconds)} seconds`;\n const mins = Math.floor(seconds / 60);\n const secs = Math.round(seconds % 60);\n if (secs === 0) return `${mins} minute${mins > 1 ? \"s\" : \"\"}`;\n return `${mins}m ${secs}s`;\n}\n\nexport function CopilotChatReasoningMessage({\n message,\n messages,\n isRunning,\n header,\n contentView,\n toggle,\n children,\n className,\n ...props\n}: CopilotChatReasoningMessageProps) {\n const isLatest = messages?.[messages.length - 1]?.id === message.id;\n const isStreaming = !!(isRunning && isLatest);\n const hasContent = !!(message.content && message.content.length > 0);\n\n // Track elapsed time while streaming\n const startTimeRef = useRef<number | null>(null);\n const [elapsed, setElapsed] = useState(0);\n\n useEffect(() => {\n if (isStreaming && startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n\n if (!isStreaming && startTimeRef.current !== null) {\n // Final snapshot of elapsed time\n setElapsed((Date.now() - startTimeRef.current) / 1000);\n return;\n }\n\n if (!isStreaming) return;\n\n // Tick every second while streaming\n const timer = setInterval(() => {\n if (startTimeRef.current !== null) {\n setElapsed((Date.now() - startTimeRef.current) / 1000);\n }\n }, 1000);\n return () => clearInterval(timer);\n }, [isStreaming]);\n\n // Default to open while streaming, auto-collapse when streaming ends\n const [isOpen, setIsOpen] = useState(isStreaming);\n\n useEffect(() => {\n if (isStreaming) {\n setIsOpen(true);\n } else {\n // Auto-collapse when reasoning finishes\n setIsOpen(false);\n }\n }, [isStreaming]);\n\n const label = isStreaming\n ? \"Thinking…\"\n : `Thought for ${formatDuration(elapsed)}`;\n\n const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {\n isOpen,\n label,\n hasContent,\n isStreaming,\n onClick: hasContent ? () => setIsOpen((prev) => !prev) : undefined,\n });\n\n const boundContent = renderSlot(\n contentView,\n CopilotChatReasoningMessage.Content,\n {\n isStreaming,\n hasContent,\n children: message.content,\n },\n );\n\n const boundToggle = renderSlot(toggle, CopilotChatReasoningMessage.Toggle, {\n isOpen,\n children: boundContent,\n });\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n header: boundHeader,\n contentView: boundContent,\n toggle: boundToggle,\n message,\n messages,\n isRunning,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={twMerge(\"cpk:my-1\", className)}\n data-message-id={message.id}\n {...props}\n >\n {boundHeader}\n {boundToggle}\n </div>\n );\n}\n\nexport namespace CopilotChatReasoningMessage {\n export const Header: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n isOpen?: boolean;\n label?: string;\n hasContent?: boolean;\n isStreaming?: boolean;\n }\n > = ({\n isOpen,\n label = \"Thoughts\",\n hasContent,\n isStreaming,\n className,\n children: headerChildren,\n ...headerProps\n }) => {\n const isExpandable = !!hasContent;\n\n return (\n <button\n type=\"button\"\n className={twMerge(\n \"cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none\",\n isExpandable\n ? \"cpk:hover:text-foreground cpk:cursor-pointer\"\n : \"cpk:cursor-default\",\n className,\n )}\n aria-expanded={isExpandable ? isOpen : undefined}\n {...headerProps}\n >\n <span className=\"cpk:font-medium\">{label}</span>\n {isStreaming && !hasContent && (\n <span className=\"cpk:inline-flex cpk:items-center cpk:ml-1\">\n <span className=\"cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse\" />\n </span>\n )}\n {headerChildren}\n {isExpandable && (\n <ChevronRight\n className={twMerge(\n \"cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200\",\n isOpen && \"cpk:rotate-90\",\n )}\n />\n )}\n </button>\n );\n };\n\n export const Content: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n isStreaming?: boolean;\n hasContent?: boolean;\n }\n > = ({\n isStreaming,\n hasContent,\n className,\n children: contentChildren,\n ...contentProps\n }) => {\n // Don't render the content area at all when there's nothing to show\n if (!hasContent && !isStreaming) return null;\n\n return (\n <div\n className={twMerge(\"cpk:pb-2 cpk:pt-1\", className)}\n {...contentProps}\n >\n <div className=\"cpk:text-sm cpk:text-muted-foreground\">\n <Streamdown>\n {typeof contentChildren === \"string\" ? contentChildren : \"\"}\n </Streamdown>\n {isStreaming && hasContent && (\n <span className=\"cpk:inline-flex cpk:items-center cpk:ml-1 cpk:align-middle\">\n <span className=\"cpk:w-2 cpk:h-2 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse-cursor\" />\n </span>\n )}\n </div>\n </div>\n );\n };\n\n export const Toggle: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n isOpen?: boolean;\n }\n > = ({ isOpen, className, children: toggleChildren, ...toggleProps }) => {\n return (\n <div\n className={twMerge(\n \"cpk:grid cpk:transition-[grid-template-rows] cpk:duration-200 cpk:ease-in-out\",\n className,\n )}\n style={{ gridTemplateRows: isOpen ? \"1fr\" : \"0fr\" }}\n {...toggleProps}\n >\n <div className=\"cpk:overflow-hidden\">{toggleChildren}</div>\n </div>\n );\n };\n}\n\nCopilotChatReasoningMessage.Header.displayName =\n \"CopilotChatReasoningMessage.Header\";\nCopilotChatReasoningMessage.Content.displayName =\n \"CopilotChatReasoningMessage.Content\";\nCopilotChatReasoningMessage.Toggle.displayName =\n \"CopilotChatReasoningMessage.Toggle\";\n\nexport default CopilotChatReasoningMessage;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatReasoningMessage.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"mappings":";;;;;KAOY,gCAAA,GAAmC,SAAA;EAE3C,MAAA,SAAe,2BAAA,CAA4B,MAAA;EAC3C,WAAA,SAAoB,2BAAA,CAA4B,OAAA;EAChD,MAAA,SAAe,2BAAA,CAA4B,MAAA;AAAA;EAG3C,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAeX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAiGlB,2BAAA;EAAA,MACF,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,MAAA;IACA,KAAA;IACA,UAAA;IACA,WAAA;EAAA;EAAA,MA6CS,OAAA,EAAS,KAAA,CAAM,EAAA,CAC1B,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,WAAA;IACA,UAAA;EAAA;EAAA,MA4BS,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,MAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"CopilotChatReasoningMessage.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"mappings":";;;;;KAOY,gCAAA,GAAmC,SAAA;EAE3C,MAAA,SAAe,2BAAA,CAA4B,MAAA;EAC3C,WAAA,SAAoB,2BAAA,CAA4B,OAAA;EAChD,MAAA,SAAe,2BAAA,CAA4B,MAAA;AAAA;EAG3C,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAeX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAiGlB,2BAAA;EAAA,MACF,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,MAAA;IACA,KAAA;IACA,UAAA;IACA,WAAA;EAAA;EAAA,MA6CS,OAAA,EAAS,KAAA,CAAM,EAAA,CAC1B,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,WAAA;IACA,UAAA;EAAA;EAAA,MA+BS,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,MAAA;EAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatReasoningMessage.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"mappings":";;;;;KAOY,gCAAA,GAAmC,SAAA;EAE3C,MAAA,SAAe,2BAAA,CAA4B,MAAA;EAC3C,WAAA,SAAoB,2BAAA,CAA4B,OAAA;EAChD,MAAA,SAAe,2BAAA,CAA4B,MAAA;AAAA;EAG3C,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAeX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAiGlB,2BAAA;EAAA,MACF,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,MAAA;IACA,KAAA;IACA,UAAA;IACA,WAAA;EAAA;EAAA,MA6CS,OAAA,EAAS,KAAA,CAAM,EAAA,CAC1B,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,WAAA;IACA,UAAA;EAAA;EAAA,MA4BS,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,MAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"CopilotChatReasoningMessage.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatReasoningMessage.tsx"],"mappings":";;;;;KAOY,gCAAA,GAAmC,SAAA;EAE3C,MAAA,SAAe,2BAAA,CAA4B,MAAA;EAC3C,WAAA,SAAoB,2BAAA,CAA4B,OAAA;EAChD,MAAA,SAAe,2BAAA,CAA4B,MAAA;AAAA;EAG3C,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAeX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBAiGlB,2BAAA;EAAA,MACF,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,MAAA;IACA,KAAA;IACA,UAAA;IACA,WAAA;EAAA;EAAA,MA6CS,OAAA,EAAS,KAAA,CAAM,EAAA,CAC1B,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,WAAA;IACA,UAAA;EAAA;EAAA,MA+BS,MAAA,EAAQ,KAAA,CAAM,EAAA,CACzB,KAAA,CAAM,cAAA,CAAe,cAAA;IACnB,MAAA;EAAA;AAAA"}
@@ -2,7 +2,7 @@ import { renderSlot } from "../../lib/slots.mjs";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { twMerge } from "tailwind-merge";
4
4
  import { ChevronRight } from "lucide-react";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import { Streamdown } from "streamdown";
7
7
 
8
8
  //#region src/components/chat/CopilotChatReasoningMessage.tsx
@@ -57,16 +57,20 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, header, con
57
57
  isOpen,
58
58
  children: boundContent
59
59
  });
60
- if (children) return /* @__PURE__ */ jsx(Fragment, { children: children({
61
- header: boundHeader,
62
- contentView: boundContent,
63
- toggle: boundToggle,
64
- message,
65
- messages,
66
- isRunning
67
- }) });
60
+ if (children) return /* @__PURE__ */ jsx("div", {
61
+ "data-copilotkit": true,
62
+ style: { display: "contents" },
63
+ children: children({
64
+ header: boundHeader,
65
+ contentView: boundContent,
66
+ toggle: boundToggle,
67
+ message,
68
+ messages,
69
+ isRunning
70
+ })
71
+ });
68
72
  return /* @__PURE__ */ jsxs("div", {
69
- className: twMerge("my-1", className),
73
+ className: twMerge("cpk:my-1", className),
70
74
  "data-message-id": message.id,
71
75
  ...props,
72
76
  children: [boundHeader, boundToggle]
@@ -77,44 +81,44 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, header, con
77
81
  const isExpandable = !!hasContent;
78
82
  return /* @__PURE__ */ jsxs("button", {
79
83
  type: "button",
80
- className: twMerge("inline-flex items-center gap-1 py-1 text-sm text-muted-foreground transition-colors select-none", isExpandable ? "hover:text-foreground cursor-pointer" : "cursor-default", className),
84
+ className: twMerge("cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none", isExpandable ? "cpk:hover:text-foreground cpk:cursor-pointer" : "cpk:cursor-default", className),
81
85
  "aria-expanded": isExpandable ? isOpen : void 0,
82
86
  ...headerProps,
83
87
  children: [
84
88
  /* @__PURE__ */ jsx("span", {
85
- className: "font-medium",
89
+ className: "cpk:font-medium",
86
90
  children: label
87
91
  }),
88
92
  isStreaming && !hasContent && /* @__PURE__ */ jsx("span", {
89
- className: "inline-flex items-center ml-1",
90
- children: /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground animate-pulse" })
93
+ className: "cpk:inline-flex cpk:items-center cpk:ml-1",
94
+ children: /* @__PURE__ */ jsx("span", { className: "cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse" })
91
95
  }),
92
96
  headerChildren,
93
- isExpandable && /* @__PURE__ */ jsx(ChevronRight, { className: twMerge("size-3.5 shrink-0 transition-transform duration-200", isOpen && "rotate-90") })
97
+ isExpandable && /* @__PURE__ */ jsx(ChevronRight, { className: twMerge("cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200", isOpen && "cpk:rotate-90") })
94
98
  ]
95
99
  });
96
100
  };
97
101
  _CopilotChatReasoningMessage.Content = ({ isStreaming, hasContent, className, children: contentChildren, ...contentProps }) => {
98
102
  if (!hasContent && !isStreaming) return null;
99
103
  return /* @__PURE__ */ jsx("div", {
100
- className: twMerge("pb-2 pt-1", className),
104
+ className: twMerge("cpk:pb-2 cpk:pt-1", className),
101
105
  ...contentProps,
102
106
  children: /* @__PURE__ */ jsxs("div", {
103
- className: "text-sm text-muted-foreground",
107
+ className: "cpk:text-sm cpk:text-muted-foreground",
104
108
  children: [/* @__PURE__ */ jsx(Streamdown, { children: typeof contentChildren === "string" ? contentChildren : "" }), isStreaming && hasContent && /* @__PURE__ */ jsx("span", {
105
- className: "inline-flex items-center ml-1 align-middle",
106
- children: /* @__PURE__ */ jsx("span", { className: "w-2 h-2 rounded-full bg-muted-foreground animate-pulse-cursor" })
109
+ className: "cpk:inline-flex cpk:items-center cpk:ml-1 cpk:align-middle",
110
+ children: /* @__PURE__ */ jsx("span", { className: "cpk:w-2 cpk:h-2 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse-cursor" })
107
111
  })]
108
112
  })
109
113
  });
110
114
  };
111
115
  _CopilotChatReasoningMessage.Toggle = ({ isOpen, className, children: toggleChildren, ...toggleProps }) => {
112
116
  return /* @__PURE__ */ jsx("div", {
113
- className: twMerge("grid transition-[grid-template-rows] duration-200 ease-in-out", className),
117
+ className: twMerge("cpk:grid cpk:transition-[grid-template-rows] cpk:duration-200 cpk:ease-in-out", className),
114
118
  style: { gridTemplateRows: isOpen ? "1fr" : "0fr" },
115
119
  ...toggleProps,
116
120
  children: /* @__PURE__ */ jsx("div", {
117
- className: "overflow-hidden",
121
+ className: "cpk:overflow-hidden",
118
122
  children: toggleChildren
119
123
  })
120
124
  });