tooluniverse 1.0.9.1__py3-none-any.whl → 1.0.11__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 tooluniverse might be problematic. Click here for more details.
- tooluniverse/__init__.py +57 -1
- tooluniverse/admetai_tool.py +1 -1
- tooluniverse/agentic_tool.py +65 -17
- tooluniverse/base_tool.py +19 -8
- tooluniverse/blast_tool.py +132 -0
- tooluniverse/boltz_tool.py +3 -3
- tooluniverse/cache/result_cache_manager.py +167 -12
- tooluniverse/cbioportal_tool.py +42 -0
- tooluniverse/clinvar_tool.py +268 -74
- tooluniverse/compose_scripts/drug_safety_analyzer.py +1 -1
- tooluniverse/compose_scripts/multi_agent_literature_search.py +1 -1
- tooluniverse/compose_scripts/output_summarizer.py +4 -4
- tooluniverse/compose_scripts/tool_discover.py +1941 -443
- tooluniverse/compose_scripts/tool_graph_composer.py +1 -1
- tooluniverse/compose_scripts/tool_metadata_generator.py +1 -1
- tooluniverse/compose_tool.py +9 -9
- tooluniverse/core_tool.py +2 -2
- tooluniverse/ctg_tool.py +4 -4
- tooluniverse/custom_tool.py +1 -1
- tooluniverse/data/agentic_tools.json +0 -370
- tooluniverse/data/alphafold_tools.json +6 -6
- tooluniverse/data/blast_tools.json +112 -0
- tooluniverse/data/cbioportal_tools.json +87 -0
- tooluniverse/data/clinvar_tools.json +235 -0
- tooluniverse/data/compose_tools.json +0 -89
- tooluniverse/data/dbsnp_tools.json +275 -0
- tooluniverse/data/emdb_tools.json +61 -0
- tooluniverse/data/ensembl_tools.json +259 -0
- tooluniverse/data/file_download_tools.json +275 -0
- tooluniverse/data/geo_tools.json +200 -48
- tooluniverse/data/gnomad_tools.json +109 -0
- tooluniverse/data/gtopdb_tools.json +68 -0
- tooluniverse/data/gwas_tools.json +32 -0
- tooluniverse/data/interpro_tools.json +199 -0
- tooluniverse/data/jaspar_tools.json +70 -0
- tooluniverse/data/kegg_tools.json +356 -0
- tooluniverse/data/mpd_tools.json +87 -0
- tooluniverse/data/ols_tools.json +314 -0
- tooluniverse/data/package_discovery_tools.json +64 -0
- tooluniverse/data/packages/categorized_tools.txt +0 -1
- tooluniverse/data/packages/machine_learning_tools.json +0 -47
- tooluniverse/data/paleobiology_tools.json +91 -0
- tooluniverse/data/pride_tools.json +62 -0
- tooluniverse/data/pypi_package_inspector_tools.json +158 -0
- tooluniverse/data/python_executor_tools.json +341 -0
- tooluniverse/data/regulomedb_tools.json +50 -0
- tooluniverse/data/remap_tools.json +89 -0
- tooluniverse/data/screen_tools.json +89 -0
- tooluniverse/data/tool_discovery_agents.json +428 -0
- tooluniverse/data/tool_discovery_agents.json.backup +1343 -0
- tooluniverse/data/uniprot_tools.json +77 -0
- tooluniverse/data/web_search_tools.json +250 -0
- tooluniverse/data/worms_tools.json +55 -0
- tooluniverse/dataset_tool.py +2 -2
- tooluniverse/dbsnp_tool.py +196 -58
- tooluniverse/default_config.py +36 -3
- tooluniverse/emdb_tool.py +30 -0
- tooluniverse/enrichr_tool.py +14 -14
- tooluniverse/ensembl_tool.py +140 -47
- tooluniverse/execute_function.py +594 -29
- tooluniverse/extended_hooks.py +4 -4
- tooluniverse/file_download_tool.py +269 -0
- tooluniverse/gene_ontology_tool.py +1 -1
- tooluniverse/generate_tools.py +3 -3
- tooluniverse/geo_tool.py +81 -28
- tooluniverse/gnomad_tool.py +100 -52
- tooluniverse/gtopdb_tool.py +41 -0
- tooluniverse/humanbase_tool.py +10 -10
- tooluniverse/interpro_tool.py +72 -0
- tooluniverse/jaspar_tool.py +30 -0
- tooluniverse/kegg_tool.py +230 -0
- tooluniverse/logging_config.py +2 -2
- tooluniverse/mcp_client_tool.py +57 -129
- tooluniverse/mcp_integration.py +52 -49
- tooluniverse/mcp_tool_registry.py +147 -528
- tooluniverse/mpd_tool.py +42 -0
- tooluniverse/ncbi_eutils_tool.py +96 -0
- tooluniverse/ols_tool.py +435 -0
- tooluniverse/openalex_tool.py +8 -8
- tooluniverse/openfda_tool.py +2 -2
- tooluniverse/output_hook.py +15 -15
- tooluniverse/package_discovery_tool.py +217 -0
- tooluniverse/package_tool.py +1 -1
- tooluniverse/paleobiology_tool.py +30 -0
- tooluniverse/pmc_tool.py +2 -2
- tooluniverse/pride_tool.py +30 -0
- tooluniverse/pypi_package_inspector_tool.py +593 -0
- tooluniverse/python_executor_tool.py +711 -0
- tooluniverse/regulomedb_tool.py +30 -0
- tooluniverse/remap_tool.py +44 -0
- tooluniverse/remote/boltz/boltz_mcp_server.py +1 -1
- tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +3 -3
- tooluniverse/remote/immune_compass/compass_tool.py +3 -3
- tooluniverse/remote/pinnacle/pinnacle_tool.py +2 -2
- tooluniverse/remote/transcriptformer/transcriptformer_tool.py +3 -3
- tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +3 -3
- tooluniverse/remote_tool.py +4 -4
- tooluniverse/screen_tool.py +44 -0
- tooluniverse/scripts/filter_tool_files.py +2 -2
- tooluniverse/smcp.py +93 -12
- tooluniverse/smcp_server.py +100 -21
- tooluniverse/space/__init__.py +46 -0
- tooluniverse/space/loader.py +133 -0
- tooluniverse/space/validator.py +353 -0
- tooluniverse/tool_finder_embedding.py +5 -3
- tooluniverse/tool_finder_keyword.py +12 -10
- tooluniverse/tool_finder_llm.py +12 -8
- tooluniverse/tools/{UCSC_get_genes_by_region.py → BLAST_nucleotide_search.py} +22 -26
- tooluniverse/tools/BLAST_protein_search.py +63 -0
- tooluniverse/tools/ClinVar_search_variants.py +26 -15
- tooluniverse/tools/CodeQualityAnalyzer.py +3 -3
- tooluniverse/tools/EMDB_get_structure.py +46 -0
- tooluniverse/tools/GtoPdb_get_targets.py +52 -0
- tooluniverse/tools/InterPro_get_domain_details.py +46 -0
- tooluniverse/tools/InterPro_get_protein_domains.py +49 -0
- tooluniverse/tools/InterPro_search_domains.py +52 -0
- tooluniverse/tools/JASPAR_get_transcription_factors.py +52 -0
- tooluniverse/tools/MPD_get_phenotype_data.py +59 -0
- tooluniverse/tools/PRIDE_search_proteomics.py +52 -0
- tooluniverse/tools/PackageAnalyzer.py +55 -0
- tooluniverse/tools/Paleobiology_get_fossils.py +52 -0
- tooluniverse/tools/PyPIPackageInspector.py +59 -0
- tooluniverse/tools/ReMap_get_transcription_factor_binding.py +59 -0
- tooluniverse/tools/ReferenceInfoAnalyzer.py +55 -0
- tooluniverse/tools/RegulomeDB_query_variant.py +46 -0
- tooluniverse/tools/SCREEN_get_regulatory_elements.py +59 -0
- tooluniverse/tools/{ArgumentDescriptionOptimizer.py → TestResultsAnalyzer.py} +13 -13
- tooluniverse/tools/ToolDiscover.py +11 -11
- tooluniverse/tools/UniProt_id_mapping.py +63 -0
- tooluniverse/tools/UniProt_search.py +63 -0
- tooluniverse/tools/UnifiedToolGenerator.py +59 -0
- tooluniverse/tools/WoRMS_search_species.py +49 -0
- tooluniverse/tools/XMLToolOptimizer.py +55 -0
- tooluniverse/tools/__init__.py +119 -29
- tooluniverse/tools/_shared_client.py +3 -3
- tooluniverse/tools/alphafold_get_annotations.py +3 -3
- tooluniverse/tools/alphafold_get_prediction.py +3 -3
- tooluniverse/tools/alphafold_get_summary.py +3 -3
- tooluniverse/tools/cBioPortal_get_cancer_studies.py +46 -0
- tooluniverse/tools/cBioPortal_get_mutations.py +52 -0
- tooluniverse/tools/{gnomAD_query_variant.py → clinvar_get_clinical_significance.py} +8 -11
- tooluniverse/tools/clinvar_get_variant_details.py +49 -0
- tooluniverse/tools/dbSNP_get_variant_by_rsid.py +7 -7
- tooluniverse/tools/dbsnp_get_frequencies.py +46 -0
- tooluniverse/tools/dbsnp_search_by_gene.py +52 -0
- tooluniverse/tools/download_binary_file.py +66 -0
- tooluniverse/tools/download_file.py +71 -0
- tooluniverse/tools/download_text_content.py +55 -0
- tooluniverse/tools/dynamic_package_discovery.py +59 -0
- tooluniverse/tools/ensembl_get_sequence.py +52 -0
- tooluniverse/tools/{Ensembl_lookup_gene_by_symbol.py → ensembl_get_variants.py} +11 -11
- tooluniverse/tools/ensembl_lookup_gene.py +46 -0
- tooluniverse/tools/geo_get_dataset_info.py +46 -0
- tooluniverse/tools/geo_get_sample_info.py +46 -0
- tooluniverse/tools/geo_search_datasets.py +67 -0
- tooluniverse/tools/gnomad_get_gene_constraints.py +49 -0
- tooluniverse/tools/kegg_find_genes.py +52 -0
- tooluniverse/tools/kegg_get_gene_info.py +46 -0
- tooluniverse/tools/kegg_get_pathway_info.py +46 -0
- tooluniverse/tools/kegg_list_organisms.py +44 -0
- tooluniverse/tools/kegg_search_pathway.py +46 -0
- tooluniverse/tools/ols_find_similar_terms.py +63 -0
- tooluniverse/tools/{get_hyperopt_info.py → ols_get_ontology_info.py} +13 -10
- tooluniverse/tools/ols_get_term_ancestors.py +67 -0
- tooluniverse/tools/ols_get_term_children.py +67 -0
- tooluniverse/tools/{TestCaseGenerator.py → ols_get_term_info.py} +12 -9
- tooluniverse/tools/{CodeOptimizer.py → ols_search_ontologies.py} +22 -14
- tooluniverse/tools/ols_search_terms.py +71 -0
- tooluniverse/tools/python_code_executor.py +79 -0
- tooluniverse/tools/python_script_runner.py +79 -0
- tooluniverse/tools/web_api_documentation_search.py +63 -0
- tooluniverse/tools/web_search.py +71 -0
- tooluniverse/uniprot_tool.py +219 -16
- tooluniverse/url_tool.py +19 -1
- tooluniverse/uspto_tool.py +1 -1
- tooluniverse/utils.py +12 -12
- tooluniverse/web_search_tool.py +229 -0
- tooluniverse/worms_tool.py +64 -0
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/METADATA +8 -3
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/RECORD +184 -92
- tooluniverse/data/genomics_tools.json +0 -174
- tooluniverse/tools/ToolDescriptionOptimizer.py +0 -67
- tooluniverse/tools/ToolImplementationGenerator.py +0 -67
- tooluniverse/tools/ToolOptimizer.py +0 -59
- tooluniverse/tools/ToolSpecificationGenerator.py +0 -67
- tooluniverse/tools/ToolSpecificationOptimizer.py +0 -63
- tooluniverse/ucsc_tool.py +0 -60
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/WHEEL +0 -0
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/entry_points.txt +0 -0
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-1.0.9.1.dist-info → tooluniverse-1.0.11.dist-info}/top_level.txt +0 -0
tooluniverse/output_hook.py
CHANGED
|
@@ -65,7 +65,7 @@ class HookRule:
|
|
|
65
65
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
66
66
|
context (Dict[str, Any]): Additional context information
|
|
67
67
|
|
|
68
|
-
Returns
|
|
68
|
+
Returns
|
|
69
69
|
bool: True if conditions are met, False otherwise
|
|
70
70
|
"""
|
|
71
71
|
# Evaluate output length conditions
|
|
@@ -158,7 +158,7 @@ class OutputHook:
|
|
|
158
158
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
159
159
|
context (Dict[str, Any]): Additional context information
|
|
160
160
|
|
|
161
|
-
Returns
|
|
161
|
+
Returns
|
|
162
162
|
bool: True if hook should trigger, False otherwise
|
|
163
163
|
"""
|
|
164
164
|
if not self.enabled:
|
|
@@ -184,7 +184,7 @@ class OutputHook:
|
|
|
184
184
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
185
185
|
context (Dict[str, Any]): Additional context information
|
|
186
186
|
|
|
187
|
-
Returns
|
|
187
|
+
Returns
|
|
188
188
|
Any: The processed output
|
|
189
189
|
|
|
190
190
|
Raises:
|
|
@@ -290,7 +290,7 @@ class SummarizationHook(OutputHook):
|
|
|
290
290
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
291
291
|
context (Dict[str, Any]): Additional context information
|
|
292
292
|
|
|
293
|
-
Returns
|
|
293
|
+
Returns
|
|
294
294
|
Any: The summarized output, or original output if summarization fails
|
|
295
295
|
"""
|
|
296
296
|
try:
|
|
@@ -408,7 +408,7 @@ class SummarizationHook(OutputHook):
|
|
|
408
408
|
Args:
|
|
409
409
|
context (Dict[str, Any]): Execution context containing arguments and metadata
|
|
410
410
|
|
|
411
|
-
Returns
|
|
411
|
+
Returns
|
|
412
412
|
str: Extracted query context or fallback description
|
|
413
413
|
"""
|
|
414
414
|
arguments = context.get("arguments", {})
|
|
@@ -519,7 +519,7 @@ class HookManager:
|
|
|
519
519
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
520
520
|
context (Dict[str, Any]): Additional context information
|
|
521
521
|
|
|
522
|
-
Returns
|
|
522
|
+
Returns
|
|
523
523
|
Any: The processed output after applying all applicable hooks
|
|
524
524
|
"""
|
|
525
525
|
if not self.enabled:
|
|
@@ -553,7 +553,7 @@ class HookManager:
|
|
|
553
553
|
"""
|
|
554
554
|
Validate that LLM API keys are available for hook tools.
|
|
555
555
|
|
|
556
|
-
Returns
|
|
556
|
+
Returns
|
|
557
557
|
bool: True if API keys are available, False otherwise
|
|
558
558
|
"""
|
|
559
559
|
from .agentic_tool import AgenticTool
|
|
@@ -641,7 +641,7 @@ class HookManager:
|
|
|
641
641
|
Args:
|
|
642
642
|
hook_name (str): Name of the hook to retrieve
|
|
643
643
|
|
|
644
|
-
Returns
|
|
644
|
+
Returns
|
|
645
645
|
Optional[OutputHook]: Hook instance if found, None otherwise
|
|
646
646
|
"""
|
|
647
647
|
for hook in self.hooks:
|
|
@@ -684,7 +684,7 @@ class HookManager:
|
|
|
684
684
|
"""
|
|
685
685
|
Get the path to the hook configuration file.
|
|
686
686
|
|
|
687
|
-
Returns
|
|
687
|
+
Returns
|
|
688
688
|
Path: Path to the configuration file
|
|
689
689
|
"""
|
|
690
690
|
try:
|
|
@@ -934,7 +934,7 @@ class HookManager:
|
|
|
934
934
|
Args:
|
|
935
935
|
tool_name (str): Name of the tool to check
|
|
936
936
|
|
|
937
|
-
Returns
|
|
937
|
+
Returns
|
|
938
938
|
bool: True if the tool is a hook tool and should be excluded from hook processing
|
|
939
939
|
"""
|
|
940
940
|
hook_tool_names = [
|
|
@@ -956,7 +956,7 @@ class HookManager:
|
|
|
956
956
|
Args:
|
|
957
957
|
hook_config (Dict[str, Any]): Hook configuration
|
|
958
958
|
|
|
959
|
-
Returns
|
|
959
|
+
Returns
|
|
960
960
|
Optional[OutputHook]: Created hook instance or None if type not supported
|
|
961
961
|
"""
|
|
962
962
|
hook_type = hook_config.get("type", "SummarizationHook")
|
|
@@ -985,7 +985,7 @@ class HookManager:
|
|
|
985
985
|
Args:
|
|
986
986
|
hook_config (Dict[str, Any]): Original hook configuration
|
|
987
987
|
|
|
988
|
-
Returns
|
|
988
|
+
Returns
|
|
989
989
|
Dict[str, Any]: Enhanced configuration with defaults applied
|
|
990
990
|
"""
|
|
991
991
|
hook_type = hook_config.get("type", "SummarizationHook")
|
|
@@ -1052,7 +1052,7 @@ class HookManager:
|
|
|
1052
1052
|
tool_name (str): Name of the current tool
|
|
1053
1053
|
context (Dict[str, Any]): Execution context
|
|
1054
1054
|
|
|
1055
|
-
Returns
|
|
1055
|
+
Returns
|
|
1056
1056
|
bool: True if hook is applicable, False otherwise
|
|
1057
1057
|
"""
|
|
1058
1058
|
# Check tool-specific hooks
|
|
@@ -1138,7 +1138,7 @@ class FileSaveHook(OutputHook):
|
|
|
1138
1138
|
arguments (Dict[str, Any]): Arguments passed to the tool
|
|
1139
1139
|
context (Dict[str, Any]): Execution context
|
|
1140
1140
|
|
|
1141
|
-
Returns
|
|
1141
|
+
Returns
|
|
1142
1142
|
Dict[str, Any]: Dictionary containing file information:
|
|
1143
1143
|
- file_path: Path to the saved file
|
|
1144
1144
|
- data_format: Format of the data (json, text, binary, etc.)
|
|
@@ -1213,7 +1213,7 @@ class FileSaveHook(OutputHook):
|
|
|
1213
1213
|
Args:
|
|
1214
1214
|
data (Any): The data to analyze
|
|
1215
1215
|
|
|
1216
|
-
Returns
|
|
1216
|
+
Returns
|
|
1217
1217
|
tuple[str, str]: (data_format, data_structure)
|
|
1218
1218
|
"""
|
|
1219
1219
|
if isinstance(data, dict):
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""Dynamic package discovery and evaluation"""
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
import time
|
|
5
|
+
from typing import Dict, Any, List
|
|
6
|
+
from .base_tool import BaseTool
|
|
7
|
+
from .tool_registry import register_tool
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@register_tool("DynamicPackageDiscovery")
|
|
11
|
+
class DynamicPackageDiscovery(BaseTool):
|
|
12
|
+
"""Searches PyPI and evaluates packages dynamically based on requirements"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, tool_config: Dict[str, Any]):
|
|
15
|
+
super().__init__(tool_config)
|
|
16
|
+
self.pypi_search_url = "https://pypi.org/pypi/{package}/json"
|
|
17
|
+
self.pypi_search_api = "https://pypi.org/search/"
|
|
18
|
+
self.session = requests.Session()
|
|
19
|
+
self.session.headers.update({"User-Agent": "ToolUniverse-PackageDiscovery/1.0"})
|
|
20
|
+
|
|
21
|
+
# Initialize WebSearchTool instance
|
|
22
|
+
from .web_search_tool import WebSearchTool
|
|
23
|
+
|
|
24
|
+
self.web_search_tool = WebSearchTool({"name": "WebSearchTool"})
|
|
25
|
+
|
|
26
|
+
def _search_pypi_via_web(self, query: str) -> List[Dict[str, Any]]:
|
|
27
|
+
"""Search PyPI using web search tool"""
|
|
28
|
+
try:
|
|
29
|
+
# Use pre-initialized WebSearchTool instance
|
|
30
|
+
result = self.web_search_tool.run(
|
|
31
|
+
{
|
|
32
|
+
"query": f"{query} site:pypi.org",
|
|
33
|
+
"max_results": 10,
|
|
34
|
+
"search_type": "python_packages",
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
packages = []
|
|
39
|
+
if result.get("status") == "success":
|
|
40
|
+
for item in result.get("results", []):
|
|
41
|
+
url = item.get("url", "")
|
|
42
|
+
if "pypi.org/project/" in url:
|
|
43
|
+
# Extract package name from URL
|
|
44
|
+
pkg_name = url.split("/project/")[-1].rstrip("/")
|
|
45
|
+
packages.append(
|
|
46
|
+
{
|
|
47
|
+
"name": pkg_name,
|
|
48
|
+
"source": "pypi_web",
|
|
49
|
+
"title": item.get("title", ""),
|
|
50
|
+
"snippet": item.get("snippet", ""),
|
|
51
|
+
"url": url,
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return packages
|
|
56
|
+
except Exception as e:
|
|
57
|
+
print(f"⚠️ Web search for PyPI packages failed: {e}")
|
|
58
|
+
return []
|
|
59
|
+
|
|
60
|
+
def _evaluate_package(self, package_name: str) -> Dict[str, Any]:
|
|
61
|
+
"""Evaluate a package's suitability by fetching PyPI metadata"""
|
|
62
|
+
try:
|
|
63
|
+
response = self.session.get(
|
|
64
|
+
self.pypi_search_url.format(package=package_name), timeout=10
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if response.status_code == 200:
|
|
68
|
+
data = response.json()
|
|
69
|
+
info = data.get("info", {})
|
|
70
|
+
urls = info.get("project_urls", {})
|
|
71
|
+
|
|
72
|
+
# Extract key metrics
|
|
73
|
+
evaluation = {
|
|
74
|
+
"name": package_name,
|
|
75
|
+
"version": info.get("version"),
|
|
76
|
+
"description": info.get("summary", ""),
|
|
77
|
+
"author": info.get("author", ""),
|
|
78
|
+
"license": info.get("license", ""),
|
|
79
|
+
"home_page": info.get("home_page", ""),
|
|
80
|
+
"download_url": info.get("download_url", ""),
|
|
81
|
+
"requires_python": info.get("requires_python", ""),
|
|
82
|
+
"dependencies": info.get("requires_dist", []),
|
|
83
|
+
"classifiers": info.get("classifiers", []),
|
|
84
|
+
# Quality indicators
|
|
85
|
+
"has_docs": bool(urls.get("Documentation")),
|
|
86
|
+
"has_source": bool(urls.get("Source")),
|
|
87
|
+
"has_homepage": bool(info.get("home_page")),
|
|
88
|
+
"has_bug_tracker": bool(urls.get("Bug Reports")),
|
|
89
|
+
"project_urls": urls,
|
|
90
|
+
# Popularity indicators
|
|
91
|
+
"is_stable": "Development Status :: 5 - Production/Stable"
|
|
92
|
+
in info.get("classifiers", []),
|
|
93
|
+
"is_mature": "Development Status :: 6 - Mature"
|
|
94
|
+
in info.get("classifiers", []),
|
|
95
|
+
"has_tests": "Topic :: Software Development :: Testing"
|
|
96
|
+
in info.get("classifiers", []),
|
|
97
|
+
"is_typed": "Typing :: Typed" in info.get("classifiers", []),
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Calculate a basic quality score
|
|
101
|
+
quality_score = 0
|
|
102
|
+
if evaluation["has_docs"]:
|
|
103
|
+
quality_score += 20
|
|
104
|
+
if evaluation["has_source"]:
|
|
105
|
+
quality_score += 15
|
|
106
|
+
if evaluation["is_stable"] or evaluation["is_mature"]:
|
|
107
|
+
quality_score += 25
|
|
108
|
+
if evaluation["has_tests"]:
|
|
109
|
+
quality_score += 15
|
|
110
|
+
if evaluation["is_typed"]:
|
|
111
|
+
quality_score += 10
|
|
112
|
+
if evaluation["has_homepage"]:
|
|
113
|
+
quality_score += 10
|
|
114
|
+
if evaluation["has_bug_tracker"]:
|
|
115
|
+
quality_score += 5
|
|
116
|
+
|
|
117
|
+
evaluation["quality_score"] = min(quality_score, 100)
|
|
118
|
+
|
|
119
|
+
return evaluation
|
|
120
|
+
else:
|
|
121
|
+
return {
|
|
122
|
+
"name": package_name,
|
|
123
|
+
"error": f"HTTP {response.status_code}",
|
|
124
|
+
"quality_score": 0,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
return {"name": package_name, "error": str(e), "quality_score": 0}
|
|
129
|
+
|
|
130
|
+
def _rank_packages(
|
|
131
|
+
self, packages: List[Dict[str, Any]], requirements: str, functionality: str
|
|
132
|
+
) -> List[Dict[str, Any]]:
|
|
133
|
+
"""Rank packages by relevance and quality"""
|
|
134
|
+
if not packages:
|
|
135
|
+
return []
|
|
136
|
+
|
|
137
|
+
# Filter out packages with errors
|
|
138
|
+
valid_packages = [pkg for pkg in packages if "error" not in pkg]
|
|
139
|
+
|
|
140
|
+
# Sort by quality score (descending)
|
|
141
|
+
ranked = sorted(
|
|
142
|
+
valid_packages, key=lambda x: x.get("quality_score", 0), reverse=True
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Add ranking metadata
|
|
146
|
+
for i, pkg in enumerate(ranked):
|
|
147
|
+
pkg["rank"] = i + 1
|
|
148
|
+
pkg["reasoning"] = f"Quality score: {pkg.get('quality_score', 0)}/100"
|
|
149
|
+
|
|
150
|
+
return ranked
|
|
151
|
+
|
|
152
|
+
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
153
|
+
"""
|
|
154
|
+
Dynamically discover and evaluate packages
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
requirements: Description of what's needed
|
|
158
|
+
functionality: Specific functionality required
|
|
159
|
+
constraints: Any constraints (Python version, license, etc.)
|
|
160
|
+
"""
|
|
161
|
+
try:
|
|
162
|
+
requirements = arguments.get("requirements", "")
|
|
163
|
+
functionality = arguments.get("functionality", "")
|
|
164
|
+
|
|
165
|
+
# Search for candidate packages
|
|
166
|
+
search_query = f"{requirements} {functionality}".strip()
|
|
167
|
+
print(f"🔍 Searching for packages: {search_query}")
|
|
168
|
+
|
|
169
|
+
candidates = self._search_pypi_via_web(search_query)
|
|
170
|
+
|
|
171
|
+
if not candidates:
|
|
172
|
+
return {
|
|
173
|
+
"status": "success",
|
|
174
|
+
"candidates": [],
|
|
175
|
+
"recommendation": None,
|
|
176
|
+
"message": "No packages found",
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
print(f"📦 Found {len(candidates)} package candidates")
|
|
180
|
+
|
|
181
|
+
# Evaluate each candidate
|
|
182
|
+
evaluated = []
|
|
183
|
+
for i, pkg in enumerate(candidates):
|
|
184
|
+
print(f" Evaluating {i+1}/{len(candidates)}: {pkg['name']}")
|
|
185
|
+
evaluation = self._evaluate_package(pkg["name"])
|
|
186
|
+
# Merge web search info with PyPI evaluation
|
|
187
|
+
evaluation.update({k: v for k, v in pkg.items() if k not in evaluation})
|
|
188
|
+
evaluated.append(evaluation)
|
|
189
|
+
|
|
190
|
+
# Rate limiting
|
|
191
|
+
time.sleep(0.2)
|
|
192
|
+
|
|
193
|
+
# Rank by suitability
|
|
194
|
+
ranked = self._rank_packages(evaluated, requirements, functionality)
|
|
195
|
+
|
|
196
|
+
top_recommendation = ranked[0] if ranked else None
|
|
197
|
+
|
|
198
|
+
if top_recommendation:
|
|
199
|
+
score = top_recommendation.get("quality_score", 0)
|
|
200
|
+
print(
|
|
201
|
+
f"🏆 Top recommendation: {top_recommendation['name']} (score: {score})"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
"status": "success",
|
|
206
|
+
"candidates": ranked,
|
|
207
|
+
"recommendation": top_recommendation,
|
|
208
|
+
"total_evaluated": len(evaluated),
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
return {
|
|
213
|
+
"status": "error",
|
|
214
|
+
"error": str(e),
|
|
215
|
+
"candidates": [],
|
|
216
|
+
"recommendation": None,
|
|
217
|
+
}
|
tooluniverse/package_tool.py
CHANGED
|
@@ -27,7 +27,7 @@ class PackageTool(BaseTool):
|
|
|
27
27
|
Args:
|
|
28
28
|
arguments (dict): Optional parameters for customization
|
|
29
29
|
|
|
30
|
-
Returns
|
|
30
|
+
Returns
|
|
31
31
|
dict: Package information including name, description, installation, docs, usage
|
|
32
32
|
"""
|
|
33
33
|
include_examples = arguments.get("include_examples", True)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
from .base_tool import BaseTool
|
|
4
|
+
from .tool_registry import register_tool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@register_tool("PaleobiologyRESTTool")
|
|
8
|
+
class PaleobiologyRESTTool(BaseTool):
|
|
9
|
+
def __init__(self, tool_config: Dict):
|
|
10
|
+
super().__init__(tool_config)
|
|
11
|
+
self.base_url = "https://paleobiodb.org/data1.2"
|
|
12
|
+
self.session = requests.Session()
|
|
13
|
+
self.session.headers.update({"Accept": "application/json"})
|
|
14
|
+
self.timeout = 30
|
|
15
|
+
|
|
16
|
+
def _build_url(self, args: Dict[str, Any]) -> str:
|
|
17
|
+
url = self.tool_config["fields"]["endpoint"]
|
|
18
|
+
for k, v in args.items():
|
|
19
|
+
url = url.replace(f"{{{k}}}", str(v))
|
|
20
|
+
return url
|
|
21
|
+
|
|
22
|
+
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
23
|
+
try:
|
|
24
|
+
url = self._build_url(arguments)
|
|
25
|
+
response = self.session.get(url, timeout=self.timeout)
|
|
26
|
+
response.raise_for_status()
|
|
27
|
+
data = response.json()
|
|
28
|
+
return {"status": "success", "data": data, "url": url}
|
|
29
|
+
except Exception as e:
|
|
30
|
+
return {"status": "error", "error": f"Paleobiology API error: {str(e)}"}
|
tooluniverse/pmc_tool.py
CHANGED
|
@@ -43,7 +43,7 @@ class PMCTool(BaseTool):
|
|
|
43
43
|
date_to: End date filter (YYYY/MM/DD)
|
|
44
44
|
article_type: Article type filter (e.g., 'research-article', 'review')
|
|
45
45
|
|
|
46
|
-
Returns
|
|
46
|
+
Returns
|
|
47
47
|
List of paper dictionaries
|
|
48
48
|
"""
|
|
49
49
|
try:
|
|
@@ -158,7 +158,7 @@ class PMCTool(BaseTool):
|
|
|
158
158
|
Args:
|
|
159
159
|
tool_arguments: Dictionary containing search parameters
|
|
160
160
|
|
|
161
|
-
Returns
|
|
161
|
+
Returns
|
|
162
162
|
List of paper dictionaries
|
|
163
163
|
"""
|
|
164
164
|
query = tool_arguments.get("query", "")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
from .base_tool import BaseTool
|
|
4
|
+
from .tool_registry import register_tool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@register_tool("PRIDERESTTool")
|
|
8
|
+
class PRIDERESTTool(BaseTool):
|
|
9
|
+
def __init__(self, tool_config: Dict):
|
|
10
|
+
super().__init__(tool_config)
|
|
11
|
+
self.base_url = "https://www.ebi.ac.uk/pride/ws/archive/v2"
|
|
12
|
+
self.session = requests.Session()
|
|
13
|
+
self.session.headers.update({"Accept": "application/json"})
|
|
14
|
+
self.timeout = 30
|
|
15
|
+
|
|
16
|
+
def _build_url(self, args: Dict[str, Any]) -> str:
|
|
17
|
+
url = self.tool_config["fields"]["endpoint"]
|
|
18
|
+
for k, v in args.items():
|
|
19
|
+
url = url.replace(f"{{{k}}}", str(v))
|
|
20
|
+
return url
|
|
21
|
+
|
|
22
|
+
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
23
|
+
try:
|
|
24
|
+
url = self._build_url(arguments)
|
|
25
|
+
response = self.session.get(url, timeout=self.timeout)
|
|
26
|
+
response.raise_for_status()
|
|
27
|
+
data = response.json()
|
|
28
|
+
return {"status": "success", "data": data, "url": url}
|
|
29
|
+
except Exception as e:
|
|
30
|
+
return {"status": "error", "error": f"PRIDE API error: {str(e)}"}
|