@copilotkit/react-core
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
1 lines • 143 kB
Source Map (JSON)
{"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 assistantMessageToolbarInspectorLabel: \"View in Inspector\",\n assistantMessageToolbarInspectorLocalOnlyLabel: \"Local Only\",\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":";;;;;;;;;;;;AAWA,SAAgB,aACd,MACA,MACS;CACT,MAAM,QAAQ,OAAO,KAAK,KAAK;CAC/B,MAAM,QAAQ,OAAO,KAAK,KAAK;AAE/B,KAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,MAAK,MAAM,OAAO,MAChB,KAAI,KAAK,SAAS,KAAK,KAAM,QAAO;AAGtC,QAAO;;;;;;AAOT,SAAS,cAAc,KAA8C;AACnE,QACE,QAAQ,QACR,OAAO,QAAQ,YACf,OAAO,UAAU,SAAS,KAAK,IAAI,KAAK;;;;;;;;;;;;;;;AAiB5C,SAAgB,oBAAuB,OAAa;CAClD,MAAM,MAAM,OAAO,MAAM;AAGzB,KAAI,IAAI,YAAY,MAAO,QAAO,IAAI;AAGtC,KAAI,cAAc,IAAI,QAAQ,IAAI,cAAc,MAAM,EACpD;MAAI,aAAa,IAAI,SAAS,MAAM,CAAE,QAAO,IAAI;;AAInD,KAAI,UAAU;AACd,QAAO,IAAI;;;;;ACjDb,MAAa,2BAA2B;CACtC,sBAAsB;CACtB,4CAA4C;CAC5C,6CAA6C;CAC7C,6CAA6C;CAC7C,gCAAgC;CAChC,kCAAkC;CAClC,sCAAsC;CACtC,4CAA4C;CAC5C,yCAAyC;CACzC,uCAAuC;CACvC,gDAAgD;CAChD,sCAAsC;CACtC,wCAAwC;CACxC,uCAAuC;CACvC,wCAAwC;CACxC,oCAAoC;CACpC,oCAAoC;CACpC,oBACE;CACF,qBAAqB;CACrB,sBAAsB;CACtB,kBAAkB;CAClB,oBAAoB;CACrB;;;;;;;AAUD,MAAM,sBAAsB;;;;;;;;;AAU5B,SAAS,mBAA4B;AACnC,KACE,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,WAE7B,QAAO;AAET,QAAO,OAAO,WAAW,eAAe,oBAAoB,KAAK,CAAC;;AAsFpE,MAAM,2BACJ,cAAoD,KAAK;AAkB3D,MAAa,oCAER,EACH,UACA,QACA,SACA,UACA,qBACA,yBACI;CACJ,MAAM,eAAe,WAAW,yBAAyB;CAMzD,MAAM,eAAe,oBAAoB,OAAO;CAChD,MAAM,eAAkC,eAC/B;EACL,GAAG;EACH,GAAG,cAAc;EACjB,GAAG;EACJ,GACD,CAAC,cAAc,cAAc,OAAO,CACrC;CAED,MAAM,kBAAkB,WAAW,cAAc,WAAW;CAS5D,MAAM,8BACJ,aAAa,UAAa,wBAAwB;CAMpD,MAAM,uBAAuB;CAO7B,MAAM,CAAC,sBAAsB,2BAA2B,SAG9C,KAAK;CAEf,MAAM,mBAAmB,cAAc;AAErC,MAAI,4BACF,QAAO;AAKT,MAAI,qBACF,QAAO,qBAAqB;AAE9B,MAAI,cAAc,SAChB,QAAO,aAAa;AAEtB,MAAI,SACF,QAAO;AAET,SAAO,YAAY;IAClB;EACD;EACA;EACA,cAAc;EACd;EACD,CAAC;CAUF,MAAM,+BAHyB,8BAC3B,OACC,sBAAsB,YAAY,uBAAuB,UAElC,CAAC,CAAC,cAAc;CAI5C,MAAM,CAAC,mBAAmB,wBACxB,SAH0B,sBAAsB,KAGV;CAExC,MAAM,qBAAqB,uBAAuB;CAOlD,MAAM,aAAa,aAChB,SAAkB;AACjB,uBAAqB,KAAK;AAC1B,gBAAc,aAAa,KAAK;IAGlC,CAAC,cAAc,aAAa,CAC7B;CAOD,MAAM,YAAY,OAAO,MAAM;AAC/B,iBAAgB;AACd,MAAI,CAAC,mBAAoB;AACzB,MAAI,CAAC,UAAU,SAAS;AACtB,aAAU,UAAU;AACpB;;AAEF,MAAI,cAAc,gBAAgB,OAAW;AAC7C,uBAAqB,aAAa,YAAY;IAC7C,CAAC,cAAc,aAAa,mBAAmB,CAAC;CAEnD,MAAM,sBAAsB,qBACxB,oBACC,cAAc,eAAe;CAClC,MAAM,uBAAuB,qBACzB,aACC,cAAc,gBAAgB;CAOnC,MAAM,CAAC,eAAe,oBAAoB,SAAkB,MAAM;CAClE,MAAM,CAAC,gBAAgB,qBAAqB,SAAiB,EAAE;CAK/D,MAAM,gBAAgB,aAAsC,GAAG;AAK/D,eAAc,UAAU;CAKxB,MAAM,4BAA4B,OAAuC,EAAE,CAAC;CAE5E,MAAM,yBAAyB,aAC5B,eAAwC;AACvC,4BAA0B,QAAQ,KAAK,WAAW;AAClD,eAAa;AACX,6BAA0B,UACxB,0BAA0B,QAAQ,QAC/B,UAAU,UAAU,WACtB;;IAGP,EAAE,CACH;CAED,MAAM,mBAAmB,aAAa,SAAkB;AACtD,mBAAiB,KAAK;AAItB,MAAI,QAAQ,kBAAkB,EAAE;GAC9B,MAAM,aAAa,0BAA0B;AAK7C,IAHE,WAAW,SAAS,IAChB,WAAW,WAAW,SAAS,KAC/B,cAAc,SACT,MAAM;;IAElB,EAAE,CAAC;CAEN,MAAM,oBAAoB,kBAAkB;AAC1C,qBAAmB,UAAU,QAAQ,EAAE;AACvC,eAAa;AACX,sBAAmB,UAAU,KAAK,IAAI,GAAG,QAAQ,EAAE,CAAC;;IAErD,EAAE,CAAC;CAEN,MAAM,qBAAqB,eACvB,aAAa,aACb;CACJ,MAAM,wBAAwB,eAC1B,aAAa,gBACb;CACJ,MAAM,2BAA2B,eAC7B,aAAa,mBACb,iBAAiB;CACrB,MAAM,yBAAyB,eAC3B,aAAa,iBACb;CACJ,MAAM,8BAA8B,eAChC,aAAa,uBACb;AAMJ,iBAAgB;AACd,MAAI,CAAC,mBAAoB;AACzB,SAAO,4BAA4B,qBAAqB;IACvD;EAAC;EAAoB;EAA6B;EAAqB,CAAC;CAe3E,MAAM,0BAA0B,OAAO,qBAAqB;AAC5D,yBAAwB,UAAU;CAElC,MAAM,uBAAuB,aAC1B,IAAY,YAAqC;AAChD,0BAAwB;GACtB,UAAU;GACV,UAAU,SAAS,YAAY;GAChC,CAAC;IAEJ,EAAE,CACH;CAED,MAAM,oBAAoB,kBAAkB;AAC1C,0BAAwB;GAAE,UAAU,YAAY;GAAE,UAAU;GAAO,CAAC;IACnE,EAAE,CAAC;CAKN,MAAM,0BAA0B,cAAc;CAC9C,MAAM,uBAAuB,cAAc;CAE3C,MAAM,4BAA4B,aAC/B,IAAY,YAAqC;AAChD,MAAI,wBAAwB,SAAS;AACnC,WAAQ,KACN,iIAED;AACD;;AAEF,MAAI,yBAAyB;AAC3B,2BAAwB,IAAI,QAAQ;AACpC;;AAEF,uBAAqB,IAAI,QAAQ;IAEnC,CAAC,yBAAyB,qBAAqB,CAChD;CAED,MAAM,yBAAyB,kBAAkB;AAC/C,MAAI,wBAAwB,SAAS;AACnC,WAAQ,KACN,8HAED;AACD;;AAEF,MAAI,sBAAsB;AACxB,yBAAsB;AACtB;;AAEF,qBAAmB;IAClB,CAAC,sBAAsB,kBAAkB,CAAC;CAK7C,MAAM,kCAAkC,aACrC,SAAkB;AACjB,MAAI,QAAQ,kBAAkB,CAC5B,uBAAsB,MAAM;AAE9B,uBAAqB,KAAK;IAE5B,CAAC,sBAAsB,sBAAsB,CAC9C;CAED,MAAM,qBAAoD,eACjD;EACL,QAAQ;EACR,SAAS;EACT,UAAU;EACV,qBAAqB;EACrB,aAAa;EACb,cAAc;EACd,YAAY;EACZ,eAAe;EACf,kBAAkB;EAClB,gBAAgB;EAChB,sBAAsB;EACtB,mBAAmB;EACnB,gBAAgB;EACjB,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QACE,oBAAC,yBAAyB;EAAS,OAAO;EACvC;GACiC;;AAKxC,MAAa,oCACiC;AAE1C,QADsB,WAAW,yBAAyB;;;;;ACtf9D,IAAY,0DAAL;AACL;AACA;AACA;;;AAGF,MAAM,cAAgC;CACpC,eAAe;CACf,eAAe;CACf,eAAe;CAChB;AAuHD,SAAgB,SAAS,EACvB,SACA,UACA,gBACA,SACA,eACiB,EAAE,EAAE;AAYrB,KAAI,YAAY,QAAQ,kBAAkB,KACxC,OAAM,IAAI,MACR,6UAIoD,WAAW,UAAU,iBAC1E;AAQH,KAAI,kBAAkB,QAAQ,YAAY,KACxC,OAAM,IAAI,MACR,6RAGuC,WAAW,SAAS,sBAAsB,eAAe,0EACnC,eAAe,OAC7E;AAQH,KAAI,kBAAkB,QAAQ,WAAW,KACvC,OAAM,IAAI,MACR,wKAEM,iBAAiB,oKAE6B,eAAe,iBACpE;CAQH,MAAM,aAAa,6BAA6B;CAChD,MAAM,kBAAkB,WAAW,YAAY,WAAW;CAE1D,MAAM,EAAE,eAAeA,iBAAe;CAItC,MAAM,qBAAqB,WAAW;CAEtC,MAAM,GAAG,eAAe,YAAY,MAAM,IAAI,GAAG,EAAE;CAEnD,MAAM,cAAc,cACZ,WAAW,aACjB,CAAC,KAAK,UAAU,QAAQ,CAAC,CAC1B;CAKD,MAAM,wBAAwB,uBAC5B,IAAI,KAAK,CACV;CASD,MAAM,CAAC,sBAAsB,2BAC3B,SAA+B,KAAK;AACtC,iBAAgB;AACd,MAAI,kBAAkB,MAAM;AAC1B,2BAAwB,KAAK;AAC7B;;EAEF,MAAM,EAAE,OAAO,OAAO,eAAe,WAAW,qBAAqB;GACnE,SAAS;GACT;GACD,CAAC;AACF,wBAAsB,QAAQ,OAAO,gBAAgB;AACrD,0BAAwB,MAAM;AAC9B,eAAa;AACX,eAAY;AACZ,2BAAwB,KAAK;;IAE9B;EAAC;EAAY;EAAiB;EAAe,CAAC;CAEjD,MAAM,EAAE,OAAO,YAAY,cAGlB;AAMP,MAAI,kBAAkB,MAAM;AAC1B,OAAI,sBAAsB;AACxB,0BAAsB,QAAQ,OAAO,gBAAgB;AACrD,WAAO;KAAE,OAAO;KAAsB,SAAS;KAAM;;GAEvD,MAAM,SAAS,sBAAsB,QAAQ,IAAI,gBAAgB;AACjE,OAAI,QAAQ;AACV,eAAW,oBAAoB,OAAO;AACtC,WAAO;KAAE,OAAO;KAAQ,SAAS;KAAO;;GAE1C,MAAM,cAAc,IAAI,2BAA2B;IACjD,YAAY,WAAW;IACvB,SAAS;IACT;IACA,WAAW,WAAW;IACtB,aAAa;IACd,CAAC;AACF,cAAW,oBAAoB,YAAY;AAC3C,yBAAsB,QAAQ,IAAI,iBAAiB,YAAY;AAC/D,UAAO;IAAE,OAAO;IAAa,SAAS;IAAO;;EAG/C,MAAM,WAAW,WAAW,SAAS,gBAAgB;AACrD,MAAI,UAAU;AAEZ,yBAAsB,QAAQ,OAAO,gBAAgB;AACrD,UAAO;IAAE,OAAO;IAAU,SAAS;IAAM;;EAG3C,MAAM,sBAAsB,WAAW,eAAe;EACtD,MAAM,SAAS,WAAW;AAG1B,MACE,wBACC,WAAW,sCAAsC,gBAChD,WAAW,sCAAsC,aACnD;GAEA,MAAM,SAAS,sBAAsB,QAAQ,IAAI,gBAAgB;AACjE,OAAI,OACF,QAAO;IAAE,OAAO;IAAQ,SAAS;IAAO;GAG1C,MAAM,cAAc,IAAI,2BAA2B;IACjD,YAAY,WAAW;IACvB,SAAS;IACT,WAAW,WAAW;IACtB,aAAa,WAAW;IACxB,aAAa;IACd,CAAC;AAEF,cAAW,oBAAoB,YAAY;AAC3C,yBAAsB,QAAQ,IAAI,iBAAiB,YAAY;AAC/D,UAAO;IAAE,OAAO;IAAa,SAAS;IAAO;;AAQ/C,MACE,uBACA,WAAW,sCAAsC,OACjD;GACA,MAAM,SAAS,sBAAsB,QAAQ,IAAI,gBAAgB;AACjE,OAAI,OACF,QAAO;IAAE,OAAO;IAAQ,SAAS;IAAO;GAE1C,MAAM,cAAc,IAAI,2BAA2B;IACjD,YAAY,WAAW;IACvB,SAAS;IACT,WAAW,WAAW;IACtB,aAAa,WAAW;IACxB,aAAa;IACd,CAAC;AACF,cAAW,oBAAoB,YAAY;AAC3C,yBAAsB,QAAQ,IAAI,iBAAiB,YAAY;AAC/D,UAAO;IAAE,OAAO;IAAa,SAAS;IAAO;;EAI/C,MAAM,cAAc,OAAO,KAAK,WAAW,UAAU,EAAE,CAAC;EACxD,MAAM,cAAc,sBAChB,cAAc,WAAW,eACzB;AACJ,QAAM,IAAI,MACR,oBAAoB,gBAAgB,kCAAkC,YAAY,QAC/E,YAAY,SACT,kBAAkB,YAAY,KAAK,KAAK,CAAC,KACzC,2BACJ,6DACH;IAEA;EACD;EACA;EACA;EACA,WAAW;EACX,WAAW;EACX,WAAW;EACX,WAAW;EACX,WAAW;EACX,KAAK,UAAU,WAAW,QAAQ;EACnC,CAAC;AAEF,iBAAgB;AACd,MAAI,YAAY,WAAW,EAAG;EAE9B,IAAI,SAAS;EACb,MAAM,WAAuC,EAAE;EAO/C,IAAI,iBAAiB;EACrB,MAAM,2BAA2B;AAC/B,OAAI,CAAC,OAAQ;AACb,OAAI,CAAC,gBAAgB;AACnB,qBAAiB;AACjB,yBAAqB;AACnB,sBAAiB;AACjB,SAAI,OACF,cAAa;MAEf;;;AAIN,MAAI,YAAY,SAAS,eAAe,kBAAkB,CACxD,UAAS,oBAAoB;AAG/B,MAAI,YAAY,SAAS,eAAe,eAAe,CACrD,UAAS,iBAAiB;AAG5B,MAAI,YAAY,SAAS,eAAe,mBAAmB,EAAE;AAC3D,YAAS,mBAAmB;AAC5B,YAAS,iBAAiB;AAC1B,YAAS,cAAc;AAGvB,YAAS,kBAAkB;;EAG7B,MAAM,eAAe,WAAW,4BAC9B,OACA,UACA,EACE,YACD,CACF;AACD,eAAa;AACX,YAAS;AACT,gBAAa,aAAa;;IAG3B;EAAC;EAAO;EAAa;EAAY;EAAoB;EAAY,CAAC;AAKrE,iBAAgB;AACd,MAAI,iBAAiB,UAInB,YAAW,oBAAoB,MAAM;AAEvC,MAAI,iBAAiB,2BACnB,OAAM,cAAc,WAAW;IAGhC;EAAC;EAAO,KAAK,UAAU,WAAW,QAAQ;EAAE,WAAW;EAAY,CAAC;CAgBvE,MAAM,iBAAiB,YAAY;CACnC,MAAM,4BAA4B,YAAY;CAC9C,MAAM,mBACJ,aAAa,4BAA4B,iBAAiB;AAC5D,iBAAgB;AACd,MAAI,CAAC,iBAAkB;AACvB,QAAM,WAAW;IAChB,CAAC,OAAO,iBAAiB,CAAC;AAE7B,QAAO;EACL;EAeA;EACD;;;;;AC7dH,MAAMC,eAAqC,EAAE;AAE7C,SAAgB,gBAEd,MAA4B,MAA+B;CAC3D,MAAM,EAAE,eAAeC,iBAAe;CACtC,MAAM,YAAY,QAAQD;AAE1B,iBAAgB;EACd,MAAM,OAAO,KAAK;AAGlB,MAAI,WAAW,QAAQ;GAAE,UAAU;GAAM,SAAS,KAAK;GAAS,CAAC,EAAE;AACjE,WAAQ,KACN,SAAS,KAAK,8BAA8B,KAAK,WAAW,SAAS,yCACtE;AACD,cAAW,WAAW,MAAM,KAAK,QAAQ;;AAE3C,aAAW,QAAQ,KAAK;AAMxB,MAAI,KAAK,OACP,YAAW,sBAAsB;GAC/B;GACA,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACd,CAAC;AAGJ,eAAa;AACX,cAAW,WAAW,MAAM,KAAK,QAAQ;;IAM1C;EAAC,KAAK;EAAM,KAAK;EAAW;EAAY,KAAK,UAAU,UAAU;EAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACcxE,SAAgB,aAId,QAQA,MACM;CACN,MAAM,SAAS,iCAAiC,OAAO,KAAK;CAC5D,MAAM,kBAAkB,OAAO,cAC3B,GAAG,OAAO,MAAM,OAAO,gBACvB;AAEJ,iBACE;EACE,MAAM,OAAO;EACb,aAAa;EACb,YAAY,OAAO;EACnB,SAAS,EAAE,WAA8B;GACvC,MAAM,YAAY,OAAO;AACzB,UAAO,oBAAC,aAAU,GAAK,OAAsC;;EAE/D,SAAS,OAAO;EAChB,UAAU,OAAO;EAClB,EACD,KACD;;;;;ACjFH,SAAgB,kBAEd,MAA8B,MAA+B;CAC7D,MAAM,EAAE,eAAeE,iBAAe;CACtC,MAAM,oBAAoB,OAA2C,KAAK;CAI1E,MAAM,kBAAkB,OAA4B,KAAK;CAEzD,MAAM,UAAU,YAAY,OAAO,WAAoB;AACrD,MAAI,kBAAkB,SAAS;AAC7B,mBAAgB,WAAW;AAC3B,mBAAgB,UAAU;AAC1B,qBAAkB,QAAQ,OAAO;AACjC,qBAAkB,UAAU;;IAE7B,EAAE,CAAC;CAEN,MAAM,UAAU,YACd,OAAO,OAAU,YAAuC;EACtD,MAAM,SAAS,SAAS;AACxB,SAAO,IAAI,SAAS,SAAS,WAAW;AAItC,OAAI,QAAQ,SAAS;AACnB,2BAAO,IAAI,MAAM,wCAAwC,CAAC;AAC1D;;AAGF,qBAAkB,UAAU;AAE5B,OAAI,QAAQ;IACV,MAAM,gBAAgB;AACpB,qBAAgB,UAAU;AAC1B,uBAAkB,UAAU;AAC5B,4BAAO,IAAI,MAAM,wCAAwC,CAAC;;AAE5D,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AACzD,oBAAgB,gBAAgB;AAC9B,YAAO,oBAAoB,SAAS,QAAQ;;;IAGhD;IAEJ,EAAE,CACH;CAED,MAAM,kBAAsD,aACzD,UAAU;EACT,MAAM,gBAAgB,KAAK;AAO3B,MAAI,MAAM,WAAW,eAAe,YAAY;GAC9C,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS,KAAK;IACd,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,eAAe,WAAW;GACpD,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS,KAAK;IACd;IACD;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,eAAe,UAAU;GACnD,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS,KAAK;IACd,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;;AAQ1D,SAD+B;IAGjC;EAAC,KAAK;EAAQ,KAAK;EAAM,KAAK;EAAa,KAAK;EAAS;EAAQ,CAClE;AAQD,iBAN2C;EACzC,GAAG;EACH;EACA,QAAQ;EACT,EAE6B,KAAK;AAInC,iBAAgB;AACd,eAAa;AACX,cAAW,yBAAyB,KAAK,MAAM,KAAK,QAAQ;;IAE7D;EAAC;EAAY,KAAK;EAAM,KAAK;EAAQ,CAAC;;;;;AC5F3C,MAAM,uBAAuB;AAiC7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;AAK1C,SAAS,cAAc,SAA2C;AAChE,KAAI,QAAQ,SAAS,SAAU,QAAO,QAAQ;AAC9C,QAAO;EAAE,MAAM;EAAsB,OAAO,QAAQ,WAAW;EAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6FrE,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAeC,iBAAe;CACtC,MAAM,EAAE,UAAU,SAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,SAAS,cAAc,SAAkC,KAAK;CACrE,MAAM,aAAa,OAAO,QAAQ;AAClC,YAAW,UAAU;CACrB,MAAM,CAAC,eAAe,oBAEpB,SAAwC,KAAK;CAE/C,MAAM,oBAAoB,OAAO,IAAI,iBAAiB,CAAC;CACvD,MAAM,qBAAqB,uBAAO,IAAI,KAAqB,CAAC;CAC5D,MAAM,iBAAiB,OAA2B,OAAU;AAE5D,iBAAgB;EACd,MAAM,iBAAiB,kBAAkB;EACzC,IAAI,cAAqC;EACzC,IAAI,gBAAoC;EAExC,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,eAAc;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG1D,qBAAqB,WAAW;AAC9B,QAAI,OAAO,YAAY,aAAa;KAClC,MAAM,QAAQ,OAAO,MAAM;AAC3B,UAAK,MAAM,aAAa,OAAO,WAC7B,oBAAmB,QAAQ,IAAI,UAAU,IAAI,MAAM;AAErD,qBAAgB,OAAO;;;GAG3B,yBAAyB;AACvB,kBAAc;AACd,oBAAgB;AAChB,uBAAmB,QAAQ,OAAO;AAClC,mBAAe,UAAU;AACzB,mBAAe,OAAO;AACtB,eAAW,KAAK;;GAElB,iBAAiB,WAAW;AAE1B,QAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,oBAAe,YAAY,cAAc;AACzC,gBAAW,eAAe,QAAQ;eACzB,aAAa;AACtB,oBAAe,UAAU,OAAO,MAAM;AACtC,oBAAe,UAAU,YAAY;AACrC,gBAAW,eAAe,QAAQ;;AAEpC,kBAAc;AACd,oBAAgB;;GAElB,mBAAmB;AACjB,kBAAc;AACd,oBAAgB;AAChB,uBAAmB,QAAQ,OAAO;AAClC,mBAAe,UAAU;AACzB,mBAAe,OAAO;AACtB,eAAW,KAAK;;GAEnB,CAAC;AAEF,eAAa;AACX,gBAAa,aAAa;AAC1B,kBAAe,OAAO;;IAEvB,CAAC,MAAM,CAAC;CAEX,MAAM,UAA8B,YAClC,OAAO,SAAS,gBAAgB;EAC9B,MAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,QAAS;AAEd,MACE,QAAQ,SAAS,cACjB,QAAQ,WAAW,SAAS,KAC5B,gBAAgB,OAEhB,SAAQ,KACN,qFAAqF,QAAQ,WAAW,OAAO,qGAChH;EAEH,MAAM,WAAW,kBAAkB,QAAQ,QAAQ,SAAS,YAAY;AACxE,MAAI,SAAS,SAAS,iBAAiB;GACrC,MAAM,QAAQ,eAAe;AAC7B,OAAI;AACF,WAAO,MAAM,WAAW,SAAS;KAC/B;KACA,GAAI,UAAU,SAAY,EAAE,OAAO,GAAG,EAAE;KACxC,gBAAgB,EACd,SAAS;MACP,QAAQ,SAAS;MACjB,gBAAgB,SAAS;MAC1B,EACF;KACF,CAAC;YACK,KAAK;AACZ,YAAQ,MACN,uFACA,IACD;AACD,eAAW,KAAK;AAChB,UAAM;;;AAGV,MAAI,SAAS,SAAS,WAAW;AAC/B,WAAQ,MACN,wCAAwC,SAAS,UAAU,GAAG,cAAc,SAAS,UAAU,UAAU,iBAC1G;AACD,qBAAkB,QAAQ,OAAO;AACjC,cAAW,KAAK;AAChB;;AAEF,MAAI,SAAS,SAAS,SAAU;EAChC,MAAM,QAAQ,SAAS,OACpB,KAAK,UAAU,mBAAmB,QAAQ,IAAI,MAAM,YAAY,CAAC,CACjE,MAAM,cAAmC,cAAc,OAAU;AACpE,OAAK,MAAM,cAAc,SAAS,YAChC,OAAM,WAAW;GACf,IAAIC,cAAY;GAChB,MAAM;GACN,YAAY,WAAW;GACvB,SAAS,WAAW;GACrB,CAAY;AAEf,MAAI;AACF,UAAO,MAAM,WAAW,SAAS;IAC/B;IACA,QAAQ,SAAS;IACjB,GAAI,UAAU,SAAY,EAAE,OAAO,GAAG,EAAE;IACzC,CAAC;WACK,KAAK;AACZ,WAAQ,MACN,uFACA,IACD;AACD,qBAAkB,QAAQ,OAAO;AACjC,cAAW,KAAK;AAChB,SAAM;;IAGV,CAAC,OAAO,WAAW,CACpB;CAED,MAAM,SAA4B,YAChC,OAAO,gBAAgB;EACrB,MAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,QAAS;AAEd,MACE,QAAQ,SAAS,cACjB,QAAQ,WAAW,SAAS,KAC5B,gBAAgB,OAEhB,SAAQ,KACN,qFAAqF,QAAQ,WAAW,OAAO,qGAChH;EAEH,MAAM,WAAW,kBAAkB,QAAQ,OAAO,YAAY;AAC9D,MAAI,SAAS,SAAS,WAAW;AAE/B,WAAQ,KACN,uGACD;AACD,qBAAkB,QAAQ,OAAO;AACjC,cAAW,KAAK;AAChB;;AAEF,MAAI,SAAS,SAAS,WAAW;AAC/B,WAAQ,MACN,wCAAwC,SAAS,UAAU,GAAG,cAAc,SAAS,UAAU,UAAU,iBAC1G;AACD,qBAAkB,QAAQ,OAAO;AACjC,cAAW,KAAK;AAChB;;AAEF,MAAI,SAAS,SAAS,SAAU;EAChC,MAAM,QAAQ,SAAS,OACpB,KAAK,UAAU,mBAAmB,QAAQ,IAAI,MAAM,YAAY,CAAC,CACjE,MAAM,cAAmC,cAAc,OAAU;AACpE,OAAK,MAAM,cAAc,SAAS,YAChC,OAAM,WAAW;GACf,IAAIA,cAAY;GAChB,MAAM;GACN,YAAY,WAAW;GACvB,SAAS,WAAW;GACrB,CAAY;AAEf,MAAI;AACF,UAAO,MAAM,WAAW,SAAS;IAC/B;IACA,QAAQ,SAAS;IACjB,GAAI,UAAU,SAAY,EAAE,OAAO,GAAG,EAAE;IACzC,CAAC;WACK,KAAK;AACZ,WAAQ,MACN,uFACA,IACD;AACD,qBAAkB,QAAQ,OAAO;AACjC,cAAW,KAAK;AAChB,SAAM;;IAGV,CAAC,OAAO,WAAW,CACpB;CAID,MAAM,YAAY,OAAO,OAAO,OAAO;AACvC,WAAU,UAAU,OAAO;CAC3B,MAAM,aAAa,OAAO,OAAO,QAAQ;AACzC,YAAW,UAAU,OAAO;CAC5B,MAAM,aAAa,OAAO,OAAO,QAAQ;AACzC,YAAW,UAAU,OAAO;CAC5B,MAAM,aAAa,OAAO,QAAQ;AAClC,YAAW,UAAU;CACrB,MAAM,YAAY,OAAO,OAAO;AAChC,WAAU,UAAU;CAGpB,MAAM,aAAa,UAAmC;EACpD,MAAM,YAAY,WAAW;AAC7B,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI;AACF,UAAO,UAAU,MAAM;WAChB,KAAK;AACZ,WAAQ,MACN,sFACA,IACD;AACD,UAAO;;;AAIX,iBAAgB;AACd,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAEF,MAAM,cAAc,cAAc,QAAQ;AAC1C,MAAI,CAAC,UAAU,YAAY,EAAE;AAC3B,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,IAAI;AACJ,MAAI;AACF,kBAAe,QAAQ;IACrB,OAAO;IACP,WAAW,QAAQ,SAAS,aAAa,QAAQ,WAAW,KAAK;IACjE,YAAY,QAAQ,SAAS,aAAa,CAAC,GAAG,QAAQ,WAAW,GAAG,EAAE;IACtE,SAAS,WAAW;IACpB,QAAQ,UAAU;IACnB,CAAC;WACK,KAAK;AACZ,WAAQ,MACN,iEACA,IACD;AACD,OAAI,CAAC,UAAW,kBAAiB,KAAK;AACtC,gBAAa;AACX,gBAAY;;;AAIhB,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,OAAO,QAAQ;AACd,WAAQ,MACN,oEACA,IACD;AACD,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb,CAAC,QAAQ,CAAC;CAEb,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,QAAS,QAAO;EACrB,MAAM,cAAc,cAAc,QAAQ;AAC1C,MAAI,CAAC,UAAU,YAAY,CAAE,QAAO;AAEpC,SAAO,UAAU,QAAQ;GACvB,OAAO;GACP,WAAW,QAAQ,SAAS,aAAa,QAAQ,WAAW,KAAK;GACjE,YAAY,QAAQ,SAAS,aAAa,CAAC,GAAG,QAAQ,WAAW,GAAG,EAAE;GACtE,QAAQ;GACR;GACA;GACD,CAAC;IAED;EAAC;EAAS;EAAe;EAAS;EAAO,CAAC;AAG7C,iBAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;IACtC;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,iBAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,eAAa;AACX,cAAW,oBAAoB,KAAK;;IAGrC,EAAE,CAAC;AAEN,KAAI,OAAO,iBAAiB,MAC1B,QAAO;;;;;ACreX,SAAgB,eAAe,EAC7B,YACyB,EAAE,EAAwB;CACnD,MAAM,EAAE,eAAeC,iBAAe;CACtC,MAAM,SAAS,6BAA6B;CAC5C,MAAM,kBAAkB,cAChB,WAAW,QAAQ,WAAW,kBACpC,CAAC,SAAS,QAAQ,QAAQ,CAC3B;CAED,MAAM,CAAC,aAAa,kBAAkB,eAA6B;AAEjE,SADe,WAAW,eAAe,gBAAgB,CAC3C;GACd;CACF,MAAM,CAAC,WAAW,gBAAgB,eAAe;AAE/C,SADe,WAAW,eAAe,gBAAgB,CAC3C;GACd;AAEF,iBAAgB;EACd,MAAM,SAAS,WAAW,eAAe,gBAAgB;AACzD,iBAAe,OAAO,YAAY;AAClC,eAAa,OAAO,UAAU;IAC7B,CAAC,YAAY,gBAAgB,CAAC;AAEjC,iBAAgB;EACd,MAAM,eAAe,WAAW,UAAU;GACxC,uBAAuB,EAAE,SAAS,gBAAgB,kBAAkB;AAClE,QAAI,mBAAmB,gBACrB;AAEF,mBAAe,YAAY;;GAE7B,8BAA8B,EAAE,SAAS,qBAAqB;AAC5D,QAAI,mBAAmB,gBACrB;AAEF,iBAAa,KAAK;;GAEpB,+BAA+B,EAAE,SAAS,qBAAqB;AAC7D,QAAI,mBAAmB,gBACrB;AAEF,iBAAa,MAAM;;GAErB,kCAAkC;IAChC,MAAM,SAAS,WAAW,eAAe,gBAAgB;AACzD,mBAAe,OAAO,YAAY;AAClC,iBAAa,OAAO,UAAU;;GAEjC,CAAC;AAEF,eAAa;AACX,gBAAa,aAAa;;IAE3B,CAAC,YAAY,gBAAgB,CAAC;AAYjC,QAAO;EACL;EACA,mBAZwB,kBAAkB;AAC1C,cAAW,kBAAkB,gBAAgB;KAE5C,CAAC,YAAY,gBAAgB,CAAC;EAU/B,kBARuB,kBAAkB;AACzC,cAAW,iBAAiB,gBAAgB;KAE3C,CAAC,YAAY,gBAAgB,CAAC;EAM/B;EACD;;;;;AChEH,SAAgB,wBACd,QACA,MACM;CACN,MAAM,EAAE,eAAeC,iBAAe;CACtC,MAAM,aAAa,6BAA6B;CAChD,MAAM,YAAY,QAAQ,EAAE;CAE5B,MAAM,0BAA0B,cACxB,YAAY,WAAW,kBAC7B,CAAC,YAAY,QAAQ,CACtB;CAED,MAAM,qBAAqB,cAEvB,SAAU,OAAkC,kBAAkB,QAChE,CAAC,OAAO,CACT;CAED,MAAM,wBAAwB,OAG3B;EACD,YAAY;EACZ,QAAQ;EACT,CAAC;CAEF,MAAM,EAAE,kBAAkB,qBAAqB,cAAc;AAC3D,MAAI,CAAC,QAAQ;AACX,yBAAsB,UAAU;IAAE,YAAY;IAAM,QAAQ;IAAM;AAClE,UAAO;IAAE,kBAAkB;IAAM,kBAAkB;IAAM;;AAG3D,MAAI,OAAO,cAAc,YAAY;AACnC,yBAAsB,UAAU;IAAE,YAAY;IAAM,QAAQ;IAAM;AAClE,UAAO;IAAE,kBAAkB;IAAM,kBAAkB;IAAM;;EAG3D,IAAI;AACJ,MAAI,gBAAgB,OAAO,CACzB,SAAQ,EACN,GAAG,QACJ;OACI;GACL,MAAM,wBAAwB,2BAC5B,OAAO,YACR;AAKD,WAJ4C;IAC1C,GAAG;IACH,aAAa;IACd;;EAIH,MAAM,aAAa,KAAK,UAAU,MAAM;EACxC,MAAM,QAAQ,sBAAsB;AACpC,MAAI,MAAM,eAAe,cAAc,MAAM,OAC3C,QAAO;GAAE,kBAAkB,MAAM;GAAQ,kBAAkB;GAAY;AAGzE,wBAAsB,UAAU;GAAE;GAAY,QAAQ;GAAO;AAC7D,SAAO;GAAE,kBAAkB;GAAO,kBAAkB;GAAY;IAC/D;EAAC;EAAQ;EAAyB,GAAG;EAAU,CAAC;CACnD,MAAM,kBAAkB,OAAiC,KAAK;AAC9D,iBAAgB,UAAU;CAC1B,MAAM,8BAA8B,OAAsB,KAAK;CAE/D,MAAM,gBAAgB,cAAc;AAClC,MAAI,CAAC,iBACH,QAAO;EAET,MAAM,WACJ,iBACA;AACF,MAAI,CAAC,YAAY,aAAa,IAC5B,QAAO;AAET,SAAO;IACN,CAAC,kBAAkB,wBAAwB,CAAC;CAE/C,MAAM,iBACJ,uBAAuB,UAAa,uBAAuB;CAE7D,MAAM,sBAAsB,cACpB,CAAC,CAAC,oBAAoB,kBAAkB,kBAC9C,CAAC,iBAAiB,CACnB;CAED,MAAM,gBAAgB,kBAAkB;AACtC,MAAI,CAAC,iBACH;AAGF,MAAI,gBAAgB;GAClB,MAAM,uBAAO,IAAI,KAAa;GAC9B,MAAM,SAAS,OAAO,OAAO,WAAW,UAAU,EAAE,CAAC;AACrD,QAAK,MAAM,SAAS,QAAQ;IAC1B,MAAM,UAAU,MAAM;AACtB,QAAI,CAAC,QACH;AAEF,SAAK,IAAI,QAAQ;AACjB,QAAI,CAAC,MAAM,UACT,YAAW,kBAAkB,QAAQ;;AAQzC,OAAI,iBAAiB,CAAC,KAAK,IAAI,cAAc,CAC3C,YAAW,kBAAkB,cAAc;AAE7C;;AAGF,MAAI,CAAC,cACH;AAGF,aAAW,kBAAkB,cAAc;IAC1C;EAAC;EAAY;EAAgB;EAAkB;EAAc,CAAC;AAEjE,iBAAgB;AACd,MAAI,CAAC,oBAAoB,CAAC,gBAAgB,QACxC;EAGF,MAAM,KAAK,WAAW,qBAAqB,gBAAgB,QAAQ;AAEnE,iBAAe;AAEf,eAAa;AACX,cAAW,wBAAwB,GAAG;;IAEvC;EAAC;EAAY;EAAkB;EAAc,CAAC;AAEjD,iBAAgB;AACd,MAAI,CAAC,kBAAkB;AACrB,+BAA4B,UAAU;AACtC;;AAEF,MACE,oBACA,4BAA4B,YAAY,iBAExC;AAEF,MAAI,iBACF,6BAA4B,UAAU;AAExC,iBAAe;IACd;EAAC;EAAkB;EAAe;EAAiB,CAAC;AAEvD,iBAAgB;AACd,MAAI,CAAC,oBAAoB,UAAU,WAAW,EAC5C;AAEF,iBAAe;IACd;EAAC,UAAU;EAAQ;EAAkB;EAAe,GAAG;EAAU,CAAC;AAUrE,iBAAgB;AACd,MAAI,CAAC,oBAAoB,CAAC,oBAAqB;AAC/C,MAAI,CAAC,cAAe;AAGpB,MADyB,CAAC,CAAC,WAAW,SAAS,cAAc,CACvC;EAEtB,MAAM,eAAe,WAAW,UAAU,EACxC,uBAAuB;AACrB,OAAI,WAAW,SAAS,cAAc,EAAE;AACtC,mBAAe;AACf,iBAAa,aAAa;;KAG/B,CAAC;AACF,eAAa;AACX,gBAAa,aAAa;;IAE3B;EACD;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,SAAS,gBACP,QACoC;AACpC,QAAO,kBAAkB;;AAG3B,SAAS,2BACP,aACc;AACd,QAAO,YAAY,KAAK,gBAAgB;EACtC,GAAG;EACH,WAAW,WAAW,aAAa;EACpC,EAAE;;;;;ACjNL,SAAgB,gBAAgB,SAA4B;CAC1D,MAAM,EAAE,aAAa,UAAU;CAC/B,MAAM,EAAE,eAAeC,iBAAe;CAEtC,MAAM,cAAc,cAAc;AAChC,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,SAAO,KAAK,UAAU,MAAM;IAC3B,CAAC,MAAM,CAAC;AAEX,uBAAsB;AACpB,MAAI,CAAC,WAAY;EAEjB,MAAM,KAAK,WAAW,WAAW;GAAE;GAAa,OAAO;GAAa,CAAC;AACrE,eAAa;AACX,cAAW,cAAc,GAAG;;IAE7B;EAAC;EAAa;EAAa;EAAW,CAAC;;;;;ACiI5C,SAAS,uBACP,OACA,UACG;AACH,QAAO,qBACL,aACG,kBAAkB;EACjB,MAAM,eAAe,MAAM,OAAO,SAAS,CAAC,UAAU,cAAc;AACpE,eAAa,aAAa,aAAa;IAEzC,CAAC,OAAO,SAAS,CAClB,QACK,SAAS,MAAM,UAAU,CAAC,QAK1B,SAAS,MAAM,gBAAgB,CAAC,CACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CH,SAAgB,WAAW,EACzB,SACA,iBACA,OACA,UAAU,QAC0B;CACpC,MAAM,EAAE,eAAeC,iBAAe;CAEtC,MAAM,CAAC,SAAS,eACd,mBAAmB,EACjB,OAAO,WAAW,OACnB,CAAC,CACH;CAED,MAAM,cAAc,uBAAuB,OAAO,eAAe;CACjE,MAAM,UAAoB,cAEtB,YAAY,KACT,EAAE,IAAI,SAAS,MAAM,UAAU,WAAW,WAAW,iBAAiB;EACrE;EACA;EACA;EACA;EACA;EACA;EACA,GAAI,cAAc,SAAY,EAAE,WAAW,GAAG,EAAE;EACjD,EACF,EACH,CAAC,YAAY,CACd;CACD,MAAM,iBAAiB,uBAAuB,OAAO,wBAAwB;CAC7E,MAAM,aAAa,uBAAuB,OAAO,oBAAoB;CACrE,MAAM,iBAAiB,uBAAuB,OAAO,sBAAsB;CAC3E,MAAM,iBAAiB,uBAAuB,OAAO,mBAAmB;CACxE,MAAM,wBAAwB,uBAC5B,OACA,0BACD;CACD,MAAM,aAAa,uBAAuB,OAAO,kBAAkB;CACnE,MAAM,aAAa,cAAc;AAC/B,SAAO,KAAK,UACV,OAAO,QAAQ,WAAW,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WACtD,KAAK,cAAc,MAAM,CAC1B,CACF;IACA,CAAC,WAAW,QAAQ,CAAC;CACxB,MAAM,gBAAgB,WAAW;CACjC,MAAM,8BACJ,WAAW,iBAAiB,SAAS;CACvC,MAAM,2BACJ,WAAW,iBAAiB,cAAc;CAC5C,MAAM,6BACJ,CAAC,CAAC,WAAW,cACb,kBAAkB,sCAAsC,aACxD,CAAC;CACH,MAAM,eAAe,cAAc;AACjC,MAAI,WAAW,WACb,QAAO;AAGT,yBAAO,IAAI,MAAM,gCAAgC;IAChD,CAAC,WAAW,WAAW,CAAC;CAC3B,MAAM,uBAAuB,cAAc;AACzC,MAAI,CAAC,2BACH,QAAO;AAGT,yBAAO,IAAI,MACT,gEACD;IACA,CAAC,2BAA2B,CAAC;CAChC,MAAM,uBAAuB,cAAc;AACzC,MAAI,yBACF,QAAO;AAGT,yBAAO,IAAI,MACT,gEACD;IACA,CAAC,yBAAyB,CAAC;CAS9B,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,MAAM;CACvE,MAAM,oBACJ,WACA,CAAC,CAAC,WAAW,cACb,CAAC,8BACD,CAAC;CASH,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,MAAM;AACvE,iBAAgB;AACd,0BAAwB,MAAM;IAC7B,CAAC,cAAc,qBAAqB,CAAC;CAExC,MAAM,qBAAqB,uBAAuB,OAAO;CACzD,MAAM,6BAA6B,uBAC/B,OACA;CAEJ,MAAM,YACJ,sBAAsB,6BAClB,QACA,qBAAqB;CAC3B,MAAM,QAAQ,sBAAsB,8BAA8B;CAIlE,MAAM,YAAY;AAElB,iBAAgB;AACd,QAAM,OAAO;AACb,eAAa;AACX,SAAM,MAAM;;IAEb,CAAC,MAAM,CAAC;AAaX,iBAAgB;AAMd,MAAI,CAAC,QAAS;AACd,aAAW,oBAAoB,SAAS,MAAM;AAC9C,eAAa;AACX,cAAW,sBAAsB,QAAQ;;IAE1C;EAAC;EAAY;EAAS;EAAO;EAAQ,CAAC;AAEzC,iBAAgB;AAGd,MAAI,CAAC,SAAS;AACZ,SAAM,WAAW,KAAK;AACtB,2BAAwB,MAAM;AAC9B;;AAGF,MAAI,CAAC,WAAW,YAAY;AAC1B,SAAM,WAAW,KAAK;AACtB,2BAAwB,MAAM;AAC9B;;AAKF,MAAI,kBAAkB,sCAAsC,UAC1D;AAGF,MAAI,CAAC,6BAA6B;AAChC,SAAM,WAAW,KAAK;AACtB,2BAAwB,MAAM;AAC9B;;EAGF,MAAM,UAAiC;GACrC,YAAY,WAAW;GACvB,SAAS,EAAE,GAAG,WAAW,SAAS;GAClC,OAAO,WAAW,cAAc;GAChC;GACA;GACA;GACD;AAED,QAAM,WAAW,QAAQ;AACzB,0BAAwB,KAAK;IAC5B;EACD;EACA;EACA,WAAW;EACX;EACA;EACA,WAAW,cAAc;EACzB;EACA;EACA;EACA;EACD,CAAC;CAEF,MAAM,gBAAgB,aAElB,aACwC;AACxC,UAAQ,GAAG,SAAgB;AACzB,OAAI,qBACF,QAAO,QAAQ,OAAO,qBAAqB;AAE7C,UAAO,SAAS,GAAG,KAAK;;IAG5B,CAAC,qBAAqB,CACvB;CAED,MAAM,eAAe,cAEjB,eAAe,UAAkB,SAC/B,MAAM,aAAa,UAAU,KAAK,CACnC,EACH,CAAC,OAAO,cAAc,CACvB;CAED,MAAM,gBAAgB,cACd,eAAe,aAAqB,MAAM,cAAc,SAAS,CAAC,EACxE,CAAC,OAAO,cAAc,CACvB;CAED,MAAM,kBAAkB,cAChB,eAAe,aAAqB,MAAM,gBAAgB,SAAS,CAAC,EAC1E,CAAC,OAAO,cAAc,CACvB;CAED,MAAM,eAAe,cACb,eAAe,aAAqB,MAAM,aAAa,SAAS,CAAC,EACvE,CAAC,OAAO,cAAc,CACvB;AAYD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,kBAnBuB,kBAAkB,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC;EAoBxE,gBAnBqB,kBAAkB,MAAM,gBAAgB,EAAE,CAAC,MAAM,CAAC;EAoBvE,gBAnBqB,kBAAkB;AAIvC,2BAAwB,KAAK;AAC7B,SAAM,gBAAgB;KACrB,CAAC,MAAM,CAAC;EAcT;EACA;EACA;EACA;EACD;;;;;ACjcH,SAAgB,uBAAmD,KAKpC;CAE7B,MAAM,aAAa,IAAI,SAAS,OAAO,CAAC,IAAI,OAAO,EAAE,KAAK,GAAG,IAAI;AAEjE,QAAO;EACL,MAAM,IAAI;EACV,MAAM;EACN,QAAQ,IAAI;EACZ,GAAI,IAAI,UAAU,EAAE,SAAS,IAAI,SAAS,GAAG,EAAE;EAChD;;;;;AC5DH,MAAM,aAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqJ7C,SAAgB,cACd,QACA,MACM;CACN,MAAM,EAAE,eAAeC,iBAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,iBAAgB;EAEd,MAAM,WACJ,OAAO,SAAS,OAAO,CAAC,OAAO,aAC3B,uBAAuB;GACrB,MAAM;GACN,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC,GACF,uBAAuB;GACrB,MAAM,OAAO;GACb,MAAM,OAAO;GAGb,SAAS,UAAU;AACjB,QAAI,MAAM,WAAW,eAAe,WAClC,QAAO,OAAO,OAAO;KAAE,GAAG;KAAO,YAAY,MAAM;KAAM,CAAC;AAE5D,QAAI,MAAM,WAAW,eAAe,UAClC,QAAO,OAAO,OAAO;KAAE,GAAG;KAAO,YAAY,MAAM;KAAM,CAAC;AAE5D,WAAO,OAAO,OAAO;KAAE,GAAG;KAAO,YAAY,MAAM;KAAM,CAAC;;GAE5D,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC;AAER,aAAW,sBAAsB,SAAS;IAGzC;EAAC,OAAO;EAAM;EAAY,KAAK,UAAU,UAAU;EAAC,CAAC;;;;;;;;;;ACnK1D,MAAM,mBAAmB,MAAM,KAC7B,SAAS,iBAAiB,EACxB,UACA,aACA,iBACA,eACwB;CAExB,MAAM,OAAO,cACL,iBAAiB,SAAS,SAAS,UAAU,EACnD,CAAC,SAAS,SAAS,UAAU,CAC9B;CAED,MAAM,WAAW,SAAS,SAAS;AAGnC,KAAI,YACF,QACE,oBAAC;EACC,MAAM;EACN,YAAY,SAAS;EACf;EACN,QAAQ,eAAe;EACvB,QAAQ,YAAY;GACpB;UAEK,YACT,QACE,oBAAC;EACC,MAAM;EACN,YAAY,SAAS;EACf;EACN,QAAQ,eAAe;EACvB,QAAQ;GACR;KAGJ,QACE,oBAAC;EACC,MAAM;EACN,YAAY,SAAS;EACf;EACN,QAAQ,eAAe;EACvB,QAAQ;GACR;IAKP,WAAW,cAAc;AAExB,KAAI,UAAU,SAAS,OAAO,UAAU,SAAS,GAAI,QAAO;AAC5D,KAAI,UAAU,SAAS,SAAS,SAAS,UAAU,SAAS,SAAS,KACnE,QAAO;AACT,KACE,UAAU,SAAS,SAAS,cAC5B,UAAU,SAAS,SAAS,UAE5B,QAAO;AAKT,KAFmB,UAAU,aAAa,YACvB,UAAU,aAAa,QACX,QAAO;AAGtC,KAAI,UAAU,gBAAgB,UAAU,YAAa,QAAO;AAG5D,KAAI,UAAU,oBAAoB,UAAU,gBAAiB,QAAO;AAEpE,QAAO;EAEV;;;;;;;AAQD,SAAgB,oBAAoB;CAClC,MAAM,EAAE,YAAY,yBAAyBC,iBAAe;CAE5D,MAAM,UADS,6BAA6B,EACpB,WAAW;CAInC,MAAM,kBAAkB,sBACrB,aAAa;AACZ,SAAO,WAAW,UAAU,EAC1B,0BAA0B,UAC3B,CAAC,CAAC;UAEC,WAAW,uBACX,WAAW,gBAClB;AA0DD,QAlDuB,aACpB,EACC,UACA,kBACuD;EAOvD,MAAM,eAAe,gBAAgB,QAClC,OAAO,GAAG,SAAS,SAAS,SAAS,KACvC;EAGD,MAAM,eACJ,aAAa,MAAM,OAAO,GAAG,YAAY,QAAQ,IACjD,aAAa,MAAM,OAAO,CAAC,GAAG,QAAQ,IACtC,aAAa,MACb,gBAAgB,MAAM,OAAO,GAAG,SAAS,IAAI;AAQ/C,MAAI,CAAC,aACH,QAAO;EAGT,MAAM,kBACJ,aAAa;AAIf,SACE,oBAAC;GAEW;GACG;GACI;GACjB,aATgB,qBAAqB,IAAI,SAAS,GAAG;KAKhD,SAAS,GAKd;IAGN;EAAC;EAAiB;EAAsB;EAAQ,CACjD;;;;;;;;;;;;;;;;;;ACrKH,SAAgB,gBACd,SAC+B;CAC/B,MAAM,EAAE,UAAU,SAAS,EAAE,SAAS,CAAC;AAEvC,KAAI,SAAS,kBAAkB,MAC7B,QAAQ,MAA+C"}