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.

Files changed (186) hide show
  1. tooluniverse/__init__.py +340 -4
  2. tooluniverse/admetai_tool.py +84 -0
  3. tooluniverse/agentic_tool.py +563 -0
  4. tooluniverse/alphafold_tool.py +96 -0
  5. tooluniverse/base_tool.py +129 -6
  6. tooluniverse/boltz_tool.py +207 -0
  7. tooluniverse/chem_tool.py +192 -0
  8. tooluniverse/compose_scripts/__init__.py +1 -0
  9. tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
  10. tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
  11. tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
  12. tooluniverse/compose_scripts/literature_tool.py +34 -0
  13. tooluniverse/compose_scripts/output_summarizer.py +279 -0
  14. tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
  15. tooluniverse/compose_scripts/tool_discover.py +705 -0
  16. tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
  17. tooluniverse/compose_tool.py +371 -0
  18. tooluniverse/ctg_tool.py +1002 -0
  19. tooluniverse/custom_tool.py +81 -0
  20. tooluniverse/dailymed_tool.py +108 -0
  21. tooluniverse/data/admetai_tools.json +155 -0
  22. tooluniverse/data/adverse_event_tools.json +108 -0
  23. tooluniverse/data/agentic_tools.json +1156 -0
  24. tooluniverse/data/alphafold_tools.json +87 -0
  25. tooluniverse/data/boltz_tools.json +9 -0
  26. tooluniverse/data/chembl_tools.json +16 -0
  27. tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
  28. tooluniverse/data/compose_tools.json +202 -0
  29. tooluniverse/data/dailymed_tools.json +70 -0
  30. tooluniverse/data/dataset_tools.json +646 -0
  31. tooluniverse/data/disease_target_score_tools.json +712 -0
  32. tooluniverse/data/efo_tools.json +17 -0
  33. tooluniverse/data/embedding_tools.json +319 -0
  34. tooluniverse/data/enrichr_tools.json +31 -0
  35. tooluniverse/data/europe_pmc_tools.json +22 -0
  36. tooluniverse/data/expert_feedback_tools.json +10 -0
  37. tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
  38. tooluniverse/data/fda_drug_labeling_tools.json +1 -1
  39. tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
  40. tooluniverse/data/finder_tools.json +209 -0
  41. tooluniverse/data/gene_ontology_tools.json +113 -0
  42. tooluniverse/data/gwas_tools.json +1082 -0
  43. tooluniverse/data/hpa_tools.json +333 -0
  44. tooluniverse/data/humanbase_tools.json +47 -0
  45. tooluniverse/data/idmap_tools.json +74 -0
  46. tooluniverse/data/mcp_client_tools_example.json +113 -0
  47. tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
  48. tooluniverse/data/medlineplus_tools.json +141 -0
  49. tooluniverse/data/monarch_tools.json +1 -1
  50. tooluniverse/data/openalex_tools.json +36 -0
  51. tooluniverse/data/opentarget_tools.json +1 -1
  52. tooluniverse/data/output_summarization_tools.json +101 -0
  53. tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
  54. tooluniverse/data/packages/categorized_tools.txt +206 -0
  55. tooluniverse/data/packages/cheminformatics_tools.json +347 -0
  56. tooluniverse/data/packages/earth_sciences_tools.json +74 -0
  57. tooluniverse/data/packages/genomics_tools.json +776 -0
  58. tooluniverse/data/packages/image_processing_tools.json +38 -0
  59. tooluniverse/data/packages/machine_learning_tools.json +789 -0
  60. tooluniverse/data/packages/neuroscience_tools.json +62 -0
  61. tooluniverse/data/packages/original_tools.txt +0 -0
  62. tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
  63. tooluniverse/data/packages/scientific_computing_tools.json +560 -0
  64. tooluniverse/data/packages/single_cell_tools.json +453 -0
  65. tooluniverse/data/packages/structural_biology_tools.json +396 -0
  66. tooluniverse/data/packages/visualization_tools.json +399 -0
  67. tooluniverse/data/pubchem_tools.json +215 -0
  68. tooluniverse/data/pubtator_tools.json +68 -0
  69. tooluniverse/data/rcsb_pdb_tools.json +1332 -0
  70. tooluniverse/data/reactome_tools.json +19 -0
  71. tooluniverse/data/semantic_scholar_tools.json +26 -0
  72. tooluniverse/data/special_tools.json +2 -25
  73. tooluniverse/data/tool_composition_tools.json +88 -0
  74. tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
  75. tooluniverse/data/txagent_client_tools.json +9 -0
  76. tooluniverse/data/uniprot_tools.json +211 -0
  77. tooluniverse/data/url_fetch_tools.json +94 -0
  78. tooluniverse/data/uspto_downloader_tools.json +9 -0
  79. tooluniverse/data/uspto_tools.json +811 -0
  80. tooluniverse/data/xml_tools.json +3275 -0
  81. tooluniverse/dataset_tool.py +296 -0
  82. tooluniverse/default_config.py +165 -0
  83. tooluniverse/efo_tool.py +42 -0
  84. tooluniverse/embedding_database.py +630 -0
  85. tooluniverse/embedding_sync.py +396 -0
  86. tooluniverse/enrichr_tool.py +266 -0
  87. tooluniverse/europe_pmc_tool.py +52 -0
  88. tooluniverse/execute_function.py +1775 -95
  89. tooluniverse/extended_hooks.py +444 -0
  90. tooluniverse/gene_ontology_tool.py +194 -0
  91. tooluniverse/graphql_tool.py +158 -36
  92. tooluniverse/gwas_tool.py +358 -0
  93. tooluniverse/hpa_tool.py +1645 -0
  94. tooluniverse/humanbase_tool.py +389 -0
  95. tooluniverse/logging_config.py +254 -0
  96. tooluniverse/mcp_client_tool.py +764 -0
  97. tooluniverse/mcp_integration.py +413 -0
  98. tooluniverse/mcp_tool_registry.py +925 -0
  99. tooluniverse/medlineplus_tool.py +337 -0
  100. tooluniverse/openalex_tool.py +228 -0
  101. tooluniverse/openfda_adv_tool.py +283 -0
  102. tooluniverse/openfda_tool.py +393 -160
  103. tooluniverse/output_hook.py +1122 -0
  104. tooluniverse/package_tool.py +195 -0
  105. tooluniverse/pubchem_tool.py +158 -0
  106. tooluniverse/pubtator_tool.py +168 -0
  107. tooluniverse/rcsb_pdb_tool.py +38 -0
  108. tooluniverse/reactome_tool.py +108 -0
  109. tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
  110. tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
  111. tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
  112. tooluniverse/remote/expert_feedback/simple_test.py +23 -0
  113. tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
  114. tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
  115. tooluniverse/remote/immune_compass/compass_tool.py +327 -0
  116. tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
  117. tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
  118. tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
  119. tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
  120. tooluniverse/remote_tool.py +99 -0
  121. tooluniverse/restful_tool.py +53 -30
  122. tooluniverse/scripts/generate_tool_graph.py +408 -0
  123. tooluniverse/scripts/visualize_tool_graph.py +829 -0
  124. tooluniverse/semantic_scholar_tool.py +62 -0
  125. tooluniverse/smcp.py +2452 -0
  126. tooluniverse/smcp_server.py +975 -0
  127. tooluniverse/test/mcp_server_test.py +0 -0
  128. tooluniverse/test/test_admetai_tool.py +370 -0
  129. tooluniverse/test/test_agentic_tool.py +129 -0
  130. tooluniverse/test/test_alphafold_tool.py +71 -0
  131. tooluniverse/test/test_chem_tool.py +37 -0
  132. tooluniverse/test/test_compose_lieraturereview.py +63 -0
  133. tooluniverse/test/test_compose_tool.py +448 -0
  134. tooluniverse/test/test_dailymed.py +69 -0
  135. tooluniverse/test/test_dataset_tool.py +200 -0
  136. tooluniverse/test/test_disease_target_score.py +56 -0
  137. tooluniverse/test/test_drugbank_filter_examples.py +179 -0
  138. tooluniverse/test/test_efo.py +31 -0
  139. tooluniverse/test/test_enrichr_tool.py +21 -0
  140. tooluniverse/test/test_europe_pmc_tool.py +20 -0
  141. tooluniverse/test/test_fda_adv.py +95 -0
  142. tooluniverse/test/test_fda_drug_labeling.py +91 -0
  143. tooluniverse/test/test_gene_ontology_tools.py +66 -0
  144. tooluniverse/test/test_gwas_tool.py +139 -0
  145. tooluniverse/test/test_hpa.py +625 -0
  146. tooluniverse/test/test_humanbase_tool.py +20 -0
  147. tooluniverse/test/test_idmap_tools.py +61 -0
  148. tooluniverse/test/test_mcp_server.py +211 -0
  149. tooluniverse/test/test_mcp_tool.py +247 -0
  150. tooluniverse/test/test_medlineplus.py +220 -0
  151. tooluniverse/test/test_openalex_tool.py +32 -0
  152. tooluniverse/test/test_opentargets.py +28 -0
  153. tooluniverse/test/test_pubchem_tool.py +116 -0
  154. tooluniverse/test/test_pubtator_tool.py +37 -0
  155. tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
  156. tooluniverse/test/test_reactome.py +54 -0
  157. tooluniverse/test/test_semantic_scholar_tool.py +24 -0
  158. tooluniverse/test/test_software_tools.py +147 -0
  159. tooluniverse/test/test_tool_description_optimizer.py +49 -0
  160. tooluniverse/test/test_tool_finder.py +26 -0
  161. tooluniverse/test/test_tool_finder_llm.py +252 -0
  162. tooluniverse/test/test_tools_find.py +195 -0
  163. tooluniverse/test/test_uniprot_tools.py +74 -0
  164. tooluniverse/test/test_uspto_tool.py +72 -0
  165. tooluniverse/test/test_xml_tool.py +113 -0
  166. tooluniverse/tool_finder_embedding.py +267 -0
  167. tooluniverse/tool_finder_keyword.py +693 -0
  168. tooluniverse/tool_finder_llm.py +699 -0
  169. tooluniverse/tool_graph_web_ui.py +955 -0
  170. tooluniverse/tool_registry.py +416 -0
  171. tooluniverse/uniprot_tool.py +155 -0
  172. tooluniverse/url_tool.py +253 -0
  173. tooluniverse/uspto_tool.py +240 -0
  174. tooluniverse/utils.py +369 -41
  175. tooluniverse/xml_tool.py +369 -0
  176. tooluniverse-1.0.1.dist-info/METADATA +387 -0
  177. tooluniverse-1.0.1.dist-info/RECORD +182 -0
  178. tooluniverse-1.0.1.dist-info/entry_points.txt +9 -0
  179. tooluniverse/generate_mcp_tools.py +0 -113
  180. tooluniverse/mcp_server.py +0 -3340
  181. tooluniverse-0.2.0.dist-info/METADATA +0 -139
  182. tooluniverse-0.2.0.dist-info/RECORD +0 -21
  183. tooluniverse-0.2.0.dist-info/entry_points.txt +0 -4
  184. {tooluniverse-0.2.0.dist-info → tooluniverse-1.0.1.dist-info}/WHEEL +0 -0
  185. {tooluniverse-0.2.0.dist-info → tooluniverse-1.0.1.dist-info}/licenses/LICENSE +0 -0
  186. {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
+ }