alita-sdk 0.3.257__py3-none-any.whl → 0.3.562__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- alita_sdk/cli/__init__.py +10 -0
- alita_sdk/cli/__main__.py +17 -0
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +155 -0
- alita_sdk/cli/agent_loader.py +215 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3601 -0
- alita_sdk/cli/callbacks.py +647 -0
- alita_sdk/cli/cli.py +168 -0
- alita_sdk/cli/config.py +306 -0
- alita_sdk/cli/context/__init__.py +30 -0
- alita_sdk/cli/context/cleanup.py +198 -0
- alita_sdk/cli/context/manager.py +731 -0
- alita_sdk/cli/context/message.py +285 -0
- alita_sdk/cli/context/strategies.py +289 -0
- alita_sdk/cli/context/token_estimation.py +127 -0
- alita_sdk/cli/formatting.py +182 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/mcp_loader.py +315 -0
- alita_sdk/cli/toolkit.py +327 -0
- alita_sdk/cli/toolkit_loader.py +85 -0
- alita_sdk/cli/tools/__init__.py +43 -0
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +1751 -0
- alita_sdk/cli/tools/planning.py +389 -0
- alita_sdk/cli/tools/terminal.py +414 -0
- alita_sdk/community/__init__.py +72 -12
- alita_sdk/community/inventory/__init__.py +236 -0
- alita_sdk/community/inventory/config.py +257 -0
- alita_sdk/community/inventory/enrichment.py +2137 -0
- alita_sdk/community/inventory/extractors.py +1469 -0
- alita_sdk/community/inventory/ingestion.py +3172 -0
- alita_sdk/community/inventory/knowledge_graph.py +1457 -0
- alita_sdk/community/inventory/parsers/__init__.py +218 -0
- alita_sdk/community/inventory/parsers/base.py +295 -0
- alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
- alita_sdk/community/inventory/parsers/go_parser.py +851 -0
- alita_sdk/community/inventory/parsers/html_parser.py +389 -0
- alita_sdk/community/inventory/parsers/java_parser.py +593 -0
- alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
- alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
- alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
- alita_sdk/community/inventory/parsers/python_parser.py +604 -0
- alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
- alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
- alita_sdk/community/inventory/parsers/text_parser.py +322 -0
- alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
- alita_sdk/community/inventory/patterns/__init__.py +61 -0
- alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
- alita_sdk/community/inventory/patterns/loader.py +348 -0
- alita_sdk/community/inventory/patterns/registry.py +198 -0
- alita_sdk/community/inventory/presets.py +535 -0
- alita_sdk/community/inventory/retrieval.py +1403 -0
- alita_sdk/community/inventory/toolkit.py +173 -0
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/community/inventory/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +11 -0
- alita_sdk/configurations/ado.py +148 -2
- alita_sdk/configurations/azure_search.py +1 -1
- alita_sdk/configurations/bigquery.py +1 -1
- alita_sdk/configurations/bitbucket.py +94 -2
- alita_sdk/configurations/browser.py +18 -0
- alita_sdk/configurations/carrier.py +19 -0
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/delta_lake.py +1 -1
- alita_sdk/configurations/figma.py +76 -5
- alita_sdk/configurations/github.py +65 -1
- alita_sdk/configurations/gitlab.py +81 -0
- alita_sdk/configurations/google_places.py +17 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/openapi.py +111 -0
- alita_sdk/configurations/postman.py +1 -1
- alita_sdk/configurations/qtest.py +72 -3
- alita_sdk/configurations/report_portal.py +115 -0
- alita_sdk/configurations/salesforce.py +19 -0
- alita_sdk/configurations/service_now.py +1 -12
- alita_sdk/configurations/sharepoint.py +167 -0
- alita_sdk/configurations/sonar.py +18 -0
- alita_sdk/configurations/sql.py +20 -0
- alita_sdk/configurations/testio.py +101 -0
- alita_sdk/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +94 -1
- alita_sdk/configurations/zephyr_enterprise.py +94 -1
- alita_sdk/configurations/zephyr_essential.py +95 -0
- alita_sdk/runtime/clients/artifact.py +21 -4
- alita_sdk/runtime/clients/client.py +458 -67
- alita_sdk/runtime/clients/mcp_discovery.py +342 -0
- alita_sdk/runtime/clients/mcp_manager.py +262 -0
- alita_sdk/runtime/clients/sandbox_client.py +352 -0
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +183 -43
- alita_sdk/runtime/langchain/constants.py +647 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +209 -31
- alita_sdk/runtime/langchain/document_loaders/AlitaImageLoader.py +1 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaMarkdownLoader.py +66 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaPDFLoader.py +79 -10
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +52 -15
- alita_sdk/runtime/langchain/document_loaders/AlitaPythonLoader.py +9 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -4
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +15 -2
- alita_sdk/runtime/langchain/document_loaders/ImageParser.py +30 -0
- alita_sdk/runtime/langchain/document_loaders/constants.py +189 -41
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
- alita_sdk/runtime/langchain/langraph_agent.py +407 -92
- alita_sdk/runtime/langchain/utils.py +102 -8
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- alita_sdk/runtime/skills/__init__.py +91 -0
- alita_sdk/runtime/skills/callbacks.py +498 -0
- alita_sdk/runtime/skills/discovery.py +540 -0
- alita_sdk/runtime/skills/executor.py +610 -0
- alita_sdk/runtime/skills/input_builder.py +371 -0
- alita_sdk/runtime/skills/models.py +330 -0
- alita_sdk/runtime/skills/registry.py +355 -0
- alita_sdk/runtime/skills/skill_runner.py +330 -0
- alita_sdk/runtime/toolkits/__init__.py +28 -0
- alita_sdk/runtime/toolkits/application.py +14 -4
- alita_sdk/runtime/toolkits/artifact.py +24 -9
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +780 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +11 -6
- alita_sdk/runtime/toolkits/tools.py +314 -70
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +24 -0
- alita_sdk/runtime/tools/application.py +16 -4
- alita_sdk/runtime/tools/artifact.py +367 -33
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +100 -4
- alita_sdk/runtime/tools/graph.py +81 -0
- alita_sdk/runtime/tools/image_generation.py +218 -0
- alita_sdk/runtime/tools/llm.py +1013 -177
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
- alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
- alita_sdk/runtime/tools/mcp_server_tool.py +3 -1
- alita_sdk/runtime/tools/planning/__init__.py +36 -0
- alita_sdk/runtime/tools/planning/models.py +246 -0
- alita_sdk/runtime/tools/planning/wrapper.py +607 -0
- alita_sdk/runtime/tools/router.py +2 -1
- alita_sdk/runtime/tools/sandbox.py +375 -0
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +69 -65
- alita_sdk/runtime/tools/vectorstore_base.py +163 -90
- alita_sdk/runtime/utils/AlitaCallback.py +137 -21
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +361 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/streamlit.py +41 -14
- alita_sdk/runtime/utils/toolkit_utils.py +28 -9
- alita_sdk/runtime/utils/utils.py +48 -0
- alita_sdk/tools/__init__.py +135 -37
- alita_sdk/tools/ado/__init__.py +2 -2
- alita_sdk/tools/ado/repos/__init__.py +15 -19
- alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
- alita_sdk/tools/ado/test_plan/__init__.py +26 -8
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
- alita_sdk/tools/ado/wiki/__init__.py +27 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
- alita_sdk/tools/ado/work_item/__init__.py +27 -12
- alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +12 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +14 -11
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +13 -8
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +454 -110
- alita_sdk/tools/bitbucket/__init__.py +27 -19
- alita_sdk/tools/bitbucket/api_wrapper.py +285 -27
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
- alita_sdk/tools/browser/__init__.py +41 -16
- alita_sdk/tools/browser/crawler.py +3 -1
- alita_sdk/tools/browser/utils.py +15 -6
- alita_sdk/tools/carrier/__init__.py +18 -17
- alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
- alita_sdk/tools/carrier/excel_reporter.py +8 -4
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/codeparser.py +1 -1
- alita_sdk/tools/chunkers/sematic/json_chunker.py +2 -1
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
- alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
- alita_sdk/tools/chunkers/universal_chunker.py +270 -0
- alita_sdk/tools/cloud/aws/__init__.py +11 -7
- alita_sdk/tools/cloud/azure/__init__.py +11 -7
- alita_sdk/tools/cloud/gcp/__init__.py +11 -7
- alita_sdk/tools/cloud/k8s/__init__.py +11 -7
- alita_sdk/tools/code/linter/__init__.py +9 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +20 -13
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +21 -14
- alita_sdk/tools/confluence/api_wrapper.py +197 -58
- alita_sdk/tools/confluence/loader.py +14 -2
- alita_sdk/tools/custom_open_api/__init__.py +11 -5
- alita_sdk/tools/elastic/__init__.py +10 -8
- alita_sdk/tools/elitea_base.py +546 -64
- alita_sdk/tools/figma/__init__.py +11 -8
- alita_sdk/tools/figma/api_wrapper.py +352 -153
- alita_sdk/tools/github/__init__.py +17 -17
- alita_sdk/tools/github/api_wrapper.py +9 -26
- alita_sdk/tools/github/github_client.py +81 -12
- alita_sdk/tools/github/schemas.py +2 -1
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/gitlab/__init__.py +18 -13
- alita_sdk/tools/gitlab/api_wrapper.py +224 -80
- alita_sdk/tools/gitlab_org/__init__.py +13 -10
- alita_sdk/tools/google/bigquery/__init__.py +13 -13
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +20 -11
- alita_sdk/tools/jira/__init__.py +21 -11
- alita_sdk/tools/jira/api_wrapper.py +315 -168
- alita_sdk/tools/keycloak/__init__.py +10 -8
- alita_sdk/tools/localgit/__init__.py +8 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +38 -14
- alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
- alita_sdk/tools/ocr/__init__.py +10 -8
- alita_sdk/tools/openapi/__init__.py +281 -108
- alita_sdk/tools/openapi/api_wrapper.py +883 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +18 -11
- alita_sdk/tools/pandas/api_wrapper.py +40 -45
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +10 -11
- alita_sdk/tools/postman/api_wrapper.py +19 -8
- alita_sdk/tools/postman/postman_analysis.py +8 -1
- alita_sdk/tools/pptx/__init__.py +10 -10
- alita_sdk/tools/qtest/__init__.py +21 -14
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +12 -10
- alita_sdk/tools/report_portal/__init__.py +22 -16
- alita_sdk/tools/salesforce/__init__.py +21 -16
- alita_sdk/tools/servicenow/__init__.py +20 -16
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +16 -14
- alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +11 -7
- alita_sdk/tools/sql/__init__.py +21 -19
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +20 -13
- alita_sdk/tools/testrail/__init__.py +12 -11
- alita_sdk/tools/testrail/api_wrapper.py +214 -46
- alita_sdk/tools/utils/__init__.py +28 -4
- alita_sdk/tools/utils/content_parser.py +182 -62
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
- alita_sdk/tools/xray/__init__.py +17 -14
- alita_sdk/tools/xray/api_wrapper.py +58 -113
- alita_sdk/tools/yagmail/__init__.py +8 -3
- alita_sdk/tools/zephyr/__init__.py +11 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +15 -9
- alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
- alita_sdk/tools/zephyr_essential/__init__.py +15 -10
- alita_sdk/tools/zephyr_essential/api_wrapper.py +297 -54
- alita_sdk/tools/zephyr_essential/client.py +6 -4
- alita_sdk/tools/zephyr_scale/__init__.py +12 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
- alita_sdk/tools/zephyr_squad/__init__.py +11 -7
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/METADATA +184 -37
- alita_sdk-0.3.562.dist-info/RECORD +450 -0
- alita_sdk-0.3.562.dist-info/entry_points.txt +2 -0
- alita_sdk/tools/bitbucket/tools.py +0 -304
- alita_sdk-0.3.257.dist-info/RECORD +0 -343
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/top_level.txt +0 -0
|
@@ -1,127 +1,300 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
|
-
import
|
|
3
|
-
import logging
|
|
4
|
-
from typing import List, Any, Optional, Dict
|
|
5
|
-
from langchain_core.tools import BaseTool, BaseToolkit, ToolException
|
|
6
|
-
from requests_openapi import Operation, Client, Server
|
|
4
|
+
from typing import Any, Dict, List, Optional
|
|
7
5
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
6
|
+
from langchain_core.tools import BaseTool, BaseToolkit
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field, create_model
|
|
8
|
+
import yaml
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
from .api_wrapper import _get_base_url_from_spec, build_wrapper
|
|
11
|
+
from .tool import OpenApiAction
|
|
12
|
+
from ..elitea_base import filter_missconfigured_index_tools
|
|
13
|
+
from ...configurations.openapi import OpenApiConfiguration
|
|
12
14
|
|
|
13
|
-
name =
|
|
15
|
+
name = 'openapi'
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
headers['Authorization'] = f'Bearer {auth_key}'
|
|
23
|
-
if auth_type.lower() == 'basic':
|
|
24
|
-
headers['Authorization'] = f'Basic {auth_key}'
|
|
25
|
-
if auth_type.lower() == 'custom':
|
|
26
|
-
headers[
|
|
27
|
-
tool["settings"]["authentication"]["settings"]["custom_header_name"]] = f'{auth_key}'
|
|
17
|
+
|
|
18
|
+
def get_toolkit(tool) -> BaseToolkit:
|
|
19
|
+
settings = tool.get('settings', {}) or {}
|
|
20
|
+
# Extract selected_tools separately to avoid duplicate keyword argument when unpacking **settings
|
|
21
|
+
selected_tools = settings.get('selected_tools', [])
|
|
22
|
+
# Filter out selected_tools from settings to prevent "got multiple values for keyword argument"
|
|
23
|
+
filtered_settings = {k: v for k, v in settings.items() if k != 'selected_tools'}
|
|
28
24
|
return AlitaOpenAPIToolkit.get_toolkit(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def create_api_tool(name: str, op: Operation):
|
|
35
|
-
fields = {}
|
|
36
|
-
headers = {}
|
|
37
|
-
headers_descriptions = []
|
|
38
|
-
|
|
39
|
-
for parameter in op.spec.parameters:
|
|
40
|
-
if "header" in parameter.param_in:
|
|
41
|
-
headers[parameter.name] = parameter.param_schema.default
|
|
42
|
-
headers_descriptions.append(f"Header: {parameter.name}. Description: {parameter.description}.")
|
|
43
|
-
continue
|
|
44
|
-
fields[parameter.name] = (str, Field(default=parameter.param_schema.default,
|
|
45
|
-
description=parameter.description))
|
|
46
|
-
|
|
47
|
-
# add headers
|
|
48
|
-
if headers:
|
|
49
|
-
fields['headers'] = (Optional[dict], Field(default = headers, description="The dict that represents headers for request:\n" + '\n'.join(headers_descriptions)))
|
|
50
|
-
|
|
51
|
-
if op.spec.requestBody:
|
|
52
|
-
fields['json'] = (Optional[str], Field(default = None, description="JSON request body provided as a string"))
|
|
53
|
-
|
|
54
|
-
op.server = Server.from_openapi_server(op.server) # patch this
|
|
55
|
-
op.server.get_url = partial(Server.get_url, op.server)
|
|
56
|
-
op.server.set_url = partial(Server.set_url, op.server)
|
|
57
|
-
return ApiTool(
|
|
58
|
-
name=name,
|
|
59
|
-
description=op.spec.description if op.spec.description else op.spec.summary,
|
|
60
|
-
args_schema=create_model(
|
|
61
|
-
'request_params',
|
|
62
|
-
regexp = (Optional[str], Field(description="Regular expression used to remove from final output if any", default=None)),
|
|
63
|
-
**fields),
|
|
64
|
-
callable=op
|
|
25
|
+
selected_tools=selected_tools,
|
|
26
|
+
toolkit_name=tool.get('toolkit_name'),
|
|
27
|
+
**filtered_settings,
|
|
65
28
|
)
|
|
66
29
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
30
|
+
|
|
31
|
+
def get_tools(tool):
|
|
32
|
+
return get_toolkit(tool).get_tools()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_toolkit_available_tools(settings: dict) -> dict:
|
|
36
|
+
"""Return instance-dependent tool list + per-tool args JSON schemas.
|
|
37
|
+
|
|
38
|
+
This is used by backend services when the UI needs spec-derived tool names
|
|
39
|
+
and input schemas (one tool per operationId). It must be JSON-serializable.
|
|
40
|
+
"""
|
|
41
|
+
if not isinstance(settings, dict):
|
|
42
|
+
settings = {}
|
|
43
|
+
|
|
44
|
+
# Extract and merge openapi_configuration if present (same pattern as get_toolkit)
|
|
45
|
+
openapi_configuration = settings.get('openapi_configuration') or {}
|
|
46
|
+
if hasattr(openapi_configuration, 'model_dump'):
|
|
47
|
+
openapi_configuration = openapi_configuration.model_dump(mode='json')
|
|
48
|
+
if not isinstance(openapi_configuration, dict):
|
|
49
|
+
openapi_configuration = {}
|
|
50
|
+
|
|
51
|
+
# Merge settings with openapi_configuration so api_key, auth_type etc. are at root level
|
|
52
|
+
merged_settings: Dict[str, Any] = {
|
|
53
|
+
**settings,
|
|
54
|
+
**openapi_configuration,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
spec = merged_settings.get('spec') or merged_settings.get('schema_settings') or merged_settings.get('openapi_spec')
|
|
58
|
+
base_url_override = merged_settings.get('base_url') or merged_settings.get('base_url_override')
|
|
59
|
+
|
|
60
|
+
if not spec or not isinstance(spec, (str, dict)):
|
|
61
|
+
return {"tools": [], "args_schemas": {}, "error": "OpenAPI spec is missing"}
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
headers = _build_headers_from_settings(merged_settings)
|
|
65
|
+
api_wrapper = build_wrapper(
|
|
66
|
+
openapi_spec=spec,
|
|
67
|
+
base_headers=headers,
|
|
68
|
+
base_url_override=base_url_override,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
tool_defs = api_wrapper.get_available_tools(selected_tools=None)
|
|
72
|
+
|
|
73
|
+
tools = []
|
|
74
|
+
args_schemas = {}
|
|
75
|
+
|
|
76
|
+
for tool_def in tool_defs:
|
|
77
|
+
name_val = tool_def.get('name')
|
|
78
|
+
if not isinstance(name_val, str) or not name_val:
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
desc_val = tool_def.get('description')
|
|
82
|
+
if not isinstance(desc_val, str):
|
|
83
|
+
desc_val = ''
|
|
84
|
+
|
|
85
|
+
tools.append({"name": name_val, "description": desc_val})
|
|
86
|
+
|
|
87
|
+
args_schema = tool_def.get('args_schema')
|
|
88
|
+
if args_schema is None:
|
|
89
|
+
args_schemas[name_val] = {"type": "object", "properties": {}, "required": []}
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
if hasattr(args_schema, 'model_json_schema'):
|
|
94
|
+
args_schemas[name_val] = args_schema.model_json_schema()
|
|
95
|
+
elif hasattr(args_schema, 'schema'):
|
|
96
|
+
args_schemas[name_val] = args_schema.schema()
|
|
97
|
+
else:
|
|
98
|
+
args_schemas[name_val] = {"type": "object", "properties": {}, "required": []}
|
|
99
|
+
except Exception:
|
|
100
|
+
args_schemas[name_val] = {"type": "object", "properties": {}, "required": []}
|
|
101
|
+
|
|
102
|
+
# Ensure stable JSON-serializability.
|
|
85
103
|
try:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
104
|
+
json.dumps({"tools": tools, "args_schemas": args_schemas})
|
|
105
|
+
except Exception:
|
|
106
|
+
return {"tools": tools, "args_schemas": {}}
|
|
107
|
+
|
|
108
|
+
return {"tools": tools, "args_schemas": args_schemas}
|
|
109
|
+
|
|
110
|
+
except Exception as e: # pylint: disable=W0718
|
|
111
|
+
return {"tools": [], "args_schemas": {}, "error": str(e)}
|
|
90
112
|
|
|
91
113
|
class AlitaOpenAPIToolkit(BaseToolkit):
|
|
92
114
|
request_session: Any #: :meta private:
|
|
93
115
|
tools: List[BaseTool] = []
|
|
94
116
|
|
|
117
|
+
@staticmethod
|
|
118
|
+
def toolkit_config_schema() -> BaseModel:
|
|
119
|
+
# OpenAPI tool names + per-tool args schemas depend on the user-provided spec,
|
|
120
|
+
# so `selected_tools` cannot be an enum here (unlike most toolkits).
|
|
121
|
+
|
|
122
|
+
model = create_model(
|
|
123
|
+
name,
|
|
124
|
+
__config__=ConfigDict(
|
|
125
|
+
extra='ignore',
|
|
126
|
+
json_schema_extra={
|
|
127
|
+
'metadata': {
|
|
128
|
+
'label': 'OpenAPI',
|
|
129
|
+
'icon_url': 'openapi.svg',
|
|
130
|
+
'categories': ['integrations'],
|
|
131
|
+
'extra_categories': ['api', 'openapi', 'swagger'],
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
openapi_configuration=(
|
|
136
|
+
OpenApiConfiguration,
|
|
137
|
+
Field(
|
|
138
|
+
description='OpenAPI credentials configuration',
|
|
139
|
+
json_schema_extra={'configuration_types': ['openapi']},
|
|
140
|
+
),
|
|
141
|
+
),
|
|
142
|
+
base_url=(
|
|
143
|
+
Optional[str],
|
|
144
|
+
Field(
|
|
145
|
+
default=None,
|
|
146
|
+
description=(
|
|
147
|
+
"Optional base URL override (absolute, starting with http:// or https://). "
|
|
148
|
+
"Use this when your OpenAPI spec has no `servers` entry, or when `servers[0].url` "
|
|
149
|
+
"is not absolute (e.g. '/api/v3'). Example: 'https://petstore3.swagger.io'."
|
|
150
|
+
),
|
|
151
|
+
),
|
|
152
|
+
),
|
|
153
|
+
spec=(
|
|
154
|
+
str,
|
|
155
|
+
Field(
|
|
156
|
+
description=(
|
|
157
|
+
'OpenAPI specification (URL or raw JSON/YAML text). '
|
|
158
|
+
'Used to generate per-operation tools (one tool per operationId).'
|
|
159
|
+
),
|
|
160
|
+
json_schema_extra={'ui_component': 'openapi_spec'},
|
|
161
|
+
),
|
|
162
|
+
),
|
|
163
|
+
selected_tools=(
|
|
164
|
+
List[str],
|
|
165
|
+
Field(
|
|
166
|
+
default=[],
|
|
167
|
+
description='Optional list of operationIds to enable. If empty, all operations are enabled.',
|
|
168
|
+
json_schema_extra={'args_schemas': {}},
|
|
169
|
+
),
|
|
170
|
+
),
|
|
171
|
+
)
|
|
172
|
+
return model
|
|
173
|
+
|
|
95
174
|
@classmethod
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
-
c = Client()
|
|
106
|
-
c.load_spec(openapi_spec)
|
|
107
|
-
if headers:
|
|
108
|
-
c.requestor.headers.update(headers)
|
|
109
|
-
tools = []
|
|
110
|
-
for i in tools_set:
|
|
175
|
+
@filter_missconfigured_index_tools
|
|
176
|
+
def get_toolkit(
|
|
177
|
+
cls,
|
|
178
|
+
selected_tools: list[str] | None = None,
|
|
179
|
+
toolkit_name: Optional[str] = None,
|
|
180
|
+
**kwargs,
|
|
181
|
+
):
|
|
182
|
+
if selected_tools is None:
|
|
183
|
+
selected_tools = []
|
|
111
184
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
185
|
+
tool_names = _coerce_selected_tool_names(selected_tools)
|
|
186
|
+
|
|
187
|
+
openapi_configuration = kwargs.get('openapi_configuration') or {}
|
|
188
|
+
if hasattr(openapi_configuration, 'model_dump'):
|
|
189
|
+
openapi_configuration = openapi_configuration.model_dump(mode='json')
|
|
190
|
+
if not isinstance(openapi_configuration, dict):
|
|
191
|
+
openapi_configuration = {}
|
|
192
|
+
|
|
193
|
+
merged_settings: Dict[str, Any] = {
|
|
194
|
+
**kwargs,
|
|
195
|
+
**openapi_configuration,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
openapi_spec = merged_settings.get('spec') or merged_settings.get('schema_settings') or merged_settings.get('openapi_spec')
|
|
199
|
+
base_url_override = merged_settings.get('base_url') or merged_settings.get('base_url_override')
|
|
200
|
+
headers = _build_headers_from_settings(merged_settings)
|
|
201
|
+
|
|
202
|
+
api_wrapper = build_wrapper(
|
|
203
|
+
openapi_spec=openapi_spec,
|
|
204
|
+
base_headers=headers,
|
|
205
|
+
base_url_override=base_url_override,
|
|
206
|
+
)
|
|
207
|
+
base_url = _get_base_url_from_spec(api_wrapper.spec)
|
|
208
|
+
|
|
209
|
+
tools: List[BaseTool] = []
|
|
210
|
+
for tool_def in api_wrapper.get_available_tools(selected_tools=tool_names):
|
|
211
|
+
description = tool_def.get('description') or ''
|
|
212
|
+
if toolkit_name:
|
|
213
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
214
|
+
if base_url:
|
|
215
|
+
description = f"{description}\nBase URL: {base_url}"
|
|
216
|
+
description = description[:1000]
|
|
217
|
+
|
|
218
|
+
tools.append(
|
|
219
|
+
OpenApiAction(
|
|
220
|
+
api_wrapper=api_wrapper,
|
|
221
|
+
name=tool_def['name'],
|
|
222
|
+
description=description,
|
|
223
|
+
args_schema=tool_def.get('args_schema'),
|
|
224
|
+
metadata={"toolkit_name": toolkit_name} if toolkit_name else {},
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
return cls(request_session=api_wrapper, tools=tools)
|
|
125
229
|
|
|
126
230
|
def get_tools(self):
|
|
127
231
|
return self.tools
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _coerce_selected_tool_names(selected_tools: Any) -> list[str]:
|
|
235
|
+
if not selected_tools:
|
|
236
|
+
return []
|
|
237
|
+
|
|
238
|
+
if isinstance(selected_tools, list):
|
|
239
|
+
tool_names: List[str] = []
|
|
240
|
+
for item in selected_tools:
|
|
241
|
+
if isinstance(item, str):
|
|
242
|
+
tool_names.append(item)
|
|
243
|
+
elif isinstance(item, dict):
|
|
244
|
+
name_val = item.get('name')
|
|
245
|
+
if isinstance(name_val, str) and name_val.strip():
|
|
246
|
+
tool_names.append(name_val)
|
|
247
|
+
return [t for t in tool_names if t]
|
|
248
|
+
|
|
249
|
+
return []
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _secret_to_str(value: Any) -> Optional[str]:
|
|
253
|
+
if value is None:
|
|
254
|
+
return None
|
|
255
|
+
if hasattr(value, 'get_secret_value'):
|
|
256
|
+
try:
|
|
257
|
+
value = value.get_secret_value()
|
|
258
|
+
except Exception:
|
|
259
|
+
pass
|
|
260
|
+
if isinstance(value, str):
|
|
261
|
+
return value
|
|
262
|
+
return str(value)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _build_headers_from_settings(settings: Dict[str, Any]) -> Dict[str, str]:
|
|
266
|
+
headers: Dict[str, str] = {}
|
|
267
|
+
|
|
268
|
+
# Legacy structure used by the custom OpenAPI UI
|
|
269
|
+
auth = settings.get('authentication')
|
|
270
|
+
if isinstance(auth, dict) and auth.get('type') == 'api_key':
|
|
271
|
+
auth_settings = auth.get('settings') or {}
|
|
272
|
+
if isinstance(auth_settings, dict):
|
|
273
|
+
auth_type = str(auth_settings.get('auth_type', '')).strip().lower()
|
|
274
|
+
api_key = _secret_to_str(auth_settings.get('api_key'))
|
|
275
|
+
if api_key:
|
|
276
|
+
if auth_type == 'bearer':
|
|
277
|
+
headers['Authorization'] = f'Bearer {api_key}'
|
|
278
|
+
elif auth_type == 'basic':
|
|
279
|
+
headers['Authorization'] = f'Basic {api_key}'
|
|
280
|
+
elif auth_type == 'custom':
|
|
281
|
+
header_name = auth_settings.get('custom_header_name')
|
|
282
|
+
if header_name:
|
|
283
|
+
headers[str(header_name)] = f'{api_key}'
|
|
284
|
+
|
|
285
|
+
# New regular-schema structure (GitHub-style sections) uses flattened fields
|
|
286
|
+
if not headers:
|
|
287
|
+
api_key = _secret_to_str(settings.get('api_key'))
|
|
288
|
+
if api_key:
|
|
289
|
+
auth_type = str(settings.get('auth_type', 'Bearer'))
|
|
290
|
+
auth_type_norm = auth_type.strip().lower()
|
|
291
|
+
if auth_type_norm == 'bearer':
|
|
292
|
+
headers['Authorization'] = f'Bearer {api_key}'
|
|
293
|
+
elif auth_type_norm == 'basic':
|
|
294
|
+
headers['Authorization'] = f'Basic {api_key}'
|
|
295
|
+
elif auth_type_norm == 'custom':
|
|
296
|
+
header_name = settings.get('custom_header_name')
|
|
297
|
+
if header_name:
|
|
298
|
+
headers[str(header_name)] = f'{api_key}'
|
|
299
|
+
|
|
300
|
+
return headers
|