UNPKG

@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 • 14 kB
{"version":3,"sources":["../src/hooks/use-coagent.ts"],"sourcesContent":["/**\n * <Callout type=\"info\">\n * Usage of this hook assumes some additional setup in your application, for more information\n * on that see the CoAgents <span className=\"text-blue-500\">[getting started guide](/coagents/quickstart/langgraph)</span>.\n * </Callout>\n * <Frame className=\"my-12\">\n * <img\n * src=\"https://cdn.copilotkit.ai/docs/copilotkit/images/coagents/SharedStateCoAgents.gif\"\n * alt=\"CoAgents demonstration\"\n * className=\"w-auto\"\n * />\n * </Frame>\n *\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of an agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences agentic copilots, or CoAgents for short.\n *\n * ## Usage\n *\n * ### Simple Usage\n *\n * ```tsx\n * import { useCoAgent } from \"@copilotkit/react-core\";\n *\n * type AgentState = {\n * count: number;\n * }\n *\n * const agent = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * ```\n *\n * `useCoAgent` returns an object with the following properties:\n *\n * ```tsx\n * const {\n * name, // The name of the agent currently being used.\n * nodeName, // The name of the current LangGraph node.\n * state, // The current state of the agent.\n * setState, // A function to update the state of the agent.\n * running, // A boolean indicating if the agent is currently running.\n * start, // A function to start the agent.\n * stop, // A function to stop the agent.\n * run, // A function to re-run the agent. Takes a HintFunction to inform the agent why it is being re-run.\n * } = agent;\n * ```\n *\n * Finally we can leverage these properties to create reactive experiences with the agent!\n *\n * ```tsx\n * const { state, setState } = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * return (\n * <div>\n * <p>Count: {state.count}</p>\n * <button onClick={() => setState({ count: state.count + 1 })}>Increment</button>\n * </div>\n * );\n * ```\n *\n * This reactivity is bidirectional, meaning that changes to the state from the agent will be reflected in the UI and vice versa.\n *\n * ## Parameters\n * <PropertyReference name=\"options\" type=\"UseCoagentOptions<T>\" required>\n * The options to use when creating the coagent.\n * <PropertyReference name=\"name\" type=\"string\" required>\n * The name of the agent to use.\n * </PropertyReference>\n * <PropertyReference name=\"initialState\" type=\"T | any\">\n * The initial state of the agent.\n * </PropertyReference>\n * <PropertyReference name=\"state\" type=\"T | any\">\n * State to manage externally if you are using this hook with external state management.\n * </PropertyReference>\n * <PropertyReference name=\"setState\" type=\"(newState: T | ((prevState: T | undefined) => T)) => void\">\n * A function to update the state of the agent if you are using this hook with external state management.\n * </PropertyReference>\n * </PropertyReference>\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { Message } from \"@copilotkit/shared\";\nimport { useAgent, useCopilotKit } from \"@copilotkitnext/react\";\nimport { type AgentSubscriber } from \"@ag-ui/client\";\nimport { useAgentNodeName } from \"./use-agent-nodename\";\n\ninterface UseCoagentOptionsBase {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * @deprecated - use \"config.configurable\"\n * Config to pass to a LangGraph Agent\n */\n configurable?: Record<string, any>;\n /**\n * Config to pass to a LangGraph Agent\n */\n config?: {\n configurable?: Record<string, any>;\n [key: string]: any;\n };\n}\n\ninterface WithInternalStateManagementAndInitial<T> extends UseCoagentOptionsBase {\n /**\n * The initial state of the agent.\n */\n initialState: T;\n}\n\ninterface WithInternalStateManagement extends UseCoagentOptionsBase {\n /**\n * Optional initialState with default type any\n */\n initialState?: any;\n}\n\ninterface WithExternalStateManagement<T> extends UseCoagentOptionsBase {\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n}\n\ntype UseCoagentOptions<T> =\n | WithInternalStateManagementAndInitial<T>\n | WithInternalStateManagement\n | WithExternalStateManagement<T>;\n\nexport interface UseCoagentReturnType<T> {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * The name of the current LangGraph node.\n */\n nodeName?: string;\n /**\n * The ID of the thread the agent is running in.\n */\n threadId?: string;\n /**\n * A boolean indicating if the agent is currently running.\n */\n running: boolean;\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n /**\n * A function to start the agent.\n */\n start: () => void;\n /**\n * A function to stop the agent.\n */\n stop: () => void;\n /**\n * A function to re-run the agent. The hint function can be used to provide a hint to the agent\n * about why it is being re-run again.\n */\n run: (...args: any[]) => Promise<any>;\n}\n\nexport interface HintFunctionParams {\n /**\n * The previous state of the agent.\n */\n previousState: any;\n /**\n * The current state of the agent.\n */\n currentState: any;\n}\n\nexport type HintFunction = (params: HintFunctionParams) => Message | undefined;\n\n/**\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of the agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences \"agentic copilots\". To get started using agentic copilots, which\n * we refer to as CoAgents, checkout the documentation at https://docs.copilotkit.ai/coagents/quickstart/langgraph.\n */\nexport function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentReturnType<T> {\n const { agent } = useAgent({ agentId: options.name });\n const { copilotkit } = useCopilotKit();\n const nodeName = useAgentNodeName(options.name);\n\n const handleStateUpdate = useCallback(\n (newState: T | ((prevState: T | undefined) => T)) => {\n if (!agent) return;\n\n if (typeof newState === \"function\") {\n const updater = newState as (prevState: T | undefined) => T;\n agent.setState(updater(agent.state));\n } else {\n agent.setState({ ...agent.state, ...newState });\n }\n },\n [agent?.state, agent?.setState],\n );\n\n useEffect(() => {\n if (!options.config && !options.configurable) return;\n\n let config = options.config ?? {};\n if (options.configurable) {\n config = {\n ...config,\n configurable: {\n ...options.configurable,\n ...config.configurable,\n },\n };\n }\n copilotkit.setProperties(config);\n }, [options.config, options.configurable]);\n\n const externalStateStr = useMemo(\n () => (isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined),\n [isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined],\n );\n\n // Sync internal state with external state if state management is external\n useEffect(() => {\n if (\n agent?.state &&\n isExternalStateManagement(options) &&\n JSON.stringify(options.state) !== JSON.stringify(agent.state)\n ) {\n handleStateUpdate(options.state);\n }\n }, [agent, externalStateStr, handleStateUpdate]);\n\n const hasStateValues = useCallback((value?: Record<string, any>) => {\n return Boolean(value && Object.keys(value).length);\n }, []);\n\n const initialStateRef = useRef<any>(\n isExternalStateManagement(options)\n ? options.state\n : \"initialState\" in options\n ? options.initialState\n : undefined,\n );\n\n useEffect(() => {\n if (isExternalStateManagement(options)) {\n initialStateRef.current = options.state;\n } else if (\"initialState\" in options) {\n initialStateRef.current = options.initialState;\n }\n }, [\n isExternalStateManagement(options)\n ? JSON.stringify(options.state)\n : \"initialState\" in options\n ? JSON.stringify(options.initialState)\n : undefined,\n ]);\n\n useEffect(() => {\n if (!agent) return;\n const subscriber: AgentSubscriber = {\n onStateChanged: (args: any) => {\n if (isExternalStateManagement(options)) {\n options.setState(args.state);\n }\n },\n onRunInitialized: (args: any) => {\n const runHasState = hasStateValues(args.state);\n if (runHasState) {\n handleStateUpdate(args.state);\n return;\n }\n\n if (hasStateValues(agent.state)) {\n return;\n }\n\n if (initialStateRef.current !== undefined) {\n handleStateUpdate(initialStateRef.current);\n }\n },\n };\n\n const subscription = agent.subscribe(subscriber);\n return () => {\n subscription.unsubscribe();\n };\n }, [agent, handleStateUpdate, hasStateValues]);\n\n // Return a consistent shape whether or not the agent is available\n return useMemo<UseCoagentReturnType<T>>(() => {\n if (!agent) {\n const noop = () => {};\n const noopAsync = async () => {};\n const initialState =\n // prefer externally provided state if available\n (\"state\" in options && (options as any).state) ??\n // then initialState if provided\n (\"initialState\" in options && (options as any).initialState) ??\n ({} as T);\n return {\n name: options.name,\n nodeName,\n threadId: undefined,\n running: false,\n state: initialState as T,\n setState: noop,\n start: noop,\n stop: noop,\n run: noopAsync,\n };\n }\n\n return {\n name: agent?.agentId ?? options.name,\n nodeName,\n threadId: agent.threadId,\n running: agent.isRunning,\n state: agent.state,\n setState: handleStateUpdate,\n // TODO: start and run both have same thing. need to figure out\n start: agent.runAgent,\n stop: agent.abortRun,\n run: agent.runAgent,\n };\n }, [\n agent?.state,\n agent?.runAgent,\n agent?.abortRun,\n agent?.runAgent,\n agent?.threadId,\n agent?.isRunning,\n agent?.agentId,\n handleStateUpdate,\n options.name,\n ]);\n}\n\nconst isExternalStateManagement = <T>(\n options: UseCoagentOptions<T>,\n): options is WithExternalStateManagement<T> => {\n return \"state\" in options && \"setState\" in options;\n};\n"],"mappings":"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","names":[]}