alita-sdk 0.3.351__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/bitbucket.py +94 -2
- alita_sdk/configurations/confluence.py +96 -1
- alita_sdk/configurations/gitlab.py +79 -0
- alita_sdk/configurations/jira.py +103 -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 +1 -1
- alita_sdk/runtime/clients/client.py +214 -42
- 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 +118 -30
- 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 +103 -60
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +4 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +41 -12
- alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -1
- alita_sdk/runtime/langchain/document_loaders/constants.py +116 -99
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +2 -2
- alita_sdk/runtime/langchain/langraph_agent.py +307 -71
- alita_sdk/runtime/langchain/utils.py +48 -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 +18 -6
- 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/tools.py +205 -55
- alita_sdk/runtime/toolkits/vectorstore.py +9 -4
- alita_sdk/runtime/tools/__init__.py +11 -3
- alita_sdk/runtime/tools/application.py +7 -0
- alita_sdk/runtime/tools/artifact.py +225 -12
- alita_sdk/runtime/tools/function.py +95 -5
- alita_sdk/runtime/tools/graph.py +10 -4
- alita_sdk/runtime/tools/image_generation.py +212 -0
- alita_sdk/runtime/tools/llm.py +494 -102
- 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 +4 -4
- 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 +180 -79
- alita_sdk/runtime/tools/vectorstore.py +22 -21
- alita_sdk/runtime/tools/vectorstore_base.py +125 -52
- 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 +40 -13
- alita_sdk/runtime/utils/toolkit_utils.py +28 -9
- alita_sdk/runtime/utils/utils.py +12 -0
- alita_sdk/tools/__init__.py +77 -33
- alita_sdk/tools/ado/repos/__init__.py +7 -6
- alita_sdk/tools/ado/repos/repos_wrapper.py +11 -11
- alita_sdk/tools/ado/test_plan/__init__.py +7 -7
- alita_sdk/tools/ado/wiki/__init__.py +7 -11
- alita_sdk/tools/ado/wiki/ado_wrapper.py +89 -15
- alita_sdk/tools/ado/work_item/__init__.py +7 -11
- alita_sdk/tools/ado/work_item/ado_wrapper.py +17 -8
- alita_sdk/tools/advanced_jira_mining/__init__.py +8 -7
- alita_sdk/tools/aws/delta_lake/__init__.py +11 -9
- alita_sdk/tools/azure_ai/search/__init__.py +7 -6
- alita_sdk/tools/base_indexer_toolkit.py +345 -70
- alita_sdk/tools/bitbucket/__init__.py +9 -8
- alita_sdk/tools/bitbucket/api_wrapper.py +50 -6
- alita_sdk/tools/browser/__init__.py +4 -4
- alita_sdk/tools/carrier/__init__.py +4 -6
- alita_sdk/tools/chunkers/__init__.py +3 -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 +7 -6
- alita_sdk/tools/cloud/azure/__init__.py +7 -6
- alita_sdk/tools/cloud/gcp/__init__.py +7 -6
- alita_sdk/tools/cloud/k8s/__init__.py +7 -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 +8 -7
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +9 -8
- alita_sdk/tools/confluence/api_wrapper.py +171 -75
- 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 +492 -52
- alita_sdk/tools/figma/__init__.py +7 -7
- alita_sdk/tools/figma/api_wrapper.py +2 -1
- alita_sdk/tools/github/__init__.py +9 -9
- alita_sdk/tools/github/api_wrapper.py +9 -26
- alita_sdk/tools/github/github_client.py +62 -2
- alita_sdk/tools/gitlab/__init__.py +8 -8
- alita_sdk/tools/gitlab/api_wrapper.py +135 -33
- alita_sdk/tools/gitlab_org/__init__.py +7 -8
- alita_sdk/tools/google/bigquery/__init__.py +11 -12
- alita_sdk/tools/google_places/__init__.py +8 -7
- alita_sdk/tools/jira/__init__.py +9 -7
- alita_sdk/tools/jira/api_wrapper.py +100 -52
- alita_sdk/tools/keycloak/__init__.py +8 -7
- alita_sdk/tools/localgit/local_git.py +56 -54
- alita_sdk/tools/memory/__init__.py +1 -1
- alita_sdk/tools/non_code_indexer_toolkit.py +3 -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/postman/__init__.py +7 -8
- 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 +16 -11
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +7 -8
- alita_sdk/tools/report_portal/__init__.py +9 -7
- alita_sdk/tools/salesforce/__init__.py +7 -7
- alita_sdk/tools/servicenow/__init__.py +10 -10
- alita_sdk/tools/sharepoint/__init__.py +7 -6
- alita_sdk/tools/sharepoint/api_wrapper.py +127 -36
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +7 -6
- alita_sdk/tools/sql/__init__.py +8 -7
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +7 -6
- alita_sdk/tools/testrail/__init__.py +8 -9
- alita_sdk/tools/utils/__init__.py +26 -4
- alita_sdk/tools/utils/content_parser.py +88 -60
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +76 -26
- alita_sdk/tools/xray/__init__.py +9 -7
- alita_sdk/tools/zephyr/__init__.py +7 -6
- alita_sdk/tools/zephyr_enterprise/__init__.py +8 -6
- alita_sdk/tools/zephyr_essential/__init__.py +7 -6
- alita_sdk/tools/zephyr_essential/api_wrapper.py +12 -13
- alita_sdk/tools/zephyr_scale/__init__.py +7 -6
- alita_sdk/tools/zephyr_squad/__init__.py +7 -6
- {alita_sdk-0.3.351.dist-info → alita_sdk-0.3.499.dist-info}/METADATA +147 -2
- {alita_sdk-0.3.351.dist-info → alita_sdk-0.3.499.dist-info}/RECORD +206 -130
- alita_sdk-0.3.499.dist-info/entry_points.txt +2 -0
- {alita_sdk-0.3.351.dist-info → alita_sdk-0.3.499.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.351.dist-info → alita_sdk-0.3.499.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.351.dist-info → alita_sdk-0.3.499.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ from pydantic import BaseModel, ConfigDict, Field, create_model
|
|
|
6
6
|
from ..base.tool import BaseAction
|
|
7
7
|
from .api_wrapper import FigmaApiWrapper, GLOBAL_LIMIT
|
|
8
8
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
9
|
-
from ..utils import clean_string,
|
|
9
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
10
10
|
from ...configurations.figma import FigmaConfiguration
|
|
11
11
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
12
12
|
|
|
@@ -36,7 +36,6 @@ def get_tools(tool):
|
|
|
36
36
|
|
|
37
37
|
class FigmaToolkit(BaseToolkit):
|
|
38
38
|
tools: List[BaseTool] = []
|
|
39
|
-
toolkit_max_length: int = 0
|
|
40
39
|
|
|
41
40
|
@staticmethod
|
|
42
41
|
def toolkit_config_schema() -> BaseModel:
|
|
@@ -44,7 +43,6 @@ class FigmaToolkit(BaseToolkit):
|
|
|
44
43
|
x["name"]: x["args_schema"].schema()
|
|
45
44
|
for x in FigmaApiWrapper.model_construct().get_available_tools()
|
|
46
45
|
}
|
|
47
|
-
FigmaToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
48
46
|
return create_model(
|
|
49
47
|
name,
|
|
50
48
|
global_limit=(Optional[int], Field(description="Global limit", default=GLOBAL_LIMIT)),
|
|
@@ -66,7 +64,6 @@ class FigmaToolkit(BaseToolkit):
|
|
|
66
64
|
"metadata": {
|
|
67
65
|
"label": "Figma",
|
|
68
66
|
"icon_url": "figma-icon.svg",
|
|
69
|
-
"max_length": FigmaToolkit.toolkit_max_length,
|
|
70
67
|
"categories": ["other"],
|
|
71
68
|
"extra_categories": ["figma", "design", "ui/ux", "prototyping", "collaboration"],
|
|
72
69
|
}
|
|
@@ -85,18 +82,21 @@ class FigmaToolkit(BaseToolkit):
|
|
|
85
82
|
**(kwargs.get('pgvector_configuration') or {}),
|
|
86
83
|
}
|
|
87
84
|
figma_api_wrapper = FigmaApiWrapper(**wrapper_payload)
|
|
88
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
89
85
|
available_tools = figma_api_wrapper.get_available_tools()
|
|
90
86
|
tools = []
|
|
91
87
|
for tool in available_tools:
|
|
92
88
|
if selected_tools:
|
|
93
89
|
if tool["name"] not in selected_tools:
|
|
94
90
|
continue
|
|
91
|
+
description = tool["description"]
|
|
92
|
+
if toolkit_name:
|
|
93
|
+
description = f"Toolkit: {toolkit_name}\n{description}"
|
|
94
|
+
description = description[:1000]
|
|
95
95
|
tools.append(
|
|
96
96
|
BaseAction(
|
|
97
97
|
api_wrapper=figma_api_wrapper,
|
|
98
|
-
name=
|
|
99
|
-
description=
|
|
98
|
+
name=tool["name"],
|
|
99
|
+
description=description,
|
|
100
100
|
args_schema=tool["args_schema"],
|
|
101
101
|
)
|
|
102
102
|
)
|
|
@@ -345,7 +345,8 @@ class FigmaApiWrapper(NonCodeIndexerToolkit):
|
|
|
345
345
|
text_nodes[node['id']] = self.get_texts_recursive(node)
|
|
346
346
|
# process image nodes
|
|
347
347
|
if image_nodes:
|
|
348
|
-
|
|
348
|
+
file_images = self._client.get_file_images(file_key, image_nodes)
|
|
349
|
+
images = self._client.get_file_images(file_key, image_nodes).images or {} if file_images else {}
|
|
349
350
|
total_images = len(images)
|
|
350
351
|
if total_images == 0:
|
|
351
352
|
logging.info(f"No images found for file {file_key}.")
|
|
@@ -7,7 +7,7 @@ from .api_wrapper import AlitaGitHubAPIWrapper
|
|
|
7
7
|
from .tool import GitHubAction
|
|
8
8
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
9
9
|
|
|
10
|
-
from ..utils import clean_string,
|
|
10
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
11
11
|
from ...configurations.github import GithubConfiguration
|
|
12
12
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
13
13
|
|
|
@@ -39,13 +39,11 @@ def get_tools(tool):
|
|
|
39
39
|
|
|
40
40
|
class AlitaGitHubToolkit(BaseToolkit):
|
|
41
41
|
tools: List[BaseTool] = []
|
|
42
|
-
toolkit_max_length: int = 0
|
|
43
42
|
|
|
44
43
|
@staticmethod
|
|
45
44
|
def toolkit_config_schema() -> BaseModel:
|
|
46
45
|
selected_tools = {x['name']: x['args_schema'].schema() for x in
|
|
47
46
|
AlitaGitHubAPIWrapper.model_construct().get_available_tools()}
|
|
48
|
-
AlitaGitHubToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
49
47
|
return create_model(
|
|
50
48
|
name,
|
|
51
49
|
__config__=ConfigDict(
|
|
@@ -62,8 +60,7 @@ class AlitaGitHubToolkit(BaseToolkit):
|
|
|
62
60
|
json_schema_extra={'configuration_types': ['github']})),
|
|
63
61
|
pgvector_configuration=(Optional[PgVectorConfiguration], Field(description="PgVector configuration", default=None,
|
|
64
62
|
json_schema_extra={'configuration_types': ['pgvector']})),
|
|
65
|
-
repository=(str, Field(description="Github repository",
|
|
66
|
-
'max_toolkit_length': AlitaGitHubToolkit.toolkit_max_length})),
|
|
63
|
+
repository=(str, Field(description="Github repository")),
|
|
67
64
|
active_branch=(Optional[str], Field(description="Active branch", default="main")),
|
|
68
65
|
base_branch=(Optional[str], Field(description="Github Base branch", default="main")),
|
|
69
66
|
# embedder settings
|
|
@@ -87,17 +84,20 @@ class AlitaGitHubToolkit(BaseToolkit):
|
|
|
87
84
|
github_api_wrapper = AlitaGitHubAPIWrapper(**wrapper_payload)
|
|
88
85
|
available_tools: List[Dict] = github_api_wrapper.get_available_tools()
|
|
89
86
|
tools = []
|
|
90
|
-
prefix = clean_string(toolkit_name, AlitaGitHubToolkit.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
91
87
|
for tool in available_tools:
|
|
92
88
|
if selected_tools:
|
|
93
89
|
if tool["name"] not in selected_tools:
|
|
94
90
|
continue
|
|
91
|
+
description = tool["description"]
|
|
92
|
+
if toolkit_name:
|
|
93
|
+
description = f"Toolkit: {toolkit_name}\n{description}"
|
|
94
|
+
description = f"Repository: {github_api_wrapper.github_repository}\n{description}"
|
|
95
|
+
description = description[:1000]
|
|
95
96
|
tools.append(GitHubAction(
|
|
96
97
|
api_wrapper=github_api_wrapper,
|
|
97
|
-
name=
|
|
98
|
+
name=tool["name"],
|
|
98
99
|
mode=tool["mode"],
|
|
99
|
-
|
|
100
|
-
description=f"Repository: {github_api_wrapper.github_repository}\n" + tool["description"],
|
|
100
|
+
description=description,
|
|
101
101
|
args_schema=tool["args_schema"]
|
|
102
102
|
))
|
|
103
103
|
return cls(tools=tools)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
from typing import Any, Dict, List, Optional, Union, Tuple
|
|
2
1
|
import logging
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
from pydantic import BaseModel, model_validator, Field, SecretStr
|
|
2
|
+
from typing import Any, Dict, Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import model_validator, Field, SecretStr
|
|
7
5
|
|
|
8
6
|
from .github_client import GitHubClient
|
|
9
7
|
from .graphql_client_wrapper import GraphQLClientWrapper
|
|
@@ -11,28 +9,17 @@ from .schemas import (
|
|
|
11
9
|
GitHubAuthConfig,
|
|
12
10
|
GitHubRepoConfig
|
|
13
11
|
)
|
|
14
|
-
|
|
15
|
-
from ..
|
|
16
|
-
|
|
17
|
-
from langchain_core.callbacks import dispatch_custom_event
|
|
12
|
+
from ..code_indexer_toolkit import CodeIndexerToolkit
|
|
13
|
+
from ..utils.available_tools_decorator import extend_with_parent_available_tools
|
|
18
14
|
|
|
19
15
|
logger = logging.getLogger(__name__)
|
|
20
16
|
|
|
21
17
|
# Import prompts for tools
|
|
22
|
-
from .tool_prompts import (
|
|
23
|
-
UPDATE_FILE_PROMPT,
|
|
24
|
-
CREATE_ISSUE_PROMPT,
|
|
25
|
-
UPDATE_ISSUE_PROMPT,
|
|
26
|
-
CREATE_ISSUE_ON_PROJECT_PROMPT,
|
|
27
|
-
UPDATE_ISSUE_ON_PROJECT_PROMPT
|
|
28
|
-
)
|
|
29
18
|
|
|
30
19
|
# Create schema models for the new indexing functionality
|
|
31
|
-
from pydantic import create_model
|
|
32
|
-
from typing import Literal
|
|
33
20
|
|
|
34
21
|
|
|
35
|
-
class AlitaGitHubAPIWrapper(
|
|
22
|
+
class AlitaGitHubAPIWrapper(CodeIndexerToolkit):
|
|
36
23
|
"""
|
|
37
24
|
Wrapper for GitHub API that integrates both REST and GraphQL functionality.
|
|
38
25
|
"""
|
|
@@ -117,7 +104,7 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
117
104
|
if "llm" not in values:
|
|
118
105
|
values["llm"] = None
|
|
119
106
|
|
|
120
|
-
return values
|
|
107
|
+
return super().validate_toolkit(values)
|
|
121
108
|
|
|
122
109
|
# Expose GitHub REST client methods directly via property
|
|
123
110
|
@property
|
|
@@ -131,7 +118,7 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
131
118
|
"""Access to GitHub GraphQL client methods"""
|
|
132
119
|
return self.graphql_client_instance
|
|
133
120
|
|
|
134
|
-
|
|
121
|
+
@extend_with_parent_available_tools
|
|
135
122
|
def get_available_tools(self):
|
|
136
123
|
# this is horrible, I need to think on something better
|
|
137
124
|
if not self.github_client_instance:
|
|
@@ -142,12 +129,8 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
142
129
|
graphql_tools = GraphQLClientWrapper.model_construct().get_available_tools()
|
|
143
130
|
else:
|
|
144
131
|
graphql_tools = self.graphql_client_instance.get_available_tools()
|
|
145
|
-
|
|
146
|
-
# Add vector search tools from base class (includes index_data + search tools)
|
|
147
|
-
vector_search_tools = self._get_vector_search_tools()
|
|
148
132
|
|
|
149
|
-
|
|
150
|
-
return tools
|
|
133
|
+
return github_tools + graphql_tools
|
|
151
134
|
|
|
152
135
|
def _get_files(self, path: str = "", branch: str = None):
|
|
153
136
|
"""Get list of files from GitHub repository."""
|
|
@@ -11,6 +11,7 @@ from github import Auth, Github, GithubIntegration, Repository
|
|
|
11
11
|
from github.Consts import DEFAULT_BASE_URL
|
|
12
12
|
from langchain_core.tools import ToolException
|
|
13
13
|
|
|
14
|
+
from ..elitea_base import extend_with_file_operations
|
|
14
15
|
from .schemas import (
|
|
15
16
|
GitHubAuthConfig,
|
|
16
17
|
GitHubRepoConfig,
|
|
@@ -1414,13 +1415,16 @@ class GitHubClient(BaseModel):
|
|
|
1414
1415
|
except Exception as e:
|
|
1415
1416
|
return f"File not found `{file_path}` on branch `{branch}`. Error: {str(e)}"
|
|
1416
1417
|
|
|
1417
|
-
def _read_file(self, file_path: str, branch: str, repo_name: Optional[str] = None) -> str:
|
|
1418
|
+
def _read_file(self, file_path: str, branch: str, repo_name: Optional[str] = None, **kwargs) -> str:
|
|
1418
1419
|
"""
|
|
1419
|
-
Read a file from specified branch
|
|
1420
|
+
Read a file from specified branch with optional partial read support.
|
|
1421
|
+
|
|
1420
1422
|
Parameters:
|
|
1421
1423
|
file_path(str): the file path
|
|
1422
1424
|
branch(str): the branch to read the file from
|
|
1423
1425
|
repo_name (Optional[str]): Name of the repository in format 'owner/repo'
|
|
1426
|
+
**kwargs: Additional parameters (offset, limit, head, tail) - currently ignored,
|
|
1427
|
+
partial read handled client-side by base class methods
|
|
1424
1428
|
|
|
1425
1429
|
Returns:
|
|
1426
1430
|
str: The file decoded as a string, or an error message if not found
|
|
@@ -1445,6 +1449,61 @@ class GitHubClient(BaseModel):
|
|
|
1445
1449
|
str: The file contents as a string
|
|
1446
1450
|
"""
|
|
1447
1451
|
return self._read_file(file_path, branch if branch else self.active_branch, repo_name)
|
|
1452
|
+
|
|
1453
|
+
def _write_file(
|
|
1454
|
+
self,
|
|
1455
|
+
file_path: str,
|
|
1456
|
+
content: str,
|
|
1457
|
+
branch: str = None,
|
|
1458
|
+
commit_message: str = None,
|
|
1459
|
+
repo_name: Optional[str] = None
|
|
1460
|
+
) -> str:
|
|
1461
|
+
"""
|
|
1462
|
+
Write content to a file (create or update).
|
|
1463
|
+
|
|
1464
|
+
Parameters:
|
|
1465
|
+
file_path: Path to the file
|
|
1466
|
+
content: New file content
|
|
1467
|
+
branch: Branch name (uses active branch if None)
|
|
1468
|
+
commit_message: Commit message
|
|
1469
|
+
repo_name: Name of the repository in format 'owner/repo'
|
|
1470
|
+
|
|
1471
|
+
Returns:
|
|
1472
|
+
Success message
|
|
1473
|
+
"""
|
|
1474
|
+
try:
|
|
1475
|
+
repo = self.github_api.get_repo(repo_name) if repo_name else self.github_repo_instance
|
|
1476
|
+
branch = branch or self.active_branch
|
|
1477
|
+
|
|
1478
|
+
if branch == self.github_base_branch:
|
|
1479
|
+
raise ToolException(
|
|
1480
|
+
f"Cannot commit directly to the {self.github_base_branch} branch. "
|
|
1481
|
+
"Please create a new branch and try again."
|
|
1482
|
+
)
|
|
1483
|
+
|
|
1484
|
+
# Check if file exists
|
|
1485
|
+
try:
|
|
1486
|
+
existing_file = repo.get_contents(file_path, ref=branch)
|
|
1487
|
+
# File exists, update it
|
|
1488
|
+
repo.update_file(
|
|
1489
|
+
path=file_path,
|
|
1490
|
+
message=commit_message or f"Update {file_path}",
|
|
1491
|
+
content=content,
|
|
1492
|
+
branch=branch,
|
|
1493
|
+
sha=existing_file.sha,
|
|
1494
|
+
)
|
|
1495
|
+
return f"Updated file {file_path}"
|
|
1496
|
+
except:
|
|
1497
|
+
# File doesn't exist, create it
|
|
1498
|
+
repo.create_file(
|
|
1499
|
+
path=file_path,
|
|
1500
|
+
message=commit_message or f"Create {file_path}",
|
|
1501
|
+
content=content,
|
|
1502
|
+
branch=branch,
|
|
1503
|
+
)
|
|
1504
|
+
return f"Created file {file_path}"
|
|
1505
|
+
except Exception as e:
|
|
1506
|
+
raise ToolException(f"Unable to write file {file_path}: {str(e)}")
|
|
1448
1507
|
|
|
1449
1508
|
def loader(self,
|
|
1450
1509
|
branch: Optional[str] = None,
|
|
@@ -1877,6 +1936,7 @@ class GitHubClient(BaseModel):
|
|
|
1877
1936
|
import traceback
|
|
1878
1937
|
return f"API call failed: {traceback.format_exc()}"
|
|
1879
1938
|
|
|
1939
|
+
@extend_with_file_operations
|
|
1880
1940
|
def get_available_tools(self) -> List[Dict[str, Any]]:
|
|
1881
1941
|
return [
|
|
1882
1942
|
{
|
|
@@ -8,7 +8,7 @@ from pydantic.fields import Field
|
|
|
8
8
|
|
|
9
9
|
from .api_wrapper import GitLabAPIWrapper
|
|
10
10
|
from ..elitea_base import filter_missconfigured_index_tools
|
|
11
|
-
from ..utils import clean_string,
|
|
11
|
+
from ..utils import clean_string, get_max_toolkit_length
|
|
12
12
|
from ...configurations.gitlab import GitlabConfiguration
|
|
13
13
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
14
14
|
|
|
@@ -34,16 +34,14 @@ def get_tools(tool):
|
|
|
34
34
|
|
|
35
35
|
class AlitaGitlabToolkit(BaseToolkit):
|
|
36
36
|
tools: List[BaseTool] = []
|
|
37
|
-
toolkit_max_length: int = 0
|
|
38
37
|
|
|
39
38
|
@staticmethod
|
|
40
39
|
def toolkit_config_schema() -> BaseModel:
|
|
41
40
|
selected_tools = {x['name']: x['args_schema'].schema() for x in
|
|
42
41
|
GitLabAPIWrapper.model_construct().get_available_tools()}
|
|
43
|
-
AlitaGitlabToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
44
42
|
return create_model(
|
|
45
43
|
name,
|
|
46
|
-
repository=(str, Field(description="GitLab repository"
|
|
44
|
+
repository=(str, Field(description="GitLab repository")),
|
|
47
45
|
gitlab_configuration=(GitlabConfiguration, Field(description="GitLab configuration", json_schema_extra={'configuration_types': ['gitlab']})),
|
|
48
46
|
branch=(str, Field(description="Main branch", default="main")),
|
|
49
47
|
# indexer settings
|
|
@@ -76,18 +74,20 @@ class AlitaGitlabToolkit(BaseToolkit):
|
|
|
76
74
|
**(kwargs.get('embedding_configuration') or {}),
|
|
77
75
|
}
|
|
78
76
|
gitlab_api_wrapper = GitLabAPIWrapper(**wrapper_payload)
|
|
79
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
80
77
|
available_tools: List[Dict] = gitlab_api_wrapper.get_available_tools()
|
|
81
78
|
tools = []
|
|
82
79
|
for tool in available_tools:
|
|
83
80
|
if selected_tools:
|
|
84
81
|
if tool["name"] not in selected_tools:
|
|
85
82
|
continue
|
|
86
|
-
|
|
83
|
+
description = tool["description"] + f"\nrepo: {gitlab_api_wrapper.repository}"
|
|
84
|
+
if toolkit_name:
|
|
85
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
86
|
+
description = description[:1000]
|
|
87
87
|
tools.append(BaseAction(
|
|
88
88
|
api_wrapper=gitlab_api_wrapper,
|
|
89
|
-
name=
|
|
90
|
-
description=
|
|
89
|
+
name=tool["name"],
|
|
90
|
+
description=description,
|
|
91
91
|
args_schema=tool["args_schema"]
|
|
92
92
|
))
|
|
93
93
|
return cls(tools=tools)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# api_wrapper.py
|
|
2
|
-
from typing import Any, Dict, List, Optional
|
|
3
2
|
import fnmatch
|
|
4
|
-
from
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from langchain_core.tools import ToolException
|
|
5
6
|
from pydantic import create_model, Field, model_validator, SecretStr, PrivateAttr
|
|
6
7
|
|
|
8
|
+
from ..code_indexer_toolkit import CodeIndexerToolkit
|
|
9
|
+
from ..utils.available_tools_decorator import extend_with_parent_available_tools
|
|
10
|
+
from ..elitea_base import extend_with_file_operations
|
|
11
|
+
from ..utils.content_parser import parse_file_content
|
|
12
|
+
|
|
7
13
|
AppendFileModel = create_model(
|
|
8
14
|
"AppendFileModel",
|
|
9
15
|
file_path=(str, Field(description="The path of the file")),
|
|
@@ -97,18 +103,26 @@ GetCommitsModel = create_model(
|
|
|
97
103
|
author=(Optional[str], Field(description="Author name", default=None)),
|
|
98
104
|
)
|
|
99
105
|
|
|
100
|
-
class GitLabAPIWrapper(
|
|
106
|
+
class GitLabAPIWrapper(CodeIndexerToolkit):
|
|
101
107
|
url: str
|
|
102
108
|
repository: str
|
|
103
109
|
private_token: SecretStr
|
|
104
110
|
branch: Optional[str] = 'main'
|
|
105
111
|
_git: Any = PrivateAttr()
|
|
106
|
-
_repo_instance: Any = PrivateAttr()
|
|
107
112
|
_active_branch: Any = PrivateAttr()
|
|
108
113
|
|
|
114
|
+
@staticmethod
|
|
115
|
+
def _sanitize_url(url: str) -> str:
|
|
116
|
+
"""Remove trailing slash from URL if present."""
|
|
117
|
+
return url.rstrip('/') if url else url
|
|
118
|
+
|
|
109
119
|
@model_validator(mode='before')
|
|
110
120
|
@classmethod
|
|
111
|
-
def
|
|
121
|
+
def validate_toolkit_before(cls, values: Dict) -> Dict:
|
|
122
|
+
return super().validate_toolkit(values)
|
|
123
|
+
|
|
124
|
+
@model_validator(mode='after')
|
|
125
|
+
def validate_toolkit(self):
|
|
112
126
|
try:
|
|
113
127
|
import gitlab
|
|
114
128
|
except ImportError:
|
|
@@ -116,22 +130,34 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
116
130
|
"python-gitlab is not installed. "
|
|
117
131
|
"Please install it with `pip install python-gitlab`"
|
|
118
132
|
)
|
|
119
|
-
|
|
133
|
+
self.repository = self._sanitize_url(self.repository)
|
|
120
134
|
g = gitlab.Gitlab(
|
|
121
|
-
url=
|
|
122
|
-
private_token=
|
|
135
|
+
url=self._sanitize_url(self.url),
|
|
136
|
+
private_token=self.private_token.get_secret_value(),
|
|
123
137
|
keep_base_url=True,
|
|
124
138
|
)
|
|
125
139
|
|
|
126
140
|
g.auth()
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
141
|
+
self._git = g
|
|
142
|
+
self._active_branch = self.branch
|
|
143
|
+
return self
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def repo_instance(self):
|
|
147
|
+
if not hasattr(self, "_repo_instance") or self._repo_instance is None:
|
|
148
|
+
try:
|
|
149
|
+
if self._git and self.repository:
|
|
150
|
+
self._repo_instance = self._git.projects.get(self.repository)
|
|
151
|
+
else:
|
|
152
|
+
self._repo_instance = None
|
|
153
|
+
except Exception as e:
|
|
154
|
+
# Only raise when accessed, not during initialization
|
|
155
|
+
raise ToolException(e)
|
|
156
|
+
return self._repo_instance
|
|
131
157
|
|
|
132
158
|
def set_active_branch(self, branch_name: str) -> str:
|
|
133
159
|
self._active_branch = branch_name
|
|
134
|
-
self.
|
|
160
|
+
self.repo_instance.default_branch = branch_name
|
|
135
161
|
return f"Active branch set to {branch_name}"
|
|
136
162
|
|
|
137
163
|
def list_branches_in_repo(self, limit: Optional[int] = 20, branch_wildcard: Optional[str] = None) -> List[str]:
|
|
@@ -146,7 +172,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
146
172
|
List[str]: List containing names of branches
|
|
147
173
|
"""
|
|
148
174
|
try:
|
|
149
|
-
branches = self.
|
|
175
|
+
branches = self.repo_instance.branches.list(get_all=True)
|
|
150
176
|
|
|
151
177
|
if branch_wildcard:
|
|
152
178
|
branches = [branch for branch in branches if fnmatch.fnmatch(branch.name, branch_wildcard)]
|
|
@@ -173,7 +199,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
173
199
|
|
|
174
200
|
def _get_all_files(self, path: str = None, recursive: bool = True, branch: str = None):
|
|
175
201
|
branch = branch if branch else self._active_branch
|
|
176
|
-
return self.
|
|
202
|
+
return self.repo_instance.repository_tree(path=path, ref=branch, recursive=recursive, all=True)
|
|
177
203
|
|
|
178
204
|
# overrided for indexer
|
|
179
205
|
def _get_files(self, path: str = None, recursive: bool = True, branch: str = None):
|
|
@@ -185,17 +211,29 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
185
211
|
Get the commit hash of a file in a specific branch.
|
|
186
212
|
"""
|
|
187
213
|
try:
|
|
188
|
-
file = self.
|
|
214
|
+
file = self.repo_instance.files.get(file_path, branch)
|
|
189
215
|
return file.commit_id
|
|
190
216
|
except Exception as e:
|
|
191
217
|
return f"Unable to get commit hash for {file_path} due to error:\n{e}"
|
|
192
218
|
|
|
193
|
-
def _read_file(self, file_path: str, branch: str):
|
|
219
|
+
def _read_file(self, file_path: str, branch: str, **kwargs):
|
|
220
|
+
"""
|
|
221
|
+
Read a file from specified branch with optional partial read support.
|
|
222
|
+
|
|
223
|
+
Parameters:
|
|
224
|
+
file_path: the file path
|
|
225
|
+
branch: the branch to read the file from
|
|
226
|
+
**kwargs: Additional parameters (offset, limit, head, tail) - currently ignored,
|
|
227
|
+
partial read handled client-side by base class methods
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
File content as string
|
|
231
|
+
"""
|
|
194
232
|
return self.read_file(file_path, branch)
|
|
195
233
|
|
|
196
234
|
def create_branch(self, branch_name: str) -> str:
|
|
197
235
|
try:
|
|
198
|
-
self.
|
|
236
|
+
self.repo_instance.branches.create(
|
|
199
237
|
{
|
|
200
238
|
'branch': branch_name,
|
|
201
239
|
'ref': self._active_branch,
|
|
@@ -218,7 +256,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
218
256
|
return parsed
|
|
219
257
|
|
|
220
258
|
def get_issues(self) -> str:
|
|
221
|
-
issues = self.
|
|
259
|
+
issues = self.repo_instance.issues.list(state="opened")
|
|
222
260
|
if len(issues) > 0:
|
|
223
261
|
parsed_issues = self.parse_issues(issues)
|
|
224
262
|
parsed_issues_str = (
|
|
@@ -229,7 +267,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
229
267
|
return "No open issues available"
|
|
230
268
|
|
|
231
269
|
def get_issue(self, issue_number: int) -> Dict[str, Any]:
|
|
232
|
-
issue = self.
|
|
270
|
+
issue = self.repo_instance.issues.get(issue_number)
|
|
233
271
|
page = 0
|
|
234
272
|
comments: List[dict] = []
|
|
235
273
|
while len(comments) <= 10:
|
|
@@ -255,7 +293,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
255
293
|
commits are already in the {self.branch} branch"""
|
|
256
294
|
else:
|
|
257
295
|
try:
|
|
258
|
-
pr = self.
|
|
296
|
+
pr = self.repo_instance.mergerequests.create(
|
|
259
297
|
{
|
|
260
298
|
"source_branch": branch,
|
|
261
299
|
"target_branch": self.branch,
|
|
@@ -272,7 +310,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
272
310
|
issue_number = int(comment_query.split("\n\n")[0])
|
|
273
311
|
comment = comment_query[len(str(issue_number)) + 2 :]
|
|
274
312
|
try:
|
|
275
|
-
issue = self.
|
|
313
|
+
issue = self.repo_instance.issues.get(issue_number)
|
|
276
314
|
issue.notes.create({"body": comment})
|
|
277
315
|
return "Commented on issue " + str(issue_number)
|
|
278
316
|
except Exception as e:
|
|
@@ -281,7 +319,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
281
319
|
def create_file(self, file_path: str, file_contents: str, branch: str) -> str:
|
|
282
320
|
try:
|
|
283
321
|
self.set_active_branch(branch)
|
|
284
|
-
self.
|
|
322
|
+
self.repo_instance.files.get(file_path, branch)
|
|
285
323
|
return f"File already exists at {file_path}. Use update_file instead"
|
|
286
324
|
except Exception:
|
|
287
325
|
data = {
|
|
@@ -290,14 +328,76 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
290
328
|
"file_path": file_path,
|
|
291
329
|
"content": file_contents,
|
|
292
330
|
}
|
|
293
|
-
self.
|
|
331
|
+
self.repo_instance.files.create(data)
|
|
294
332
|
|
|
295
333
|
return "Created file " + file_path
|
|
296
334
|
|
|
297
335
|
def read_file(self, file_path: str, branch: str) -> str:
|
|
298
336
|
self.set_active_branch(branch)
|
|
299
|
-
file = self.
|
|
300
|
-
return
|
|
337
|
+
file = self.repo_instance.files.get(file_path, branch)
|
|
338
|
+
return parse_file_content(file_name=file_path,
|
|
339
|
+
file_content=file.decode(),
|
|
340
|
+
llm=self.llm)
|
|
341
|
+
|
|
342
|
+
def _write_file(
|
|
343
|
+
self,
|
|
344
|
+
file_path: str,
|
|
345
|
+
content: str,
|
|
346
|
+
branch: str = None,
|
|
347
|
+
commit_message: str = None
|
|
348
|
+
) -> str:
|
|
349
|
+
"""
|
|
350
|
+
Write content to a file (create or update).
|
|
351
|
+
|
|
352
|
+
Parameters:
|
|
353
|
+
file_path: Path to the file
|
|
354
|
+
content: New file content
|
|
355
|
+
branch: Branch name (uses active branch if None)
|
|
356
|
+
commit_message: Commit message
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
Success message
|
|
360
|
+
"""
|
|
361
|
+
try:
|
|
362
|
+
branch = branch or self._active_branch
|
|
363
|
+
|
|
364
|
+
if branch == self.branch:
|
|
365
|
+
raise ToolException(
|
|
366
|
+
f"Cannot commit directly to the {self.branch} branch. "
|
|
367
|
+
"Please create a new branch and try again."
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
self.set_active_branch(branch)
|
|
371
|
+
|
|
372
|
+
# Check if file exists
|
|
373
|
+
try:
|
|
374
|
+
self.repo_instance.files.get(file_path, branch)
|
|
375
|
+
# File exists, update it
|
|
376
|
+
commit = {
|
|
377
|
+
"branch": branch,
|
|
378
|
+
"commit_message": commit_message or f"Update {file_path}",
|
|
379
|
+
"actions": [
|
|
380
|
+
{
|
|
381
|
+
"action": "update",
|
|
382
|
+
"file_path": file_path,
|
|
383
|
+
"content": content,
|
|
384
|
+
}
|
|
385
|
+
],
|
|
386
|
+
}
|
|
387
|
+
self.repo_instance.commits.create(commit)
|
|
388
|
+
return f"Updated file {file_path}"
|
|
389
|
+
except:
|
|
390
|
+
# File doesn't exist, create it
|
|
391
|
+
data = {
|
|
392
|
+
"branch": branch,
|
|
393
|
+
"commit_message": commit_message or f"Create {file_path}",
|
|
394
|
+
"file_path": file_path,
|
|
395
|
+
"content": content,
|
|
396
|
+
}
|
|
397
|
+
self.repo_instance.files.create(data)
|
|
398
|
+
return f"Created file {file_path}"
|
|
399
|
+
except Exception as e:
|
|
400
|
+
raise ToolException(f"Unable to write file {file_path}: {str(e)}")
|
|
301
401
|
|
|
302
402
|
def update_file(self, file_query: str, branch: str) -> str:
|
|
303
403
|
if branch == self.branch:
|
|
@@ -335,7 +435,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
335
435
|
],
|
|
336
436
|
}
|
|
337
437
|
|
|
338
|
-
self.
|
|
438
|
+
self.repo_instance.commits.create(commit)
|
|
339
439
|
return "Updated file " + file_path
|
|
340
440
|
except Exception as e:
|
|
341
441
|
return "Unable to update file due to error:\n" + str(e)
|
|
@@ -365,7 +465,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
365
465
|
],
|
|
366
466
|
}
|
|
367
467
|
|
|
368
|
-
self.
|
|
468
|
+
self.repo_instance.commits.create(commit)
|
|
369
469
|
return "Updated file " + file_path
|
|
370
470
|
except Exception as e:
|
|
371
471
|
return "Unable to update file due to error:\n" + str(e)
|
|
@@ -375,20 +475,20 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
375
475
|
self.set_active_branch(branch)
|
|
376
476
|
if not commit_message:
|
|
377
477
|
commit_message = f"Delete {file_path}"
|
|
378
|
-
self.
|
|
478
|
+
self.repo_instance.files.delete(file_path, branch, commit_message)
|
|
379
479
|
return f"Deleted file {file_path}"
|
|
380
480
|
except Exception as e:
|
|
381
481
|
return f"Unable to delete file due to error:\n{e}"
|
|
382
482
|
|
|
383
483
|
def get_pr_changes(self, pr_number: int) -> str:
|
|
384
|
-
mr = self.
|
|
484
|
+
mr = self.repo_instance.mergerequests.get(pr_number)
|
|
385
485
|
res = f"title: {mr.title}\ndescription: {mr.description}\n\n"
|
|
386
486
|
for change in mr.changes()["changes"]:
|
|
387
487
|
res += f"diff --git a/{change['old_path']} b/{change['new_path']}\n{change['diff']}\n"
|
|
388
488
|
return res
|
|
389
489
|
|
|
390
490
|
def create_pr_change_comment(self, pr_number: int, file_path: str, line_number: int, comment: str) -> str:
|
|
391
|
-
mr = self.
|
|
491
|
+
mr = self.repo_instance.mergerequests.get(pr_number)
|
|
392
492
|
position = {"position_type": "text", "new_path": file_path, "new_line": line_number}
|
|
393
493
|
mr.discussions.create({"body": comment, "position": position})
|
|
394
494
|
return "Comment added"
|
|
@@ -405,7 +505,7 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
405
505
|
params["until"] = until
|
|
406
506
|
if author:
|
|
407
507
|
params["author"] = author
|
|
408
|
-
commits = self.
|
|
508
|
+
commits = self.repo_instance.commits.list(**params)
|
|
409
509
|
return [
|
|
410
510
|
{
|
|
411
511
|
"sha": commit.id,
|
|
@@ -417,6 +517,8 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
417
517
|
for commit in commits
|
|
418
518
|
]
|
|
419
519
|
|
|
520
|
+
@extend_with_parent_available_tools
|
|
521
|
+
@extend_with_file_operations
|
|
420
522
|
def get_available_tools(self):
|
|
421
523
|
return [
|
|
422
524
|
{
|
|
@@ -521,4 +623,4 @@ class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
|
|
521
623
|
"description": "Retrieve a list of commits from the repository.",
|
|
522
624
|
"args_schema": GetCommitsModel,
|
|
523
625
|
}
|
|
524
|
-
]
|
|
626
|
+
]
|