tooluniverse 1.0.2__py3-none-any.whl → 1.0.4__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/agentic_tool.py +262 -330
- tooluniverse/compose_scripts/output_summarizer.py +21 -15
- tooluniverse/compose_scripts/tool_metadata_generator.py +6 -0
- tooluniverse/data/agentic_tools.json +1 -1
- tooluniverse/data/output_summarization_tools.json +2 -2
- tooluniverse/execute_function.py +185 -70
- tooluniverse/llm_clients.py +369 -0
- tooluniverse/output_hook.py +92 -3
- tooluniverse/scripts/filter_tool_files.py +194 -0
- tooluniverse/smcp_server.py +19 -13
- tooluniverse/test/list_azure_openai_models.py +210 -0
- tooluniverse/test/test_agentic_tool_azure_models.py +91 -0
- tooluniverse/test/test_api_key_validation_min.py +64 -0
- tooluniverse/test/test_global_fallback.py +288 -0
- tooluniverse/test/test_hooks_direct.py +219 -0
- tooluniverse/test/test_list_built_in_tools.py +33 -0
- tooluniverse/test/test_stdio_hooks.py +285 -0
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/METADATA +7 -6
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/RECORD +23 -14
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/WHEEL +0 -0
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/entry_points.txt +0 -0
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-1.0.2.dist-info → tooluniverse-1.0.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test script to verify global fallback functionality in AgenticTool.
|
|
4
|
+
Tests the system-wide default fallback chain.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import json
|
|
9
|
+
from src.tooluniverse.agentic_tool import AgenticTool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_default_global_fallback():
|
|
13
|
+
"""Test: Tool uses default global fallback chain when no explicit fallback is configured."""
|
|
14
|
+
|
|
15
|
+
print("=== Test 1: Default Global Fallback Chain ===\n")
|
|
16
|
+
|
|
17
|
+
# Remove Gemini API key to force fallback
|
|
18
|
+
original_gemini_key = os.environ.get("GEMINI_API_KEY")
|
|
19
|
+
if "GEMINI_API_KEY" in os.environ:
|
|
20
|
+
del os.environ["GEMINI_API_KEY"]
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
# Create tool with only primary API (no explicit fallback)
|
|
24
|
+
tool = AgenticTool(
|
|
25
|
+
{
|
|
26
|
+
"name": "gemini_with_global_fallback",
|
|
27
|
+
"api_type": "GEMINI",
|
|
28
|
+
"model_id": "gemini-2.0-flash",
|
|
29
|
+
# No fallback_api_type configured - should use global fallback
|
|
30
|
+
"prompt": "You are a helpful assistant. Answer: {question}",
|
|
31
|
+
"input_arguments": ["question"],
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
print(f"Tool available: {tool.is_available()}")
|
|
36
|
+
print(f"Current API: {tool._current_api_type}")
|
|
37
|
+
print(f"Current model: {tool._current_model_id}")
|
|
38
|
+
print(f"Original config: {tool._api_type} with {tool._model_id}")
|
|
39
|
+
print(f"Global fallback enabled: {tool._use_global_fallback}")
|
|
40
|
+
print(f"Global fallback chain: {tool._global_fallback_chain}")
|
|
41
|
+
|
|
42
|
+
if tool.is_available():
|
|
43
|
+
result = tool.run({"question": "What is 2+2?"})
|
|
44
|
+
if result.get("success"):
|
|
45
|
+
print(f"✅ Tool worked with global fallback: {result['result']}")
|
|
46
|
+
else:
|
|
47
|
+
print(f"❌ Tool failed: {result['error']}")
|
|
48
|
+
else:
|
|
49
|
+
print(f"❌ Tool not available: {tool._initialization_error}")
|
|
50
|
+
|
|
51
|
+
finally:
|
|
52
|
+
# Restore Gemini key
|
|
53
|
+
if original_gemini_key:
|
|
54
|
+
os.environ["GEMINI_API_KEY"] = original_gemini_key
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_custom_global_fallback():
|
|
58
|
+
"""Test: Tool uses custom global fallback chain from environment variable."""
|
|
59
|
+
|
|
60
|
+
print("\n=== Test 2: Custom Global Fallback Chain ===\n")
|
|
61
|
+
|
|
62
|
+
# Set custom global fallback chain
|
|
63
|
+
custom_chain = [
|
|
64
|
+
{"api_type": "GEMINI", "model_id": "gemini-2.0-flash"},
|
|
65
|
+
{"api_type": "CHATGPT", "model_id": "gpt-4o-mini-0718"},
|
|
66
|
+
]
|
|
67
|
+
os.environ["AGENTIC_TOOL_FALLBACK_CHAIN"] = json.dumps(custom_chain)
|
|
68
|
+
|
|
69
|
+
# Remove Azure OpenAI API key to force fallback
|
|
70
|
+
original_azure_key = os.environ.get("AZURE_OPENAI_API_KEY")
|
|
71
|
+
if "AZURE_OPENAI_API_KEY" in os.environ:
|
|
72
|
+
del os.environ["AZURE_OPENAI_API_KEY"]
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
# Create tool with ChatGPT as primary
|
|
76
|
+
tool = AgenticTool(
|
|
77
|
+
{
|
|
78
|
+
"name": "chatgpt_with_custom_global_fallback",
|
|
79
|
+
"api_type": "CHATGPT",
|
|
80
|
+
"model_id": "gpt-4o-1120",
|
|
81
|
+
"prompt": "You are a helpful assistant. Answer: {question}",
|
|
82
|
+
"input_arguments": ["question"],
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
print(f"Tool available: {tool.is_available()}")
|
|
87
|
+
print(f"Current API: {tool._current_api_type}")
|
|
88
|
+
print(f"Current model: {tool._current_model_id}")
|
|
89
|
+
print(f"Original config: {tool._api_type} with {tool._model_id}")
|
|
90
|
+
print(f"Custom global fallback chain: {tool._global_fallback_chain}")
|
|
91
|
+
|
|
92
|
+
if tool.is_available():
|
|
93
|
+
result = tool.run({"question": "What is 2+2?"})
|
|
94
|
+
if result.get("success"):
|
|
95
|
+
print(f"✅ Tool worked with custom global fallback: {result['result']}")
|
|
96
|
+
else:
|
|
97
|
+
print(f"❌ Tool failed: {result['error']}")
|
|
98
|
+
else:
|
|
99
|
+
print(f"❌ Tool not available: {tool._initialization_error}")
|
|
100
|
+
|
|
101
|
+
finally:
|
|
102
|
+
# Restore Azure key and remove custom chain
|
|
103
|
+
if original_azure_key:
|
|
104
|
+
os.environ["AZURE_OPENAI_API_KEY"] = original_azure_key
|
|
105
|
+
if "AGENTIC_TOOL_FALLBACK_CHAIN" in os.environ:
|
|
106
|
+
del os.environ["AGENTIC_TOOL_FALLBACK_CHAIN"]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_disable_global_fallback():
|
|
110
|
+
"""Test: Tool can disable global fallback."""
|
|
111
|
+
|
|
112
|
+
print("\n=== Test 3: Disable Global Fallback ===\n")
|
|
113
|
+
|
|
114
|
+
# Remove Azure OpenAI API key
|
|
115
|
+
original_azure_key = os.environ.get("AZURE_OPENAI_API_KEY")
|
|
116
|
+
if "AZURE_OPENAI_API_KEY" in os.environ:
|
|
117
|
+
del os.environ["AZURE_OPENAI_API_KEY"]
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
# Create tool with global fallback disabled
|
|
121
|
+
tool = AgenticTool(
|
|
122
|
+
{
|
|
123
|
+
"name": "no_global_fallback",
|
|
124
|
+
"api_type": "CHATGPT",
|
|
125
|
+
"model_id": "gpt-4o-1120",
|
|
126
|
+
"use_global_fallback": False, # Disable global fallback
|
|
127
|
+
"prompt": "You are a helpful assistant. Answer: {question}",
|
|
128
|
+
"input_arguments": ["question"],
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
print(f"Tool available: {tool.is_available()}")
|
|
133
|
+
print(f"Current API: {tool._current_api_type}")
|
|
134
|
+
print(f"Current model: {tool._current_model_id}")
|
|
135
|
+
print(f"Global fallback enabled: {tool._use_global_fallback}")
|
|
136
|
+
|
|
137
|
+
if tool.is_available():
|
|
138
|
+
result = tool.run({"question": "What is 2+2?"})
|
|
139
|
+
print(f"Unexpected success: {result}")
|
|
140
|
+
else:
|
|
141
|
+
print(
|
|
142
|
+
f"✅ Tool correctly failed without global fallback: {tool._initialization_error}"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
finally:
|
|
146
|
+
# Restore Azure key
|
|
147
|
+
if original_azure_key:
|
|
148
|
+
os.environ["AZURE_OPENAI_API_KEY"] = original_azure_key
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_explicit_fallback_priority():
|
|
152
|
+
"""Test: Explicit fallback takes priority over global fallback."""
|
|
153
|
+
|
|
154
|
+
print("\n=== Test 4: Explicit Fallback Priority ===\n")
|
|
155
|
+
|
|
156
|
+
# Remove Gemini API key
|
|
157
|
+
original_gemini_key = os.environ.get("GEMINI_API_KEY")
|
|
158
|
+
if "GEMINI_API_KEY" in os.environ:
|
|
159
|
+
del os.environ["GEMINI_API_KEY"]
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
# Create tool with both explicit and global fallback
|
|
163
|
+
tool = AgenticTool(
|
|
164
|
+
{
|
|
165
|
+
"name": "explicit_vs_global_fallback",
|
|
166
|
+
"api_type": "GEMINI",
|
|
167
|
+
"model_id": "gemini-2.0-flash",
|
|
168
|
+
"fallback_api_type": "CHATGPT", # Explicit fallback
|
|
169
|
+
"fallback_model_id": "gpt-4o-mini-0718", # Different from global default
|
|
170
|
+
"prompt": "You are a helpful assistant. Answer: {question}",
|
|
171
|
+
"input_arguments": ["question"],
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
print(f"Tool available: {tool.is_available()}")
|
|
176
|
+
print(f"Current API: {tool._current_api_type}")
|
|
177
|
+
print(f"Current model: {tool._current_model_id}")
|
|
178
|
+
print(
|
|
179
|
+
f"Explicit fallback: {tool._fallback_api_type} ({tool._fallback_model_id})"
|
|
180
|
+
)
|
|
181
|
+
print(f"Global fallback chain: {tool._global_fallback_chain}")
|
|
182
|
+
|
|
183
|
+
if tool.is_available():
|
|
184
|
+
result = tool.run({"question": "What is 2+2?"})
|
|
185
|
+
if result.get("success"):
|
|
186
|
+
print(f"✅ Tool worked with explicit fallback: {result['result']}")
|
|
187
|
+
# Check if it used explicit fallback (gpt-4o-mini-0718) instead of global default (gpt-4o-1120)
|
|
188
|
+
if tool._current_model_id == "gpt-4o-mini-0718":
|
|
189
|
+
print("✅ Used explicit fallback as expected")
|
|
190
|
+
else:
|
|
191
|
+
print(
|
|
192
|
+
f"⚠️ Used {tool._current_model_id} instead of explicit fallback"
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
print(f"❌ Tool failed: {result['error']}")
|
|
196
|
+
else:
|
|
197
|
+
print(f"❌ Tool not available: {tool._initialization_error}")
|
|
198
|
+
|
|
199
|
+
finally:
|
|
200
|
+
# Restore Gemini key
|
|
201
|
+
if original_gemini_key:
|
|
202
|
+
os.environ["GEMINI_API_KEY"] = original_gemini_key
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_multiple_tools_global_fallback():
|
|
206
|
+
"""Test: Multiple tools using global fallback."""
|
|
207
|
+
|
|
208
|
+
print("\n=== Test 5: Multiple Tools with Global Fallback ===\n")
|
|
209
|
+
|
|
210
|
+
# Remove Gemini API key to force fallback for Gemini tools
|
|
211
|
+
original_gemini_key = os.environ.get("GEMINI_API_KEY")
|
|
212
|
+
if "GEMINI_API_KEY" in os.environ:
|
|
213
|
+
del os.environ["GEMINI_API_KEY"]
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
tools_config = [
|
|
217
|
+
{
|
|
218
|
+
"name": "gemini_tool_1",
|
|
219
|
+
"api_type": "GEMINI",
|
|
220
|
+
"model_id": "gemini-2.0-flash",
|
|
221
|
+
"prompt": "Gemini tool 1: {question}",
|
|
222
|
+
"input_arguments": ["question"],
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"name": "gemini_tool_2",
|
|
226
|
+
"api_type": "GEMINI",
|
|
227
|
+
"model_id": "gemini-2.0-flash",
|
|
228
|
+
"prompt": "Gemini tool 2: {question}",
|
|
229
|
+
"input_arguments": ["question"],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"name": "chatgpt_tool",
|
|
233
|
+
"api_type": "CHATGPT",
|
|
234
|
+
"model_id": "gpt-4o-1120",
|
|
235
|
+
"prompt": "ChatGPT tool: {question}",
|
|
236
|
+
"input_arguments": ["question"],
|
|
237
|
+
},
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
tools = []
|
|
241
|
+
for config in tools_config:
|
|
242
|
+
tool = AgenticTool(config)
|
|
243
|
+
tools.append(tool)
|
|
244
|
+
|
|
245
|
+
status = "✅ Available" if tool.is_available() else "❌ Unavailable"
|
|
246
|
+
current_api = (
|
|
247
|
+
f"{tool._current_api_type} ({tool._current_model_id})"
|
|
248
|
+
if tool._current_api_type
|
|
249
|
+
else "None"
|
|
250
|
+
)
|
|
251
|
+
print(f"{config['name']}: {status} - Using: {current_api}")
|
|
252
|
+
|
|
253
|
+
print()
|
|
254
|
+
|
|
255
|
+
# Test all available tools
|
|
256
|
+
available_tools = [tool for tool in tools if tool.is_available()]
|
|
257
|
+
if available_tools:
|
|
258
|
+
print("=== Testing Available Tools ===")
|
|
259
|
+
for tool in available_tools:
|
|
260
|
+
result = tool.run({"question": "Hello!"})
|
|
261
|
+
if result.get("success"):
|
|
262
|
+
print(f"✅ {tool.name}: {result['result'][:50]}...")
|
|
263
|
+
else:
|
|
264
|
+
print(f"❌ {tool.name}: {result['error']}")
|
|
265
|
+
|
|
266
|
+
finally:
|
|
267
|
+
# Restore Gemini key
|
|
268
|
+
if original_gemini_key:
|
|
269
|
+
os.environ["GEMINI_API_KEY"] = original_gemini_key
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
if __name__ == "__main__":
|
|
273
|
+
test_default_global_fallback()
|
|
274
|
+
test_custom_global_fallback()
|
|
275
|
+
test_disable_global_fallback()
|
|
276
|
+
test_explicit_fallback_priority()
|
|
277
|
+
test_multiple_tools_global_fallback()
|
|
278
|
+
|
|
279
|
+
print("\n=== Summary ===")
|
|
280
|
+
print("✅ Global fallback chain works as default")
|
|
281
|
+
print("✅ Custom global fallback chain from environment variable")
|
|
282
|
+
print("✅ Global fallback can be disabled per tool")
|
|
283
|
+
print("✅ Explicit fallback takes priority over global fallback")
|
|
284
|
+
print("✅ Multiple tools can use global fallback independently")
|
|
285
|
+
print("\n=== Configuration Options ===")
|
|
286
|
+
print("• use_global_fallback: true/false (default: true)")
|
|
287
|
+
print("• AGENTIC_TOOL_FALLBACK_CHAIN: JSON array of {api_type, model_id}")
|
|
288
|
+
print("• Explicit fallback_api_type/fallback_model_id takes priority")
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
简化的 MCP stdio 模式 hooks 测试
|
|
4
|
+
直接测试工具调用功能
|
|
5
|
+
"""
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_tool_call_directly(hooks_enabled=False):
|
|
11
|
+
"""直接测试工具调用"""
|
|
12
|
+
print(f"\n{'='*60}")
|
|
13
|
+
print(f"测试模式: {'开启 hooks' if hooks_enabled else '关闭 hooks'}")
|
|
14
|
+
print(f"{'='*60}")
|
|
15
|
+
|
|
16
|
+
# 构建命令
|
|
17
|
+
cmd = [
|
|
18
|
+
sys.executable,
|
|
19
|
+
"-c",
|
|
20
|
+
f"""
|
|
21
|
+
import sys
|
|
22
|
+
import time
|
|
23
|
+
sys.path.insert(0, 'src')
|
|
24
|
+
from tooluniverse.execute_function import ToolUniverse
|
|
25
|
+
|
|
26
|
+
# 创建 ToolUniverse 实例
|
|
27
|
+
tooluniverse = ToolUniverse()
|
|
28
|
+
|
|
29
|
+
# 配置 hooks
|
|
30
|
+
if {hooks_enabled}:
|
|
31
|
+
print("启用 hooks...")
|
|
32
|
+
tooluniverse.toggle_hooks(True)
|
|
33
|
+
else:
|
|
34
|
+
print("禁用 hooks...")
|
|
35
|
+
tooluniverse.toggle_hooks(False)
|
|
36
|
+
|
|
37
|
+
# 加载工具
|
|
38
|
+
print("加载工具...")
|
|
39
|
+
tooluniverse.load_tools()
|
|
40
|
+
|
|
41
|
+
# 测试工具调用
|
|
42
|
+
function_call = {{
|
|
43
|
+
"name": "OpenTargets_get_target_gene_ontology_by_ensemblID",
|
|
44
|
+
"arguments": {{"ensemblId": "ENSG00000012048"}}
|
|
45
|
+
}}
|
|
46
|
+
|
|
47
|
+
print("开始工具调用...")
|
|
48
|
+
start_time = time.time()
|
|
49
|
+
result = tooluniverse.run_one_function(function_call)
|
|
50
|
+
end_time = time.time()
|
|
51
|
+
|
|
52
|
+
response_time = end_time - start_time
|
|
53
|
+
result_str = str(result)
|
|
54
|
+
result_length = len(result_str)
|
|
55
|
+
|
|
56
|
+
print(f"工具调用完成")
|
|
57
|
+
print(f"响应时间: {{response_time:.2f}} 秒")
|
|
58
|
+
print(f"响应长度: {{result_length}} 字符")
|
|
59
|
+
print(f"响应类型: {{type(result)}}")
|
|
60
|
+
|
|
61
|
+
# 检查是否是摘要
|
|
62
|
+
if "summary" in result_str.lower() or "摘要" in result_str:
|
|
63
|
+
print("✅ 检测到摘要内容")
|
|
64
|
+
else:
|
|
65
|
+
print("📄 原始内容(未摘要)")
|
|
66
|
+
|
|
67
|
+
# 输出结果的前200个字符
|
|
68
|
+
print(f"结果预览: {{result_str[:200]}}...")
|
|
69
|
+
""",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
print(f"启动命令: {' '.join(cmd[:3])} ...")
|
|
73
|
+
|
|
74
|
+
# 启动进程
|
|
75
|
+
process = subprocess.Popen(
|
|
76
|
+
cmd,
|
|
77
|
+
stdin=subprocess.PIPE,
|
|
78
|
+
stdout=subprocess.PIPE,
|
|
79
|
+
stderr=subprocess.PIPE,
|
|
80
|
+
text=True,
|
|
81
|
+
bufsize=0,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# 等待执行完成
|
|
86
|
+
stdout, stderr = process.communicate(timeout=60)
|
|
87
|
+
|
|
88
|
+
print("标准输出:")
|
|
89
|
+
print(stdout)
|
|
90
|
+
|
|
91
|
+
if stderr:
|
|
92
|
+
print("标准错误:")
|
|
93
|
+
print(stderr)
|
|
94
|
+
|
|
95
|
+
# 解析结果
|
|
96
|
+
lines = stdout.split("\n")
|
|
97
|
+
response_time = None
|
|
98
|
+
result_length = None
|
|
99
|
+
is_summary = False
|
|
100
|
+
|
|
101
|
+
for line in lines:
|
|
102
|
+
if "响应时间:" in line:
|
|
103
|
+
try:
|
|
104
|
+
response_time = float(line.split(":")[1].strip().split()[0])
|
|
105
|
+
except (ValueError, IndexError):
|
|
106
|
+
pass
|
|
107
|
+
elif "响应长度:" in line:
|
|
108
|
+
try:
|
|
109
|
+
result_length = int(line.split(":")[1].strip().split()[0])
|
|
110
|
+
except (ValueError, IndexError):
|
|
111
|
+
pass
|
|
112
|
+
elif "检测到摘要内容" in line:
|
|
113
|
+
is_summary = True
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
"hooks_enabled": hooks_enabled,
|
|
117
|
+
"response_time": response_time,
|
|
118
|
+
"result_length": result_length,
|
|
119
|
+
"is_summary": is_summary,
|
|
120
|
+
"success": process.returncode == 0,
|
|
121
|
+
"stdout": stdout,
|
|
122
|
+
"stderr": stderr,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
except subprocess.TimeoutExpired:
|
|
126
|
+
print("❌ 测试超时")
|
|
127
|
+
process.kill()
|
|
128
|
+
return {
|
|
129
|
+
"hooks_enabled": hooks_enabled,
|
|
130
|
+
"response_time": None,
|
|
131
|
+
"result_length": None,
|
|
132
|
+
"is_summary": False,
|
|
133
|
+
"success": False,
|
|
134
|
+
"error": "超时",
|
|
135
|
+
}
|
|
136
|
+
except Exception as e:
|
|
137
|
+
print(f"❌ 测试失败: {e}")
|
|
138
|
+
return {
|
|
139
|
+
"hooks_enabled": hooks_enabled,
|
|
140
|
+
"response_time": None,
|
|
141
|
+
"result_length": None,
|
|
142
|
+
"is_summary": False,
|
|
143
|
+
"success": False,
|
|
144
|
+
"error": str(e),
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def main():
|
|
149
|
+
"""主函数"""
|
|
150
|
+
print("MCP stdio 模式 hooks 直接测试")
|
|
151
|
+
print("测试工具: OpenTargets_get_target_gene_ontology_by_ensemblID")
|
|
152
|
+
print("测试参数: ensemblId=ENSG00000012048")
|
|
153
|
+
|
|
154
|
+
# 测试关闭 hooks
|
|
155
|
+
result_no_hooks = test_tool_call_directly(hooks_enabled=False)
|
|
156
|
+
|
|
157
|
+
# 测试开启 hooks
|
|
158
|
+
result_with_hooks = test_tool_call_directly(hooks_enabled=True)
|
|
159
|
+
|
|
160
|
+
# 对比结果
|
|
161
|
+
print(f"\n{'='*60}")
|
|
162
|
+
print("测试结果对比")
|
|
163
|
+
print(f"{'='*60}")
|
|
164
|
+
|
|
165
|
+
print("关闭 hooks:")
|
|
166
|
+
if result_no_hooks["success"]:
|
|
167
|
+
print(
|
|
168
|
+
f" ✅ 成功 - 响应时间: {result_no_hooks['response_time']:.2f}s, 长度: {result_no_hooks['result_length']} 字符"
|
|
169
|
+
)
|
|
170
|
+
if result_no_hooks["is_summary"]:
|
|
171
|
+
print(" 📄 检测到摘要内容")
|
|
172
|
+
else:
|
|
173
|
+
print(" 📄 原始内容(未摘要)")
|
|
174
|
+
else:
|
|
175
|
+
print(f" ❌ 失败 - {result_no_hooks.get('error', '未知错误')}")
|
|
176
|
+
|
|
177
|
+
print("开启 hooks:")
|
|
178
|
+
if result_with_hooks["success"]:
|
|
179
|
+
print(
|
|
180
|
+
f" ✅ 成功 - 响应时间: {result_with_hooks['response_time']:.2f}s, 长度: {result_with_hooks['result_length']} 字符"
|
|
181
|
+
)
|
|
182
|
+
if result_with_hooks["is_summary"]:
|
|
183
|
+
print(" ✅ 检测到摘要内容")
|
|
184
|
+
else:
|
|
185
|
+
print(" 📄 原始内容(未摘要)")
|
|
186
|
+
else:
|
|
187
|
+
print(f" ❌ 失败 - {result_with_hooks.get('error', '未知错误')}")
|
|
188
|
+
|
|
189
|
+
# 性能对比
|
|
190
|
+
if result_no_hooks["success"] and result_with_hooks["success"]:
|
|
191
|
+
time_diff = (
|
|
192
|
+
result_with_hooks["response_time"] - result_no_hooks["response_time"]
|
|
193
|
+
)
|
|
194
|
+
length_diff = (
|
|
195
|
+
result_with_hooks["result_length"] - result_no_hooks["result_length"]
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
print("\n性能对比:")
|
|
199
|
+
print(
|
|
200
|
+
f" 时间差异: {time_diff:+.2f}s ({'hooks 更慢' if time_diff > 0 else 'hooks 更快'})"
|
|
201
|
+
)
|
|
202
|
+
print(
|
|
203
|
+
f" 长度差异: {length_diff:+d} 字符 ({'hooks 更长' if length_diff > 0 else 'hooks 更短'})"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
if abs(time_diff) < 5.0:
|
|
207
|
+
print(" ✅ 时间差异在可接受范围内")
|
|
208
|
+
else:
|
|
209
|
+
print(" ⚠️ 时间差异较大,需要进一步优化")
|
|
210
|
+
|
|
211
|
+
# 检查 hooks 是否生效
|
|
212
|
+
if result_with_hooks["is_summary"] and not result_no_hooks["is_summary"]:
|
|
213
|
+
print(" ✅ Hooks 功能正常工作")
|
|
214
|
+
elif result_with_hooks["is_summary"] == result_no_hooks["is_summary"]:
|
|
215
|
+
print(" ⚠️ Hooks 功能可能未生效")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
if __name__ == "__main__":
|
|
219
|
+
main()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Basic test for list_built_in_tools including scan_all option.
|
|
4
|
+
Run directly: python tests/test_list_built_in_tools.py
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from tooluniverse import ToolUniverse # noqa: E402
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
tu = ToolUniverse()
|
|
12
|
+
|
|
13
|
+
# Use predefined files (original behavior)
|
|
14
|
+
tool_names = tu.list_built_in_tools(mode="list_name", scan_all=False)
|
|
15
|
+
print(f"predefined tool names: {len(tool_names)}")
|
|
16
|
+
|
|
17
|
+
# Scan all JSON files
|
|
18
|
+
all_tool_names = tu.list_built_in_tools(mode="list_name", scan_all=True)
|
|
19
|
+
print(f"all tool names (scan_all): {len(all_tool_names)}")
|
|
20
|
+
|
|
21
|
+
# Get all tool specifications
|
|
22
|
+
all_tool_specs = tu.list_built_in_tools(mode="list_spec", scan_all=True)
|
|
23
|
+
print(f"all tool specs (scan_all): {len(all_tool_specs)}")
|
|
24
|
+
|
|
25
|
+
# Organize all tools by type
|
|
26
|
+
type_stats = tu.list_built_in_tools(mode="type", scan_all=True)
|
|
27
|
+
print(
|
|
28
|
+
f"type stats -> total_categories: {type_stats['total_categories']}, total_tools: {type_stats['total_tools']}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
main()
|