alita-sdk 0.3.257__py3-none-any.whl → 0.3.584__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.
Potentially problematic release.
This version of alita-sdk might be problematic. Click here for more details.
- 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 +3794 -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 +323 -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 +493 -105
- alita_sdk/runtime/langchain/utils.py +118 -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 +25 -9
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +782 -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 +1032 -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/constants.py +5 -1
- 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 +16 -19
- alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
- alita_sdk/tools/ado/test_plan/__init__.py +27 -8
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
- alita_sdk/tools/ado/wiki/__init__.py +28 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
- alita_sdk/tools/ado/work_item/__init__.py +28 -12
- alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +13 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +15 -11
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +14 -8
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +454 -110
- alita_sdk/tools/bitbucket/__init__.py +28 -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 +12 -7
- alita_sdk/tools/cloud/azure/__init__.py +12 -7
- alita_sdk/tools/cloud/gcp/__init__.py +12 -7
- alita_sdk/tools/cloud/k8s/__init__.py +12 -7
- alita_sdk/tools/code/linter/__init__.py +10 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +21 -13
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +22 -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 +12 -5
- alita_sdk/tools/elastic/__init__.py +11 -8
- alita_sdk/tools/elitea_base.py +546 -64
- alita_sdk/tools/figma/__init__.py +60 -11
- alita_sdk/tools/figma/api_wrapper.py +1400 -167
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +18 -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 +19 -13
- alita_sdk/tools/gitlab/api_wrapper.py +256 -80
- alita_sdk/tools/gitlab_org/__init__.py +14 -10
- alita_sdk/tools/google/bigquery/__init__.py +14 -13
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +21 -11
- alita_sdk/tools/jira/__init__.py +22 -11
- alita_sdk/tools/jira/api_wrapper.py +315 -168
- alita_sdk/tools/keycloak/__init__.py +11 -8
- alita_sdk/tools/localgit/__init__.py +9 -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 +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- alita_sdk/tools/openapi/api_wrapper.py +1357 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- 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 +11 -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 +11 -10
- alita_sdk/tools/qtest/__init__.py +22 -14
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +13 -10
- alita_sdk/tools/report_portal/__init__.py +23 -16
- alita_sdk/tools/salesforce/__init__.py +22 -16
- alita_sdk/tools/servicenow/__init__.py +21 -16
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +17 -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 +13 -8
- alita_sdk/tools/sql/__init__.py +22 -19
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +21 -13
- alita_sdk/tools/testrail/__init__.py +13 -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 +241 -55
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
- alita_sdk/tools/xray/__init__.py +18 -14
- alita_sdk/tools/xray/api_wrapper.py +58 -113
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +12 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +16 -9
- alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
- alita_sdk/tools/zephyr_essential/__init__.py +16 -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 +13 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
- alita_sdk/tools/zephyr_squad/__init__.py +12 -7
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/METADATA +184 -37
- alita_sdk-0.3.584.dist-info/RECORD +452 -0
- alita_sdk-0.3.584.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.584.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,33 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
3
|
+
from copy import deepcopy
|
|
2
4
|
from json import dumps
|
|
3
5
|
|
|
4
6
|
from langchain_core.callbacks import dispatch_custom_event
|
|
5
7
|
from langchain_core.messages import ToolCall
|
|
6
8
|
from langchain_core.runnables import RunnableConfig
|
|
7
|
-
from langchain_core.tools import BaseTool
|
|
8
|
-
from typing import Any, Optional, Union
|
|
9
|
+
from langchain_core.tools import BaseTool, ToolException
|
|
10
|
+
from typing import Any, Optional, Union
|
|
9
11
|
from langchain_core.utils.function_calling import convert_to_openai_tool
|
|
10
12
|
from pydantic import ValidationError
|
|
13
|
+
|
|
11
14
|
from ..langchain.utils import propagate_the_input_mapping
|
|
12
15
|
|
|
13
16
|
logger = logging.getLogger(__name__)
|
|
14
17
|
|
|
15
18
|
|
|
19
|
+
def replace_escaped_newlines(data):
|
|
20
|
+
"""
|
|
21
|
+
Replace \\n with \n in all string values recursively.
|
|
22
|
+
Required for sanitization of state variables in code node
|
|
23
|
+
"""
|
|
24
|
+
if isinstance(data, dict):
|
|
25
|
+
return {key: replace_escaped_newlines(value) for key, value in data.items()}
|
|
26
|
+
elif isinstance(data, str):
|
|
27
|
+
return data.replace('\\n', '\n')
|
|
28
|
+
else:
|
|
29
|
+
return data
|
|
30
|
+
|
|
16
31
|
class FunctionTool(BaseTool):
|
|
17
32
|
name: str = 'FunctionalTool'
|
|
18
33
|
description: str = 'This is direct call node for tools'
|
|
@@ -21,6 +36,61 @@ class FunctionTool(BaseTool):
|
|
|
21
36
|
input_variables: Optional[list[str]] = None
|
|
22
37
|
input_mapping: Optional[dict[str, dict]] = None
|
|
23
38
|
output_variables: Optional[list[str]] = None
|
|
39
|
+
structured_output: Optional[bool] = False
|
|
40
|
+
alita_client: Optional[Any] = None
|
|
41
|
+
|
|
42
|
+
def _prepare_pyodide_input(self, state: Union[str, dict, ToolCall]) -> str:
|
|
43
|
+
"""Prepare input for PyodideSandboxTool by injecting state into the code block."""
|
|
44
|
+
# add state into the code block here since it might be changed during the execution of the code
|
|
45
|
+
state_copy = replace_escaped_newlines(deepcopy(state))
|
|
46
|
+
|
|
47
|
+
del state_copy['messages'] # remove messages to avoid issues with pickling without langchain-core
|
|
48
|
+
# inject state into the code block as alita_state variable
|
|
49
|
+
state_json = json.dumps(state_copy, ensure_ascii=False)
|
|
50
|
+
pyodide_predata = f'#state dict\nimport json\nalita_state = json.loads({json.dumps(state_json)})\n'
|
|
51
|
+
|
|
52
|
+
return pyodide_predata
|
|
53
|
+
|
|
54
|
+
def _handle_pyodide_output(self, tool_result: Any) -> dict:
|
|
55
|
+
"""Handle output processing for PyodideSandboxTool results."""
|
|
56
|
+
tool_result_converted = {}
|
|
57
|
+
|
|
58
|
+
if self.output_variables:
|
|
59
|
+
for var in self.output_variables:
|
|
60
|
+
if var == "messages":
|
|
61
|
+
tool_result_converted.update(
|
|
62
|
+
{"messages": [{"role": "assistant", "content": dumps(tool_result)}]})
|
|
63
|
+
continue
|
|
64
|
+
if isinstance(tool_result, dict) and var in tool_result:
|
|
65
|
+
tool_result_converted[var] = tool_result[var]
|
|
66
|
+
else:
|
|
67
|
+
# handler in case user points to a var that is not in the output of the tool
|
|
68
|
+
tool_result_converted[var] = tool_result.get('result',
|
|
69
|
+
tool_result.get('error') if tool_result.get('error')
|
|
70
|
+
else 'Execution result is missing')
|
|
71
|
+
else:
|
|
72
|
+
tool_result_converted.update({"messages": [{"role": "assistant", "content": dumps(tool_result)}]})
|
|
73
|
+
|
|
74
|
+
if self.structured_output:
|
|
75
|
+
# execute code tool and update state variables
|
|
76
|
+
try:
|
|
77
|
+
result_value = tool_result.get('result', {})
|
|
78
|
+
if isinstance(result_value, dict):
|
|
79
|
+
tool_result_converted.update(result_value)
|
|
80
|
+
elif isinstance(result_value, list):
|
|
81
|
+
# Handle list case - could wrap in a key or handle differently based on requirements
|
|
82
|
+
tool_result_converted.update({"result": result_value})
|
|
83
|
+
else:
|
|
84
|
+
# Handle JSON string case
|
|
85
|
+
tool_result_converted.update(json.loads(result_value))
|
|
86
|
+
except json.JSONDecodeError:
|
|
87
|
+
logger.error(f"JSONDecodeError: {tool_result}")
|
|
88
|
+
|
|
89
|
+
return tool_result_converted
|
|
90
|
+
|
|
91
|
+
def _is_pyodide_tool(self) -> bool:
|
|
92
|
+
"""Check if the current tool is a PyodideSandboxTool."""
|
|
93
|
+
return self.tool.name.lower() == 'pyodide_sandbox'
|
|
24
94
|
|
|
25
95
|
def invoke(
|
|
26
96
|
self,
|
|
@@ -31,8 +101,15 @@ class FunctionTool(BaseTool):
|
|
|
31
101
|
params = convert_to_openai_tool(self.tool).get(
|
|
32
102
|
'function', {'parameters': {}}).get(
|
|
33
103
|
'parameters', {'properties': {}}).get('properties', {})
|
|
104
|
+
|
|
34
105
|
func_args = propagate_the_input_mapping(input_mapping=self.input_mapping, input_variables=self.input_variables,
|
|
35
106
|
state=state)
|
|
107
|
+
|
|
108
|
+
# special handler for PyodideSandboxTool
|
|
109
|
+
if self._is_pyodide_tool():
|
|
110
|
+
# replace new lines in strings in code block
|
|
111
|
+
code = func_args['code'].replace('\\n', '\\\\n')
|
|
112
|
+
func_args['code'] = f"{self._prepare_pyodide_input(state)}\n{code}"
|
|
36
113
|
try:
|
|
37
114
|
tool_result = self.tool.invoke(func_args, config, **kwargs)
|
|
38
115
|
dispatch_custom_event(
|
|
@@ -44,11 +121,30 @@ class FunctionTool(BaseTool):
|
|
|
44
121
|
}, config=config
|
|
45
122
|
)
|
|
46
123
|
logger.info(f"ToolNode response: {tool_result}")
|
|
124
|
+
|
|
125
|
+
# handler for PyodideSandboxTool
|
|
126
|
+
if self._is_pyodide_tool():
|
|
127
|
+
return self._handle_pyodide_output(tool_result)
|
|
128
|
+
|
|
47
129
|
if not self.output_variables:
|
|
48
130
|
return {"messages": [{"role": "assistant", "content": dumps(tool_result)}]}
|
|
49
131
|
else:
|
|
50
|
-
if self.output_variables
|
|
51
|
-
|
|
132
|
+
if "messages" in self.output_variables:
|
|
133
|
+
messages_dict = {
|
|
134
|
+
"messages": [{
|
|
135
|
+
"role": "assistant",
|
|
136
|
+
"content": dumps(tool_result)
|
|
137
|
+
if not isinstance(tool_result, ToolException) and not isinstance(tool_result, str)
|
|
138
|
+
else str(tool_result)
|
|
139
|
+
}]
|
|
140
|
+
}
|
|
141
|
+
for var in self.output_variables:
|
|
142
|
+
if var != "messages":
|
|
143
|
+
if isinstance(tool_result, dict) and var in tool_result:
|
|
144
|
+
messages_dict[var] = tool_result[var]
|
|
145
|
+
else:
|
|
146
|
+
messages_dict[var] = tool_result
|
|
147
|
+
return messages_dict
|
|
52
148
|
else:
|
|
53
149
|
return { self.output_variables[0]: tool_result }
|
|
54
150
|
except ValidationError:
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
4
|
+
|
|
5
|
+
from ..utils.utils import clean_string
|
|
6
|
+
from langchain_core.tools import BaseTool
|
|
7
|
+
from langchain_core.messages import BaseMessage, AIMessage, ToolCall
|
|
8
|
+
from typing import Any, Type, Optional, Union
|
|
9
|
+
from pydantic import create_model, field_validator, BaseModel
|
|
10
|
+
from pydantic.fields import FieldInfo
|
|
11
|
+
from ..langchain.mixedAgentRenderes import convert_message_to_json
|
|
12
|
+
from logging import getLogger
|
|
13
|
+
|
|
14
|
+
logger = getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
graphToolSchema = create_model(
|
|
17
|
+
"graphToolSchema",
|
|
18
|
+
input=(str, FieldInfo(description="User Input for Graph")),
|
|
19
|
+
chat_history=(Optional[list[BaseMessage]],
|
|
20
|
+
FieldInfo(description="Chat History relevant for Graph in format [{'role': '<user| assistant | etc>', 'content': '<content of the respected message>'}]", default=[]))
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def formulate_query(kwargs):
|
|
25
|
+
chat_history = []
|
|
26
|
+
if kwargs.get('chat_history'):
|
|
27
|
+
if isinstance(kwargs.get('chat_history')[-1], BaseMessage):
|
|
28
|
+
chat_history = convert_message_to_json(kwargs.get('chat_history')[:])
|
|
29
|
+
elif isinstance(kwargs.get('chat_history')[-1], dict):
|
|
30
|
+
if all([True if message.get('role') and message.get('content') else False for message in
|
|
31
|
+
kwargs.get('chat_history')]):
|
|
32
|
+
chat_history = kwargs.get('chat_history')[:]
|
|
33
|
+
else:
|
|
34
|
+
for each in kwargs.get('chat_history')[:]:
|
|
35
|
+
chat_history.append(AIMessage(json.dumps(each)))
|
|
36
|
+
elif isinstance(kwargs.get('chat_history')[-1], str):
|
|
37
|
+
chat_history = []
|
|
38
|
+
for each in kwargs.get('chat_history')[:]:
|
|
39
|
+
chat_history.append(AIMessage(each))
|
|
40
|
+
elif kwargs.get('messages'):
|
|
41
|
+
chat_history = convert_message_to_json(kwargs.get('messages')[:])
|
|
42
|
+
result = {"input": kwargs.get('input'), "chat_history": chat_history}
|
|
43
|
+
for key, value in kwargs.items():
|
|
44
|
+
if key not in ("input", "chat_history"):
|
|
45
|
+
result[key] = value
|
|
46
|
+
return result
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GraphTool(BaseTool):
|
|
50
|
+
name: str = 'GraphTool'
|
|
51
|
+
description: str = 'Graph tool for tools'
|
|
52
|
+
graph: CompiledStateGraph
|
|
53
|
+
args_schema: Type[BaseModel] = graphToolSchema
|
|
54
|
+
return_type: str = "str"
|
|
55
|
+
|
|
56
|
+
@field_validator('name', mode='before')
|
|
57
|
+
@classmethod
|
|
58
|
+
def remove_spaces(cls, v):
|
|
59
|
+
return clean_string(v)
|
|
60
|
+
|
|
61
|
+
def invoke(self, input: Any, config: Optional[dict] = None, **kwargs: Any) -> Any:
|
|
62
|
+
"""Override default invoke to preserve all fields, not just args_schema"""
|
|
63
|
+
schema_values = self.args_schema(**input).model_dump() if self.args_schema else {}
|
|
64
|
+
extras = {k: v for k, v in input.items() if k not in schema_values}
|
|
65
|
+
all_kwargs = {**kwargs, **extras, **schema_values}
|
|
66
|
+
if config is None:
|
|
67
|
+
config = {}
|
|
68
|
+
# Pass the config to the _run empty or the one passed from the parent executor.
|
|
69
|
+
return self._run(config, **all_kwargs)
|
|
70
|
+
|
|
71
|
+
def _run(self, *args, **kwargs):
|
|
72
|
+
config = None
|
|
73
|
+
# From invoke method we are passing only 1 arg so it is safe to do this condition and config assignment.
|
|
74
|
+
# Default to None is safe because it will be checked also on the langchain side.
|
|
75
|
+
if args:
|
|
76
|
+
config = args[0]
|
|
77
|
+
response = self.graph.invoke(formulate_query(kwargs), config=config)
|
|
78
|
+
if self.return_type == "str":
|
|
79
|
+
return response["output"]
|
|
80
|
+
else:
|
|
81
|
+
return {"messages": [{"role": "assistant", "content": response["output"]}]}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Image generation tool for Alita SDK.
|
|
3
|
+
"""
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import uuid
|
|
7
|
+
from typing import Optional, Type, Any, List, Literal
|
|
8
|
+
from langchain_core.tools import BaseTool, BaseToolkit
|
|
9
|
+
from pydantic import BaseModel, Field, create_model, ConfigDict
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
name = "image_generation"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_tools(tools_list: list, alita_client=None, llm=None,
|
|
17
|
+
memory_store=None):
|
|
18
|
+
"""
|
|
19
|
+
Get image generation tools for the provided tool configurations.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
tools_list: List of tool configurations
|
|
23
|
+
alita_client: Alita client instance (required for image generation)
|
|
24
|
+
llm: LLM client instance (unused for image generation)
|
|
25
|
+
memory_store: Optional memory store instance (unused)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
List of image generation tools
|
|
29
|
+
"""
|
|
30
|
+
all_tools = []
|
|
31
|
+
|
|
32
|
+
for tool in tools_list:
|
|
33
|
+
if (tool.get('type') == 'image_generation' or
|
|
34
|
+
tool.get('toolkit_name') == 'image_generation'):
|
|
35
|
+
try:
|
|
36
|
+
if not alita_client:
|
|
37
|
+
logger.error("Alita client is required for image "
|
|
38
|
+
"generation tools")
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
toolkit_instance = ImageGenerationToolkit.get_toolkit(
|
|
42
|
+
client=alita_client,
|
|
43
|
+
toolkit_name=tool.get('toolkit_name', '')
|
|
44
|
+
)
|
|
45
|
+
all_tools.extend(toolkit_instance.get_tools())
|
|
46
|
+
except Exception as e:
|
|
47
|
+
logger.error(f"Error in image generation toolkit "
|
|
48
|
+
f"get_tools: {e}")
|
|
49
|
+
logger.error(f"Tool config: {tool}")
|
|
50
|
+
raise
|
|
51
|
+
|
|
52
|
+
return all_tools
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ImageGenerationInput(BaseModel):
|
|
56
|
+
"""Input schema for image generation tool."""
|
|
57
|
+
prompt: str = Field(
|
|
58
|
+
description="Text prompt describing the image to generate"
|
|
59
|
+
)
|
|
60
|
+
n: int = Field(
|
|
61
|
+
default=1, description="Number of images to generate (1-10)",
|
|
62
|
+
ge=1, le=10
|
|
63
|
+
)
|
|
64
|
+
size: str = Field(
|
|
65
|
+
default="auto",
|
|
66
|
+
description="Size of the generated image (e.g., '1024x1024')"
|
|
67
|
+
)
|
|
68
|
+
quality: str = Field(
|
|
69
|
+
default="auto",
|
|
70
|
+
description="Quality of the generated image ('low', 'medium', 'high')"
|
|
71
|
+
)
|
|
72
|
+
style: Optional[str] = Field(
|
|
73
|
+
default=None, description="Style of the generated image (optional)"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ImageGenerationTool(BaseTool):
|
|
78
|
+
"""Tool for generating images using the Alita client."""
|
|
79
|
+
|
|
80
|
+
name: str = "generate_image"
|
|
81
|
+
description: str = (
|
|
82
|
+
"Generate images from text prompts using AI models. "
|
|
83
|
+
"Returns a JSON object with 'cached_image_id' field containing a reference to the generated image data. "
|
|
84
|
+
"The cached_image_id can be used to save or process the image. "
|
|
85
|
+
"The actual image data is stored temporarily and can be retrieved using the cached_image_id reference."
|
|
86
|
+
)
|
|
87
|
+
args_schema: Type[BaseModel] = ImageGenerationInput
|
|
88
|
+
alita_client: Any = None
|
|
89
|
+
|
|
90
|
+
def __init__(self, client, **kwargs):
|
|
91
|
+
super().__init__(**kwargs)
|
|
92
|
+
self.alita_client = client
|
|
93
|
+
|
|
94
|
+
def _run(self, prompt: str, n: int = 1, size: str = "auto",
|
|
95
|
+
quality: str = "auto", style: Optional[str] = None) -> str:
|
|
96
|
+
"""Generate an image based on the provided parameters."""
|
|
97
|
+
try:
|
|
98
|
+
logger.debug(f"Generating image with prompt: {prompt[:50]}...")
|
|
99
|
+
|
|
100
|
+
result = self.alita_client.generate_image(
|
|
101
|
+
prompt=prompt,
|
|
102
|
+
n=n,
|
|
103
|
+
size=size,
|
|
104
|
+
quality=quality,
|
|
105
|
+
style=style
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Return simple JSON structure with reference ID instead of full base64
|
|
109
|
+
if 'data' in result:
|
|
110
|
+
images = result['data']
|
|
111
|
+
|
|
112
|
+
# Process all images with unified structure
|
|
113
|
+
images_list = []
|
|
114
|
+
for idx, image_data in enumerate(images, 1):
|
|
115
|
+
if not image_data.get('b64_json'):
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
cached_image_id = f"img_{uuid.uuid4().hex[:12]}"
|
|
119
|
+
|
|
120
|
+
# Store in cache
|
|
121
|
+
if hasattr(self.alita_client, '_generated_images_cache'):
|
|
122
|
+
self.alita_client._generated_images_cache[cached_image_id] = {
|
|
123
|
+
'base64_data': image_data['b64_json']
|
|
124
|
+
}
|
|
125
|
+
logger.debug(f"Stored generated image in cache with ID: {cached_image_id}")
|
|
126
|
+
|
|
127
|
+
images_list.append({
|
|
128
|
+
"image_number": idx,
|
|
129
|
+
"image_type": "png",
|
|
130
|
+
"cached_image_id": cached_image_id
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
if not images_list:
|
|
134
|
+
return json.dumps({
|
|
135
|
+
"status": "error",
|
|
136
|
+
"message": "No base64 image data found"
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
return json.dumps({
|
|
140
|
+
"status": "success",
|
|
141
|
+
"prompt": prompt,
|
|
142
|
+
"total_images": len(images_list),
|
|
143
|
+
"images": images_list
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
# Fallback to error response if no images in result
|
|
147
|
+
return json.dumps({
|
|
148
|
+
"status": "error",
|
|
149
|
+
"message": f"Image generation completed but no images returned: {result}"
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
except Exception as e:
|
|
153
|
+
logger.error(f"Error generating image: {e}")
|
|
154
|
+
return json.dumps({
|
|
155
|
+
"status": "error",
|
|
156
|
+
"message": f"Error generating image: {str(e)}"
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
async def _arun(self, prompt: str, n: int = 1, size: str = "256x256",
|
|
160
|
+
quality: str = "auto",
|
|
161
|
+
style: Optional[str] = None) -> list:
|
|
162
|
+
"""Async version - for now just calls the sync version."""
|
|
163
|
+
return self._run(prompt, n, size, quality, style)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def create_image_generation_tool(client):
|
|
167
|
+
"""Create an image generation tool with the provided Alita client."""
|
|
168
|
+
return ImageGenerationTool(client=client)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class ImageGenerationToolkit(BaseToolkit):
|
|
172
|
+
"""Toolkit for image generation tools."""
|
|
173
|
+
tools: List[BaseTool] = []
|
|
174
|
+
|
|
175
|
+
@staticmethod
|
|
176
|
+
def toolkit_config_schema() -> BaseModel:
|
|
177
|
+
"""Get the configuration schema for the image generation toolkit."""
|
|
178
|
+
# Create sample tool to get schema
|
|
179
|
+
sample_tool = ImageGenerationTool(client=None)
|
|
180
|
+
selected_tools = {sample_tool.name: sample_tool.args_schema.schema()}
|
|
181
|
+
|
|
182
|
+
return create_model(
|
|
183
|
+
'image_generation',
|
|
184
|
+
selected_tools=(
|
|
185
|
+
List[Literal[tuple(selected_tools)]],
|
|
186
|
+
Field(
|
|
187
|
+
default=[],
|
|
188
|
+
json_schema_extra={'args_schemas': selected_tools}
|
|
189
|
+
)
|
|
190
|
+
),
|
|
191
|
+
__config__=ConfigDict(json_schema_extra={
|
|
192
|
+
'metadata': {
|
|
193
|
+
"label": "Image Generation",
|
|
194
|
+
"icon_url": "image_generation.svg",
|
|
195
|
+
"hidden": True,
|
|
196
|
+
"categories": ["internal_tool"],
|
|
197
|
+
"extra_categories": ["image generation"],
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
@classmethod
|
|
203
|
+
def get_toolkit(cls, client=None, **kwargs):
|
|
204
|
+
"""
|
|
205
|
+
Get toolkit with image generation tools.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
client: Alita client instance (required)
|
|
209
|
+
**kwargs: Additional arguments
|
|
210
|
+
"""
|
|
211
|
+
if not client:
|
|
212
|
+
raise ValueError("Alita client is required for image generation")
|
|
213
|
+
|
|
214
|
+
tools = [ImageGenerationTool(client=client)]
|
|
215
|
+
return cls(tools=tools)
|
|
216
|
+
|
|
217
|
+
def get_tools(self):
|
|
218
|
+
return self.tools
|