Skip to content

Commit

Permalink
Merge pull request #238 from bonk1t/fix/tool-factory
Browse files Browse the repository at this point in the history
 Fix: Closure Issue in ToolFactory.from_openapi_schema
  • Loading branch information
VRSEN authored Feb 25, 2025
2 parents 561107b + a57b908 commit 349e7b2
Showing 1 changed file with 64 additions and 41 deletions.
105 changes: 64 additions & 41 deletions agency_swarm/tools/ToolFactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,49 +149,14 @@ def from_openapi_schema(
tools = []
headers = headers or {}
headers = {k: v for k, v in headers.items() if v is not None}

for path, methods in openapi_spec["paths"].items():
for method, spec_with_ref in methods.items():

async def callback(self):
url = openapi_spec["servers"][0]["url"] + path
parameters = self.model_dump().get("parameters", {})
# replace all parameters in url
for param, value in parameters.items():
if "{" + str(param) + "}" in url:
url = url.replace(f"{{{param}}}", str(value))
parameters[param] = None
url = url.rstrip("/")
parameters = {k: v for k, v in parameters.items() if v is not None}
parameters = {**parameters, **params} if params else parameters
async with httpx.AsyncClient(
timeout=90
) as client: # Set custom read timeout to 10 seconds
if method == "get":
response = await client.get(
url, params=parameters, headers=headers
)
elif method == "post":
response = await client.post(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
elif method == "put":
response = await client.put(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
elif method == "delete":
response = await client.delete(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
return response.json()
# Use the callback factory to create a unique callback for each path/method
# This ensures each callback captures the correct path value
callback = ToolFactory._create_callback_for_path(
path, method, openapi_spec, params, headers
)

# 1. Resolve JSON references.
spec = jsonref.replace_refs(spec_with_ref)
Expand Down Expand Up @@ -253,6 +218,64 @@ async def callback(self):

return tools

@staticmethod
def _create_callback_for_path(path, method, openapi_spec, params, headers):
"""
Creates a callback function for a specific path and method.
This is a factory function that captures the current values of path and method.
Parameters:
path: The path to create the callback for.
method: The HTTP method to use.
openapi_spec: The OpenAPI specification.
params: Additional parameters to include in the request.
headers: Headers to include in the request.
Returns:
An async callback function that makes the appropriate HTTP request.
"""

async def callback(self):
url = openapi_spec["servers"][0]["url"] + path
parameters = self.model_dump().get("parameters", {})
# replace all parameters in url
for param, value in parameters.items():
if "{" + str(param) + "}" in url:
url = url.replace(f"{{{param}}}", str(value))
parameters[param] = None
url = url.rstrip("/")
parameters = {k: v for k, v in parameters.items() if v is not None}
parameters = {**parameters, **params} if params else parameters
async with httpx.AsyncClient(
timeout=90
) as client: # Set custom read timeout to 10 seconds
if method == "get":
response = await client.get(url, params=parameters, headers=headers)
elif method == "post":
response = await client.post(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
elif method == "put":
response = await client.put(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
elif method == "delete":
response = await client.delete(
url,
params=parameters,
json=self.model_dump().get("requestBody", None),
headers=headers,
)
return response.json()

return callback

@staticmethod
def from_file(file_path: str) -> Type[BaseTool]:
"""Dynamically imports a BaseTool class from a Python file within a package structure.
Expand Down

0 comments on commit 349e7b2

Please sign in to comment.