appium-mcp 1.21.0 → 1.21.2

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/tests/benchmark_model/benchmark_model.d.ts +3 -0
  3. package/dist/tests/benchmark_model/benchmark_model.d.ts.map +1 -0
  4. package/dist/tests/benchmark_model/benchmark_model.js +597 -0
  5. package/dist/tests/benchmark_model/benchmark_model.js.map +1 -0
  6. package/dist/tests/tools/session/create-session.test.js +24 -1
  7. package/dist/tests/tools/session/create-session.test.js.map +1 -1
  8. package/dist/tools/session/create-session.d.ts +5 -0
  9. package/dist/tools/session/create-session.d.ts.map +1 -1
  10. package/dist/tools/session/create-session.js +7 -1
  11. package/dist/tools/session/create-session.js.map +1 -1
  12. package/package.json +1 -1
  13. package/server.json +2 -2
  14. package/src/tests/benchmark_model/TEST_REPORT.md +331 -0
  15. package/src/tests/benchmark_model/benchmark_model.ts +796 -0
  16. package/src/tests/benchmark_model/image.png +0 -0
  17. package/src/tests/benchmark_model/output/DeepSeek_V3_2_annotated.png +0 -0
  18. package/src/tests/benchmark_model/output/Qwen3_VL_235B_A22B_Instruct_annotated.png +0 -0
  19. package/src/tests/benchmark_model/output/claude_sonnet_4_6_annotated.png +0 -0
  20. package/src/tests/benchmark_model/output/doubao_seed_2_0_pro_260215_annotated.png +0 -0
  21. package/src/tests/benchmark_model/output/gemini_2_5_flash_annotated.png +0 -0
  22. package/src/tests/benchmark_model/output/gemini_2_5_pro_annotated.png +0 -0
  23. package/src/tests/benchmark_model/output/gemini_3_flash_preview_annotated.png +0 -0
  24. package/src/tests/benchmark_model/output/gemini_3_pro_preview_annotated.png +0 -0
  25. package/src/tests/benchmark_model/output/gpt_5_1_annotated.png +0 -0
  26. package/src/tests/benchmark_model/output/gpt_5_2_annotated.png +0 -0
  27. package/src/tests/benchmark_model/output/gpt_5_2_pro_annotated.png +0 -0
  28. package/src/tests/benchmark_model/output/gpt_5_nano_annotated.png +0 -0
  29. package/src/tests/benchmark_model/output/grok_4_1_fast_annotated.png +0 -0
  30. package/src/tests/benchmark_model/output/kimi_k2_5_annotated.png +0 -0
  31. package/src/tests/benchmark_model/output/qwen3_vl_8b_instruct_annotated.png +0 -0
  32. package/src/tests/benchmark_model/output/qwen3_vl_plus_annotated.png +0 -0
  33. package/src/tests/tools/session/create-session.test.ts +30 -1
  34. package/src/tools/session/create-session.ts +8 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [1.21.2](https://github.com/appium/appium-mcp/compare/v1.21.1...v1.21.2) (2026-03-02)
2
+
3
+ ### Miscellaneous Chores
4
+
5
+ * simplify a bit, ignore submodules for tests ([#185](https://github.com/appium/appium-mcp/issues/185)) ([59e9d02](https://github.com/appium/appium-mcp/commit/59e9d02909cb5236c3172bbb45c5dad7cbf4c7fc))
6
+
7
+ ## [1.21.1](https://github.com/appium/appium-mcp/compare/v1.21.0...v1.21.1) (2026-03-02)
8
+
9
+ ### Bug Fixes
10
+
11
+ * remote server URL port handling for default ports ([#184](https://github.com/appium/appium-mcp/issues/184)) ([6d138b8](https://github.com/appium/appium-mcp/commit/6d138b83373bfb4b5a956c5a048da65c937c0646))
12
+
1
13
  ## [1.21.0](https://github.com/appium/appium-mcp/compare/v1.20.0...v1.21.0) (2026-02-26)
2
14
 
3
15
  ### Features
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=benchmark_model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark_model.d.ts","sourceRoot":"","sources":["../../../src/tests/benchmark_model/benchmark_model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,597 @@
1
+ #!/usr/bin/env tsx
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import axios, { AxiosError } from 'axios';
6
+ import { imageUtil } from '@appium/support';
7
+ const sharp = imageUtil.requireSharp();
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ /**
11
+ * Model list for benchmarking
12
+ * Configure coordinate type for each model based on actual test results
13
+ */
14
+ const MODELS = [
15
+ // Deepseek
16
+ { name: 'DeepSeek-V3.2', coordType: 'absolute' },
17
+ // Qwen
18
+ { name: 'qwen3-vl-plus', coordType: 'normalized' },
19
+ { name: 'qwen3-vl-8b-instruct', coordType: 'normalized' },
20
+ { name: 'Qwen3-VL-235B-A22B-Instruct', coordType: 'normalized' },
21
+ // tiktok
22
+ { name: 'doubao-seed-2-0-pro-260215', coordType: 'normalized' },
23
+ // moonshot
24
+ { name: 'kimi-k2.5', coordType: 'absolute' },
25
+ // openai
26
+ { name: 'gpt-5.2-pro', coordType: 'absolute' },
27
+ { name: 'gpt-5.2', coordType: 'absolute' },
28
+ { name: 'gpt-5.1', coordType: 'absolute' },
29
+ { name: 'gpt-5-nano', coordType: 'absolute' },
30
+ // claude
31
+ { name: 'claude-sonnet-4-6', coordType: 'absolute' },
32
+ // google
33
+ { name: 'gemini-3-flash-preview', coordType: 'absolute' },
34
+ { name: 'gemini-3-pro-preview', coordType: 'absolute' },
35
+ { name: 'gemini-2.5-pro', coordType: 'normalized' },
36
+ { name: 'gemini-2.5-flash', coordType: 'normalized' },
37
+ // xai
38
+ { name: 'grok-4.1-fast', coordType: 'absolute' },
39
+ ];
40
+ /**
41
+ * Generate test prompt with image dimensions
42
+ */
43
+ function generateTestPrompt(imageWidth, imageHeight) {
44
+ return `You are a professional mobile automation testing expert. Your task is to locate the "Search Button" in the provided UI screenshot.
45
+
46
+ **CRITICAL: Output Format Rules**
47
+ You MUST respond using ONLY this exact format, nothing else:
48
+
49
+ action: **CLICK**
50
+ Parameters: {"target": "<exact visible text or icon description>", "bbox_2d": [<x1>, <y1>, <x2>, <y2>]}
51
+
52
+ **BBox Coordinates**
53
+ - x1: Left edge X coordinate (top-left corner of element)
54
+ - y1: Top edge Y coordinate (top-left corner of element)
55
+ - x2: Right edge X coordinate (bottom-right corner of element)
56
+ - y2: Bottom edge Y coordinate (bottom-right corner of element)
57
+
58
+ **Image Dimensions (ABSOLUTE PIXEL COORDINATES)**
59
+ - Width: ${imageWidth} pixels
60
+ - Height: ${imageHeight} pixels
61
+ - Origin (0,0): Top-left corner
62
+ - Max (${imageWidth}, ${imageHeight}): Bottom-right corner
63
+ - **MUST use integer values between 0-${imageWidth} for x, 0-${imageHeight} for y**
64
+
65
+ **What to Look For**
66
+ - **TARGET**: The YELLOW "搜索酒店" button (搜索酒店 means "Search Hotel")
67
+ - **LOCATION**: Bottom section of the screen, large yellow rounded rectangle button
68
+ - **APPEARANCE**: Bright yellow background with black text "搜索酒店"
69
+ - Choose ONLY the main yellow search button
70
+
71
+ **Examples of CORRECT responses:**
72
+ action: **CLICK**
73
+ Parameters: {"target": "Search", "bbox_2d": [100, 200, 300, 280]}
74
+ // target is exact visible text or icon description
75
+ // bbox_2d is absolute pixel coordinates, x1 and y1 are top-left corner, x2 and y2 are bottom-right corner
76
+
77
+ **Your response (STRICT FORMAT ONLY):**`;
78
+ }
79
+ /**
80
+ * Read image as base64
81
+ */
82
+ function readImageAsBase64(imagePath) {
83
+ const imageBuffer = fs.readFileSync(imagePath);
84
+ return imageBuffer.toString('base64');
85
+ }
86
+ /**
87
+ * Get MIME type from file extension
88
+ */
89
+ function getMimeType(imagePath) {
90
+ const ext = path.extname(imagePath).toLowerCase();
91
+ const mimeTypes = {
92
+ '.png': 'image/png',
93
+ '.jpg': 'image/jpeg',
94
+ '.jpeg': 'image/jpeg',
95
+ '.gif': 'image/gif',
96
+ '.webp': 'image/webp',
97
+ };
98
+ return mimeTypes[ext] || 'image/png';
99
+ }
100
+ /**
101
+ * Call unified model API
102
+ */
103
+ async function callModelAPI(model, imageBase64, prompt, mimeType, _imageWidth, _imageHeight) {
104
+ const baseUrl = process.env.API_BASE_URL;
105
+ const token = process.env.API_TOKEN;
106
+ if (!baseUrl) {
107
+ throw new Error('API_BASE_URL environment variable not set');
108
+ }
109
+ if (!token) {
110
+ throw new Error('API_TOKEN environment variable not set');
111
+ }
112
+ const response = await axios.post(`${baseUrl}/chat/completions`, {
113
+ model: model.name,
114
+ messages: [
115
+ {
116
+ role: 'user',
117
+ content: [
118
+ {
119
+ type: 'text',
120
+ text: prompt,
121
+ },
122
+ {
123
+ type: 'image_url',
124
+ image_url: {
125
+ url: `data:${mimeType};base64,${imageBase64}`,
126
+ },
127
+ // Add image size control parameters to ensure all models use the same image processing method
128
+ min_pixels: 64 * 32 * 32, // 65536 pixels
129
+ max_pixels: 2560 * 32 * 32, // 2621440 pixels
130
+ },
131
+ ],
132
+ },
133
+ ],
134
+ max_tokens: 4096,
135
+ }, {
136
+ headers: {
137
+ 'Content-Type': 'application/json',
138
+ Authorization: `Bearer ${token}`,
139
+ },
140
+ timeout: 120000,
141
+ });
142
+ return response.data.choices[0].message.content;
143
+ }
144
+ /**
145
+ * Judge model: Evaluate whether the search button in the annotated image is correctly boxed
146
+ */
147
+ async function judgeAnnotation(annotatedImagePath, modelName) {
148
+ try {
149
+ console.log(`\n🔍 [Judge] Evaluating ${modelName}...`);
150
+ const imageBase64 = readImageAsBase64(annotatedImagePath);
151
+ const mimeType = getMimeType(annotatedImagePath);
152
+ const judgePrompt = `You are a professional UI testing quality evaluation expert. Please carefully observe this annotated image; there is a red border marking a UI element.
153
+
154
+ **Your Task:**
155
+ Evaluate how accurately the red bounding box encloses the "Search Button" or "Search Input Box". Return a percentage score from 0% to 100%.
156
+
157
+ **Scoring Guidelines:**
158
+ - 100%: Perfect match - The red box exactly and completely encloses the search button/input box with minimal extra space
159
+ - 80-99%: Good match - The red box fully contains the search button with slight extra margins or minor misalignment
160
+ - 60-79%: Fair match - The red box covers most of the search button but misses some edges or includes significant extra area
161
+ - 40-59%: Poor match - The red box partially covers the search button or is significantly misaligned
162
+ - 20-39%: Bad match - The red box barely touches the search button or covers mostly wrong area
163
+ - 0-19%: Very bad match - The red box completely misses the search button, enclosing unrelated elements or empty space
164
+
165
+ **Please strictly return in the following format:**
166
+ Accuracy Score: [0-100]%
167
+ Reason: [One sentence explaining the scoring reason]
168
+
169
+ Example:
170
+ Accuracy Score: 85%
171
+ Reason: The red box completely contains the yellow search button with slight margins on all sides.`;
172
+ const baseUrl = process.env.API_BASE_URL;
173
+ const token = process.env.API_TOKEN;
174
+ // judge model
175
+ const response = await axios.post(`${baseUrl}/chat/completions`, {
176
+ model: 'qwen3-vl-plus',
177
+ messages: [
178
+ {
179
+ role: 'user',
180
+ content: [
181
+ {
182
+ type: 'text',
183
+ text: judgePrompt,
184
+ },
185
+ {
186
+ type: 'image_url',
187
+ image_url: {
188
+ url: `data:${mimeType};base64,${imageBase64}`,
189
+ },
190
+ },
191
+ ],
192
+ },
193
+ ],
194
+ max_tokens: 1024,
195
+ }, {
196
+ headers: {
197
+ 'Content-Type': 'application/json',
198
+ Authorization: `Bearer ${token}`,
199
+ },
200
+ timeout: 60000,
201
+ });
202
+ const judgeResponse = response.data.choices[0].message.content;
203
+ console.log(` Judge response: ${judgeResponse}`);
204
+ // Parse accuracy score
205
+ const scoreMatch = judgeResponse.match(/Accuracy Score[::]?\s*(\d+)%?/i);
206
+ const score = scoreMatch ? parseInt(scoreMatch[1], 10) : 0;
207
+ console.log(` 📊 Accuracy Score: ${score}%`);
208
+ return score;
209
+ }
210
+ catch (error) {
211
+ console.error(`✗ Judge failed for ${modelName}:`, error);
212
+ return 0;
213
+ }
214
+ }
215
+ /**
216
+ * Parse bbox coordinates from model response
217
+ */
218
+ function parseBBoxFromResponse(response) {
219
+ try {
220
+ // Try to match JSON format bbox
221
+ const jsonMatch = response.match(/\{[^}]*"target"[^}]*"bbox_2d"[^}]*\}/);
222
+ if (jsonMatch) {
223
+ const parsed = JSON.parse(jsonMatch[0]);
224
+ if (parsed.bbox_2d &&
225
+ Array.isArray(parsed.bbox_2d) &&
226
+ parsed.bbox_2d.length === 4) {
227
+ return parsed;
228
+ }
229
+ }
230
+ // Try to match array format [x1, y1, x2, y2]
231
+ const arrayMatch = response.match(/\[(\d+),\s*(\d+),\s*(\d+),\s*(\d+)\]/);
232
+ if (arrayMatch) {
233
+ return {
234
+ target: 'Detected element',
235
+ bbox_2d: [
236
+ parseInt(arrayMatch[1], 10),
237
+ parseInt(arrayMatch[2], 10),
238
+ parseInt(arrayMatch[3], 10),
239
+ parseInt(arrayMatch[4], 10),
240
+ ],
241
+ };
242
+ }
243
+ return null;
244
+ }
245
+ catch (error) {
246
+ console.error('Failed to parse bbox:', error);
247
+ return null;
248
+ }
249
+ }
250
+ /**
251
+ * Draw bounding box on image
252
+ * Process according to the coordinate type configured for the model
253
+ */
254
+ async function drawBBoxOnImage(originalImagePath, bbox, outputPath, modelName, coordType) {
255
+ try {
256
+ let [x1, y1, x2, y2] = bbox;
257
+ // Read original image to get dimensions
258
+ const image = sharp(originalImagePath);
259
+ const metadata = await image.metadata();
260
+ if (!metadata.width || !metadata.height) {
261
+ throw new Error('Failed to get image dimensions');
262
+ }
263
+ const width = metadata.width;
264
+ const height = metadata.height;
265
+ // Process according to model's configured coordinate type
266
+ if (coordType === 'normalized') {
267
+ // Normalized coordinates (0-1000) → Absolute pixel coordinates
268
+ const originalCoords = [x1, y1, x2, y2];
269
+ x1 = Math.floor((x1 / 1000) * width);
270
+ y1 = Math.floor((y1 / 1000) * height);
271
+ x2 = Math.floor((x2 / 1000) * width);
272
+ y2 = Math.floor((y2 / 1000) * height);
273
+ console.log(` [${modelName}] Converted normalized coords ${JSON.stringify(originalCoords)} to absolute: [${x1}, ${y1}, ${x2}, ${y2}]`);
274
+ }
275
+ else {
276
+ // Absolute pixel coordinates, use directly
277
+ console.log(` [${modelName}] Using absolute coords: [${x1}, ${y1}, ${x2}, ${y2}]`);
278
+ }
279
+ // Ensure coordinate order is correct (x1 < x2, y1 < y2)
280
+ if (x1 > x2) {
281
+ [x1, x2] = [x2, x1];
282
+ }
283
+ if (y1 > y2) {
284
+ [y1, y2] = [y2, y1];
285
+ }
286
+ // Ensure coordinates are valid
287
+ if (x1 >= x2 || y1 >= y2) {
288
+ throw new Error(`Invalid bbox coordinates after normalization: [${x1}, ${y1}, ${x2}, ${y2}]`);
289
+ }
290
+ // Ensure coordinates are within image bounds
291
+ x1 = Math.max(0, Math.min(x1, width - 1));
292
+ y1 = Math.max(0, Math.min(y1, height - 1));
293
+ x2 = Math.max(0, Math.min(x2, width));
294
+ y2 = Math.max(0, Math.min(y2, height));
295
+ const boxWidth = x2 - x1;
296
+ const boxHeight = y2 - y1;
297
+ // Create SVG red box (3px width)
298
+ const svg = `
299
+ <svg width="${width}" height="${height}">
300
+ <rect x="${x1}" y="${y1}" width="${boxWidth}" height="${boxHeight}"
301
+ fill="none" stroke="red" stroke-width="3"/>
302
+ <text x="${x1 + 5}" y="${y1 - 8}" font-family="Arial" font-size="14"
303
+ fill="red" font-weight="bold">${modelName}</text>
304
+ </svg>
305
+ `;
306
+ // Overlay SVG on original image
307
+ await image
308
+ .composite([
309
+ {
310
+ input: Buffer.from(svg),
311
+ top: 0,
312
+ left: 0,
313
+ },
314
+ ])
315
+ .toFile(outputPath);
316
+ console.log(`✓ Saved annotated image: ${outputPath}`);
317
+ console.log(` BBox: [${x1}, ${y1}, ${x2}, ${y2}] (${boxWidth}x${boxHeight})`);
318
+ }
319
+ catch (error) {
320
+ console.error(`✗ Failed to draw bbox for ${modelName}:`, error);
321
+ throw error;
322
+ }
323
+ }
324
+ /**
325
+ * Write content to TEST_REPORT.md
326
+ */
327
+ function writeToReport(content) {
328
+ const reportPath = path.join(__dirname, 'TEST_REPORT.md');
329
+ fs.appendFileSync(reportPath, content + '\n', 'utf-8');
330
+ }
331
+ /**
332
+ * Initialize TEST_REPORT.md
333
+ */
334
+ function initializeReport() {
335
+ const reportPath = path.join(__dirname, 'TEST_REPORT.md');
336
+ const header = `# Model Benchmark Test Report
337
+
338
+ **Test Date:** ${new Date().toLocaleString()}
339
+ **Test Type:** Automation Testing - Click Action Recognition
340
+
341
+ ---
342
+
343
+ ## Summary
344
+
345
+ | Model Name | Duration(ms) | Status | Accuracy Score | Annotated Image |
346
+ |------------|--------------|--------|----------------|-----------------|
347
+ <!-- SUMMARY_TABLE_ROWS -->
348
+
349
+ ### Statistics
350
+
351
+ <!-- STATISTICS_SECTION -->
352
+
353
+ ---
354
+
355
+ ## Detailed Results
356
+
357
+ `;
358
+ fs.writeFileSync(reportPath, header, 'utf-8');
359
+ }
360
+ /**
361
+ * Update summary table in TEST_REPORT.md with actual results
362
+ */
363
+ function updateSummaryTable(results) {
364
+ const reportPath = path.join(__dirname, 'TEST_REPORT.md');
365
+ let content = fs.readFileSync(reportPath, 'utf-8');
366
+ // Sort results by accuracy score (descending), failed models go to the end
367
+ const sortedResults = [...results].sort((a, b) => {
368
+ const scoreA = a.error ? -1 : a.judgeResult || 0;
369
+ const scoreB = b.error ? -1 : b.judgeResult || 0;
370
+ return scoreB - scoreA;
371
+ });
372
+ // Generate summary table rows
373
+ const tableRows = sortedResults
374
+ .map((result) => {
375
+ const status = result.error ? '❌ Failed' : '✅ Success';
376
+ const accuracy = result.judgeResult !== undefined ? `${result.judgeResult}%` : 'N/A';
377
+ const annotatedImage = result.annotatedImagePath
378
+ ? `[View](${path.relative(__dirname, result.annotatedImagePath).replace(/\\/g, '/')})`
379
+ : 'N/A';
380
+ return `| ${result.modelName} | ${result.duration} | ${status} | ${accuracy} | ${annotatedImage} |`;
381
+ })
382
+ .join('\n');
383
+ // Replace placeholder with actual rows and remove the placeholder
384
+ if (content.includes('<!-- SUMMARY_TABLE_ROWS -->')) {
385
+ content = content.replace('<!-- SUMMARY_TABLE_ROWS -->', tableRows);
386
+ }
387
+ // Calculate statistics
388
+ const successCount = results.filter((r) => !r.error).length;
389
+ const failCount = results.filter((r) => r.error).length;
390
+ const avgAccuracyScore = results.reduce((sum, r) => sum + (r.judgeResult || 0), 0) / results.length;
391
+ const highAccuracyCount = results.filter((r) => (r.judgeResult || 0) >= 70).length;
392
+ const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length;
393
+ const minDuration = Math.min(...results.map((r) => r.duration));
394
+ const maxDuration = Math.max(...results.map((r) => r.duration));
395
+ // Generate statistics section
396
+ const statisticsSection = `- **Total**: ${results.length} models
397
+ - **Success**: ${successCount} (${((successCount / results.length) * 100).toFixed(1)}%)
398
+ - **Failed**: ${failCount}
399
+ - **High Accuracy (≥70%)**: ${highAccuracyCount} (${((highAccuracyCount / results.length) * 100).toFixed(1)}%)
400
+ - **Avg Accuracy Score**: ${avgAccuracyScore.toFixed(1)}%
401
+ - **Average Duration**: ${avgDuration.toFixed(2)}ms
402
+ - **Min Duration**: ${minDuration}ms
403
+ - **Max Duration**: ${maxDuration}ms`;
404
+ // Replace placeholder with actual statistics and remove the placeholder
405
+ if (content.includes('<!-- STATISTICS_SECTION -->')) {
406
+ content = content.replace('<!-- STATISTICS_SECTION -->', statisticsSection);
407
+ }
408
+ fs.writeFileSync(reportPath, content, 'utf-8');
409
+ }
410
+ /**
411
+ * Test a single model
412
+ */
413
+ async function testModel(model, imageBase64, prompt, mimeType, originalImagePath, imageWidth, imageHeight) {
414
+ const startTime = Date.now();
415
+ const timestamp = new Date().toISOString();
416
+ try {
417
+ const separator = `\n${'='.repeat(60)}`;
418
+ const testingMsg = `Testing: ${model.name}`;
419
+ console.log(separator);
420
+ console.log(testingMsg);
421
+ console.log('='.repeat(60));
422
+ writeToReport(`${separator}\n## ${model.name}\n`);
423
+ writeToReport(`**Started at:** ${new Date().toLocaleString()}\n`);
424
+ const response = await callModelAPI(model, imageBase64, prompt, mimeType, imageWidth, imageHeight);
425
+ const duration = Date.now() - startTime;
426
+ const successMsg = `✓ Completed in ${duration}ms`;
427
+ const responseMsg = `\nResponse:\n${response}\n==========`;
428
+ console.log(successMsg);
429
+ console.log(responseMsg);
430
+ // Parse bbox coordinates
431
+ const bboxData = parseBBoxFromResponse(response);
432
+ let bbox;
433
+ if (bboxData) {
434
+ bbox = bboxData.bbox_2d;
435
+ console.log(`✓ Parsed bbox: [${bbox.join(', ')}]`);
436
+ console.log(`✓ Target: ${bboxData.target}`);
437
+ // Draw annotated image and save to output folder
438
+ const outputDir = path.join(__dirname, 'output');
439
+ // Ensure output directory exists
440
+ if (!fs.existsSync(outputDir)) {
441
+ fs.mkdirSync(outputDir, { recursive: true });
442
+ }
443
+ const annotatedImageName = `${model.name.replace(/[^a-zA-Z0-9]/g, '_')}_annotated.png`;
444
+ const annotatedImagePath = path.join(outputDir, annotatedImageName);
445
+ await drawBBoxOnImage(originalImagePath, bbox, annotatedImagePath, model.name, model.coordType);
446
+ writeToReport(`**BBox:** [${bbox.join(', ')}]`);
447
+ writeToReport(`**Target:** ${bboxData.target}`);
448
+ writeToReport(`**Annotated Image:** [${annotatedImageName}](output/${annotatedImageName})`);
449
+ // Use judge model to evaluate annotation result
450
+ const judgeResult = await judgeAnnotation(annotatedImagePath, model.name);
451
+ writeToReport(`**Accuracy Score:** ${judgeResult}%`);
452
+ writeToReport(`**Status:** ✅ Success`);
453
+ writeToReport(`**Duration:** ${duration}ms`);
454
+ writeToReport(`**Response:**\n\`\`\`\n${response}\n\`\`\`\n`);
455
+ return {
456
+ modelName: model.name,
457
+ response,
458
+ duration,
459
+ timestamp,
460
+ bbox,
461
+ judgeResult,
462
+ annotatedImagePath,
463
+ };
464
+ }
465
+ else {
466
+ console.log('⚠ No valid bbox found in response');
467
+ writeToReport(`**BBox:** Not found or invalid format`);
468
+ writeToReport(`**Judge Result:** ❌ No bbox to judge`);
469
+ writeToReport(`**Status:** ✅ Success`);
470
+ writeToReport(`**Duration:** ${duration}ms`);
471
+ writeToReport(`**Response:**\n\`\`\`\n${response}\n\`\`\`\n`);
472
+ return {
473
+ modelName: model.name,
474
+ response,
475
+ duration,
476
+ timestamp,
477
+ bbox,
478
+ judgeResult: 0,
479
+ };
480
+ }
481
+ }
482
+ catch (error) {
483
+ const duration = Date.now() - startTime;
484
+ let errorMessage = 'Unknown error';
485
+ if (error instanceof AxiosError) {
486
+ const status = error.response?.status || 'N/A';
487
+ const errorData = error.response?.data;
488
+ const errorDetail = errorData?.error?.message || errorData?.message || error.message;
489
+ errorMessage = `HTTP ${status}: ${errorDetail}`;
490
+ // Log detailed error information
491
+ console.error(`✗ Failed (${model.name}): ${errorMessage}`);
492
+ if (error.response?.data) {
493
+ console.error('Response data:', JSON.stringify(error.response.data, null, 2));
494
+ }
495
+ }
496
+ else if (error instanceof Error) {
497
+ errorMessage = error.message;
498
+ console.error(`✗ Failed (${model.name}): ${errorMessage}`);
499
+ }
500
+ writeToReport(`**Status:** ❌ Failed`);
501
+ writeToReport(`**Duration:** ${duration}ms`);
502
+ writeToReport(`**Error:** ${errorMessage}\n`);
503
+ return {
504
+ modelName: model.name,
505
+ response: '',
506
+ duration,
507
+ timestamp,
508
+ error: errorMessage,
509
+ judgeResult: 0,
510
+ };
511
+ }
512
+ }
513
+ /**
514
+ * Print summary table
515
+ */
516
+ function printSummary(results) {
517
+ const separator = '\n' + '='.repeat(60);
518
+ const summaryTitle = 'BENCHMARK SUMMARY';
519
+ console.log(separator);
520
+ console.log(summaryTitle);
521
+ console.log(separator);
522
+ console.log('\n📊 Results:\n');
523
+ results.forEach((result) => {
524
+ const status = result.error ? '❌ Failed' : '✅ Success';
525
+ const duration = `${result.duration}ms`;
526
+ const judgeStatus = result.judgeResult !== undefined ? `${result.judgeResult}%` : 'N/A';
527
+ console.log(` ${result.modelName}: ${status} (${duration}) - Judge: ${judgeStatus}`);
528
+ });
529
+ console.log(`\n📈 Statistics:\n`);
530
+ const successCount = results.filter((r) => !r.error).length;
531
+ const failCount = results.filter((r) => r.error).length;
532
+ const avgAccuracyScore = results.reduce((sum, r) => sum + (r.judgeResult || 0), 0) / results.length;
533
+ const highAccuracyCount = results.filter((r) => (r.judgeResult || 0) >= 70).length;
534
+ const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length;
535
+ console.log(` Total: ${results.length} models`);
536
+ console.log(` Success: ${successCount} (${((successCount / results.length) * 100).toFixed(1)}%)`);
537
+ console.log(` Failed: ${failCount}`);
538
+ console.log(` High Accuracy (≥70%): ${highAccuracyCount} (${((highAccuracyCount / results.length) * 100).toFixed(1)}%)`);
539
+ console.log(` Avg Accuracy Score: ${avgAccuracyScore.toFixed(1)}%`);
540
+ console.log(` Average Duration: ${avgDuration.toFixed(2)}ms`);
541
+ console.log(` Min Duration: ${Math.min(...results.map((r) => r.duration))}ms`);
542
+ console.log(` Max Duration: ${Math.max(...results.map((r) => r.duration))}ms`);
543
+ console.log(`\n---`);
544
+ }
545
+ /**
546
+ * Main benchmark function
547
+ */
548
+ async function runBenchmark() {
549
+ const args = process.argv.slice(2);
550
+ const imagePath = args[0] || path.join(__dirname, 'image.png');
551
+ // Validate image file exists
552
+ if (!fs.existsSync(imagePath)) {
553
+ console.error(`Error: Image file not found: ${imagePath}`);
554
+ console.log('\nUsage: npx tsx benchmark_model.ts <path-to-image>');
555
+ console.log(' or: npm run benchmark -- <path-to-image>');
556
+ process.exit(1);
557
+ }
558
+ const absoluteImagePath = path.resolve(imagePath);
559
+ try {
560
+ console.log('='.repeat(60));
561
+ console.log('MODEL BENCHMARK TEST');
562
+ console.log('='.repeat(60));
563
+ console.log(`\nTest Image: ${absoluteImagePath}`);
564
+ // Read image and get dimensions
565
+ const imageBase64 = readImageAsBase64(absoluteImagePath);
566
+ const mimeType = getMimeType(absoluteImagePath);
567
+ const imageInfo = await sharp(absoluteImagePath).metadata();
568
+ const imageWidth = imageInfo.width || 0;
569
+ const imageHeight = imageInfo.height || 0;
570
+ console.log(`Image Size: ${imageWidth}x${imageHeight}`);
571
+ console.log(`Models to Test: ${MODELS.length}`);
572
+ console.log(`List: ${MODELS.map((m) => m.name).join(', ')}`);
573
+ // Generate test prompt
574
+ const testPrompt = generateTestPrompt(imageWidth, imageHeight);
575
+ // Initialize report
576
+ initializeReport();
577
+ // Test all models concurrently
578
+ const results = await Promise.all(MODELS.map((model) => testModel(model, imageBase64, testPrompt, mimeType, absoluteImagePath, imageWidth, imageHeight)));
579
+ // Print summary
580
+ printSummary(results);
581
+ // Update summary table in report
582
+ updateSummaryTable(results);
583
+ console.log(`\n✓ Benchmark completed!`);
584
+ console.log(` Report saved to: TEST_REPORT.md`);
585
+ console.log(` Annotated images saved to: output/ folder`);
586
+ }
587
+ catch (error) {
588
+ console.error('\n✗ Benchmark failed:', error);
589
+ process.exit(1);
590
+ }
591
+ }
592
+ // Run the benchmark
593
+ runBenchmark().catch((error) => {
594
+ console.error('Fatal error:', error);
595
+ process.exit(1);
596
+ });
597
+ //# sourceMappingURL=benchmark_model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark_model.js","sourceRoot":"","sources":["../../../src/tests/benchmark_model/benchmark_model.ts"],"names":[],"mappings":"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"}