alita-sdk 0.3.486__py3-none-any.whl → 0.3.515__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/agent_loader.py +27 -6
- alita_sdk/cli/agents.py +10 -1
- alita_sdk/cli/inventory.py +12 -195
- alita_sdk/cli/tools/filesystem.py +95 -9
- alita_sdk/community/inventory/__init__.py +12 -0
- alita_sdk/community/inventory/toolkit.py +9 -5
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/configurations/ado.py +144 -0
- alita_sdk/configurations/confluence.py +76 -42
- alita_sdk/configurations/figma.py +76 -0
- alita_sdk/configurations/gitlab.py +2 -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/runtime/clients/artifact.py +2 -2
- alita_sdk/runtime/clients/client.py +64 -40
- alita_sdk/runtime/clients/sandbox_client.py +14 -0
- alita_sdk/runtime/langchain/assistant.py +48 -2
- alita_sdk/runtime/langchain/constants.py +3 -1
- 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 +2 -1
- alita_sdk/runtime/langchain/document_loaders/constants.py +12 -7
- alita_sdk/runtime/langchain/langraph_agent.py +10 -10
- alita_sdk/runtime/langchain/utils.py +6 -1
- alita_sdk/runtime/toolkits/artifact.py +14 -5
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +94 -219
- alita_sdk/runtime/toolkits/planning.py +13 -6
- alita_sdk/runtime/toolkits/tools.py +60 -25
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/artifact.py +185 -23
- alita_sdk/runtime/tools/function.py +2 -1
- alita_sdk/runtime/tools/llm.py +155 -34
- alita_sdk/runtime/tools/mcp_remote_tool.py +25 -10
- alita_sdk/runtime/tools/mcp_server_tool.py +2 -4
- alita_sdk/runtime/tools/vectorstore_base.py +3 -3
- alita_sdk/runtime/utils/AlitaCallback.py +136 -21
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +125 -8
- alita_sdk/runtime/utils/mcp_sse_client.py +35 -6
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/toolkit_utils.py +7 -13
- alita_sdk/runtime/utils/utils.py +2 -0
- alita_sdk/tools/__init__.py +15 -0
- alita_sdk/tools/ado/repos/__init__.py +10 -12
- alita_sdk/tools/ado/test_plan/__init__.py +23 -8
- alita_sdk/tools/ado/wiki/__init__.py +24 -8
- alita_sdk/tools/ado/wiki/ado_wrapper.py +21 -7
- alita_sdk/tools/ado/work_item/__init__.py +24 -8
- alita_sdk/tools/advanced_jira_mining/__init__.py +10 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +12 -9
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +9 -7
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +26 -1
- alita_sdk/tools/bitbucket/__init__.py +14 -10
- alita_sdk/tools/bitbucket/api_wrapper.py +50 -2
- alita_sdk/tools/browser/__init__.py +5 -4
- alita_sdk/tools/carrier/__init__.py +5 -6
- alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +2 -0
- alita_sdk/tools/chunkers/universal_chunker.py +1 -0
- alita_sdk/tools/cloud/aws/__init__.py +9 -7
- alita_sdk/tools/cloud/azure/__init__.py +9 -7
- alita_sdk/tools/cloud/gcp/__init__.py +9 -7
- alita_sdk/tools/cloud/k8s/__init__.py +9 -7
- alita_sdk/tools/code/linter/__init__.py +9 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +9 -7
- alita_sdk/tools/confluence/__init__.py +15 -10
- alita_sdk/tools/confluence/api_wrapper.py +63 -14
- alita_sdk/tools/custom_open_api/__init__.py +11 -5
- alita_sdk/tools/elastic/__init__.py +10 -8
- alita_sdk/tools/elitea_base.py +387 -9
- alita_sdk/tools/figma/__init__.py +8 -7
- alita_sdk/tools/github/__init__.py +12 -14
- alita_sdk/tools/github/github_client.py +68 -2
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/gitlab/__init__.py +14 -11
- alita_sdk/tools/gitlab/api_wrapper.py +81 -1
- alita_sdk/tools/gitlab_org/__init__.py +9 -8
- alita_sdk/tools/google/bigquery/__init__.py +12 -12
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +9 -8
- alita_sdk/tools/jira/__init__.py +15 -10
- alita_sdk/tools/keycloak/__init__.py +10 -8
- alita_sdk/tools/localgit/__init__.py +8 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +11 -3
- alita_sdk/tools/ocr/__init__.py +10 -8
- alita_sdk/tools/openapi/__init__.py +6 -2
- alita_sdk/tools/pandas/__init__.py +9 -7
- alita_sdk/tools/postman/__init__.py +10 -11
- alita_sdk/tools/pptx/__init__.py +9 -9
- alita_sdk/tools/qtest/__init__.py +9 -8
- alita_sdk/tools/rally/__init__.py +9 -8
- alita_sdk/tools/report_portal/__init__.py +11 -9
- alita_sdk/tools/salesforce/__init__.py +9 -9
- alita_sdk/tools/servicenow/__init__.py +10 -8
- alita_sdk/tools/sharepoint/__init__.py +9 -8
- alita_sdk/tools/sharepoint/api_wrapper.py +2 -2
- alita_sdk/tools/slack/__init__.py +8 -7
- alita_sdk/tools/sql/__init__.py +9 -8
- alita_sdk/tools/testio/__init__.py +9 -8
- alita_sdk/tools/testrail/__init__.py +10 -8
- alita_sdk/tools/utils/__init__.py +9 -4
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +16 -18
- alita_sdk/tools/xray/__init__.py +10 -8
- alita_sdk/tools/yagmail/__init__.py +8 -3
- alita_sdk/tools/zephyr/__init__.py +8 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +10 -8
- alita_sdk/tools/zephyr_essential/__init__.py +9 -8
- alita_sdk/tools/zephyr_scale/__init__.py +9 -8
- alita_sdk/tools/zephyr_squad/__init__.py +9 -8
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/METADATA +1 -1
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/RECORD +124 -119
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/entry_points.txt +0 -0
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.486.dist-info → alita_sdk-0.3.515.dist-info}/top_level.txt +0 -0
|
@@ -71,6 +71,7 @@ class McpSseClient:
|
|
|
71
71
|
McpAuthorizationRequired,
|
|
72
72
|
canonical_resource,
|
|
73
73
|
extract_resource_metadata_url,
|
|
74
|
+
extract_authorization_uri,
|
|
74
75
|
fetch_resource_metadata_async,
|
|
75
76
|
infer_authorization_servers_from_realm,
|
|
76
77
|
fetch_oauth_authorization_server_metadata
|
|
@@ -79,13 +80,41 @@ class McpSseClient:
|
|
|
79
80
|
auth_header = self._stream_response.headers.get('WWW-Authenticate', '')
|
|
80
81
|
resource_metadata_url = extract_resource_metadata_url(auth_header, self.url)
|
|
81
82
|
|
|
83
|
+
# First, try authorization_uri from WWW-Authenticate header (preferred)
|
|
84
|
+
authorization_uri = extract_authorization_uri(auth_header)
|
|
85
|
+
|
|
82
86
|
metadata = None
|
|
83
|
-
if
|
|
84
|
-
metadata
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
if authorization_uri:
|
|
88
|
+
# Fetch OAuth metadata directly from authorization_uri
|
|
89
|
+
auth_server_metadata = fetch_oauth_authorization_server_metadata(authorization_uri, timeout=30)
|
|
90
|
+
if auth_server_metadata:
|
|
91
|
+
# Extract base authorization server URL from the issuer or the well-known URL
|
|
92
|
+
base_auth_server = auth_server_metadata.get('issuer')
|
|
93
|
+
if not base_auth_server and '/.well-known/' in authorization_uri:
|
|
94
|
+
base_auth_server = authorization_uri.split('/.well-known/')[0]
|
|
95
|
+
|
|
96
|
+
metadata = {
|
|
97
|
+
'authorization_servers': [base_auth_server] if base_auth_server else [authorization_uri],
|
|
98
|
+
'oauth_authorization_server': auth_server_metadata
|
|
99
|
+
}
|
|
100
|
+
logger.info(f"[MCP SSE Client] Using authorization_uri: {authorization_uri}, base: {base_auth_server}")
|
|
101
|
+
|
|
102
|
+
# Fall back to resource_metadata if authorization_uri didn't work
|
|
103
|
+
if not metadata:
|
|
104
|
+
if resource_metadata_url:
|
|
105
|
+
metadata = await fetch_resource_metadata_async(
|
|
106
|
+
resource_metadata_url,
|
|
107
|
+
session=self._stream_session,
|
|
108
|
+
timeout=30
|
|
109
|
+
)
|
|
110
|
+
# If we got resource_metadata, also fetch oauth_authorization_server
|
|
111
|
+
if metadata and metadata.get('authorization_servers'):
|
|
112
|
+
auth_server_metadata = fetch_oauth_authorization_server_metadata(
|
|
113
|
+
metadata['authorization_servers'][0], timeout=30
|
|
114
|
+
)
|
|
115
|
+
if auth_server_metadata:
|
|
116
|
+
metadata['oauth_authorization_server'] = auth_server_metadata
|
|
117
|
+
logger.info(f"[MCP SSE Client] Fetched OAuth metadata from resource_metadata")
|
|
89
118
|
|
|
90
119
|
# Infer authorization servers if not in metadata
|
|
91
120
|
if not metadata or not metadata.get('authorization_servers'):
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP Tools Discovery Utility.
|
|
3
|
+
Provides a standalone function to discover tools from remote MCP servers.
|
|
4
|
+
Supports both SSE (Server-Sent Events) and Streamable HTTP transports with auto-detection.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from .mcp_oauth import McpAuthorizationRequired
|
|
12
|
+
from .mcp_client import McpClient
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def discover_mcp_tools(
|
|
18
|
+
url: str,
|
|
19
|
+
headers: Optional[Dict[str, str]] = None,
|
|
20
|
+
timeout: int = 60,
|
|
21
|
+
session_id: Optional[str] = None,
|
|
22
|
+
) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Discover available tools from a remote MCP server.
|
|
25
|
+
|
|
26
|
+
This function connects to a remote MCP server and retrieves the list of
|
|
27
|
+
available tools using the MCP protocol. Automatically detects and uses
|
|
28
|
+
the appropriate transport (SSE or Streamable HTTP).
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
url: MCP server HTTP URL (http:// or https://)
|
|
32
|
+
headers: Optional HTTP headers for authentication
|
|
33
|
+
timeout: Request timeout in seconds (default: 60)
|
|
34
|
+
session_id: Optional session ID for stateful connections
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
List of tool definitions, each containing:
|
|
38
|
+
- name: Tool name
|
|
39
|
+
- description: Tool description
|
|
40
|
+
- inputSchema: JSON schema for tool input parameters
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
McpAuthorizationRequired: If the server requires OAuth authorization (401)
|
|
44
|
+
Exception: For other connection or protocol errors
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
>>> tools = discover_mcp_tools(
|
|
48
|
+
... url="https://mcp.example.com/sse",
|
|
49
|
+
... headers={"Authorization": "Bearer token123"}
|
|
50
|
+
... )
|
|
51
|
+
>>> print(f"Found {len(tools)} tools")
|
|
52
|
+
"""
|
|
53
|
+
logger.info(f"[MCP Discovery] Starting tool discovery from {url}")
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
# Run the async discovery in a new event loop
|
|
57
|
+
tools_list = asyncio.run(
|
|
58
|
+
_discover_tools_async(url, headers, timeout, session_id)
|
|
59
|
+
)
|
|
60
|
+
logger.info(f"[MCP Discovery] Successfully discovered {len(tools_list)} tools from {url}")
|
|
61
|
+
return tools_list
|
|
62
|
+
|
|
63
|
+
except McpAuthorizationRequired:
|
|
64
|
+
# Re-raise auth exceptions directly
|
|
65
|
+
logger.info(f"[MCP Discovery] Authorization required for {url}")
|
|
66
|
+
raise
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error(f"[MCP Discovery] Failed to discover tools from {url}: {e}")
|
|
70
|
+
raise
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def _discover_tools_async(
|
|
74
|
+
url: str,
|
|
75
|
+
headers: Optional[Dict[str, str]],
|
|
76
|
+
timeout: int,
|
|
77
|
+
session_id: Optional[str],
|
|
78
|
+
) -> List[Dict[str, Any]]:
|
|
79
|
+
"""
|
|
80
|
+
Async implementation of tool discovery using unified MCP client.
|
|
81
|
+
"""
|
|
82
|
+
all_tools = []
|
|
83
|
+
|
|
84
|
+
# Create unified MCP client (auto-detects transport)
|
|
85
|
+
client = McpClient(
|
|
86
|
+
url=url,
|
|
87
|
+
session_id=session_id,
|
|
88
|
+
headers=headers,
|
|
89
|
+
timeout=timeout
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async with client:
|
|
93
|
+
# Initialize MCP session
|
|
94
|
+
await client.initialize()
|
|
95
|
+
logger.debug(f"[MCP Discovery] Session initialized (transport={client.detected_transport})")
|
|
96
|
+
|
|
97
|
+
# Get tools list
|
|
98
|
+
tools = await client.list_tools()
|
|
99
|
+
logger.debug(f"[MCP Discovery] Received {len(tools)} tools")
|
|
100
|
+
|
|
101
|
+
# Convert tools to standard format
|
|
102
|
+
for tool in tools:
|
|
103
|
+
tool_def = {
|
|
104
|
+
'name': tool.get('name'),
|
|
105
|
+
'description': tool.get('description', ''),
|
|
106
|
+
'inputSchema': tool.get('inputSchema', {}),
|
|
107
|
+
}
|
|
108
|
+
all_tools.append(tool_def)
|
|
109
|
+
|
|
110
|
+
return all_tools
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def discover_mcp_tools_async(
|
|
114
|
+
url: str,
|
|
115
|
+
headers: Optional[Dict[str, str]] = None,
|
|
116
|
+
timeout: int = 60,
|
|
117
|
+
session_id: Optional[str] = None,
|
|
118
|
+
) -> List[Dict[str, Any]]:
|
|
119
|
+
"""
|
|
120
|
+
Async version of discover_mcp_tools.
|
|
121
|
+
|
|
122
|
+
See discover_mcp_tools for full documentation.
|
|
123
|
+
"""
|
|
124
|
+
return await _discover_tools_async(url, headers, timeout, session_id)
|
|
@@ -13,7 +13,8 @@ logger = logging.getLogger(__name__)
|
|
|
13
13
|
def instantiate_toolkit_with_client(toolkit_config: Dict[str, Any],
|
|
14
14
|
llm_client: Any,
|
|
15
15
|
alita_client: Optional[Any] = None,
|
|
16
|
-
mcp_tokens: Optional[Dict[str, Any]] = None
|
|
16
|
+
mcp_tokens: Optional[Dict[str, Any]] = None,
|
|
17
|
+
use_prefix: bool = False) -> List[Any]:
|
|
17
18
|
"""
|
|
18
19
|
Instantiate a toolkit with LLM client support.
|
|
19
20
|
|
|
@@ -25,6 +26,9 @@ def instantiate_toolkit_with_client(toolkit_config: Dict[str, Any],
|
|
|
25
26
|
llm_client: LLM client instance for tools that need LLM capabilities
|
|
26
27
|
alita_client: Optional additional client instance
|
|
27
28
|
mcp_tokens: Optional dictionary of MCP OAuth tokens by server URL
|
|
29
|
+
use_prefix: If True, tools get prefixed with toolkit_name to prevent collisions
|
|
30
|
+
(for agent use). If False, tools use base names only (for testing interface).
|
|
31
|
+
Default False for backward compatibility with testing.
|
|
28
32
|
|
|
29
33
|
Returns:
|
|
30
34
|
List of instantiated tools from the toolkit
|
|
@@ -54,11 +58,12 @@ def instantiate_toolkit_with_client(toolkit_config: Dict[str, Any],
|
|
|
54
58
|
toolkit_type = toolkit_config.get('type', toolkit_name.lower())
|
|
55
59
|
|
|
56
60
|
# Create a tool configuration dict with required fields
|
|
61
|
+
# Note: MCP toolkit always requires toolkit_name, other toolkits respect use_prefix flag
|
|
57
62
|
tool_config = {
|
|
58
63
|
'id': toolkit_config.get('id', random.randint(1, 1000000)),
|
|
59
64
|
'type': toolkit_config.get('type', toolkit_type),
|
|
60
65
|
'settings': settings,
|
|
61
|
-
'toolkit_name': toolkit_name
|
|
66
|
+
'toolkit_name': toolkit_name if (use_prefix or toolkit_type == 'mcp') else None
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
# Get tools using the toolkit configuration with clients
|
|
@@ -76,21 +81,10 @@ def instantiate_toolkit_with_client(toolkit_config: Dict[str, Any],
|
|
|
76
81
|
# Re-raise McpAuthorizationRequired without logging as error
|
|
77
82
|
from ..utils.mcp_oauth import McpAuthorizationRequired
|
|
78
83
|
|
|
79
|
-
# Check if it's McpAuthorizationRequired directly
|
|
80
84
|
if isinstance(e, McpAuthorizationRequired):
|
|
81
85
|
logger.info(f"Toolkit {toolkit_name} requires MCP OAuth authorization")
|
|
82
86
|
raise
|
|
83
87
|
|
|
84
|
-
# Also check for wrapped exceptions
|
|
85
|
-
if hasattr(e, '__cause__') and isinstance(e.__cause__, McpAuthorizationRequired):
|
|
86
|
-
logger.info(f"Toolkit {toolkit_name} requires MCP OAuth authorization (wrapped)")
|
|
87
|
-
raise e.__cause__
|
|
88
|
-
|
|
89
|
-
# Check exception class name as fallback
|
|
90
|
-
if e.__class__.__name__ == 'McpAuthorizationRequired':
|
|
91
|
-
logger.info(f"Toolkit {toolkit_name} requires MCP OAuth authorization (by name)")
|
|
92
|
-
raise
|
|
93
|
-
|
|
94
88
|
# Log and re-raise other errors
|
|
95
89
|
logger.error(f"Error instantiating toolkit {toolkit_name} with client: {str(e)}")
|
|
96
90
|
raise
|
alita_sdk/runtime/utils/utils.py
CHANGED
alita_sdk/tools/__init__.py
CHANGED
|
@@ -45,6 +45,9 @@ def _safe_import_tool(tool_name, module_path, get_tools_name=None, toolkit_class
|
|
|
45
45
|
imported = {}
|
|
46
46
|
if get_tools_name and hasattr(module, get_tools_name):
|
|
47
47
|
imported['get_tools'] = getattr(module, get_tools_name)
|
|
48
|
+
|
|
49
|
+
if hasattr(module, 'get_toolkit'):
|
|
50
|
+
imported['get_toolkit'] = getattr(module, 'get_toolkit')
|
|
48
51
|
|
|
49
52
|
if toolkit_class_name and hasattr(module, toolkit_class_name):
|
|
50
53
|
imported['toolkit_class'] = getattr(module, toolkit_class_name)
|
|
@@ -209,6 +212,18 @@ def get_toolkits():
|
|
|
209
212
|
logger.info(f"Successfully loaded {len(toolkit_configs)} toolkit configurations")
|
|
210
213
|
return toolkit_configs
|
|
211
214
|
|
|
215
|
+
def instantiate_toolkit(tool_config):
|
|
216
|
+
"""Instantiate a toolkit from its configuration."""
|
|
217
|
+
tool_type = tool_config.get('type')
|
|
218
|
+
|
|
219
|
+
if tool_type in AVAILABLE_TOOLS:
|
|
220
|
+
tool_module = AVAILABLE_TOOLS[tool_type]
|
|
221
|
+
|
|
222
|
+
if 'get_toolkit' in tool_module:
|
|
223
|
+
return tool_module['get_toolkit'](tool_config)
|
|
224
|
+
|
|
225
|
+
raise ValueError(f"Toolkit type '{tool_type}' does not support direct instantiation or is not available.")
|
|
226
|
+
|
|
212
227
|
def get_available_tools():
|
|
213
228
|
"""Return list of available tool types."""
|
|
214
229
|
return list(AVAILABLE_TOOLS.keys())
|
|
@@ -10,12 +10,12 @@ from ....configurations.ado import AdoReposConfiguration
|
|
|
10
10
|
from ....configurations.pgvector import PgVectorConfiguration
|
|
11
11
|
from ...base.tool import BaseAction
|
|
12
12
|
from .repos_wrapper import ReposApiWrapper
|
|
13
|
-
from ...utils import clean_string,
|
|
13
|
+
from ...utils import clean_string, get_max_toolkit_length, check_connection_response
|
|
14
14
|
|
|
15
15
|
name = "ado_repos"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def get_toolkit(tool) -> BaseToolkit:
|
|
19
19
|
return AzureDevOpsReposToolkit().get_toolkit(
|
|
20
20
|
selected_tools=tool['settings'].get('selected_tools', []),
|
|
21
21
|
ado_repos_configuration=tool['settings']['ado_repos_configuration'],
|
|
@@ -30,20 +30,15 @@ def _get_toolkit(tool) -> BaseToolkit:
|
|
|
30
30
|
llm=tool['settings'].get('llm', None),
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
-
def get_toolkit():
|
|
34
|
-
return AzureDevOpsReposToolkit.toolkit_config_schema()
|
|
35
|
-
|
|
36
33
|
def get_tools(tool):
|
|
37
|
-
return
|
|
34
|
+
return get_toolkit(tool).get_tools()
|
|
38
35
|
|
|
39
36
|
class AzureDevOpsReposToolkit(BaseToolkit):
|
|
40
37
|
tools: List[BaseTool] = []
|
|
41
|
-
toolkit_max_length: int = 0
|
|
42
38
|
|
|
43
39
|
@staticmethod
|
|
44
40
|
def toolkit_config_schema() -> BaseModel:
|
|
45
41
|
selected_tools = {x['name']: x['args_schema'].schema() for x in ReposApiWrapper.model_construct().get_available_tools()}
|
|
46
|
-
AzureDevOpsReposToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
47
42
|
m = create_model(
|
|
48
43
|
name,
|
|
49
44
|
ado_repos_configuration=(AdoReposConfiguration, Field(description="Ado Repos configuration", default=None,
|
|
@@ -63,7 +58,6 @@ class AzureDevOpsReposToolkit(BaseToolkit):
|
|
|
63
58
|
"icon_url": "ado-repos-icon.svg",
|
|
64
59
|
"categories": ["code repositories"],
|
|
65
60
|
"extra_categories": ["code", "repository", "version control"],
|
|
66
|
-
"max_length": AzureDevOpsReposToolkit.toolkit_max_length
|
|
67
61
|
}}}
|
|
68
62
|
)
|
|
69
63
|
|
|
@@ -99,17 +93,21 @@ class AzureDevOpsReposToolkit(BaseToolkit):
|
|
|
99
93
|
azure_devops_repos_wrapper = ReposApiWrapper(**wrapper_payload)
|
|
100
94
|
available_tools = azure_devops_repos_wrapper.get_available_tools()
|
|
101
95
|
tools = []
|
|
102
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
103
96
|
for tool in available_tools:
|
|
104
97
|
if selected_tools:
|
|
105
98
|
if tool["name"] not in selected_tools:
|
|
106
99
|
continue
|
|
100
|
+
description = tool["description"] + f"\nADO instance: {azure_devops_repos_wrapper.organization_url}/{azure_devops_repos_wrapper.project}"
|
|
101
|
+
if toolkit_name:
|
|
102
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
103
|
+
description = description[:1000]
|
|
107
104
|
tools.append(
|
|
108
105
|
BaseAction(
|
|
109
106
|
api_wrapper=azure_devops_repos_wrapper,
|
|
110
|
-
name=
|
|
111
|
-
description=
|
|
107
|
+
name=tool["name"],
|
|
108
|
+
description=description,
|
|
112
109
|
args_schema=tool["args_schema"],
|
|
110
|
+
metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
|
|
113
111
|
)
|
|
114
112
|
)
|
|
115
113
|
return cls(tools=tools)
|
|
@@ -10,21 +10,33 @@ from ....configurations.ado import AdoConfiguration
|
|
|
10
10
|
from ....configurations.pgvector import PgVectorConfiguration
|
|
11
11
|
from .test_plan_wrapper import TestPlanApiWrapper
|
|
12
12
|
from ...base.tool import BaseAction
|
|
13
|
-
from ...utils import clean_string,
|
|
13
|
+
from ...utils import clean_string, get_max_toolkit_length, check_connection_response
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
name = "azure_devops_plans"
|
|
17
17
|
name_alias = "ado_plans"
|
|
18
18
|
|
|
19
|
+
def get_toolkit(tool):
|
|
20
|
+
return AzureDevOpsPlansToolkit().get_toolkit(
|
|
21
|
+
selected_tools=tool['settings'].get('selected_tools', []),
|
|
22
|
+
ado_configuration=tool['settings']['ado_configuration'],
|
|
23
|
+
limit=tool['settings'].get('limit', 5),
|
|
24
|
+
toolkit_name=tool.get('toolkit_name', ''),
|
|
25
|
+
alita=tool['settings'].get('alita', None),
|
|
26
|
+
llm=tool['settings'].get('llm', None),
|
|
27
|
+
pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
|
|
28
|
+
collection_name=tool['toolkit_name'],
|
|
29
|
+
doctype='doc',
|
|
30
|
+
embedding_model=tool['settings'].get('embedding_model'),
|
|
31
|
+
vectorstore_type="PGVector"
|
|
32
|
+
)
|
|
19
33
|
|
|
20
34
|
class AzureDevOpsPlansToolkit(BaseToolkit):
|
|
21
35
|
tools: List[BaseTool] = []
|
|
22
|
-
toolkit_max_length: int = 0
|
|
23
36
|
|
|
24
37
|
@staticmethod
|
|
25
38
|
def toolkit_config_schema() -> BaseModel:
|
|
26
39
|
selected_tools = {x['name']: x['args_schema'].schema() for x in TestPlanApiWrapper.model_construct().get_available_tools()}
|
|
27
|
-
AzureDevOpsPlansToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
28
40
|
m = create_model(
|
|
29
41
|
name_alias,
|
|
30
42
|
ado_configuration=(AdoConfiguration, Field(description="Ado configuration", json_schema_extra={'configuration_types': ['ado']})),
|
|
@@ -39,7 +51,6 @@ class AzureDevOpsPlansToolkit(BaseToolkit):
|
|
|
39
51
|
{
|
|
40
52
|
"label": "ADO plans",
|
|
41
53
|
"icon_url": "ado-plans.svg",
|
|
42
|
-
"max_length": AzureDevOpsPlansToolkit.toolkit_max_length,
|
|
43
54
|
"categories": ["test management"],
|
|
44
55
|
"extra_categories": ["test case management", "qa"],
|
|
45
56
|
"sections": {
|
|
@@ -97,17 +108,21 @@ class AzureDevOpsPlansToolkit(BaseToolkit):
|
|
|
97
108
|
azure_devops_api_wrapper = TestPlanApiWrapper(**wrapper_payload)
|
|
98
109
|
available_tools = azure_devops_api_wrapper.get_available_tools()
|
|
99
110
|
tools = []
|
|
100
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
101
111
|
for tool in available_tools:
|
|
102
112
|
if selected_tools:
|
|
103
113
|
if tool["name"] not in selected_tools:
|
|
104
114
|
continue
|
|
105
115
|
print(tool)
|
|
116
|
+
description = tool["description"] + f"\nADO instance: {azure_devops_api_wrapper.organization_url}"
|
|
117
|
+
if toolkit_name:
|
|
118
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
119
|
+
description = description[:1000]
|
|
106
120
|
tools.append(BaseAction(
|
|
107
121
|
api_wrapper=azure_devops_api_wrapper,
|
|
108
|
-
name=
|
|
109
|
-
description=
|
|
110
|
-
args_schema=tool["args_schema"]
|
|
122
|
+
name=tool["name"],
|
|
123
|
+
description=description,
|
|
124
|
+
args_schema=tool["args_schema"],
|
|
125
|
+
metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
|
|
111
126
|
))
|
|
112
127
|
return cls(tools=tools)
|
|
113
128
|
|
|
@@ -9,19 +9,32 @@ from ...elitea_base import filter_missconfigured_index_tools
|
|
|
9
9
|
from ....configurations.ado import AdoConfiguration
|
|
10
10
|
from ....configurations.pgvector import PgVectorConfiguration
|
|
11
11
|
from ...base.tool import BaseAction
|
|
12
|
-
from ...utils import clean_string,
|
|
12
|
+
from ...utils import clean_string, get_max_toolkit_length, check_connection_response
|
|
13
13
|
|
|
14
14
|
name = "azure_devops_wiki"
|
|
15
15
|
name_alias = 'ado_wiki'
|
|
16
16
|
|
|
17
|
+
def get_toolkit(tool):
|
|
18
|
+
return AzureDevOpsWikiToolkit().get_toolkit(
|
|
19
|
+
selected_tools=tool['settings'].get('selected_tools', []),
|
|
20
|
+
ado_configuration=tool['settings']['ado_configuration'],
|
|
21
|
+
limit=tool['settings'].get('limit', 5),
|
|
22
|
+
toolkit_name=tool.get('toolkit_name', ''),
|
|
23
|
+
alita=tool['settings'].get('alita', None),
|
|
24
|
+
llm=tool['settings'].get('llm', None),
|
|
25
|
+
pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
|
|
26
|
+
collection_name=tool['toolkit_name'],
|
|
27
|
+
doctype='doc',
|
|
28
|
+
embedding_model=tool['settings'].get('embedding_model'),
|
|
29
|
+
vectorstore_type="PGVector"
|
|
30
|
+
)
|
|
31
|
+
|
|
17
32
|
class AzureDevOpsWikiToolkit(BaseToolkit):
|
|
18
33
|
tools: List[BaseTool] = []
|
|
19
|
-
toolkit_max_length: int = 0
|
|
20
34
|
|
|
21
35
|
@staticmethod
|
|
22
36
|
def toolkit_config_schema() -> BaseModel:
|
|
23
37
|
selected_tools = {x['name']: x['args_schema'].schema() for x in AzureDevOpsApiWrapper.model_construct().get_available_tools()}
|
|
24
|
-
AzureDevOpsWikiToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
25
38
|
m = create_model(
|
|
26
39
|
name_alias,
|
|
27
40
|
ado_configuration=(AdoConfiguration, Field(description="Ado configuration", json_schema_extra={'configuration_types': ['ado']})),
|
|
@@ -37,7 +50,6 @@ class AzureDevOpsWikiToolkit(BaseToolkit):
|
|
|
37
50
|
'metadata': {
|
|
38
51
|
"label": "ADO wiki",
|
|
39
52
|
"icon_url": "ado-wiki-icon.svg",
|
|
40
|
-
"max_length": AzureDevOpsWikiToolkit.toolkit_max_length,
|
|
41
53
|
"categories": ["documentation"],
|
|
42
54
|
"extra_categories": ["knowledge base", "documentation management", "wiki"],
|
|
43
55
|
"sections": {
|
|
@@ -91,16 +103,20 @@ class AzureDevOpsWikiToolkit(BaseToolkit):
|
|
|
91
103
|
azure_devops_api_wrapper = AzureDevOpsApiWrapper(**wrapper_payload)
|
|
92
104
|
available_tools = azure_devops_api_wrapper.get_available_tools()
|
|
93
105
|
tools = []
|
|
94
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
95
106
|
for tool in available_tools:
|
|
96
107
|
if selected_tools:
|
|
97
108
|
if tool["name"] not in selected_tools:
|
|
98
109
|
continue
|
|
110
|
+
description = tool["description"] + f"\nADO instance: {azure_devops_api_wrapper.organization_url}/{azure_devops_api_wrapper.project}"
|
|
111
|
+
if toolkit_name:
|
|
112
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
113
|
+
description = description[:1000]
|
|
99
114
|
tools.append(BaseAction(
|
|
100
115
|
api_wrapper=azure_devops_api_wrapper,
|
|
101
|
-
name=
|
|
102
|
-
description=
|
|
103
|
-
args_schema=tool["args_schema"]
|
|
116
|
+
name=tool["name"],
|
|
117
|
+
description=description,
|
|
118
|
+
args_schema=tool["args_schema"],
|
|
119
|
+
metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
|
|
104
120
|
))
|
|
105
121
|
return cls(tools=tools)
|
|
106
122
|
|
|
@@ -52,8 +52,9 @@ ModifyPageInput = create_model(
|
|
|
52
52
|
wiki_identified=(str, Field(description="Wiki ID or wiki name")),
|
|
53
53
|
page_name=(str, Field(description="Wiki page name")),
|
|
54
54
|
page_content=(str, Field(description="Wiki page content")),
|
|
55
|
-
version_identifier=(str, Field(description="Version string identifier (name of tag/branch, SHA1 of commit)")),
|
|
56
|
-
version_type=(Optional[str], Field(description="Version type (branch, tag, or commit). Determines how Id is interpreted", default="branch"))
|
|
55
|
+
version_identifier=(str, Field(description="Version string identifier (name of tag/branch, SHA1 of commit). Usually for wiki the branch is 'wikiMaster'")),
|
|
56
|
+
version_type=(Optional[str], Field(description="Version type (branch, tag, or commit). Determines how Id is interpreted", default="branch")),
|
|
57
|
+
expanded=(Optional[bool], Field(description="Whether to return the full page object or just its simplified version.", default=False))
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
RenamePageInput = create_model(
|
|
@@ -66,6 +67,19 @@ RenamePageInput = create_model(
|
|
|
66
67
|
)
|
|
67
68
|
|
|
68
69
|
|
|
70
|
+
def _format_wiki_page_response(wiki_page_response, expanded: bool = False):
|
|
71
|
+
"""Format wiki page response."""
|
|
72
|
+
try:
|
|
73
|
+
return {
|
|
74
|
+
'eTag': wiki_page_response.eTag,
|
|
75
|
+
'page': wiki_page_response.page.__dict__ if wiki_page_response.page else None
|
|
76
|
+
} if expanded else {"eTag": wiki_page_response.eTag, "id": wiki_page_response.page.id,
|
|
77
|
+
"page": wiki_page_response.page.url}
|
|
78
|
+
except:
|
|
79
|
+
logger.error(f"Unable to format wiki page response: {wiki_page_response}")
|
|
80
|
+
return wiki_page_response
|
|
81
|
+
|
|
82
|
+
|
|
69
83
|
class AzureDevOpsApiWrapper(NonCodeIndexerToolkit):
|
|
70
84
|
# TODO use ado_configuration instead of organization_url, project and token
|
|
71
85
|
organization_url: str
|
|
@@ -226,7 +240,7 @@ class AzureDevOpsApiWrapper(NonCodeIndexerToolkit):
|
|
|
226
240
|
logger.error(f"Unable to rename wiki page: {str(e)}")
|
|
227
241
|
return ToolException(f"Unable to rename wiki page: {str(e)}")
|
|
228
242
|
|
|
229
|
-
def modify_wiki_page(self, wiki_identified: str, page_name: str, page_content: str, version_identifier: str, version_type: str = "branch"):
|
|
243
|
+
def modify_wiki_page(self, wiki_identified: str, page_name: str, page_content: str, version_identifier: str, version_type: str = "branch", expanded: Optional[bool] = False):
|
|
230
244
|
"""Create or Update ADO wiki page content."""
|
|
231
245
|
try:
|
|
232
246
|
all_wikis = [wiki.name for wiki in self._client.get_all_wikis(project=self.project)]
|
|
@@ -257,24 +271,24 @@ class AzureDevOpsApiWrapper(NonCodeIndexerToolkit):
|
|
|
257
271
|
return ToolException(f"Unable to extract page by path {page_name}: {str(get_page_e)}")
|
|
258
272
|
|
|
259
273
|
try:
|
|
260
|
-
return self._client.create_or_update_page(
|
|
274
|
+
return _format_wiki_page_response(self._client.create_or_update_page(
|
|
261
275
|
project=self.project,
|
|
262
276
|
wiki_identifier=wiki_identified,
|
|
263
277
|
path=page_name,
|
|
264
278
|
parameters=WikiPageCreateOrUpdateParameters(content=page_content),
|
|
265
279
|
version=version,
|
|
266
280
|
version_descriptor=GitVersionDescriptor(version=version_identifier, version_type=version_type)
|
|
267
|
-
)
|
|
281
|
+
), expanded=expanded)
|
|
268
282
|
except AzureDevOpsServiceError as e:
|
|
269
283
|
if "The version '{0}' either is invalid or does not exist." in str(e):
|
|
270
284
|
# Retry the request without version_descriptor
|
|
271
|
-
return self._client.create_or_update_page(
|
|
285
|
+
return _format_wiki_page_response(wiki_page_response=self._client.create_or_update_page(
|
|
272
286
|
project=self.project,
|
|
273
287
|
wiki_identifier=wiki_identified,
|
|
274
288
|
path=page_name,
|
|
275
289
|
parameters=WikiPageCreateOrUpdateParameters(content=page_content),
|
|
276
290
|
version=version
|
|
277
|
-
)
|
|
291
|
+
), expanded=expanded)
|
|
278
292
|
else:
|
|
279
293
|
raise
|
|
280
294
|
except Exception as e:
|
|
@@ -9,18 +9,31 @@ from ...elitea_base import filter_missconfigured_index_tools
|
|
|
9
9
|
from ....configurations.ado import AdoConfiguration
|
|
10
10
|
from ....configurations.pgvector import PgVectorConfiguration
|
|
11
11
|
from ...base.tool import BaseAction
|
|
12
|
-
from ...utils import clean_string,
|
|
12
|
+
from ...utils import clean_string, get_max_toolkit_length, check_connection_response
|
|
13
13
|
|
|
14
14
|
name = "ado_boards"
|
|
15
15
|
|
|
16
|
+
def get_toolkit(tool):
|
|
17
|
+
return AzureDevOpsWorkItemsToolkit().get_toolkit(
|
|
18
|
+
selected_tools=tool['settings'].get('selected_tools', []),
|
|
19
|
+
ado_configuration=tool['settings']['ado_configuration'],
|
|
20
|
+
limit=tool['settings'].get('limit', 5),
|
|
21
|
+
toolkit_name=tool.get('toolkit_name', ''),
|
|
22
|
+
alita=tool['settings'].get('alita', None),
|
|
23
|
+
llm=tool['settings'].get('llm', None),
|
|
24
|
+
pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
|
|
25
|
+
collection_name=tool['toolkit_name'],
|
|
26
|
+
doctype='doc',
|
|
27
|
+
embedding_model=tool['settings'].get('embedding_model'),
|
|
28
|
+
vectorstore_type="PGVector"
|
|
29
|
+
)
|
|
30
|
+
|
|
16
31
|
class AzureDevOpsWorkItemsToolkit(BaseToolkit):
|
|
17
32
|
tools: List[BaseTool] = []
|
|
18
|
-
toolkit_max_length: int = 0
|
|
19
33
|
|
|
20
34
|
@staticmethod
|
|
21
35
|
def toolkit_config_schema() -> BaseModel:
|
|
22
36
|
selected_tools = {x['name']: x['args_schema'].schema() for x in AzureDevOpsApiWrapper.model_construct().get_available_tools()}
|
|
23
|
-
AzureDevOpsWorkItemsToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
24
37
|
m = create_model(
|
|
25
38
|
name,
|
|
26
39
|
ado_configuration=(AdoConfiguration, Field(description="Ado Work Item configuration", json_schema_extra={'configuration_types': ['ado']})),
|
|
@@ -37,7 +50,6 @@ class AzureDevOpsWorkItemsToolkit(BaseToolkit):
|
|
|
37
50
|
'metadata': {
|
|
38
51
|
"label": "ADO boards",
|
|
39
52
|
"icon_url": "ado-boards-icon.svg",
|
|
40
|
-
"max_length": AzureDevOpsWorkItemsToolkit.toolkit_max_length,
|
|
41
53
|
"categories": ["project management"],
|
|
42
54
|
"extra_categories": ["work item management", "issue tracking", "agile boards"],
|
|
43
55
|
"sections": {
|
|
@@ -92,16 +104,20 @@ class AzureDevOpsWorkItemsToolkit(BaseToolkit):
|
|
|
92
104
|
azure_devops_api_wrapper = AzureDevOpsApiWrapper(**wrapper_payload)
|
|
93
105
|
available_tools = azure_devops_api_wrapper.get_available_tools()
|
|
94
106
|
tools = []
|
|
95
|
-
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
|
96
107
|
for tool in available_tools:
|
|
97
108
|
if selected_tools:
|
|
98
109
|
if tool["name"] not in selected_tools:
|
|
99
110
|
continue
|
|
111
|
+
description = tool["description"] + f"\nADO instance: {azure_devops_api_wrapper.organization_url}/{azure_devops_api_wrapper.project}"
|
|
112
|
+
if toolkit_name:
|
|
113
|
+
description = f"{description}\nToolkit: {toolkit_name}"
|
|
114
|
+
description = description[:1000]
|
|
100
115
|
tools.append(BaseAction(
|
|
101
116
|
api_wrapper=azure_devops_api_wrapper,
|
|
102
|
-
name=
|
|
103
|
-
description=
|
|
104
|
-
args_schema=tool["args_schema"]
|
|
117
|
+
name=tool["name"],
|
|
118
|
+
description=description,
|
|
119
|
+
args_schema=tool["args_schema"],
|
|
120
|
+
metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
|
|
105
121
|
))
|
|
106
122
|
return cls(tools=tools)
|
|
107
123
|
|