@lutery/vision-mcp 1.0.0
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.
- package/README.md +428 -0
- package/dist/adapters/base-adapter.d.ts +69 -0
- package/dist/adapters/base-adapter.d.ts.map +1 -0
- package/dist/adapters/base-adapter.js +143 -0
- package/dist/adapters/base-adapter.js.map +1 -0
- package/dist/adapters/claude-adapter.d.ts +38 -0
- package/dist/adapters/claude-adapter.d.ts.map +1 -0
- package/dist/adapters/claude-adapter.js +251 -0
- package/dist/adapters/claude-adapter.js.map +1 -0
- package/dist/adapters/glm-adapter.d.ts +15 -0
- package/dist/adapters/glm-adapter.d.ts.map +1 -0
- package/dist/adapters/glm-adapter.js +131 -0
- package/dist/adapters/glm-adapter.js.map +1 -0
- package/dist/adapters/modelscope-adapter.d.ts +20 -0
- package/dist/adapters/modelscope-adapter.d.ts.map +1 -0
- package/dist/adapters/modelscope-adapter.js +142 -0
- package/dist/adapters/modelscope-adapter.js.map +1 -0
- package/dist/adapters/openai-adapter.d.ts +20 -0
- package/dist/adapters/openai-adapter.d.ts.map +1 -0
- package/dist/adapters/openai-adapter.js +194 -0
- package/dist/adapters/openai-adapter.js.map +1 -0
- package/dist/adapters/siliconflow-adapter.d.ts +21 -0
- package/dist/adapters/siliconflow-adapter.d.ts.map +1 -0
- package/dist/adapters/siliconflow-adapter.js +145 -0
- package/dist/adapters/siliconflow-adapter.js.map +1 -0
- package/dist/config/model-config.d.ts +39 -0
- package/dist/config/model-config.d.ts.map +1 -0
- package/dist/config/model-config.js +115 -0
- package/dist/config/model-config.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +186 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/system.d.ts +75 -0
- package/dist/prompts/system.d.ts.map +1 -0
- package/dist/prompts/system.js +272 -0
- package/dist/prompts/system.js.map +1 -0
- package/dist/providers/provider-registry.d.ts +58 -0
- package/dist/providers/provider-registry.d.ts.map +1 -0
- package/dist/providers/provider-registry.js +173 -0
- package/dist/providers/provider-registry.js.map +1 -0
- package/dist/src/adapters/base-adapter.d.ts +59 -0
- package/dist/src/adapters/base-adapter.d.ts.map +1 -0
- package/dist/src/adapters/base-adapter.js +83 -0
- package/dist/src/adapters/base-adapter.js.map +1 -0
- package/dist/src/adapters/glm-adapter.d.ts +15 -0
- package/dist/src/adapters/glm-adapter.d.ts.map +1 -0
- package/dist/src/adapters/glm-adapter.js +116 -0
- package/dist/src/adapters/glm-adapter.js.map +1 -0
- package/dist/src/adapters/siliconflow-adapter.d.ts +21 -0
- package/dist/src/adapters/siliconflow-adapter.d.ts.map +1 -0
- package/dist/src/adapters/siliconflow-adapter.js +130 -0
- package/dist/src/adapters/siliconflow-adapter.js.map +1 -0
- package/dist/src/config/model-config.d.ts +40 -0
- package/dist/src/config/model-config.d.ts.map +1 -0
- package/dist/src/config/model-config.js +126 -0
- package/dist/src/config/model-config.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +188 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/prompts/system.d.ts +75 -0
- package/dist/src/prompts/system.d.ts.map +1 -0
- package/dist/src/prompts/system.js +272 -0
- package/dist/src/prompts/system.js.map +1 -0
- package/dist/src/tools/vision-tool.d.ts +91 -0
- package/dist/src/tools/vision-tool.d.ts.map +1 -0
- package/dist/src/tools/vision-tool.js +171 -0
- package/dist/src/tools/vision-tool.js.map +1 -0
- package/dist/src/utils/errors.d.ts +65 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +146 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/image-input.d.ts +45 -0
- package/dist/src/utils/image-input.d.ts.map +1 -0
- package/dist/src/utils/image-input.js +226 -0
- package/dist/src/utils/image-input.js.map +1 -0
- package/dist/src/utils/logger.d.ts +63 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +157 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/test/integration.test.d.ts +10 -0
- package/dist/test/integration.test.d.ts.map +1 -0
- package/dist/test/integration.test.js +270 -0
- package/dist/test/integration.test.js.map +1 -0
- package/dist/test/test-utils.d.ts +45 -0
- package/dist/test/test-utils.d.ts.map +1 -0
- package/dist/test/test-utils.js +107 -0
- package/dist/test/test-utils.js.map +1 -0
- package/dist/test/vision-tool.test.d.ts +9 -0
- package/dist/test/vision-tool.test.d.ts.map +1 -0
- package/dist/test/vision-tool.test.js +167 -0
- package/dist/test/vision-tool.test.js.map +1 -0
- package/dist/tools/vision-tool.d.ts +91 -0
- package/dist/tools/vision-tool.d.ts.map +1 -0
- package/dist/tools/vision-tool.js +167 -0
- package/dist/tools/vision-tool.js.map +1 -0
- package/dist/utils/data-url-parser.d.ts +27 -0
- package/dist/utils/data-url-parser.d.ts.map +1 -0
- package/dist/utils/data-url-parser.js +53 -0
- package/dist/utils/data-url-parser.js.map +1 -0
- package/dist/utils/errors.d.ts +65 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +146 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/image-input.d.ts +45 -0
- package/dist/utils/image-input.d.ts.map +1 -0
- package/dist/utils/image-input.js +238 -0
- package/dist/utils/image-input.js.map +1 -0
- package/dist/utils/logger.d.ts +63 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +157 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/thinking-extractors.d.ts +34 -0
- package/dist/utils/thinking-extractors.d.ts.map +1 -0
- package/dist/utils/thinking-extractors.js +83 -0
- package/dist/utils/thinking-extractors.js.map +1 -0
- package/dist/utils/thinking-filter.d.ts +32 -0
- package/dist/utils/thinking-filter.d.ts.map +1 -0
- package/dist/utils/thinking-filter.js +147 -0
- package/dist/utils/thinking-filter.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests for Vision MCP
|
|
3
|
+
*
|
|
4
|
+
* @description Comprehensive integration tests using real API calls
|
|
5
|
+
* Tests both GLM-4.6V and SiliconFlow models
|
|
6
|
+
* Verifies timeout fix and all functionality
|
|
7
|
+
*/
|
|
8
|
+
declare function main(): Promise<void>;
|
|
9
|
+
export { main as runIntegrationTests };
|
|
10
|
+
//# sourceMappingURL=integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../test/integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqQH,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAyCnC;AAUD,OAAO,EAAE,IAAI,IAAI,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests for Vision MCP
|
|
3
|
+
*
|
|
4
|
+
* @description Comprehensive integration tests using real API calls
|
|
5
|
+
* Tests both GLM-4.6V and SiliconFlow models
|
|
6
|
+
* Verifies timeout fix and all functionality
|
|
7
|
+
*/
|
|
8
|
+
import { createMCPClient, runTest } from './test-utils.js';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs/promises';
|
|
11
|
+
// Load API keys from .env file if present
|
|
12
|
+
import { config } from 'dotenv';
|
|
13
|
+
config();
|
|
14
|
+
const TEST_IMAGE_PATH = path.join(process.cwd(), 'test', 'image.png');
|
|
15
|
+
const TEST_PROMPT = '请识别这张图中热搜新闻有哪些。';
|
|
16
|
+
const MODEL_CONFIGS = [
|
|
17
|
+
{
|
|
18
|
+
name: 'GLM-4.6V',
|
|
19
|
+
envConfig: {
|
|
20
|
+
VISION_MODEL_TYPE: 'glm-4.6v',
|
|
21
|
+
VISION_MODEL_NAME: 'glm-4.6v',
|
|
22
|
+
VISION_API_BASE_URL: 'https://open.bigmodel.cn/api/paas/v4',
|
|
23
|
+
VISION_API_KEY: '4fb93939e52449de942a1fafd1553e79.xXnQg0wDcsoDfGwI',
|
|
24
|
+
VISION_API_TIMEOUT: '60000',
|
|
25
|
+
LOG_LEVEL: 'info'
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'SiliconFlow',
|
|
30
|
+
envConfig: {
|
|
31
|
+
VISION_MODEL_TYPE: 'siliconflow',
|
|
32
|
+
VISION_MODEL_NAME: 'Qwen/Qwen2-VL-72B-Instruct',
|
|
33
|
+
VISION_API_BASE_URL: 'https://api.siliconflow.cn/v1',
|
|
34
|
+
VISION_API_KEY: 'sk-nqghsderykvzxdtmgpcocpndmtqkomxepdljqriyakcuehkc',
|
|
35
|
+
VISION_API_TIMEOUT: '60000',
|
|
36
|
+
LOG_LEVEL: 'info'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
async function verifyTestImageExists() {
|
|
41
|
+
try {
|
|
42
|
+
await fs.access(TEST_IMAGE_PATH);
|
|
43
|
+
const stats = await fs.stat(TEST_IMAGE_PATH);
|
|
44
|
+
console.log(`✓ Test image found: ${TEST_IMAGE_PATH} (${Math.round(stats.size / 1024)}KB)`);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new Error(`Test image not found at ${TEST_IMAGE_PATH}. Please ensure test image exists.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function testAnalyzeImageWithLocalPath(client) {
|
|
51
|
+
return runTest('Analyze image with local file path', async () => {
|
|
52
|
+
const result = await client.callTool('analyze_image', {
|
|
53
|
+
image: TEST_IMAGE_PATH,
|
|
54
|
+
prompt: TEST_PROMPT,
|
|
55
|
+
output_format: 'text'
|
|
56
|
+
});
|
|
57
|
+
if (result.isError) {
|
|
58
|
+
throw new Error(`Tool returned error: ${JSON.stringify(result.content)}`);
|
|
59
|
+
}
|
|
60
|
+
const content = result.content[0]?.text;
|
|
61
|
+
if (!content || content.length === 0) {
|
|
62
|
+
throw new Error('Empty response from model');
|
|
63
|
+
}
|
|
64
|
+
// Verify we got a meaningful response
|
|
65
|
+
if (content.length < 50) {
|
|
66
|
+
throw new Error(`Response too short, likely an error: ${content}`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
contentLength: content.length,
|
|
70
|
+
preview: content.substring(0, 200) + '...'
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function testAnalyzeImageWithJsonOutput(client) {
|
|
75
|
+
return runTest('Analyze image with JSON output format', async () => {
|
|
76
|
+
const result = await client.callTool('analyze_image', {
|
|
77
|
+
image: TEST_IMAGE_PATH,
|
|
78
|
+
prompt: `${TEST_PROMPT} Please structure your response as JSON with a "hot_news" array containing title and summary for each item.`,
|
|
79
|
+
output_format: 'json'
|
|
80
|
+
});
|
|
81
|
+
if (result.isError) {
|
|
82
|
+
throw new Error(`Tool returned error: ${JSON.stringify(result.content)}`);
|
|
83
|
+
}
|
|
84
|
+
const content = result.content[0]?.text;
|
|
85
|
+
if (!content || content.length === 0) {
|
|
86
|
+
throw new Error('Empty response from model');
|
|
87
|
+
}
|
|
88
|
+
// Verify JSON format (but don't validate structure per D-005)
|
|
89
|
+
try {
|
|
90
|
+
JSON.parse(content);
|
|
91
|
+
return {
|
|
92
|
+
isValidJson: true,
|
|
93
|
+
contentLength: content.length
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
// Per D-005, we don't enforce JSON schema, just verify it's parsable
|
|
98
|
+
return {
|
|
99
|
+
isValidJson: false,
|
|
100
|
+
contentLength: content.length,
|
|
101
|
+
note: 'Model returned non-JSON content (acceptable per D-005)'
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function testListTemplates(client) {
|
|
107
|
+
return runTest('List available templates', async () => {
|
|
108
|
+
const result = await client.callTool('list_templates', {});
|
|
109
|
+
if (result.isError) {
|
|
110
|
+
throw new Error(`Tool returned error: ${JSON.stringify(result.content)}`);
|
|
111
|
+
}
|
|
112
|
+
const content = result.content[0]?.text;
|
|
113
|
+
if (!content) {
|
|
114
|
+
throw new Error('Empty response');
|
|
115
|
+
}
|
|
116
|
+
const templates = JSON.parse(content);
|
|
117
|
+
if (!templates || typeof templates !== 'object') {
|
|
118
|
+
throw new Error('Invalid template format');
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
templateCount: Object.keys(templates).length,
|
|
122
|
+
templates: Object.keys(templates)
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
async function testGetConfig(client) {
|
|
127
|
+
return runTest('Get model configuration', async () => {
|
|
128
|
+
const result = await client.callTool('get_config', {});
|
|
129
|
+
if (result.isError) {
|
|
130
|
+
throw new Error(`Tool returned error: ${JSON.stringify(result.content)}`);
|
|
131
|
+
}
|
|
132
|
+
const content = result.content[0]?.text;
|
|
133
|
+
if (!content) {
|
|
134
|
+
throw new Error('Empty response');
|
|
135
|
+
}
|
|
136
|
+
const config = JSON.parse(content);
|
|
137
|
+
// Verify required config fields
|
|
138
|
+
const requiredFields = ['type', 'name', 'baseUrl', 'apiKey'];
|
|
139
|
+
for (const field of requiredFields) {
|
|
140
|
+
if (!config[field]) {
|
|
141
|
+
throw new Error(`Missing required config field: ${field}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Verify API key is masked (not showing full key)
|
|
145
|
+
if (config.apiKey !== '***...***' && !config.apiKey.includes('***')) {
|
|
146
|
+
throw new Error('API key should be masked in response');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
modelType: config.type,
|
|
150
|
+
modelName: config.name,
|
|
151
|
+
timeout: config.timeout,
|
|
152
|
+
maxRetries: config.maxRetries
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async function timeoutTest(client) {
|
|
157
|
+
return runTest('Timeout operation verification', async () => {
|
|
158
|
+
// This test verifies that the timeout fix is working
|
|
159
|
+
// We make a normal request and ensure it doesn't hang
|
|
160
|
+
const startTime = Date.now();
|
|
161
|
+
const result = await client.callTool('analyze_image', {
|
|
162
|
+
image: TEST_IMAGE_PATH,
|
|
163
|
+
prompt: 'Describe this image briefly.',
|
|
164
|
+
output_format: 'text'
|
|
165
|
+
});
|
|
166
|
+
const duration = Date.now() - startTime;
|
|
167
|
+
if (result.isError) {
|
|
168
|
+
throw new Error(`Tool returned error: ${JSON.stringify(result.content)}`);
|
|
169
|
+
}
|
|
170
|
+
// Verify we got a response within reasonable time (not hanging)
|
|
171
|
+
if (duration > 120000) {
|
|
172
|
+
throw new Error(`Request took too long: ${duration}ms (possible timeout issue)`);
|
|
173
|
+
}
|
|
174
|
+
if (duration < 1000) {
|
|
175
|
+
throw new Error(`Request completed too quickly: ${duration}ms (suspicious)`);
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
duration,
|
|
179
|
+
status: 'completed'
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async function testModel(testConfig) {
|
|
184
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
185
|
+
console.log(`Testing Model: ${testConfig.name}`);
|
|
186
|
+
console.log('='.repeat(60));
|
|
187
|
+
let client;
|
|
188
|
+
try {
|
|
189
|
+
console.log(`Creating MCP client...`);
|
|
190
|
+
client = await createMCPClient(testConfig.envConfig);
|
|
191
|
+
console.log(`✓ Client created successfully`);
|
|
192
|
+
const tests = [
|
|
193
|
+
() => testGetConfig(client),
|
|
194
|
+
() => testListTemplates(client),
|
|
195
|
+
() => testAnalyzeImageWithLocalPath(client),
|
|
196
|
+
() => testAnalyzeImageWithJsonOutput(client),
|
|
197
|
+
() => timeoutTest(client)
|
|
198
|
+
];
|
|
199
|
+
for (const test of tests) {
|
|
200
|
+
const result = await test();
|
|
201
|
+
if (!result.passed) {
|
|
202
|
+
console.log(`\n❌ Test suite failed: ${result.name}`);
|
|
203
|
+
console.log(`Error: ${result.error}`);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
console.log(`\n✓ All tests passed for ${testConfig.name}`);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.log(`\n❌ Failed to initialize client for ${testConfig.name}`);
|
|
212
|
+
console.log(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
if (client) {
|
|
217
|
+
try {
|
|
218
|
+
await client.close();
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.warn(`Warning: Failed to close client: ${error}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async function main() {
|
|
227
|
+
console.log('Vision MCP Integration Tests');
|
|
228
|
+
console.log('============================\n');
|
|
229
|
+
console.log('Preparing tests...');
|
|
230
|
+
// Verify test image exists
|
|
231
|
+
try {
|
|
232
|
+
await verifyTestImageExists();
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.error(`\n❌ Setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
const results = [];
|
|
239
|
+
// Test each model
|
|
240
|
+
for (const modelConfig of MODEL_CONFIGS) {
|
|
241
|
+
const passed = await testModel(modelConfig);
|
|
242
|
+
results.push({ model: modelConfig.name, passed });
|
|
243
|
+
}
|
|
244
|
+
// Summary
|
|
245
|
+
console.log('\n' + '='.repeat(60));
|
|
246
|
+
console.log('Test Summary');
|
|
247
|
+
console.log('='.repeat(60));
|
|
248
|
+
results.forEach(({ model, passed }) => {
|
|
249
|
+
const status = passed ? '✅ PASSED' : '❌ FAILED';
|
|
250
|
+
console.log(`${model}: ${status}`);
|
|
251
|
+
});
|
|
252
|
+
const allPassed = results.every(r => r.passed);
|
|
253
|
+
if (allPassed) {
|
|
254
|
+
console.log('\n🎉 All model tests passed!');
|
|
255
|
+
process.exit(0);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
console.log('\n💥 Some tests failed. Review the output above.');
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Run tests if this file is executed directly
|
|
263
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
264
|
+
main().catch(error => {
|
|
265
|
+
console.error('Fatal error:', error);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
export { main as runIntegrationTests };
|
|
270
|
+
//# sourceMappingURL=integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../test/integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,eAAe,EAAE,OAAO,EAAc,MAAM,iBAAiB,CAAC;AACtF,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,aAAa,CAAC;AAE7B,0CAA0C;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,MAAM,EAAE,CAAC;AAET,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;AACtE,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAOtC,MAAM,aAAa,GAAsB;IACvC;QACE,IAAI,EAAE,UAAU;QAChB,SAAS,EAAE;YACT,iBAAiB,EAAE,UAAU;YAC7B,iBAAiB,EAAE,UAAU;YAC7B,mBAAmB,EAAE,sCAAsC;YAC3D,cAAc,EAAE,mDAAmD;YACnE,kBAAkB,EAAE,OAAO;YAC3B,SAAS,EAAE,MAAM;SAClB;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,SAAS,EAAE;YACT,iBAAiB,EAAE,aAAa;YAChC,iBAAiB,EAAE,4BAA4B;YAC/C,mBAAmB,EAAE,+BAA+B;YACpD,cAAc,EAAE,qDAAqD;YACrE,kBAAkB,EAAE,OAAO;YAC3B,SAAS,EAAE,MAAM;SAClB;KACF;CACF,CAAC;AAEF,KAAK,UAAU,qBAAqB;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,uBAAuB,eAAe,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,2BAA2B,eAAe,oCAAoC,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,MAAW;IACtD,OAAO,OAAO,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;YACpD,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,WAAW;YACnB,aAAa,EAAE,MAAM;SACtB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACxC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,sCAAsC;QACtC,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,OAAO;YACL,aAAa,EAAE,OAAO,CAAC,MAAM;YAC7B,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;SAC3C,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,MAAW;IACvD,OAAO,OAAO,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;YACpD,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,GAAG,WAAW,6GAA6G;YACnI,aAAa,EAAE,MAAM;SACtB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACxC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,8DAA8D;QAC9D,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,aAAa,EAAE,OAAO,CAAC,MAAM;aAC9B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qEAAqE;YACrE,OAAO;gBACL,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,OAAO,CAAC,MAAM;gBAC7B,IAAI,EAAE,wDAAwD;aAC/D,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,MAAW;IAC1C,OAAO,OAAO,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,OAAO;YACL,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;YAC5C,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAClC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAW;IACtC,OAAO,OAAO,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAEvD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEnC,gCAAgC;QAChC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC7D,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,IAAI;YACtB,SAAS,EAAE,MAAM,CAAC,IAAI;YACtB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAW;IACpC,OAAO,OAAO,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC1D,qDAAqD;QACrD,sDAAsD;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;YACpD,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,8BAA8B;YACtC,aAAa,EAAE,MAAM;SACtB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAExC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,gEAAgE;QAChE,IAAI,QAAQ,GAAG,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,6BAA6B,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,QAAQ,GAAG,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,iBAAiB,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,WAAW;SACpB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,UAA2B;IAClD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,kBAAkB,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,IAAI,MAAW,CAAC;IAEhB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAE7C,MAAM,KAAK,GAAG;YACZ,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC;YAC3B,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;YAC/B,GAAG,EAAE,CAAC,6BAA6B,CAAC,MAAM,CAAC;YAC3C,GAAG,EAAE,CAAC,8BAA8B,CAAC,MAAM,CAAC;YAC5C,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;SAC1B,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;YAE5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrD,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;gBACtC,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IAEd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,uCAAuC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChF,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAElC,2BAA2B;IAC3B,IAAI,CAAC;QACH,MAAM,qBAAqB,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAyC,EAAE,CAAC;IAEzD,kBAAkB;IAClB,KAAK,MAAM,WAAW,IAAI,aAAa,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE/C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,8CAA8C;AAC9C,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpD,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,IAAI,IAAI,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Utilities
|
|
3
|
+
*
|
|
4
|
+
* @description Common utility functions for testing Vision MCP
|
|
5
|
+
*/
|
|
6
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
export interface TestEnvConfig {
|
|
8
|
+
VISION_MODEL_TYPE: string;
|
|
9
|
+
VISION_MODEL_NAME: string;
|
|
10
|
+
VISION_API_BASE_URL: string;
|
|
11
|
+
VISION_API_KEY: string;
|
|
12
|
+
VISION_API_TIMEOUT?: string;
|
|
13
|
+
LOG_LEVEL?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create MCP client connected to the Vision MCP server
|
|
17
|
+
*/
|
|
18
|
+
export declare function createMCPClient(envConfig?: TestEnvConfig): Promise<Client>;
|
|
19
|
+
/**
|
|
20
|
+
* Test result interface
|
|
21
|
+
*/
|
|
22
|
+
export interface TestResult {
|
|
23
|
+
name: string;
|
|
24
|
+
passed: boolean;
|
|
25
|
+
error?: string;
|
|
26
|
+
duration: number;
|
|
27
|
+
details?: any;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run a test and capture results
|
|
31
|
+
*/
|
|
32
|
+
export declare function runTest(name: string, testFn: () => Promise<any>): Promise<TestResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Run multiple tests and print results
|
|
35
|
+
*/
|
|
36
|
+
export declare function runTestSuite(suiteName: string, tests: Array<() => Promise<TestResult>>): Promise<{
|
|
37
|
+
passed: number;
|
|
38
|
+
failed: number;
|
|
39
|
+
results: TestResult[];
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Convert image to base64 data URL
|
|
43
|
+
*/
|
|
44
|
+
export declare function imageToDataUrl(imagePath: string): Promise<string>;
|
|
45
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../test/test-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,MAAM,WAAW,aAAa;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBhF;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACzB,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CA8BpE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBvE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Utilities
|
|
3
|
+
*
|
|
4
|
+
* @description Common utility functions for testing Vision MCP
|
|
5
|
+
*/
|
|
6
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Create MCP client connected to the Vision MCP server
|
|
11
|
+
*/
|
|
12
|
+
export async function createMCPClient(envConfig) {
|
|
13
|
+
const serverPath = path.join(process.cwd(), 'dist', 'index.js');
|
|
14
|
+
// Set environment variables if provided
|
|
15
|
+
const env = { ...process.env };
|
|
16
|
+
if (envConfig) {
|
|
17
|
+
Object.assign(env, envConfig);
|
|
18
|
+
}
|
|
19
|
+
const transport = new StdioClientTransport(serverPath, [], { env });
|
|
20
|
+
const client = new Client({
|
|
21
|
+
name: 'vision-mcp-test',
|
|
22
|
+
version: '1.0.0'
|
|
23
|
+
}, {
|
|
24
|
+
capabilities: {}
|
|
25
|
+
});
|
|
26
|
+
await client.connect(transport);
|
|
27
|
+
return client;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run a test and capture results
|
|
31
|
+
*/
|
|
32
|
+
export async function runTest(name, testFn) {
|
|
33
|
+
const startTime = Date.now();
|
|
34
|
+
try {
|
|
35
|
+
const result = await testFn();
|
|
36
|
+
return {
|
|
37
|
+
name,
|
|
38
|
+
passed: true,
|
|
39
|
+
duration: Date.now() - startTime,
|
|
40
|
+
details: result
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return {
|
|
45
|
+
name,
|
|
46
|
+
passed: false,
|
|
47
|
+
error: error instanceof Error ? error.message : String(error),
|
|
48
|
+
duration: Date.now() - startTime
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Run multiple tests and print results
|
|
54
|
+
*/
|
|
55
|
+
export async function runTestSuite(suiteName, tests) {
|
|
56
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
57
|
+
console.log(`Running: ${suiteName}`);
|
|
58
|
+
console.log('='.repeat(60));
|
|
59
|
+
const results = [];
|
|
60
|
+
for (const test of tests) {
|
|
61
|
+
const result = await test();
|
|
62
|
+
results.push(result);
|
|
63
|
+
if (result.passed) {
|
|
64
|
+
console.log(`✅ ${result.name} (${result.duration}ms)`);
|
|
65
|
+
if (result.details) {
|
|
66
|
+
console.log(` Details: ${JSON.stringify(result.details).substring(0, 200)}...`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log(`❌ ${result.name} (${result.duration}ms)`);
|
|
71
|
+
console.log(` Error: ${result.error}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const passed = results.filter(r => r.passed).length;
|
|
75
|
+
const failed = results.filter(r => !r.passed).length;
|
|
76
|
+
console.log('='.repeat(60));
|
|
77
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
78
|
+
console.log('='.repeat(60));
|
|
79
|
+
return { passed, failed, results };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Convert image to base64 data URL
|
|
83
|
+
*/
|
|
84
|
+
export async function imageToDataUrl(imagePath) {
|
|
85
|
+
const fs = await import('fs/promises');
|
|
86
|
+
const path = await import('path');
|
|
87
|
+
const imageBuffer = await fs.readFile(imagePath);
|
|
88
|
+
const ext = path.extname(imagePath).toLowerCase();
|
|
89
|
+
let mimeType;
|
|
90
|
+
switch (ext) {
|
|
91
|
+
case '.jpg':
|
|
92
|
+
case '.jpeg':
|
|
93
|
+
mimeType = 'image/jpeg';
|
|
94
|
+
break;
|
|
95
|
+
case '.png':
|
|
96
|
+
mimeType = 'image/png';
|
|
97
|
+
break;
|
|
98
|
+
case '.webp':
|
|
99
|
+
mimeType = 'image/webp';
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`Unsupported image format: ${ext}`);
|
|
103
|
+
}
|
|
104
|
+
const base64Data = imageBuffer.toString('base64');
|
|
105
|
+
return `data:${mimeType};base64,${base64Data}`;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../test/test-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct Vision Tool Tests
|
|
3
|
+
*
|
|
4
|
+
* @description Direct tests of the VisionTool class without MCP client
|
|
5
|
+
* This provides simpler testing without STDIO protocol overhead
|
|
6
|
+
*/
|
|
7
|
+
declare function main(): Promise<void>;
|
|
8
|
+
export { main as runDirectTests };
|
|
9
|
+
//# sourceMappingURL=vision-tool.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-tool.test.d.ts","sourceRoot":"","sources":["../../test/vision-tool.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6JH,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAgCnC;AAUD,OAAO,EAAE,IAAI,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct Vision Tool Tests
|
|
3
|
+
*
|
|
4
|
+
* @description Direct tests of the VisionTool class without MCP client
|
|
5
|
+
* This provides simpler testing without STDIO protocol overhead
|
|
6
|
+
*/
|
|
7
|
+
import { VisionTool } from '../src/tools/vision-tool.js';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
const TEST_IMAGE_PATH = path.join(process.cwd(), 'test', 'image.png');
|
|
10
|
+
const TEST_PROMPT = '请识别这张图中热搜新闻有哪些。';
|
|
11
|
+
// Load API keys from environment
|
|
12
|
+
const SILICONFLOW_CONFIG = {
|
|
13
|
+
type: 'siliconflow',
|
|
14
|
+
name: 'Qwen/Qwen2-VL-72B-Instruct',
|
|
15
|
+
baseUrl: 'https://api.siliconflow.cn/v1',
|
|
16
|
+
apiKey: 'sk-nqghsderykvzxdtmgpcocpndmtqkomxepdljqriyakcuehkc',
|
|
17
|
+
timeout: 60000,
|
|
18
|
+
maxRetries: 2
|
|
19
|
+
};
|
|
20
|
+
const GLM_CONFIG = {
|
|
21
|
+
type: 'glm-4.6v',
|
|
22
|
+
name: 'glm-4.6v',
|
|
23
|
+
baseUrl: 'https://open.bigmodel.cn/api/paas/v4',
|
|
24
|
+
apiKey: '4fb93939e52449de942a1fafd1553e79.xXnQg0wDcsoDfGwI',
|
|
25
|
+
timeout: 60000,
|
|
26
|
+
maxRetries: 2
|
|
27
|
+
};
|
|
28
|
+
function runTest(name, testFn) {
|
|
29
|
+
const startTime = Date.now();
|
|
30
|
+
return testFn()
|
|
31
|
+
.then(result => ({
|
|
32
|
+
name,
|
|
33
|
+
passed: true,
|
|
34
|
+
duration: Date.now() - startTime,
|
|
35
|
+
details: result
|
|
36
|
+
}))
|
|
37
|
+
.catch(error => ({
|
|
38
|
+
name,
|
|
39
|
+
passed: false,
|
|
40
|
+
error: error instanceof Error ? error.message : String(error),
|
|
41
|
+
duration: Date.now() - startTime
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
async function testVisionToolWithModel(config, modelName) {
|
|
45
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
46
|
+
console.log(`Testing Vision Tool with ${modelName}`);
|
|
47
|
+
console.log('='.repeat(60));
|
|
48
|
+
const visionTool = new VisionTool(config);
|
|
49
|
+
// Test 1: Basic image analysis
|
|
50
|
+
console.log('\n1. Testing basic image analysis...');
|
|
51
|
+
const result1 = await runTest('Analyze image with text output', async () => {
|
|
52
|
+
const result = await visionTool.analyze({
|
|
53
|
+
image: TEST_IMAGE_PATH,
|
|
54
|
+
prompt: TEST_PROMPT,
|
|
55
|
+
output_format: 'text'
|
|
56
|
+
});
|
|
57
|
+
if (!result.content || result.content.length === 0) {
|
|
58
|
+
throw new Error('Empty response');
|
|
59
|
+
}
|
|
60
|
+
console.log(`Response received (${result.content.length} characters)`);
|
|
61
|
+
console.log(`Preview: ${result.content.substring(0, 200)}...`);
|
|
62
|
+
return {
|
|
63
|
+
contentLength: result.content.length,
|
|
64
|
+
processingTime: result.metadata.processingTimeMs,
|
|
65
|
+
model: result.metadata.modelName
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
console.log(result1.passed ? `✅ ${result1.name}` : `❌ ${result1.name}`);
|
|
69
|
+
if (!result1.passed) {
|
|
70
|
+
console.log(` Error: ${result1.error}`);
|
|
71
|
+
throw new Error(`Test failed: ${result1.name}`);
|
|
72
|
+
}
|
|
73
|
+
// Test 2: JSON output format
|
|
74
|
+
console.log('\n2. Testing JSON output format...');
|
|
75
|
+
const result2 = await runTest('Analyze image with JSON output', async () => {
|
|
76
|
+
const result = await visionTool.analyze({
|
|
77
|
+
image: TEST_IMAGE_PATH,
|
|
78
|
+
prompt: `${TEST_PROMPT} Please structure your response as JSON.`,
|
|
79
|
+
output_format: 'json'
|
|
80
|
+
});
|
|
81
|
+
if (!result.content || result.content.length === 0) {
|
|
82
|
+
throw new Error('Empty response');
|
|
83
|
+
}
|
|
84
|
+
// Verify JSON is parsable (per D-005, no schema validation)
|
|
85
|
+
let isValidJson = false;
|
|
86
|
+
try {
|
|
87
|
+
JSON.parse(result.content);
|
|
88
|
+
isValidJson = true;
|
|
89
|
+
console.log('Model returned valid JSON');
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.log('Model returned non-JSON content (acceptable per D-005)');
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
isValidJson,
|
|
96
|
+
contentLength: result.content.length
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
console.log(result2.passed ? `✅ ${result2.name}` : `❌ ${result2.name}`);
|
|
100
|
+
if (!result2.passed) {
|
|
101
|
+
console.log(` Error: ${result2.error}`);
|
|
102
|
+
}
|
|
103
|
+
// Test 3: Timeout verification
|
|
104
|
+
console.log('\n3. Testing timeout handling...');
|
|
105
|
+
const result3 = await runTest('Verify timeout functionality', async () => {
|
|
106
|
+
const startTime = Date.now();
|
|
107
|
+
const result = await visionTool.analyze({
|
|
108
|
+
image: TEST_IMAGE_PATH,
|
|
109
|
+
prompt: 'Describe this image briefly.',
|
|
110
|
+
output_format: 'text'
|
|
111
|
+
});
|
|
112
|
+
const duration = Date.now() - startTime;
|
|
113
|
+
if (duration > 120000) {
|
|
114
|
+
throw new Error(`Request took too long: ${duration}ms (possible timeout issue)`);
|
|
115
|
+
}
|
|
116
|
+
console.log(`Request completed in ${duration}ms (not hanging)`);
|
|
117
|
+
return {
|
|
118
|
+
duration,
|
|
119
|
+
status: 'completed successfully'
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
console.log(result3.passed ? `✅ ${result3.name}` : `❌ ${result3.name}`);
|
|
123
|
+
if (!result3.passed) {
|
|
124
|
+
console.log(` Error: ${result3.error}`);
|
|
125
|
+
}
|
|
126
|
+
console.log(`\n✅ All tests passed for ${modelName}`);
|
|
127
|
+
}
|
|
128
|
+
async function main() {
|
|
129
|
+
console.log('Vision MCP Vision Tool Direct Tests');
|
|
130
|
+
console.log('====================================\n');
|
|
131
|
+
console.log(`Using test image: ${TEST_IMAGE_PATH}`);
|
|
132
|
+
// Test SiliconFlow first
|
|
133
|
+
try {
|
|
134
|
+
console.log('\nTesting SiliconFlow model...');
|
|
135
|
+
await testVisionToolWithModel(SILICONFLOW_CONFIG, 'SiliconFlow');
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error(`SiliconFlow test failed: ${error}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
// Test GLM-4.6V
|
|
142
|
+
try {
|
|
143
|
+
console.log('\n\nTesting GLM-4.6V model...');
|
|
144
|
+
await testVisionToolWithModel(GLM_CONFIG, 'GLM-4.6V');
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error(`GLM-4.6V test failed: ${error}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
console.log('\n' + '='.repeat(60));
|
|
151
|
+
console.log('🎉 All model tests completed successfully!');
|
|
152
|
+
console.log('='.repeat(60));
|
|
153
|
+
console.log('\nVerification Summary:');
|
|
154
|
+
console.log('✅ Timeout fix verified - requests complete without hanging');
|
|
155
|
+
console.log('✅ JSON output format works per D-005 (no forced schema validation)');
|
|
156
|
+
console.log('✅ Both GLM-4.6V and SiliconFlow adapters work correctly');
|
|
157
|
+
console.log('✅ Local file path input works correctly');
|
|
158
|
+
}
|
|
159
|
+
// Run if executed directly
|
|
160
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
161
|
+
main().catch(error => {
|
|
162
|
+
console.error('Fatal error:', error);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
export { main as runDirectTests };
|
|
167
|
+
//# sourceMappingURL=vision-tool.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-tool.test.js","sourceRoot":"","sources":["../../test/vision-tool.test.ts"],"names":[],"mappings":"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"}
|