@copilotkitnext/react 1.52.0-next.6 → 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 (41) hide show
  1. package/dist/components/chat/CopilotChatMessageView.cjs +18 -5
  2. package/dist/components/chat/CopilotChatMessageView.cjs.map +1 -1
  3. package/dist/components/chat/CopilotChatMessageView.d.cts +1 -0
  4. package/dist/components/chat/CopilotChatMessageView.d.cts.map +1 -1
  5. package/dist/components/chat/CopilotChatMessageView.d.mts +1 -0
  6. package/dist/components/chat/CopilotChatMessageView.d.mts.map +1 -1
  7. package/dist/components/chat/CopilotChatMessageView.mjs +19 -6
  8. package/dist/components/chat/CopilotChatMessageView.mjs.map +1 -1
  9. package/dist/hooks/index.cjs +1 -0
  10. package/dist/hooks/index.d.cts +2 -1
  11. package/dist/hooks/index.d.mts +2 -1
  12. package/dist/hooks/index.mjs +1 -0
  13. package/dist/hooks/use-interrupt.cjs +171 -0
  14. package/dist/hooks/use-interrupt.cjs.map +1 -0
  15. package/dist/hooks/use-interrupt.d.cts +102 -0
  16. package/dist/hooks/use-interrupt.d.cts.map +1 -0
  17. package/dist/hooks/use-interrupt.d.mts +102 -0
  18. package/dist/hooks/use-interrupt.d.mts.map +1 -0
  19. package/dist/hooks/use-interrupt.mjs +170 -0
  20. package/dist/hooks/use-interrupt.mjs.map +1 -0
  21. package/dist/index.cjs +2 -0
  22. package/dist/index.d.cts +3 -1
  23. package/dist/index.d.mts +3 -1
  24. package/dist/index.mjs +2 -1
  25. package/dist/index.umd.js +198 -5
  26. package/dist/index.umd.js.map +1 -1
  27. package/dist/lib/react-core.cjs +13 -0
  28. package/dist/lib/react-core.cjs.map +1 -1
  29. package/dist/lib/react-core.d.cts +8 -0
  30. package/dist/lib/react-core.d.cts.map +1 -1
  31. package/dist/lib/react-core.d.mts +8 -0
  32. package/dist/lib/react-core.d.mts.map +1 -1
  33. package/dist/lib/react-core.mjs +13 -0
  34. package/dist/lib/react-core.mjs.map +1 -1
  35. package/dist/types/index.d.cts +2 -1
  36. package/dist/types/index.d.mts +2 -1
  37. package/dist/types/interrupt.d.cts +17 -0
  38. package/dist/types/interrupt.d.cts.map +1 -0
  39. package/dist/types/interrupt.d.mts +17 -0
  40. package/dist/types/interrupt.d.mts.map +1 -0
  41. package/package.json +6 -6
@@ -129,6 +129,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
129
129
  copilotkit,
130
130
  forceUpdate
131
131
  ]);
132
+ const [interruptElement, setInterruptElement] = (0, react.useState)(null);
133
+ (0, react.useEffect)(() => {
134
+ setInterruptElement(copilotkit.interruptElement);
135
+ const subscription = copilotkit.subscribe({ onInterruptElementChanged: ({ interruptElement }) => {
136
+ setInterruptElement(interruptElement);
137
+ } });
138
+ return () => subscription.unsubscribe();
139
+ }, [copilotkit]);
132
140
  const getStateSnapshotForMessage = (messageId) => {
133
141
  if (!config) return void 0;
134
142
  const resolvedRunId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId) ?? copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
@@ -202,7 +210,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
202
210
  children: children({
203
211
  messageElements,
204
212
  messages,
205
- isRunning
213
+ isRunning,
214
+ interruptElement
206
215
  })
207
216
  });
208
217
  const lastMessage = messages[messages.length - 1];
@@ -211,10 +220,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
211
220
  "data-copilotkit": true,
212
221
  className: (0, tailwind_merge.twMerge)("cpk:flex cpk:flex-col", className),
213
222
  ...props,
214
- children: [messageElements, showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
215
- className: "cpk:mt-2",
216
- children: require_slots.renderSlot(cursor, CopilotChatMessageView.Cursor, {})
217
- })]
223
+ children: [
224
+ messageElements,
225
+ interruptElement,
226
+ showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
227
+ className: "cpk:mt-2",
228
+ children: require_slots.renderSlot(cursor, CopilotChatMessageView.Cursor, {})
229
+ })
230
+ ]
218
231
  });
