mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 06:58:59 +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:
|
if 'api_key_header_prefix' in credentials:
|
||||||
api_key_header_prefix = credentials['api_key_header_prefix']
|
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"]}'
|
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"]}'
|
credentials['api_key_value'] = f'Bearer {credentials["api_key_value"]}'
|
||||||
elif api_key_header_prefix == 'custom':
|
elif api_key_header_prefix == 'custom':
|
||||||
pass
|
pass
|
||||||
@ -184,21 +184,7 @@ class ApiTool(Tool):
|
|||||||
for name, property in properties.items():
|
for name, property in properties.items():
|
||||||
if name in parameters:
|
if name in parameters:
|
||||||
# convert type
|
# convert type
|
||||||
try:
|
body[name] = self._convert_body_property_type(property, parameters[name])
|
||||||
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]
|
|
||||||
elif name in required:
|
elif name in required:
|
||||||
raise ToolProviderCredentialValidationError(
|
raise ToolProviderCredentialValidationError(
|
||||||
f"Missing required parameter {name} in operation {self.api_bundle.operation_id}"
|
f"Missing required parameter {name} in operation {self.api_bundle.operation_id}"
|
||||||
@ -228,10 +214,6 @@ class ApiTool(Tool):
|
|||||||
elif method == 'put':
|
elif method == 'put':
|
||||||
response = ssrf_proxy.put(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
response = ssrf_proxy.put(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
||||||
elif method == 'delete':
|
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)
|
response = ssrf_proxy.delete(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, allow_redirects=True)
|
||||||
elif method == 'patch':
|
elif method == 'patch':
|
||||||
response = ssrf_proxy.patch(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
response = ssrf_proxy.patch(url, params=params, headers=headers, cookies=cookies, data=body, timeout=10, follow_redirects=True)
|
||||||
@ -243,6 +225,66 @@ class ApiTool(Tool):
|
|||||||
raise ValueError(f'Invalid http method {method}')
|
raise ValueError(f'Invalid http method {method}')
|
||||||
|
|
||||||
return response
|
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]:
|
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
|
||||||
"""
|
"""
|
||||||
|
@ -43,7 +43,7 @@ const TestApi: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
const data = {
|
const data = {
|
||||||
tool_name: toolName,
|
tool_name: toolName,
|
||||||
credentials: tempCredential,
|
credentials,
|
||||||
schema_type: customCollection.schema_type,
|
schema_type: customCollection.schema_type,
|
||||||
schema: customCollection.schema,
|
schema: customCollection.schema,
|
||||||
parameters: parametersValue,
|
parameters: parametersValue,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user