alita-sdk 0.3.379__py3-none-any.whl → 0.3.627__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 +156 -0
- alita_sdk/cli/agent_loader.py +245 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3113 -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/testcases/__init__.py +94 -0
- alita_sdk/cli/testcases/data_generation.py +119 -0
- alita_sdk/cli/testcases/discovery.py +96 -0
- alita_sdk/cli/testcases/executor.py +84 -0
- alita_sdk/cli/testcases/logger.py +85 -0
- alita_sdk/cli/testcases/parser.py +172 -0
- alita_sdk/cli/testcases/prompts.py +91 -0
- alita_sdk/cli/testcases/reporting.py +125 -0
- alita_sdk/cli/testcases/setup.py +108 -0
- alita_sdk/cli/testcases/test_runner.py +282 -0
- alita_sdk/cli/testcases/utils.py +39 -0
- alita_sdk/cli/testcases/validation.py +90 -0
- alita_sdk/cli/testcases/workflow.py +196 -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 +1 -1
- alita_sdk/configurations/ado.py +141 -20
- alita_sdk/configurations/bitbucket.py +94 -2
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/figma.py +76 -0
- alita_sdk/configurations/gitlab.py +91 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/openapi.py +329 -0
- alita_sdk/configurations/qtest.py +72 -1
- alita_sdk/configurations/report_portal.py +96 -0
- alita_sdk/configurations/sharepoint.py +148 -0
- alita_sdk/configurations/testio.py +83 -0
- alita_sdk/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +93 -0
- alita_sdk/configurations/zephyr_enterprise.py +93 -0
- alita_sdk/configurations/zephyr_essential.py +75 -0
- alita_sdk/runtime/clients/artifact.py +3 -3
- alita_sdk/runtime/clients/client.py +388 -46
- 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 +8 -21
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +157 -39
- 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 +103 -60
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -4
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
- alita_sdk/runtime/langchain/document_loaders/constants.py +40 -19
- alita_sdk/runtime/langchain/langraph_agent.py +405 -84
- alita_sdk/runtime/langchain/utils.py +106 -7
- 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 +31 -0
- alita_sdk/runtime/toolkits/application.py +29 -10
- alita_sdk/runtime/toolkits/artifact.py +20 -11
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +783 -0
- alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +251 -6
- alita_sdk/runtime/toolkits/tools.py +356 -69
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +10 -3
- alita_sdk/runtime/tools/application.py +27 -6
- alita_sdk/runtime/tools/artifact.py +511 -28
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +67 -35
- alita_sdk/runtime/tools/graph.py +10 -4
- alita_sdk/runtime/tools/image_generation.py +148 -46
- alita_sdk/runtime/tools/llm.py +1003 -128
- 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 +8 -5
- 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 -4
- alita_sdk/runtime/tools/sandbox.py +65 -48
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +9 -3
- alita_sdk/runtime/tools/vectorstore_base.py +70 -14
- 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/serialization.py +155 -0
- alita_sdk/runtime/utils/streamlit.py +40 -13
- alita_sdk/runtime/utils/toolkit_utils.py +30 -9
- alita_sdk/runtime/utils/utils.py +36 -0
- alita_sdk/tools/__init__.py +134 -35
- alita_sdk/tools/ado/repos/__init__.py +51 -32
- alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
- alita_sdk/tools/ado/test_plan/__init__.py +25 -9
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
- alita_sdk/tools/ado/utils.py +1 -18
- alita_sdk/tools/ado/wiki/__init__.py +25 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
- alita_sdk/tools/ado/work_item/__init__.py +26 -13
- alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +11 -8
- alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +271 -84
- alita_sdk/tools/bitbucket/__init__.py +17 -11
- alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
- alita_sdk/tools/browser/__init__.py +5 -4
- alita_sdk/tools/carrier/__init__.py +5 -6
- alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
- alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
- alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
- 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 +10 -7
- alita_sdk/tools/cloud/azure/__init__.py +10 -7
- alita_sdk/tools/cloud/gcp/__init__.py +10 -7
- alita_sdk/tools/cloud/k8s/__init__.py +10 -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 +11 -8
- alita_sdk/tools/code_indexer_toolkit.py +82 -22
- alita_sdk/tools/confluence/__init__.py +22 -16
- alita_sdk/tools/confluence/api_wrapper.py +107 -30
- 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 +493 -30
- alita_sdk/tools/figma/__init__.py +58 -11
- alita_sdk/tools/figma/api_wrapper.py +1235 -143
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +14 -15
- alita_sdk/tools/github/github_client.py +224 -100
- alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
- alita_sdk/tools/github/schemas.py +14 -5
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/github/tool_prompts.py +9 -22
- alita_sdk/tools/gitlab/__init__.py +16 -11
- alita_sdk/tools/gitlab/api_wrapper.py +218 -48
- alita_sdk/tools/gitlab_org/__init__.py +10 -9
- alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
- alita_sdk/tools/google/bigquery/__init__.py +13 -12
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +11 -8
- alita_sdk/tools/google_places/api_wrapper.py +1 -1
- alita_sdk/tools/jira/__init__.py +17 -10
- alita_sdk/tools/jira/api_wrapper.py +92 -41
- 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 +12 -4
- alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- alita_sdk/tools/openapi/api_wrapper.py +1368 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- alita_sdk/tools/pandas/api_wrapper.py +38 -25
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +10 -9
- alita_sdk/tools/pptx/__init__.py +11 -10
- alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
- alita_sdk/tools/qtest/__init__.py +31 -11
- alita_sdk/tools/qtest/api_wrapper.py +2135 -86
- alita_sdk/tools/rally/__init__.py +10 -9
- alita_sdk/tools/rally/api_wrapper.py +1 -1
- alita_sdk/tools/report_portal/__init__.py +12 -8
- alita_sdk/tools/salesforce/__init__.py +10 -8
- alita_sdk/tools/servicenow/__init__.py +17 -15
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +10 -7
- alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
- 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/slack/api_wrapper.py +2 -2
- alita_sdk/tools/sql/__init__.py +12 -9
- alita_sdk/tools/testio/__init__.py +10 -7
- alita_sdk/tools/testrail/__init__.py +11 -10
- alita_sdk/tools/testrail/api_wrapper.py +1 -1
- alita_sdk/tools/utils/__init__.py +9 -4
- alita_sdk/tools/utils/content_parser.py +103 -18
- alita_sdk/tools/utils/text_operations.py +410 -0
- alita_sdk/tools/utils/tool_prompts.py +79 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +30 -13
- alita_sdk/tools/xray/__init__.py +13 -9
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +10 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
- alita_sdk/tools/zephyr_essential/__init__.py +10 -7
- alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
- alita_sdk/tools/zephyr_essential/client.py +2 -2
- alita_sdk/tools/zephyr_scale/__init__.py +11 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
- alita_sdk/tools/zephyr_squad/__init__.py +10 -7
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
- alita_sdk-0.3.627.dist-info/RECORD +468 -0
- alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
- alita_sdk-0.3.379.dist-info/RECORD +0 -360
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/top_level.txt +0 -0
|
@@ -5,8 +5,9 @@ from .api_wrapper import RallyApiWrapper
|
|
|
5
5
|
from langchain_core.tools import BaseTool
|
|
6
6
|
from ..base.tool import BaseAction
|
|
7
7
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
8
|
-
from ..utils import clean_string,
|
|
8
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
9
9
|
from ...configurations.rally import RallyConfiguration
|
|
10
|
+
from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
|
|
10
11
|
|
|
11
12
|
name = "rally"
|
|
12
13
|
|
|
@@ -21,16 +22,12 @@ def get_tools(tool):
|
|
|
21
22
|
|
|
22
23
|
class RallyToolkit(BaseToolkit):
|
|
23
24
|
tools: List[BaseTool] = []
|
|
24
|
-
toolkit_max_length: int = 0
|
|
25
25
|
|
|
26
26
|
@staticmethod
|
|
27
27
|
def toolkit_config_schema() -> BaseModel:
|
|
28
28
|
selected_tools = {x['name']: x['args_schema'].schema() for x in RallyApiWrapper.model_construct().get_available_tools()}
|
|
29
|
-
RallyToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
30
29
|
return create_model(
|
|
31
30
|
name,
|
|
32
|
-
name=(str, Field(description="Toolkit name", json_schema_extra={'toolkit_name': True,
|
|
33
|
-
'max_toolkit_length': RallyToolkit.toolkit_max_length})),
|
|
34
31
|
rally_configuration=(RallyConfiguration, Field(description="Rally configuration", json_schema_extra={'configuration_types': ['rally']})),
|
|
35
32
|
workspace=(Optional[str], Field(default=None, description="Rally workspace")),
|
|
36
33
|
project=(Optional[str], Field(default=None, description="Rally project")),
|
|
@@ -55,18 +52,22 @@ class RallyToolkit(BaseToolkit):
|
|
|
55
52
|
**kwargs.get('rally_configuration'),
|
|
56
53
|
}
|
|
57
54
|
rally_api_wrapper = RallyApiWrapper(**wrapper_payload)
|
|
58
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
59
55
|
available_tools = rally_api_wrapper.get_available_tools()
|
|
60
56
|
tools = []
|
|
61
57
|
for tool in available_tools:
|
|
62
58
|
if selected_tools:
|
|
63
59
|
if tool["name"] not in selected_tools:
|
|
64
60
|
continue
|
|
61
|
+
description = f"{tool['description']}\nWorkspace: {rally_api_wrapper.workspace}. Project: {rally_api_wrapper.project}"
|
|
62
|
+
if toolkit_name:
|
|
63
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
64
|
+
description = description[:1000]
|
|
65
65
|
tools.append(BaseAction(
|
|
66
66
|
api_wrapper=rally_api_wrapper,
|
|
67
|
-
name=
|
|
68
|
-
description=
|
|
69
|
-
args_schema=tool["args_schema"]
|
|
67
|
+
name=tool["name"],
|
|
68
|
+
description=description,
|
|
69
|
+
args_schema=tool["args_schema"],
|
|
70
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
|
|
70
71
|
))
|
|
71
72
|
return cls(tools=tools)
|
|
72
73
|
|
|
@@ -40,7 +40,7 @@ RallyGetEntities = create_model(
|
|
|
40
40
|
entity_type=(Optional[str], Field(description="Artifact type, e.g. 'HierarchicalRequirement', 'Defect', 'UserStory'", default="UserStory")),
|
|
41
41
|
query=(Optional[str], Field(description="Query for searching Rally stories", default=None)),
|
|
42
42
|
fetch=(Optional[bool], Field(description="Whether to fetch the full details of the stories", default=True)),
|
|
43
|
-
limit=(Optional[int], Field(description="Limit the number of results", default=10))
|
|
43
|
+
limit=(Optional[int], Field(description="Limit the number of results", default=10, gt=0))
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
RallyGetProject = create_model(
|
|
@@ -7,8 +7,9 @@ from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
|
7
7
|
from .api_wrapper import ReportPortalApiWrapper
|
|
8
8
|
from ..base.tool import BaseAction
|
|
9
9
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
10
|
-
from ..utils import clean_string,
|
|
10
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
11
11
|
from ...configurations.report_portal import ReportPortalConfiguration
|
|
12
|
+
from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
|
|
12
13
|
|
|
13
14
|
name = "report_portal"
|
|
14
15
|
|
|
@@ -21,13 +22,11 @@ def get_tools(tool):
|
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class ReportPortalToolkit(BaseToolkit):
|
|
24
|
-
tools:
|
|
25
|
-
toolkit_max_length: int = 0
|
|
25
|
+
tools: List[BaseTool] = []
|
|
26
26
|
|
|
27
27
|
@staticmethod
|
|
28
28
|
def toolkit_config_schema() -> BaseModel:
|
|
29
29
|
selected_tools = {x['name']: x['args_schema'].schema() for x in ReportPortalApiWrapper.model_construct().get_available_tools()}
|
|
30
|
-
ReportPortalToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
31
30
|
return create_model(
|
|
32
31
|
name,
|
|
33
32
|
report_portal_configuration=(ReportPortalConfiguration, Field(description="Report Portal Configuration", json_schema_extra={'configuration_types': ['report_portal']})),
|
|
@@ -47,17 +46,22 @@ class ReportPortalToolkit(BaseToolkit):
|
|
|
47
46
|
**kwargs.get('report_portal_configuration', {}),
|
|
48
47
|
}
|
|
49
48
|
report_portal_api_wrapper = ReportPortalApiWrapper(**wrapper_payload)
|
|
50
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
51
49
|
available_tools = report_portal_api_wrapper.get_available_tools()
|
|
52
50
|
tools = []
|
|
53
51
|
for tool in available_tools:
|
|
54
52
|
if selected_tools and tool["name"] not in selected_tools:
|
|
55
53
|
continue
|
|
54
|
+
description = tool['description']
|
|
55
|
+
if toolkit_name:
|
|
56
|
+
description = f"Toolkit: {toolkit_name}\n{description}"
|
|
57
|
+
description = f"{description}\nReport portal configuration: 'url - {report_portal_api_wrapper.endpoint}, project - {report_portal_api_wrapper.project}'"
|
|
58
|
+
description = description[:1000]
|
|
56
59
|
tools.append(BaseAction(
|
|
57
60
|
api_wrapper=report_portal_api_wrapper,
|
|
58
|
-
name=
|
|
59
|
-
description=
|
|
60
|
-
args_schema=tool["args_schema"]
|
|
61
|
+
name=tool["name"],
|
|
62
|
+
description=description,
|
|
63
|
+
args_schema=tool["args_schema"],
|
|
64
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
|
|
61
65
|
))
|
|
62
66
|
return cls(tools=tools)
|
|
63
67
|
|
|
@@ -5,8 +5,9 @@ from ..base.tool import BaseAction
|
|
|
5
5
|
from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
6
6
|
|
|
7
7
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
8
|
-
from ..utils import clean_string,
|
|
8
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
9
9
|
from ...configurations.salesforce import SalesforceConfiguration
|
|
10
|
+
from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
|
|
10
11
|
|
|
11
12
|
name = "salesforce"
|
|
12
13
|
|
|
@@ -19,11 +20,9 @@ def get_tools(tool):
|
|
|
19
20
|
|
|
20
21
|
class SalesforceToolkit(BaseToolkit):
|
|
21
22
|
tools: List[BaseTool] = []
|
|
22
|
-
toolkit_max_length: int = 0
|
|
23
23
|
@staticmethod
|
|
24
24
|
def toolkit_config_schema() -> BaseModel:
|
|
25
25
|
available_tools = {x['name']: x['args_schema'].schema() for x in SalesforceApiWrapper.model_construct().get_available_tools()}
|
|
26
|
-
SalesforceToolkit.toolkit_max_length = get_max_toolkit_length(available_tools)
|
|
27
26
|
return create_model(
|
|
28
27
|
name,
|
|
29
28
|
api_version=(str, Field(description="Salesforce API Version", default='v59.0')),
|
|
@@ -47,18 +46,21 @@ class SalesforceToolkit(BaseToolkit):
|
|
|
47
46
|
**kwargs.get('salesforce_configuration', {}),
|
|
48
47
|
}
|
|
49
48
|
api_wrapper = SalesforceApiWrapper(**wrapper_payload)
|
|
50
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
51
49
|
tools = []
|
|
52
50
|
|
|
53
51
|
for tool in api_wrapper.get_available_tools():
|
|
54
52
|
if selected_tools and tool["name"] not in selected_tools:
|
|
55
53
|
continue
|
|
56
|
-
|
|
54
|
+
description = f"Salesforce Tool: {tool['description']}"
|
|
55
|
+
if toolkit_name:
|
|
56
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
57
|
+
description = description[:1000]
|
|
57
58
|
tools.append(BaseAction(
|
|
58
59
|
api_wrapper=api_wrapper,
|
|
59
|
-
name=
|
|
60
|
-
description=
|
|
61
|
-
args_schema=tool["args_schema"]
|
|
60
|
+
name=tool["name"],
|
|
61
|
+
description=description,
|
|
62
|
+
args_schema=tool["args_schema"],
|
|
63
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
|
|
62
64
|
))
|
|
63
65
|
|
|
64
66
|
return cls(tools=tools)
|
|
@@ -7,37 +7,33 @@ from ..base.tool import BaseAction
|
|
|
7
7
|
from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
8
8
|
|
|
9
9
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
10
|
-
from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
|
|
11
10
|
from ...configurations.service_now import ServiceNowConfiguration
|
|
11
|
+
from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
name = "service_now"
|
|
15
15
|
|
|
16
16
|
def get_tools(tool):
|
|
17
|
+
settings = tool.get('settings') or {}
|
|
18
|
+
|
|
17
19
|
return ServiceNowToolkit().get_toolkit(
|
|
18
|
-
selected_tools=
|
|
19
|
-
instance_alias=
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
response_fields=tool['settings'].get('response_fields', None),
|
|
20
|
+
selected_tools=settings.get('selected_tools', []),
|
|
21
|
+
instance_alias=settings.get('instance_alias', None),
|
|
22
|
+
servicenow_configuration=settings.get('servicenow_configuration', None),
|
|
23
|
+
response_fields=settings.get('response_fields', None),
|
|
23
24
|
toolkit_name=tool.get('toolkit_name')
|
|
24
25
|
).get_tools()
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class ServiceNowToolkit(BaseToolkit):
|
|
28
29
|
tools: List[BaseTool] = []
|
|
29
|
-
toolkit_max_length: int = 0
|
|
30
30
|
|
|
31
31
|
@staticmethod
|
|
32
32
|
def toolkit_config_schema() -> BaseModel:
|
|
33
33
|
selected_tools = {x['name']: x['args_schema'].schema() for x in
|
|
34
34
|
ServiceNowAPIWrapper.model_construct().get_available_tools()}
|
|
35
|
-
ServiceNowToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
36
35
|
return create_model(
|
|
37
36
|
name,
|
|
38
|
-
name=(str, Field(description="Toolkit name",
|
|
39
|
-
json_schema_extra={
|
|
40
|
-
'toolkit_name': True, 'max_toolkit_length': ServiceNowToolkit.toolkit_max_length})),
|
|
41
37
|
response_fields=(Optional[str], Field(description="Response fields", default=None)),
|
|
42
38
|
servicenow_configuration=(ServiceNowConfiguration, Field(description="ServiceNow Configuration",
|
|
43
39
|
json_schema_extra={
|
|
@@ -80,18 +76,24 @@ class ServiceNowToolkit(BaseToolkit):
|
|
|
80
76
|
**kwargs['servicenow_configuration'],
|
|
81
77
|
}
|
|
82
78
|
servicenow_api_wrapper = ServiceNowAPIWrapper(**wrapper_payload)
|
|
83
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
84
79
|
available_tools = servicenow_api_wrapper.get_available_tools()
|
|
85
80
|
tools = []
|
|
86
81
|
for tool in available_tools:
|
|
87
82
|
if selected_tools:
|
|
88
83
|
if tool["name"] not in selected_tools:
|
|
89
84
|
continue
|
|
85
|
+
base_url = getattr(servicenow_api_wrapper, "base_url", "") or ""
|
|
86
|
+
description = tool.get("description", "") if isinstance(tool, dict) else ""
|
|
87
|
+
if toolkit_name:
|
|
88
|
+
description = f"Toolkit: {toolkit_name}\n{description}"
|
|
89
|
+
description = f"ServiceNow: {base_url}\n{description}".strip()
|
|
90
|
+
description = description[:1000]
|
|
90
91
|
tools.append(BaseAction(
|
|
91
92
|
api_wrapper=servicenow_api_wrapper,
|
|
92
|
-
name=
|
|
93
|
-
description=
|
|
94
|
-
args_schema=tool["args_schema"]
|
|
93
|
+
name=tool["name"],
|
|
94
|
+
description=description,
|
|
95
|
+
args_schema=tool["args_schema"],
|
|
96
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
|
|
95
97
|
))
|
|
96
98
|
return cls(tools=tools)
|
|
97
99
|
|
|
@@ -58,7 +58,7 @@ class ServiceNowAPIWrapper(BaseToolApiWrapper):
|
|
|
58
58
|
password = SecretStr(values['password'])
|
|
59
59
|
username = values['username']
|
|
60
60
|
cls.fields = values.get('fields', ['sys_id', 'number', 'state', 'short_description', 'description', 'priority', 'category', 'urgency', 'impact', 'creation_date'])
|
|
61
|
-
cls.client = ServiceNowClient(base_url, (username, password.get_secret_value()))
|
|
61
|
+
cls.client = ServiceNowClient(instance=base_url, auth=(username, password.get_secret_value()))
|
|
62
62
|
return values
|
|
63
63
|
|
|
64
64
|
def get_incidents(self, data: Optional[Dict[str, Any]] = None) -> ToolException | str:
|
|
@@ -5,9 +5,10 @@ from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
|
5
5
|
from .api_wrapper import SharepointApiWrapper
|
|
6
6
|
from ..base.tool import BaseAction
|
|
7
7
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
8
|
-
from ..utils import clean_string,
|
|
8
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
9
9
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
10
10
|
from ...configurations.sharepoint import SharepointConfiguration
|
|
11
|
+
from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
|
|
11
12
|
|
|
12
13
|
name = "sharepoint"
|
|
13
14
|
|
|
@@ -29,12 +30,10 @@ def get_tools(tool):
|
|
|
29
30
|
|
|
30
31
|
class SharepointToolkit(BaseToolkit):
|
|
31
32
|
tools: List[BaseTool] = []
|
|
32
|
-
toolkit_max_length: int = 0
|
|
33
33
|
|
|
34
34
|
@staticmethod
|
|
35
35
|
def toolkit_config_schema() -> BaseModel:
|
|
36
36
|
selected_tools = {x['name']: x['args_schema'].schema() for x in SharepointApiWrapper.model_construct().get_available_tools()}
|
|
37
|
-
SharepointToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
38
37
|
return create_model(
|
|
39
38
|
name,
|
|
40
39
|
sharepoint_configuration=(SharepointConfiguration, Field(description="SharePoint Configuration", json_schema_extra={'configuration_types': ['sharepoint']})),
|
|
@@ -64,18 +63,22 @@ class SharepointToolkit(BaseToolkit):
|
|
|
64
63
|
**(kwargs.get('pgvector_configuration') or {}),
|
|
65
64
|
}
|
|
66
65
|
sharepoint_api_wrapper = SharepointApiWrapper(**wrapper_payload)
|
|
67
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
68
66
|
available_tools = sharepoint_api_wrapper.get_available_tools()
|
|
69
67
|
tools = []
|
|
70
68
|
for tool in available_tools:
|
|
71
69
|
if selected_tools:
|
|
72
70
|
if tool["name"] not in selected_tools:
|
|
73
71
|
continue
|
|
72
|
+
description = f"Sharepoint {sharepoint_api_wrapper.site_url}\n{tool['description']}"
|
|
73
|
+
if toolkit_name:
|
|
74
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
75
|
+
description = description[:1000]
|
|
74
76
|
tools.append(BaseAction(
|
|
75
77
|
api_wrapper=sharepoint_api_wrapper,
|
|
76
|
-
name=
|
|
77
|
-
description=
|
|
78
|
-
args_schema=tool["args_schema"]
|
|
78
|
+
name=tool["name"],
|
|
79
|
+
description=description,
|
|
80
|
+
args_schema=tool["args_schema"],
|
|
81
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
|
|
79
82
|
))
|
|
80
83
|
return cls(tools=tools)
|
|
81
84
|
|
|
@@ -8,6 +8,7 @@ from office365.runtime.auth.client_credential import ClientCredential
|
|
|
8
8
|
from office365.sharepoint.client_context import ClientContext
|
|
9
9
|
from pydantic import Field, PrivateAttr, create_model, model_validator, SecretStr
|
|
10
10
|
|
|
11
|
+
from .utils import decode_sharepoint_string
|
|
11
12
|
from ..non_code_indexer_toolkit import NonCodeIndexerToolkit
|
|
12
13
|
from ..utils.content_parser import parse_file_content
|
|
13
14
|
from ...runtime.utils.utils import IndexerKeywords
|
|
@@ -19,7 +20,7 @@ NoInput = create_model(
|
|
|
19
20
|
ReadList = create_model(
|
|
20
21
|
"ReadList",
|
|
21
22
|
list_title=(str, Field(description="Name of a Sharepoint list to be read.")),
|
|
22
|
-
limit=(Optional[int], Field(description="Limit (maximum number) of list items to be returned", default=1000))
|
|
23
|
+
limit=(Optional[int], Field(description="Limit (maximum number) of list items to be returned", default=1000, gt=0))
|
|
23
24
|
)
|
|
24
25
|
|
|
25
26
|
GetFiles = create_model(
|
|
@@ -29,7 +30,7 @@ GetFiles = create_model(
|
|
|
29
30
|
"Can be called with synonyms, such as First, Top, etc., "
|
|
30
31
|
"or can be reflected just by a number for example 'Top 10 files'. "
|
|
31
32
|
"Use default value if not specified in a query WITH NO EXTRA "
|
|
32
|
-
"CONFIRMATION FROM A USER", default=100)),
|
|
33
|
+
"CONFIRMATION FROM A USER", default=100, gt=0)),
|
|
33
34
|
)
|
|
34
35
|
|
|
35
36
|
ReadDocument = create_model(
|
|
@@ -91,44 +92,100 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
|
|
|
91
92
|
target_list = self._client.web.lists.get_by_title(list_title)
|
|
92
93
|
self._client.load(target_list)
|
|
93
94
|
self._client.execute_query()
|
|
94
|
-
items = target_list.items.
|
|
95
|
-
logging.info("{0} items from sharepoint loaded successfully.".format(len(items)))
|
|
95
|
+
items = target_list.items.top(limit).get().execute_query()
|
|
96
|
+
logging.info("{0} items from sharepoint loaded successfully via SharePoint REST API.".format(len(items)))
|
|
96
97
|
result = []
|
|
97
98
|
for item in items:
|
|
98
99
|
result.append(item.properties)
|
|
99
100
|
return result
|
|
100
|
-
except Exception as
|
|
101
|
-
logging.
|
|
102
|
-
|
|
101
|
+
except Exception as base_e:
|
|
102
|
+
logging.warning(f"Primary SharePoint REST list read failed: {base_e}. Attempting Graph API fallback.")
|
|
103
|
+
# Attempt Graph API fallback
|
|
104
|
+
try:
|
|
105
|
+
from .authorization_helper import SharepointAuthorizationHelper
|
|
106
|
+
auth_helper = SharepointAuthorizationHelper(
|
|
107
|
+
client_id=self.client_id,
|
|
108
|
+
client_secret=self.client_secret.get_secret_value() if self.client_secret else None,
|
|
109
|
+
tenant="", # optional for graph api (derived inside helper)
|
|
110
|
+
scope="", # optional for graph api
|
|
111
|
+
token_json="", # not needed for client credentials flow here
|
|
112
|
+
)
|
|
113
|
+
graph_items = auth_helper.get_list_items(self.site_url, list_title, limit)
|
|
114
|
+
if graph_items:
|
|
115
|
+
logging.info(f"{len(graph_items)} items from sharepoint loaded successfully via Graph API fallback.")
|
|
116
|
+
return graph_items
|
|
117
|
+
else:
|
|
118
|
+
return ToolException("List appears empty or inaccessible via both REST and Graph APIs.")
|
|
119
|
+
except Exception as graph_e:
|
|
120
|
+
logging.error(f"Graph API fallback failed: {graph_e}")
|
|
121
|
+
return ToolException(f"Cannot read list '{list_title}'. Check list name and permissions: {base_e} | {graph_e}")
|
|
103
122
|
|
|
104
123
|
|
|
105
124
|
def get_files_list(self, folder_name: str = None, limit_files: int = 100):
|
|
106
125
|
""" If folder name is specified, lists all files in this folder under Shared Documents path. If folder name is empty, lists all files under root catalog (Shared Documents). Number of files is limited by limit_files (default is 100)."""
|
|
107
126
|
try:
|
|
127
|
+
# exclude default system libraries like 'Form Templates', 'Site Assets', 'Style Library'
|
|
128
|
+
all_libraries = self._client.web.lists.filter("BaseTemplate eq 101 and Title ne 'Form Templates' and Title ne 'Site Assets' and Title ne 'Style Library'").get().execute_query()
|
|
108
129
|
result = []
|
|
109
130
|
if not limit_files:
|
|
110
131
|
limit_files = 100
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
#
|
|
133
|
+
site_segments = [seg for seg in self.site_url.strip('/').split('/') if seg][-2:]
|
|
134
|
+
full_path_prefix = '/'.join(site_segments)
|
|
135
|
+
#
|
|
136
|
+
for lib in all_libraries:
|
|
137
|
+
library_type = decode_sharepoint_string(lib.properties["EntityTypeName"])
|
|
138
|
+
target_folder_url = library_type
|
|
139
|
+
if folder_name:
|
|
140
|
+
folder_path = folder_name.strip('/')
|
|
141
|
+
expected_prefix = f'{full_path_prefix}/{library_type}'
|
|
142
|
+
if folder_path.startswith(full_path_prefix):
|
|
143
|
+
if folder_path.startswith(expected_prefix):
|
|
144
|
+
target_folder_url = folder_path.removeprefix(f'{full_path_prefix}/')
|
|
145
|
+
else:
|
|
146
|
+
# ignore full path folder which is not targeted to current library
|
|
147
|
+
continue
|
|
148
|
+
else:
|
|
149
|
+
target_folder_url = f"{library_type}/{folder_name}"
|
|
150
|
+
#
|
|
151
|
+
files = (self._client.web.get_folder_by_server_relative_path(target_folder_url)
|
|
152
|
+
.get_files(True)
|
|
153
|
+
.execute_query())
|
|
154
|
+
#
|
|
155
|
+
for file in files:
|
|
156
|
+
if f"{library_type}/Forms" in file.properties['ServerRelativeUrl']:
|
|
157
|
+
# skip files from system folder "Forms"
|
|
158
|
+
continue
|
|
159
|
+
if len(result) >= limit_files:
|
|
160
|
+
break
|
|
161
|
+
temp_props = {
|
|
162
|
+
'Name': file.properties['Name'],
|
|
163
|
+
'Path': file.properties['ServerRelativeUrl'],
|
|
164
|
+
'Created': file.properties['TimeCreated'],
|
|
165
|
+
'Modified': file.properties['TimeLastModified'],
|
|
166
|
+
'Link': file.properties['LinkingUrl'],
|
|
167
|
+
'id': file.properties['UniqueId']
|
|
168
|
+
}
|
|
169
|
+
result.append(temp_props)
|
|
128
170
|
return result if result else ToolException("Can not get files or folder is empty. Please, double check folder name and read permissions.")
|
|
129
171
|
except Exception as e:
|
|
130
|
-
|
|
131
|
-
|
|
172
|
+
# attempt to get via graph api
|
|
173
|
+
try:
|
|
174
|
+
# attempt to get files via graph api
|
|
175
|
+
from .authorization_helper import SharepointAuthorizationHelper
|
|
176
|
+
auth_helper = SharepointAuthorizationHelper(
|
|
177
|
+
client_id=self.client_id,
|
|
178
|
+
client_secret=self.client_secret.get_secret_value(),
|
|
179
|
+
tenant="", # optional for graph api
|
|
180
|
+
scope="", # optional for graph api
|
|
181
|
+
token_json="", # optional for graph api
|
|
182
|
+
)
|
|
183
|
+
files = auth_helper.get_files_list(self.site_url, folder_name, limit_files)
|
|
184
|
+
return files
|
|
185
|
+
except Exception as graph_e:
|
|
186
|
+
logging.error(f"Failed to load files from sharepoint via base api: {e}")
|
|
187
|
+
logging.error(f"Failed to load files from sharepoint via graph api: {graph_e}")
|
|
188
|
+
return ToolException(f"Can not get files. Please, double check folder name and read permissions: {e} and {graph_e}")
|
|
132
189
|
|
|
133
190
|
def read_file(self, path,
|
|
134
191
|
is_capture_image: bool = False,
|
|
@@ -141,11 +198,28 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
|
|
|
141
198
|
self._client.load(file).execute_query()
|
|
142
199
|
|
|
143
200
|
file_content = file.read()
|
|
201
|
+
file_name = file.name
|
|
144
202
|
self._client.execute_query()
|
|
145
203
|
except Exception as e:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
204
|
+
# attempt to get via graph api
|
|
205
|
+
try:
|
|
206
|
+
# attempt to get files via graph api
|
|
207
|
+
from .authorization_helper import SharepointAuthorizationHelper
|
|
208
|
+
auth_helper = SharepointAuthorizationHelper(
|
|
209
|
+
client_id=self.client_id,
|
|
210
|
+
client_secret=self.client_secret.get_secret_value(),
|
|
211
|
+
tenant="", # optional for graph api
|
|
212
|
+
scope="", # optional for graph api
|
|
213
|
+
token_json="", # optional for graph api
|
|
214
|
+
)
|
|
215
|
+
file_content = auth_helper.get_file_content(self.site_url, path)
|
|
216
|
+
file_name = path.split('/')[-1]
|
|
217
|
+
except Exception as graph_e:
|
|
218
|
+
logging.error(f"Failed to load file from SharePoint via base api: {e}. Path: {path}. Please, double check file name and path.")
|
|
219
|
+
logging.error(f"Failed to load file from SharePoint via graph api: {graph_e}. Path: {path}. Please, double check file name and path.")
|
|
220
|
+
return ToolException(f"File not found. Please, check file name and path: {e} and {graph_e}")
|
|
221
|
+
#
|
|
222
|
+
return parse_file_content(file_name=file_name,
|
|
149
223
|
file_content=file_content,
|
|
150
224
|
is_capture_image=is_capture_image,
|
|
151
225
|
page_number=page_number,
|
|
@@ -167,13 +241,18 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
|
|
|
167
241
|
'skip_extensions': (Optional[List[str]], Field(
|
|
168
242
|
description="List of file extensions to skip when processing: i.e. ['*.png', '*.jpg']",
|
|
169
243
|
default=[])),
|
|
244
|
+
'path': (Optional[str], Field(
|
|
245
|
+
description="Folder path. "
|
|
246
|
+
"Accepts either a full server-relative path (e.g., '/sites/SiteName/...') or a relative path. "
|
|
247
|
+
"If a relative path is provided, the search will be performed recursively under 'Shared Documents' and other private libraries.",
|
|
248
|
+
default=None)),
|
|
170
249
|
}
|
|
171
250
|
|
|
172
251
|
def _base_loader(self, **kwargs) -> Generator[Document, None, None]:
|
|
173
252
|
|
|
174
253
|
self._log_tool_event(message="Starting SharePoint files extraction", tool_name="loader")
|
|
175
254
|
try:
|
|
176
|
-
all_files = self.get_files_list(
|
|
255
|
+
all_files = self.get_files_list(kwargs.get('path'), kwargs.get('limit_files', 10000))
|
|
177
256
|
self._log_tool_event(message="List of the files has been extracted", tool_name="loader")
|
|
178
257
|
except Exception as e:
|
|
179
258
|
raise ToolException(f"Unable to extract files: {e}")
|
|
@@ -192,13 +271,13 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
|
|
|
192
271
|
file_name = file.get('Name', '')
|
|
193
272
|
|
|
194
273
|
# Check if file should be skipped based on skip_extensions
|
|
195
|
-
if any(re.match(pattern.replace('
|
|
274
|
+
if any(re.match(re.escape(pattern).replace(r'\*', '.*') + '$', file_name, re.IGNORECASE)
|
|
196
275
|
for pattern in skip_extensions):
|
|
197
276
|
continue
|
|
198
277
|
|
|
199
278
|
# Check if file should be included based on include_extensions
|
|
200
279
|
# If include_extensions is empty, process all files (that weren't skipped)
|
|
201
|
-
if include_extensions and not (any(re.match(pattern.replace('
|
|
280
|
+
if include_extensions and not (any(re.match(re.escape(pattern).replace(r'\*', '.*') + '$', file_name, re.IGNORECASE)
|
|
202
281
|
for pattern in include_extensions)):
|
|
203
282
|
continue
|
|
204
283
|
|
|
@@ -219,12 +298,24 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
|
|
|
219
298
|
yield document
|
|
220
299
|
|
|
221
300
|
def _load_file_content_in_bytes(self, path):
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
301
|
+
try:
|
|
302
|
+
file = self._client.web.get_file_by_server_relative_path(path)
|
|
303
|
+
self._client.load(file).execute_query()
|
|
304
|
+
file_content = file.read()
|
|
305
|
+
self._client.execute_query()
|
|
306
|
+
#
|
|
307
|
+
return file_content
|
|
308
|
+
except Exception as e:
|
|
309
|
+
# attempt to get via graph api
|
|
310
|
+
from .authorization_helper import SharepointAuthorizationHelper
|
|
311
|
+
auth_helper = SharepointAuthorizationHelper(
|
|
312
|
+
client_id=self.client_id,
|
|
313
|
+
client_secret=self.client_secret.get_secret_value(),
|
|
314
|
+
tenant="", # optional for graph api
|
|
315
|
+
scope="", # optional for graph api
|
|
316
|
+
token_json="", # optional for graph api
|
|
317
|
+
)
|
|
318
|
+
return auth_helper.get_file_content(self.site_url, path)
|
|
228
319
|
|
|
229
320
|
def get_available_tools(self):
|
|
230
321
|
return super().get_available_tools() + [
|