219
232
  }
220
233
  CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
@@ -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 (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({ messageElements, messages, isRunning })}\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 {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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"}
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;;;KAwNb,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;;;KAwNb,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];
@@ -200,7 +208,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
200
208
  children: children({
201
209
  messageElements,
202
210
  messages,
203
- isRunning
211
+ isRunning,
212
+ interruptElement
204
213
  })
205
214
  });
206
215
  const lastMessage = messages[messages.length - 1];
@@ -209,10 +218,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
209
218
  "data-copilotkit": true,
210
219
  className: twMerge("cpk:flex cpk:flex-col", className),
211
220
  ...props,
212
- children: [messageElements, showCursor && /* @__PURE__ */ jsx("div", {
213
- className: "cpk:mt-2",
214
- children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
215
- })]
221
+ children: [
222
+ messageElements,
223
+ interruptElement,
224
+ showCursor && /* @__PURE__ */ jsx("div", {
225
+ className: "cpk:mt-2",
226
+ children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
227
+ })
228
+ ]
216
229
  });
217
230
  }
218
231
  CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
@@ -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 (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({ messageElements, messages, isRunning })}\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 {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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"}
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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"}
@@ -10,3 +10,4 @@ const require_use_agent = require('./use-agent.cjs');
10
10
  const require_use_agent_context = require('./use-agent-context.cjs');
11
11
  const require_use_suggestions = require('./use-suggestions.cjs');
12
12
  const require_use_configure_suggestions = require('./use-configure-suggestions.cjs');
13
+ const require_use_interrupt = require('./use-interrupt.cjs');
@@ -9,4 +9,5 @@ import { useHumanInTheLoop } from "./use-human-in-the-loop.cjs";
9
9
  import { UseAgentUpdate, useAgent } from "./use-agent.cjs";
10
10
  import { AgentContextInput, JsonSerializable, useAgentContext } from "./use-agent-context.cjs";
11
11
  import { useSuggestions } from "./use-suggestions.cjs";
12
- import { useConfigureSuggestions } from "./use-configure-suggestions.cjs";
12
+ import { useConfigureSuggestions } from "./use-configure-suggestions.cjs";
13
+ import { UseInterruptConfig, useInterrupt } from "./use-interrupt.cjs";
@@ -9,4 +9,5 @@ import { useHumanInTheLoop } from "./use-human-in-the-loop.mjs";
9
9
  import { UseAgentUpdate, useAgent } from "./use-agent.mjs";
10
10
  import { AgentContextInput, JsonSerializable, useAgentContext } from "./use-agent-context.mjs";
11
11
  import { useSuggestions } from "./use-suggestions.mjs";
12
- import { useConfigureSuggestions } from "./use-configure-suggestions.mjs";
12
+ import { useConfigureSuggestions } from "./use-configure-suggestions.mjs";
13
+ import { UseInterruptConfig, useInterrupt } from "./use-interrupt.mjs";
@@ -10,5 +10,6 @@ import { UseAgentUpdate, useAgent } from "./use-agent.mjs";
10
10
  import { useAgentContext } from "./use-agent-context.mjs";
11
11
  import { useSuggestions } from "./use-suggestions.mjs";
12
12
  import { useConfigureSuggestions } from "./use-configure-suggestions.mjs";
13
+ import { useInterrupt } from "./use-interrupt.mjs";
13
14
 
14
15
  export { };
@@ -0,0 +1,171 @@
1
+ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
2
+ const require_CopilotKitProvider = require('../providers/CopilotKitProvider.cjs');
3
+ const require_use_agent = require('./use-agent.cjs');
4
+ let react = require("react");
5
+
6
+ //#region src/hooks/use-interrupt.tsx
7
+ const INTERRUPT_EVENT_NAME = "on_interrupt";
8
+ function isPromiseLike(value) {
9
+ return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
10
+ }
11
+ /**
12
+ * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
13
+ *
14
+ * The hook listens to custom events on the active agent, stores interrupt payloads per run,
15
+ * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
16
+ * execution with user-provided data.
17
+ *
18
+ * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
19
+ * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
20
+ *
21
+ * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
22
+ * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
23
+ *
24
+ * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
25
+ * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
26
+ * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
27
+ * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
28
+ * either the handler's resolved return value or `null` (including when no handler is provided,
29
+ * when filtering skips the interrupt, or when handler execution fails).
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * import { useInterrupt } from "@copilotkitnext/react";
34
+ *
35
+ * function InterruptUI() {
36
+ * useInterrupt({
37
+ * render: ({ event, resolve }) => (
38
+ * <div>
39
+ * <p>{event.value.question}</p>
40
+ * <button onClick={() => resolve({ approved: true })}>Approve</button>
41
+ * <button onClick={() => resolve({ approved: false })}>Reject</button>
42
+ * </div>
43
+ * ),
44
+ * });
45
+ *
46
+ * return null;
47
+ * }
48
+ * ```
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * import { useInterrupt } from "@copilotkitnext/react";
53
+ *
54
+ * function CustomPanel() {
55
+ * const interruptElement = useInterrupt({
56
+ * renderInChat: false,
57
+ * enabled: (event) => event.value.startsWith("approval:"),
58
+ * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
59
+ * render: ({ event, result, resolve }) => (
60
+ * <aside>
61
+ * <strong>{result?.label ?? ""}</strong>
62
+ * <button onClick={() => resolve({ value: event.value })}>Continue</button>
63
+ * </aside>
64
+ * ),
65
+ * });
66
+ *
67
+ * return <>{interruptElement}</>;
68
+ * }
69
+ * ```
70
+ */
71
+ function useInterrupt(config) {
72
+ const { copilotkit } = require_CopilotKitProvider.useCopilotKit();
73
+ const { agent } = require_use_agent.useAgent({ agentId: config.agentId });
74
+ const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
75
+ const [handlerResult, setHandlerResult] = (0, react.useState)(null);
76
+ (0, react.useEffect)(() => {
77
+ let localInterrupt = null;
78
+ const subscription = agent.subscribe({
79
+ onCustomEvent: ({ event }) => {
80
+ if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
81
+ name: event.name,
82
+ value: event.value
83
+ };
84
+ },
85
+ onRunStartedEvent: () => {
86
+ localInterrupt = null;
87
+ setPendingEvent(null);
88
+ },
89
+ onRunFinalized: () => {
90
+ if (localInterrupt) {
91
+ setPendingEvent(localInterrupt);
92
+ localInterrupt = null;
93
+ }
94
+ },
95
+ onRunFailed: () => {
96
+ localInterrupt = null;
97
+ }
98
+ });
99
+ return () => subscription.unsubscribe();
100
+ }, [agent]);
101
+ const resolve = (0, react.useCallback)((response) => {
102
+ setPendingEvent(null);
103
+ copilotkit.runAgent({
104
+ agent,
105
+ forwardedProps: { command: { resume: response } }
106
+ });
107
+ }, [agent, copilotkit]);
108
+ (0, react.useEffect)(() => {
109
+ if (!pendingEvent) {
110
+ setHandlerResult(null);
111
+ return;
112
+ }
113
+ if (config.enabled && !config.enabled(pendingEvent)) {
114
+ setHandlerResult(null);
115
+ return;
116
+ }
117
+ const handler = config.handler;
118
+ if (!handler) {
119
+ setHandlerResult(null);
120
+ return;
121
+ }
122
+ let cancelled = false;
123
+ const maybePromise = handler({
124
+ event: pendingEvent,
125
+ resolve
126
+ });
127
+ if (isPromiseLike(maybePromise)) Promise.resolve(maybePromise).then((resolved) => {
128
+ if (!cancelled) setHandlerResult(resolved);
129
+ }).catch(() => {
130
+ if (!cancelled) setHandlerResult(null);
131
+ });
132
+ else setHandlerResult(maybePromise);
133
+ return () => {
134
+ cancelled = true;
135
+ };
136
+ }, [
137
+ pendingEvent,
138
+ config.enabled,
139
+ config.handler,
140
+ resolve
141
+ ]);
142
+ const element = (0, react.useMemo)(() => {
143
+ if (!pendingEvent) return null;
144
+ if (config.enabled && !config.enabled(pendingEvent)) return null;
145
+ return config.render({
146
+ event: pendingEvent,
147
+ result: handlerResult,
148
+ resolve
149
+ });
150
+ }, [
151
+ pendingEvent,
152
+ handlerResult,
153
+ config.enabled,
154
+ config.render,
155
+ resolve
156
+ ]);
157
+ (0, react.useEffect)(() => {
158
+ if (config.renderInChat === false) return;
159
+ copilotkit.setInterruptElement(element);
160
+ return () => copilotkit.setInterruptElement(null);
161
+ }, [
162
+ element,
163
+ config.renderInChat,
164
+ copilotkit
165
+ ]);
166
+ if (config.renderInChat === false) return element;
167
+ }
168
+
169
+ //#endregion
170
+ exports.useInterrupt = useInterrupt;
171
+ //# sourceMappingURL=use-interrupt.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-interrupt.cjs","names":["useCopilotKit","useAgent"],"sources":["../../src/hooks/use-interrupt.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useMemo } from \"react\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n} from \"../types/interrupt\";\n\nexport type { InterruptEvent, InterruptRenderProps, InterruptHandlerProps };\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\ntype InterruptHandlerFn<TValue, TResult> = (\n props: InterruptHandlerProps<TValue>,\n) => TResult | PromiseLike<TResult>;\n\ntype InterruptResultFromHandler<THandler> = THandler extends (\n ...args: never[]\n) => infer TResult\n ? TResult extends PromiseLike<infer TResolved>\n ? TResolved | null\n : TResult | null\n : null;\n\ntype InterruptResult<TValue, TResult> = InterruptResultFromHandler<\n InterruptHandlerFn<TValue, TResult>\n>;\n\ntype InterruptRenderInChat = boolean | undefined;\n\ntype UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> =\n TRenderInChat extends false\n ? React.ReactElement | null\n : TRenderInChat extends true | undefined\n ? void\n : React.ReactElement | null | void;\n\nexport function isPromiseLike<TValue>(\n value: TValue | PromiseLike<TValue>,\n): value is PromiseLike<TValue> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"then\") === \"function\"\n );\n}\n\n/**\n * Configuration options for `useInterrupt`.\n */\ninterface UseInterruptConfigBase<TValue = unknown, TResult = never> {\n /**\n * Render function for the interrupt UI.\n *\n * This is called once an interrupt is finalized and accepted by `enabled` (if provided).\n * Use `resolve` from render props to resume the agent run with user input.\n */\n render: (\n props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>,\n ) => React.ReactElement;\n /**\n * Optional pre-render handler invoked when an interrupt is received.\n *\n * Return either a sync value or an async value to pass into `render` as `result`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts should be handled by this hook.\n * Return `false` to ignore an interrupt.\n */\n enabled?: (event: InterruptEvent<TValue>) => boolean;\n /** Optional agent id. Defaults to the current configured chat agent. */\n agentId?: string;\n}\n\nexport interface UseInterruptInChatConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat: false;\n}\n\nexport interface UseInterruptDynamicConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** Dynamic boolean mode. When non-literal, return type is a union. */\n renderInChat: boolean;\n}\n\nexport type UseInterruptConfig<\n TValue = unknown,\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n> = UseInterruptConfigBase<TValue, TResult> & {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.\n *\n * The hook listens to custom events on the active agent, stores interrupt payloads per run,\n * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume\n * execution with user-provided data.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.\n *\n * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.\n * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.\n *\n * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.\n * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).\n * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).\n * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always\n * either the handler's resolved return value or `null` (including when no handler is provided,\n * when filtering skips the interrupt, or when handler execution fails).\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function InterruptUI() {\n * useInterrupt({\n * render: ({ event, resolve }) => (\n * <div>\n * <p>{event.value.question}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => resolve({ approved: false })}>Reject</button>\n * </div>\n * ),\n * });\n *\n * return null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function CustomPanel() {\n * const interruptElement = useInterrupt({\n * renderInChat: false,\n * enabled: (event) => event.value.startsWith(\"approval:\"),\n * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),\n * render: ({ event, result, resolve }) => (\n * <aside>\n * <strong>{result?.label ?? \"\"}</strong>\n * <button onClick={() => resolve({ value: event.value })}>Continue</button>\n * </aside>\n * ),\n * });\n *\n * return <>{interruptElement}</>;\n * }\n * ```\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function useInterrupt<\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n>(\n config: UseInterruptConfig<any, TResult, TRenderInChat>,\n): UseInterruptReturn<TRenderInChat> {\n /* eslint-enable @typescript-eslint/no-explicit-any */\n const { copilotkit } = useCopilotKit();\n const { agent } = useAgent({ agentId: config.agentId });\n const [pendingEvent, setPendingEvent] = useState<InterruptEvent | null>(null);\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n useEffect(() => {\n let localInterrupt: InterruptEvent | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localInterrupt = { name: event.name, value: event.value };\n }\n },\n onRunStartedEvent: () => {\n localInterrupt = null;\n setPendingEvent(null);\n },\n onRunFinalized: () => {\n if (localInterrupt) {\n setPendingEvent(localInterrupt);\n localInterrupt = null;\n }\n },\n onRunFailed: () => {\n localInterrupt = null;\n },\n });\n\n return () => subscription.unsubscribe();\n }, [agent]);\n\n const resolve = useCallback(\n (response: unknown) => {\n setPendingEvent(null);\n copilotkit.runAgent({\n agent,\n forwardedProps: { command: { resume: response } },\n });\n },\n [agent, copilotkit],\n );\n\n useEffect(() => {\n // No interrupt to process — reset any stale handler result from a previous interrupt\n if (!pendingEvent) {\n setHandlerResult(null);\n return;\n }\n // Interrupt exists but the consumer's filter rejects it — treat as no-op\n if (config.enabled && !config.enabled(pendingEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = config.handler;\n // No handler provided — skip straight to rendering with a null result\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n const maybePromise = handler({\n event: pendingEvent,\n resolve,\n });\n\n // If the handler returns a promise/thenable, wait for resolution before setting result.\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch(() => {\n if (!cancelled) setHandlerResult(null);\n });\n } else {\n setHandlerResult(maybePromise);\n }\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, config.enabled, config.handler, resolve]);\n\n const element = useMemo(() => {\n if (!pendingEvent) return null;\n if (config.enabled && !config.enabled(pendingEvent)) return null;\n\n return config.render({\n event: pendingEvent,\n result: handlerResult,\n resolve,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, handlerResult, config.enabled, config.render, resolve]);\n\n // Publish to core for in-chat rendering\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n return () => copilotkit.setInterruptElement(null);\n }, [element, config.renderInChat, copilotkit]);\n\n // Only return element when rendering outside chat\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n"],"mappings":";;;;;;AAWA,MAAM,uBAAuB;AA2B7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+H1C,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,EAAE,UAAUC,2BAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,cAAc,uCAAmD,KAAK;CAC7E,MAAM,CAAC,eAAe,wCAEoB,KAAK;AAE/C,4BAAgB;EACd,IAAI,iBAAwC;EAE5C,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,kBAAiB;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG7D,yBAAyB;AACvB,qBAAiB;AACjB,oBAAgB,KAAK;;GAEvB,sBAAsB;AACpB,QAAI,gBAAgB;AAClB,qBAAgB,eAAe;AAC/B,sBAAiB;;;GAGrB,mBAAmB;AACjB,qBAAiB;;GAEpB,CAAC;AAEF,eAAa,aAAa,aAAa;IACtC,CAAC,MAAM,CAAC;CAEX,MAAM,kCACH,aAAsB;AACrB,kBAAgB,KAAK;AACrB,aAAW,SAAS;GAClB;GACA,gBAAgB,EAAE,SAAS,EAAE,QAAQ,UAAU,EAAE;GAClD,CAAC;IAEJ,CAAC,OAAO,WAAW,CACpB;AAED,4BAAgB;AAEd,MAAI,CAAC,cAAc;AACjB,oBAAiB,KAAK;AACtB;;AAGF,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,EAAE;AACnD,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,MAAM,eAAe,QAAQ;GAC3B,OAAO;GACP;GACD,CAAC;AAGF,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,YAAY;AACX,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb;EAAC;EAAc,OAAO;EAAS,OAAO;EAAS;EAAQ,CAAC;CAE3D,MAAM,mCAAwB;AAC5B,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,CAAE,QAAO;AAE5D,SAAO,OAAO,OAAO;GACnB,OAAO;GACP,QAAQ;GACR;GACD,CAAC;IAED;EAAC;EAAc;EAAe,OAAO;EAAS,OAAO;EAAQ;EAAQ,CAAC;AAGzE,4BAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;AACvC,eAAa,WAAW,oBAAoB,KAAK;IAChD;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,KAAI,OAAO,iBAAiB,MAC1B,QAAO"}