llm-checker 3.1.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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +418 -0
  3. package/analyzer/compatibility.js +584 -0
  4. package/analyzer/performance.js +505 -0
  5. package/bin/CLAUDE.md +12 -0
  6. package/bin/enhanced_cli.js +3118 -0
  7. package/bin/test-deterministic.js +41 -0
  8. package/package.json +96 -0
  9. package/src/CLAUDE.md +12 -0
  10. package/src/ai/intelligent-selector.js +615 -0
  11. package/src/ai/model-selector.js +312 -0
  12. package/src/ai/multi-objective-selector.js +820 -0
  13. package/src/commands/check.js +58 -0
  14. package/src/data/CLAUDE.md +11 -0
  15. package/src/data/model-database.js +637 -0
  16. package/src/data/sync-manager.js +279 -0
  17. package/src/hardware/CLAUDE.md +12 -0
  18. package/src/hardware/backends/CLAUDE.md +11 -0
  19. package/src/hardware/backends/apple-silicon.js +318 -0
  20. package/src/hardware/backends/cpu-detector.js +490 -0
  21. package/src/hardware/backends/cuda-detector.js +417 -0
  22. package/src/hardware/backends/intel-detector.js +436 -0
  23. package/src/hardware/backends/rocm-detector.js +440 -0
  24. package/src/hardware/detector.js +573 -0
  25. package/src/hardware/pc-optimizer.js +635 -0
  26. package/src/hardware/specs.js +286 -0
  27. package/src/hardware/unified-detector.js +442 -0
  28. package/src/index.js +2289 -0
  29. package/src/models/CLAUDE.md +17 -0
  30. package/src/models/ai-check-selector.js +806 -0
  31. package/src/models/catalog.json +426 -0
  32. package/src/models/deterministic-selector.js +1145 -0
  33. package/src/models/expanded_database.js +1142 -0
  34. package/src/models/intelligent-selector.js +532 -0
  35. package/src/models/requirements.js +310 -0
  36. package/src/models/scoring-config.js +57 -0
  37. package/src/models/scoring-engine.js +715 -0
  38. package/src/ollama/.cache/README.md +33 -0
  39. package/src/ollama/CLAUDE.md +24 -0
  40. package/src/ollama/client.js +438 -0
  41. package/src/ollama/enhanced-client.js +113 -0
  42. package/src/ollama/enhanced-scraper.js +634 -0
  43. package/src/ollama/manager.js +357 -0
  44. package/src/ollama/native-scraper.js +776 -0
  45. package/src/plugins/CLAUDE.md +11 -0
  46. package/src/plugins/examples/custom_model_plugin.js +87 -0
  47. package/src/plugins/index.js +295 -0
  48. package/src/utils/CLAUDE.md +11 -0
  49. package/src/utils/config.js +359 -0
  50. package/src/utils/formatter.js +315 -0
  51. package/src/utils/logger.js +272 -0
  52. package/src/utils/model-classifier.js +167 -0
  53. package/src/utils/verbose-progress.js +266 -0
