import { CopilotCloudConfig, FunctionCallHandler, CopilotErrorHandler, CopilotKitError, } from "@copilotkit/shared"; import { ActionRenderProps, CatchAllActionRenderProps, FrontendAction, } from "../types/frontend-action"; import React from "react"; import { TreeNodeId, Tree } from "../hooks/use-tree"; import { DocumentPointer } from "../types"; import { CopilotChatSuggestionConfiguration } from "../types/chat-suggestion-configuration"; import { CoAgentStateRender, CoAgentStateRenderProps, } from "../types/coagent-action"; import { CoagentState } from "../types/coagent-state"; import { CopilotRuntimeClient, ExtensionsInput, ForwardedParametersInput, } from "@copilotkit/runtime-client-gql"; import { Agent } from "@copilotkit/runtime-client-gql"; import { LangGraphInterruptRender, LangGraphInterruptActionSetter, QueuedInterruptEvent, } from "../types/interrupt-action"; /** * Interface for the configuration of the Copilot API. */ export interface CopilotApiConfig { /** * The public API key for Copilot Cloud. */ publicApiKey?: string; /** * The configuration for Copilot Cloud. */ cloud?: CopilotCloudConfig; /** * The endpoint for the chat API. */ chatApiEndpoint: string; /** * The endpoint for the Copilot transcribe audio service. */ transcribeAudioUrl?: string; /** * The endpoint for the Copilot text to speech service. */ textToSpeechUrl?: string; /** * additional headers to be sent with the request * @default {} * @example * ``` * { * 'Authorization': 'Bearer your_token_here' * } * ``` */ headers: Record; /** * Custom properties to be sent with the request * @default {} * @example * ``` * { * 'user_id': 'user_id' * } * ``` */ properties?: Record; /** * Indicates whether the user agent should send or receive cookies from the other domain * in the case of cross-origin requests. */ credentials?: RequestCredentials; /** * Optional configuration for connecting to Model Context Protocol (MCP) servers. * This is typically derived from the CopilotKitProps and used internally. * @experimental */ mcpServers?: Array<{ endpoint: string; apiKey?: string }>; } export type InChatRenderFunction< TProps = ActionRenderProps | CatchAllActionRenderProps, > = (props: TProps) => string | React.JSX.Element; export type CoagentInChatRenderFunction = ( props: CoAgentStateRenderProps, ) => string | React.JSX.Element | undefined | null; export interface ChatComponentsCache { actions: Record; coAgentStateRenders: Record; } export interface AgentSession { agentName: string; threadId?: string; nodeName?: string; } export interface AuthState { status: "authenticated" | "unauthenticated"; authHeaders: Record; userId?: string; metadata?: Record; } export type ActionName = string; export type ContextTree = Tree; export interface CopilotContextParams { // function-calling actions: Record>; setAction: (id: string, action: FrontendAction) => void; removeAction: (id: string) => void; // registered actions for component-based rendering setRegisteredActions: (actionConfig: any) => string; removeRegisteredAction: (actionKey: string) => void; chatComponentsCache: React.RefObject; getFunctionCallHandler: ( customEntryPoints?: Record>, ) => FunctionCallHandler; // text context addContext: ( context: string, parentId?: string, categories?: string[], ) => TreeNodeId; removeContext: (id: TreeNodeId) => void; getAllContext: () => Tree; getContextString: ( documents: DocumentPointer[], categories: string[], ) => string; // document context addDocumentContext: ( documentPointer: DocumentPointer, categories?: string[], ) => TreeNodeId; removeDocumentContext: (documentId: string) => void; getDocumentsContext: (categories: string[]) => DocumentPointer[]; isLoading: boolean; setIsLoading: React.Dispatch>; chatSuggestionConfiguration: { [key: string]: CopilotChatSuggestionConfiguration; }; addChatSuggestionConfiguration: ( id: string, suggestion: CopilotChatSuggestionConfiguration, ) => void; removeChatSuggestionConfiguration: (id: string) => void; chatInstructions: string; setChatInstructions: React.Dispatch>; additionalInstructions?: string[]; setAdditionalInstructions: React.Dispatch>; // api endpoints copilotApiConfig: CopilotApiConfig; showDevConsole: boolean; // agents coagentStates: Record; setCoagentStates: React.Dispatch< React.SetStateAction> >; coagentStatesRef: React.RefObject>; setCoagentStatesWithRef: ( value: | Record | ((prev: Record) => Record), ) => void; agentSession: AgentSession | null; setAgentSession: React.Dispatch>; agentLock: string | null; threadId: string; setThreadId: React.Dispatch>; runId: string | null; setRunId: React.Dispatch>; // The chat abort controller can be used to stop generation globally, // i.e. when using `stop()` from `useChat` chatAbortControllerRef: React.MutableRefObject; /** * The forwarded parameters to use for the task. */ forwardedParameters?: Partial>; availableAgents: Agent[]; /** * The auth states for the CopilotKit. */ authStates_c?: Record; setAuthStates_c?: React.Dispatch< React.SetStateAction> >; /** * The auth config for the CopilotKit. */ authConfig_c?: { SignInComponent: React.ComponentType<{ onSignInComplete: (authState: AuthState) => void; }>; }; extensions: ExtensionsInput; setExtensions: React.Dispatch>; interruptActions: Record; setInterruptAction: LangGraphInterruptActionSetter; removeInterruptAction: (actionId: string) => void; interruptEventQueue: Record; addInterruptEvent: (queuedEvent: QueuedInterruptEvent) => void; resolveInterruptEvent: ( threadId: string, eventId: string, response: string, ) => void; /** * Optional trace handler for comprehensive debugging and observability. */ onError: CopilotErrorHandler; // banner error state bannerError: CopilotKitError | null; setBannerError: React.Dispatch>; // Internal error handlers // These are used to handle errors that occur during the execution of the chat. // They are not intended for use by the developer. A component can register itself an error listener to be activated somewhere else as needed internalErrorHandlers: Record; setInternalErrorHandler: ( handler: Record, ) => void; removeInternalErrorHandler: (id: string) => void; } const emptyCopilotContext: CopilotContextParams = { actions: {}, setAction: () => {}, removeAction: () => {}, setRegisteredActions: () => "", removeRegisteredAction: () => {}, chatComponentsCache: { current: { actions: {}, coAgentStateRenders: {} } }, getContextString: (documents: DocumentPointer[], categories: string[]) => returnAndThrowInDebug(""), addContext: () => "", removeContext: () => {}, getAllContext: () => [], getFunctionCallHandler: () => returnAndThrowInDebug(async () => {}), isLoading: false, setIsLoading: () => returnAndThrowInDebug(false), chatInstructions: "", setChatInstructions: () => returnAndThrowInDebug(""), additionalInstructions: [], setAdditionalInstructions: () => returnAndThrowInDebug([]), getDocumentsContext: (categories: string[]) => returnAndThrowInDebug([]), addDocumentContext: () => returnAndThrowInDebug(""), removeDocumentContext: () => {}, copilotApiConfig: new (class implements CopilotApiConfig { get chatApiEndpoint(): string { throw new Error( "Remember to wrap your app in a ` {...} ` !!!", ); } get headers(): Record { return {}; } get body(): Record { return {}; } })(), chatSuggestionConfiguration: {}, addChatSuggestionConfiguration: () => {}, removeChatSuggestionConfiguration: () => {}, showDevConsole: false, coagentStates: {}, setCoagentStates: () => {}, coagentStatesRef: { current: {} }, setCoagentStatesWithRef: () => {}, agentSession: null, setAgentSession: () => {}, forwardedParameters: {}, agentLock: null, threadId: "", setThreadId: () => {}, runId: null, setRunId: () => {}, chatAbortControllerRef: { current: null }, availableAgents: [], extensions: {}, setExtensions: () => {}, interruptActions: {}, setInterruptAction: () => {}, removeInterruptAction: () => {}, interruptEventQueue: {}, addInterruptEvent: () => {}, resolveInterruptEvent: () => {}, onError: () => {}, bannerError: null, setBannerError: () => {}, internalErrorHandlers: {}, setInternalErrorHandler: () => {}, removeInternalErrorHandler: () => {}, }; export const CopilotContext = React.createContext(emptyCopilotContext); export function useCopilotContext(): CopilotContextParams { const context = React.useContext(CopilotContext); if (context === emptyCopilotContext) { throw new Error( "Remember to wrap your app in a ` {...} ` !!!", ); } return context; } function returnAndThrowInDebug(_value: T): T { throw new Error( "Remember to wrap your app in a ` {...} ` !!!", ); }