tooluniverse 0.2.0__py3-none-any.whl ā 1.0.1__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 +340 -4
- tooluniverse/admetai_tool.py +84 -0
- tooluniverse/agentic_tool.py +563 -0
- tooluniverse/alphafold_tool.py +96 -0
- tooluniverse/base_tool.py +129 -6
- tooluniverse/boltz_tool.py +207 -0
- tooluniverse/chem_tool.py +192 -0
- tooluniverse/compose_scripts/__init__.py +1 -0
- tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
- tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
- tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
- tooluniverse/compose_scripts/literature_tool.py +34 -0
- tooluniverse/compose_scripts/output_summarizer.py +279 -0
- tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
- tooluniverse/compose_scripts/tool_discover.py +705 -0
- tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
- tooluniverse/compose_tool.py +371 -0
- tooluniverse/ctg_tool.py +1002 -0
- tooluniverse/custom_tool.py +81 -0
- tooluniverse/dailymed_tool.py +108 -0
- tooluniverse/data/admetai_tools.json +155 -0
- tooluniverse/data/adverse_event_tools.json +108 -0
- tooluniverse/data/agentic_tools.json +1156 -0
- tooluniverse/data/alphafold_tools.json +87 -0
- tooluniverse/data/boltz_tools.json +9 -0
- tooluniverse/data/chembl_tools.json +16 -0
- tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
- tooluniverse/data/compose_tools.json +202 -0
- tooluniverse/data/dailymed_tools.json +70 -0
- tooluniverse/data/dataset_tools.json +646 -0
- tooluniverse/data/disease_target_score_tools.json +712 -0
- tooluniverse/data/efo_tools.json +17 -0
- tooluniverse/data/embedding_tools.json +319 -0
- tooluniverse/data/enrichr_tools.json +31 -0
- tooluniverse/data/europe_pmc_tools.json +22 -0
- tooluniverse/data/expert_feedback_tools.json +10 -0
- tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
- tooluniverse/data/fda_drug_labeling_tools.json +1 -1
- tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
- tooluniverse/data/finder_tools.json +209 -0
- tooluniverse/data/gene_ontology_tools.json +113 -0
- tooluniverse/data/gwas_tools.json +1082 -0
- tooluniverse/data/hpa_tools.json +333 -0
- tooluniverse/data/humanbase_tools.json +47 -0
- tooluniverse/data/idmap_tools.json +74 -0
- tooluniverse/data/mcp_client_tools_example.json +113 -0
- tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
- tooluniverse/data/medlineplus_tools.json +141 -0
- tooluniverse/data/monarch_tools.json +1 -1
- tooluniverse/data/openalex_tools.json +36 -0
- tooluniverse/data/opentarget_tools.json +1 -1
- tooluniverse/data/output_summarization_tools.json +101 -0
- tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
- tooluniverse/data/packages/categorized_tools.txt +206 -0
- tooluniverse/data/packages/cheminformatics_tools.json +347 -0
- tooluniverse/data/packages/earth_sciences_tools.json +74 -0
- tooluniverse/data/packages/genomics_tools.json +776 -0
- tooluniverse/data/packages/image_processing_tools.json +38 -0
- tooluniverse/data/packages/machine_learning_tools.json +789 -0
- tooluniverse/data/packages/neuroscience_tools.json +62 -0
- tooluniverse/data/packages/original_tools.txt +0 -0
- tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
- tooluniverse/data/packages/scientific_computing_tools.json +560 -0
- tooluniverse/data/packages/single_cell_tools.json +453 -0
- tooluniverse/data/packages/structural_biology_tools.json +396 -0
- tooluniverse/data/packages/visualization_tools.json +399 -0
- tooluniverse/data/pubchem_tools.json +215 -0
- tooluniverse/data/pubtator_tools.json +68 -0
- tooluniverse/data/rcsb_pdb_tools.json +1332 -0
- tooluniverse/data/reactome_tools.json +19 -0
- tooluniverse/data/semantic_scholar_tools.json +26 -0
- tooluniverse/data/special_tools.json +2 -25
- tooluniverse/data/tool_composition_tools.json +88 -0
- tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
- tooluniverse/data/txagent_client_tools.json +9 -0
- tooluniverse/data/uniprot_tools.json +211 -0
- tooluniverse/data/url_fetch_tools.json +94 -0
- tooluniverse/data/uspto_downloader_tools.json +9 -0
- tooluniverse/data/uspto_tools.json +811 -0
- tooluniverse/data/xml_tools.json +3275 -0
- tooluniverse/dataset_tool.py +296 -0
- tooluniverse/default_config.py +165 -0
- tooluniverse/efo_tool.py +42 -0
- tooluniverse/embedding_database.py +630 -0
- tooluniverse/embedding_sync.py +396 -0
- tooluniverse/enrichr_tool.py +266 -0
- tooluniverse/europe_pmc_tool.py +52 -0
- tooluniverse/execute_function.py +1775 -95
- tooluniverse/extended_hooks.py +444 -0
- tooluniverse/gene_ontology_tool.py +194 -0
- tooluniverse/graphql_tool.py +158 -36
- tooluniverse/gwas_tool.py +358 -0
- tooluniverse/hpa_tool.py +1645 -0
- tooluniverse/humanbase_tool.py +389 -0
- tooluniverse/logging_config.py +254 -0
- tooluniverse/mcp_client_tool.py +764 -0
- tooluniverse/mcp_integration.py +413 -0
- tooluniverse/mcp_tool_registry.py +925 -0
- tooluniverse/medlineplus_tool.py +337 -0
- tooluniverse/openalex_tool.py +228 -0
- tooluniverse/openfda_adv_tool.py +283 -0
- tooluniverse/openfda_tool.py +393 -160
- tooluniverse/output_hook.py +1122 -0
- tooluniverse/package_tool.py +195 -0
- tooluniverse/pubchem_tool.py +158 -0
- tooluniverse/pubtator_tool.py +168 -0
- tooluniverse/rcsb_pdb_tool.py +38 -0
- tooluniverse/reactome_tool.py +108 -0
- tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
- tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
- tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
- tooluniverse/remote/expert_feedback/simple_test.py +23 -0
- tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
- tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
- tooluniverse/remote/immune_compass/compass_tool.py +327 -0
- tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
- tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
- tooluniverse/remote_tool.py +99 -0
- tooluniverse/restful_tool.py +53 -30
- tooluniverse/scripts/generate_tool_graph.py +408 -0
- tooluniverse/scripts/visualize_tool_graph.py +829 -0
- tooluniverse/semantic_scholar_tool.py +62 -0
- tooluniverse/smcp.py +2452 -0
- tooluniverse/smcp_server.py +975 -0
- tooluniverse/test/mcp_server_test.py +0 -0
- tooluniverse/test/test_admetai_tool.py +370 -0
- tooluniverse/test/test_agentic_tool.py +129 -0
- tooluniverse/test/test_alphafold_tool.py +71 -0
- tooluniverse/test/test_chem_tool.py +37 -0
- tooluniverse/test/test_compose_lieraturereview.py +63 -0
- tooluniverse/test/test_compose_tool.py +448 -0
- tooluniverse/test/test_dailymed.py +69 -0
- tooluniverse/test/test_dataset_tool.py +200 -0
- tooluniverse/test/test_disease_target_score.py +56 -0
- tooluniverse/test/test_drugbank_filter_examples.py +179 -0
- tooluniverse/test/test_efo.py +31 -0
- tooluniverse/test/test_enrichr_tool.py +21 -0
- tooluniverse/test/test_europe_pmc_tool.py +20 -0
- tooluniverse/test/test_fda_adv.py +95 -0
- tooluniverse/test/test_fda_drug_labeling.py +91 -0
- tooluniverse/test/test_gene_ontology_tools.py +66 -0
- tooluniverse/test/test_gwas_tool.py +139 -0
- tooluniverse/test/test_hpa.py +625 -0
- tooluniverse/test/test_humanbase_tool.py +20 -0
- tooluniverse/test/test_idmap_tools.py +61 -0
- tooluniverse/test/test_mcp_server.py +211 -0
- tooluniverse/test/test_mcp_tool.py +247 -0
- tooluniverse/test/test_medlineplus.py +220 -0
- tooluniverse/test/test_openalex_tool.py +32 -0
- tooluniverse/test/test_opentargets.py +28 -0
- tooluniverse/test/test_pubchem_tool.py +116 -0
- tooluniverse/test/test_pubtator_tool.py +37 -0
- tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
- tooluniverse/test/test_reactome.py +54 -0
- tooluniverse/test/test_semantic_scholar_tool.py +24 -0
- tooluniverse/test/test_software_tools.py +147 -0
- tooluniverse/test/test_tool_description_optimizer.py +49 -0
- tooluniverse/test/test_tool_finder.py +26 -0
- tooluniverse/test/test_tool_finder_llm.py +252 -0
- tooluniverse/test/test_tools_find.py +195 -0
- tooluniverse/test/test_uniprot_tools.py +74 -0
- tooluniverse/test/test_uspto_tool.py +72 -0
- tooluniverse/test/test_xml_tool.py +113 -0
- tooluniverse/tool_finder_embedding.py +267 -0
- tooluniverse/tool_finder_keyword.py +693 -0
- tooluniverse/tool_finder_llm.py +699 -0
- tooluniverse/tool_graph_web_ui.py +955 -0
- tooluniverse/tool_registry.py +416 -0
- tooluniverse/uniprot_tool.py +155 -0
- tooluniverse/url_tool.py +253 -0
- tooluniverse/uspto_tool.py +240 -0
- tooluniverse/utils.py +369 -41
- tooluniverse/xml_tool.py +369 -0
- tooluniverse-1.0.1.dist-info/METADATA +387 -0
- tooluniverse-1.0.1.dist-info/RECORD +182 -0
- tooluniverse-1.0.1.dist-info/entry_points.txt +9 -0
- tooluniverse/generate_mcp_tools.py +0 -113
- tooluniverse/mcp_server.py +0 -3340
- tooluniverse-0.2.0.dist-info/METADATA +0 -139
- tooluniverse-0.2.0.dist-info/RECORD +0 -21
- tooluniverse-0.2.0.dist-info/entry_points.txt +0 -4
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.1.dist-info}/WHEEL +0 -0
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _discover_similar_tools(tool_description, call_tool):
|
|
6
|
+
"""Discover similar tools"""
|
|
7
|
+
similar_tools = []
|
|
8
|
+
|
|
9
|
+
discovery_methods = [
|
|
10
|
+
("Tool_Finder_Keyword", {"description": tool_description, "limit": 5})
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
for method_name, args in discovery_methods:
|
|
14
|
+
result = call_tool(method_name, args)
|
|
15
|
+
if result and isinstance(result, list):
|
|
16
|
+
similar_tools.extend(result)
|
|
17
|
+
|
|
18
|
+
# Deduplicate
|
|
19
|
+
seen = set()
|
|
20
|
+
deduped_tools = []
|
|
21
|
+
for tool in similar_tools:
|
|
22
|
+
try:
|
|
23
|
+
if isinstance(tool, dict):
|
|
24
|
+
tool_tuple = tuple(sorted(tool.items()))
|
|
25
|
+
elif isinstance(tool, (list, tuple)):
|
|
26
|
+
deduped_tools.append(tool)
|
|
27
|
+
continue
|
|
28
|
+
else:
|
|
29
|
+
tool_tuple = tool
|
|
30
|
+
|
|
31
|
+
if tool_tuple not in seen:
|
|
32
|
+
seen.add(tool_tuple)
|
|
33
|
+
deduped_tools.append(tool)
|
|
34
|
+
except (TypeError, AttributeError):
|
|
35
|
+
deduped_tools.append(tool)
|
|
36
|
+
|
|
37
|
+
return deduped_tools
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _generate_tool_specification(tool_description, similar_tools, call_tool):
|
|
41
|
+
"""Generate tool specification"""
|
|
42
|
+
spec_input = {
|
|
43
|
+
"tool_description": tool_description,
|
|
44
|
+
"tool_category": "general",
|
|
45
|
+
"tool_type": "CustomTool",
|
|
46
|
+
"similar_tools": json.dumps(similar_tools) if similar_tools else "[]",
|
|
47
|
+
"existing_tools_summary": "Available tools: standard ToolUniverse tools",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
result = call_tool("ToolSpecificationGenerator", spec_input)
|
|
51
|
+
if not result or "result" not in result:
|
|
52
|
+
raise RuntimeError("ToolSpecificationGenerator returned invalid result")
|
|
53
|
+
|
|
54
|
+
tool_config = result["result"]
|
|
55
|
+
|
|
56
|
+
# Ensure tool_config is a dictionary
|
|
57
|
+
if isinstance(tool_config, str):
|
|
58
|
+
try:
|
|
59
|
+
tool_config = json.loads(tool_config)
|
|
60
|
+
except json.JSONDecodeError:
|
|
61
|
+
raise ValueError(f"Failed to parse tool_config JSON: {tool_config}")
|
|
62
|
+
elif not isinstance(tool_config, dict):
|
|
63
|
+
raise TypeError(
|
|
64
|
+
f"tool_config must be a dictionary, " f"got: {type(tool_config)}"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return tool_config
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _generate_implementation(tool_config, call_tool):
|
|
71
|
+
"""Generate implementation code for all tool types"""
|
|
72
|
+
if "implementation" in tool_config:
|
|
73
|
+
return tool_config
|
|
74
|
+
|
|
75
|
+
impl_input = {
|
|
76
|
+
"tool_description": tool_config.get("description", ""),
|
|
77
|
+
"tool_parameters": json.dumps(tool_config.get("parameter", {})),
|
|
78
|
+
"domain": "general",
|
|
79
|
+
"complexity_level": "intermediate",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Try multiple times to generate implementation
|
|
83
|
+
for attempt in range(3):
|
|
84
|
+
try:
|
|
85
|
+
print(
|
|
86
|
+
f"š Attempting to generate implementation code "
|
|
87
|
+
f"(attempt {attempt + 1}/3)..."
|
|
88
|
+
)
|
|
89
|
+
result = call_tool("ToolImplementationGenerator", impl_input)
|
|
90
|
+
|
|
91
|
+
if result and "result" in result:
|
|
92
|
+
result_data = result["result"]
|
|
93
|
+
if isinstance(result_data, str):
|
|
94
|
+
try:
|
|
95
|
+
impl_data = json.loads(result_data)
|
|
96
|
+
except json.JSONDecodeError as e:
|
|
97
|
+
print(f"ā ļø JSON parsing failed: {e}")
|
|
98
|
+
continue
|
|
99
|
+
else:
|
|
100
|
+
impl_data = result_data
|
|
101
|
+
|
|
102
|
+
if (
|
|
103
|
+
"implementation" in impl_data
|
|
104
|
+
and "source_code" in impl_data["implementation"]
|
|
105
|
+
):
|
|
106
|
+
tool_config["implementation"] = impl_data["implementation"]
|
|
107
|
+
print("ā
Successfully generated implementation code")
|
|
108
|
+
return tool_config
|
|
109
|
+
else:
|
|
110
|
+
missing_fields = list(impl_data.get("implementation", {}).keys())
|
|
111
|
+
print(
|
|
112
|
+
f"ā ļø Generated implementation missing required "
|
|
113
|
+
f"fields: {missing_fields}"
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
print("ā ļø ToolImplementationGenerator returned invalid result")
|
|
117
|
+
|
|
118
|
+
except Exception as e:
|
|
119
|
+
print(
|
|
120
|
+
f"ā Error generating implementation code "
|
|
121
|
+
f"(attempt {attempt + 1}/3): {e}"
|
|
122
|
+
)
|
|
123
|
+
continue
|
|
124
|
+
|
|
125
|
+
return tool_config
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _generate_test_cases(tool_config, call_tool):
|
|
129
|
+
"""Generate test cases"""
|
|
130
|
+
test_input = {"tool_config": tool_config}
|
|
131
|
+
|
|
132
|
+
for attempt in range(5):
|
|
133
|
+
try:
|
|
134
|
+
result = call_tool("TestCaseGenerator", test_input)
|
|
135
|
+
if result and "result" in result:
|
|
136
|
+
result_data = result["result"]
|
|
137
|
+
if isinstance(result_data, str):
|
|
138
|
+
test_data = json.loads(result_data)
|
|
139
|
+
else:
|
|
140
|
+
test_data = result_data
|
|
141
|
+
|
|
142
|
+
if "test_cases" in test_data:
|
|
143
|
+
test_cases = test_data["test_cases"]
|
|
144
|
+
if _validate_test_cases(test_cases, tool_config):
|
|
145
|
+
return test_cases
|
|
146
|
+
except Exception as e:
|
|
147
|
+
print(f"š§ TestCaseGenerator attempt #{attempt + 1}/5 failed: {e}")
|
|
148
|
+
continue
|
|
149
|
+
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _validate_test_cases(test_cases, tool_config):
|
|
154
|
+
"""Validate test cases"""
|
|
155
|
+
if not isinstance(test_cases, list):
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
tool_name = tool_config.get("name", "")
|
|
159
|
+
required_params = tool_config.get("parameter", {}).get("required", [])
|
|
160
|
+
|
|
161
|
+
for test_case in test_cases:
|
|
162
|
+
if not isinstance(test_case, dict):
|
|
163
|
+
return False
|
|
164
|
+
if test_case.get("name") != tool_name:
|
|
165
|
+
return False
|
|
166
|
+
args = test_case.get("arguments", {})
|
|
167
|
+
missing_params = [p for p in required_params if p not in args]
|
|
168
|
+
if missing_params:
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _execute_test_cases(tool_config, test_cases):
|
|
175
|
+
"""Execute test cases to validate code functionality"""
|
|
176
|
+
print("š§Ŗ Executing test cases to validate code functionality...")
|
|
177
|
+
|
|
178
|
+
test_results = {
|
|
179
|
+
"total_tests": len(test_cases),
|
|
180
|
+
"passed_tests": 0,
|
|
181
|
+
"failed_tests": 0,
|
|
182
|
+
"test_details": [],
|
|
183
|
+
"overall_success_rate": 0.0,
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if not test_cases:
|
|
187
|
+
print("ā ļø No test cases to execute")
|
|
188
|
+
return test_results
|
|
189
|
+
|
|
190
|
+
# Dynamic import of generated tool code
|
|
191
|
+
# try:
|
|
192
|
+
# Build tool code file path
|
|
193
|
+
tool_name = tool_config.get("name", "UnknownTool")
|
|
194
|
+
base_filename = f"generated_tool_{tool_config['name']}"
|
|
195
|
+
code_file = f"generated_tool_{tool_name.lower()}_code.py"
|
|
196
|
+
|
|
197
|
+
print("š¾ Saving tool files for testing...")
|
|
198
|
+
|
|
199
|
+
saved_files = _save_tool_files(tool_config, base_filename)
|
|
200
|
+
print(f"Saved: {saved_files}")
|
|
201
|
+
|
|
202
|
+
if os.path.exists(code_file):
|
|
203
|
+
# åØę导å
„å·„å
·
|
|
204
|
+
import importlib.util
|
|
205
|
+
|
|
206
|
+
spec = importlib.util.spec_from_file_location(tool_name, code_file)
|
|
207
|
+
tool_module = importlib.util.module_from_spec(spec)
|
|
208
|
+
spec.loader.exec_module(tool_module)
|
|
209
|
+
|
|
210
|
+
# Get tool function
|
|
211
|
+
tool_function = getattr(tool_module, tool_name.lower(), None)
|
|
212
|
+
|
|
213
|
+
if tool_function:
|
|
214
|
+
print(f"ā
Successfully imported tool: {tool_name}")
|
|
215
|
+
|
|
216
|
+
# Execute each test case
|
|
217
|
+
for i, test_case in enumerate(test_cases):
|
|
218
|
+
test_result = {
|
|
219
|
+
"test_id": i + 1,
|
|
220
|
+
"test_case": test_case,
|
|
221
|
+
"status": "unknown",
|
|
222
|
+
"result": None,
|
|
223
|
+
"error": None,
|
|
224
|
+
"execution_time": 0,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try:
|
|
228
|
+
import time
|
|
229
|
+
|
|
230
|
+
start_time = time.time()
|
|
231
|
+
|
|
232
|
+
# Extract test parameters
|
|
233
|
+
if isinstance(test_case, dict) and "input" in test_case:
|
|
234
|
+
test_args = test_case["input"]
|
|
235
|
+
elif isinstance(test_case, dict) and "arguments" in test_case:
|
|
236
|
+
test_args = test_case["arguments"]
|
|
237
|
+
else:
|
|
238
|
+
test_args = test_case
|
|
239
|
+
|
|
240
|
+
# Execute test
|
|
241
|
+
result = tool_function(test_args)
|
|
242
|
+
print(f"result: {result}")
|
|
243
|
+
execution_time = time.time() - start_time
|
|
244
|
+
|
|
245
|
+
# Validate result
|
|
246
|
+
if result is not None and not isinstance(result, dict):
|
|
247
|
+
test_result["status"] = "failed"
|
|
248
|
+
test_result["error"] = "Return value is not a dictionary"
|
|
249
|
+
elif result is None:
|
|
250
|
+
test_result["status"] = "failed"
|
|
251
|
+
test_result["error"] = "Return value is None"
|
|
252
|
+
else:
|
|
253
|
+
test_result["status"] = "passed"
|
|
254
|
+
test_result["result"] = result
|
|
255
|
+
|
|
256
|
+
test_result["execution_time"] = execution_time
|
|
257
|
+
|
|
258
|
+
except Exception as e:
|
|
259
|
+
test_result["status"] = "failed"
|
|
260
|
+
test_result["error"] = str(e)
|
|
261
|
+
test_result["execution_time"] = 0
|
|
262
|
+
|
|
263
|
+
# Count results
|
|
264
|
+
if test_result["status"] == "passed":
|
|
265
|
+
test_results["passed_tests"] += 1
|
|
266
|
+
else:
|
|
267
|
+
test_results["failed_tests"] += 1
|
|
268
|
+
|
|
269
|
+
test_results["test_details"].append(test_result)
|
|
270
|
+
|
|
271
|
+
# Print test results
|
|
272
|
+
status_emoji = "ā
" if test_result["status"] == "passed" else "ā"
|
|
273
|
+
print(f" {status_emoji} Test {i+1}: {test_result['status']}")
|
|
274
|
+
if test_result["error"]:
|
|
275
|
+
print(f" Error: {test_result['error']}")
|
|
276
|
+
|
|
277
|
+
# Calculate success rate
|
|
278
|
+
test_results["overall_success_rate"] = (
|
|
279
|
+
(test_results["passed_tests"] / test_results["total_tests"])
|
|
280
|
+
if test_results["total_tests"] > 0
|
|
281
|
+
else 0.0
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
passed = test_results["passed_tests"]
|
|
285
|
+
total = test_results["total_tests"]
|
|
286
|
+
print(f"š Test execution completed: {passed}/{total} passed")
|
|
287
|
+
print(f"šÆ Success rate: {test_results['overall_success_rate']:.1%}")
|
|
288
|
+
|
|
289
|
+
else:
|
|
290
|
+
print(f"ā Unable to find tool function: {tool_name.lower()}")
|
|
291
|
+
test_results["error"] = f"Tool function not found: {tool_name.lower()}"
|
|
292
|
+
else:
|
|
293
|
+
print(f"ā Tool code file does not exist: {code_file}")
|
|
294
|
+
test_results["error"] = f"Code file does not exist: {code_file}"
|
|
295
|
+
|
|
296
|
+
return test_results
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _evaluate_quality(tool_config, test_cases, call_tool):
|
|
300
|
+
"""čÆä¼°ä»£ē 蓨é - 使ēØå¢å¼ŗēCodeQualityAnalyzer + å®é
ęµčÆę§č”"""
|
|
301
|
+
|
|
302
|
+
# é¦å
ę§č”ęµčÆę ·ä¾ę„éŖčÆåč½
|
|
303
|
+
test_execution_results = _execute_test_cases(tool_config, test_cases)
|
|
304
|
+
|
|
305
|
+
# ęåå®ē°ä»£ē
|
|
306
|
+
implementation_code = ""
|
|
307
|
+
if "implementation" in tool_config:
|
|
308
|
+
impl = tool_config["implementation"]
|
|
309
|
+
print("impl.keys():", impl.keys())
|
|
310
|
+
implementation_code = impl["source_code"]
|
|
311
|
+
|
|
312
|
+
# Build analysis input including test execution results
|
|
313
|
+
eval_input = {
|
|
314
|
+
"tool_name": tool_config.get("name", "UnknownTool"),
|
|
315
|
+
"tool_description": tool_config.get("description", ""),
|
|
316
|
+
"tool_parameters": json.dumps(tool_config.get("parameter", {})),
|
|
317
|
+
"implementation_code": implementation_code,
|
|
318
|
+
"test_cases": json.dumps(test_cases),
|
|
319
|
+
"test_execution_results": json.dumps(test_execution_results),
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
print("š Using CodeQualityAnalyzer for deep code quality analysis...")
|
|
323
|
+
|
|
324
|
+
result = call_tool("CodeQualityAnalyzer", eval_input)
|
|
325
|
+
print(f"result: {result['result']}")
|
|
326
|
+
|
|
327
|
+
result_data = result["result"]
|
|
328
|
+
parsed_data = json.loads(result_data)
|
|
329
|
+
parsed_data["test_execution"] = test_execution_results
|
|
330
|
+
|
|
331
|
+
return parsed_data
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _expand_test_coverage(tool_config, call_tool):
|
|
335
|
+
"""Expand test coverage"""
|
|
336
|
+
test_input = {
|
|
337
|
+
"tool_config": tool_config,
|
|
338
|
+
"focus_areas": ["edge_cases", "boundary_conditions", "error_scenarios"],
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
result = call_tool("TestCaseGenerator", test_input)
|
|
342
|
+
if result and "result" in result:
|
|
343
|
+
result_data = result["result"]
|
|
344
|
+
if isinstance(result_data, str):
|
|
345
|
+
try:
|
|
346
|
+
test_cases = json.loads(result_data)
|
|
347
|
+
if "test_cases" in test_cases:
|
|
348
|
+
if "testing" not in tool_config:
|
|
349
|
+
tool_config["testing"] = {}
|
|
350
|
+
tool_config["testing"]["test_cases"] = test_cases["test_cases"]
|
|
351
|
+
return tool_config
|
|
352
|
+
except json.JSONDecodeError:
|
|
353
|
+
pass
|
|
354
|
+
|
|
355
|
+
return None
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _optimize_code(tool_config, call_tool, quality_evaluation):
|
|
359
|
+
"""General code optimization"""
|
|
360
|
+
optimization_input = {
|
|
361
|
+
"tool_config": json.dumps(tool_config),
|
|
362
|
+
"quality_evaluation": json.dumps(quality_evaluation),
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
result = call_tool("CodeOptimizer", optimization_input)
|
|
366
|
+
|
|
367
|
+
if result and "result" in result:
|
|
368
|
+
result_data = result["result"]
|
|
369
|
+
optimized = json.loads(result_data)
|
|
370
|
+
|
|
371
|
+
# Check return format, CodeOptimizer now returns {"implementation": {...}}
|
|
372
|
+
if "implementation" in optimized:
|
|
373
|
+
tool_config["implementation"] = optimized["implementation"]
|
|
374
|
+
else:
|
|
375
|
+
# Compatible with old format
|
|
376
|
+
tool_config["implementation"] = optimized
|
|
377
|
+
|
|
378
|
+
return tool_config
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def iterative_code_improvement(
|
|
382
|
+
tool_config, call_tool, max_iterations=5, target_score=9.5
|
|
383
|
+
):
|
|
384
|
+
"""Iteratively improve code implementation until target quality score is reached"""
|
|
385
|
+
print("\nš Starting iterative code improvement process")
|
|
386
|
+
print(f"Target quality score: {target_score}/10")
|
|
387
|
+
print(f"Maximum iterations: {max_iterations}")
|
|
388
|
+
|
|
389
|
+
current_score = 0
|
|
390
|
+
improvement_history = []
|
|
391
|
+
|
|
392
|
+
for iteration in range(max_iterations):
|
|
393
|
+
print(f"\nš Iteration {iteration + 1}/{max_iterations}")
|
|
394
|
+
print(f"Current quality score: {current_score:.2f}/10")
|
|
395
|
+
|
|
396
|
+
# Generate test cases and evaluate quality
|
|
397
|
+
test_cases = _generate_test_cases(tool_config, call_tool)
|
|
398
|
+
print(f"Generated {len(test_cases)} test cases")
|
|
399
|
+
|
|
400
|
+
print(f"test_cases: {test_cases}")
|
|
401
|
+
|
|
402
|
+
quality_evaluation = _evaluate_quality(tool_config, test_cases, call_tool)
|
|
403
|
+
new_score = quality_evaluation.get("overall_score", 0)
|
|
404
|
+
|
|
405
|
+
print(f"Quality evaluation result: {new_score:.2f}/10")
|
|
406
|
+
if "scores" in quality_evaluation:
|
|
407
|
+
for aspect, score in quality_evaluation["scores"].items():
|
|
408
|
+
print(f" - {aspect}: {score:.2f}/10")
|
|
409
|
+
|
|
410
|
+
# Check if target is reached
|
|
411
|
+
if new_score >= target_score:
|
|
412
|
+
print(f"š Target quality score {target_score}/10 reached!")
|
|
413
|
+
improvement_history.append(
|
|
414
|
+
{
|
|
415
|
+
"iteration": iteration + 1,
|
|
416
|
+
"score": new_score,
|
|
417
|
+
"improvement": new_score - current_score,
|
|
418
|
+
"status": "target_achieved",
|
|
419
|
+
}
|
|
420
|
+
)
|
|
421
|
+
break
|
|
422
|
+
|
|
423
|
+
# Record improvement
|
|
424
|
+
improvement = new_score - current_score
|
|
425
|
+
print(f"Improvement: {improvement:+.2f}")
|
|
426
|
+
|
|
427
|
+
improvement_history.append(
|
|
428
|
+
{
|
|
429
|
+
"iteration": iteration + 1,
|
|
430
|
+
"score": new_score,
|
|
431
|
+
"improvement": improvement,
|
|
432
|
+
"status": "improved",
|
|
433
|
+
}
|
|
434
|
+
)
|
|
435
|
+
current_score = new_score
|
|
436
|
+
|
|
437
|
+
tool_config = _optimize_code(tool_config, call_tool, quality_evaluation)
|
|
438
|
+
|
|
439
|
+
# Final quality evaluation
|
|
440
|
+
final_test_cases = _generate_test_cases(tool_config, call_tool)
|
|
441
|
+
final_quality = _evaluate_quality(tool_config, final_test_cases, call_tool)
|
|
442
|
+
final_score = final_quality.get("overall_score", current_score)
|
|
443
|
+
|
|
444
|
+
print("š Iterative improvement completed")
|
|
445
|
+
print(f"Final quality score: {final_score:.2f}/10")
|
|
446
|
+
print(f"Total iterations: {len(improvement_history)}")
|
|
447
|
+
|
|
448
|
+
print("\nš Improvement history:")
|
|
449
|
+
for record in improvement_history:
|
|
450
|
+
status_emoji = "šÆ" if record["status"] == "target_achieved" else "š"
|
|
451
|
+
print(
|
|
452
|
+
f" {status_emoji} Round {record['iteration']}: {record['score']:.2f}/10 (improvement: {record['score']:+.2f})"
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
return tool_config, final_score, improvement_history
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def _save_tool_files(tool_config, base_filename):
|
|
459
|
+
"""Save tool files"""
|
|
460
|
+
# Update configuration
|
|
461
|
+
config_to_save = tool_config.copy()
|
|
462
|
+
class_name = config_to_save.get("name", "CustomTool")
|
|
463
|
+
config_to_save["type"] = class_name
|
|
464
|
+
|
|
465
|
+
# Extract dependency information
|
|
466
|
+
dependencies = []
|
|
467
|
+
if (
|
|
468
|
+
"implementation" in tool_config
|
|
469
|
+
and "dependencies" in tool_config["implementation"]
|
|
470
|
+
):
|
|
471
|
+
dependencies = tool_config["implementation"]["dependencies"]
|
|
472
|
+
|
|
473
|
+
# Add dependencies field to configuration
|
|
474
|
+
config_to_save["dependencies"] = dependencies
|
|
475
|
+
|
|
476
|
+
# Remove implementation code
|
|
477
|
+
if "implementation" in config_to_save:
|
|
478
|
+
del config_to_save["implementation"]
|
|
479
|
+
|
|
480
|
+
# Save configuration file
|
|
481
|
+
config_file = f"{base_filename}_config.json"
|
|
482
|
+
with open(config_file, "w", encoding="utf-8") as f:
|
|
483
|
+
json.dump(config_to_save, f, indent=2, ensure_ascii=False)
|
|
484
|
+
|
|
485
|
+
# Generate code file
|
|
486
|
+
code_file = f"{base_filename}_code.py"
|
|
487
|
+
_generate_tool_code(tool_config, code_file)
|
|
488
|
+
|
|
489
|
+
return [config_file, code_file]
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def _convert_json_to_python(obj):
|
|
493
|
+
"""Recursively convert JSON object booleans and types to Python format"""
|
|
494
|
+
if isinstance(obj, dict):
|
|
495
|
+
result = {}
|
|
496
|
+
for key, value in obj.items():
|
|
497
|
+
result[key] = _convert_json_to_python(value)
|
|
498
|
+
return result
|
|
499
|
+
elif isinstance(obj, list):
|
|
500
|
+
return [_convert_json_to_python(item) for item in obj]
|
|
501
|
+
elif obj == "true":
|
|
502
|
+
return True
|
|
503
|
+
elif obj == "false":
|
|
504
|
+
return False
|
|
505
|
+
elif obj == "string":
|
|
506
|
+
return str
|
|
507
|
+
elif obj == "number":
|
|
508
|
+
return float
|
|
509
|
+
elif obj == "integer":
|
|
510
|
+
return int
|
|
511
|
+
elif obj == "object":
|
|
512
|
+
return dict
|
|
513
|
+
elif obj == "array":
|
|
514
|
+
return list
|
|
515
|
+
else:
|
|
516
|
+
return obj
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def _convert_python_types_to_strings(obj):
|
|
520
|
+
"""Recursively convert Python type objects to string representations for JSON serialization"""
|
|
521
|
+
if isinstance(obj, dict):
|
|
522
|
+
result = {}
|
|
523
|
+
for key, value in obj.items():
|
|
524
|
+
result[key] = _convert_python_types_to_strings(value)
|
|
525
|
+
return result
|
|
526
|
+
elif isinstance(obj, list):
|
|
527
|
+
return [_convert_python_types_to_strings(item) for item in obj]
|
|
528
|
+
elif obj is True:
|
|
529
|
+
return "True"
|
|
530
|
+
elif obj is False:
|
|
531
|
+
return "False"
|
|
532
|
+
elif obj is str:
|
|
533
|
+
return "str"
|
|
534
|
+
elif obj is float:
|
|
535
|
+
return "float"
|
|
536
|
+
elif obj is int:
|
|
537
|
+
return "int"
|
|
538
|
+
elif obj is dict:
|
|
539
|
+
return "dict"
|
|
540
|
+
elif obj is list:
|
|
541
|
+
return "list"
|
|
542
|
+
else:
|
|
543
|
+
return obj
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def _generate_tool_code(tool_config, code_file):
|
|
547
|
+
"""Generate Python code for all tool types using correct register_tool method"""
|
|
548
|
+
tool_name = tool_config["name"]
|
|
549
|
+
|
|
550
|
+
with open(code_file, "w", encoding="utf-8") as f:
|
|
551
|
+
# Add dependency instructions comment
|
|
552
|
+
if (
|
|
553
|
+
"implementation" in tool_config
|
|
554
|
+
and "dependencies" in tool_config["implementation"]
|
|
555
|
+
):
|
|
556
|
+
dependencies = tool_config["implementation"]["dependencies"]
|
|
557
|
+
if dependencies:
|
|
558
|
+
f.write("# Required packages:\n")
|
|
559
|
+
for dep in dependencies:
|
|
560
|
+
f.write(f"# pip install {dep}\n")
|
|
561
|
+
f.write("\n")
|
|
562
|
+
|
|
563
|
+
f.write("from typing import Dict, Any\n")
|
|
564
|
+
f.write("from src.tooluniverse import register_tool\n\n")
|
|
565
|
+
|
|
566
|
+
# Import dependencies
|
|
567
|
+
if (
|
|
568
|
+
"implementation" in tool_config
|
|
569
|
+
and "imports" in tool_config["implementation"]
|
|
570
|
+
):
|
|
571
|
+
for imp in tool_config["implementation"]["imports"]:
|
|
572
|
+
f.write(f"{imp}\n")
|
|
573
|
+
|
|
574
|
+
f.write("\n")
|
|
575
|
+
|
|
576
|
+
# Generate function implementation directly, no classes
|
|
577
|
+
f.write("@register_tool(\n")
|
|
578
|
+
f.write(f' "{tool_name}",\n')
|
|
579
|
+
f.write(" {\n")
|
|
580
|
+
f.write(f' "name": "{tool_name}",\n')
|
|
581
|
+
f.write(f' "type": "{tool_name}",\n')
|
|
582
|
+
f.write(f' "description": "{tool_config.get("description", "")}",\n')
|
|
583
|
+
|
|
584
|
+
# Use helper functions to convert JSON booleans and types to Python format
|
|
585
|
+
parameter_json = _convert_json_to_python(tool_config.get("parameter", {}))
|
|
586
|
+
# Convert Python type objects to string representations
|
|
587
|
+
parameter_json_str = _convert_python_types_to_strings(parameter_json)
|
|
588
|
+
f.write(f' "parameter": {json.dumps(parameter_json_str, indent=8)},\n')
|
|
589
|
+
|
|
590
|
+
return_schema_json = _convert_json_to_python(
|
|
591
|
+
tool_config.get("return_schema", {})
|
|
592
|
+
)
|
|
593
|
+
# Convert Python type objects to string representations
|
|
594
|
+
return_schema_json_str = _convert_python_types_to_strings(return_schema_json)
|
|
595
|
+
f.write(
|
|
596
|
+
f' "return_schema": {json.dumps(return_schema_json_str, indent=8)},\n'
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
# Add dependency information
|
|
600
|
+
if (
|
|
601
|
+
"implementation" in tool_config
|
|
602
|
+
and "dependencies" in tool_config["implementation"]
|
|
603
|
+
):
|
|
604
|
+
dependencies = tool_config["implementation"]["dependencies"]
|
|
605
|
+
f.write(f' "dependencies": {json.dumps(dependencies, indent=8)}\n')
|
|
606
|
+
else:
|
|
607
|
+
f.write(' "dependencies": []\n')
|
|
608
|
+
|
|
609
|
+
f.write(" }\n")
|
|
610
|
+
f.write(")\n")
|
|
611
|
+
f.write(
|
|
612
|
+
f"def {tool_name.lower()}(arguments: Dict[str, Any]) -> Dict[str, Any]:\n"
|
|
613
|
+
)
|
|
614
|
+
f.write(f' """{tool_config.get("description", "")}"""\n')
|
|
615
|
+
f.write(" try:\n")
|
|
616
|
+
|
|
617
|
+
# Add source code
|
|
618
|
+
if (
|
|
619
|
+
"implementation" in tool_config
|
|
620
|
+
and "source_code" in tool_config["implementation"]
|
|
621
|
+
):
|
|
622
|
+
source_code = tool_config["implementation"]["source_code"]
|
|
623
|
+
f.write(" # Generated implementation:\n")
|
|
624
|
+
for line in source_code.split("\n"):
|
|
625
|
+
if line.strip(): # Skip empty lines
|
|
626
|
+
f.write(f" {line}\n")
|
|
627
|
+
else:
|
|
628
|
+
f.write("\n")
|
|
629
|
+
|
|
630
|
+
# Ensure execute_tool is called and result is returned
|
|
631
|
+
f.write(" \n")
|
|
632
|
+
f.write(" # Execute the tool and return result\n")
|
|
633
|
+
f.write(" return execute_tool(arguments)\n")
|
|
634
|
+
else:
|
|
635
|
+
# Default implementation
|
|
636
|
+
f.write(" result = {\n")
|
|
637
|
+
f.write(' "status": "success",\n')
|
|
638
|
+
f.write(' "message": "Tool executed successfully",\n')
|
|
639
|
+
f.write(' "input": arguments\n')
|
|
640
|
+
f.write(" }\n")
|
|
641
|
+
f.write(" return result\n")
|
|
642
|
+
|
|
643
|
+
f.write(" except Exception as e:\n")
|
|
644
|
+
f.write(' return {"error": str(e)}\n')
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
def compose(arguments, tooluniverse, call_tool):
|
|
648
|
+
"""General tool discovery and generation system"""
|
|
649
|
+
tool_description = arguments["tool_description"]
|
|
650
|
+
max_iterations = arguments.get("max_iterations", 2)
|
|
651
|
+
arguments.get("save_to_file", True)
|
|
652
|
+
|
|
653
|
+
print(f"š Starting tool discovery: {tool_description}")
|
|
654
|
+
|
|
655
|
+
# 1. Discover similar tools
|
|
656
|
+
print("š Discovering similar tools...")
|
|
657
|
+
similar_tools = _discover_similar_tools(tool_description, call_tool)
|
|
658
|
+
print(f"Found {len(similar_tools)} similar tools")
|
|
659
|
+
|
|
660
|
+
# 2. Generate initial tool specification
|
|
661
|
+
print("šļø Generating tool specification...")
|
|
662
|
+
tool_config = _generate_tool_specification(
|
|
663
|
+
tool_description, similar_tools, call_tool
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
# 3. Generate implementation for all tools
|
|
667
|
+
print("š» Generating code implementation...")
|
|
668
|
+
tool_config = _generate_implementation(tool_config, call_tool)
|
|
669
|
+
|
|
670
|
+
# 4. Iterative optimization
|
|
671
|
+
print("\nš Starting enhanced iterative improvement system...")
|
|
672
|
+
|
|
673
|
+
target_quality_score = arguments.get("target_quality_score", 8.5)
|
|
674
|
+
|
|
675
|
+
print(
|
|
676
|
+
f"šÆ Enabling iterative improvement, target quality score: {target_quality_score}/10"
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
tool_config, final_quality_score, improvement_history = iterative_code_improvement(
|
|
680
|
+
tool_config,
|
|
681
|
+
call_tool,
|
|
682
|
+
max_iterations=max_iterations,
|
|
683
|
+
target_score=target_quality_score,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
print(
|
|
687
|
+
f"š Iterative improvement completed! Final quality score: {final_quality_score:.2f}/10"
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
# 5. Save tool files
|
|
691
|
+
print("š¾ Saving tool files...")
|
|
692
|
+
base_filename = f"generated_tool_{tool_config['name']}"
|
|
693
|
+
saved_files = _save_tool_files(tool_config, base_filename)
|
|
694
|
+
print(f"Saved: {saved_files}")
|
|
695
|
+
|
|
696
|
+
print("\nš Tool generation completed!")
|
|
697
|
+
print(f"Tool name: {tool_config['name']}")
|
|
698
|
+
print(f"Tool type: {tool_config['type']}")
|
|
699
|
+
print(f"Final quality: {final_quality_score:.1f}/10")
|
|
700
|
+
|
|
701
|
+
return {
|
|
702
|
+
"tool_config": tool_config,
|
|
703
|
+
"quality_score": final_quality_score,
|
|
704
|
+
"saved_files": saved_files,
|
|
705
|
+
}
|