alita-sdk 0.3.150__py3-none-any.whl → 0.3.152__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/__init__.py CHANGED
@@ -9,13 +9,13 @@ This package contains three main modules:
9
9
 
10
10
  __version__ = "0.3.142"
11
11
 
12
- # Import key components
13
- from .runtime import *
14
- from .tools import *
15
- from .community import *
12
+ __all__ = ["runtime", "tools", "community"]
16
13
 
17
- __all__ = [
18
- "runtime",
19
- "tools",
20
- "community",
21
- ]
14
+ import importlib
15
+
16
+ def __getattr__(name):
17
+ if name in __all__:
18
+ module = importlib.import_module(f".{name}", __name__)
19
+ globals()[name] = module
20
+ return module
21
+ raise AttributeError(f"module {__name__} has no attribute {name}")
@@ -7,23 +7,27 @@ Includes agents, clients, language models, and utilities.
7
7
 
8
8
  import importlib
9
9
 
10
- # Import available runtime modules
11
- __all__ = []
10
+ _modules = [
11
+ "agents",
12
+ "clients",
13
+ "langchain",
14
+ "llamaindex",
15
+ "llms",
16
+ "toolkits",
17
+ "tools",
18
+ "utils",
19
+ ]
12
20
 
13
- # Standard imports with fallback
14
- _modules = ['agents', 'clients', 'langchain', 'llamaindex', 'llms', 'toolkits', 'tools', 'utils']
21
+ __all__ = _modules + ["get_tools", "get_toolkits"]
15
22
 
16
- for module_name in _modules:
17
- try:
18
- module = importlib.import_module(f'.{module_name}', package=__name__)
19
- globals()[module_name] = module
20
- __all__.append(module_name)
21
- except ImportError:
22
- pass
23
-
24
- # Always try to export core functions from toolkits
25
- try:
26
- from .toolkits.tools import get_tools, get_toolkits
27
- __all__.extend(["get_tools", "get_toolkits"])
28
- except ImportError:
29
- pass
23
+ def __getattr__(name):
24
+ if name in _modules:
25
+ module = importlib.import_module(f".{name}", __name__)
26
+ globals()[name] = module
27
+ return module
28
+ if name in {"get_tools", "get_toolkits"}:
29
+ toolkits = importlib.import_module(".toolkits.tools", __name__)
30
+ value = getattr(toolkits, name)
31
+ globals()[name] = value
32
+ return value
33
+ raise AttributeError(f"module {__name__} has no attribute {name}")
@@ -1 +1,12 @@
1
- from .client import AlitaClient
1
+ """
2
+ Runtime clients package.
3
+ """
4
+
5
+ try:
6
+ from .client import AlitaClient
7
+ __all__ = ['AlitaClient']
8
+ except ImportError as e:
9
+ # Handle case where dependencies are not available
10
+ import logging
11
+ logging.getLogger(__name__).debug(f"Failed to import AlitaClient: {e}")
12
+ __all__ = []
@@ -30,7 +30,11 @@ from langchain_core.language_models import BaseChatModel # pylint: disable=E040
30
30
  from langchain_core.messages import AIMessage, AIMessageChunk # pylint: disable=E0401
31
31
  from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult # pylint: disable=E0401
32
32
 
33
- from ..langchain.tools import log
33
+ try:
34
+ from ..langchain.tools import log
35
+ except ImportError:
36
+ import logging as _logging
37
+ log = _logging.getLogger(__name__)
34
38
 
35
39
 
36
40
  class PreloadedEmbeddings(Embeddings):
@@ -1,7 +1,12 @@
1
1
  import logging
2
2
  from functools import wraps
3
3
 
4
- from langchain_core.callbacks import dispatch_custom_event
4
+ try:
5
+ from langchain_core.callbacks import dispatch_custom_event
6
+ except ImportError:
7
+ # Fallback stub if langchain_core is unavailable
8
+ def dispatch_custom_event(name: str, data: dict): # pragma: no cover
9
+ pass
5
10
 