@@ -0,0 +1,573 @@
1
+ const si = require('systeminformation');
2
+
3
+ class HardwareDetector {
4
+ constructor() {
5
+ this.cache = null;
6
+ this.cacheExpiry = 5 * 60 * 1000;
7
+ this.cacheTime = 0;
8
+ }
9
+
10
+ async getSystemInfo(forceFresh = false) {
11
+
12
+ if (!forceFresh && this.cache && (Date.now() - this.cacheTime < this.cacheExpiry)) {
13
+ return this.cache;
14
+ }
15
+
16
+ try {
17
+ const [cpu, memory, graphics, system, osInfo] = await Promise.all([
18
+ si.cpu(),
19
+ si.mem(),
20
+ si.graphics(),
21
+ si.system(),
22
+ si.osInfo()
23
+ ]);
24
+
25
+ const systemInfo = {
26
+ cpu: this.processCPUInfo(cpu),
27
+ memory: this.processMemoryInfo(memory),
28
+ gpu: this.processGPUInfo(graphics),
29
+ system: this.processSystemInfo(system),
30
+ os: this.processOSInfo(osInfo),
31
+ timestamp: Date.now()
32
+ };
33
+
34
+ this.cache = systemInfo;
35
+ this.cacheTime = Date.now();
36
+
37
+ return systemInfo;
38
+ } catch (error) {
39
+ throw new Error(`Failed to detect hardware: ${error.message}`);
40
+ }
41
+ }
42
+
43
+ processCPUInfo(cpu) {
44
+ return {
45
+ brand: cpu.brand || 'Unknown',
46
+ manufacturer: cpu.manufacturer || 'Unknown',
47
+ family: cpu.family || 'Unknown',
48
+ model: cpu.model || 'Unknown',
49
+ speed: cpu.speed || 0,
50
+ speedMax: cpu.speedMax || cpu.speed || 0,
51
+ cores: cpu.cores || 1,
52
+ physicalCores: cpu.physicalCores || cpu.cores || 1,
53
+ processors: cpu.processors || 1,
54
+ cache: {
55
+ l1d: cpu.cache?.l1d || 0,
56
+ l1i: cpu.cache?.l1i || 0,
57
+ l2: cpu.cache?.l2 || 0,
58
+ l3: cpu.cache?.l3 || 0
59
+ },
60
+ architecture: this.detectArchitecture(cpu),
61
+ score: this.calculateCPUScore(cpu)
62
+ };
63
+ }
64
+
65
+ processMemoryInfo(memory) {
66
+ const totalGB = Math.round(memory.total / (1024 ** 3));
67
+ const freeGB = Math.round(memory.free / (1024 ** 3));
68
+ const usedGB = totalGB - freeGB;
69
+
70
+ return {
71
+ total: totalGB,
72
+ free: freeGB,
73
+ used: usedGB,
74
+ available: Math.round(memory.available / (1024 ** 3)),
75
+ usagePercent: Math.round((usedGB / totalGB) * 100),
76
+ swapTotal: Math.round(memory.swaptotal / (1024 ** 3)),
77
+ swapUsed: Math.round(memory.swapused / (1024 ** 3)),
78
+ score: this.calculateMemoryScore(totalGB, freeGB)
79
+ };
80
+ }
81
+
82
+ processGPUInfo(graphics) {
83
+ const controllers = graphics.controllers || [];
84
+ const displays = graphics.displays || [];
85
+
86
+ // Debug logging to help diagnose GPU detection issues
87
+ if (process.env.DEBUG_GPU) {
88
+ console.log('GPU Detection Debug:', JSON.stringify(controllers, null, 2));
89
+ }
90
+
91
+
92
+ // Filter out invalid/virtualized GPUs first
93
+ const validGPUs = controllers.filter(gpu => {
94
+ const model = (gpu.model || '').toLowerCase();
95
+ const vendor = (gpu.vendor || '').toLowerCase();
96
+
97
+ // Skip GPUs with empty/invalid data (like virtualized GPUs)
98
+ if (!model || !vendor || model === 'unknown' || vendor === '') {
99
+ return false;
100
+ }
101
+
102
+ // Skip very generic/placeholder entries
103
+ if (model.includes('standard vga') || model.includes('microsoft basic')) {
104
+ return false;
105
+ }
106
+
107
+ return true;
108
+ });
109
+
110
+ // Find all dedicated GPUs from valid GPUs
111
+ const dedicatedGPUs = validGPUs.filter(gpu => {
112
+ const model = (gpu.model || '').toLowerCase();
113
+ const isDedicated = !this.isIntegratedGPU(gpu.model) && (
114
+ gpu.vram > 0 || // Has dedicated VRAM
115
+ model.includes('rtx') || // NVIDIA RTX series
116
+ model.includes('gtx') || // NVIDIA GTX series
117
+ model.includes('radeon rx') || // AMD RX series
118
+ model.includes('tesla') || // NVIDIA Tesla
119
+ model.includes('quadro') || // NVIDIA Quadro
120
+ model.includes('geforce') // NVIDIA GeForce
121
+ );
122
+ return isDedicated;
123
+ });
124
+
125
+ // Find integrated GPUs from valid GPUs
126
+ const integratedGPUs = validGPUs.filter(gpu =>
127
+ this.isIntegratedGPU(gpu.model)
128
+ );
129
+
130
+ // Select the best GPU using smart selection logic
131
+ const primaryGPU = this.selectBestGPU(dedicatedGPUs, integratedGPUs, validGPUs);
132
+
133
+ if (!primaryGPU) {
134
+ return {
135
+ model: 'No GPU detected',
136
+ vendor: 'Unknown',
137
+ vram: 0,
138
+ dedicated: false,
139
+ score: 0
140
+ };
141
+ }
142
+
143
+ // Enhance model detection using device ID when model is generic or missing
144
+ let enhancedModel = primaryGPU.model || 'Unknown GPU';
145
+ if (primaryGPU.deviceId && (
146
+ !primaryGPU.model ||
147
+ primaryGPU.model === 'Unknown' ||
148
+ primaryGPU.model.includes('NVIDIA Corporation Device')
149
+ )) {
150
+ enhancedModel = this.getGPUModelFromDeviceId(primaryGPU.deviceId) || enhancedModel;
151
+ }
152
+
153
+ // Enhanced VRAM detection using the new normalizeVRAM function
154
+ let vram = this.normalizeVRAM(primaryGPU.vram || 0);
155
+
156
+ // If VRAM is still 0, try to estimate based on model or handle unified memory
157
+ if (vram === 0 && primaryGPU.model) {
158
+ const modelLower = primaryGPU.model.toLowerCase();
159
+ if (modelLower.includes('apple') || modelLower.includes('unified')) {
160
+ // Apple Silicon uses unified memory - return 0 to indicate this
161
+ vram = 0;
162
+ } else {
163
+ vram = this.estimateVRAMFromModel(primaryGPU.model);
164
+ }
165
+ }
166
+
167
+ // Calculate total VRAM from all dedicated GPUs (for multi-GPU setups)
168
+ let totalDedicatedVRAM = 0;
169
+ let gpuCount = 0;
170
+
171
+ dedicatedGPUs.forEach(gpu => {
172
+ const gpuVram = this.normalizeVRAM(gpu.vram || 0) || this.estimateVRAMFromModel(gpu.model);
173
+ if (gpuVram > 0) {
174
+ totalDedicatedVRAM += gpuVram;
175
+ gpuCount++;
176
+ }
177
+ });
178
+
179
+ // If we have multiple dedicated GPUs, use the combined VRAM
180
+ const effectiveVRAM = gpuCount > 1 ? totalDedicatedVRAM : vram;
181
+
182
+ return {
183
+ model: enhancedModel,
184
+ vendor: primaryGPU.vendor || 'Unknown',
185
+ vram: effectiveVRAM,
186
+ vramPerGPU: vram, // VRAM of primary GPU for reference
187
+ vramDynamic: primaryGPU.vramDynamic || false,
188
+ dedicated: !this.isIntegratedGPU(enhancedModel),
189
+ driverVersion: primaryGPU.driverVersion || 'Unknown',
190
+ gpuCount: gpuCount > 0 ? gpuCount : (dedicatedGPUs.length > 0 ? dedicatedGPUs.length : 1),
191
+ isMultiGPU: gpuCount > 1,
192
+ all: controllers.map(gpu => ({
193
+ model: gpu.model,
194
+ vram: this.normalizeVRAM(gpu.vram || 0),
195
+ vendor: gpu.vendor
196
+ })),
197
+ displays: displays.length,
198
+ score: this.calculateGPUScore(primaryGPU)
199
+ };
200
+ }
201
+
202
+ processSystemInfo(system) {
203
+ return {
204
+ manufacturer: system.manufacturer || 'Unknown',
205
+ model: system.model || 'Unknown',
206
+ version: system.version || 'Unknown',
207
+ serial: system.serial || 'Unknown',
208
+ uuid: system.uuid || 'Unknown',
209
+ sku: system.sku || 'Unknown'
210
+ };
211
+ }
212
+
213
+ processOSInfo(osInfo) {
214
+ return {
215
+ platform: osInfo.platform || process.platform,
216
+ distro: osInfo.distro || 'Unknown',
217
+ release: osInfo.release || 'Unknown',
218
+ codename: osInfo.codename || 'Unknown',
219
+ kernel: osInfo.kernel || 'Unknown',
220
+ arch: osInfo.arch || process.arch,
221
+ hostname: osInfo.hostname || 'Unknown',
222
+ logofile: osInfo.logofile || ''
223
+ };
224
+ }
225
+
226
+ detectArchitecture(cpu) {
227
+ const brand = (cpu.brand || '').toLowerCase();
228
+ const model = (cpu.model || '').toLowerCase();
229
+ const manufacturer = (cpu.manufacturer || '').toLowerCase();
230
+
231
+ if (manufacturer.includes('apple') || brand.includes('apple') || brand.includes('m1') || brand.includes('m2') || brand.includes('m3') || brand.includes('m4')) {
232
+ return 'Apple Silicon';
233
+ } else if (brand.includes('intel')) {
234
+ return 'x86_64';
235
+ } else if (brand.includes('amd')) {
236
+ return 'x86_64';
237
+ } else if (process.arch === 'arm64') {
238
+ return 'ARM64';
239
+ } else {
240
+ return process.arch || 'Unknown';
241
+ }
242
+ }
243
+
244
+ isIntegratedGPU(model) {
245
+ if (!model) return false;
246
+ const modelLower = model.toLowerCase();
247
+ // Check if GPU is integrated (on-chip or shared memory, not discrete)
248
+ // Note: && has higher precedence than ||, each line is grouped with ()
249
+ return (modelLower.includes('intel') && !modelLower.includes('arc')) ||
250
+ (modelLower.includes('amd') && modelLower.includes('graphics') && !modelLower.includes(' rx ')) ||
251
+ (modelLower.includes('radeon') && modelLower.includes('graphics')) ||
252
+ modelLower.includes('iris') ||
253
+ modelLower.includes('uhd') ||
254
+ modelLower.includes('hd graphics') ||
255
+ modelLower.includes('apple');
256
+ }
257
+
258
+ getGPUModelFromDeviceId(deviceId) {
259
+ if (!deviceId) return null;
260
+
261
+ // Normalize device ID (remove 0x prefix if present and convert to lowercase)
262
+ const normalizedId = deviceId.toLowerCase().replace('0x', '');
263
+
264
+ // NVIDIA RTX 50 series device IDs
265
+ const deviceIdMap = {
266
+ '2d04': 'NVIDIA GeForce RTX 5060 Ti',
267
+ '2d05': 'NVIDIA GeForce RTX 5060',
268
+ '2d06': 'NVIDIA GeForce RTX 5070',
269
+ '2d07': 'NVIDIA GeForce RTX 5070 Ti',
270
+ '2d08': 'NVIDIA GeForce RTX 5080',
271
+ '2d09': 'NVIDIA GeForce RTX 5090',
272
+
273
+ // NVIDIA RTX 40 series device IDs
274
+ '2684': 'NVIDIA GeForce RTX 4090',
275
+ '2685': 'NVIDIA GeForce RTX 4080',
276
+ '2786': 'NVIDIA GeForce RTX 4070 Ti',
277
+ '2787': 'NVIDIA GeForce RTX 4070',
278
+ '27a0': 'NVIDIA GeForce RTX 4060 Ti',
279
+ '27a1': 'NVIDIA GeForce RTX 4060',
280
+
281
+ // NVIDIA RTX 30 series device IDs
282
+ '2204': 'NVIDIA GeForce RTX 3090',
283
+ '2206': 'NVIDIA GeForce RTX 3080',
284
+ '2484': 'NVIDIA GeForce RTX 3070',
285
+ '2487': 'NVIDIA GeForce RTX 3060 Ti',
286
+ '2504': 'NVIDIA GeForce RTX 3060'
287
+ };
288
+
289
+ return deviceIdMap[normalizedId] || null;
290
+ }
291
+
292
+ estimateVRAMFromModel(model) {
293
+ if (!model) return 0;
294
+ const modelLower = model.toLowerCase();
295
+
296
+ // NVIDIA RTX 50 series
297
+ if (modelLower.includes('rtx 5090')) return 32;
298
+ if (modelLower.includes('rtx 5080')) return 16;
299
+ if (modelLower.includes('rtx 5070 ti')) return 16;
300
+ if (modelLower.includes('rtx 5070')) return 12;
301
+ if (modelLower.includes('rtx 5060 ti')) return 16;
302
+ if (modelLower.includes('rtx 5060')) return 8;
303
+
304
+ // NVIDIA RTX 40 series
305
+ if (modelLower.includes('rtx 4090')) return 24;
306
+ if (modelLower.includes('rtx 4080')) return 16;
307
+ if (modelLower.includes('rtx 4070 ti')) return 12;
308
+ if (modelLower.includes('rtx 4070')) return 12;
309
+ if (modelLower.includes('rtx 4060 ti')) return 16;
310
+ if (modelLower.includes('rtx 4060')) return 8;
311
+
312
+ // NVIDIA RTX 30 series
313
+ if (modelLower.includes('rtx 3090')) return 24;
314
+ if (modelLower.includes('rtx 3080 ti')) return 12;
315
+ if (modelLower.includes('rtx 3080')) return 10;
316
+ if (modelLower.includes('rtx 3070')) return 8;
317
+ if (modelLower.includes('rtx 3060 ti')) return 8;
318
+ if (modelLower.includes('rtx 3060')) return 12;
319
+
320
+ // AMD RX 7000 series
321
+ if (modelLower.includes('rx 7900')) return 24;
322
+ if (modelLower.includes('rx 7800')) return 16;
323
+ if (modelLower.includes('rx 7700')) return 12;
324
+ if (modelLower.includes('rx 7600')) return 8;
325
+
326
+ // Generic estimates
327
+ if (modelLower.includes('rtx')) return 8; // Default for RTX
328
+ if (modelLower.includes('gtx')) return 4; // Default for GTX
329
+ if (modelLower.includes('rx ')) return 8; // Default for AMD RX
330
+
331
+ return 0; // Unknown or integrated
332
+ }
333
+
334
+ calculateCPUScore(cpu) {
335
+ let score = 0;
336
+
337
+ // Base score por número de cores
338
+ score += (cpu.cores || 1) * 5;
339
+ score += (cpu.physicalCores || cpu.cores || 1) * 3;
340
+
341
+ // Score por velocidad
342
+ const speed = cpu.speedMax || cpu.speed || 0;
343
+ score += speed * 10;
344
+
345
+ // Bonus por arquitectura moderna
346
+ const brand = (cpu.brand || '').toLowerCase();
347
+ if (brand.includes('apple m')) {
348
+ score += 20; // Apple Silicon bonus
349
+ } else if (brand.includes('intel') && speed > 3.0) {
350
+ score += 15;
351
+ } else if (brand.includes('amd') && speed > 3.0) {
352
+ score += 15;
353
+ }
354
+
355
+ return Math.min(Math.round(score), 100);
356
+ }
357
+
358
+ calculateMemoryScore(totalGB, freeGB) {
359
+ let score = 0;
360
+
361
+ // Score basado en RAM total
362
+ if (totalGB >= 64) score += 40;
363
+ else if (totalGB >= 32) score += 35;
364
+ else if (totalGB >= 16) score += 25;
365
+ else if (totalGB >= 8) score += 15;
366
+ else score += totalGB * 2;
367
+
368
+ // Score basado en RAM disponible
369
+ const freePercent = (freeGB / totalGB) * 100;
370
+ if (freePercent > 50) score += 20;
371
+ else if (freePercent > 30) score += 15;
372
+ else if (freePercent > 20) score += 10;
373
+ else score += 5;
374
+
375
+ return Math.min(Math.round(score), 100);
376
+ }
377
+
378
+ calculateGPUScore(gpu) {
379
+ if (!gpu || !gpu.model) return 0;
380
+
381
+ let score = 0;
382
+ const model = gpu.model.toLowerCase();
383
+ const vram = gpu.vram || 0;
384
+
385
+
386
+ score += vram * 8;
387
+
388
+
389
+ if (!this.isIntegratedGPU(gpu.model)) {
390
+ score += 20;
391
+ }
392
+
393
+ // Bonus por marcas/modelos específicos
394
+ if (model.includes('rtx 5090')) score += 30;
395
+ else if (model.includes('rtx 5080')) score += 27;
396
+ else if (model.includes('rtx 5070')) score += 24;
397
+ else if (model.includes('rtx 5060')) score += 21;
398
+ else if (model.includes('rtx 4090')) score += 25;
399
+ else if (model.includes('rtx 4080')) score += 22;
400
+ else if (model.includes('rtx 4070')) score += 20;
401
+ else if (model.includes('rtx 30')) score += 18;
402
+ else if (model.includes('rtx 20')) score += 15;
403
+ else if (model.includes('gtx 16')) score += 12;
404
+ else if (model.includes('apple m')) score += 15;
405
+
406
+ return Math.min(Math.round(score), 100);
407
+ }
408
+
409
+ /**
410
+ * Select the best GPU from multiple available GPUs
411
+ * Prioritizes: 1) Dedicated GPUs by VRAM, 2) Model tier, 3) Integrated GPUs
412
+ */
413
+ selectBestGPU(dedicatedGPUs, integratedGPUs, validGPUs) {
414
+ // If we have dedicated GPUs, choose the best one
415
+ if (dedicatedGPUs.length > 0) {
416
+ // Sort dedicated GPUs by a combination of VRAM and model tier
417
+ return dedicatedGPUs.sort((a, b) => {
418
+ // First priority: VRAM amount
419
+ const vramA = this.normalizeVRAM(a.vram || 0);
420
+ const vramB = this.normalizeVRAM(b.vram || 0);
421
+
422
+ if (vramA !== vramB) {
423
+ return vramB - vramA; // Higher VRAM first
424
+ }
425
+
426
+ // Second priority: GPU tier (RTX 50xx > RTX 40xx > RTX 30xx, etc.)
427
+ const tierA = this.getGPUTier(a.model || '');
428
+ const tierB = this.getGPUTier(b.model || '');
429
+
430
+ if (tierA !== tierB) {
431
+ return tierB - tierA; // Higher tier first
432
+ }
433
+
434
+ // Third priority: Vendor preference (NVIDIA > AMD > Intel)
435
+ const vendorA = this.getVendorPriority(a.vendor || '');
436
+ const vendorB = this.getVendorPriority(b.vendor || '');
437
+
438
+ return vendorB - vendorA;
439
+ })[0];
440
+ }
441
+
442
+ // If no dedicated GPUs, use the best integrated GPU
443
+ if (integratedGPUs.length > 0) {
444
+ return integratedGPUs.sort((a, b) => {
445
+ const tierA = this.getGPUTier(a.model || '');
446
+ const tierB = this.getGPUTier(b.model || '');
447
+ return tierB - tierA;
448
+ })[0];
449
+ }
450
+
451
+ // Fallback to any valid GPU (should rarely happen)
452
+ return validGPUs.length > 0 ? validGPUs[0] : null;
453
+ }
454
+
455
+ /**
456
+ * Normalize VRAM values (handle different units and wrong totals)
457
+ */
458
+ normalizeVRAM(vram) {
459
+ if (!vram || vram <= 0) return 0;
460
+
461
+ let vramValue = vram;
462
+
463
+ // Handle VRAM in bytes (some systems report this way)
464
+ if (vramValue > 100000) {
465
+ vramValue = Math.round(vramValue / (1024 * 1024)); // Convert bytes to MB
466
+ }
467
+
468
+ // Now determine if we have MB or GB values
469
+ if (vramValue >= 1024) {
470
+ // Values >= 1024 are likely MB, convert to GB
471
+ vramValue = Math.round(vramValue / 1024);
472
+ } else if (vramValue >= 512 && vramValue < 1024) {
473
+ // 512-1023 MB, round to 1GB
474
+ vramValue = 1;
475
+ } else if (vramValue > 80) {
476
+ // Values between 80-511 are likely incorrect MB values, treat as MB
477
+ vramValue = Math.round(vramValue / 1024) || 1;
478
+ } else if (vramValue >= 1 && vramValue <= 80) {
479
+ // Values 1-80 are likely already in GB, keep as is
480
+ vramValue = vramValue;
481
+ } else {
482
+ // Values < 1 round to 0
483
+ vramValue = 0;
484
+ }
485
+
486
+ return vramValue;
487
+ }
488
+
489
+ /**
490
+ * Get GPU tier score for prioritization
491
+ */
492
+ getGPUTier(model) {
493
+ const modelLower = model.toLowerCase();
494
+
495
+ // NVIDIA RTX series
496
+ if (modelLower.includes('rtx 50')) return 100;
497
+ if (modelLower.includes('rtx 4090')) return 95;
498
+ if (modelLower.includes('rtx 40')) return 90;
499
+ if (modelLower.includes('rtx 3090')) return 85;
500
+ if (modelLower.includes('rtx 30')) return 80;
501
+ if (modelLower.includes('rtx 20')) return 70;
502
+ if (modelLower.includes('gtx 16')) return 60;
503
+ if (modelLower.includes('gtx 10')) return 50;
504
+
505
+ // NVIDIA Professional
506
+ if (modelLower.includes('a100')) return 98;
507
+ if (modelLower.includes('h100')) return 99;
508
+ if (modelLower.includes('tesla')) return 75;
509
+ if (modelLower.includes('quadro')) return 65;
510
+
511
+ // AMD
512
+ if (modelLower.includes('rx 7900')) return 85;
513
+ if (modelLower.includes('rx 7800')) return 80;
514
+ if (modelLower.includes('rx 7700')) return 75;
515
+ if (modelLower.includes('rx 6900')) return 70;
516
+ if (modelLower.includes('rx 6800')) return 65;
517
+
518
+ // Intel
519
+ if (modelLower.includes('arc a7')) return 55;
520
+ if (modelLower.includes('arc a5')) return 45;
521
+
522
+ // Apple Silicon
523
+ if (modelLower.includes('apple') || modelLower.includes('m1') ||
524
+ modelLower.includes('m2') || modelLower.includes('m3') ||
525
+ modelLower.includes('m4')) return 80;
526
+
527
+ return 10; // Default for unknown
528
+ }
529
+
530
+ /**
531
+ * Get vendor priority score
532
+ */
533
+ getVendorPriority(vendor) {
534
+ const vendorLower = vendor.toLowerCase();
535
+ if (vendorLower.includes('nvidia')) return 3;
536
+ if (vendorLower.includes('amd') || vendorLower.includes('ati')) return 2;
537
+ if (vendorLower.includes('intel')) return 1;
538
+ if (vendorLower.includes('apple')) return 3;
539
+ return 0;
540
+ }
541
+
542
+ async runQuickBenchmark() {
543
+
544
+ const start = process.hrtime.bigint();
545
+
546
+
547
+ let cpuResult = 0;
548
+ for (let i = 0; i < 1000000; i++) {
549
+ cpuResult += Math.sqrt(i);
550
+ }
551
+
552
+ const end = process.hrtime.bigint();
553
+ const cpuTime = Number(end - start) / 1000000; // ms
554
+
555
+ const memStart = process.hrtime.bigint();
556
+ const largeArray = new Array(1000000).fill(0).map((_, i) => i);
557
+ largeArray.sort((a, b) => b - a);
558
+ const memEnd = process.hrtime.bigint();
559
+ const memTime = Number(memEnd - memStart) / 1000000;
560
+
561
+ return {
562
+ cpu: Math.max(0, Math.min(100, 100 - (cpuTime / 100))),
563
+ memory: Math.max(0, Math.min(100, 100 - (memTime / 50))),
564
+ overall: Math.round((
565
+ Math.max(0, Math.min(100, 100 - (cpuTime / 100))) +
566
+ Math.max(0, Math.min(100, 100 - (memTime / 50)))
567
+ ) / 2)
568
+ };
569
+ }
570
+
571
+ }
572
+
573
+ module.exports = HardwareDetector;