alita-sdk 0.3.263__py3-none-any.whl → 0.3.499__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 +1256 -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 +64 -8
- alita_sdk/community/inventory/__init__.py +224 -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/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +10 -0
- alita_sdk/configurations/ado.py +4 -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 +96 -1
- alita_sdk/configurations/delta_lake.py +1 -1
- alita_sdk/configurations/figma.py +0 -5
- alita_sdk/configurations/github.py +65 -1
- alita_sdk/configurations/gitlab.py +79 -0
- alita_sdk/configurations/google_places.py +17 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/postman.py +1 -1
- alita_sdk/configurations/qtest.py +1 -3
- alita_sdk/configurations/report_portal.py +19 -0
- alita_sdk/configurations/salesforce.py +19 -0
- alita_sdk/configurations/service_now.py +1 -12
- alita_sdk/configurations/sharepoint.py +19 -0
- alita_sdk/configurations/sonar.py +18 -0
- alita_sdk/configurations/sql.py +20 -0
- alita_sdk/configurations/testio.py +18 -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 +12 -2
- alita_sdk/runtime/clients/client.py +235 -66
- 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 +373 -0
- alita_sdk/runtime/langchain/assistant.py +123 -17
- alita_sdk/runtime/langchain/constants.py +8 -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/AlitaJSONLoader.py +8 -2
- 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 +187 -40
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
- alita_sdk/runtime/langchain/langraph_agent.py +406 -91
- alita_sdk/runtime/langchain/utils.py +51 -8
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- alita_sdk/runtime/toolkits/__init__.py +26 -0
- alita_sdk/runtime/toolkits/application.py +9 -2
- alita_sdk/runtime/toolkits/artifact.py +19 -7
- 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/subgraph.py +11 -6
- alita_sdk/runtime/toolkits/tools.py +214 -60
- alita_sdk/runtime/toolkits/vectorstore.py +9 -4
- alita_sdk/runtime/tools/__init__.py +22 -0
- alita_sdk/runtime/tools/application.py +16 -4
- alita_sdk/runtime/tools/artifact.py +312 -19
- alita_sdk/runtime/tools/function.py +100 -4
- alita_sdk/runtime/tools/graph.py +81 -0
- alita_sdk/runtime/tools/image_generation.py +212 -0
- alita_sdk/runtime/tools/llm.py +539 -180
- 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/vectorstore.py +62 -63
- alita_sdk/runtime/tools/vectorstore_base.py +156 -85
- alita_sdk/runtime/utils/AlitaCallback.py +106 -20
- alita_sdk/runtime/utils/mcp_client.py +465 -0
- alita_sdk/runtime/utils/mcp_oauth.py +244 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +405 -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 +14 -0
- alita_sdk/tools/__init__.py +78 -35
- alita_sdk/tools/ado/__init__.py +0 -1
- alita_sdk/tools/ado/repos/__init__.py +10 -6
- alita_sdk/tools/ado/repos/repos_wrapper.py +12 -11
- alita_sdk/tools/ado/test_plan/__init__.py +10 -7
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -23
- alita_sdk/tools/ado/wiki/__init__.py +10 -11
- alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -28
- alita_sdk/tools/ado/work_item/__init__.py +10 -11
- alita_sdk/tools/ado/work_item/ado_wrapper.py +63 -10
- alita_sdk/tools/advanced_jira_mining/__init__.py +10 -7
- alita_sdk/tools/aws/delta_lake/__init__.py +13 -11
- alita_sdk/tools/azure_ai/search/__init__.py +11 -7
- alita_sdk/tools/base_indexer_toolkit.py +392 -86
- alita_sdk/tools/bitbucket/__init__.py +18 -11
- alita_sdk/tools/bitbucket/api_wrapper.py +52 -9
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
- alita_sdk/tools/browser/__init__.py +40 -16
- alita_sdk/tools/browser/crawler.py +3 -1
- alita_sdk/tools/browser/utils.py +15 -6
- alita_sdk/tools/carrier/__init__.py +17 -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 +1 -0
- 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 +9 -6
- alita_sdk/tools/cloud/azure/__init__.py +9 -6
- alita_sdk/tools/cloud/gcp/__init__.py +9 -6
- alita_sdk/tools/cloud/k8s/__init__.py +9 -6
- alita_sdk/tools/code/linter/__init__.py +7 -7
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +18 -12
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +14 -11
- alita_sdk/tools/confluence/api_wrapper.py +198 -58
- alita_sdk/tools/confluence/loader.py +10 -0
- alita_sdk/tools/custom_open_api/__init__.py +9 -4
- alita_sdk/tools/elastic/__init__.py +8 -7
- alita_sdk/tools/elitea_base.py +543 -64
- alita_sdk/tools/figma/__init__.py +10 -8
- alita_sdk/tools/figma/api_wrapper.py +352 -153
- alita_sdk/tools/github/__init__.py +13 -11
- alita_sdk/tools/github/api_wrapper.py +9 -26
- alita_sdk/tools/github/github_client.py +75 -12
- alita_sdk/tools/github/schemas.py +2 -1
- alita_sdk/tools/gitlab/__init__.py +11 -10
- alita_sdk/tools/gitlab/api_wrapper.py +135 -45
- alita_sdk/tools/gitlab_org/__init__.py +11 -9
- alita_sdk/tools/google/bigquery/__init__.py +12 -13
- alita_sdk/tools/google_places/__init__.py +18 -10
- alita_sdk/tools/jira/__init__.py +14 -8
- alita_sdk/tools/jira/api_wrapper.py +315 -168
- alita_sdk/tools/keycloak/__init__.py +8 -7
- alita_sdk/tools/localgit/local_git.py +56 -54
- alita_sdk/tools/memory/__init__.py +27 -11
- alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
- alita_sdk/tools/ocr/__init__.py +8 -7
- alita_sdk/tools/openapi/__init__.py +10 -1
- alita_sdk/tools/pandas/__init__.py +8 -7
- alita_sdk/tools/pandas/api_wrapper.py +7 -25
- alita_sdk/tools/postman/__init__.py +8 -10
- alita_sdk/tools/postman/api_wrapper.py +19 -8
- alita_sdk/tools/postman/postman_analysis.py +8 -1
- alita_sdk/tools/pptx/__init__.py +8 -9
- alita_sdk/tools/qtest/__init__.py +19 -13
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +10 -9
- alita_sdk/tools/report_portal/__init__.py +20 -15
- alita_sdk/tools/salesforce/__init__.py +19 -15
- alita_sdk/tools/servicenow/__init__.py +14 -11
- alita_sdk/tools/sharepoint/__init__.py +14 -13
- 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 +10 -7
- alita_sdk/tools/sql/__init__.py +19 -18
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +18 -12
- alita_sdk/tools/testrail/__init__.py +10 -10
- alita_sdk/tools/testrail/api_wrapper.py +213 -45
- alita_sdk/tools/utils/__init__.py +28 -4
- alita_sdk/tools/utils/content_parser.py +181 -61
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
- alita_sdk/tools/xray/__init__.py +12 -7
- alita_sdk/tools/xray/api_wrapper.py +58 -113
- alita_sdk/tools/zephyr/__init__.py +9 -6
- alita_sdk/tools/zephyr_enterprise/__init__.py +13 -8
- alita_sdk/tools/zephyr_enterprise/api_wrapper.py +17 -7
- alita_sdk/tools/zephyr_essential/__init__.py +13 -9
- alita_sdk/tools/zephyr_essential/api_wrapper.py +289 -47
- alita_sdk/tools/zephyr_essential/client.py +6 -4
- alita_sdk/tools/zephyr_scale/__init__.py +10 -7
- alita_sdk/tools/zephyr_scale/api_wrapper.py +6 -2
- alita_sdk/tools/zephyr_squad/__init__.py +9 -6
- {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/METADATA +180 -33
- alita_sdk-0.3.499.dist-info/RECORD +433 -0
- alita_sdk-0.3.499.dist-info/entry_points.txt +2 -0
- alita_sdk-0.3.263.dist-info/RECORD +0 -342
- {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/top_level.txt +0 -0
|
@@ -2,11 +2,12 @@ import builtins
|
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
-
from pydantic import create_model, Field
|
|
5
|
+
from pydantic import create_model, Field, Json
|
|
6
6
|
from typing import Tuple, TypedDict, Any, Optional, Annotated
|
|
7
7
|
from langchain_core.messages import AnyMessage
|
|
8
|
-
from
|
|
9
|
-
|
|
8
|
+
from langgraph.graph import add_messages
|
|
9
|
+
|
|
10
|
+
from ...runtime.langchain.constants import ELITEA_RS, PRINTER_NODE_RS
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
12
13
|
|
|
@@ -121,6 +122,8 @@ def parse_type(type_str):
|
|
|
121
122
|
"""Parse a type string into an actual Python type."""
|
|
122
123
|
try:
|
|
123
124
|
# Evaluate the type string using builtins and imported modules
|
|
125
|
+
if type_str == 'number':
|
|
126
|
+
type_str = 'int'
|
|
124
127
|
return eval(type_str, {**vars(builtins), **globals()})
|
|
125
128
|
except Exception as e:
|
|
126
129
|
print(f"Error parsing type: {e}")
|
|
@@ -128,16 +131,23 @@ def parse_type(type_str):
|
|
|
128
131
|
|
|
129
132
|
|
|
130
133
|
def create_state(data: Optional[dict] = None):
|
|
131
|
-
state_dict = {'input': str, '
|
|
134
|
+
state_dict = {'input': str, 'messages': 'list[str]', 'router_output': str,
|
|
135
|
+
ELITEA_RS: str, PRINTER_NODE_RS: str} # Always include router_output
|
|
136
|
+
types_dict = {}
|
|
132
137
|
if not data:
|
|
133
138
|
data = {'messages': 'list[str]'}
|
|
134
139
|
for key, value in data.items():
|
|
135
140
|
# support of old & new UI
|
|
136
141
|
value = value['type'] if isinstance(value, dict) else value
|
|
142
|
+
value = 'str' if value == 'string' else value # normalize string type (old state support)
|
|
137
143
|
if key == 'messages':
|
|
138
144
|
state_dict[key] = Annotated[list[AnyMessage], add_messages]
|
|
139
|
-
elif value in ['str', 'int', 'float', 'bool', 'list', 'dict', 'number']:
|
|
145
|
+
elif value in ['str', 'int', 'float', 'bool', 'list', 'dict', 'number', 'dict']:
|
|
140
146
|
state_dict[key] = parse_type(value)
|
|
147
|
+
|
|
148
|
+
state_dict["state_types"] = types_dict # Default value for state_types
|
|
149
|
+
types_dict["state_types"] = dict
|
|
150
|
+
logger.debug(f"Created state: {state_dict}")
|
|
141
151
|
return TypedDict('State', state_dict)
|
|
142
152
|
|
|
143
153
|
def create_typed_dict_from_yaml(data):
|
|
@@ -170,16 +180,49 @@ def propagate_the_input_mapping(input_mapping: dict[str, dict], input_variables:
|
|
|
170
180
|
var_dict = create_params(input_variables, source)
|
|
171
181
|
|
|
172
182
|
if value['type'] == 'fstring':
|
|
173
|
-
|
|
183
|
+
try:
|
|
184
|
+
input_data[key] = value['value'].format(**var_dict)
|
|
185
|
+
except KeyError as e:
|
|
186
|
+
logger.error(f"KeyError in fstring formatting for key '{key}'. Attempt to find proper data in state.\n{e}")
|
|
187
|
+
try:
|
|
188
|
+
# search for variables in state if not found in var_dict
|
|
189
|
+
input_data[key] = safe_format(value['value'], state)
|
|
190
|
+
except KeyError as no_var_exception:
|
|
191
|
+
logger.error(f"KeyError in fstring formatting for key '{key}' with state data.\n{no_var_exception}")
|
|
192
|
+
# leave value as is if still not found (could be a constant string marked as fstring by mistake)
|
|
193
|
+
input_data[key] = value['value']
|
|
174
194
|
elif value['type'] == 'fixed':
|
|
175
195
|
input_data[key] = value['value']
|
|
176
196
|
else:
|
|
177
197
|
input_data[key] = source.get(value['value'], "")
|
|
178
198
|
return input_data
|
|
179
199
|
|
|
200
|
+
def safe_format(template, mapping):
|
|
201
|
+
"""Format a template string using a mapping, leaving placeholders unchanged if keys are missing."""
|
|
202
|
+
|
|
203
|
+
def replacer(match):
|
|
204
|
+
key = match.group(1)
|
|
205
|
+
return str(mapping.get(key, f'{{{key}}}'))
|
|
206
|
+
return re.sub(r'\{(\w+)\}', replacer, template)
|
|
180
207
|
|
|
181
208
|
def create_pydantic_model(model_name: str, variables: dict[str, dict]):
|
|
182
209
|
fields = {}
|
|
183
210
|
for var_name, var_data in variables.items():
|
|
184
|
-
fields[var_name] = (
|
|
185
|
-
return create_model(model_name, **fields)
|
|
211
|
+
fields[var_name] = (parse_pydantic_type(var_data['type']), Field(description=var_data.get('description', None)))
|
|
212
|
+
return create_model(model_name, **fields)
|
|
213
|
+
|
|
214
|
+
def parse_pydantic_type(type_name: str):
|
|
215
|
+
"""
|
|
216
|
+
Helper function to parse type names into Python types.
|
|
217
|
+
Extend this function to handle custom types like 'dict' -> Json[Any].
|
|
218
|
+
"""
|
|
219
|
+
type_mapping = {
|
|
220
|
+
'str': str,
|
|
221
|
+
'int': int,
|
|
222
|
+
'float': float,
|
|
223
|
+
'bool': bool,
|
|
224
|
+
'dict': Json[Any], # Map 'dict' to Pydantic's Json type
|
|
225
|
+
'list': list,
|
|
226
|
+
'any': Any
|
|
227
|
+
}
|
|
228
|
+
return type_mapping.get(type_name, Any)
|
|
@@ -105,8 +105,7 @@ class PreloadedChatModel(BaseChatModel): # pylint: disable=R0903
|
|
|
105
105
|
model_name: str = ""
|
|
106
106
|
max_tokens: Optional[int] = 256
|
|
107
107
|
temperature: Optional[float] = 0.9
|
|
108
|
-
|
|
109
|
-
top_k: Optional[int] = 20
|
|
108
|
+
reasoning_effort: Optional[str] = None
|
|
110
109
|
token_limit: Optional[int] = 1024
|
|
111
110
|
|
|
112
111
|
_local_streams: Any = PrivateAttr()
|
|
@@ -252,8 +251,7 @@ class PreloadedChatModel(BaseChatModel): # pylint: disable=R0903
|
|
|
252
251
|
"return_full_text": False,
|
|
253
252
|
"temperature": self.temperature,
|
|
254
253
|
"do_sample": True,
|
|
255
|
-
"
|
|
256
|
-
"top_p": self.top_p,
|
|
254
|
+
"reasoning_effort": self.reasoning_effort
|
|
257
255
|
}
|
|
258
256
|
#
|
|
259
257
|
try:
|
|
@@ -302,8 +300,6 @@ class PreloadedChatModel(BaseChatModel): # pylint: disable=R0903
|
|
|
302
300
|
"return_full_text": False,
|
|
303
301
|
"temperature": self.temperature,
|
|
304
302
|
"do_sample": True,
|
|
305
|
-
"top_k": self.top_k,
|
|
306
|
-
"top_p": self.top_p,
|
|
307
303
|
}
|
|
308
304
|
#
|
|
309
305
|
while True:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Models for MCP (Model Context Protocol) configuration.
|
|
3
|
+
Following MCP specification for remote HTTP servers only.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional, List, Dict, Any
|
|
7
|
+
from pydantic import BaseModel, Field, validator
|
|
8
|
+
from urllib.parse import urlparse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class McpConnectionConfig(BaseModel):
|
|
12
|
+
"""
|
|
13
|
+
MCP connection configuration for remote HTTP servers.
|
|
14
|
+
Based on https://modelcontextprotocol.io/specification/2025-06-18
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
url: str = Field(description="MCP server HTTP URL (http:// or https://)")
|
|
18
|
+
headers: Optional[Dict[str, str]] = Field(
|
|
19
|
+
default=None,
|
|
20
|
+
description="HTTP headers for the connection (JSON object)"
|
|
21
|
+
)
|
|
22
|
+
session_id: Optional[str] = Field(
|
|
23
|
+
default=None,
|
|
24
|
+
description="MCP session ID for stateful SSE servers (managed by client)"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
@validator('url')
|
|
28
|
+
def validate_url(cls, v):
|
|
29
|
+
"""Validate URL is HTTP/HTTPS."""
|
|
30
|
+
if not v:
|
|
31
|
+
raise ValueError("URL cannot be empty")
|
|
32
|
+
|
|
33
|
+
parsed = urlparse(v)
|
|
34
|
+
if parsed.scheme not in ['http', 'https']:
|
|
35
|
+
raise ValueError("URL must use http:// or https:// scheme for remote MCP servers")
|
|
36
|
+
|
|
37
|
+
if not parsed.netloc:
|
|
38
|
+
raise ValueError("URL must include host and port")
|
|
39
|
+
|
|
40
|
+
return v
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class McpToolkitConfig(BaseModel):
|
|
44
|
+
"""Configuration for a single remote MCP server toolkit."""
|
|
45
|
+
|
|
46
|
+
server_name: str = Field(description="MCP server name/identifier")
|
|
47
|
+
connection: McpConnectionConfig = Field(description="MCP connection configuration")
|
|
48
|
+
timeout: int = Field(default=60, description="Request timeout in seconds", ge=1, le=3600)
|
|
49
|
+
selected_tools: List[str] = Field(default_factory=list, description="Specific tools to enable (empty = all)")
|
|
50
|
+
enable_caching: bool = Field(default=True, description="Enable tool schema caching")
|
|
51
|
+
cache_ttl: int = Field(default=300, description="Cache TTL in seconds", ge=60, le=3600)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class McpToolMetadata(BaseModel):
|
|
55
|
+
"""Metadata about an MCP tool."""
|
|
56
|
+
|
|
57
|
+
name: str = Field(description="Tool name")
|
|
58
|
+
description: str = Field(description="Tool description")
|
|
59
|
+
server: str = Field(description="Source server name")
|
|
60
|
+
input_schema: Dict[str, Any] = Field(description="Tool input schema")
|
|
61
|
+
enabled: bool = Field(default=True, description="Whether tool is enabled")
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime toolkits module for Alita SDK.
|
|
3
|
+
This module provides various toolkit implementations for LangGraph agents.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .application import ApplicationToolkit
|
|
7
|
+
from .artifact import ArtifactToolkit
|
|
8
|
+
from .datasource import DatasourcesToolkit
|
|
9
|
+
from .planning import PlanningToolkit
|
|
10
|
+
from .prompt import PromptToolkit
|
|
11
|
+
from .subgraph import SubgraphToolkit
|
|
12
|
+
from .vectorstore import VectorStoreToolkit
|
|
13
|
+
from .mcp import McpToolkit
|
|
14
|
+
from ...tools.memory import MemoryToolkit
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"ApplicationToolkit",
|
|
18
|
+
"ArtifactToolkit",
|
|
19
|
+
"DatasourcesToolkit",
|
|
20
|
+
"PlanningToolkit",
|
|
21
|
+
"PromptToolkit",
|
|
22
|
+
"SubgraphToolkit",
|
|
23
|
+
"VectorStoreToolkit",
|
|
24
|
+
"McpToolkit",
|
|
25
|
+
"MemoryToolkit"
|
|
26
|
+
]
|
|
@@ -28,7 +28,7 @@ class ApplicationToolkit(BaseToolkit):
|
|
|
28
28
|
version_details = client.get_app_version_details(application_id, application_version_id)
|
|
29
29
|
model_settings = {
|
|
30
30
|
"max_tokens": version_details['llm_settings']['max_tokens'],
|
|
31
|
-
"
|
|
31
|
+
"reasoning_effort": version_details['llm_settings'].get('reasoning_effort'),
|
|
32
32
|
"temperature": version_details['llm_settings']['temperature'],
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -39,7 +39,14 @@ class ApplicationToolkit(BaseToolkit):
|
|
|
39
39
|
description=app_details.get("description"),
|
|
40
40
|
application=app,
|
|
41
41
|
args_schema=applicationToolSchema,
|
|
42
|
-
return_type='str'
|
|
42
|
+
return_type='str',
|
|
43
|
+
client=client,
|
|
44
|
+
args_runnable={
|
|
45
|
+
"application_id": application_id,
|
|
46
|
+
"application_version_id": application_version_id,
|
|
47
|
+
"store": store,
|
|
48
|
+
"llm": client.get_llm(version_details['llm_settings']['model_name'], model_settings),
|
|
49
|
+
})])
|
|
43
50
|
|
|
44
51
|
def get_tools(self):
|
|
45
52
|
return self.tools
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from typing import List, Any, Literal, Optional
|
|
2
2
|
|
|
3
|
-
from alita_sdk.tools.utils import clean_string,
|
|
3
|
+
from alita_sdk.tools.utils import clean_string, get_max_toolkit_length
|
|
4
4
|
from langchain_community.agent_toolkits.base import BaseToolkit
|
|
5
5
|
from langchain_core.tools import BaseTool
|
|
6
6
|
from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
7
7
|
from pydantic.fields import FieldInfo
|
|
8
8
|
from ..tools.artifact import ArtifactWrapper
|
|
9
|
-
from
|
|
9
|
+
from ...tools.base.tool import BaseAction
|
|
10
10
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
11
11
|
|
|
12
12
|
|
|
@@ -21,7 +21,10 @@ class ArtifactToolkit(BaseToolkit):
|
|
|
21
21
|
return create_model(
|
|
22
22
|
"artifact",
|
|
23
23
|
# client = (Any, FieldInfo(description="Client object", required=True, autopopulate=True)),
|
|
24
|
-
bucket
|
|
24
|
+
bucket=(str, FieldInfo(
|
|
25
|
+
description="Bucket name",
|
|
26
|
+
pattern=r'^[a-z][a-z0-9-]*$'
|
|
27
|
+
)),
|
|
25
28
|
selected_tools=(List[Literal[tuple(selected_tools)]], Field(default=[], json_schema_extra={'args_schemas': selected_tools})),
|
|
26
29
|
# indexer settings
|
|
27
30
|
pgvector_configuration=(Optional[PgVectorConfiguration], Field(default=None, description="PgVector Configuration", json_schema_extra={'configuration_types': ['pgvector']})),
|
|
@@ -30,29 +33,38 @@ class ArtifactToolkit(BaseToolkit):
|
|
|
30
33
|
embedding_model=(Optional[str], Field(default=None, description="Embedding configuration.",
|
|
31
34
|
json_schema_extra={'configuration_model': 'embedding'})),
|
|
32
35
|
|
|
33
|
-
__config__=ConfigDict(json_schema_extra={'metadata': {"label": "Artifact",
|
|
36
|
+
__config__=ConfigDict(json_schema_extra={'metadata': {"label": "Artifact",
|
|
37
|
+
"icon_url": None,
|
|
38
|
+
"max_length": ArtifactToolkit.toolkit_max_length
|
|
39
|
+
}})
|
|
34
40
|
)
|
|
35
41
|
|
|
36
42
|
@classmethod
|
|
37
43
|
def get_toolkit(cls, client: Any, bucket: str, toolkit_name: Optional[str] = None, selected_tools: list[str] = [], **kwargs):
|
|
38
44
|
if selected_tools is None:
|
|
39
45
|
selected_tools = []
|
|
46
|
+
|
|
40
47
|
tools = []
|
|
41
48
|
wrapper_payload = {
|
|
42
49
|
**kwargs,
|
|
43
50
|
**(kwargs.get('pgvector_configuration') or {}),
|
|
44
51
|
}
|
|
45
52
|
artifact_wrapper = ArtifactWrapper(alita=client, bucket=bucket, **wrapper_payload)
|
|
46
|
-
|
|
53
|
+
# Use clean toolkit name for context (max 1000 chars in description)
|
|
54
|
+
toolkit_context = f" [Toolkit: {clean_string(toolkit_name, 0)}]" if toolkit_name else ''
|
|
47
55
|
available_tools = artifact_wrapper.get_available_tools()
|
|
48
56
|
for tool in available_tools:
|
|
49
57
|
if selected_tools:
|
|
50
58
|
if tool["name"] not in selected_tools:
|
|
51
59
|
continue
|
|
60
|
+
# Add toolkit context to description with character limit
|
|
61
|
+
description = tool["description"]
|
|
62
|
+
if toolkit_context and len(description + toolkit_context) <= 1000:
|
|
63
|
+
description = description + toolkit_context
|
|
52
64
|
tools.append(BaseAction(
|
|
53
65
|
api_wrapper=artifact_wrapper,
|
|
54
|
-
name=
|
|
55
|
-
description=
|
|
66
|
+
name=tool["name"],
|
|
67
|
+
description=description,
|
|
56
68
|
args_schema=tool["args_schema"]
|
|
57
69
|
))
|
|
58
70
|
return cls(tools=tools)
|
|
@@ -3,7 +3,7 @@ from pydantic import create_model, BaseModel, Field
|
|
|
3
3
|
from langchain_community.agent_toolkits.base import BaseToolkit
|
|
4
4
|
from langchain_core.tools import BaseTool, ToolException
|
|
5
5
|
from ..tools.datasource import DatasourcePredict, DatasourceSearch, datasourceToolSchema
|
|
6
|
-
from alita_sdk.tools.utils import clean_string
|
|
6
|
+
from alita_sdk.tools.utils import clean_string
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class DatasourcesToolkit(BaseToolkit):
|
|
@@ -21,21 +21,28 @@ class DatasourcesToolkit(BaseToolkit):
|
|
|
21
21
|
@classmethod
|
|
22
22
|
def get_toolkit(cls, client: Any, datasource_ids: list[int], toolkit_name: Optional[str] = None, selected_tools: list[str] = []):
|
|
23
23
|
tools = []
|
|
24
|
-
|
|
24
|
+
# Use clean toolkit name for context (max 1000 chars in description)
|
|
25
|
+
toolkit_context = f" [Toolkit: {clean_string(toolkit_name)}]" if toolkit_name else ''
|
|
25
26
|
for datasource_id in datasource_ids:
|
|
26
27
|
datasource = client.datasource(datasource_id)
|
|
27
28
|
ds_name = clean_string(datasource.name)
|
|
28
29
|
if len(ds_name) == 0:
|
|
29
30
|
raise ToolException(f'Datasource with id {datasource_id} has incorrect name (i.e. special characters, etc.)')
|
|
30
31
|
if len(selected_tools) == 0 or 'chat' in selected_tools:
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
description = f'Search and summarize. {datasource.description}'
|
|
33
|
+
if toolkit_context and len(description + toolkit_context) <= 1000:
|
|
34
|
+
description = description + toolkit_context
|
|
35
|
+
tools.append(DatasourcePredict(name=f'chat',
|
|
36
|
+
description=description,
|
|
33
37
|
datasource=datasource,
|
|
34
38
|
args_schema=datasourceToolSchema,
|
|
35
39
|
return_type='str'))
|
|
36
40
|
if len(selected_tools) == 0 or 'search' in selected_tools:
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
description = f'Search return results. {datasource.description}'
|
|
42
|
+
if toolkit_context and len(description + toolkit_context) <= 1000:
|
|
43
|
+
description = description + toolkit_context
|
|
44
|
+
tools.append(DatasourceSearch(name=f'search',
|
|
45
|
+
description=description,
|
|
39
46
|
datasource=datasource,
|
|
40
47
|
args_schema=datasourceToolSchema,
|
|
41
48
|
return_type='str'))
|