initial commit

This commit is contained in:
2026-05-11 12:36:20 +05:30
commit 384cbe8019
15377 changed files with 2360544 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
"""
This module contains the ConneryAction Tool and ConneryService.
"""
from .service import ConneryService
from .tool import ConneryAction
__all__ = ["ConneryAction", "ConneryService"]

View File

@@ -0,0 +1,32 @@
from typing import Any, List, Optional
from pydantic import BaseModel
class Validation(BaseModel):
"""Connery Action parameter validation model."""
required: Optional[bool] = None
class Parameter(BaseModel):
"""Connery Action parameter model."""
key: str
title: str
description: Optional[str] = None
type: Any
validation: Optional[Validation] = None
class Action(BaseModel):
"""Connery Action model."""
id: str
key: str
title: str
description: Optional[str] = None
type: str
inputParameters: List[Parameter]
outputParameters: List[Parameter]
pluginId: str

View File

@@ -0,0 +1,166 @@
import json
from typing import Any, Dict, List, Optional
import requests
from langchain_core.utils.env import get_from_dict_or_env
from pydantic import BaseModel, model_validator
from langchain_community.tools.connery.models import Action
from langchain_community.tools.connery.tool import ConneryAction
class ConneryService(BaseModel):
"""Service for interacting with the Connery Runner API.
It gets the list of available actions from the Connery Runner,
wraps them in ConneryAction Tools and returns them to the user.
It also provides a method for running the actions.
"""
runner_url: Optional[str] = None
api_key: Optional[str] = None
@model_validator(mode="before")
@classmethod
def validate_attributes(cls, values: Dict) -> Any:
"""
Validate the attributes of the ConneryService class.
Parameters:
values (dict): The arguments to validate.
Returns:
dict: The validated arguments.
"""
runner_url = get_from_dict_or_env(values, "runner_url", "CONNERY_RUNNER_URL")
api_key = get_from_dict_or_env(values, "api_key", "CONNERY_RUNNER_API_KEY")
if not runner_url:
raise ValueError("CONNERY_RUNNER_URL environment variable must be set.")
if not api_key:
raise ValueError("CONNERY_RUNNER_API_KEY environment variable must be set.")
values["runner_url"] = runner_url
values["api_key"] = api_key
return values
def list_actions(self) -> List[ConneryAction]:
"""
Returns the list of actions available in the Connery Runner.
Returns:
List[ConneryAction]: The list of actions available in the Connery Runner.
"""
return [
ConneryAction.create_instance(action, self)
for action in self._list_actions()
]
def get_action(self, action_id: str) -> ConneryAction:
"""
Returns the specified action available in the Connery Runner.
Parameters:
action_id (str): The ID of the action to return.
Returns:
ConneryAction: The action with the specified ID.
"""
return ConneryAction.create_instance(self._get_action(action_id), self)
def run_action(self, action_id: str, input: Dict[str, str] = {}) -> Dict[str, str]:
"""
Runs the specified Connery Action with the provided input.
Parameters:
action_id (str): The ID of the action to run.
input (Dict[str, str]): The input object expected by the action.
Returns:
Dict[str, str]: The output of the action.
"""
return self._run_action(action_id, input)
def _list_actions(self) -> List[Action]:
"""
Returns the list of actions available in the Connery Runner.
Returns:
List[Action]: The list of actions available in the Connery Runner.
"""
response = requests.get(
f"{self.runner_url}/v1/actions", headers=self._get_headers()
)
if not response.ok:
raise ValueError(
(
"Failed to list actions."
f"Status code: {response.status_code}."
f"Error message: {response.json()['error']['message']}"
)
)
return [Action(**action) for action in response.json()["data"]]
def _get_action(self, action_id: str) -> Action:
"""
Returns the specified action available in the Connery Runner.
Parameters:
action_id (str): The ID of the action to return.
Returns:
Action: The action with the specified ID.
"""
actions = self._list_actions()
action = next((action for action in actions if action.id == action_id), None)
if not action:
raise ValueError(
(
f"The action with ID {action_id} was not found in the list"
"of available actions in the Connery Runner."
)
)
return action
def _run_action(self, action_id: str, input: Dict[str, str] = {}) -> Dict[str, str]:
"""
Runs the specified Connery Action with the provided input.
Parameters:
action_id (str): The ID of the action to run.
prompt (str): This is a plain English prompt
with all the information needed to run the action.
input (Dict[str, str]): The input object expected by the action.
If provided together with the prompt,
the input takes precedence over the input specified in the prompt.
Returns:
Dict[str, str]: The output of the action.
"""
response = requests.post(
f"{self.runner_url}/v1/actions/{action_id}/run",
headers=self._get_headers(),
data=json.dumps({"input": input}),
)
if not response.ok:
raise ValueError(
(
"Failed to run action."
f"Status code: {response.status_code}."
f"Error message: {response.json()['error']['message']}"
)
)
if not response.json()["data"]["output"]:
return {}
else:
return response.json()["data"]["output"]
def _get_headers(self) -> Dict[str, str]:
"""
Returns a standard set of HTTP headers
to be used in API calls to the Connery runner.
Returns:
Dict[str, str]: The standard set of HTTP headers.
"""
return {"Content-Type": "application/json", "x-api-key": self.api_key or ""}

