@copilotkit/react-core
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
1 lines • 921 kB
Source Map (JSON)
{"version":3,"file":"copilotkit-CdpDZi3i.cjs","names":["React","DEFAULT_AGENT_ID","twMerge","React","Slot","TooltipPrimitive","DropdownMenuPrimitive","ChevronRightIcon","Square","Loader2","ArrowUp","Mic","X","Check","Plus","CopilotKitCore","React","ToolCallStatus","DEFAULT_AGENT_ID","React","z","z","React","ToolCallStatus","z","z","DEFAULT_SURFACE_ID","A2UIProvider","A2UIRenderer","z","z","A2UI_SCHEMA_CONTEXT_DESCRIPTION","A2UI_DEFAULT_GENERATION_GUIDELINES","A2UI_DEFAULT_DESIGN_GUIDELINES","COPILOT_CLOUD_CHAT_URL","viewerTheme","z","DEFAULT_AGENT_ID","EMPTY_DEPS","ToolCallStatus","ToolCallStatus","ToolCallStatus","React","DEFAULT_AGENT_ID","CopilotKitCoreRuntimeConnectionStatus","ProxiedCopilotRuntimeAgent","HttpAgent","DEFAULT_AGENT_ID","DEFAULT_AGENT_ID","useThreads","ɵselectThreads","ɵselectThreadsIsLoading","ɵselectThreadsError","ɵselectHasNextPage","ɵselectIsFetchingNextPage","ɵselectIsMutating","CopilotKitCoreRuntimeConnectionStatus","React","Streamdown","Check","Copy","ThumbsUp","ThumbsDown","Volume2","RefreshCw","X","Check","Copy","Edit","ChevronLeft","ChevronRight","ChevronRight","Streamdown","React","Loader2","React","React","React","CopilotChatAssistantMessage","CopilotChatUserMessage","CopilotChatReasoningMessage","DEFAULT_AGENT_ID","Play","React","Upload","CopilotChatInput","StickToBottom","ChevronDown","TranscriptionErrorCode","DEFAULT_AGENT_ID","HttpAgent","TranscriptionErrorCode","MessageCircle","X","React","X","PanelLeftOpen","CopilotChatView","CopilotChatView","CopilotChatView","CopilotPopupView","CopilotChatView","useThreads","React","COPILOTKIT_THREADS_DRAWER_TAG","emptyCopilotContext","React","setsHaveIntersection","React","Severity","ErrorVisibility","CopilotKitApiDiscoveryError","CopilotKitRemoteEndpointDiscoveryError","CopilotKitAgentDiscoveryError","CopilotKitError","CopilotKitErrorCode","Severity","CopilotKitErrorCode","COPILOT_CLOUD_API_URL","COPILOT_CLOUD_PUBLIC_API_KEY_HEADER","ReactMarkdown","React","CopilotKitError","CopilotKitLowLevelError","CopilotKitV2Provider","COPILOT_CLOUD_CHAT_URL","COPILOT_CLOUD_PUBLIC_API_KEY_HEADER","React","ConfigurationError","MissingPublicApiKeyError"],"sources":["../src/v2/lib/slots.tsx","../src/v2/providers/CopilotChatConfigurationProvider.tsx","../src/v2/lib/utils.ts","../src/v2/components/ui/button.tsx","../src/v2/components/ui/tooltip.tsx","../src/v2/components/ui/dropdown-menu.tsx","../src/v2/components/chat/CopilotChatAudioRecorder.tsx","../src/v2/components/chat/CopilotChatInput.tsx","../src/v2/hooks/useKatexStyles.ts","../src/v2/lib/react-core.ts","../src/v2/context.ts","../src/v2/hooks/use-render-tool-call.tsx","../src/v2/components/CopilotKitInspector.tsx","../src/v2/components/license-warning-banner.tsx","../src/v2/components/MCPAppsActivityRenderer.tsx","../src/v2/providers/SandboxFunctionsContext.ts","../src/v2/lib/processPartialHtml.ts","../src/v2/components/OpenGenerativeUIRenderer.tsx","../src/v2/a2ui/A2UIRecoveryStates.tsx","../src/v2/a2ui/A2UIMessageRenderer.tsx","../src/v2/types/defineToolCallRenderer.ts","../src/v2/a2ui/A2UIToolCallRenderer.tsx","../src/v2/a2ui/A2UICatalogContext.tsx","../src/v2/providers/CopilotKitProvider.tsx","../src/v2/hooks/use-render-custom-messages.tsx","../src/v2/hooks/use-render-activity-message.tsx","../src/v2/hooks/use-frontend-tool.tsx","../src/v2/hooks/use-component.tsx","../src/v2/hooks/use-render-tool.tsx","../src/v2/hooks/use-default-render-tool.tsx","../src/v2/hooks/use-human-in-the-loop.tsx","../src/v2/hooks/use-agent.tsx","../src/v2/hooks/use-capabilities.tsx","../src/v2/hooks/use-agent-context.tsx","../src/v2/hooks/use-suggestions.tsx","../src/v2/hooks/use-configure-suggestions.tsx","../src/v2/hooks/use-interrupt.tsx","../src/v2/hooks/use-threads.tsx","../src/v2/lib/record-annotation.ts","../src/v2/hooks/use-learn-from-user-action.tsx","../src/v2/hooks/use-learn-from-user-action-in-current-thread.tsx","../src/v2/hooks/use-attachments.tsx","../src/v2/hooks/use-learning-containers.tsx","../src/v2/hooks/use-learning-containers-in-current-thread.tsx","../src/v2/components/chat/CopilotChatToolCallsView.tsx","../src/v2/components/chat/CopilotChatAssistantMessage.tsx","../src/v2/components/chat/Lightbox.tsx","../src/v2/components/chat/CopilotChatAttachmentRenderer.tsx","../src/v2/components/chat/CopilotChatUserMessage.tsx","../src/v2/components/chat/CopilotChatReasoningMessage.tsx","../src/v2/components/chat/CopilotChatSuggestionPill.tsx","../src/v2/components/chat/CopilotChatSuggestionView.tsx","../src/v2/components/chat/scroll-element-context.ts","../src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx","../src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx","../src/v2/components/chat/CopilotChatMessageView.tsx","../src/v2/components/chat/CopilotChatAttachmentQueue.tsx","../src/v2/hooks/use-keyboard-height.tsx","../src/v2/components/chat/normalize-auto-scroll.ts","../src/v2/components/chat/last-user-message-context.ts","../src/v2/hooks/use-pin-to-send.ts","../src/v2/components/chat/CopilotChatView.tsx","../src/v2/lib/transcription-client.ts","../src/v2/components/chat/CopilotChat.tsx","../src/v2/components/chat/CopilotChatToggleButton.tsx","../src/v2/components/chat/CopilotModalHeader.tsx","../src/v2/components/chat/CopilotSidebarView.tsx","../src/v2/components/chat/CopilotPopupView.tsx","../src/v2/components/chat/CopilotSidebar.tsx","../src/v2/components/chat/CopilotPopup.tsx","../src/v2/components/chat/CopilotThreadsDrawer.tsx","../src/v2/components/WildcardToolCallRender.tsx","../src/context/copilot-context.tsx","../src/hooks/use-tree.ts","../src/hooks/use-flat-category-store.ts","../src/context/copilot-messages-context.tsx","../src/components/toast/toast-provider.tsx","../src/utils/dev-console.ts","../src/components/copilot-provider/copilot-messages.tsx","../src/components/usage-banner.tsx","../src/lib/status-checker.ts","../src/components/toast/exclamation-mark-icon.tsx","../src/components/error-boundary/error-utils.tsx","../src/components/error-boundary/error-boundary.tsx","../src/context/coagent-state-renders-context.tsx","../src/context/threads-context.tsx","../src/hooks/use-coagent-state-render-bridge.helpers.ts","../src/hooks/use-coagent-state-render-registry.ts","../src/hooks/use-coagent-state-render-bridge.tsx","../src/components/CopilotListeners.tsx","../src/components/copilot-provider/copilotkit.tsx"],"sourcesContent":["import React, { useRef } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Existing union (unchanged) */\nexport type SlotValue<C extends React.ComponentType<any>> =\n | C\n | string\n | Partial<React.ComponentProps<C>>;\n\n/**\n * Shallow equality comparison for objects.\n */\nexport function shallowEqual<T extends Record<string, unknown>>(\n obj1: T,\n obj2: T,\n): boolean {\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) return false;\n\n for (const key of keys1) {\n if (obj1[key] !== obj2[key]) return false;\n }\n\n return true;\n}\n\n/**\n * Returns true only for plain JS objects (`{}`), excluding arrays, Dates,\n * class instances, and other exotic objects that happen to have typeof \"object\".\n */\nfunction isPlainObject(obj: unknown): obj is Record<string, unknown> {\n return (\n obj !== null &&\n typeof obj === \"object\" &&\n Object.prototype.toString.call(obj) === \"[object Object]\"\n );\n}\n\n/**\n * Returns the same reference as long as the value is shallowly equal to the\n * previous render's value.\n *\n * - Identical references bail out immediately (O(1)).\n * - Plain objects ({}) are shallow-compared key-by-key.\n * - Arrays, Dates, class instances, functions, and primitives are compared by\n * reference only — shallowEqual is never called on non-plain objects, which\n * avoids incorrect equality for e.g. [1,2] vs [1,2] (different arrays).\n *\n * Typical use: stabilize inline slot props so MemoizedSlotWrapper's shallow\n * equality check isn't defeated by a new object reference on every render.\n */\nexport function useShallowStableRef<T>(value: T): T {\n const ref = useRef(value);\n\n // 1. Identical reference — bail early, no comparison needed.\n if (ref.current === value) return ref.current;\n\n // 2. Both are plain objects — shallow-compare to detect structural equality.\n if (isPlainObject(ref.current) && isPlainObject(value)) {\n if (shallowEqual(ref.current, value)) return ref.current;\n }\n\n // 3. Different values (or non-comparable types) — update the ref.\n ref.current = value;\n return ref.current;\n}\n\n/** Utility: concrete React elements for every slot */\ntype SlotElements<S> = { [K in keyof S]: React.ReactElement };\n\nexport type WithSlots<\n S extends Record<string, React.ComponentType<any>>,\n Rest = {},\n> = {\n /** Per‑slot overrides */\n [K in keyof S]?: SlotValue<S[K]>;\n} & {\n children?: (props: SlotElements<S> & Rest) => React.ReactNode;\n} & Omit<Rest, \"children\">;\n\n/**\n * Check if a value is a React component type (function, class, forwardRef, memo, etc.)\n */\nexport function isReactComponentType(\n value: unknown,\n): value is React.ComponentType<any> {\n if (typeof value === \"function\") {\n return true;\n }\n // forwardRef, memo, lazy have $$typeof but are not valid elements\n if (\n value &&\n typeof value === \"object\" &&\n \"$$typeof\" in value &&\n !React.isValidElement(value)\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Internal function to render a slot value as a React element (non-memoized).\n */\nfunction renderSlotElement(\n slot: SlotValue<React.ComponentType<any>> | undefined,\n DefaultComponent: React.ComponentType<any>,\n props: Record<string, unknown>,\n): React.ReactElement {\n if (typeof slot === \"string\") {\n // When slot is a string, treat it as a className and merge with existing className\n const existingClassName = props.className as string | undefined;\n return React.createElement(DefaultComponent, {\n ...props,\n className: twMerge(existingClassName, slot),\n });\n }\n\n // Check if slot is a React component type (function, forwardRef, memo, etc.)\n if (isReactComponentType(slot)) {\n return React.createElement(slot, props);\n }\n\n // If slot is a plain object (not a React element), treat it as props override\n if (slot && typeof slot === \"object\" && !React.isValidElement(slot)) {\n return React.createElement(DefaultComponent, {\n ...props,\n ...slot,\n });\n }\n\n return React.createElement(DefaultComponent, props);\n}\n\n/**\n * Internal memoized wrapper component for renderSlot.\n * Uses forwardRef to support ref forwarding.\n */\nconst MemoizedSlotWrapper = React.memo(\n React.forwardRef<unknown, any>(function MemoizedSlotWrapper(props, ref) {\n const { $slot, $component, ...rest } = props;\n const propsWithRef: Record<string, unknown> =\n ref !== null ? { ...rest, ref } : rest;\n return renderSlotElement($slot, $component, propsWithRef);\n }),\n (prev: any, next: any) => {\n // Compare slot and component references\n if (prev.$slot !== next.$slot) return false;\n if (prev.$component !== next.$component) return false;\n\n // Shallow compare remaining props (ref is handled separately by React)\n const { $slot: _ps, $component: _pc, ...prevRest } = prev;\n const { $slot: _ns, $component: _nc, ...nextRest } = next;\n return shallowEqual(\n prevRest as Record<string, unknown>,\n nextRest as Record<string, unknown>,\n );\n },\n);\n\n/**\n * Renders a slot value as a memoized React element.\n * Automatically prevents unnecessary re-renders using shallow prop comparison.\n * Supports ref forwarding.\n *\n * @example\n * renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })\n */\nexport function renderSlot<\n C extends React.ComponentType<any>,\n P = React.ComponentProps<C>,\n>(\n slot: SlotValue<C> | undefined,\n DefaultComponent: C,\n props: P,\n): React.ReactElement {\n return React.createElement(MemoizedSlotWrapper, {\n ...props,\n $slot: slot,\n $component: DefaultComponent,\n } as any);\n}\n","import type { ReactNode } from \"react\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { DEFAULT_AGENT_ID, randomUUID } from \"@copilotkit/shared\";\nimport { useShallowStableRef } from \"../lib/slots\";\n\n// Default labels\nexport const CopilotChatDefaultLabels = {\n chatInputPlaceholder: \"Type a message...\",\n chatInputToolbarStartTranscribeButtonLabel: \"Transcribe\",\n chatInputToolbarCancelTranscribeButtonLabel: \"Cancel\",\n chatInputToolbarFinishTranscribeButtonLabel: \"Finish\",\n chatInputToolbarAddButtonLabel: \"Add attachments\",\n chatInputToolbarToolsButtonLabel: \"Tools\",\n assistantMessageToolbarCopyCodeLabel: \"Copy\",\n assistantMessageToolbarCopyCodeCopiedLabel: \"Copied\",\n assistantMessageToolbarCopyMessageLabel: \"Copy\",\n assistantMessageToolbarThumbsUpLabel: \"Good response\",\n assistantMessageToolbarThumbsDownLabel: \"Bad response\",\n assistantMessageToolbarReadAloudLabel: \"Read aloud\",\n assistantMessageToolbarRegenerateLabel: \"Regenerate\",\n userMessageToolbarCopyMessageLabel: \"Copy\",\n userMessageToolbarEditMessageLabel: \"Edit\",\n chatDisclaimerText:\n \"AI can make mistakes. Please verify important information.\",\n chatToggleOpenLabel: \"Open chat\",\n chatToggleCloseLabel: \"Close chat\",\n modalHeaderTitle: \"CopilotKit Chat\",\n welcomeMessageText: \"How can I help you today?\",\n};\n\nexport type CopilotChatLabels = typeof CopilotChatDefaultLabels;\n\n/**\n * Mobile breakpoint below which the chat modal and the thread-list drawer are\n * mutually exclusive. At or above this width both surfaces may coexist. This\n * mirrors the `(max-width: 767px)` / `(min-width: 768px)` split already used by\n * CopilotChatInput and CopilotSidebarView.\n */\nconst MOBILE_MAX_WIDTH_PX = 767;\n\n/**\n * Reports whether the current viewport is in the mobile range (`<768px`), where\n * the chat modal and drawer must not be open simultaneously. SSR-safe and\n * defensive against environments without `matchMedia` (treated as desktop, so\n * no mutual-exclusion constraint is applied).\n *\n * @returns `true` when the viewport is mobile-width, `false` otherwise.\n */\nfunction isMobileViewport(): boolean {\n if (\n typeof window === \"undefined\" ||\n typeof window.matchMedia !== \"function\"\n ) {\n return false;\n }\n return window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH_PX}px)`).matches;\n}\n\n// Define the full configuration interface\nexport interface CopilotChatConfigurationValue {\n labels: CopilotChatLabels;\n agentId: string;\n threadId: string;\n isModalOpen: boolean;\n setModalOpen: (open: boolean) => void;\n /**\n * Whether the thread-list drawer is open. A sibling boolean to `isModalOpen`\n * (deliberately NOT folded into a tri-state enum): on desktop the chat modal\n * and the drawer coexist, so two independent booleans are required.\n */\n drawerOpen: boolean;\n /**\n * Toggles the drawer open state. On mobile viewports (`<768px`) opening the\n * drawer closes the chat modal (mutual exclusion); on desktop there is no\n * constraint.\n */\n setDrawerOpen: (open: boolean) => void;\n /**\n * True once a `<CopilotThreadsDrawer>` wrapper has registered itself with this chat\n * configuration. The header thread-list launcher renders ONLY when this is\n * set, so chats with no drawer stay byte-for-byte unchanged.\n */\n drawerRegistered: boolean;\n /**\n * Called by the drawer wrapper on mount to announce its presence (and flip\n * `drawerRegistered`). Returns a cleanup function that de-registers the\n * drawer on unmount.\n *\n * @returns A cleanup callback that reverses the registration.\n */\n registerDrawer: () => () => void;\n /**\n * Internal: registers the modal-close setter of the provider that actually\n * owns the rendered modal (a descendant that supplied `isModalDefaultOpen`),\n * so the drawer's mobile mutual-exclusion — owned by the top-most provider —\n * closes the modal that is genuinely on screen rather than the top-most\n * provider's own (possibly unrendered) modal state.\n *\n * @param closeModal - A setter the drawer may call to close the rendered modal.\n * @returns A cleanup callback that de-registers the closer.\n */\n ɵregisterModalCloser: (closeModal: (open: boolean) => void) => () => void;\n // True when the current threadId was chosen by the caller rather than\n // silently minted inside the provider chain. Consumers that only make\n // sense against a real backend thread (e.g. /connect, suppressing the\n // welcome screen on switch) gate on this instead of `!!threadId`.\n hasExplicitThreadId: boolean;\n /**\n * Imperatively sets the active thread for this chat configuration.\n *\n * Use this to drive the rendered thread without a host callback — e.g. a\n * `<CopilotThreadsDrawer>` selecting a thread row sets it explicitly so the chat\n * connects to that backend thread.\n *\n * Guarded like the top-level `<CopilotKit>` provider's `setThreadId`: when\n * the consumer controls the threadId via the `threadId` prop on this\n * provider, this is a no-op (a warning is logged) so a prop-controlled\n * threadId is never silently overridden.\n *\n * @param threadId - The thread id to make active.\n * @param options.explicit - Whether the thread is a caller choice. Defaults\n * to `true` (a picked thread). Pass `false` to set a non-explicit thread\n * so the welcome screen shows (see {@link startNewThread}).\n */\n setActiveThreadId: (\n threadId: string,\n options?: { explicit?: boolean },\n ) => void;\n /**\n * Resets the active thread to a fresh, non-explicit client-side thread: a\n * newly minted UUID with `hasExplicitThreadId=false`, so the welcome screen\n * shows. Pairs with the core `startNewThread()` to clear the conversation\n * with no host wiring.\n *\n * Guarded identically to {@link setActiveThreadId}: a no-op when the\n * threadId is prop-controlled.\n */\n startNewThread: () => void;\n}\n\n// Create the configuration context\nconst CopilotChatConfiguration =\n createContext<CopilotChatConfigurationValue | null>(null);\n\n// Provider props interface\nexport interface CopilotChatConfigurationProviderProps {\n children: ReactNode;\n labels?: Partial<CopilotChatLabels>;\n agentId?: string;\n threadId?: string;\n // Lets internal wrappers (e.g. the v1 CopilotKit bridge, which pipes a\n // ThreadsProvider-minted UUID through as `threadId`) declare that the\n // threadId they are supplying is NOT a caller choice. When omitted, the\n // provider infers explicitness from whether the `threadId` prop itself\n // was supplied.\n hasExplicitThreadId?: boolean;\n isModalDefaultOpen?: boolean;\n}\n\n// Provider component\nexport const CopilotChatConfigurationProvider: React.FC<\n CopilotChatConfigurationProviderProps\n> = ({\n children,\n labels,\n agentId,\n threadId,\n hasExplicitThreadId,\n isModalDefaultOpen,\n}) => {\n const parentConfig = useContext(CopilotChatConfiguration);\n\n // Stabilize labels references so that inline objects (new reference on every\n // parent render) don't invalidate mergedLabels and churn the context value.\n // parentConfig?.labels is already stabilized by the parent provider's own\n // useShallowStableRef, so we only need to stabilize the local labels prop.\n const stableLabels = useShallowStableRef(labels);\n const mergedLabels: CopilotChatLabels = useMemo(\n () => ({\n ...CopilotChatDefaultLabels,\n ...parentConfig?.labels,\n ...stableLabels,\n }),\n [stableLabels, parentConfig?.labels],\n );\n\n const resolvedAgentId = agentId ?? parentConfig?.agentId ?? DEFAULT_AGENT_ID;\n\n // A threadId prop is \"authoritative\" (caller-chosen) only when it is present\n // AND not explicitly flagged non-explicit. The v1 `<CopilotKit>` bridge pipes\n // an auto-minted UUID through as `threadId` with `hasExplicitThreadId={false}`\n // to SEED the thread without claiming the caller picked it; that seed must\n // stay overridable so imperative callers (e.g. `<CopilotThreadsDrawer>` selecting a\n // row, or `startNewThread`) can switch threads. A bare `threadId` prop (no\n // `hasExplicitThreadId`) is still treated as a caller choice.\n const threadIdPropIsAuthoritative =\n threadId !== undefined && hasExplicitThreadId !== false;\n\n // Whether this provider's threadId is controlled by the consumer. When\n // controlled, the imperative active-thread setters below must not override\n // the prop-driven value. A non-authoritative seed (v1 bridge auto-mint) is\n // NOT controlled, so imperative selection still works underneath it.\n const isThreadIdControlled = threadIdPropIsAuthoritative;\n\n // Imperative active-thread override owned by the TOP-MOST provider (the one\n // with no parent). A non-null override takes precedence over the auto-minted\n // UUID fallback below. Nested providers do not own this state — they proxy\n // the parent's setter (see resolved*ActiveThread below) and observe the\n // override through the inherited `parentConfig.threadId`.\n const [activeThreadOverride, setActiveThreadOverride] = useState<{\n threadId: string;\n explicit: boolean;\n } | null>(null);\n\n const resolvedThreadId = useMemo(() => {\n // An authoritative (caller-chosen) threadId prop always wins.\n if (threadIdPropIsAuthoritative) {\n return threadId as string;\n }\n // Otherwise an imperative override (a picked row or freshly-started thread)\n // beats both a non-authoritative seed (the v1 bridge's auto-minted UUID) and\n // the thread inherited from a parent provider.\n if (activeThreadOverride) {\n return activeThreadOverride.threadId;\n }\n if (parentConfig?.threadId) {\n return parentConfig.threadId;\n }\n if (threadId) {\n return threadId;\n }\n return randomUUID();\n }, [\n threadIdPropIsAuthoritative,\n threadId,\n parentConfig?.threadId,\n activeThreadOverride,\n ]);\n\n // Explicitness of this provider's own thread, mirroring the resolution order\n // above: an authoritative prop is a caller choice; otherwise an imperative\n // override carries its own explicitness (a picked row is explicit, a fresh\n // `startNewThread` is not); failing both, fall back to the (non-authoritative)\n // prop flag, which is `false` for the v1 bridge seed.\n const ownHasExplicitThreadId = threadIdPropIsAuthoritative\n ? true\n : (activeThreadOverride?.explicit ?? hasExplicitThreadId ?? false);\n const resolvedHasExplicitThreadId =\n ownHasExplicitThreadId || !!parentConfig?.hasExplicitThreadId;\n\n const resolvedDefaultOpen = isModalDefaultOpen ?? true;\n\n const [internalModalOpen, setInternalModalOpen] =\n useState<boolean>(resolvedDefaultOpen);\n\n const hasExplicitDefault = isModalDefaultOpen !== undefined;\n\n // When this provider owns its modal state, wrap the setter so that changes\n // propagate upward to any ancestor provider. This allows an outer\n // CopilotChatConfigurationProvider (e.g. a user's layout-level provider) to\n // observe open/close events that originate deep in the tree — fixing the\n // \"outer hook always returns true\" regression (CPK-7152 Behavior B).\n const setAndSync = useCallback(\n (open: boolean) => {\n setInternalModalOpen(open);\n parentConfig?.setModalOpen(open);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentConfig?.setModalOpen],\n );\n\n // Sync parent → child: when an ancestor's modal state is changed externally\n // (e.g. the user calls setModalOpen from an outer hook), reflect that change\n // in our own state so the sidebar/popup responds accordingly.\n // Skip the initial mount so that our own isModalDefaultOpen is respected and\n // not immediately overwritten by the parent's current value.\n const isMounted = useRef(false);\n useEffect(() => {\n if (!hasExplicitDefault) return;\n if (!isMounted.current) {\n isMounted.current = true;\n return;\n }\n if (parentConfig?.isModalOpen === undefined) return;\n setInternalModalOpen(parentConfig.isModalOpen);\n }, [parentConfig?.isModalOpen, hasExplicitDefault]);\n\n const resolvedIsModalOpen = hasExplicitDefault\n ? internalModalOpen\n : (parentConfig?.isModalOpen ?? internalModalOpen);\n const resolvedSetModalOpen = hasExplicitDefault\n ? setAndSync\n : (parentConfig?.setModalOpen ?? setInternalModalOpen);\n\n // Drawer presence + open state. When a parent provider exists, this provider\n // proxies the parent's drawer state and registration so that the whole chain\n // shares a single drawer (the drawer wrapper registers once, anywhere in the\n // subtree, and the header launcher anywhere can read/toggle it). Only the\n // top-most provider owns the underlying state.\n const [ownDrawerOpen, setOwnDrawerOpen] = useState<boolean>(false);\n const [ownDrawerCount, setOwnDrawerCount] = useState<number>(0);\n\n // The modal-close path used by the drawer's mobile mutual-exclusion. Held in\n // a ref so the drawer setter (owned by the top-most provider) can reach the\n // resolved modal setter without recreating its identity on every render.\n const modalCloseRef = useRef<(open: boolean) => void>(() => {});\n // Default to this provider's own resolved modal setter. When a DESCENDANT\n // provider owns the rendered modal (it supplied `isModalDefaultOpen`), it\n // registers its closer via `ɵregisterModalCloser` below, which overrides this\n // so the drawer closes the modal that is actually on screen.\n modalCloseRef.current = resolvedSetModalOpen;\n\n // Stack of descendant-registered modal closers. The most recently registered\n // closer (the deepest/last-rendered modal owner) is preferred, mirroring how\n // `resolvedThreadId`/modal ownership flows to the nearest explicit owner.\n const registeredModalClosersRef = useRef<Array<(open: boolean) => void>>([]);\n\n const ownRegisterModalCloser = useCallback(\n (closeModal: (open: boolean) => void) => {\n registeredModalClosersRef.current.push(closeModal);\n return () => {\n registeredModalClosersRef.current =\n registeredModalClosersRef.current.filter(\n (entry) => entry !== closeModal,\n );\n };\n },\n [],\n );\n\n const ownSetDrawerOpen = useCallback((open: boolean) => {\n setOwnDrawerOpen(open);\n // Mobile mutual-exclusion: opening the drawer closes the chat modal. Prefer\n // a descendant-registered closer (the actually-rendered modal) over this\n // provider's own resolved modal setter.\n if (open && isMobileViewport()) {\n const registered = registeredModalClosersRef.current;\n const closeModal =\n registered.length > 0\n ? registered[registered.length - 1]\n : modalCloseRef.current;\n closeModal(false);\n }\n }, []);\n\n const ownRegisterDrawer = useCallback(() => {\n setOwnDrawerCount((count) => count + 1);\n return () => {\n setOwnDrawerCount((count) => Math.max(0, count - 1));\n };\n }, []);\n\n const resolvedDrawerOpen = parentConfig\n ? parentConfig.drawerOpen\n : ownDrawerOpen;\n const resolvedSetDrawerOpen = parentConfig\n ? parentConfig.setDrawerOpen\n : ownSetDrawerOpen;\n const resolvedDrawerRegistered = parentConfig\n ? parentConfig.drawerRegistered\n : ownDrawerCount > 0;\n const resolvedRegisterDrawer = parentConfig\n ? parentConfig.registerDrawer\n : ownRegisterDrawer;\n const resolvedRegisterModalCloser = parentConfig\n ? parentConfig.ɵregisterModalCloser\n : ownRegisterModalCloser;\n\n // When THIS provider owns the rendered modal (it supplied\n // `isModalDefaultOpen`), register its closer up the chain so the top-most\n // provider's drawer mobile mutual-exclusion closes the modal that is actually\n // on screen. Re-registers if the resolved setter identity changes.\n useEffect(() => {\n if (!hasExplicitDefault) return;\n return resolvedRegisterModalCloser(resolvedSetModalOpen);\n }, [hasExplicitDefault, resolvedRegisterModalCloser, resolvedSetModalOpen]);\n\n // Active-thread override setters. The TOP-MOST provider owns the override\n // state; nested providers proxy the parent's setter so the whole chain drives\n // a single active thread (the override placed on the owner flows down via the\n // inherited threadId).\n //\n // The controlled-guard is applied at EACH level, not only on the owner: a\n // provider whose own `threadId` prop pins the rendered thread (per the\n // `resolvedThreadId` precedence above) intercepts the set with a no-op +\n // warning BEFORE proxying upward. This is required because in a nested chain\n // the controlled provider is often NOT the override owner — e.g. an\n // uncontrolled top-most provider with a controlled nested provider. Guarding\n // only the owner would let the set silently no-op (the nested `threadId` prop\n // wins at render) while the documented warning never fired.\n const isThreadIdControlledRef = useRef(isThreadIdControlled);\n isThreadIdControlledRef.current = isThreadIdControlled;\n\n const ownSetActiveThreadId = useCallback(\n (id: string, options?: { explicit?: boolean }) => {\n setActiveThreadOverride({\n threadId: id,\n explicit: options?.explicit ?? true,\n });\n },\n [],\n );\n\n const ownStartNewThread = useCallback(() => {\n setActiveThreadOverride({ threadId: randomUUID(), explicit: false });\n }, []);\n\n // Proxy to the parent's setter when nested, else to the owner's. Wrapped with\n // this provider's own controlled-guard so the nearest pinning (controlled)\n // provider — wherever it sits in the chain — is the one that no-ops + warns.\n const parentSetActiveThreadId = parentConfig?.setActiveThreadId;\n const parentStartNewThread = parentConfig?.startNewThread;\n\n const resolvedSetActiveThreadId = useCallback(\n (id: string, options?: { explicit?: boolean }) => {\n if (isThreadIdControlledRef.current) {\n console.warn(\n \"[CopilotKit] Ignoring setActiveThreadId(): threadId is controlled \" +\n \"via the `threadId` prop on CopilotChatConfigurationProvider.\",\n );\n return;\n }\n if (parentSetActiveThreadId) {\n parentSetActiveThreadId(id, options);\n return;\n }\n ownSetActiveThreadId(id, options);\n },\n [parentSetActiveThreadId, ownSetActiveThreadId],\n );\n\n const resolvedStartNewThread = useCallback(() => {\n if (isThreadIdControlledRef.current) {\n console.warn(\n \"[CopilotKit] Ignoring startNewThread(): threadId is controlled via \" +\n \"the `threadId` prop on CopilotChatConfigurationProvider.\",\n );\n return;\n }\n if (parentStartNewThread) {\n parentStartNewThread();\n return;\n }\n ownStartNewThread();\n }, [parentStartNewThread, ownStartNewThread]);\n\n // Mobile mutual-exclusion (other direction): opening the chat modal closes\n // the drawer. Layered over whichever modal setter we resolved above so the\n // existing parent/child modal-sync contract is preserved untouched.\n const setModalOpenWithDrawerExclusion = useCallback(\n (open: boolean) => {\n if (open && isMobileViewport()) {\n resolvedSetDrawerOpen(false);\n }\n resolvedSetModalOpen(open);\n },\n [resolvedSetModalOpen, resolvedSetDrawerOpen],\n );\n\n const configurationValue: CopilotChatConfigurationValue = useMemo(\n () => ({\n labels: mergedLabels,\n agentId: resolvedAgentId,\n threadId: resolvedThreadId,\n hasExplicitThreadId: resolvedHasExplicitThreadId,\n isModalOpen: resolvedIsModalOpen,\n setModalOpen: setModalOpenWithDrawerExclusion,\n drawerOpen: resolvedDrawerOpen,\n setDrawerOpen: resolvedSetDrawerOpen,\n drawerRegistered: resolvedDrawerRegistered,\n registerDrawer: resolvedRegisterDrawer,\n ɵregisterModalCloser: resolvedRegisterModalCloser,\n setActiveThreadId: resolvedSetActiveThreadId,\n startNewThread: resolvedStartNewThread,\n }),\n [\n mergedLabels,\n resolvedAgentId,\n resolvedThreadId,\n resolvedHasExplicitThreadId,\n resolvedIsModalOpen,\n setModalOpenWithDrawerExclusion,\n resolvedDrawerOpen,\n resolvedSetDrawerOpen,\n resolvedDrawerRegistered,\n resolvedRegisterDrawer,\n resolvedRegisterModalCloser,\n resolvedSetActiveThreadId,\n resolvedStartNewThread,\n ],\n );\n\n return (\n <CopilotChatConfiguration.Provider value={configurationValue}>\n {children}\n </CopilotChatConfiguration.Provider>\n );\n};\n\n// Hook to use the full configuration\nexport const useCopilotChatConfiguration =\n (): CopilotChatConfigurationValue | null => {\n const configuration = useContext(CopilotChatConfiguration);\n return configuration;\n };\n","import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({ prefix: \"cpk\" });\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst buttonVariants = cva(\n \"cpk:inline-flex cpk:items-center cpk:justify-center cpk:gap-2 cpk:whitespace-nowrap cpk:rounded-md cpk:text-sm cpk:font-medium cpk:transition-all cpk:disabled:pointer-events-none cpk:disabled:opacity-50 cpk:[&_svg]:pointer-events-none cpk:[&_svg:not([class*='size-'])]:size-4 cpk:shrink-0 cpk:[&_svg]:shrink-0 cpk:outline-none cpk:focus-visible:border-ring cpk:focus-visible:ring-ring/50 cpk:focus-visible:ring-[3px] cpk:aria-invalid:ring-destructive/20 cpk:dark:aria-invalid:ring-destructive/40 cpk:aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"cpk:bg-primary cpk:text-primary-foreground cpk:shadow-xs cpk:hover:bg-primary/90\",\n destructive:\n \"cpk:bg-destructive cpk:text-white cpk:shadow-xs cpk:hover:bg-destructive/90 cpk:focus-visible:ring-destructive/20 cpk:dark:focus-visible:ring-destructive/40 cpk:dark:bg-destructive/60\",\n outline:\n \"cpk:border cpk:bg-background cpk:shadow-xs cpk:hover:bg-accent cpk:hover:text-accent-foreground cpk:dark:bg-input/30 cpk:dark:border-input cpk:dark:hover:bg-input/50\",\n secondary:\n \"cpk:bg-secondary cpk:text-secondary-foreground cpk:shadow-xs cpk:hover:bg-secondary/80\",\n ghost:\n \"cpk:hover:bg-accent cpk:hover:text-accent-foreground cpk:dark:hover:bg-accent/50 cpk:cursor-pointer\",\n link: \"cpk:text-primary cpk:underline-offset-4 cpk:hover:underline\",\n assistantMessageToolbarButton: [\n \"cpk:cursor-pointer\",\n // Background and text\n \"cpk:p-0 cpk:text-[rgb(93,93,93)] cpk:hover:bg-[#E8E8E8]\",\n // Dark mode - lighter gray for better contrast\n \"cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]\",\n // Shape and sizing\n \"cpk:h-8 cpk:w-8\",\n // Interactions\n \"cpk:transition-colors\",\n // Hover states\n \"cpk:hover:text-[rgb(93,93,93)]\",\n \"cpk:dark:hover:text-[rgb(243,243,243)]\",\n ],\n chatInputToolbarPrimary: [\n \"cpk:cursor-pointer\",\n // Background and text\n \"cpk:bg-black cpk:text-white\",\n // Dark mode\n \"cpk:dark:bg-white cpk:dark:text-black cpk:dark:focus-visible:outline-white\",\n // Shape and sizing\n \"cpk:rounded-full\",\n // Interactions\n \"cpk:transition-colors\",\n // Focus states\n \"cpk:focus:outline-none\",\n // Hover states\n \"cpk:hover:opacity-70 cpk:disabled:hover:opacity-100\",\n // Disabled states\n \"cpk:disabled:cursor-not-allowed cpk:disabled:bg-[#00000014] cpk:disabled:text-[rgb(13,13,13)]\",\n \"cpk:dark:disabled:bg-[#454545] cpk:dark:disabled:text-white \",\n ],\n chatInputToolbarSecondary: [\n \"cpk:cursor-pointer\",\n // Background and text\n \"cpk:bg-transparent cpk:text-[#444444]\",\n // Dark mode\n \"cpk:dark:text-white cpk:dark:border-[#404040]\",\n // Shape and sizing\n \"cpk:rounded-full\",\n // Interactions\n \"cpk:transition-colors\",\n // Focus states\n \"cpk:focus:outline-none\",\n // Hover states\n \"cpk:hover:bg-[#f8f8f8] cpk:hover:text-[#333333]\",\n \"cpk:dark:hover:bg-[#404040] cpk:dark:hover:text-[#FFFFFF]\",\n // Disabled states\n \"cpk:disabled:cursor-not-allowed cpk:disabled:opacity-50\",\n \"cpk:disabled:hover:bg-transparent cpk:disabled:hover:text-[#444444]\",\n \"cpk:dark:disabled:hover:bg-transparent cpk:dark:disabled:hover:text-[#CCCCCC]\",\n ],\n },\n size: {\n default: \"cpk:h-9 cpk:px-4 cpk:py-2 cpk:has-[>svg]:px-3\",\n sm: \"cpk:h-8 cpk:rounded-md cpk:gap-1.5 cpk:px-3 cpk:has-[>svg]:px-2.5\",\n lg: \"cpk:h-10 cpk:rounded-md cpk:px-6 cpk:has-[>svg]:px-4\",\n icon: \"cpk:size-9\",\n chatInputToolbarIcon: [\n // Shape and sizing\n \"cpk:h-9 cpk:w-9 cpk:rounded-full\",\n ],\n chatInputToolbarIconLabel: [\n // Shape and sizing\n \"cpk:h-9 cpk:px-3 cpk:rounded-full\",\n // Layout\n \"cpk:gap-2\",\n // Typography\n \"cpk:font-normal\",\n ],\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }\n>(function Button(\n { className, variant, size, asChild = false, ...props },\n ref,\n) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n ref={ref}\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n});\n\nexport { Button, buttonVariants };\n","import * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction TooltipProvider({\n delayDuration = 0,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n );\n}\n\nfunction Tooltip({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n );\n}\n\nfunction TooltipTrigger({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 0,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-copilotkit\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n \"cpk:bg-primary cpk:text-primary-foreground cpk:animate-in cpk:fade-in-0 cpk:zoom-in-95 cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:w-fit cpk:origin-(--radix-tooltip-content-transform-origin) cpk:rounded-md cpk:px-3 cpk:py-1.5 cpk:text-xs cpk:text-balance\",\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"cpk:bg-primary cpk:fill-primary cpk:z-50 cpk:size-2.5 cpk:translate-y-[calc(-50%_-_2px)] cpk:rotate-45 cpk:rounded-[2px]\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction DropdownMenu({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuPortal({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n return (\n <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n );\n}\n\nfunction DropdownMenuTrigger({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-copilotkit\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"cpk:bg-popover cpk:text-popover-foreground cpk:data-[state=open]:animate-in cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=open]:fade-in-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[state=open]:zoom-in-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:max-h-(--radix-dropdown-menu-content-available-height) cpk:min-w-[8rem] cpk:origin-(--radix-dropdown-menu-content-transform-origin) cpk:overflow-x-hidden cpk:overflow-y-auto cpk:rounded-md cpk:border cpk:p-1 cpk:shadow-md\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return (\n <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: \"default\" | \"destructive\";\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:data-[variant=destructive]:text-destructive cpk:data-[variant=destructive]:focus:bg-destructive/10 cpk:dark:data-[variant=destructive]:focus:bg-destructive/20 cpk:data-[variant=destructive]:focus:text-destructive cpk:data-[variant=destructive]:*:[svg]:!text-destructive cpk:[&_svg:not([class*='text-'])]:text-muted-foreground cpk:relative cpk:flex cpk:cursor-default cpk:items-center cpk:gap-2 cpk:rounded-sm cpk:px-2 cpk:py-1.5 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[disabled]:pointer-events-none cpk:data-[disabled]:opacity-50 cpk:data-[inset]:pl-8 cpk:[&_svg]:pointer-events-none cpk:[&_svg]:shrink-0 cpk:[&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:relative cpk:flex cpk:cursor-default cpk:items-center cpk:gap-2 cpk:rounded-sm cpk:py-1.5 cpk:pr-2 cpk:pl-8 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[disabled]:pointer-events-none cpk:data-[disabled]:opacity-50 cpk:[&_svg]:pointer-events-none cpk:[&_svg]:shrink-0 cpk:[&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"cpk:pointer-events-none cpk:absolute cpk:left-2 cpk:flex cpk:size-3.5 cpk:items-center cpk:justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"cpk:size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n return (\n <DropdownMenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:relative cpk:flex cpk:cursor-default cpk:items-center cpk:gap-2 cpk:rounded-sm cpk:py-1.5 cpk:pr-2 cpk:pl-8 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[disabled]:pointer-events-none cpk:data-[disabled]:opacity-50 cpk:[&_svg]:pointer-events-none cpk:[&_svg]:shrink-0 cpk:[&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <span className=\"cpk:pointer-events-none cpk:absolute cpk:left-2 cpk:flex cpk:size-3.5 cpk:items-center cpk:justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"cpk:size-2 cpk:fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"cpk:px-2 cpk:py-1.5 cpk:text-sm cpk:font-medium cpk:data-[inset]:pl-8\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"cpk:bg-border cpk:-mx-1 cpk:my-1 cpk:h-px\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"cpk:text-muted-foreground cpk:ml-auto cpk:text-xs cpk:tracking-widest\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:data-[state=open]:bg-accent cpk:data-[state=open]:text-accent-foreground cpk:flex cpk:cursor-default cpk:items-center cpk:rounded-sm cpk:px-2 cpk:py-1.5 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[inset]:pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"cpk:ml-auto cpk:size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"cpk:bg-popover cpk:text-popover-foreground cpk:data-[state=open]:animate-in cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=open]:fade-in-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[state=open]:zoom-in-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:min-w-[8rem] cpk:origin-(--radix-dropdown-menu-content-transform-origin) cpk:overflow-hidden cpk:rounded-md cpk:border cpk:p-1 cpk:shadow-lg\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n D