6
11
 
7
12
  class StreamlitCallbackHandler(logging.Handler):
@@ -42,6 +47,7 @@ def setup_streamlit_logging(
42
47
  formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
43
48
  handler.setFormatter(formatter)
44
49
  logger.addHandler(handler)
50
+ logger.setLevel(logging.INFO)
45
51
 
46
52
  return handler
47
53
 
@@ -6,13 +6,16 @@ from typing import Any, Dict, Optional
6
6
  from langchain_core.tools import ToolException
7
7
  import pandas as pd
8
8
 
9
- from ..tools.artifact import ArtifactWrapper
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING: # pragma: no cover - avoid heavy imports at runtime
12
+ from ..tools.artifact import ArtifactWrapper
10
13
 
11
14
  logger = logging.getLogger(__name__)
12
15
 
13
16
 
14
17
  def save_dataframe_to_artifact(
15
- artifacts_wrapper: ArtifactWrapper,
18
+ artifacts_wrapper: 'ArtifactWrapper',
16
19
  df: pd.DataFrame,
17
20
  target_file: str,
18
21
  csv_options: Optional[Dict[str, Any]] = None,
@@ -1,178 +1,205 @@
1
1
  import logging
2
2
  from importlib import import_module
3
3
 
4
- from .github import get_tools as get_github, AlitaGitHubToolkit
5
- from .openapi import get_tools as get_openapi
6
- from .jira import get_tools as get_jira, JiraToolkit
7
- from .confluence import get_tools as get_confluence, ConfluenceToolkit
8
- from .servicenow import get_tools as get_service_now, ServiceNowToolkit
9
- from .gitlab import get_tools as get_gitlab, AlitaGitlabToolkit
10
- from .gitlab_org import get_tools as get_gitlab_org, AlitaGitlabSpaceToolkit
11
- from .zephyr import get_tools as get_zephyr, ZephyrToolkit
12
- from .browser import get_tools as get_browser, BrowserToolkit
13
- from .report_portal import get_tools as get_report_portal, ReportPortalToolkit
14
- from .bitbucket import get_tools as get_bitbucket, AlitaBitbucketToolkit
15
- from .testrail import get_tools as get_testrail, TestrailToolkit
16
- from .testio import get_tools as get_testio, TestIOToolkit
17
- from .xray import get_tools as get_xray_cloud, XrayToolkit
18
- from .sharepoint import get_tools as get_sharepoint, SharepointToolkit
19
- from .qtest import get_tools as get_qtest, QtestToolkit
20
- from .zephyr_scale import get_tools as get_zephyr_scale, ZephyrScaleToolkit
21
- from .zephyr_enterprise import get_tools as get_zephyr_enterprise, ZephyrEnterpriseToolkit
22
- from .ado import get_tools as get_ado
23
- from .ado.repos import get_tools as get_ado_repo, AzureDevOpsReposToolkit
24
- from .ado.test_plan import AzureDevOpsPlansToolkit
25
- from .ado.work_item import AzureDevOpsWorkItemsToolkit
26
- from .ado.wiki import AzureDevOpsWikiToolkit
27
- from .rally import get_tools as get_rally, RallyToolkit
28
- from .sql import get_tools as get_sql, SQLToolkit
29
- from .code.sonar import get_tools as get_sonar, SonarToolkit
30
- from .google_places import get_tools as get_google_places, GooglePlacesToolkit
31
- from .yagmail import get_tools as get_yagmail, AlitaYagmailToolkit
32
- from .cloud.aws import AWSToolkit
33
- from .cloud.azure import AzureToolkit
34
- from .cloud.gcp import GCPToolkit
35
- from .cloud.k8s import KubernetesToolkit
36
- from .custom_open_api import OpenApiToolkit as CustomOpenApiToolkit
37
- from .elastic import ElasticToolkit
38
- from .keycloak import KeycloakToolkit
39
- from .localgit import AlitaLocalGitToolkit
40
- from .pandas import get_tools as get_pandas, PandasToolkit
41
- from .azure_ai.search import AzureSearchToolkit, get_tools as get_azure_search
42
- from .figma import get_tools as get_figma, FigmaToolkit
43
- from .salesforce import get_tools as get_salesforce, SalesforceToolkit
44
- from .carrier import get_tools as get_carrier, AlitaCarrierToolkit
45
- from .ocr import get_tools as get_ocr, OCRToolkit
46
- from .pptx import get_tools as get_pptx, PPTXToolkit
47
-
48
4
  logger = logging.getLogger(__name__)
49
5
 
50
- def get_tools(tools_list, alita: 'AlitaClient', llm: 'LLMLikeObject', *args, **kwargs):
6
+ # Available tools and toolkits - populated by safe imports
7
+ AVAILABLE_TOOLS = {}
8
+ AVAILABLE_TOOLKITS = {}
9
+ FAILED_IMPORTS = {}
10
+
11
+ def _safe_import_tool(tool_name, module_path, get_tools_name=None, toolkit_class_name=None):
12
+ """Safely import a tool module and register available functions/classes."""
13
+ try:
14
+ module = __import__(f'alita_sdk.tools.{module_path}', fromlist=[''])
15
+
16
+ imported = {}
17
+ if get_tools_name and hasattr(module, get_tools_name):
18
+ imported['get_tools'] = getattr(module, get_tools_name)
19
+
20
+ if toolkit_class_name and hasattr(module, toolkit_class_name):
21
+ imported['toolkit_class'] = getattr(module, toolkit_class_name)
22
+ AVAILABLE_TOOLKITS[toolkit_class_name] = getattr(module, toolkit_class_name)
23
+
24
+ if imported:
25
+ AVAILABLE_TOOLS[tool_name] = imported
26
+ logger.debug(f"Successfully imported {tool_name}")
27
+
28
+ except Exception as e:
29
+ FAILED_IMPORTS[tool_name] = str(e)
30
+ logger.debug(f"Failed to import {tool_name}: {e}")
31
+
32
+ # Safe imports for all tools
33
+ _safe_import_tool('github', 'github', 'get_tools', 'AlitaGitHubToolkit')
34
+ _safe_import_tool('openapi', 'openapi', 'get_tools')
35
+ _safe_import_tool('jira', 'jira', 'get_tools', 'JiraToolkit')
36
+ _safe_import_tool('confluence', 'confluence', 'get_tools', 'ConfluenceToolkit')
37
+ _safe_import_tool('service_now', 'servicenow', 'get_tools', 'ServiceNowToolkit')
38
+ _safe_import_tool('gitlab', 'gitlab', 'get_tools', 'AlitaGitlabToolkit')
39
+ _safe_import_tool('gitlab_org', 'gitlab_org', 'get_tools', 'AlitaGitlabSpaceToolkit')
40
+ _safe_import_tool('zephyr', 'zephyr', 'get_tools', 'ZephyrToolkit')
41
+ _safe_import_tool('browser', 'browser', 'get_tools', 'BrowserToolkit')
42
+ _safe_import_tool('report_portal', 'report_portal', 'get_tools', 'ReportPortalToolkit')
43
+ _safe_import_tool('bitbucket', 'bitbucket', 'get_tools', 'AlitaBitbucketToolkit')
44
+ _safe_import_tool('testrail', 'testrail', 'get_tools', 'TestrailToolkit')
45
+ _safe_import_tool('testio', 'testio', 'get_tools', 'TestIOToolkit')
46
+ _safe_import_tool('xray_cloud', 'xray', 'get_tools', 'XrayToolkit')
47
+ _safe_import_tool('sharepoint', 'sharepoint', 'get_tools', 'SharepointToolkit')
48
+ _safe_import_tool('qtest', 'qtest', 'get_tools', 'QtestToolkit')
49
+ _safe_import_tool('zephyr_scale', 'zephyr_scale', 'get_tools', 'ZephyrScaleToolkit')
50
+ _safe_import_tool('zephyr_enterprise', 'zephyr_enterprise', 'get_tools', 'ZephyrEnterpriseToolkit')
51
+ _safe_import_tool('ado', 'ado', 'get_tools')
52
+ _safe_import_tool('ado_repos', 'ado.repos', 'get_tools', 'AzureDevOpsReposToolkit')
53
+ _safe_import_tool('ado_plans', 'ado.test_plan', None, 'AzureDevOpsPlansToolkit')
54
+ _safe_import_tool('ado_work_items', 'ado.work_item', None, 'AzureDevOpsWorkItemsToolkit')
55
+ _safe_import_tool('ado_wiki', 'ado.wiki', None, 'AzureDevOpsWikiToolkit')
56
+ _safe_import_tool('rally', 'rally', 'get_tools', 'RallyToolkit')
57
+ _safe_import_tool('sql', 'sql', 'get_tools', 'SQLToolkit')
58
+ _safe_import_tool('sonar', 'code.sonar', 'get_tools', 'SonarToolkit')
59
+ _safe_import_tool('google_places', 'google_places', 'get_tools', 'GooglePlacesToolkit')
60
+ _safe_import_tool('yagmail', 'yagmail', 'get_tools', 'AlitaYagmailToolkit')
61
+ _safe_import_tool('aws', 'cloud.aws', None, 'AWSToolkit')
62
+ _safe_import_tool('azure', 'cloud.azure', None, 'AzureToolkit')
63
+ _safe_import_tool('gcp', 'cloud.gcp', None, 'GCPToolkit')
64
+ _safe_import_tool('k8s', 'cloud.k8s', None, 'KubernetesToolkit')
65
+ _safe_import_tool('custom_open_api', 'custom_open_api', None, 'OpenApiToolkit')
66
+ _safe_import_tool('elastic', 'elastic', None, 'ElasticToolkit')
67
+ _safe_import_tool('keycloak', 'keycloak', None, 'KeycloakToolkit')
68
+ _safe_import_tool('localgit', 'localgit', None, 'AlitaLocalGitToolkit')
69
+ _safe_import_tool('pandas', 'pandas', 'get_tools', 'PandasToolkit')
70
+ _safe_import_tool('azure_search', 'azure_ai.search', 'get_tools', 'AzureSearchToolkit')
71
+ _safe_import_tool('figma', 'figma', 'get_tools', 'FigmaToolkit')
72
+ _safe_import_tool('salesforce', 'salesforce', 'get_tools', 'SalesforceToolkit')
73
+ _safe_import_tool('carrier', 'carrier', 'get_tools', 'AlitaCarrierToolkit')
74
+ _safe_import_tool('ocr', 'ocr', 'get_tools', 'OCRToolkit')
75
+ _safe_import_tool('pptx', 'pptx', 'get_tools', 'PPTXToolkit')
76
+ _safe_import_tool('postman', 'postman', 'get_tools', 'PostmanToolkit')
77
+
78
+ # Log import summary
79
+ available_count = len(AVAILABLE_TOOLS)
80
+ total_attempted = len(AVAILABLE_TOOLS) + len(FAILED_IMPORTS)
81
+ logger.info(f"Tool imports completed: {available_count}/{total_attempted} successful")
82
+
83
+ def get_tools(tools_list, alita, llm, *args, **kwargs):
51
84
  tools = []
52
85
  for tool in tools_list:
53
86
  # validate tool name syntax - it cannot be started with _
54
87
  for tool_name in tool.get('settings', {}).get('selected_tools', []):
55
88
  if isinstance(tool_name, str) and tool_name.startswith('_'):
56
89
  raise ValueError(f"Tool name '{tool_name}' from toolkit '{tool.get('type', '')}' cannot start with '_'")
90
+
57
91
  tool['settings']['alita'] = alita
58
92
  tool['settings']['llm'] = llm
59
- if tool['type'] == 'openapi':
60
- tools.extend(get_openapi(tool))
61
- elif tool['type'] == 'github':
62
- tools.extend(get_github(tool))
63
- elif tool['type'] == 'jira':
64
- tools.extend(get_jira(tool))
65
- elif tool['type'] == 'confluence':
66
- tools.extend(get_confluence(tool))
67
- elif tool['type'] == 'service_now':
68
- tools.extend(get_service_now(tool))
69
- elif tool['type'] == 'gitlab':
70
- tools.extend(get_gitlab(tool))
71
- elif tool['type'] == 'gitlab_org':
72
- tools.extend(get_gitlab_org(tool))
73
- elif tool['type'] == 'zephyr':
74
- tools.extend(get_zephyr(tool))
75
- elif tool['type'] == 'browser':
76
- tools.extend(get_browser(tool))
77
- elif tool['type'] == 'yagmail':
78
- tools.extend(get_yagmail(tool))
79
- elif tool['type'] == 'report_portal':
80
- tools.extend(get_report_portal(tool))
81
- elif tool['type'] == 'bitbucket':
82
- tools.extend(get_bitbucket(tool))
83
- elif tool['type'] == 'testrail':
84
- tools.extend(get_testrail(tool))
85
- elif tool['type'] in ['ado_boards', 'ado_wiki', 'ado_plans']:
86
- tools.extend(get_ado(tool['type'], tool))
87
- elif tool['type'] in ['ado_repos', 'azure_devops_repos']:
88
- tools.extend(get_ado_repo(tool))
89
- elif tool['type'] == 'testio':
90
- tools.extend(get_testio(tool))
91
- elif tool['type'] == 'xray_cloud':
92
- tools.extend(get_xray_cloud(tool))
93
- elif tool['type'] == 'sharepoint':
94
- tools.extend(get_sharepoint(tool))
95
- elif tool['type'] == 'qtest':
96
- tools.extend(get_qtest(tool))
97
- elif tool['type'] == 'zephyr_scale':
98
- tools.extend(get_zephyr_scale(tool))
99
- elif tool['type'] == 'zephyr_enterprise':
100
- tools.extend(get_zephyr_enterprise(tool))
101
- elif tool['type'] == 'rally':
102
- tools.extend(get_rally(tool))
103
- elif tool['type'] == 'sql':
104
- tools.extend(get_sql(tool))
105
- elif tool['type'] == 'sonar':
106
- tools.extend(get_sonar(tool))
107
- elif tool['type'] == 'google_places':
108
- tools.extend(get_google_places(tool))
109
- elif tool['type'] == 'azure_search':
110
- tools.extend(get_azure_search(tool))
111
- elif tool['type'] == 'pandas':
112
- tools.extend(get_pandas(tool))
113
- elif tool['type'] == 'figma':
114
- tools.extend(get_figma(tool))
115
- elif tool['type'] == 'salesforce':
116
- tools.extend(get_salesforce(tool))
117
- elif tool['type'] == 'carrier':
118
- tools.extend(get_carrier(tool))
119
- elif tool['type'] == 'ocr':
120
- tools.extend(get_ocr(tool))
121
- elif tool['type'] == 'pptx':
122
- tools.extend(get_pptx(tool))
93
+ tool_type = tool['type']
94
+
95
+ # Check if tool is available and has get_tools function
96
+ if tool_type in AVAILABLE_TOOLS and 'get_tools' in AVAILABLE_TOOLS[tool_type]:
97
+ try:
98
+ get_tools_func = AVAILABLE_TOOLS[tool_type]['get_tools']
99
+
100
+ # Handle special cases for ADO tools
101
+ if tool_type in ['ado_boards', 'ado_wiki', 'ado_plans']:
102
+ tools.extend(get_tools_func(tool_type, tool))
103
+ else:
104
+ tools.extend(get_tools_func(tool))
105
+
106
+ except Exception as e:
107
+ logger.error(f"Error getting tools for {tool_type}: {e}")
108
+
109
+ # Handle ADO repos special case (it might be requested as azure_devops_repos)
110
+ elif tool_type in ['ado_repos', 'azure_devops_repos'] and 'ado_repos' in AVAILABLE_TOOLS:
111
+ try:
112
+ get_tools_func = AVAILABLE_TOOLS['ado_repos']['get_tools']
113
+ tools.extend(get_tools_func(tool))
114
+ except Exception as e:
115
+ logger.error(f"Error getting ADO repos tools: {e}")
116
+
117
+ # Handle custom modules
118
+ elif tool.get("settings", {}).get("module"):
119
+ try:
120
+ settings = tool.get("settings", {})
121
+ mod = import_module(settings.pop("module"))
122
+ tkitclass = getattr(mod, settings.pop("class"))
123
+ toolkit = tkitclass.get_toolkit(**tool["settings"])
124
+ tools.extend(toolkit.get_tools())
125
+ except Exception as e:
126
+ logger.error(f"Error in getting custom toolkit: {e}")
127
+
123
128
  else:
124
- if tool.get("settings", {}).get("module"):
125
- try:
126
- settings = tool.get("settings", {})
127
- mod = import_module(settings.pop("module"))
128
- tkitclass = getattr(mod, settings.pop("class"))
129
- toolkit = tkitclass.get_toolkit(**tool["settings"])
130
- tools.extend(toolkit.get_tools())
131
- except Exception as e:
132
- logger.error(f"Error in getting toolkit: {e}")
129
+ # Tool not available or not found
130
+ if tool_type in FAILED_IMPORTS:
131
+ logger.warning(f"Tool '{tool_type}' is not available: {FAILED_IMPORTS[tool_type]}")
132
+ else:
133
+ logger.warning(f"Unknown tool type: {tool_type}")
134
+
133
135
  return tools
134
136
 
135
137
  def get_toolkits():
136
- return [
137
- AlitaGitHubToolkit.toolkit_config_schema(),
138
- TestrailToolkit.toolkit_config_schema(),
139
- JiraToolkit.toolkit_config_schema(),
140
- AzureDevOpsPlansToolkit.toolkit_config_schema(),
141
- AzureDevOpsWikiToolkit.toolkit_config_schema(),
142
- AzureDevOpsWorkItemsToolkit.toolkit_config_schema(),
143
- RallyToolkit.toolkit_config_schema(),
144
- QtestToolkit.toolkit_config_schema(),
145
- ReportPortalToolkit.toolkit_config_schema(),
146
- TestIOToolkit.toolkit_config_schema(),
147
- SQLToolkit.toolkit_config_schema(),
148
- SonarToolkit.toolkit_config_schema(),
149
- GooglePlacesToolkit.toolkit_config_schema(),
150
- BrowserToolkit.toolkit_config_schema(),
151
- XrayToolkit.toolkit_config_schema(),
152
- AlitaGitlabToolkit.toolkit_config_schema(),
153
- ConfluenceToolkit.toolkit_config_schema(),
154
- ServiceNowToolkit.toolkit_config_schema(),
155
- AlitaBitbucketToolkit.toolkit_config_schema(),
156
- AlitaGitlabSpaceToolkit.toolkit_config_schema(),
157
- ZephyrScaleToolkit.toolkit_config_schema(),
158
- ZephyrEnterpriseToolkit.toolkit_config_schema(),
159
- ZephyrToolkit.toolkit_config_schema(),
160
- AlitaYagmailToolkit.toolkit_config_schema(),
161
- SharepointToolkit.toolkit_config_schema(),
162
- AzureDevOpsReposToolkit.toolkit_config_schema(),
163
- AWSToolkit.toolkit_config_schema(),
164
- AzureToolkit.toolkit_config_schema(),
165
- GCPToolkit.toolkit_config_schema(),
166
- KubernetesToolkit.toolkit_config_schema(),
167
- CustomOpenApiToolkit.toolkit_config_schema(),
168
- ElasticToolkit.toolkit_config_schema(),
169
- KeycloakToolkit.toolkit_config_schema(),
170
- AlitaLocalGitToolkit.toolkit_config_schema(),
171
- PandasToolkit.toolkit_config_schema(),
172
- AzureSearchToolkit.toolkit_config_schema(),
173
- FigmaToolkit.toolkit_config_schema(),
174
- SalesforceToolkit.toolkit_config_schema(),
175
- AlitaCarrierToolkit.toolkit_config_schema(),
176
- OCRToolkit.toolkit_config_schema(),
177
- PPTXToolkit.toolkit_config_schema(),
178
- ]
138
+ """Return toolkit configurations for all successfully imported toolkits."""
139
+ toolkit_configs = []
140
+
141
+ for toolkit_name, toolkit_class in AVAILABLE_TOOLKITS.items():
142
+ try:
143
+ if hasattr(toolkit_class, 'toolkit_config_schema'):
144
+ toolkit_configs.append(toolkit_class.toolkit_config_schema())
145
+ else:
146
+ logger.debug(f"Toolkit {toolkit_name} does not have toolkit_config_schema method")
147
+ except Exception as e:
148
+ logger.error(f"Error getting config schema for {toolkit_name}: {e}")
149
+
150
+ logger.info(f"Successfully loaded {len(toolkit_configs)} toolkit configurations")
151
+ return toolkit_configs
152
+
153
+ def get_available_tools():
154
+ """Return list of available tool types."""
155
+ return list(AVAILABLE_TOOLS.keys())
156
+
157
+ def get_failed_imports():
158
+ """Return dictionary of failed imports and their error messages."""
159
+ return FAILED_IMPORTS.copy()
160
+
161
+ def get_available_toolkits():
162
+ """Return list of available toolkit class names."""
163
+ return list(AVAILABLE_TOOLKITS.keys())
164
+
165
+ def diagnose_imports():
166
+ """Print diagnostic information about tool imports."""
167
+ available_count = len(AVAILABLE_TOOLS)
168
+ failed_count = len(FAILED_IMPORTS)
169
+ total_count = available_count + failed_count
170
+
171
+ print(f"=== Tool Import Diagnostic ===")
172
+ print(f"Total tools: {total_count}")
173
+ print(f"Successfully imported: {available_count}")
174
+ print(f"Failed imports: {failed_count}")
175
+ print(f"Success rate: {(available_count/total_count*100):.1f}%")
176
+
177
+ if AVAILABLE_TOOLS:
178
+ print(f"\n✅ Available tools ({len(AVAILABLE_TOOLS)}):")
179
+ for tool_name in sorted(AVAILABLE_TOOLS.keys()):
180
+ functions = []
181
+ if 'get_tools' in AVAILABLE_TOOLS[tool_name]:
182
+ functions.append('get_tools')
183
+ if 'toolkit_class' in AVAILABLE_TOOLS[tool_name]:
184
+ functions.append('toolkit')
185
+ print(f" - {tool_name}: {', '.join(functions)}")
186
+
187
+ if FAILED_IMPORTS:
188
+ print(f"\n❌ Failed imports ({len(FAILED_IMPORTS)}):")
189
+ for tool_name, error in FAILED_IMPORTS.items():
190
+ print(f" - {tool_name}: {error}")
191
+
192
+ if AVAILABLE_TOOLKITS:
193
+ print(f"\n🔧 Available toolkits ({len(AVAILABLE_TOOLKITS)}):")
194
+ for toolkit_name in sorted(AVAILABLE_TOOLKITS.keys()):
195
+ print(f" - {toolkit_name}")
196
+
197
+ # Export useful functions
198
+ __all__ = [
199
+ 'get_tools',
200
+ 'get_toolkits',
201
+ 'get_available_tools',
202
+ 'get_failed_imports',
203
+ 'get_available_toolkits',
204
+ 'diagnose_imports'
205
+ ]