chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:18 +08:00
commit 6d5d58c1a9
18293 changed files with 3502153 additions and 0 deletions
+397
View File
@@ -0,0 +1,397 @@
"""CopilotKit SDK"""
import warnings
from importlib import metadata
from pprint import pformat
from typing import List, Callable, Union, Optional, Any, Coroutine
from typing_extensions import TypedDict, Tuple, cast, Mapping
from .agent import Agent, AgentDict
from .action import Action, ActionDict, ActionResultDict
from .types import Message, MetaEvent
from .exc import (
ActionNotFoundException,
AgentNotFoundException,
ActionExecutionException,
AgentExecutionException,
)
from .logging import get_logger, bold
try:
__version__ = metadata.version(cast(str, __package__))
except metadata.PackageNotFoundError:
# Case where package metadata is not available.
__version__ = ""
del metadata # optional, avoids polluting the results of dir(__package__)
COPILOTKIT_SDK_VERSION = __version__
logger = get_logger(__name__)
class InfoDict(TypedDict):
"""
Info dictionary
"""
sdkVersion: str
actions: List[ActionDict]
agents: List[AgentDict]
class CopilotKitContext(TypedDict):
"""
CopilotKit Context
Parameters
----------
properties : Any
The properties provided to the frontend via `<CopilotKit properties={...} />`
frontend_url : Optional[str]
The current URL of the frontend
headers : Mapping[str, str]
The headers of the request
"""
properties: Any
frontend_url: Optional[str]
headers: Mapping[str, str]
# Alias for backwards compatibility
CopilotKitSDKContext = CopilotKitContext
class CopilotKitRemoteEndpoint:
"""
CopilotKitRemoteEndpoint lets you connect actions and agents written in Python to your
CopilotKit application.
To install CopilotKit for Python, run:
```bash
pip install copilotkit
# or to include crewai
pip install copilotkit[crewai]
```
## Adding actions
In this example, we provide a simple action to the Copilot:
```python
from copilotkit import CopilotKitRemoteEndpoint, Action
sdk = CopilotKitRemoteEndpoint(
actions=[
Action(
name="greet_user",
handler=greet_user_handler,
description="Greet the user",
parameters=[
{
"name": "name",
"type": "string",
"description": "The name of the user"
}
]
)
]
)
```
You can also dynamically build actions by providing a callable that returns a list of actions.
In this example, we use "name" from the `properties` object to parameterize the action handler.
```python
from copilotkit import CopilotKitRemoteEndpoint, Action
sdk = CopilotKitRemoteEndpoint(
actions=lambda context: [
Action(
name="greet_user",
handler=make_greet_user_handler(context["properties"]["name"]),
description="Greet the user"
)
]
)
```
Using the same approach, you can restrict the actions available to the Copilot:
```python
from copilotkit import CopilotKitRemoteEndpoint, Action
sdk = CopilotKitRemoteEndpoint(
actions=lambda context: (
[action_a, action_b] if is_admin(context["properties"]["token"]) else [action_a]
)
)
```
## Adding agents
Serving agents works in a similar way to serving actions:
```python
from copilotkit import CopilotKitRemoteEndpoint, LangGraphAGUIAgent
from my_agent.agent import graph
sdk = CopilotKitRemoteEndpoint(
agents=[
LangGraphAGUIAgent(
name="email_agent",
description="This agent sends emails",
graph=graph,
)
]
)
```
To dynamically build agents, provide a callable that returns a list of agents:
```python
from copilotkit import CopilotKitRemoteEndpoint, LangGraphAGUIAgent
from my_agent.agent import graph
sdk = CopilotKitRemoteEndpoint(
agents=lambda context: [
LangGraphAGUIAgent(
name="email_agent",
description="This agent sends emails",
graph=graph,
langgraph_config={
"token": context["properties"]["token"]
}
)
]
)
```
To restrict the agents available to the Copilot, simply return a different list of agents based on the `context`:
```python
from copilotkit import CopilotKitRemoteEndpoint
from my_agents import agent_a, agent_b, is_admin
sdk = CopilotKitRemoteEndpoint(
agents=lambda context: (
[agent_a, agent_b] if is_admin(context["properties"]["token"]) else [agent_a]
)
)
```
## Serving the CopilotKit SDK
To serve the CopilotKit SDK, you can use the `add_fastapi_endpoint` function from the `copilotkit.integrations.fastapi` module:
```python
from copilotkit.integrations.fastapi import add_fastapi_endpoint
from fastapi import FastAPI
app = FastAPI()
sdk = CopilotKitRemoteEndpoint(...)
add_fastapi_endpoint(app, sdk, "/copilotkit")
def main():
uvicorn.run(
"your_package:app",
host="0.0.0.0",
port=8000,
reload=True,
)
```
Parameters
----------
actions : Optional[Union[List[Action], Callable[[CopilotKitContext], List[Action]]]]
The actions to make available to the Copilot.
agents : Optional[Union[List[Agent], Callable[[CopilotKitContext], List[Agent]]]]
The agents to make available to the Copilot.
"""
def __init__(
self,
*,
actions: Optional[
Union[List[Action], Callable[[CopilotKitContext], List[Action]]]
] = None,
agents: Optional[
Union[List[Agent], Callable[[CopilotKitContext], List[Agent]]]
] = None,
):
self.agents = agents or []
self.actions = actions or []
def info(self, *, context: CopilotKitContext) -> InfoDict:
"""
Returns information about available actions and agents
"""
actions = self.actions(context) if callable(self.actions) else self.actions
agents = self.agents(context) if callable(self.agents) else self.agents
actions_list = [action.dict_repr() for action in actions]
agents_list = [agent.dict_repr() for agent in agents]
self._log_request_info(
title="Handling info request:",
data=[
("Context", context),
("Actions", actions_list),
("Agents", agents_list),
],
)
return {
"actions": actions_list,
"agents": agents_list,
"sdkVersion": COPILOTKIT_SDK_VERSION,
}
def _get_action(
self,
*,
context: CopilotKitContext,
name: str,
) -> Action:
"""
Get an action by name
"""
actions = self.actions(context) if callable(self.actions) else self.actions
action = next((action for action in actions if action.name == name), None)
if action is None:
raise ActionNotFoundException(name)
return action
def execute_action(
self,
*,
context: CopilotKitContext,
name: str,
arguments: dict,
) -> Coroutine[Any, Any, ActionResultDict]:
"""
Execute an action
"""
action = self._get_action(context=context, name=name)
self._log_request_info(
title="Handling execute action request:",
data=[
("Context", context),
("Action", action.dict_repr()),
("Arguments", arguments),
],
)
try:
result = action.execute(arguments=arguments)
return result
except Exception as error:
raise ActionExecutionException(name, error) from error
def execute_agent( # pylint: disable=too-many-arguments
self,
*,
context: CopilotKitContext,
name: str,
thread_id: str,
state: dict,
config: Optional[dict] = None,
messages: List[Message],
actions: List[ActionDict],
node_name: str,
meta_events: Optional[List[MetaEvent]] = None,
) -> Any:
"""
Execute an agent
"""
agents = self.agents(context) if callable(self.agents) else self.agents
agent = next((agent for agent in agents if agent.name == name), None)
if agent is None:
raise AgentNotFoundException(name)
self._log_request_info(
title="Handling execute agent request:",
data=[
("Context", context),
("Agent", agent.dict_repr()),
("Thread ID", thread_id),
("Node Name", node_name),
("State", state),
("Config", config),
("Messages", messages),
("Actions", actions),
("MetaEvents", meta_events),
],
)
try:
return agent.execute(
thread_id=thread_id,
node_name=node_name,
state=state,
config=config,
messages=messages,
actions=actions,
meta_events=meta_events,
)
except Exception as error:
raise AgentExecutionException(name, error) from error
async def get_agent_state(
self,
*,
context: CopilotKitContext,
thread_id: str,
name: str,
):
"""
Get agent state
"""
agents = self.agents(context) if callable(self.agents) else self.agents
agent = next((agent for agent in agents if agent.name == name), None)
if agent is None:
raise AgentNotFoundException(name)
self._log_request_info(
title="Handling get agent state request:",
data=[
("Context", context),
("Agent", agent.dict_repr()),
("Thread ID", thread_id),
],
)
try:
return await agent.get_state(thread_id=thread_id)
except Exception as error:
raise AgentExecutionException(name, error) from error
def _log_request_info(self, title: str, data: List[Tuple[str, Any]]):
"""
Log request info
"""
logger.info(bold(title))
logger.info("--------------------------")
for key, value in data:
logger.info(bold(key + ":"))
logger.info(pformat(value))
logger.info("--------------------------")
# Alias for backwards compatibility
class CopilotKitSDK(CopilotKitRemoteEndpoint):
"""Deprecated: Use CopilotKitRemoteEndpoint instead. This class will be removed in a future version."""
def __init__(self, *args, **kwargs):
warnings.warn(
"CopilotKitSDK is deprecated since version 0.1.31. "
"Use CopilotKitRemoteEndpoint instead.",
DeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwargs)