|
|
|
@@ -1,10 +1,12 @@ |
|
|
|
|
|
|
|
import re |
|
|
|
import uuid |
|
|
|
from json import dumps as json_dumps |
|
|
|
from json import loads as json_loads |
|
|
|
from json.decoder import JSONDecodeError |
|
|
|
|
|
|
|
from requests import get |
|
|
|
from yaml import FullLoader, load |
|
|
|
from yaml import YAMLError, safe_load |
|
|
|
|
|
|
|
from core.tools.entities.common_entities import I18nObject |
|
|
|
from core.tools.entities.tool_bundle import ApiBasedToolBundle |
|
|
|
@@ -184,27 +186,11 @@ class ApiBasedToolSchemaParser: |
|
|
|
warning = warning if warning is not None else {} |
|
|
|
extra_info = extra_info if extra_info is not None else {} |
|
|
|
|
|
|
|
openapi: dict = load(yaml, Loader=FullLoader) |
|
|
|
openapi: dict = safe_load(yaml) |
|
|
|
if openapi is None: |
|
|
|
raise ToolApiSchemaError('Invalid openapi yaml.') |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi, extra_info=extra_info, warning=warning) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def parse_openapi_json_to_tool_bundle(json: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]: |
|
|
|
""" |
|
|
|
parse openapi yaml to tool bundle |
|
|
|
|
|
|
|
:param yaml: the yaml string |
|
|
|
:return: the tool bundle |
|
|
|
""" |
|
|
|
warning = warning if warning is not None else {} |
|
|
|
extra_info = extra_info if extra_info is not None else {} |
|
|
|
|
|
|
|
openapi: dict = json_loads(json) |
|
|
|
if openapi is None: |
|
|
|
raise ToolApiSchemaError('Invalid openapi json.') |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi, extra_info=extra_info, warning=warning) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def parse_swagger_to_openapi(swagger: dict, extra_info: dict = None, warning: dict = None) -> dict: |
|
|
|
""" |
|
|
|
@@ -271,38 +257,6 @@ class ApiBasedToolSchemaParser: |
|
|
|
|
|
|
|
return openapi |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def parse_swagger_yaml_to_tool_bundle(yaml: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]: |
|
|
|
""" |
|
|
|
parse swagger yaml to tool bundle |
|
|
|
|
|
|
|
:param yaml: the yaml string |
|
|
|
:return: the tool bundle |
|
|
|
""" |
|
|
|
warning = warning if warning is not None else {} |
|
|
|
extra_info = extra_info if extra_info is not None else {} |
|
|
|
|
|
|
|
swagger: dict = load(yaml, Loader=FullLoader) |
|
|
|
|
|
|
|
openapi = ApiBasedToolSchemaParser.parse_swagger_to_openapi(swagger, extra_info=extra_info, warning=warning) |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi, extra_info=extra_info, warning=warning) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def parse_swagger_json_to_tool_bundle(json: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]: |
|
|
|
""" |
|
|
|
parse swagger yaml to tool bundle |
|
|
|
|
|
|
|
:param yaml: the yaml string |
|
|
|
:return: the tool bundle |
|
|
|
""" |
|
|
|
warning = warning if warning is not None else {} |
|
|
|
extra_info = extra_info if extra_info is not None else {} |
|
|
|
|
|
|
|
swagger: dict = json_loads(json) |
|
|
|
|
|
|
|
openapi = ApiBasedToolSchemaParser.parse_swagger_to_openapi(swagger, extra_info=extra_info, warning=warning) |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi, extra_info=extra_info, warning=warning) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def parse_openai_plugin_json_to_tool_bundle(json: str, extra_info: dict = None, warning: dict = None) -> list[ApiBasedToolBundle]: |
|
|
|
""" |
|
|
|
@@ -346,40 +300,50 @@ class ApiBasedToolSchemaParser: |
|
|
|
warning = warning if warning is not None else {} |
|
|
|
extra_info = extra_info if extra_info is not None else {} |
|
|
|
|
|
|
|
json_possible = False |
|
|
|
content = content.strip() |
|
|
|
loaded_content = None |
|
|
|
json_error = None |
|
|
|
yaml_error = None |
|
|
|
|
|
|
|
try: |
|
|
|
loaded_content = json_loads(content) |
|
|
|
except JSONDecodeError as e: |
|
|
|
json_error = e |
|
|
|
|
|
|
|
if content.startswith('{') and content.endswith('}'): |
|
|
|
json_possible = True |
|
|
|
|
|
|
|
if json_possible: |
|
|
|
try: |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_json_to_tool_bundle(content, extra_info=extra_info, warning=warning), \ |
|
|
|
ApiProviderSchemaType.OPENAPI.value |
|
|
|
except: |
|
|
|
pass |
|
|
|
|
|
|
|
try: |
|
|
|
return ApiBasedToolSchemaParser.parse_swagger_json_to_tool_bundle(content, extra_info=extra_info, warning=warning), \ |
|
|
|
ApiProviderSchemaType.SWAGGER.value |
|
|
|
except: |
|
|
|
pass |
|
|
|
try: |
|
|
|
return ApiBasedToolSchemaParser.parse_openai_plugin_json_to_tool_bundle(content, extra_info=extra_info, warning=warning), \ |
|
|
|
ApiProviderSchemaType.OPENAI_PLUGIN.value |
|
|
|
except: |
|
|
|
pass |
|
|
|
else: |
|
|
|
try: |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_yaml_to_tool_bundle(content, extra_info=extra_info, warning=warning), \ |
|
|
|
ApiProviderSchemaType.OPENAPI.value |
|
|
|
except: |
|
|
|
pass |
|
|
|
|
|
|
|
if loaded_content is None: |
|
|
|
try: |
|
|
|
return ApiBasedToolSchemaParser.parse_swagger_yaml_to_tool_bundle(content, extra_info=extra_info, warning=warning), \ |
|
|
|
ApiProviderSchemaType.SWAGGER.value |
|
|
|
except: |
|
|
|
pass |
|
|
|
loaded_content = safe_load(content) |
|
|
|
except YAMLError as e: |
|
|
|
yaml_error = e |
|
|
|
if loaded_content is None: |
|
|
|
raise ToolApiSchemaError(f'Invalid api schema, schema is neither json nor yaml. json error: {str(json_error)}, yaml error: {str(yaml_error)}') |
|
|
|
|
|
|
|
swagger_error = None |
|
|
|
openapi_error = None |
|
|
|
openapi_plugin_error = None |
|
|
|
schema_type = None |
|
|
|
|
|
|
|
try: |
|
|
|
openapi = ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(loaded_content, extra_info=extra_info, warning=warning) |
|
|
|
schema_type = ApiProviderSchemaType.OPENAPI.value |
|
|
|
return openapi, schema_type |
|
|
|
except ToolApiSchemaError as e: |
|
|
|
openapi_error = e |
|
|
|
|
|
|
|
# openai parse error, fallback to swagger |
|
|
|
try: |
|
|
|
converted_swagger = ApiBasedToolSchemaParser.parse_swagger_to_openapi(loaded_content, extra_info=extra_info, warning=warning) |
|
|
|
schema_type = ApiProviderSchemaType.SWAGGER.value |
|
|
|
return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(converted_swagger, extra_info=extra_info, warning=warning), schema_type |
|
|
|
except ToolApiSchemaError as e: |
|
|
|
swagger_error = e |
|
|
|
|
|
|
|
# swagger parse error, fallback to openai plugin |
|
|
|
try: |
|
|
|
openapi_plugin = ApiBasedToolSchemaParser.parse_openai_plugin_json_to_tool_bundle(json_dumps(loaded_content), extra_info=extra_info, warning=warning) |
|
|
|
return openapi_plugin, ApiProviderSchemaType.OPENAI_PLUGIN.value |
|
|
|
except ToolNotSupportedError as e: |
|
|
|
# maybe it's not plugin at all |
|
|
|
openapi_plugin_error = e |
|
|
|
|
|
|
|
raise ToolApiSchemaError('Invalid api schema.') |
|
|
|
raise ToolApiSchemaError(f'Invalid api schema, openapi error: {str(openapi_error)}, swagger error: {str(swagger_error)}, openapi plugin error: {str(openapi_plugin_error)}') |