@copilotkit/react-core 1.66.2 → 1.66.4
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.
- package/dist/copilotkit-CBCT7BlL.d.cts.map +1 -1
- package/dist/copilotkit-D0aAnD3i.d.mts.map +1 -1
- package/dist/{copilotkit-DnlgZWST.mjs → copilotkit-nRjRp2_5.mjs} +73 -19
- package/dist/copilotkit-nRjRp2_5.mjs.map +1 -0
- package/dist/{copilotkit-2v7ami2b.cjs → copilotkit-sitn7Oe8.cjs} +73 -19
- package/dist/copilotkit-sitn7Oe8.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +35 -16
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/headless.cjs +35 -16
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.mjs +35 -16
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/index.umd.js +72 -18
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +7 -7
- package/dist/copilotkit-2v7ami2b.cjs.map +0 -1
- package/dist/copilotkit-DnlgZWST.mjs.map +0 -1
package/dist/v2/headless.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.mjs","names":["useCopilotKit","EMPTY_DEPS","useCopilotKit","useCopilotKit","useCopilotKit","randomUUID","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit"],"sources":["../../src/v2/lib/shallow-stable-ref.ts","../../src/v2/providers/CopilotChatConfigurationProvider.tsx","../../src/v2/hooks/use-agent.tsx","../../src/v2/hooks/use-frontend-tool.tsx","../../src/v2/hooks/use-component.tsx","../../src/v2/hooks/use-human-in-the-loop.tsx","../../src/v2/hooks/use-interrupt.tsx","../../src/v2/hooks/use-suggestions.tsx","../../src/v2/hooks/use-configure-suggestions.tsx","../../src/v2/hooks/use-agent-context.tsx","../../src/v2/hooks/use-threads.tsx","../../src/v2/types/defineToolCallRenderer.ts","../../src/v2/hooks/use-render-tool.tsx","../../src/v2/hooks/use-render-tool-call.tsx","../../src/v2/hooks/use-capabilities.tsx"],"sourcesContent":["import { useRef } from \"react\";\n\n// Tailwind-free reference-stability helpers. Kept in their own leaf module (not\n// in ./slots, which imports `tailwind-merge`) so that DOM/CSS-free consumers —\n// e.g. CopilotChatConfigurationProvider, which is re-exported from the lean\n// `@copilotkit/react-core/v2/headless` entry — can reach them without pulling\n// `tailwind-merge` into the bundle (issue #4893).\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","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\";\n// Import from the tailwind-free leaf module (not ../lib/slots, which pulls\n// tailwind-merge) so this provider stays lean in the headless entry (issue #4893).\nimport { useShallowStableRef } from \"../lib/shallow-stable-ref\";\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 { useCopilotKit } from \"../context\";\nimport { useMemo, useEffect, useReducer, useRef, useState } from \"react\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport {\n ProxiedCopilotRuntimeAgent,\n CopilotKitCoreRuntimeConnectionStatus,\n} from \"@copilotkit/core\";\nimport type { SubscribeToAgentSubscriber } from \"@copilotkit/core\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\n\nexport enum UseAgentUpdate {\n OnMessagesChanged = \"OnMessagesChanged\",\n OnStateChanged = \"OnStateChanged\",\n OnRunStatusChanged = \"OnRunStatusChanged\",\n}\n\nconst ALL_UPDATES: UseAgentUpdate[] = [\n UseAgentUpdate.OnMessagesChanged,\n UseAgentUpdate.OnStateChanged,\n UseAgentUpdate.OnRunStatusChanged,\n];\n\ninterface UseAgentPropsBase {\n updates?: UseAgentUpdate[];\n /**\n * Throttle interval (in milliseconds) for re-renders triggered by\n * `onMessagesChanged` and `onStateChanged` notifications. Useful to reduce\n * re-render frequency during high-frequency streaming updates.\n *\n * Uses a leading+trailing pattern with a shared window — first update\n * fires immediately, subsequent updates within the window are coalesced,\n * and a trailing timer ensures the most recent update fires after the\n * window expires. See `CopilotKitCore.subscribeToAgentWithOptions` in `@copilotkit/core`\n * for details.\n *\n * Resolved as: `throttleMs ?? provider defaultThrottleMs ?? 0`.\n * Passing `throttleMs={0}` explicitly disables throttling even when the\n * provider specifies a non-zero `defaultThrottleMs`.\n *\n * Run lifecycle callbacks (`onRunInitialized`, `onRunFinalized`,\n * `onRunFailed`, `onRunErrorEvent`) always fire immediately.\n *\n * @default undefined\n * When unset, inherits from the provider's `defaultThrottleMs`;\n * if that is also unset, the effective value is `0` (no throttle).\n */\n throttleMs?: number;\n}\n\n/**\n * Thread-scoped variant. `agentId`, `runtimeAgentId`, and `threadId` are a\n * matched set: together they give this hook a *private* agent — registered\n * under the local `agentId`, routing outbound to `runtimeAgentId` — that is\n * safe to pin a thread onto. None of the three is meaningful without the other\n * two, so all are required here.\n */\ninterface UseAgentThreadScopedProps {\n /**\n * The name to register this hook's proxied agent under.\n *\n * Required, and must not already be taken. The usual fallbacks (the chat\n * configuration's agentId, then `DEFAULT_AGENT_ID`) name agents that already\n * exist, and registering over one either throws `already registered` or\n * silently shadows it, depending on whether runtime discovery has landed — so\n * the caller has to name it.\n */\n agentId: string;\n /**\n * Thread to scope the agent's run to. Written onto the underlying agent, so\n * `/agent/run`, `/agent/connect`, and `/agent/stop` address this thread.\n *\n * REQUIRES `runtimeAgentId`. A runtime agent registered under a given id is a\n * singleton, so writing a per-hook threadId directly onto it would let two\n * `useAgent` calls that share an `agentId` clobber each other's thread.\n * Passing a distinct local `agentId` plus the `runtimeAgentId` it routes to\n * gives this hook a private proxied agent to pin the thread onto instead of a\n * shared one.\n */\n threadId: string;\n /**\n * The id of the runtime agent to route outbound requests to, while this hook\n * exposes a distinct local `agentId`. Registers a proxied agent via\n * `CopilotKitCore.registerProxiedAgent`, letting several frontend agents\n * (e.g. one per open thread) mount against a single runtime agent without a\n * shared-singleton collision.\n *\n * When set, `agentId` is the *local* registry id (must not collide with an\n * existing local or runtime-discovered agent) and `runtimeAgentId` is the\n * runtime agent the proxy addresses on `/agent/run` etc.\n *\n * REQUIRES `threadId`. Registering a private agent is only worth doing to\n * scope a thread to it; without a `threadId` the private agent would take its\n * thread from the chat configuration, which is what binding to the shared\n * agent via `agentId` alone already does — just with an extra registration\n * and a local id to keep unique.\n */\n runtimeAgentId: string;\n}\n\n/**\n * Default variant: neither `threadId` nor `runtimeAgentId`. The hook binds to\n * the shared agent registered under `agentId` and leaves its threadId to the\n * chat configuration (or to the agent's own auto-minted UUID).\n *\n * Both props are typed `undefined` here rather than omitted so that supplying\n * either one on its own fails to match *both* branches — that is the\n * type-level enforcement of the all-or-nothing rule.\n */\ninterface UseAgentUnscopedProps {\n /**\n * Agent to bind to. Resolution precedence: this property, then the surrounding\n * chat configuration's agentId, then the global default.\n */\n agentId?: string;\n /** Requires `runtimeAgentId`. See {@link UseAgentThreadScopedProps.threadId}. */\n threadId?: undefined;\n /** Requires `threadId`. See {@link UseAgentThreadScopedProps.runtimeAgentId}. */\n runtimeAgentId?: undefined;\n}\n\n/**\n * Props for {@link useAgent}.\n *\n * There are exactly two valid shapes, and the type admits nothing in between:\n *\n * - **Bind to an agent** — `useAgent()`, `useAgent({ agentId })`. The shared\n * instance from the registry; the thread comes from the chat configuration.\n * - **Bind a private agent to a thread** —\n * `useAgent({ agentId, runtimeAgentId, threadId })`. All three required.\n *\n * So `useAgent({ agentId, threadId })`, `useAgent({ agentId, runtimeAgentId })`,\n * and `useAgent({ runtimeAgentId, threadId })` are all compile errors. Each\n * partial combination is either unsafe (a thread scoped onto a shared singleton)\n * or pointless (a private agent with no thread, or one registered over an id\n * that already belongs to a real agent).\n */\nexport type UseAgentProps = UseAgentPropsBase &\n (UseAgentThreadScopedProps | UseAgentUnscopedProps);\n\nexport function useAgent({\n agentId,\n threadId,\n runtimeAgentId,\n updates,\n throttleMs,\n}: UseAgentProps = {}) {\n // `threadId` and `runtimeAgentId` are all-or-nothing. UseAgentProps already\n // rejects a lone one at compile time; these are the runtime backstop for\n // callers TypeScript doesn't cover — plain JS, `as any`, and props widened to\n // `string | undefined` at a call boundary. Fail loud rather than silently\n // mutating shared state or registering an agent that buys nothing.\n //\n // A threadId is written onto a single agent instance. An agent resolved by\n // `agentId` alone is a shared singleton, so a per-hook threadId there would\n // let two useAgent calls with the same agentId clobber each other's thread.\n // runtimeAgentId is what lets the hook register a *private* proxied agent\n // (below) and scope the threadId to that instead.\n if (threadId != null && runtimeAgentId == null) {\n throw new Error(\n `useAgent: \\`threadId\\` requires \\`runtimeAgentId\\`. A threadId is written onto a ` +\n `single agent, but an agent resolved by agentId alone is shared, so scoping a ` +\n `thread to it would clobber other useAgent callers. Pass a distinct local \\`agentId\\` ` +\n `and the runtime agent to route to, e.g. ` +\n `useAgent({ agentId: \"chat-1\", runtimeAgentId: \"${agentId ?? \"default\"}\", threadId }).`,\n );\n }\n\n // The converse: registering a private proxied agent is only worth doing in\n // order to scope a thread to it. Without a threadId the proxy would source its\n // thread from the chat configuration — exactly what binding to the shared\n // agent by `agentId` already does, minus a registration and a local id the\n // caller has to keep unique. Reject it rather than let it look meaningful.\n if (runtimeAgentId != null && threadId == null) {\n throw new Error(\n `useAgent: \\`runtimeAgentId\\` requires \\`threadId\\`. A proxied agent exists to scope a ` +\n `thread to a private instance; without a threadId it behaves like the shared agent ` +\n `while adding a registration and a local agentId to keep unique. Either pass the ` +\n `thread, e.g. useAgent({ agentId: \"${agentId ?? \"chat-1\"}\", runtimeAgentId: \"${runtimeAgentId}\", threadId }), ` +\n `or bind to the agent directly with useAgent({ agentId: \"${runtimeAgentId}\" }).`,\n );\n }\n\n // A proxied agent needs a local id of its own. Without an explicit `agentId`\n // the resolution below falls back to the chat configuration's agentId and then\n // DEFAULT_AGENT_ID — ids that already belong to real agents, so registering a\n // proxy over one either throws `already registered` or silently shadows it,\n // depending on whether runtime discovery has landed. Demand the caller name it.\n if (runtimeAgentId != null && agentId == null) {\n throw new Error(\n `useAgent: \\`runtimeAgentId\\` requires an explicit \\`agentId\\`. The proxied agent is ` +\n `registered under \\`agentId\\`, and the usual fallbacks (chat configuration, then ` +\n `\"${DEFAULT_AGENT_ID}\") name agents that already exist — registering over one throws or ` +\n `shadows it. Pick a local id for this hook, e.g. ` +\n `useAgent({ agentId: \"chat-1\", runtimeAgentId: \"${runtimeAgentId}\", threadId }).`,\n );\n }\n\n // Resolve agentId mirroring CopilotChat's precedence: an explicit prop wins,\n // then the surrounding chat configuration's agentId, then the global default.\n // Without the chat-config fallback, a useAgent() consumer rendered inside a\n // <CopilotChat agentId=\"...\"> subtree resolves to 'default' and throws once\n // the runtime has synced only a non-default agent (#5533).\n const chatConfig = useCopilotChatConfiguration();\n const resolvedAgentId = agentId ?? chatConfig?.agentId ?? DEFAULT_AGENT_ID;\n\n const { copilotkit } = useCopilotKit();\n // Read the provider-level default so it appears in the effect's dep array.\n // subscribeToAgentWithOptions reads it from the core instance, but React needs the dep\n // to know when to re-subscribe.\n const providerThrottleMs = copilotkit.defaultThrottleMs;\n\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n const updateFlags = useMemo(\n () => updates ?? ALL_UPDATES,\n [JSON.stringify(updates)],\n );\n\n // Cache provisional agents to avoid creating new references on every render\n // while the runtime is still connecting. A new reference would cascade into\n // CopilotChat's connectAgent effect, causing unnecessary HTTP calls.\n const provisionalAgentCache = useRef<Map<string, ProxiedCopilotRuntimeAgent>>(\n new Map(),\n );\n\n // When runtimeAgentId is set, this hook owns a proxied agent registered under\n // `resolvedAgentId` that routes to `runtimeAgentId`. Register/unregister as a\n // single balanced effect (StrictMode-safe: the cleanup unregisters before the\n // remount re-registers). Exposing the registered agent via state re-renders\n // the hook so it swaps from the provisional stand-in to the real proxy\n // deterministically, without depending on the provider's agents-changed\n // subscription.\n const [registeredProxyAgent, setRegisteredProxyAgent] =\n useState<AbstractAgent | null>(null);\n useEffect(() => {\n if (runtimeAgentId == null) {\n setRegisteredProxyAgent(null);\n return;\n }\n const { agent: proxy, unregister } = copilotkit.registerProxiedAgent({\n agentId: resolvedAgentId,\n runtimeAgentId,\n });\n provisionalAgentCache.current.delete(resolvedAgentId);\n setRegisteredProxyAgent(proxy);\n return () => {\n unregister();\n setRegisteredProxyAgent(null);\n };\n }, [copilotkit, resolvedAgentId, runtimeAgentId]);\n\n const { agent, isReady } = useMemo<{\n agent: AbstractAgent;\n isReady: boolean;\n }>(() => {\n // Proxied-agent path: this hook registers its own agent (routing to\n // runtimeAgentId), so bypass the shared-singleton lookup entirely. Use the\n // registered instance once the effect has run; until then return a\n // provisional proxy so `agent` is never null and its reference stays stable\n // across the pre-registration renders.\n if (runtimeAgentId != null) {\n if (registeredProxyAgent) {\n provisionalAgentCache.current.delete(resolvedAgentId);\n return { agent: registeredProxyAgent, isReady: true };\n }\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n copilotkit.applyHeadersToAgent(cached);\n return { agent: cached, isReady: false };\n }\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n runtimeAgentId,\n transport: copilotkit.runtimeTransport,\n runtimeMode: \"pending\",\n });\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n const existing = copilotkit.getAgent(resolvedAgentId);\n if (existing) {\n // Real agent found — clear any cached provisional for this ID\n provisionalAgentCache.current.delete(resolvedAgentId);\n return { agent: existing, isReady: true };\n }\n\n const isRuntimeConfigured = copilotkit.runtimeUrl !== undefined;\n const status = copilotkit.runtimeConnectionStatus;\n\n // While runtime is not yet synced, return a provisional runtime agent\n if (\n isRuntimeConfigured &&\n (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected ||\n status === CopilotKitCoreRuntimeConnectionStatus.Connecting)\n ) {\n // Return cached provisional if available (keeps reference stable)\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n return { agent: cached, isReady: false };\n }\n\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n transport: copilotkit.runtimeTransport,\n credentials: copilotkit.credentials,\n runtimeMode: \"pending\",\n });\n // Apply current headers so runs/connects inherit them\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n // Runtime is in Error state — return a provisional agent instead of throwing.\n // The error has already been emitted through the subscriber system\n // (RUNTIME_INFO_FETCH_FAILED). Throwing here would crash the React tree;\n // returning a provisional agent lets onError handlers fire while keeping\n // the app alive.\n if (\n isRuntimeConfigured &&\n status === CopilotKitCoreRuntimeConnectionStatus.Error\n ) {\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n return { agent: cached, isReady: false };\n }\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n transport: copilotkit.runtimeTransport,\n credentials: copilotkit.credentials,\n runtimeMode: \"pending\",\n });\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n // No runtime configured and agent doesn't exist — this is a configuration error.\n const knownAgents = Object.keys(copilotkit.agents ?? {});\n const runtimePart = isRuntimeConfigured\n ? `runtimeUrl=${copilotkit.runtimeUrl}`\n : \"no runtimeUrl\";\n throw new Error(\n `useAgent: Agent '${resolvedAgentId}' not found after runtime sync (${runtimePart}). ` +\n (knownAgents.length\n ? `Known agents: [${knownAgents.join(\", \")}]`\n : \"No agents registered.\") +\n \" Verify your runtime /info and/or agents__unsafe_dev_only.\",\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n resolvedAgentId,\n runtimeAgentId,\n registeredProxyAgent,\n copilotkit.agents,\n copilotkit.runtimeConnectionStatus,\n copilotkit.runtimeUrl,\n copilotkit.runtimeTransport,\n copilotkit.credentials,\n JSON.stringify(copilotkit.headers),\n ]);\n\n useEffect(() => {\n if (updateFlags.length === 0) return;\n\n let active = true;\n const handlers: SubscribeToAgentSubscriber = {};\n\n // Microtask-batched forceUpdate: coalesces multiple synchronous\n // notifications (e.g. OnStateChanged + OnRunStatusChanged firing in the\n // same tick) into a single React re-render. This prevents the scroll\n // jumping described in #3499 where rapid unbatched forceUpdate calls\n // cause brief content height fluctuations during streaming.\n let batchScheduled = false;\n const batchedForceUpdate = () => {\n if (!active) return;\n if (!batchScheduled) {\n batchScheduled = true;\n queueMicrotask(() => {\n batchScheduled = false;\n if (active) {\n forceUpdate();\n }\n });\n }\n };\n\n if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {\n handlers.onMessagesChanged = batchedForceUpdate;\n }\n\n if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) {\n handlers.onStateChanged = batchedForceUpdate;\n }\n\n if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {\n handlers.onRunInitialized = batchedForceUpdate;\n handlers.onRunFinalized = batchedForceUpdate;\n handlers.onRunFailed = batchedForceUpdate;\n // Protocol-level RUN_ERROR event (distinct from onRunFailed which\n // handles local exceptions like network errors).\n handlers.onRunErrorEvent = batchedForceUpdate;\n }\n\n const subscription = copilotkit.subscribeToAgentWithOptions(\n agent,\n handlers,\n {\n throttleMs,\n },\n );\n return () => {\n active = false;\n subscription.unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, forceUpdate, throttleMs, providerThrottleMs, updateFlags]);\n\n // Keep HttpAgent request settings fresh without mutating inside useMemo,\n // which is unsafe in concurrent mode (React may invoke useMemo multiple\n // times and discard intermediate results, but mutations always land).\n useEffect(() => {\n if (agent instanceof HttpAgent) {\n // Merge core headers on top of the agent's own headers rather than\n // replacing them, so per-agent headers (e.g. an Authorization for a\n // self-hosted backend) are preserved (see #5635).\n copilotkit.applyHeadersToAgent(agent);\n }\n if (agent instanceof ProxiedCopilotRuntimeAgent) {\n agent.credentials = copilotkit.credentials;\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, JSON.stringify(copilotkit.headers), copilotkit.credentials]);\n\n // Propagate the caller-supplied threadId onto the agent. AbstractAgent's\n // constructor auto-mints a UUID when no threadId is passed, so without this\n // sync the agent ships its own random UUID in /agent/run, /agent/connect,\n // /agent/stop — diverging from the threadId the app code intends.\n //\n // Resolution precedence:\n // 1. An explicit `threadId` prop always wins. This lets headless callers\n // (e.g. React Native) scope the run to a thread without a\n // <CopilotChatConfigurationProvider> in the tree.\n // 2. Otherwise fall back to the chat configuration's threadId, gated on\n // hasExplicitThreadId so a ThreadsProvider-minted placeholder UUID\n // doesn't overwrite the auto-minted agent UUID (both are random and\n // useless to the backend; the explicit gate keeps the agent's UUID\n // stable across renders).\n const configThreadId = chatConfig?.threadId;\n const configHasExplicitThreadId = chatConfig?.hasExplicitThreadId;\n const resolvedThreadId =\n threadId ?? (configHasExplicitThreadId ? configThreadId : undefined);\n useEffect(() => {\n if (!resolvedThreadId) return;\n agent.threadId = resolvedThreadId;\n }, [agent, resolvedThreadId]);\n\n return {\n agent,\n /**\n * Whether `agent` is the real, runtime-synced (or locally-registered) agent\n * rather than a provisional stand-in returned while the runtime is still\n * connecting (or in an error state).\n *\n * `agent` is always a fully-constructed `AbstractAgent`, so calling\n * `agent.subscribe(...)`, `agent.setState(...)`, etc. is always safe. But\n * while `isReady` is `false` the instance is a placeholder that will be\n * swapped for the real agent once the runtime `/info` sync resolves, at\n * which point `agent` changes reference and dependent effects re-run.\n * Guard on `isReady` when you only want to act against the real agent —\n * e.g. subscribing to run-lifecycle events you don't want to miss during\n * the provisional window (#5000).\n */\n isReady,\n };\n}\n","import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../context\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core.\n // The render function is registered even when tool.parameters is\n // undefined — tools like HITL confirm dialogs have no parameters\n // but still need their UI rendered in the chat.\n if (tool.render) {\n copilotkit.addHookRenderToolCall({\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n });\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, JSON.stringify(extraDeps)]);\n}\n","import type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport type { ComponentType } from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\ntype InferRenderProps<T> = T extends StandardSchemaV1\n ? InferSchemaOutput<T>\n : any;\n\n/**\n * Registers a React component as a frontend tool renderer in chat.\n *\n * This hook is a convenience wrapper around `useFrontendTool` that:\n * - builds a model-facing tool description,\n * - forwards optional schema parameters (any Standard Schema V1 compatible library),\n * - renders your component with tool call parameters.\n *\n * Use this when you want to display a typed visual component for a tool call\n * without manually wiring a full frontend tool object.\n *\n * When `parameters` is provided, render props are inferred from the schema.\n * When omitted, the render component may accept any props.\n *\n * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.\n * @param config - Tool registration config.\n * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).\n *\n * @example\n * ```tsx\n * // Without parameters — render accepts any props\n * useComponent({\n * name: \"showGreeting\",\n * render: ({ message }: { message: string }) => <div>{message}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With parameters — render props inferred from schema\n * useComponent({\n * name: \"showWeatherCard\",\n * parameters: z.object({ city: z.string() }),\n * render: ({ city }) => <div>{city}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * useComponent(\n * {\n * name: \"renderProfile\",\n * parameters: z.object({ userId: z.string() }),\n * render: ProfileCard,\n * agentId: \"support-agent\",\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useComponent<\n TSchema extends StandardSchemaV1<any, Record<string, unknown>> | undefined =\n undefined,\n>(\n config: {\n name: string;\n description?: string;\n parameters?: TSchema;\n render: ComponentType<NoInfer<InferRenderProps<TSchema>>>;\n agentId?: string;\n followUp?: boolean;\n },\n deps?: ReadonlyArray<unknown>,\n): void {\n const prefix = `Use this tool to display the \"${config.name}\" component in the chat. This tool renders a visual UI component for the user.`;\n const fullDescription = config.description\n ? `${prefix}\\n\\n${config.description}`\n : prefix;\n\n useFrontendTool(\n {\n name: config.name,\n description: fullDescription,\n parameters: config.parameters,\n render: ({ args }: { args: unknown }) => {\n const Component = config.render;\n return <Component {...(args as InferRenderProps<TSchema>)} />;\n },\n agentId: config.agentId,\n followUp: config.followUp,\n },\n deps,\n );\n}\n","import { useCopilotKit } from \"../context\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"../types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n // Cleanup that detaches the pending abort listener; cleared whenever the\n // promise settles (via respond() or abort) so the listener can't fire twice\n // or leak after the interaction is done.\n const cleanupAbortRef = useRef<(() => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n cleanupAbortRef.current?.();\n cleanupAbortRef.current = null;\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(\n async (_args: T, context?: { signal?: AbortSignal }) => {\n const signal = context?.signal;\n return new Promise((resolve, reject) => {\n // If the run was already aborted before the handler ran, reject\n // immediately so core records an explicit error tool result instead of\n // silently resolving to an empty string.\n if (signal?.aborted) {\n reject(new Error(\"Human-in-the-loop interaction aborted\"));\n return;\n }\n\n resolvePromiseRef.current = resolve;\n\n if (signal) {\n const onAbort = () => {\n cleanupAbortRef.current = null;\n resolvePromiseRef.current = null;\n reject(new Error(\"Human-in-the-loop interaction aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n cleanupAbortRef.current = () => {\n signal.removeEventListener(\"abort\", onAbort);\n };\n }\n });\n },\n [],\n );\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Build the HITL render props per status. `props` already carries\n // `toolCallId`; we overwrite `name`/`description` with the tool's\n // registration values and add the registration `agentId`, so the HITL\n // render always receives the full prop contract. `respond` is only live\n // while the tool is executing.\n if (props.status === ToolCallStatus.InProgress) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === ToolCallStatus.Executing) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === ToolCallStatus.Complete) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // ToolCallStatus has only the three states handled above, so this point\n // is unreachable and `props` narrows to `never`. The assignment turns a\n // newly-added status into a compile error here — forcing it to get its\n // own branch above — instead of silently rendering without `respond`.\n const exhaustiveCheck: never = props;\n return exhaustiveCheck;\n },\n [tool.render, tool.name, tool.description, tool.agentId, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n","import React, {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { randomUUID } from \"@ag-ui/client\";\nimport type { Interrupt, Message } from \"@ag-ui/client\";\nimport { ɵInterruptState } from \"@copilotkit/core\";\nimport type { ɵPendingInterrupt } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n InterruptResolveFn,\n InterruptCancelFn,\n} from \"../types/interrupt\";\n\nexport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n Interrupt,\n};\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\n/**\n * Normalized pending interrupt. `legacy` carries the custom-event payload;\n * `standard` carries the AG-UI `outcome:\"interrupt\"` interrupts array.\n */\ntype PendingInterrupt = ɵPendingInterrupt;\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/** Derive the legacy-compatible `event` for any pending interrupt. */\nfunction toLegacyEvent(pending: PendingInterrupt): InterruptEvent {\n if (pending.kind === \"legacy\") return pending.event;\n return { name: INTERRUPT_EVENT_NAME, value: pending.interrupts[0] };\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 * Receives both the standard `interrupt`/`interrupts` and the legacy `event`.\n * Call `resolve(payload)` to resume with user input, or `cancel()` to cancel.\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 * Return a sync or async value to expose as `result` in `render`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts this hook handles.\n * Receives the legacy-compatible event (for standard interrupts, `value` is\n * the primary `Interrupt`). Return `false` to ignore.\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. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When false, the hook returns the interrupt element so you can place 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. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts with optional filtering, preprocessing, and resume behavior.\n *\n * Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with\n * `outcome.type === \"interrupt\"`) and the legacy custom-event flow\n * (`on_interrupt`). For standard interrupts, `render` receives `interrupt`\n * (the primary one) and `interrupts` (the full open set); call `resolve(payload)`\n * to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt\n * and, once every open interrupt is addressed, submits a single spec `resume`\n * array via `copilotkit.runAgent`.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element for manual placement.\n *\n * @example\n * ```tsx\n * useInterrupt({\n * render: ({ interrupt, resolve, cancel }) => (\n * <div>\n * <p>{interrupt?.message}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => cancel()}>Cancel</button>\n * </div>\n * ),\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 [pending, setPending] = useState<PendingInterrupt | null>(null);\n const pendingRef = useRef(pending);\n pendingRef.current = pending;\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n const interruptStateRef = useRef(new ɵInterruptState());\n\n useEffect(() => {\n const interruptState = interruptStateRef.current;\n let localLegacy: InterruptEvent | null = null;\n let localStandard: Interrupt[] | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localLegacy = { name: event.name, value: event.value };\n }\n },\n onRunFinishedEvent: (params) => {\n if (params.outcome === \"interrupt\") {\n localStandard = params.interrupts;\n }\n },\n onRunStartedEvent: () => {\n localLegacy = null;\n localStandard = null;\n interruptState.clear();\n setPending(null);\n },\n onRunFinalized: () => {\n // Standard wins if both somehow appear for one run.\n if (localStandard && localStandard.length > 0) {\n interruptState.setStandard(localStandard);\n setPending(interruptState.pending);\n } else if (localLegacy) {\n interruptState.setLegacy(localLegacy);\n setPending(interruptState.pending);\n }\n localLegacy = null;\n localStandard = null;\n },\n onRunFailed: () => {\n localLegacy = null;\n localStandard = null;\n interruptState.clear();\n setPending(null);\n },\n });\n\n return () => {\n subscription.unsubscribe();\n interruptState.clear();\n };\n }, [agent]);\n\n const resolve: InterruptResolveFn = useCallback(\n async (payload, interruptId) => {\n const current = pendingRef.current;\n if (!current) return;\n\n if (\n current.kind === \"standard\" &&\n current.interrupts.length > 1 &&\n interruptId === undefined\n ) {\n console.warn(\n `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,\n );\n }\n const decision = interruptStateRef.current.resolve(payload, interruptId);\n if (decision.kind === \"legacy-resume\") {\n try {\n return await copilotkit.runAgent({\n agent,\n forwardedProps: {\n command: {\n resume: decision.payload,\n interruptEvent: decision.interruptValue,\n },\n },\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n setPending(null);\n throw err;\n }\n }\n if (decision.kind === \"expired\") {\n console.error(\n `[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`,\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind !== \"resume\") return;\n for (const toolResult of decision.toolResults) {\n agent.addMessage({\n id: randomUUID(),\n role: \"tool\",\n toolCallId: toolResult.toolCallId,\n content: toolResult.content,\n } as Message);\n }\n try {\n return await copilotkit.runAgent({ agent, resume: decision.resume });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n interruptStateRef.current.clear();\n setPending(null);\n throw err;\n }\n },\n [agent, copilotkit],\n );\n\n const cancel: InterruptCancelFn = useCallback(\n async (interruptId) => {\n const current = pendingRef.current;\n if (!current) return;\n\n if (\n current.kind === \"standard\" &&\n current.interrupts.length > 1 &&\n interruptId === undefined\n ) {\n console.warn(\n `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,\n );\n }\n const decision = interruptStateRef.current.cancel(interruptId);\n if (decision.kind === \"dismiss\") {\n // Legacy interrupts have no cancel semantics; dismiss without resuming.\n console.warn(\n \"[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.\",\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind === \"expired\") {\n console.error(\n `[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`,\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind !== \"resume\") return;\n for (const toolResult of decision.toolResults) {\n agent.addMessage({\n id: randomUUID(),\n role: \"tool\",\n toolCallId: toolResult.toolCallId,\n content: toolResult.content,\n } as Message);\n }\n try {\n return await copilotkit.runAgent({ agent, resume: decision.resume });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n interruptStateRef.current.clear();\n setPending(null);\n throw err;\n }\n },\n [agent, copilotkit],\n );\n\n // Stabilize consumer-supplied callbacks behind refs so inline lambdas do not\n // churn the element memo identity or the handler effect.\n const renderRef = useRef(config.render);\n renderRef.current = config.render;\n const enabledRef = useRef(config.enabled);\n enabledRef.current = config.enabled;\n const handlerRef = useRef(config.handler);\n handlerRef.current = config.handler;\n const resolveRef = useRef(resolve);\n resolveRef.current = resolve;\n const cancelRef = useRef(cancel);\n cancelRef.current = cancel;\n\n // Predicate evaluator: a throw is treated as \"disabled\" (false) and logged.\n const isEnabled = (event: InterruptEvent): boolean => {\n const predicate = enabledRef.current;\n if (!predicate) return true;\n try {\n return predicate(event);\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt enabled predicate threw; treating interrupt as disabled:\",\n err,\n );\n return false;\n }\n };\n\n useEffect(() => {\n if (!pending) {\n setHandlerResult(null);\n return;\n }\n const legacyEvent = toLegacyEvent(pending);\n if (!isEnabled(legacyEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = handlerRef.current;\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n let maybePromise: ReturnType<typeof handler>;\n try {\n maybePromise = handler({\n event: legacyEvent,\n interrupt: pending.kind === \"standard\" ? pending.interrupts[0] : null,\n interrupts: pending.kind === \"standard\" ? [...pending.interrupts] : [],\n resolve: resolveRef.current,\n cancel: cancelRef.current,\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt handler threw; result will be null:\",\n err,\n );\n if (!cancelled) setHandlerResult(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch((err) => {\n console.error(\n \"[CopilotKit] useInterrupt handler rejected; result will be null:\",\n err,\n );\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 }, [pending]);\n\n const element = useMemo(() => {\n if (!pending) return null;\n const legacyEvent = toLegacyEvent(pending);\n if (!isEnabled(legacyEvent)) return null;\n\n return renderRef.current({\n event: legacyEvent,\n interrupt: pending.kind === \"standard\" ? pending.interrupts[0] : null,\n interrupts: pending.kind === \"standard\" ? [...pending.interrupts] : [],\n result: handlerResult,\n resolve,\n cancel,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pending, handlerResult, resolve, cancel]);\n\n // Publish to core for in-chat rendering. Publish-only.\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n }, [element, config.renderInChat, copilotkit]);\n\n // Nullify on true unmount only.\n useEffect(() => {\n if (config.renderInChat === false) return;\n return () => {\n copilotkit.setInterruptElement(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { Suggestion } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\n\nexport interface UseSuggestionsOptions {\n agentId?: string;\n}\n\nexport interface UseSuggestionsResult {\n suggestions: Suggestion[];\n reloadSuggestions: () => void;\n clearSuggestions: () => void;\n isLoading: boolean;\n}\n\nexport function useSuggestions({\n agentId,\n}: UseSuggestionsOptions = {}): UseSuggestionsResult {\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const resolvedAgentId = useMemo(\n () => agentId ?? config?.agentId ?? DEFAULT_AGENT_ID,\n [agentId, config?.agentId],\n );\n\n const [suggestions, setSuggestions] = useState<Suggestion[]>(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n return result.suggestions;\n });\n const [isLoading, setIsLoading] = useState(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n return result.isLoading;\n });\n\n useEffect(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n setSuggestions(result.suggestions);\n setIsLoading(result.isLoading);\n }, [copilotkit, resolvedAgentId]);\n\n useEffect(() => {\n const subscription = copilotkit.subscribe({\n onSuggestionsChanged: ({ agentId: changedAgentId, suggestions }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setSuggestions(suggestions);\n },\n onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setIsLoading(true);\n },\n onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setIsLoading(false);\n },\n onSuggestionsConfigChanged: () => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n setSuggestions(result.suggestions);\n setIsLoading(result.isLoading);\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [copilotkit, resolvedAgentId]);\n\n const reloadSuggestions = useCallback(() => {\n copilotkit.reloadSuggestions(resolvedAgentId);\n // Loading state is handled by onSuggestionsStartedLoading event\n }, [copilotkit, resolvedAgentId]);\n\n const clearSuggestions = useCallback(() => {\n copilotkit.clearSuggestions(resolvedAgentId);\n // State updates are handled by onSuggestionsChanged event\n }, [copilotkit, resolvedAgentId]);\n\n return {\n suggestions,\n reloadSuggestions,\n clearSuggestions,\n isLoading,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport type {\n DynamicSuggestionsConfig,\n StaticSuggestionsConfig,\n SuggestionsConfig,\n Suggestion,\n} from \"@copilotkit/core\";\n\ntype StaticSuggestionInput = Omit<Suggestion, \"isLoading\"> &\n Partial<Pick<Suggestion, \"isLoading\">>;\n\ntype StaticSuggestionsConfigInput = Omit<\n StaticSuggestionsConfig,\n \"suggestions\"\n> & {\n suggestions: StaticSuggestionInput[];\n};\n\ntype SuggestionsConfigInput =\n | DynamicSuggestionsConfig\n | StaticSuggestionsConfigInput;\n\nexport function useConfigureSuggestions(\n config: SuggestionsConfigInput | null | undefined,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const chatConfig = useCopilotChatConfiguration();\n const extraDeps = deps ?? [];\n\n const resolvedConsumerAgentId = useMemo(\n () => chatConfig?.agentId ?? DEFAULT_AGENT_ID,\n [chatConfig?.agentId],\n );\n\n const rawConsumerAgentId = useMemo(\n () =>\n config ? (config as SuggestionsConfigInput).consumerAgentId : undefined,\n [config],\n );\n\n const normalizationCacheRef = useRef<{\n serialized: string | null;\n config: SuggestionsConfig | null;\n }>({\n serialized: null,\n config: null,\n });\n\n const { normalizedConfig, serializedConfig } = useMemo(() => {\n if (!config) {\n normalizationCacheRef.current = { serialized: null, config: null };\n return { normalizedConfig: null, serializedConfig: null };\n }\n\n if (config.available === \"disabled\") {\n normalizationCacheRef.current = { serialized: null, config: null };\n return { normalizedConfig: null, serializedConfig: null };\n }\n\n let built: SuggestionsConfig;\n if (isDynamicConfig(config)) {\n built = {\n ...config,\n } satisfies DynamicSuggestionsConfig;\n } else {\n const normalizedSuggestions = normalizeStaticSuggestions(\n config.suggestions,\n );\n const baseConfig: StaticSuggestionsConfig = {\n ...config,\n suggestions: normalizedSuggestions,\n };\n built = baseConfig;\n }\n\n const serialized = JSON.stringify(built);\n const cache = normalizationCacheRef.current;\n if (cache.serialized === serialized && cache.config) {\n return { normalizedConfig: cache.config, serializedConfig: serialized };\n }\n\n normalizationCacheRef.current = { serialized, config: built };\n return { normalizedConfig: built, serializedConfig: serialized };\n }, [config, resolvedConsumerAgentId, ...extraDeps]);\n const latestConfigRef = useRef<SuggestionsConfig | null>(null);\n latestConfigRef.current = normalizedConfig;\n const previousSerializedConfigRef = useRef<string | null>(null);\n\n const targetAgentId = useMemo(() => {\n if (!normalizedConfig) {\n return resolvedConsumerAgentId;\n }\n const consumer = (\n normalizedConfig as StaticSuggestionsConfig | DynamicSuggestionsConfig\n ).consumerAgentId;\n if (!consumer || consumer === \"*\") {\n return resolvedConsumerAgentId;\n }\n return consumer;\n }, [normalizedConfig, resolvedConsumerAgentId]);\n\n const isGlobalConfig =\n rawConsumerAgentId === undefined || rawConsumerAgentId === \"*\";\n\n const isDynamicConfigType = useMemo(\n () => !!normalizedConfig && \"instructions\" in normalizedConfig,\n [normalizedConfig],\n );\n\n const requestReload = useCallback(() => {\n if (!normalizedConfig) {\n return;\n }\n\n if (isGlobalConfig) {\n const seen = new Set<string>();\n const agents = Object.values(copilotkit.agents ?? {});\n for (const entry of agents) {\n const agentId = entry.agentId;\n if (!agentId) {\n continue;\n }\n seen.add(agentId);\n if (!entry.isRunning) {\n copilotkit.reloadSuggestions(agentId);\n }\n }\n // Also reload for the chat's resolved consumer agent. The registry can\n // be empty at this point (e.g. runtime info still loading), in which\n // case the loop above wouldn't have fired for the agent the user is\n // actually chatting with — and the welcome screen would render with\n // no suggestions until they navigate away and back.\n if (targetAgentId && !seen.has(targetAgentId)) {\n copilotkit.reloadSuggestions(targetAgentId);\n }\n return;\n }\n\n if (!targetAgentId) {\n return;\n }\n\n copilotkit.reloadSuggestions(targetAgentId);\n }, [copilotkit, isGlobalConfig, normalizedConfig, targetAgentId]);\n\n useEffect(() => {\n if (!serializedConfig || !latestConfigRef.current) {\n return;\n }\n\n const id = copilotkit.addSuggestionsConfig(latestConfigRef.current);\n\n requestReload();\n\n return () => {\n copilotkit.removeSuggestionsConfig(id);\n };\n }, [copilotkit, serializedConfig, requestReload]);\n\n useEffect(() => {\n if (!normalizedConfig) {\n previousSerializedConfigRef.current = null;\n return;\n }\n if (\n serializedConfig &&\n previousSerializedConfigRef.current === serializedConfig\n ) {\n return;\n }\n if (serializedConfig) {\n previousSerializedConfigRef.current = serializedConfig;\n }\n requestReload();\n }, [normalizedConfig, requestReload, serializedConfig]);\n\n useEffect(() => {\n if (!normalizedConfig || extraDeps.length === 0) {\n return;\n }\n requestReload();\n }, [extraDeps.length, normalizedConfig, requestReload, ...extraDeps]);\n\n // When agents arrive after the initial render (runtime info just landed),\n // re-request a reload so dynamic configs that need a real agent can finally\n // generate. Skip for static configs — they don't need an agent and the\n // initial mount reload already handled them. Skip when the target agent\n // is already in the registry — the initial reload already covered it, and\n // re-firing on every subsequent `onAgentsChanged` (e.g. dev-mode hot\n // reloads, sibling chat configs mounting) would stack overlapping\n // generations.\n useEffect(() => {\n if (!normalizedConfig || !isDynamicConfigType) return;\n if (!targetAgentId) return;\n\n const initiallyPresent = !!copilotkit.getAgent(targetAgentId);\n if (initiallyPresent) return;\n\n const subscription = copilotkit.subscribe({\n onAgentsChanged: () => {\n if (copilotkit.getAgent(targetAgentId)) {\n requestReload();\n subscription.unsubscribe();\n }\n },\n });\n return () => {\n subscription.unsubscribe();\n };\n }, [\n copilotkit,\n normalizedConfig,\n isDynamicConfigType,\n targetAgentId,\n requestReload,\n ]);\n}\n\nfunction isDynamicConfig(\n config: SuggestionsConfigInput,\n): config is DynamicSuggestionsConfig {\n return \"instructions\" in config;\n}\n\nfunction normalizeStaticSuggestions(\n suggestions: StaticSuggestionInput[],\n): Suggestion[] {\n return suggestions.map((suggestion) => ({\n ...suggestion,\n isLoading: suggestion.isLoading ?? false,\n }));\n}\n","import { useCopilotKit } from \"../context\";\nimport { useLayoutEffect, useMemo } from \"react\";\n\n/**\n * Represents any value that can be serialized to JSON.\n */\nexport type JsonSerializable =\n | string\n | number\n | boolean\n | null\n | JsonSerializable[]\n | { [key: string]: JsonSerializable };\n\n/**\n * Context configuration for useAgentContext.\n * Accepts any JSON-serializable value which will be converted to a string.\n */\nexport interface AgentContextInput {\n /** A human-readable description of what this context represents */\n description: string;\n /** The context value - will be converted to a JSON string if not already a string */\n value: JsonSerializable;\n}\n\nexport function useAgentContext(context: AgentContextInput) {\n const { description, value } = context;\n const { copilotkit } = useCopilotKit();\n\n const stringValue = useMemo(() => {\n if (typeof value === \"string\") {\n return value;\n }\n return JSON.stringify(value);\n }, [value]);\n\n useLayoutEffect(() => {\n if (!copilotkit) return;\n\n const id = copilotkit.addContext({ description, value: stringValue });\n return () => {\n copilotkit.removeContext(id);\n };\n }, [description, stringValue, copilotkit]);\n}\n","import { useCopilotKit } from \"../context\";\nimport {\n CopilotKitCoreRuntimeConnectionStatus,\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectFetchMoreError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n ɵselectIsMutating,\n} from \"@copilotkit/core\";\nimport type { ɵThreadRuntimeContext, ɵThreadStore } from \"@copilotkit/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread {\n id: string;\n agentId: string;\n name: string | null;\n archived: boolean;\n createdAt: string;\n updatedAt: string;\n /**\n * ISO-8601 timestamp of the most recent agent run on this thread. Absent\n * when the thread has never been run. Prefer this over `updatedAt` for\n * user-facing \"last activity\" displays — it is not bumped by metadata-only\n * actions like rename or archive.\n */\n lastRunAt?: string;\n}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Thread operations are scoped to the runtime-authenticated user and the\n * provided agent on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n /**\n * When `false`, the hook stays inert: no runtime context is dispatched, so\n * NO thread-list fetch or realtime subscription is issued. Used by gated\n * surfaces (e.g. an unlicensed `<CopilotThreadsDrawer>`) that must not touch the\n * network until the gate opens. Defaults to `true`.\n *\n * Flipping `enabled` back to `true` resumes normal fetching on the next\n * effect run; mutations are likewise short-circuited while disabled.\n */\n enabled?: boolean;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n *\n * This channel folds together developer/config errors (missing runtime URL,\n * runtime without thread endpoints) and genuine list-load/mutation failures.\n * End-user surfaces that must not leak config errors should prefer\n * {@link listError}, which excludes the config/runtime-setup errors.\n */\n error: Error | null;\n /**\n * The most recent genuine list-load or mutation error from the platform, or\n * `null`. Unlike {@link error}, this EXCLUDES developer/config errors (a\n * missing runtime URL, or a runtime that does not advertise thread\n * endpoints), so an end-user surface can render it directly without leaking\n * a developer-facing configuration message into the UI.\n */\n listError: Error | null;\n /**\n * The error from the most recent FAILED next-page (fetch-more) load, or\n * `null`. Tracked separately from {@link listError} so a paginated-load\n * failure surfaces an inline \"couldn't load more\" affordance while the\n * already-loaded list stays visible. Cleared when a fetch-more is retried or\n * succeeds.\n */\n fetchMoreError: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchMoreThreads}. Only meaningful when `limit` is set.\n */\n hasMoreThreads: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingMoreThreads: boolean;\n /**\n * `true` while at least one thread mutation (rename, archive, unarchive,\n * delete) is awaiting a server response. Mutations apply optimistically, so\n * this is primarily useful for disabling controls or showing a subtle\n * in-flight indicator.\n */\n isMutating: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasMoreThreads} is\n * `false` or a fetch is already in progress.\n */\n fetchMoreThreads: () => void;\n /**\n * Re-fetch the thread list from the platform without clearing the current\n * list. Backs the drawer's error-state Retry and the Active/All filter\n * refetch. No-op until the runtime is connected.\n */\n refetchThreads: () => void;\n /**\n * Reset to a fresh, non-explicit client-side thread so the welcome screen\n * shows. Lazy creation: no row appears in {@link threads} until the new\n * thread's first run persists server-side.\n */\n startNewThread: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Restore a previously archived thread on the platform.\n * The thread re-appears in default (non-archived) list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n unarchiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n // getServerSnapshot: without this third argument React throws\n // \"Missing getServerSnapshot\" during SSR/prerender (e.g. Next.js). The\n // store has no client data while prerendering, so we project from its\n // stable server state.\n () => selector(store.getServerState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the runtime-authenticated user\n * and the given `agentId`. When the Intelligence platform exposes a WebSocket\n * URL, it also opens a realtime subscription so the `threads` array stays\n * current without polling — thread creates, renames, archives, and deletes\n * from any client are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,\n * `deleteThread`) return promises that resolve once the platform confirms the\n * operation and reject with an `Error` on failure.\n *\n * @param input - Agent identifier and optional list controls.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkit/react-core\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n agentId,\n includeArchived,\n limit,\n enabled = true,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const coreThreads = useThreadStoreSelector(store, ɵselectThreads);\n const threads: Thread[] = useMemo(\n () =>\n coreThreads.map(\n ({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({\n id,\n agentId,\n name,\n archived,\n createdAt,\n updatedAt,\n ...(lastRunAt !== undefined ? { lastRunAt } : {}),\n }),\n ),\n [coreThreads],\n );\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const fetchMoreError = useThreadStoreSelector(store, ɵselectFetchMoreError);\n const hasMoreThreads = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingMoreThreads = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const isMutating = useThreadStoreSelector(store, ɵselectIsMutating);\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeStatus = copilotkit.runtimeConnectionStatus;\n const threadListEndpointSupported =\n copilotkit.threadEndpoints?.list !== false;\n const threadMutationsSupported =\n copilotkit.threadEndpoints?.mutations !== false;\n const threadEndpointsUnavailable =\n !!copilotkit.runtimeUrl &&\n runtimeStatus === CopilotKitCoreRuntimeConnectionStatus.Connected &&\n !threadListEndpointSupported;\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const threadEndpointsError = useMemo(() => {\n if (!threadEndpointsUnavailable) {\n return null;\n }\n\n return new Error(\n \"Thread endpoints are not available on this CopilotKit runtime\",\n );\n }, [threadEndpointsUnavailable]);\n const threadMutationsError = useMemo(() => {\n if (threadMutationsSupported) {\n return null;\n }\n\n return new Error(\n \"Thread mutations are not available on this CopilotKit runtime\",\n );\n }, [threadMutationsSupported]);\n\n // Tracks whether we've dispatched the first real context to the store.\n // The store itself starts with `isLoading: false`, so before we dispatch\n // consumers would otherwise see an empty, non-loading state (empty-list\n // flash). While runtimeUrl is set and we haven't dispatched yet, we\n // synthesize `isLoading: true` so the UI keeps its loading indicator until\n // the first fetch is in flight (at which point the store's own\n // isLoading takes over).\n const [hasDispatchedContext, setHasDispatchedContext] = useState(false);\n const preConnectLoading =\n enabled &&\n !!copilotkit.runtimeUrl &&\n !threadEndpointsUnavailable &&\n !hasDispatchedContext;\n\n // `startNewThread` resets to a clean welcome surface, so it should clear any\n // lingering error banner — including the config/runtime-setup errors that\n // otherwise outrank the store's own (already-cleared) error. We cannot clear\n // a derived `runtimeError`/`threadEndpointsError` directly (they reflect\n // current config), so we suppress them with a dismissal flag that resets\n // whenever the underlying config-error identity changes (a genuine new config\n // problem re-surfaces).\n const [configErrorDismissed, setConfigErrorDismissed] = useState(false);\n useEffect(() => {\n setConfigErrorDismissed(false);\n }, [runtimeError, threadEndpointsError]);\n\n const activeRuntimeError = configErrorDismissed ? null : runtimeError;\n const activeThreadEndpointsError = configErrorDismissed\n ? null\n : threadEndpointsError;\n\n const isLoading =\n activeRuntimeError || activeThreadEndpointsError\n ? false\n : preConnectLoading || storeIsLoading;\n const error = activeRuntimeError ?? activeThreadEndpointsError ?? storeError;\n // End-user-facing list/mutation error only: developer/config errors are\n // excluded so a surface like <CopilotThreadsDrawer> does not show \"Runtime URL is\n // not configured\" to an end user.\n const listError = storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n // Defer setting the context until the runtime reports Connected. Before\n // `/info` resolves we don't know `intelligence.wsUrl`, so dispatching the\n // context early would issue a list fetch with `wsUrl: undefined`, then a\n // second list fetch (and a `/threads/subscribe`) once the flag lands.\n // Waiting lets the hook issue just one `/threads?…` + one `/threads/subscribe`.\n //\n // When `runtimeUrl` is absent we dispatch `null` to clear the store. For\n // transient states (Disconnected/Connecting/Error with a URL still set) we\n // leave the previously-dispatched context in place — any in-flight\n // realtime subscription or cached thread list stays usable while the\n // runtime recovers, and we don't re-trigger a fetch storm on transitions.\n useEffect(() => {\n // A disabled (e.g. unlicensed) drawer must not claim the agentId slot. The\n // registry is single-slot/last-writer-wins, so registering an inert store\n // would evict — and on unmount tear down — a co-mounted live store for the\n // same agent. Staying unregistered while disabled leaves the live store's\n // registration intact.\n if (!enabled) return;\n copilotkit.registerThreadStore(agentId, store);\n return () => {\n copilotkit.unregisterThreadStore(agentId);\n };\n }, [copilotkit, agentId, store, enabled]);\n\n useEffect(() => {\n // Disabled: stay inert. Clear any previously-dispatched context so an\n // in-flight subscription is torn down and no further fetch is issued.\n if (!enabled) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n if (!copilotkit.runtimeUrl) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n // Wait for /info to land so we can include `wsUrl` in the initial\n // context and avoid a redundant second list fetch.\n if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) {\n return;\n }\n\n if (!threadListEndpointSupported) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n const context: ɵThreadRuntimeContext = {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n agentId,\n includeArchived,\n limit,\n };\n\n store.setContext(context);\n setHasDispatchedContext(true);\n }, [\n store,\n enabled,\n copilotkit.runtimeUrl,\n runtimeStatus,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n threadListEndpointSupported,\n agentId,\n includeArchived,\n limit,\n ]);\n\n const guardMutation = useCallback(\n <TArgs extends unknown[]>(\n mutation: (...args: TArgs) => Promise<void>,\n ): ((...args: TArgs) => Promise<void>) => {\n return (...args: TArgs) => {\n if (threadMutationsError) {\n return Promise.reject(threadMutationsError);\n }\n return mutation(...args);\n };\n },\n [threadMutationsError],\n );\n\n const renameThread = useMemo(\n () =>\n guardMutation((threadId: string, name: string) =>\n store.renameThread(threadId, name),\n ),\n [store, guardMutation],\n );\n\n const archiveThread = useMemo(\n () => guardMutation((threadId: string) => store.archiveThread(threadId)),\n [store, guardMutation],\n );\n\n const unarchiveThread = useMemo(\n () => guardMutation((threadId: string) => store.unarchiveThread(threadId)),\n [store, guardMutation],\n );\n\n const deleteThread = useMemo(\n () => guardMutation((threadId: string) => store.deleteThread(threadId)),\n [store, guardMutation],\n );\n\n const fetchMoreThreads = useCallback(() => store.fetchNextPage(), [store]);\n const refetchThreads = useCallback(() => store.refetchThreads(), [store]);\n const startNewThread = useCallback(() => {\n // The store's `newThreadStarted` reducer clears its own error; also dismiss\n // the derived config/runtime-setup errors so the welcome surface renders\n // with no stale error banner.\n setConfigErrorDismissed(true);\n store.startNewThread();\n }, [store]);\n\n return {\n threads,\n isLoading,\n error,\n listError,\n fetchMoreError,\n hasMoreThreads,\n isFetchingMoreThreads,\n isMutating,\n fetchMoreThreads,\n refetchThreads,\n startNewThread,\n renameThread,\n archiveThread,\n unarchiveThread,\n deleteThread,\n };\n}\n","import React from \"react\";\nimport { z } from \"zod\";\nimport type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport { ReactToolCallRenderer } from \"./react-tool-call-renderer\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\n\n/**\n * Helper to define a type-safe tool call renderer entry.\n * - Accepts a single object whose keys match ReactToolCallRenderer's fields: { name, args, render, agentId? }.\n * - Derives `args` type from the provided schema (any Standard Schema V1 compatible library).\n * - Ensures the render function param type exactly matches ReactToolCallRenderer<T>[\"render\"]'s param.\n * - For wildcard tools (name: \"*\"), args is optional and defaults to z.any()\n */\ntype RenderProps<T> =\n | {\n name: string;\n toolCallId: string;\n args: Partial<T>;\n status: ToolCallStatus.InProgress;\n result: undefined;\n }\n | {\n name: string;\n toolCallId: string;\n args: T;\n status: ToolCallStatus.Executing;\n result: undefined;\n }\n | {\n name: string;\n toolCallId: string;\n args: T;\n status: ToolCallStatus.Complete;\n result: string;\n };\n\n// Overload for wildcard tools without args\nexport function defineToolCallRenderer(def: {\n name: \"*\";\n render: (props: RenderProps<any>) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<any>;\n\n// Overload for regular tools with args\nexport function defineToolCallRenderer<S extends StandardSchemaV1>(def: {\n name: string;\n args: S;\n render: (props: RenderProps<InferSchemaOutput<S>>) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<InferSchemaOutput<S>>;\n\n// Implementation\nexport function defineToolCallRenderer<S extends StandardSchemaV1>(def: {\n name: string;\n args?: S;\n render: (props: any) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<any> {\n // For wildcard tools, default to z.any() if no args provided\n const argsSchema = def.name === \"*\" && !def.args ? z.any() : def.args;\n\n return {\n name: def.name,\n args: argsSchema,\n render: def.render as React.ComponentType<any>,\n ...(def.agentId ? { agentId: def.agentId } : {}),\n };\n}\n","import { useEffect } from \"react\";\nimport type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n // Branch per status so the discriminated union stays correlated\n // when `args` is re-exposed as `parameters`.\n render: (props) => {\n if (props.status === ToolCallStatus.InProgress) {\n return config.render({ ...props, parameters: props.args });\n }\n if (props.status === ToolCallStatus.Executing) {\n return config.render({ ...props, parameters: props.args });\n }\n return config.render({ ...props, parameters: props.args });\n },\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n copilotkit.addHookRenderToolCall(renderer);\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, JSON.stringify(extraDeps)]);\n}\n","import React, { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { ToolCall, ToolMessage } from \"@ag-ui/core\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport { partialJSONParse } from \"@copilotkit/shared\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nexport interface UseRenderToolCallProps {\n toolCall: ToolCall;\n toolMessage?: ToolMessage;\n}\n\n/**\n * Props for the memoized ToolCallRenderer component\n */\ninterface ToolCallRendererProps {\n toolCall: ToolCall;\n toolMessage?: ToolMessage;\n RenderComponent: ReactToolCallRenderer<unknown>[\"render\"];\n isExecuting: boolean;\n}\n\n/**\n * Memoized component that renders a single tool call.\n * This prevents unnecessary re-renders when parent components update\n * but the tool call data hasn't changed.\n */\nconst ToolCallRenderer = React.memo(\n function ToolCallRenderer({\n toolCall,\n toolMessage,\n RenderComponent,\n isExecuting,\n }: ToolCallRendererProps) {\n // Memoize args based on the arguments string to maintain stable reference\n const args = useMemo(\n () => partialJSONParse(toolCall.function.arguments),\n [toolCall.function.arguments],\n );\n\n const toolName = toolCall.function.name;\n\n // Render based on status to preserve discriminated union type inference\n if (toolMessage) {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.Complete}\n result={toolMessage.content}\n />\n );\n } else if (isExecuting) {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.Executing}\n result={undefined}\n />\n );\n } else {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.InProgress}\n result={undefined}\n />\n );\n }\n },\n // Custom comparison function to prevent re-renders when tool call data hasn't changed\n (prevProps, nextProps) => {\n // Compare tool call identity and content\n if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;\n if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name)\n return false;\n if (\n prevProps.toolCall.function.arguments !==\n nextProps.toolCall.function.arguments\n )\n return false;\n\n // Compare tool message (result)\n const prevResult = prevProps.toolMessage?.content;\n const nextResult = nextProps.toolMessage?.content;\n if (prevResult !== nextResult) return false;\n\n // Compare executing state\n if (prevProps.isExecuting !== nextProps.isExecuting) return false;\n\n // Compare render component reference\n if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;\n\n return true;\n },\n);\n\n/**\n * Hook that returns a function to render tool calls based on the render functions\n * defined in CopilotKitProvider.\n *\n * @returns A function that takes a tool call and optional tool message and returns the rendered component\n */\nexport function useRenderToolCall() {\n const { copilotkit, executingToolCallIds } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const agentId = config?.agentId ?? DEFAULT_AGENT_ID;\n\n // Subscribe to render tool calls changes using useSyncExternalStore\n // This ensures we always have the latest value, even if subscriptions run in any order\n const renderToolCalls = useSyncExternalStore(\n (callback) => {\n return copilotkit.subscribe({\n onRenderToolCallsChanged: callback,\n }).unsubscribe;\n },\n () => copilotkit.renderToolCalls,\n () => copilotkit.renderToolCalls,\n );\n\n // Note: executingToolCallIds is now provided by CopilotKitProvider context.\n // This is critical for HITL reconnection: when connecting to a thread with\n // pending tool calls, the onToolExecutionStart event fires before child components\n // mount. By tracking at the provider level, the executing state is already\n // available when this hook first runs.\n\n const renderToolCall = useCallback(\n ({\n toolCall,\n toolMessage,\n }: UseRenderToolCallProps): React.ReactElement | null => {\n // Find the render config for this tool call by name\n // For rendering, we show all tool calls regardless of agentId\n // The agentId scoping only affects handler execution (in core)\n // Priority order:\n // 1. Exact match by name (prefer agent-specific if multiple exist)\n // 2. Wildcard (*) renderer\n const exactMatches = renderToolCalls.filter(\n (rc) => rc.name === toolCall.function.name,\n );\n\n // If multiple renderers with same name exist, prefer the one matching our agentId\n const renderConfig =\n exactMatches.find((rc) => rc.agentId === agentId) ||\n exactMatches.find((rc) => !rc.agentId) ||\n exactMatches[0] ||\n renderToolCalls.find((rc) => rc.name === \"*\");\n\n // No per-tool or wildcard renderer registered → render nothing.\n // Showing an unhandled tool call is opt-in: register a named/wildcard\n // renderer via useRenderTool, or call useDefaultRenderTool() for the\n // built-in card. Auto-painting a default card here would leak internal\n // tool names plus raw args/result JSON into every app's chat in\n // production, so the card must be explicitly enabled.\n if (!renderConfig) {\n return null;\n }\n\n const RenderComponent =\n renderConfig.render as ReactToolCallRenderer<unknown>[\"render\"];\n const isExecuting = executingToolCallIds.has(toolCall.id);\n\n // Use the memoized ToolCallRenderer component to prevent unnecessary re-renders\n return (\n <ToolCallRenderer\n key={toolCall.id}\n toolCall={toolCall}\n toolMessage={toolMessage}\n RenderComponent={RenderComponent}\n isExecuting={isExecuting}\n />\n );\n },\n [renderToolCalls, executingToolCallIds, agentId],\n );\n\n return renderToolCall;\n}\n","import type { AgentCapabilities } from \"@ag-ui/core\";\nimport { useAgent } from \"./use-agent\";\n\n/**\n * Returns the capabilities declared by the given agent (or the agent resolved\n * from the surrounding chat configuration, falling back to the default agent).\n * Capabilities are populated from the runtime `/info` response at connection\n * time. The hook reads them synchronously from the agent instance — there is\n * no separate loading state, but the value will be `undefined` until the\n * runtime handshake completes.\n *\n * @param agentId - Optional agent ID. If omitted, inherits the surrounding\n * chat configuration's agent, falling back to the default agent.\n * @returns The agent's capabilities, or `undefined` if the agent doesn't\n * declare capabilities.\n */\nexport function useCapabilities(\n agentId?: string,\n): AgentCapabilities | undefined {\n const { agent } = useAgent({ agentId });\n\n if (agent && \"capabilities\" in agent) {\n return (agent as { capabilities?: AgentCapabilities }).capabilities;\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"headless.mjs","names":["useCopilotKit","EMPTY_DEPS","useCopilotKit","useCopilotKit","useCopilotKit","randomUUID","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit","useCopilotKit"],"sources":["../../src/v2/lib/shallow-stable-ref.ts","../../src/v2/providers/CopilotChatConfigurationProvider.tsx","../../src/v2/hooks/use-agent.tsx","../../src/v2/hooks/use-frontend-tool.tsx","../../src/v2/hooks/use-component.tsx","../../src/v2/hooks/use-human-in-the-loop.tsx","../../src/v2/hooks/use-interrupt.tsx","../../src/v2/hooks/use-suggestions.tsx","../../src/v2/hooks/use-configure-suggestions.tsx","../../src/v2/hooks/use-agent-context.tsx","../../src/v2/hooks/use-threads.tsx","../../src/v2/types/defineToolCallRenderer.ts","../../src/v2/hooks/use-render-tool.tsx","../../src/v2/hooks/use-render-tool-call.tsx","../../src/v2/hooks/use-capabilities.tsx"],"sourcesContent":["import { useRef } from \"react\";\n\n// Tailwind-free reference-stability helpers. Kept in their own leaf module (not\n// in ./slots, which imports `tailwind-merge`) so that DOM/CSS-free consumers —\n// e.g. CopilotChatConfigurationProvider, which is re-exported from the lean\n// `@copilotkit/react-core/v2/headless` entry — can reach them without pulling\n// `tailwind-merge` into the bundle (issue #4893).\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","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\";\n// Import from the tailwind-free leaf module (not ../lib/slots, which pulls\n// tailwind-merge) so this provider stays lean in the headless entry (issue #4893).\nimport { useShallowStableRef } from \"../lib/shallow-stable-ref\";\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 { useCopilotKit } from \"../context\";\nimport { useMemo, useEffect, useReducer, useRef, useState } from \"react\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport { HttpAgent } from \"@ag-ui/client\";\nimport {\n ProxiedCopilotRuntimeAgent,\n CopilotKitCoreRuntimeConnectionStatus,\n} from \"@copilotkit/core\";\nimport type { SubscribeToAgentSubscriber } from \"@copilotkit/core\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\n\nexport enum UseAgentUpdate {\n OnMessagesChanged = \"OnMessagesChanged\",\n OnStateChanged = \"OnStateChanged\",\n OnRunStatusChanged = \"OnRunStatusChanged\",\n}\n\nconst ALL_UPDATES: UseAgentUpdate[] = [\n UseAgentUpdate.OnMessagesChanged,\n UseAgentUpdate.OnStateChanged,\n UseAgentUpdate.OnRunStatusChanged,\n];\n\ninterface UseAgentPropsBase {\n updates?: UseAgentUpdate[];\n /**\n * Throttle interval (in milliseconds) for re-renders triggered by\n * `onMessagesChanged` and `onStateChanged` notifications. Useful to reduce\n * re-render frequency during high-frequency streaming updates.\n *\n * Uses a leading+trailing pattern with a shared window — first update\n * fires immediately, subsequent updates within the window are coalesced,\n * and a trailing timer ensures the most recent update fires after the\n * window expires. See `CopilotKitCore.subscribeToAgentWithOptions` in `@copilotkit/core`\n * for details.\n *\n * Resolved as: `throttleMs ?? provider defaultThrottleMs ?? 0`.\n * Passing `throttleMs={0}` explicitly disables throttling even when the\n * provider specifies a non-zero `defaultThrottleMs`.\n *\n * Run lifecycle callbacks (`onRunInitialized`, `onRunFinalized`,\n * `onRunFailed`, `onRunErrorEvent`) always fire immediately.\n *\n * @default undefined\n * When unset, inherits from the provider's `defaultThrottleMs`;\n * if that is also unset, the effective value is `0` (no throttle).\n */\n throttleMs?: number;\n}\n\n/**\n * Thread-scoped variant. `agentId`, `runtimeAgentId`, and `threadId` are a\n * matched set: together they give this hook a *private* agent — registered\n * under the local `agentId`, routing outbound to `runtimeAgentId` — that is\n * safe to pin a thread onto. None of the three is meaningful without the other\n * two, so all are required here.\n */\ninterface UseAgentThreadScopedProps {\n /**\n * The name to register this hook's proxied agent under.\n *\n * Required, and must not already be taken. The usual fallbacks (the chat\n * configuration's agentId, then `DEFAULT_AGENT_ID`) name agents that already\n * exist, and registering over one either throws `already registered` or\n * silently shadows it, depending on whether runtime discovery has landed — so\n * the caller has to name it.\n */\n agentId: string;\n /**\n * Thread to scope the agent's run to. Written onto the underlying agent, so\n * `/agent/run`, `/agent/connect`, and `/agent/stop` address this thread.\n *\n * REQUIRES `runtimeAgentId`. A runtime agent registered under a given id is a\n * singleton, so writing a per-hook threadId directly onto it would let two\n * `useAgent` calls that share an `agentId` clobber each other's thread.\n * Passing a distinct local `agentId` plus the `runtimeAgentId` it routes to\n * gives this hook a private proxied agent to pin the thread onto instead of a\n * shared one.\n */\n threadId: string;\n /**\n * The id of the runtime agent to route outbound requests to, while this hook\n * exposes a distinct local `agentId`. Registers a proxied agent via\n * `CopilotKitCore.registerProxiedAgent`, letting several frontend agents\n * (e.g. one per open thread) mount against a single runtime agent without a\n * shared-singleton collision.\n *\n * When set, `agentId` is the *local* registry id (must not collide with an\n * existing local or runtime-discovered agent) and `runtimeAgentId` is the\n * runtime agent the proxy addresses on `/agent/run` etc.\n *\n * REQUIRES `threadId`. Registering a private agent is only worth doing to\n * scope a thread to it; without a `threadId` the private agent would take its\n * thread from the chat configuration, which is what binding to the shared\n * agent via `agentId` alone already does — just with an extra registration\n * and a local id to keep unique.\n */\n runtimeAgentId: string;\n}\n\n/**\n * Default variant: neither `threadId` nor `runtimeAgentId`. The hook binds to\n * the shared agent registered under `agentId` and leaves its threadId to the\n * chat configuration (or to the agent's own auto-minted UUID).\n *\n * Both props are typed `undefined` here rather than omitted so that supplying\n * either one on its own fails to match *both* branches — that is the\n * type-level enforcement of the all-or-nothing rule.\n */\ninterface UseAgentUnscopedProps {\n /**\n * Agent to bind to. Resolution precedence: this property, then the surrounding\n * chat configuration's agentId, then the global default.\n */\n agentId?: string;\n /** Requires `runtimeAgentId`. See {@link UseAgentThreadScopedProps.threadId}. */\n threadId?: undefined;\n /** Requires `threadId`. See {@link UseAgentThreadScopedProps.runtimeAgentId}. */\n runtimeAgentId?: undefined;\n}\n\n/**\n * Props for {@link useAgent}.\n *\n * There are exactly two valid shapes, and the type admits nothing in between:\n *\n * - **Bind to an agent** — `useAgent()`, `useAgent({ agentId })`. The shared\n * instance from the registry; the thread comes from the chat configuration.\n * - **Bind a private agent to a thread** —\n * `useAgent({ agentId, runtimeAgentId, threadId })`. All three required.\n *\n * So `useAgent({ agentId, threadId })`, `useAgent({ agentId, runtimeAgentId })`,\n * and `useAgent({ runtimeAgentId, threadId })` are all compile errors. Each\n * partial combination is either unsafe (a thread scoped onto a shared singleton)\n * or pointless (a private agent with no thread, or one registered over an id\n * that already belongs to a real agent).\n */\nexport type UseAgentProps = UseAgentPropsBase &\n (UseAgentThreadScopedProps | UseAgentUnscopedProps);\n\nexport function useAgent({\n agentId,\n threadId,\n runtimeAgentId,\n updates,\n throttleMs,\n}: UseAgentProps = {}) {\n // `threadId` and `runtimeAgentId` are all-or-nothing. UseAgentProps already\n // rejects a lone one at compile time; these are the runtime backstop for\n // callers TypeScript doesn't cover — plain JS, `as any`, and props widened to\n // `string | undefined` at a call boundary. Fail loud rather than silently\n // mutating shared state or registering an agent that buys nothing.\n //\n // A threadId is written onto a single agent instance. An agent resolved by\n // `agentId` alone is a shared singleton, so a per-hook threadId there would\n // let two useAgent calls with the same agentId clobber each other's thread.\n // runtimeAgentId is what lets the hook register a *private* proxied agent\n // (below) and scope the threadId to that instead.\n if (threadId != null && runtimeAgentId == null) {\n throw new Error(\n `useAgent: \\`threadId\\` requires \\`runtimeAgentId\\`. A threadId is written onto a ` +\n `single agent, but an agent resolved by agentId alone is shared, so scoping a ` +\n `thread to it would clobber other useAgent callers. Pass a distinct local \\`agentId\\` ` +\n `and the runtime agent to route to, e.g. ` +\n `useAgent({ agentId: \"chat-1\", runtimeAgentId: \"${agentId ?? \"default\"}\", threadId }).`,\n );\n }\n\n // The converse: registering a private proxied agent is only worth doing in\n // order to scope a thread to it. Without a threadId the proxy would source its\n // thread from the chat configuration — exactly what binding to the shared\n // agent by `agentId` already does, minus a registration and a local id the\n // caller has to keep unique. Reject it rather than let it look meaningful.\n if (runtimeAgentId != null && threadId == null) {\n throw new Error(\n `useAgent: \\`runtimeAgentId\\` requires \\`threadId\\`. A proxied agent exists to scope a ` +\n `thread to a private instance; without a threadId it behaves like the shared agent ` +\n `while adding a registration and a local agentId to keep unique. Either pass the ` +\n `thread, e.g. useAgent({ agentId: \"${agentId ?? \"chat-1\"}\", runtimeAgentId: \"${runtimeAgentId}\", threadId }), ` +\n `or bind to the agent directly with useAgent({ agentId: \"${runtimeAgentId}\" }).`,\n );\n }\n\n // A proxied agent needs a local id of its own. Without an explicit `agentId`\n // the resolution below falls back to the chat configuration's agentId and then\n // DEFAULT_AGENT_ID — ids that already belong to real agents, so registering a\n // proxy over one either throws `already registered` or silently shadows it,\n // depending on whether runtime discovery has landed. Demand the caller name it.\n if (runtimeAgentId != null && agentId == null) {\n throw new Error(\n `useAgent: \\`runtimeAgentId\\` requires an explicit \\`agentId\\`. The proxied agent is ` +\n `registered under \\`agentId\\`, and the usual fallbacks (chat configuration, then ` +\n `\"${DEFAULT_AGENT_ID}\") name agents that already exist — registering over one throws or ` +\n `shadows it. Pick a local id for this hook, e.g. ` +\n `useAgent({ agentId: \"chat-1\", runtimeAgentId: \"${runtimeAgentId}\", threadId }).`,\n );\n }\n\n // Resolve agentId mirroring CopilotChat's precedence: an explicit prop wins,\n // then the surrounding chat configuration's agentId, then the global default.\n // Without the chat-config fallback, a useAgent() consumer rendered inside a\n // <CopilotChat agentId=\"...\"> subtree resolves to 'default' and throws once\n // the runtime has synced only a non-default agent (#5533).\n const chatConfig = useCopilotChatConfiguration();\n const resolvedAgentId = agentId ?? chatConfig?.agentId ?? DEFAULT_AGENT_ID;\n\n const { copilotkit } = useCopilotKit();\n // Read the provider-level default so it appears in the effect's dep array.\n // subscribeToAgentWithOptions reads it from the core instance, but React needs the dep\n // to know when to re-subscribe.\n const providerThrottleMs = copilotkit.defaultThrottleMs;\n\n const [, forceUpdate] = useReducer((x) => x + 1, 0);\n\n const updateFlags = useMemo(\n () => updates ?? ALL_UPDATES,\n [JSON.stringify(updates)],\n );\n\n // Cache provisional agents to avoid creating new references on every render\n // while the runtime is still connecting. A new reference would cascade into\n // CopilotChat's connectAgent effect, causing unnecessary HTTP calls.\n const provisionalAgentCache = useRef<Map<string, ProxiedCopilotRuntimeAgent>>(\n new Map(),\n );\n\n // When runtimeAgentId is set, this hook owns a proxied agent registered under\n // `resolvedAgentId` that routes to `runtimeAgentId`. Register/unregister as a\n // single balanced effect (StrictMode-safe: the cleanup unregisters before the\n // remount re-registers). Exposing the registered agent via state re-renders\n // the hook so it swaps from the provisional stand-in to the real proxy\n // deterministically, without depending on the provider's agents-changed\n // subscription.\n const [registeredProxyAgent, setRegisteredProxyAgent] =\n useState<AbstractAgent | null>(null);\n useEffect(() => {\n if (runtimeAgentId == null) {\n setRegisteredProxyAgent(null);\n return;\n }\n const { agent: proxy, unregister } = copilotkit.registerProxiedAgent({\n agentId: resolvedAgentId,\n runtimeAgentId,\n });\n provisionalAgentCache.current.delete(resolvedAgentId);\n setRegisteredProxyAgent(proxy);\n return () => {\n unregister();\n setRegisteredProxyAgent(null);\n };\n }, [copilotkit, resolvedAgentId, runtimeAgentId]);\n\n const { agent, isReady } = useMemo<{\n agent: AbstractAgent;\n isReady: boolean;\n }>(() => {\n // Proxied-agent path: this hook registers its own agent (routing to\n // runtimeAgentId), so bypass the shared-singleton lookup entirely. Use the\n // registered instance once the effect has run; until then return a\n // provisional proxy so `agent` is never null and its reference stays stable\n // across the pre-registration renders.\n if (runtimeAgentId != null) {\n if (registeredProxyAgent) {\n provisionalAgentCache.current.delete(resolvedAgentId);\n return { agent: registeredProxyAgent, isReady: true };\n }\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n copilotkit.applyHeadersToAgent(cached);\n return { agent: cached, isReady: false };\n }\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n runtimeAgentId,\n transport: copilotkit.runtimeTransport,\n runtimeMode: \"pending\",\n });\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n const existing = copilotkit.getAgent(resolvedAgentId);\n if (existing) {\n // Real agent found — clear any cached provisional for this ID\n provisionalAgentCache.current.delete(resolvedAgentId);\n return { agent: existing, isReady: true };\n }\n\n const isRuntimeConfigured = copilotkit.runtimeUrl !== undefined;\n const status = copilotkit.runtimeConnectionStatus;\n\n // While runtime is not yet synced, return a provisional runtime agent\n if (\n isRuntimeConfigured &&\n (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected ||\n status === CopilotKitCoreRuntimeConnectionStatus.Connecting)\n ) {\n // Return cached provisional if available (keeps reference stable)\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n return { agent: cached, isReady: false };\n }\n\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n transport: copilotkit.runtimeTransport,\n credentials: copilotkit.credentials,\n runtimeMode: \"pending\",\n });\n // Apply current headers so runs/connects inherit them\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n // Runtime is in Error state — return a provisional agent instead of throwing.\n // The error has already been emitted through the subscriber system\n // (RUNTIME_INFO_FETCH_FAILED). Throwing here would crash the React tree;\n // returning a provisional agent lets onError handlers fire while keeping\n // the app alive.\n if (\n isRuntimeConfigured &&\n status === CopilotKitCoreRuntimeConnectionStatus.Error\n ) {\n const cached = provisionalAgentCache.current.get(resolvedAgentId);\n if (cached) {\n return { agent: cached, isReady: false };\n }\n const provisional = new ProxiedCopilotRuntimeAgent({\n runtimeUrl: copilotkit.runtimeUrl,\n agentId: resolvedAgentId,\n transport: copilotkit.runtimeTransport,\n credentials: copilotkit.credentials,\n runtimeMode: \"pending\",\n });\n copilotkit.applyHeadersToAgent(provisional);\n provisionalAgentCache.current.set(resolvedAgentId, provisional);\n return { agent: provisional, isReady: false };\n }\n\n // No runtime configured and agent doesn't exist — this is a configuration error.\n const knownAgents = Object.keys(copilotkit.agents ?? {});\n const runtimePart = isRuntimeConfigured\n ? `runtimeUrl=${copilotkit.runtimeUrl}`\n : \"no runtimeUrl\";\n throw new Error(\n `useAgent: Agent '${resolvedAgentId}' not found after runtime sync (${runtimePart}). ` +\n (knownAgents.length\n ? `Known agents: [${knownAgents.join(\", \")}]`\n : \"No agents registered.\") +\n \" Verify your runtime /info and/or agents__unsafe_dev_only.\",\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n resolvedAgentId,\n runtimeAgentId,\n registeredProxyAgent,\n copilotkit.agents,\n copilotkit.runtimeConnectionStatus,\n copilotkit.runtimeUrl,\n copilotkit.runtimeTransport,\n copilotkit.credentials,\n JSON.stringify(copilotkit.headers),\n ]);\n\n useEffect(() => {\n if (updateFlags.length === 0) return;\n\n let active = true;\n const handlers: SubscribeToAgentSubscriber = {};\n\n // Microtask-batched forceUpdate: coalesces multiple synchronous\n // notifications (e.g. OnStateChanged + OnRunStatusChanged firing in the\n // same tick) into a single React re-render. This prevents the scroll\n // jumping described in #3499 where rapid unbatched forceUpdate calls\n // cause brief content height fluctuations during streaming.\n let batchScheduled = false;\n const batchedForceUpdate = () => {\n if (!active) return;\n if (!batchScheduled) {\n batchScheduled = true;\n queueMicrotask(() => {\n batchScheduled = false;\n if (active) {\n forceUpdate();\n }\n });\n }\n };\n\n if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {\n handlers.onMessagesChanged = batchedForceUpdate;\n }\n\n if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) {\n handlers.onStateChanged = batchedForceUpdate;\n }\n\n if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {\n handlers.onRunInitialized = batchedForceUpdate;\n handlers.onRunFinalized = batchedForceUpdate;\n handlers.onRunFailed = batchedForceUpdate;\n // Protocol-level RUN_ERROR event (distinct from onRunFailed which\n // handles local exceptions like network errors).\n handlers.onRunErrorEvent = batchedForceUpdate;\n }\n\n const subscription = copilotkit.subscribeToAgentWithOptions(\n agent,\n handlers,\n {\n throttleMs,\n },\n );\n return () => {\n active = false;\n subscription.unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, forceUpdate, throttleMs, providerThrottleMs, updateFlags]);\n\n // Keep HttpAgent request settings fresh without mutating inside useMemo,\n // which is unsafe in concurrent mode (React may invoke useMemo multiple\n // times and discard intermediate results, but mutations always land).\n useEffect(() => {\n if (agent instanceof HttpAgent) {\n // Merge core headers on top of the agent's own headers rather than\n // replacing them, so per-agent headers (e.g. an Authorization for a\n // self-hosted backend) are preserved (see #5635).\n copilotkit.applyHeadersToAgent(agent);\n }\n if (agent instanceof ProxiedCopilotRuntimeAgent) {\n agent.credentials = copilotkit.credentials;\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, JSON.stringify(copilotkit.headers), copilotkit.credentials]);\n\n // Propagate the caller-supplied threadId onto the agent. AbstractAgent's\n // constructor auto-mints a UUID when no threadId is passed, so without this\n // sync the agent ships its own random UUID in /agent/run, /agent/connect,\n // /agent/stop — diverging from the threadId the app code intends.\n //\n // Resolution precedence:\n // 1. An explicit `threadId` prop always wins. This lets headless callers\n // (e.g. React Native) scope the run to a thread without a\n // <CopilotChatConfigurationProvider> in the tree.\n // 2. Otherwise fall back to the chat configuration's threadId, gated on\n // hasExplicitThreadId so a ThreadsProvider-minted placeholder UUID\n // doesn't overwrite the auto-minted agent UUID (both are random and\n // useless to the backend; the explicit gate keeps the agent's UUID\n // stable across renders).\n const configThreadId = chatConfig?.threadId;\n const configHasExplicitThreadId = chatConfig?.hasExplicitThreadId;\n const resolvedThreadId =\n threadId ?? (configHasExplicitThreadId ? configThreadId : undefined);\n useEffect(() => {\n if (!resolvedThreadId) return;\n agent.threadId = resolvedThreadId;\n }, [agent, resolvedThreadId]);\n\n return {\n agent,\n /**\n * Whether `agent` is the real, runtime-synced (or locally-registered) agent\n * rather than a provisional stand-in returned while the runtime is still\n * connecting (or in an error state).\n *\n * `agent` is always a fully-constructed `AbstractAgent`, so calling\n * `agent.subscribe(...)`, `agent.setState(...)`, etc. is always safe. But\n * while `isReady` is `false` the instance is a placeholder that will be\n * swapped for the real agent once the runtime `/info` sync resolves, at\n * which point `agent` changes reference and dependent effects re-run.\n * Guard on `isReady` when you only want to act against the real agent —\n * e.g. subscribing to run-lifecycle events you don't want to miss during\n * the provisional window (#5000).\n */\n isReady,\n };\n}\n","import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../context\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core.\n // The render function is registered even when tool.parameters is\n // undefined — tools like HITL confirm dialogs have no parameters\n // but still need their UI rendered in the chat.\n if (tool.render) {\n copilotkit.addHookRenderToolCall({\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n });\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, JSON.stringify(extraDeps)]);\n}\n","import type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport type { ComponentType } from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\ntype InferRenderProps<T> = T extends StandardSchemaV1\n ? InferSchemaOutput<T>\n : any;\n\n/**\n * Registers a React component as a frontend tool renderer in chat.\n *\n * This hook is a convenience wrapper around `useFrontendTool` that:\n * - builds a model-facing tool description,\n * - forwards optional schema parameters (any Standard Schema V1 compatible library),\n * - renders your component with tool call parameters.\n *\n * Use this when you want to display a typed visual component for a tool call\n * without manually wiring a full frontend tool object.\n *\n * When `parameters` is provided, render props are inferred from the schema.\n * When omitted, the render component may accept any props.\n *\n * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.\n * @param config - Tool registration config.\n * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).\n *\n * @example\n * ```tsx\n * // Without parameters — render accepts any props\n * useComponent({\n * name: \"showGreeting\",\n * render: ({ message }: { message: string }) => <div>{message}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With parameters — render props inferred from schema\n * useComponent({\n * name: \"showWeatherCard\",\n * parameters: z.object({ city: z.string() }),\n * render: ({ city }) => <div>{city}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * useComponent(\n * {\n * name: \"renderProfile\",\n * parameters: z.object({ userId: z.string() }),\n * render: ProfileCard,\n * agentId: \"support-agent\",\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useComponent<\n TSchema extends StandardSchemaV1<any, Record<string, unknown>> | undefined =\n undefined,\n>(\n config: {\n name: string;\n description?: string;\n parameters?: TSchema;\n render: ComponentType<NoInfer<InferRenderProps<TSchema>>>;\n agentId?: string;\n followUp?: boolean;\n },\n deps?: ReadonlyArray<unknown>,\n): void {\n const prefix = `Use this tool to display the \"${config.name}\" component in the chat. This tool renders a visual UI component for the user.`;\n const fullDescription = config.description\n ? `${prefix}\\n\\n${config.description}`\n : prefix;\n\n useFrontendTool(\n {\n name: config.name,\n description: fullDescription,\n parameters: config.parameters,\n render: ({ args }: { args: unknown }) => {\n const Component = config.render;\n return <Component {...(args as InferRenderProps<TSchema>)} />;\n },\n agentId: config.agentId,\n followUp: config.followUp,\n },\n deps,\n );\n}\n","import { useCopilotKit } from \"../context\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"../types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n // Cleanup that detaches the pending abort listener; cleared whenever the\n // promise settles (via respond() or abort) so the listener can't fire twice\n // or leak after the interaction is done.\n const cleanupAbortRef = useRef<(() => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n cleanupAbortRef.current?.();\n cleanupAbortRef.current = null;\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(\n async (_args: T, context?: { signal?: AbortSignal }) => {\n const signal = context?.signal;\n return new Promise((resolve, reject) => {\n // If the run was already aborted before the handler ran, reject\n // immediately so core records an explicit error tool result instead of\n // silently resolving to an empty string.\n if (signal?.aborted) {\n reject(new Error(\"Human-in-the-loop interaction aborted\"));\n return;\n }\n\n resolvePromiseRef.current = resolve;\n\n if (signal) {\n const onAbort = () => {\n cleanupAbortRef.current = null;\n resolvePromiseRef.current = null;\n reject(new Error(\"Human-in-the-loop interaction aborted\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n cleanupAbortRef.current = () => {\n signal.removeEventListener(\"abort\", onAbort);\n };\n }\n });\n },\n [],\n );\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Build the HITL render props per status. `props` already carries\n // `toolCallId`; we overwrite `name`/`description` with the tool's\n // registration values and add the registration `agentId`, so the HITL\n // render always receives the full prop contract. `respond` is only live\n // while the tool is executing.\n if (props.status === ToolCallStatus.InProgress) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === ToolCallStatus.Executing) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === ToolCallStatus.Complete) {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n agentId: tool.agentId,\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // ToolCallStatus has only the three states handled above, so this point\n // is unreachable and `props` narrows to `never`. The assignment turns a\n // newly-added status into a compile error here — forcing it to get its\n // own branch above — instead of silently rendering without `respond`.\n const exhaustiveCheck: never = props;\n return exhaustiveCheck;\n },\n [tool.render, tool.name, tool.description, tool.agentId, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n","import React, {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { randomUUID } from \"@ag-ui/client\";\nimport type { Interrupt, Message } from \"@ag-ui/client\";\nimport { ɵInterruptState } from \"@copilotkit/core\";\nimport type { ɵPendingInterrupt } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n InterruptResolveFn,\n InterruptCancelFn,\n} from \"../types/interrupt\";\n\nexport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n Interrupt,\n};\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\n/**\n * Normalized pending interrupt. `legacy` carries the custom-event payload;\n * `standard` carries the AG-UI `outcome:\"interrupt\"` interrupts array.\n */\ntype PendingInterrupt = ɵPendingInterrupt;\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/** Derive the legacy-compatible `event` for any pending interrupt. */\nfunction toLegacyEvent(pending: PendingInterrupt): InterruptEvent {\n if (pending.kind === \"legacy\") return pending.event;\n return { name: INTERRUPT_EVENT_NAME, value: pending.interrupts[0] };\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 * Receives both the standard `interrupt`/`interrupts` and the legacy `event`.\n * Call `resolve(payload)` to resume with user input, or `cancel()` to cancel.\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 * Return a sync or async value to expose as `result` in `render`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts this hook handles.\n * Receives the legacy-compatible event (for standard interrupts, `value` is\n * the primary `Interrupt`). Return `false` to ignore.\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. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When false, the hook returns the interrupt element so you can place 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. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts with optional filtering, preprocessing, and resume behavior.\n *\n * Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with\n * `outcome.type === \"interrupt\"`) and the legacy custom-event flow\n * (`on_interrupt`). For standard interrupts, `render` receives `interrupt`\n * (the primary one) and `interrupts` (the full open set); call `resolve(payload)`\n * to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt\n * and, once every open interrupt is addressed, submits a single spec `resume`\n * array via `copilotkit.runAgent`.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element for manual placement.\n *\n * @example\n * ```tsx\n * useInterrupt({\n * render: ({ interrupt, resolve, cancel }) => (\n * <div>\n * <p>{interrupt?.message}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => cancel()}>Cancel</button>\n * </div>\n * ),\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 [pending, setPending] = useState<PendingInterrupt | null>(null);\n const pendingRef = useRef(pending);\n pendingRef.current = pending;\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n const interruptStateRef = useRef(new ɵInterruptState());\n const interruptRunIdsRef = useRef(new Map<string, string>());\n const legacyRunIdRef = useRef<string | undefined>(undefined);\n\n useEffect(() => {\n const interruptState = interruptStateRef.current;\n let localLegacy: InterruptEvent | null = null;\n let localStandard: Interrupt[] | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localLegacy = { name: event.name, value: event.value };\n }\n },\n onRunFinishedEvent: (params) => {\n if (params.outcome === \"interrupt\") {\n const runId = params.input.runId;\n for (const interrupt of params.interrupts) {\n interruptRunIdsRef.current.set(interrupt.id, runId);\n }\n localStandard = params.interrupts;\n }\n },\n onRunStartedEvent: () => {\n localLegacy = null;\n localStandard = null;\n interruptRunIdsRef.current.clear();\n legacyRunIdRef.current = undefined;\n interruptState.clear();\n setPending(null);\n },\n onRunFinalized: (params) => {\n // Standard wins if both somehow appear for one run.\n if (localStandard && localStandard.length > 0) {\n interruptState.setStandard(localStandard);\n setPending(interruptState.pending);\n } else if (localLegacy) {\n legacyRunIdRef.current = params.input.runId;\n interruptState.setLegacy(localLegacy);\n setPending(interruptState.pending);\n }\n localLegacy = null;\n localStandard = null;\n },\n onRunFailed: () => {\n localLegacy = null;\n localStandard = null;\n interruptRunIdsRef.current.clear();\n legacyRunIdRef.current = undefined;\n interruptState.clear();\n setPending(null);\n },\n });\n\n return () => {\n subscription.unsubscribe();\n interruptState.clear();\n };\n }, [agent]);\n\n const resolve: InterruptResolveFn = useCallback(\n async (payload, interruptId) => {\n const current = pendingRef.current;\n if (!current) return;\n\n if (\n current.kind === \"standard\" &&\n current.interrupts.length > 1 &&\n interruptId === undefined\n ) {\n console.warn(\n `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,\n );\n }\n const decision = interruptStateRef.current.resolve(payload, interruptId);\n if (decision.kind === \"legacy-resume\") {\n const runId = legacyRunIdRef.current;\n try {\n return await copilotkit.runAgent({\n agent,\n ...(runId !== undefined ? { runId } : {}),\n forwardedProps: {\n command: {\n resume: decision.payload,\n interruptEvent: decision.interruptValue,\n },\n },\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n setPending(null);\n throw err;\n }\n }\n if (decision.kind === \"expired\") {\n console.error(\n `[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`,\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind !== \"resume\") return;\n const runId = decision.resume\n .map((entry) => interruptRunIdsRef.current.get(entry.interruptId))\n .find((candidate): candidate is string => candidate !== undefined);\n for (const toolResult of decision.toolResults) {\n agent.addMessage({\n id: randomUUID(),\n role: \"tool\",\n toolCallId: toolResult.toolCallId,\n content: toolResult.content,\n } as Message);\n }\n try {\n return await copilotkit.runAgent({\n agent,\n resume: decision.resume,\n ...(runId !== undefined ? { runId } : {}),\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n interruptStateRef.current.clear();\n setPending(null);\n throw err;\n }\n },\n [agent, copilotkit],\n );\n\n const cancel: InterruptCancelFn = useCallback(\n async (interruptId) => {\n const current = pendingRef.current;\n if (!current) return;\n\n if (\n current.kind === \"standard\" &&\n current.interrupts.length > 1 &&\n interruptId === undefined\n ) {\n console.warn(\n `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,\n );\n }\n const decision = interruptStateRef.current.cancel(interruptId);\n if (decision.kind === \"dismiss\") {\n // Legacy interrupts have no cancel semantics; dismiss without resuming.\n console.warn(\n \"[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.\",\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind === \"expired\") {\n console.error(\n `[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`,\n );\n interruptStateRef.current.clear();\n setPending(null);\n return;\n }\n if (decision.kind !== \"resume\") return;\n const runId = decision.resume\n .map((entry) => interruptRunIdsRef.current.get(entry.interruptId))\n .find((candidate): candidate is string => candidate !== undefined);\n for (const toolResult of decision.toolResults) {\n agent.addMessage({\n id: randomUUID(),\n role: \"tool\",\n toolCallId: toolResult.toolCallId,\n content: toolResult.content,\n } as Message);\n }\n try {\n return await copilotkit.runAgent({\n agent,\n resume: decision.resume,\n ...(runId !== undefined ? { runId } : {}),\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing\",\n err,\n );\n interruptStateRef.current.clear();\n setPending(null);\n throw err;\n }\n },\n [agent, copilotkit],\n );\n\n // Stabilize consumer-supplied callbacks behind refs so inline lambdas do not\n // churn the element memo identity or the handler effect.\n const renderRef = useRef(config.render);\n renderRef.current = config.render;\n const enabledRef = useRef(config.enabled);\n enabledRef.current = config.enabled;\n const handlerRef = useRef(config.handler);\n handlerRef.current = config.handler;\n const resolveRef = useRef(resolve);\n resolveRef.current = resolve;\n const cancelRef = useRef(cancel);\n cancelRef.current = cancel;\n\n // Predicate evaluator: a throw is treated as \"disabled\" (false) and logged.\n const isEnabled = (event: InterruptEvent): boolean => {\n const predicate = enabledRef.current;\n if (!predicate) return true;\n try {\n return predicate(event);\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt enabled predicate threw; treating interrupt as disabled:\",\n err,\n );\n return false;\n }\n };\n\n useEffect(() => {\n if (!pending) {\n setHandlerResult(null);\n return;\n }\n const legacyEvent = toLegacyEvent(pending);\n if (!isEnabled(legacyEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = handlerRef.current;\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n let maybePromise: ReturnType<typeof handler>;\n try {\n maybePromise = handler({\n event: legacyEvent,\n interrupt: pending.kind === \"standard\" ? pending.interrupts[0] : null,\n interrupts: pending.kind === \"standard\" ? [...pending.interrupts] : [],\n resolve: resolveRef.current,\n cancel: cancelRef.current,\n });\n } catch (err) {\n console.error(\n \"[CopilotKit] useInterrupt handler threw; result will be null:\",\n err,\n );\n if (!cancelled) setHandlerResult(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch((err) => {\n console.error(\n \"[CopilotKit] useInterrupt handler rejected; result will be null:\",\n err,\n );\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 }, [pending]);\n\n const element = useMemo(() => {\n if (!pending) return null;\n const legacyEvent = toLegacyEvent(pending);\n if (!isEnabled(legacyEvent)) return null;\n\n return renderRef.current({\n event: legacyEvent,\n interrupt: pending.kind === \"standard\" ? pending.interrupts[0] : null,\n interrupts: pending.kind === \"standard\" ? [...pending.interrupts] : [],\n result: handlerResult,\n resolve,\n cancel,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pending, handlerResult, resolve, cancel]);\n\n // Publish to core for in-chat rendering. Publish-only.\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n }, [element, config.renderInChat, copilotkit]);\n\n // Nullify on true unmount only.\n useEffect(() => {\n if (config.renderInChat === false) return;\n return () => {\n copilotkit.setInterruptElement(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { Suggestion } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\n\nexport interface UseSuggestionsOptions {\n agentId?: string;\n}\n\nexport interface UseSuggestionsResult {\n suggestions: Suggestion[];\n reloadSuggestions: () => void;\n clearSuggestions: () => void;\n isLoading: boolean;\n}\n\nexport function useSuggestions({\n agentId,\n}: UseSuggestionsOptions = {}): UseSuggestionsResult {\n const { copilotkit } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const resolvedAgentId = useMemo(\n () => agentId ?? config?.agentId ?? DEFAULT_AGENT_ID,\n [agentId, config?.agentId],\n );\n\n const [suggestions, setSuggestions] = useState<Suggestion[]>(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n return result.suggestions;\n });\n const [isLoading, setIsLoading] = useState(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n return result.isLoading;\n });\n\n useEffect(() => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n setSuggestions(result.suggestions);\n setIsLoading(result.isLoading);\n }, [copilotkit, resolvedAgentId]);\n\n useEffect(() => {\n const subscription = copilotkit.subscribe({\n onSuggestionsChanged: ({ agentId: changedAgentId, suggestions }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setSuggestions(suggestions);\n },\n onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setIsLoading(true);\n },\n onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {\n if (changedAgentId !== resolvedAgentId) {\n return;\n }\n setIsLoading(false);\n },\n onSuggestionsConfigChanged: () => {\n const result = copilotkit.getSuggestions(resolvedAgentId);\n setSuggestions(result.suggestions);\n setIsLoading(result.isLoading);\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [copilotkit, resolvedAgentId]);\n\n const reloadSuggestions = useCallback(() => {\n copilotkit.reloadSuggestions(resolvedAgentId);\n // Loading state is handled by onSuggestionsStartedLoading event\n }, [copilotkit, resolvedAgentId]);\n\n const clearSuggestions = useCallback(() => {\n copilotkit.clearSuggestions(resolvedAgentId);\n // State updates are handled by onSuggestionsChanged event\n }, [copilotkit, resolvedAgentId]);\n\n return {\n suggestions,\n reloadSuggestions,\n clearSuggestions,\n isLoading,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport type {\n DynamicSuggestionsConfig,\n StaticSuggestionsConfig,\n SuggestionsConfig,\n Suggestion,\n} from \"@copilotkit/core\";\n\ntype StaticSuggestionInput = Omit<Suggestion, \"isLoading\"> &\n Partial<Pick<Suggestion, \"isLoading\">>;\n\ntype StaticSuggestionsConfigInput = Omit<\n StaticSuggestionsConfig,\n \"suggestions\"\n> & {\n suggestions: StaticSuggestionInput[];\n};\n\ntype SuggestionsConfigInput =\n | DynamicSuggestionsConfig\n | StaticSuggestionsConfigInput;\n\nexport function useConfigureSuggestions(\n config: SuggestionsConfigInput | null | undefined,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const chatConfig = useCopilotChatConfiguration();\n const extraDeps = deps ?? [];\n\n const resolvedConsumerAgentId = useMemo(\n () => chatConfig?.agentId ?? DEFAULT_AGENT_ID,\n [chatConfig?.agentId],\n );\n\n const rawConsumerAgentId = useMemo(\n () =>\n config ? (config as SuggestionsConfigInput).consumerAgentId : undefined,\n [config],\n );\n\n const normalizationCacheRef = useRef<{\n serialized: string | null;\n config: SuggestionsConfig | null;\n }>({\n serialized: null,\n config: null,\n });\n\n const { normalizedConfig, serializedConfig } = useMemo(() => {\n if (!config) {\n normalizationCacheRef.current = { serialized: null, config: null };\n return { normalizedConfig: null, serializedConfig: null };\n }\n\n if (config.available === \"disabled\") {\n normalizationCacheRef.current = { serialized: null, config: null };\n return { normalizedConfig: null, serializedConfig: null };\n }\n\n let built: SuggestionsConfig;\n if (isDynamicConfig(config)) {\n built = {\n ...config,\n } satisfies DynamicSuggestionsConfig;\n } else {\n const normalizedSuggestions = normalizeStaticSuggestions(\n config.suggestions,\n );\n const baseConfig: StaticSuggestionsConfig = {\n ...config,\n suggestions: normalizedSuggestions,\n };\n built = baseConfig;\n }\n\n const serialized = JSON.stringify(built);\n const cache = normalizationCacheRef.current;\n if (cache.serialized === serialized && cache.config) {\n return { normalizedConfig: cache.config, serializedConfig: serialized };\n }\n\n normalizationCacheRef.current = { serialized, config: built };\n return { normalizedConfig: built, serializedConfig: serialized };\n }, [config, resolvedConsumerAgentId, ...extraDeps]);\n const latestConfigRef = useRef<SuggestionsConfig | null>(null);\n latestConfigRef.current = normalizedConfig;\n const previousSerializedConfigRef = useRef<string | null>(null);\n\n const targetAgentId = useMemo(() => {\n if (!normalizedConfig) {\n return resolvedConsumerAgentId;\n }\n const consumer = (\n normalizedConfig as StaticSuggestionsConfig | DynamicSuggestionsConfig\n ).consumerAgentId;\n if (!consumer || consumer === \"*\") {\n return resolvedConsumerAgentId;\n }\n return consumer;\n }, [normalizedConfig, resolvedConsumerAgentId]);\n\n const isGlobalConfig =\n rawConsumerAgentId === undefined || rawConsumerAgentId === \"*\";\n\n const isDynamicConfigType = useMemo(\n () => !!normalizedConfig && \"instructions\" in normalizedConfig,\n [normalizedConfig],\n );\n\n const requestReload = useCallback(() => {\n if (!normalizedConfig) {\n return;\n }\n\n if (isGlobalConfig) {\n const seen = new Set<string>();\n const agents = Object.values(copilotkit.agents ?? {});\n for (const entry of agents) {\n const agentId = entry.agentId;\n if (!agentId) {\n continue;\n }\n seen.add(agentId);\n if (!entry.isRunning) {\n copilotkit.reloadSuggestions(agentId);\n }\n }\n // Also reload for the chat's resolved consumer agent. The registry can\n // be empty at this point (e.g. runtime info still loading), in which\n // case the loop above wouldn't have fired for the agent the user is\n // actually chatting with — and the welcome screen would render with\n // no suggestions until they navigate away and back.\n if (targetAgentId && !seen.has(targetAgentId)) {\n copilotkit.reloadSuggestions(targetAgentId);\n }\n return;\n }\n\n if (!targetAgentId) {\n return;\n }\n\n copilotkit.reloadSuggestions(targetAgentId);\n }, [copilotkit, isGlobalConfig, normalizedConfig, targetAgentId]);\n\n useEffect(() => {\n if (!serializedConfig || !latestConfigRef.current) {\n return;\n }\n\n const id = copilotkit.addSuggestionsConfig(latestConfigRef.current);\n\n requestReload();\n\n return () => {\n copilotkit.removeSuggestionsConfig(id);\n };\n }, [copilotkit, serializedConfig, requestReload]);\n\n useEffect(() => {\n if (!normalizedConfig) {\n previousSerializedConfigRef.current = null;\n return;\n }\n if (\n serializedConfig &&\n previousSerializedConfigRef.current === serializedConfig\n ) {\n return;\n }\n if (serializedConfig) {\n previousSerializedConfigRef.current = serializedConfig;\n }\n requestReload();\n }, [normalizedConfig, requestReload, serializedConfig]);\n\n useEffect(() => {\n if (!normalizedConfig || extraDeps.length === 0) {\n return;\n }\n requestReload();\n }, [extraDeps.length, normalizedConfig, requestReload, ...extraDeps]);\n\n // When agents arrive after the initial render (runtime info just landed),\n // re-request a reload so dynamic configs that need a real agent can finally\n // generate. Skip for static configs — they don't need an agent and the\n // initial mount reload already handled them. Skip when the target agent\n // is already in the registry — the initial reload already covered it, and\n // re-firing on every subsequent `onAgentsChanged` (e.g. dev-mode hot\n // reloads, sibling chat configs mounting) would stack overlapping\n // generations.\n useEffect(() => {\n if (!normalizedConfig || !isDynamicConfigType) return;\n if (!targetAgentId) return;\n\n const initiallyPresent = !!copilotkit.getAgent(targetAgentId);\n if (initiallyPresent) return;\n\n const subscription = copilotkit.subscribe({\n onAgentsChanged: () => {\n if (copilotkit.getAgent(targetAgentId)) {\n requestReload();\n subscription.unsubscribe();\n }\n },\n });\n return () => {\n subscription.unsubscribe();\n };\n }, [\n copilotkit,\n normalizedConfig,\n isDynamicConfigType,\n targetAgentId,\n requestReload,\n ]);\n}\n\nfunction isDynamicConfig(\n config: SuggestionsConfigInput,\n): config is DynamicSuggestionsConfig {\n return \"instructions\" in config;\n}\n\nfunction normalizeStaticSuggestions(\n suggestions: StaticSuggestionInput[],\n): Suggestion[] {\n return suggestions.map((suggestion) => ({\n ...suggestion,\n isLoading: suggestion.isLoading ?? false,\n }));\n}\n","import { useCopilotKit } from \"../context\";\nimport { useLayoutEffect, useMemo } from \"react\";\n\n/**\n * Represents any value that can be serialized to JSON.\n */\nexport type JsonSerializable =\n | string\n | number\n | boolean\n | null\n | JsonSerializable[]\n | { [key: string]: JsonSerializable };\n\n/**\n * Context configuration for useAgentContext.\n * Accepts any JSON-serializable value which will be converted to a string.\n */\nexport interface AgentContextInput {\n /** A human-readable description of what this context represents */\n description: string;\n /** The context value - will be converted to a JSON string if not already a string */\n value: JsonSerializable;\n}\n\nexport function useAgentContext(context: AgentContextInput) {\n const { description, value } = context;\n const { copilotkit } = useCopilotKit();\n\n const stringValue = useMemo(() => {\n if (typeof value === \"string\") {\n return value;\n }\n return JSON.stringify(value);\n }, [value]);\n\n useLayoutEffect(() => {\n if (!copilotkit) return;\n\n const id = copilotkit.addContext({ description, value: stringValue });\n return () => {\n copilotkit.removeContext(id);\n };\n }, [description, stringValue, copilotkit]);\n}\n","import { useCopilotKit } from \"../context\";\nimport {\n CopilotKitCoreRuntimeConnectionStatus,\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectFetchMoreError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n ɵselectIsMutating,\n} from \"@copilotkit/core\";\nimport type { ɵThreadRuntimeContext, ɵThreadStore } from \"@copilotkit/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread {\n id: string;\n agentId: string;\n name: string | null;\n archived: boolean;\n createdAt: string;\n updatedAt: string;\n /**\n * ISO-8601 timestamp of the most recent agent run on this thread. Absent\n * when the thread has never been run. Prefer this over `updatedAt` for\n * user-facing \"last activity\" displays — it is not bumped by metadata-only\n * actions like rename or archive.\n */\n lastRunAt?: string;\n}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Thread operations are scoped to the runtime-authenticated user and the\n * provided agent on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n /**\n * When `false`, the hook stays inert: no runtime context is dispatched, so\n * NO thread-list fetch or realtime subscription is issued. Used by gated\n * surfaces (e.g. an unlicensed `<CopilotThreadsDrawer>`) that must not touch the\n * network until the gate opens. Defaults to `true`.\n *\n * Flipping `enabled` back to `true` resumes normal fetching on the next\n * effect run; mutations are likewise short-circuited while disabled.\n */\n enabled?: boolean;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n *\n * This channel folds together developer/config errors (missing runtime URL,\n * runtime without thread endpoints) and genuine list-load/mutation failures.\n * End-user surfaces that must not leak config errors should prefer\n * {@link listError}, which excludes the config/runtime-setup errors.\n */\n error: Error | null;\n /**\n * The most recent genuine list-load or mutation error from the platform, or\n * `null`. Unlike {@link error}, this EXCLUDES developer/config errors (a\n * missing runtime URL, or a runtime that does not advertise thread\n * endpoints), so an end-user surface can render it directly without leaking\n * a developer-facing configuration message into the UI.\n */\n listError: Error | null;\n /**\n * The error from the most recent FAILED next-page (fetch-more) load, or\n * `null`. Tracked separately from {@link listError} so a paginated-load\n * failure surfaces an inline \"couldn't load more\" affordance while the\n * already-loaded list stays visible. Cleared when a fetch-more is retried or\n * succeeds.\n */\n fetchMoreError: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchMoreThreads}. Only meaningful when `limit` is set.\n */\n hasMoreThreads: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingMoreThreads: boolean;\n /**\n * `true` while at least one thread mutation (rename, archive, unarchive,\n * delete) is awaiting a server response. Mutations apply optimistically, so\n * this is primarily useful for disabling controls or showing a subtle\n * in-flight indicator.\n */\n isMutating: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasMoreThreads} is\n * `false` or a fetch is already in progress.\n */\n fetchMoreThreads: () => void;\n /**\n * Re-fetch the thread list from the platform without clearing the current\n * list. Backs the drawer's error-state Retry and the Active/All filter\n * refetch. No-op until the runtime is connected.\n */\n refetchThreads: () => void;\n /**\n * Reset to a fresh, non-explicit client-side thread so the welcome screen\n * shows. Lazy creation: no row appears in {@link threads} until the new\n * thread's first run persists server-side.\n */\n startNewThread: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Restore a previously archived thread on the platform.\n * The thread re-appears in default (non-archived) list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n unarchiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n // getServerSnapshot: without this third argument React throws\n // \"Missing getServerSnapshot\" during SSR/prerender (e.g. Next.js). The\n // store has no client data while prerendering, so we project from its\n // stable server state.\n () => selector(store.getServerState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the runtime-authenticated user\n * and the given `agentId`. When the Intelligence platform exposes a WebSocket\n * URL, it also opens a realtime subscription so the `threads` array stays\n * current without polling — thread creates, renames, archives, and deletes\n * from any client are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,\n * `deleteThread`) return promises that resolve once the platform confirms the\n * operation and reject with an `Error` on failure.\n *\n * @param input - Agent identifier and optional list controls.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkit/react-core\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n agentId,\n includeArchived,\n limit,\n enabled = true,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const coreThreads = useThreadStoreSelector(store, ɵselectThreads);\n const threads: Thread[] = useMemo(\n () =>\n coreThreads.map(\n ({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({\n id,\n agentId,\n name,\n archived,\n createdAt,\n updatedAt,\n ...(lastRunAt !== undefined ? { lastRunAt } : {}),\n }),\n ),\n [coreThreads],\n );\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const fetchMoreError = useThreadStoreSelector(store, ɵselectFetchMoreError);\n const hasMoreThreads = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingMoreThreads = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const isMutating = useThreadStoreSelector(store, ɵselectIsMutating);\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeStatus = copilotkit.runtimeConnectionStatus;\n const threadListEndpointSupported =\n copilotkit.threadEndpoints?.list !== false;\n const threadMutationsSupported =\n copilotkit.threadEndpoints?.mutations !== false;\n const threadEndpointsUnavailable =\n !!copilotkit.runtimeUrl &&\n runtimeStatus === CopilotKitCoreRuntimeConnectionStatus.Connected &&\n !threadListEndpointSupported;\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const threadEndpointsError = useMemo(() => {\n if (!threadEndpointsUnavailable) {\n return null;\n }\n\n return new Error(\n \"Thread endpoints are not available on this CopilotKit runtime\",\n );\n }, [threadEndpointsUnavailable]);\n const threadMutationsError = useMemo(() => {\n if (threadMutationsSupported) {\n return null;\n }\n\n return new Error(\n \"Thread mutations are not available on this CopilotKit runtime\",\n );\n }, [threadMutationsSupported]);\n\n // Tracks whether we've dispatched the first real context to the store.\n // The store itself starts with `isLoading: false`, so before we dispatch\n // consumers would otherwise see an empty, non-loading state (empty-list\n // flash). While runtimeUrl is set and we haven't dispatched yet, we\n // synthesize `isLoading: true` so the UI keeps its loading indicator until\n // the first fetch is in flight (at which point the store's own\n // isLoading takes over).\n const [hasDispatchedContext, setHasDispatchedContext] = useState(false);\n const preConnectLoading =\n enabled &&\n !!copilotkit.runtimeUrl &&\n !threadEndpointsUnavailable &&\n !hasDispatchedContext;\n\n // `startNewThread` resets to a clean welcome surface, so it should clear any\n // lingering error banner — including the config/runtime-setup errors that\n // otherwise outrank the store's own (already-cleared) error. We cannot clear\n // a derived `runtimeError`/`threadEndpointsError` directly (they reflect\n // current config), so we suppress them with a dismissal flag that resets\n // whenever the underlying config-error identity changes (a genuine new config\n // problem re-surfaces).\n const [configErrorDismissed, setConfigErrorDismissed] = useState(false);\n useEffect(() => {\n setConfigErrorDismissed(false);\n }, [runtimeError, threadEndpointsError]);\n\n const activeRuntimeError = configErrorDismissed ? null : runtimeError;\n const activeThreadEndpointsError = configErrorDismissed\n ? null\n : threadEndpointsError;\n\n const isLoading =\n activeRuntimeError || activeThreadEndpointsError\n ? false\n : preConnectLoading || storeIsLoading;\n const error = activeRuntimeError ?? activeThreadEndpointsError ?? storeError;\n // End-user-facing list/mutation error only: developer/config errors are\n // excluded so a surface like <CopilotThreadsDrawer> does not show \"Runtime URL is\n // not configured\" to an end user.\n const listError = storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n // Defer setting the context until the runtime reports Connected. Before\n // `/info` resolves we don't know `intelligence.wsUrl`, so dispatching the\n // context early would issue a list fetch with `wsUrl: undefined`, then a\n // second list fetch (and a `/threads/subscribe`) once the flag lands.\n // Waiting lets the hook issue just one `/threads?…` + one `/threads/subscribe`.\n //\n // When `runtimeUrl` is absent we dispatch `null` to clear the store. For\n // transient states (Disconnected/Connecting/Error with a URL still set) we\n // leave the previously-dispatched context in place — any in-flight\n // realtime subscription or cached thread list stays usable while the\n // runtime recovers, and we don't re-trigger a fetch storm on transitions.\n useEffect(() => {\n // A disabled (e.g. unlicensed) drawer must not claim the agentId slot. The\n // registry is single-slot/last-writer-wins, so registering an inert store\n // would evict — and on unmount tear down — a co-mounted live store for the\n // same agent. Staying unregistered while disabled leaves the live store's\n // registration intact.\n if (!enabled) return;\n copilotkit.registerThreadStore(agentId, store);\n return () => {\n copilotkit.unregisterThreadStore(agentId);\n };\n }, [copilotkit, agentId, store, enabled]);\n\n useEffect(() => {\n // Disabled: stay inert. Clear any previously-dispatched context so an\n // in-flight subscription is torn down and no further fetch is issued.\n if (!enabled) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n if (!copilotkit.runtimeUrl) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n // Wait for /info to land so we can include `wsUrl` in the initial\n // context and avoid a redundant second list fetch.\n if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) {\n return;\n }\n\n if (!threadListEndpointSupported) {\n store.setContext(null);\n setHasDispatchedContext(false);\n return;\n }\n\n const context: ɵThreadRuntimeContext = {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n agentId,\n includeArchived,\n limit,\n };\n\n store.setContext(context);\n setHasDispatchedContext(true);\n }, [\n store,\n enabled,\n copilotkit.runtimeUrl,\n runtimeStatus,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n threadListEndpointSupported,\n agentId,\n includeArchived,\n limit,\n ]);\n\n const guardMutation = useCallback(\n <TArgs extends unknown[]>(\n mutation: (...args: TArgs) => Promise<void>,\n ): ((...args: TArgs) => Promise<void>) => {\n return (...args: TArgs) => {\n if (threadMutationsError) {\n return Promise.reject(threadMutationsError);\n }\n return mutation(...args);\n };\n },\n [threadMutationsError],\n );\n\n const renameThread = useMemo(\n () =>\n guardMutation((threadId: string, name: string) =>\n store.renameThread(threadId, name),\n ),\n [store, guardMutation],\n );\n\n const archiveThread = useMemo(\n () => guardMutation((threadId: string) => store.archiveThread(threadId)),\n [store, guardMutation],\n );\n\n const unarchiveThread = useMemo(\n () => guardMutation((threadId: string) => store.unarchiveThread(threadId)),\n [store, guardMutation],\n );\n\n const deleteThread = useMemo(\n () => guardMutation((threadId: string) => store.deleteThread(threadId)),\n [store, guardMutation],\n );\n\n const fetchMoreThreads = useCallback(() => store.fetchNextPage(), [store]);\n const refetchThreads = useCallback(() => store.refetchThreads(), [store]);\n const startNewThread = useCallback(() => {\n // The store's `newThreadStarted` reducer clears its own error; also dismiss\n // the derived config/runtime-setup errors so the welcome surface renders\n // with no stale error banner.\n setConfigErrorDismissed(true);\n store.startNewThread();\n }, [store]);\n\n return {\n threads,\n isLoading,\n error,\n listError,\n fetchMoreError,\n hasMoreThreads,\n isFetchingMoreThreads,\n isMutating,\n fetchMoreThreads,\n refetchThreads,\n startNewThread,\n renameThread,\n archiveThread,\n unarchiveThread,\n deleteThread,\n };\n}\n","import React from \"react\";\nimport { z } from \"zod\";\nimport type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport { ReactToolCallRenderer } from \"./react-tool-call-renderer\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\n\n/**\n * Helper to define a type-safe tool call renderer entry.\n * - Accepts a single object whose keys match ReactToolCallRenderer's fields: { name, args, render, agentId? }.\n * - Derives `args` type from the provided schema (any Standard Schema V1 compatible library).\n * - Ensures the render function param type exactly matches ReactToolCallRenderer<T>[\"render\"]'s param.\n * - For wildcard tools (name: \"*\"), args is optional and defaults to z.any()\n */\ntype RenderProps<T> =\n | {\n name: string;\n toolCallId: string;\n args: Partial<T>;\n status: ToolCallStatus.InProgress;\n result: undefined;\n }\n | {\n name: string;\n toolCallId: string;\n args: T;\n status: ToolCallStatus.Executing;\n result: undefined;\n }\n | {\n name: string;\n toolCallId: string;\n args: T;\n status: ToolCallStatus.Complete;\n result: string;\n };\n\n// Overload for wildcard tools without args\nexport function defineToolCallRenderer(def: {\n name: \"*\";\n render: (props: RenderProps<any>) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<any>;\n\n// Overload for regular tools with args\nexport function defineToolCallRenderer<S extends StandardSchemaV1>(def: {\n name: string;\n args: S;\n render: (props: RenderProps<InferSchemaOutput<S>>) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<InferSchemaOutput<S>>;\n\n// Implementation\nexport function defineToolCallRenderer<S extends StandardSchemaV1>(def: {\n name: string;\n args?: S;\n render: (props: any) => React.ReactElement;\n agentId?: string;\n}): ReactToolCallRenderer<any> {\n // For wildcard tools, default to z.any() if no args provided\n const argsSchema = def.name === \"*\" && !def.args ? z.any() : def.args;\n\n return {\n name: def.name,\n args: argsSchema,\n render: def.render as React.ComponentType<any>,\n ...(def.agentId ? { agentId: def.agentId } : {}),\n };\n}\n","import { useEffect } from \"react\";\nimport type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n toolCallId: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n // Branch per status so the discriminated union stays correlated\n // when `args` is re-exposed as `parameters`.\n render: (props) => {\n if (props.status === ToolCallStatus.InProgress) {\n return config.render({ ...props, parameters: props.args });\n }\n if (props.status === ToolCallStatus.Executing) {\n return config.render({ ...props, parameters: props.args });\n }\n return config.render({ ...props, parameters: props.args });\n },\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n copilotkit.addHookRenderToolCall(renderer);\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, JSON.stringify(extraDeps)]);\n}\n","import React, { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport type { ToolCall, ToolMessage } from \"@ag-ui/core\";\nimport { ToolCallStatus } from \"@copilotkit/core\";\nimport { useCopilotKit } from \"../context\";\nimport { useCopilotChatConfiguration } from \"../providers/CopilotChatConfigurationProvider\";\nimport { DEFAULT_AGENT_ID } from \"@copilotkit/shared\";\nimport { partialJSONParse } from \"@copilotkit/shared\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nexport interface UseRenderToolCallProps {\n toolCall: ToolCall;\n toolMessage?: ToolMessage;\n}\n\n/**\n * Props for the memoized ToolCallRenderer component\n */\ninterface ToolCallRendererProps {\n toolCall: ToolCall;\n toolMessage?: ToolMessage;\n RenderComponent: ReactToolCallRenderer<unknown>[\"render\"];\n isExecuting: boolean;\n}\n\n/**\n * Memoized component that renders a single tool call.\n * This prevents unnecessary re-renders when parent components update\n * but the tool call data hasn't changed.\n */\nconst ToolCallRenderer = React.memo(\n function ToolCallRenderer({\n toolCall,\n toolMessage,\n RenderComponent,\n isExecuting,\n }: ToolCallRendererProps) {\n // Memoize args based on the arguments string to maintain stable reference\n const args = useMemo(\n () => partialJSONParse(toolCall.function.arguments),\n [toolCall.function.arguments],\n );\n\n const toolName = toolCall.function.name;\n\n // Render based on status to preserve discriminated union type inference\n if (toolMessage) {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.Complete}\n result={toolMessage.content}\n />\n );\n } else if (isExecuting) {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.Executing}\n result={undefined}\n />\n );\n } else {\n return (\n <RenderComponent\n name={toolName}\n toolCallId={toolCall.id}\n args={args}\n status={ToolCallStatus.InProgress}\n result={undefined}\n />\n );\n }\n },\n // Custom comparison function to prevent re-renders when tool call data hasn't changed\n (prevProps, nextProps) => {\n // Compare tool call identity and content\n if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;\n if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name)\n return false;\n if (\n prevProps.toolCall.function.arguments !==\n nextProps.toolCall.function.arguments\n )\n return false;\n\n // Compare tool message (result)\n const prevResult = prevProps.toolMessage?.content;\n const nextResult = nextProps.toolMessage?.content;\n if (prevResult !== nextResult) return false;\n\n // Compare executing state\n if (prevProps.isExecuting !== nextProps.isExecuting) return false;\n\n // Compare render component reference\n if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;\n\n return true;\n },\n);\n\n/**\n * Hook that returns a function to render tool calls based on the render functions\n * defined in CopilotKitProvider.\n *\n * @returns A function that takes a tool call and optional tool message and returns the rendered component\n */\nexport function useRenderToolCall() {\n const { copilotkit, executingToolCallIds } = useCopilotKit();\n const config = useCopilotChatConfiguration();\n const agentId = config?.agentId ?? DEFAULT_AGENT_ID;\n\n // Subscribe to render tool calls changes using useSyncExternalStore\n // This ensures we always have the latest value, even if subscriptions run in any order\n const renderToolCalls = useSyncExternalStore(\n (callback) => {\n return copilotkit.subscribe({\n onRenderToolCallsChanged: callback,\n }).unsubscribe;\n },\n () => copilotkit.renderToolCalls,\n () => copilotkit.renderToolCalls,\n );\n\n // Note: executingToolCallIds is now provided by CopilotKitProvider context.\n // This is critical for HITL reconnection: when connecting to a thread with\n // pending tool calls, the onToolExecutionStart event fires before child components\n // mount. By tracking at the provider level, the executing state is already\n // available when this hook first runs.\n\n const renderToolCall = useCallback(\n ({\n toolCall,\n toolMessage,\n }: UseRenderToolCallProps): React.ReactElement | null => {\n // Find the render config for this tool call by name\n // For rendering, we show all tool calls regardless of agentId\n // The agentId scoping only affects handler execution (in core)\n // Priority order:\n // 1. Exact match by name (prefer agent-specific if multiple exist)\n // 2. Wildcard (*) renderer\n const exactMatches = renderToolCalls.filter(\n (rc) => rc.name === toolCall.function.name,\n );\n\n // If multiple renderers with same name exist, prefer the one matching our agentId\n const renderConfig =\n exactMatches.find((rc) => rc.agentId === agentId) ||\n exactMatches.find((rc) => !rc.agentId) ||\n exactMatches[0] ||\n renderToolCalls.find((rc) => rc.name === \"*\");\n\n // No per-tool or wildcard renderer registered → render nothing.\n // Showing an unhandled tool call is opt-in: register a named/wildcard\n // renderer via useRenderTool, or call useDefaultRenderTool() for the\n // built-in card. Auto-painting a default card here would leak internal\n // tool names plus raw args/result JSON into every app's chat in\n // production, so the card must be explicitly enabled.\n if (!renderConfig) {\n return null;\n }\n\n const RenderComponent =\n renderConfig.render as ReactToolCallRenderer<unknown>[\"render\"];\n const isExecuting = executingToolCallIds.has(toolCall.id);\n\n // Use the memoized ToolCallRenderer component to prevent unnecessary re-renders\n return (\n <ToolCallRenderer\n key={toolCall.id}\n toolCall={toolCall}\n toolMessage={toolMessage}\n RenderComponent={RenderComponent}\n isExecuting={isExecuting}\n />\n );\n },\n [renderToolCalls, executingToolCallIds, agentId],\n );\n\n return renderToolCall;\n}\n","import type { AgentCapabilities } from \"@ag-ui/core\";\nimport { useAgent } from \"./use-agent\";\n\n/**\n * Returns the capabilities declared by the given agent (or the agent resolved\n * from the surrounding chat configuration, falling back to the default agent).\n * Capabilities are populated from the runtime `/info` response at connection\n * time. The hook reads them synchronously from the agent instance — there is\n * no separate loading state, but the value will be `undefined` until the\n * runtime handshake completes.\n *\n * @param agentId - Optional agent ID. If omitted, inherits the surrounding\n * chat configuration's agent, falling back to the default agent.\n * @returns The agent's capabilities, or `undefined` if the agent doesn't\n * declare capabilities.\n */\nexport function useCapabilities(\n agentId?: string,\n): AgentCapabilities | undefined {\n const { agent } = useAgent({ agentId });\n\n if (agent && \"capabilities\" in agent) {\n return (agent as { capabilities?: AgentCapabilities }).capabilities;\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|