chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:38:34 +08:00
commit 0549b088a4
2405 changed files with 810255 additions and 0 deletions
@@ -0,0 +1,175 @@
"""Session context implementation injected into custom tool execute functions.
One instance is created per session and shared across all custom tool invocations,
including sibling routing (tool A calling tool B without hitting the network).
"""
from __future__ import annotations
import typing as t
from composio_client import omit
from composio_client.types.tool_router.session_proxy_execute_params import Parameter
from composio_client.types.tool_router.session_execute_response import (
SessionExecuteResponse,
)
from composio_client.types.tool_router.session_proxy_execute_response import (
SessionProxyExecuteResponse,
)
from composio.client import HttpClient
from composio.core.models.custom_tool_execution import (
execute_custom_tool,
find_custom_tool,
)
from composio.core.models.custom_tool_types import (
CustomToolsMap,
InlineCustomToolsWirePayload,
)
from composio.core.models.inline_custom_tools_payload import (
inline_custom_tools_execute_experimental,
)
from composio.core.models.tools import _serialize_arguments
from composio.exceptions import ValidationError
_VALID_METHODS = frozenset({"GET", "POST", "PUT", "DELETE", "PATCH"})
_VALID_PARAM_TYPES = frozenset({"header", "query"})
def proxy_execute_impl(
client: HttpClient,
session_id: str,
*,
toolkit: str,
endpoint: str,
method: t.Literal["GET", "POST", "PUT", "DELETE", "PATCH"],
body: t.Any = None,
parameters: t.Optional[t.List[t.Dict[str, t.Any]]] = None,
) -> SessionProxyExecuteResponse:
"""Shared proxy execute implementation used by SessionContextImpl and ToolRouterSession."""
# Client-side validation (matches TS SessionProxyExecuteParamsSchema)
if not toolkit:
raise ValidationError("proxy_execute: toolkit is required")
if not endpoint:
raise ValidationError("proxy_execute: endpoint is required")
if method not in _VALID_METHODS:
raise ValidationError(
f"proxy_execute: method must be one of {sorted(_VALID_METHODS)}, got {method!r}"
)
# Transform and validate parameters
api_params: t.List[Parameter] = []
if parameters:
for i, p in enumerate(parameters):
if not isinstance(p, dict) or "name" not in p or "value" not in p:
raise ValidationError(
f"proxy_execute: parameters[{i}] must be a dict with 'name' and 'value' keys"
)
param_type = p.get("in", p.get("type", "header"))
if param_type not in _VALID_PARAM_TYPES:
raise ValidationError(
f"proxy_execute: parameters[{i}].type must be 'header' or 'query', "
f"got {param_type!r}"
)
api_params.append(
Parameter(
name=p["name"],
type=param_type, # type: ignore[typeddict-item]
value=str(p["value"]),
)
)
return client.tool_router.session.proxy_execute(
session_id=session_id,
toolkit_slug=toolkit,
endpoint=endpoint,
method=method,
body=body if body is not None else omit,
parameters=api_params if api_params else omit,
)
class SessionContextImpl:
"""Concrete implementation of SessionContext.
One instance is created per session (singleton) and shared across
all custom tool invocations. When ``custom_tools_map`` is provided,
``execute()`` checks local tools first before falling back to the
backend API (sibling routing).
"""
def __init__(
self,
client: HttpClient,
user_id: str,
session_id: str,
custom_tools_map: t.Optional[CustomToolsMap] = None,
inline_custom_tools_payload: t.Optional[InlineCustomToolsWirePayload] = None,
) -> None:
self._client = client
self._user_id = user_id
self._session_id = session_id
self._custom_tools_map = custom_tools_map
self._inline_custom_tools_payload = inline_custom_tools_payload
@property
def user_id(self) -> str:
"""The user ID for the current session."""
return self._user_id
def execute(
self,
tool_slug: str,
arguments: t.Dict[str, t.Any],
) -> SessionExecuteResponse:
"""Execute any tool from within a custom tool.
Routes to sibling local tools in-process when available,
otherwise delegates to the backend API.
Returns the same response model as ``session.execute()``.
"""
# Try local tool first (sibling routing)
entry = find_custom_tool(self._custom_tools_map, tool_slug)
if entry:
result = execute_custom_tool(entry, arguments, self)
return SessionExecuteResponse(
data=result["data"],
error=result["error"],
log_id="",
)
# Serialize any Pydantic model instances before sending to remote API
serialized = _serialize_arguments(arguments)
return self._client.tool_router.session.execute(
session_id=self._session_id,
tool_slug=tool_slug,
arguments=serialized,
experimental=inline_custom_tools_execute_experimental(
self._inline_custom_tools_payload
),
)
def proxy_execute(
self,
*,
toolkit: str,
endpoint: str,
method: t.Literal["GET", "POST", "PUT", "DELETE", "PATCH"],
body: t.Any = None,
parameters: t.Optional[t.List[t.Dict[str, t.Any]]] = None,
) -> SessionProxyExecuteResponse:
"""Proxy API calls through Composio's auth layer.
Returns the same response model as ``session.proxy_execute()``.
"""
return proxy_execute_impl(
self._client,
self._session_id,
toolkit=toolkit,
endpoint=endpoint,
method=method,
body=body,
parameters=parameters,
)