mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 03:29:01 +08:00
Fix/custom tool any of (#2625)
This commit is contained in:
parent
57ffecd0e5
commit
a769edbc89
@ -67,9 +67,9 @@ class ApiTool(Tool):
|
||||
|
||||
if 'api_key_header_prefix' in credentials:
|
||||
api_key_header_prefix = credentials['api_key_header_prefix']
|
||||
if api_key_header_prefix == 'basic':
|
||||
if api_key_header_prefix == 'basic' and credentials['api_key_value']:
|
||||
credentials['api_key_value'] = f'Basic {credentials["api_key_value"]}'
|
||||
elif api_key_header_prefix == 'bearer':
|
||||
elif api_key_header_prefix == 'bearer' and credentials['api_key_value']:
|
||||
credentials['api_key_value'] = f'Bearer {credentials["api_key_value"]}'
|
||||
elif api_key_header_prefix == 'custom':
|
||||
pass
|
||||
@ -184,21 +184,7 @@ class ApiTool(Tool):
|
||||
for name, property in properties.items():
|
||||
if name in parameters:
|
||||
# convert type
|
||||
try:
|
||||
value = parameters[name]
|
||||
if property['type'] == 'integer':
|
||||
value = int(value)
|
||||
elif property['type'] == 'number':
|
||||
# check if it is a float
|
||||
if '.' in value:
|
||||
value = float(value)
|
||||
else:
|
||||
value = int(value)
|
||||
elif property['type'] == 'boolean':
|
||||
value = bool(value)
|
||||
body[name] = value
|
||||
except ValueError as e:
|
||||
body[name] = parameters[name]
|
||||
body[name] = self._convert_body_property_type(property, parameters[name])
|
||||
elif name in required:
|
||||
raise ToolProviderCredentialValidationError(
|
||||
f"Missing required parameter {name} in operation {self.api_bundle.operation_id}"
|
||||
@ -228,10 +214,6 @@ class ApiTool(Tool):
|
||||
elif method == 'put':
|
||||
response = ssrf_proxy.put(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
||||
elif method == 'delete':
|
||||
"""
|
||||
request body data is unsupported for DELETE method in standard http protocol
|
||||
however, OpenAPI 3.0 supports request body data for DELETE method, so we support it here by using requests
|
||||
"""
|
||||
response = ssrf_proxy.delete(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, allow_redirects=True)
|
||||
elif method == 'patch':
|
||||
response = ssrf_proxy.patch(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
||||
@ -244,6 +226,66 @@ class ApiTool(Tool):
|
||||
|
||||
return response
|
||||
|
||||
def _convert_body_property_any_of(self, property: dict[str, Any], value: Any, any_of: list[dict[str, Any]], max_recursive=10) -> Any:
|
||||
if max_recursive <= 0:
|
||||
raise Exception("Max recursion depth reached")
|
||||
for option in any_of or []:
|
||||
try:
|
||||
if 'type' in option:
|
||||
# Attempt to convert the value based on the type.
|
||||
if option['type'] == 'integer' or option['type'] == 'int':
|
||||
return int(value)
|
||||
elif option['type'] == 'number':
|
||||
if '.' in str(value):
|
||||
return float(value)
|
||||
else:
|
||||
return int(value)
|
||||
elif option['type'] == 'string':
|
||||
return str(value)
|
||||
elif option['type'] == 'boolean':
|
||||
if str(value).lower() in ['true', '1']:
|
||||
return True
|
||||
elif str(value).lower() in ['false', '0']:
|
||||
return False
|
||||
else:
|
||||
continue # Not a boolean, try next option
|
||||
elif option['type'] == 'null' and not value:
|
||||
return None
|
||||
else:
|
||||
continue # Unsupported type, try next option
|
||||
elif 'anyOf' in option and isinstance(option['anyOf'], list):
|
||||
# Recursive call to handle nested anyOf
|
||||
return self._convert_body_property_any_of(property, value, option['anyOf'], max_recursive - 1)
|
||||
except ValueError:
|
||||
continue # Conversion failed, try next option
|
||||
# If no option succeeded, you might want to return the value as is or raise an error
|
||||
return value # or raise ValueError(f"Cannot convert value '{value}' to any specified type in anyOf")
|
||||
|
||||
def _convert_body_property_type(self, property: dict[str, Any], value: Any) -> Any:
|
||||
try:
|
||||
if 'type' in property:
|
||||
if property['type'] == 'integer' or property['type'] == 'int':
|
||||
return int(value)
|
||||
elif property['type'] == 'number':
|
||||
# check if it is a float
|
||||
if '.' in value:
|
||||
return float(value)
|
||||
else:
|
||||
return int(value)
|
||||
elif property['type'] == 'string':
|
||||
return str(value)
|
||||
elif property['type'] == 'boolean':
|
||||
return bool(value)
|
||||
elif property['type'] == 'null':
|
||||
if value is None:
|
||||
return None
|
||||
else:
|
||||
raise ValueError(f"Invalid type {property['type']} for property {property}")
|
||||
elif 'anyOf' in property and isinstance(property['anyOf'], list):
|
||||
return self._convert_body_property_any_of(property, value, property['anyOf'])
|
||||
except ValueError as e:
|
||||
return value
|
||||
|
||||
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
|
||||
"""
|
||||
invoke http request
|
||||
|
@ -43,7 +43,7 @@ const TestApi: FC<Props> = ({
|
||||
}
|
||||
const data = {
|
||||
tool_name: toolName,
|
||||
credentials: tempCredential,
|
||||
credentials,
|
||||
schema_type: customCollection.schema_type,
|
||||
schema: customCollection.schema,
|
||||
parameters: parametersValue,
|
||||
|
Loading…
x
Reference in New Issue
Block a user