View File

@@ -0,0 +1,162 @@
import asyncio
from functools import partial
from typing import Any, Dict, List, Optional, Type
from langchain_core.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field, create_model, model_validator
from langchain_community.tools.connery.models import Action, Parameter
class ConneryAction(BaseTool):
"""Connery Action tool."""
name: str
description: str
args_schema: Type[BaseModel]
action: Action
connery_service: Any
def _run(
self,
run_manager: Optional[CallbackManagerForToolRun] = None,
**kwargs: Any,
) -> Dict[str, str]:
"""
Runs the Connery Action with the provided input.
Parameters:
kwargs (Dict[str, str]): The input dictionary expected by the action.
Returns:
Dict[str, str]: The output of the action.
"""
return self.connery_service.run_action(self.action.id, kwargs)
async def _arun(
self,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
**kwargs: Any,
) -> Dict[str, str]:
"""
Runs the Connery Action asynchronously with the provided input.
Parameters:
kwargs (Dict[str, str]): The input dictionary expected by the action.
Returns:
Dict[str, str]: The output of the action.
"""
func = partial(self._run, **kwargs)
return await asyncio.get_event_loop().run_in_executor(None, func)
def get_schema_json(self) -> str:
"""
Returns the JSON representation of the Connery Action Tool schema.
This is useful for debugging.
Returns:
str: The JSON representation of the Connery Action Tool schema.
"""
return self.args_schema.schema_json(indent=2)
@model_validator(mode="before")
@classmethod
def validate_attributes(cls, values: dict) -> Any:
"""
Validate the attributes of the ConneryAction class.
Parameters:
values (dict): The arguments to validate.
Returns:
dict: The validated arguments.
"""
# Import ConneryService here and check if it is an instance
# of ConneryService to avoid circular imports
from .service import ConneryService
if not isinstance(values.get("connery_service"), ConneryService):
raise ValueError(
"The attribute 'connery_service' must be an instance of ConneryService."
)
if not values.get("name"):
raise ValueError("The attribute 'name' must be set.")
if not values.get("description"):
raise ValueError("The attribute 'description' must be set.")
if not values.get("args_schema"):
raise ValueError("The attribute 'args_schema' must be set.")
if not values.get("action"):
raise ValueError("The attribute 'action' must be set.")
if not values.get("connery_service"):
raise ValueError("The attribute 'connery_service' must be set.")
return values
@classmethod
def create_instance(cls, action: Action, connery_service: Any) -> "ConneryAction":
"""
Creates a Connery Action Tool from a Connery Action.
Parameters:
action (Action): The Connery Action to wrap in a Connery Action Tool.
connery_service (ConneryService): The Connery Service
to run the Connery Action. We use Any here to avoid circular imports.
Returns:
ConneryAction: The Connery Action Tool.
"""
# Import ConneryService here and check if it is an instance
# of ConneryService to avoid circular imports
from .service import ConneryService
if not isinstance(connery_service, ConneryService):
raise ValueError(
"The connery_service must be an instance of ConneryService."
)
input_schema = cls._create_input_schema(action.inputParameters)
description = action.title + (
": " + action.description if action.description else ""
)
instance = cls(
name=action.id,
description=description,
args_schema=input_schema,
action=action,
connery_service=connery_service,
)
return instance
@classmethod
def _create_input_schema(cls, inputParameters: List[Parameter]) -> Type[BaseModel]:
"""
Creates an input schema for a Connery Action Tool
based on the input parameters of the Connery Action.
Parameters:
inputParameters: List of input parameters of the Connery Action.
Returns:
Type[BaseModel]: The input schema for the Connery Action Tool.
"""
dynamic_input_fields: Dict[str, Any] = {}
for param in inputParameters:
default = ... if param.validation and param.validation.required else None
title = param.title
description = param.title + (
": " + param.description if param.description else ""
)
type = param.type
dynamic_input_fields[param.key] = (
type,
Field(default, title=title, description=description),
)
InputModel = create_model("InputSchema", **dynamic_input_fields)
return InputModel