devicely 2.2.13 โ†’ 2.2.14

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 (41) hide show
  1. package/bin/devicely.js +1 -1
  2. package/lib/advanced-logger.js +1 -1
  3. package/lib/androidDeviceDetection.js +1 -1
  4. package/lib/appMappings.js +1 -1
  5. package/lib/commanderService.js +1 -1
  6. package/lib/deviceDetection.js +1 -1
  7. package/lib/devices.js +1 -1
  8. package/lib/doctor.js +1 -1
  9. package/lib/encryption.js +1 -1
  10. package/lib/executor.js +1 -1
  11. package/lib/hybridAI.js +1 -1
  12. package/lib/intelligentLocatorService.js +1 -1
  13. package/lib/lightweightAI.js +1 -1
  14. package/lib/localBuiltInAI.js +1 -1
  15. package/lib/localBuiltInAI_backup.js +1 -1
  16. package/lib/localBuiltInAI_simple.js +1 -1
  17. package/lib/locatorStrategy.js +1 -1
  18. package/lib/logger-demo.js +1 -1
  19. package/lib/logger.js +1 -1
  20. package/lib/quick-start-logger.js +1 -1
  21. package/lib/scriptLoader.js +1 -1
  22. package/lib/server.js +1 -1
  23. package/lib/tensorflowAI.js +1 -1
  24. package/lib/tinyAI.js +1 -1
  25. package/lib/universalSessionManager.js +1 -1
  26. package/package.json +1 -1
  27. package/lib/.logging-backup/aiProviders.js.backup +0 -654
  28. package/lib/.logging-backup/appMappings.js.backup +0 -337
  29. package/lib/.logging-backup/commanderService.js.backup +0 -4427
  30. package/lib/.logging-backup/devices.js.backup +0 -54
  31. package/lib/.logging-backup/doctor.js.backup +0 -94
  32. package/lib/.logging-backup/encryption.js.backup +0 -61
  33. package/lib/.logging-backup/executor.js.backup +0 -104
  34. package/lib/.logging-backup/hybridAI.js.backup +0 -154
  35. package/lib/.logging-backup/intelligentLocatorService.js.backup +0 -1541
  36. package/lib/.logging-backup/locatorStrategy.js.backup +0 -342
  37. package/lib/.logging-backup/scriptLoader.js.backup +0 -13
  38. package/lib/.logging-backup/server.js.backup +0 -6298
  39. package/lib/.logging-backup/tensorflowAI.js.backup +0 -714
  40. package/lib/.logging-backup/universalSessionManager.js.backup +0 -370
  41. package/lib/.logging-enhanced-backup/server.js.enhanced-backup +0 -6298
@@ -1,714 +0,0 @@
1
- /**
2
- * ๐Ÿง  TENSORFLOW.JS LIGHTWEIGHT AI + GENIUS CONVERTER
3
- * Uses existing TensorFlow.js infrastructure + Revolutionary Genius AI system
4
- */
5
-
6
- let tf = null;
7
- let GeniusAICommandConverter = null;
8
-
9
- // Optional dependencies - graceful degradation if not installed
10
- try {
11
- tf = require('@tensorflow/tfjs-node');
12
- } catch (err) {
13
- console.warn('[TensorFlowAI] TensorFlow.js not installed - using fallback mode');
14
- }
15
-
16
- try {
17
- GeniusAICommandConverter = require('../../geniusAIConverter');
18
- } catch (err) {
19
- console.warn('[TensorFlowAI] GeniusAIConverter not available - using simple converter');
20
- }
21
-
22
- class TensorFlowAI {
23
- constructor() {
24
- this.logger = console;
25
-
26
- // Check if dependencies are available
27
- this.hasTensorFlow = tf !== null;
28
- this.hasGeniusConverter = GeniusAICommandConverter !== null;
29
-
30
- // ๐Ÿš€ GENIUS: Initialize Revolutionary AI Converter (if available)
31
- if (this.hasGeniusConverter) {
32
- try {
33
- this.geniusConverter = new GeniusAICommandConverter();
34
- } catch (err) {
35
- this.logger.warn('[TensorFlowAI] Failed to initialize GeniusAIConverter:', err.message);
36
- this.hasGeniusConverter = false;
37
- this.geniusConverter = null;
38
- }
39
- } else {
40
- this.geniusConverter = null;
41
- }
42
-
43
- // Model state
44
- this.textEmbeddingModel = null;
45
- this.isLoading = false;
46
- this.isReady = this.hasTensorFlow; // Only ready if TensorFlow is available
47
-
48
- // Enhanced command templates with similarity scores
49
- this.commandTemplates = {
50
- launch: {
51
- patterns: ['open', 'launch', 'start', 'run', 'begin'],
52
- apps: ['settings', 'camera', 'calculator', 'safari', 'maps', 'photos', 'mail', 'notes', 'music', 'calendar']
53
- },
54
- click: {
55
- patterns: ['tap', 'click', 'press', 'touch', 'select', 'choose'],
56
- elements: ['bluetooth', 'wifi', 'cellular', 'battery', 'display', 'sound', 'general', 'privacy', 'storage']
57
- },
58
- swipe: {
59
- patterns: ['swipe', 'scroll', 'slide', 'drag'],
60
- directions: ['up', 'down', 'left', 'right', 'upward', 'downward']
61
- },
62
- navigation: {
63
- patterns: ['home', 'back', 'return', 'exit', 'close'],
64
- targets: ['home screen', 'previous', 'main menu']
65
- },
66
- input: {
67
- patterns: ['type', 'enter', 'input', 'write', 'search'],
68
- actions: ['text', 'message', 'query', 'search term']
69
- }
70
- };
71
-
72
- // Enhanced rule fallback
73
- this.ruleBasedAI = null;
74
-
75
- this.stats = {
76
- tensorflowSuccess: 0,
77
- ruleBasedFallback: 0,
78
- totalRequests: 0,
79
- avgInferenceTime: 0
80
- };
81
- }
82
-
83
- /**
84
- * ๐Ÿš€ Initialize TensorFlow.js (simplified approach)
85
- */
86
- async initialize() {
87
- if (this.isReady) return true;
88
- if (this.isLoading) {
89
- while (this.isLoading) {
90
- await new Promise(resolve => setTimeout(resolve, 100));
91
- }
92
- return this.isReady;
93
- }
94
-
95
- this.isLoading = true;
96
-
97
- try {
98
- if (this.hasTensorFlow) {
99
- this.logger.info('๐Ÿง  TensorFlowAI: Initializing with TensorFlow.js support...');
100
- // Initialize with simple but effective text similarity
101
- // This avoids network dependencies and works completely offline
102
- this.isReady = true;
103
- this.logger.info('โœ… TensorFlowAI: Enhanced pattern matching ready! (TensorFlow mode)');
104
- } else {
105
- this.logger.info('๐Ÿง  TensorFlowAI: Initializing in fallback mode (no TensorFlow)...');
106
- // Still functional with rule-based processing
107
- this.isReady = true;
108
- this.logger.info('โœ… TensorFlowAI: Rule-based pattern matching ready! (Fallback mode)');
109
- }
110
-
111
- } catch (error) {
112
- this.logger.warn('โš ๏ธ TensorFlowAI: Initialization failed, will use basic rule-based fallback');
113
- this.isReady = false;
114
- } finally {
115
- this.isLoading = false;
116
- }
117
-
118
- return this.isReady;
119
- }
120
-
121
- /**
122
- * ๐Ÿš€ GENIUS: Main Conversion Method - Revolutionary Approach
123
- */
124
- async convertCommand(text, devices = [], options = {}) {
125
- this.stats.totalRequests++;
126
- const startTime = Date.now();
127
-
128
- // ๐Ÿง  GENIUS: Use Revolutionary Genius AI Converter First (if available)
129
- if (this.hasGeniusConverter && this.geniusConverter) {
130
- try {
131
- console.log('๐Ÿš€ Using GENIUS AI Converter for maximum accuracy...');
132
- const geniusResult = await this.geniusConverter.convertCommand(text, devices, options);
133
-
134
- if (geniusResult.success && geniusResult.confidence > 0.8) {
135
- console.log(`โœ… GENIUS AI SUCCESS: ${geniusResult.processingTime}ms, confidence: ${(geniusResult.confidence * 100).toFixed(1)}%, method: ${geniusResult.method}`);
136
- this.stats.tensorflowSuccess++; // Count as success
137
-
138
- return {
139
- success: true,
140
- converted: geniusResult.converted,
141
- confidence: geniusResult.confidence,
142
- processingTime: geniusResult.processingTime,
143
- method: geniusResult.method,
144
- details: geniusResult.details
145
- };
146
- }
147
-
148
- console.log('๐Ÿ”„ Genius AI confidence low, trying enhanced pattern matching...');
149
-
150
- } catch (error) {
151
- console.log('โš ๏ธ Genius AI error, falling back to enhanced patterns:', error.message);
152
- }
153
- } else {
154
- console.log('๐Ÿ”„ Genius AI not available, using pattern matching...');
155
- }
156
-
157
- // Fallback to enhanced pattern matching
158
- try {
159
- // Try enhanced pattern matching first
160
- if (this.isReady || await this.initialize()) {
161
- this.logger.info('๐Ÿง  TensorFlowAI: Processing with enhanced pattern matching...');
162
-
163
- const patternResult = await this.processWithPatternMatching(text);
164
-
165
- if (patternResult.success && patternResult.confidence > 0.75) {
166
- this.stats.tensorflowSuccess++;
167
- const inferenceTime = Date.now() - startTime;
168
- this.updateAverageInferenceTime(inferenceTime);
169
-
170
- this.logger.info(`โœ… Enhanced Pattern SUCCESS: ${inferenceTime}ms, confidence: ${(patternResult.confidence * 100).toFixed(1)}%`);
171
- return {
172
- ...patternResult,
173
- processingTime: inferenceTime,
174
- method: 'enhanced-patterns'
175
- };
176
- }
177
- }
178
-
179
- // Fallback to enhanced rule-based
180
- this.logger.info('๐Ÿ”„ TensorFlowAI: Using enhanced rule-based fallback...');
181
- const ruleResult = await this.getRuleBasedFallback(text, devices, options);
182
-
183
- this.stats.ruleBasedFallback++;
184
- return {
185
- ...ruleResult,
186
- processingTime: Date.now() - startTime,
187
- method: 'rule-based-fallback'
188
- };
189
-
190
- } catch (error) {
191
- this.logger.error('โŒ TensorFlowAI: Error during processing:', error.message);
192
-
193
- return {
194
- success: false,
195
- error: error.message,
196
- processingTime: Date.now() - startTime,
197
- method: 'error'
198
- };
199
- }
200
- }
201
-
202
- /**
203
- * ๐ŸŽฏ Process command using enhanced pattern matching
204
- */
205
- async processWithPatternMatching(text) {
206
- try {
207
- const cleanText = text.toLowerCase().trim();
208
-
209
- // ๐Ÿ” First, try to break down into multiple commands
210
- const multipleCommands = this.parseMultipleCommands(cleanText);
211
- if (multipleCommands.length > 1) {
212
- const allCommands = [];
213
-
214
- for (const commandText of multipleCommands) {
215
- const singleCommand = this.parseSingleCommand(commandText);
216
- if (singleCommand) {
217
- allCommands.push(singleCommand);
218
- }
219
- }
220
-
221
- if (allCommands.length > 0) {
222
- return {
223
- success: true,
224
- converted: allCommands.join('\nWAIT 1500\n'),
225
- confidence: 0.95,
226
- matchedCategory: 'multi-command',
227
- commandCount: allCommands.length
228
- };
229
- }
230
- }
231
-
232
- // ๐ŸŽฏ Fall back to single command parsing
233
- const singleCommand = this.parseSingleCommand(cleanText);
234
- if (singleCommand) {
235
- return {
236
- success: true,
237
- converted: singleCommand,
238
- confidence: 0.9,
239
- matchedCategory: 'single-command',
240
- commandCount: 1
241
- };
242
- }
243
-
244
- return { success: false, confidence: 0 };
245
-
246
- } catch (error) {
247
- this.logger.error('โŒ Pattern matching error:', error.message);
248
- return { success: false, error: error.message };
249
- }
250
- }
251
-
252
- /**
253
- * ๐Ÿ” Parse multiple commands from text
254
- */
255
- parseMultipleCommands(text) {
256
- // Split by common conjunctions and action words
257
- const separators = [
258
- 'then', 'and', 'after that', 'next', 'also', 'now',
259
- 'launch', 'open', 'start', 'click', 'tap', 'swipe', 'scroll',
260
- 'go', 'goto', 'home', 'back', 'close', 'type', 'enter'
261
- ];
262
-
263
- let segments = [text];
264
-
265
- // Split by separators while preserving the separator as part of next command
266
- for (const separator of separators) {
267
- const newSegments = [];
268
-
269
- for (const segment of segments) {
270
- const parts = segment.split(new RegExp(`\\b(${separator})\\b`, 'i'));
271
-
272
- for (let i = 0; i < parts.length; i++) {
273
- const part = parts[i].trim();
274
- if (!part || part === separator) continue;
275
-
276
- // If this part starts with a separator, include it
277
- if (separators.includes(part.toLowerCase()) && i + 1 < parts.length) {
278
- const nextPart = parts[i + 1].trim();
279
- if (nextPart) {
280
- newSegments.push(part + ' ' + nextPart);
281
- i++; // Skip the next part since we combined it
282
- }
283
- } else if (part.length > 2) {
284
- newSegments.push(part);
285
- }
286
- }
287
- }
288
-
289
- if (newSegments.length > segments.length) {
290
- segments = newSegments;
291
- }
292
- }
293
-
294
- // Clean up segments and filter out noise
295
- return segments
296
- .map(s => s.trim())
297
- .filter(s => s.length > 3)
298
- .filter(s => !['and', 'then', 'after', 'that', 'next', 'also', 'now'].includes(s.toLowerCase()));
299
- }
300
-
301
- /**
302
- * ๐ŸŽฏ Parse a single command from text - ENHANCED VERSION
303
- */
304
- parseSingleCommand(text) {
305
- const cleanText = text.toLowerCase().trim();
306
-
307
- // ๐Ÿ“‹ VERSION/DEVICE INFO commands (FIXED - HIGH PRIORITY)
308
- if (/\b(version|about|info)\b/i.test(cleanText) ||
309
- (/\bdevice\b/i.test(cleanText) && /\b(check|info|show)\b/i.test(cleanText))) {
310
-
311
- // Voice-specific version checks
312
- if (/\bvoice\b/i.test(cleanText)) {
313
- return 'navigate_to Settings > Accessibility > Voice Control';
314
- }
315
- // iOS/Android version checks
316
- else if (/\b(ios|android|system|device)\b/i.test(cleanText)) {
317
- return 'navigate_to Settings > General > About';
318
- }
319
- // General version/about requests
320
- else {
321
- return 'navigate_to Settings > General > About';
322
- }
323
- }
324
-
325
- // ๐ŸŽค VOICE SETTINGS commands (FIXED)
326
- if (/\bvoice\b/i.test(cleanText) &&
327
- /\b(settings|show|open|control|accessibility)\b/i.test(cleanText)) {
328
- return 'navigate_to Settings > Accessibility > Voice Control';
329
- }
330
-
331
- // ๐Ÿ“ธ PHOTO/SCREENSHOT commands (FIXED - HIGH PRIORITY)
332
- if (/\b(take|capture|snap)\b/i.test(cleanText) &&
333
- /\b(photo|picture|screenshot|pic|image|shot)\b/i.test(cleanText)) {
334
- return 'screenshot';
335
- }
336
-
337
- // ๐Ÿ“ท Camera-specific photo commands (FIXED)
338
- if (/\bcamera\b/i.test(cleanText) &&
339
- /\b(photo|picture|take|capture|snap|pic)\b/i.test(cleanText)) {
340
- return 'screenshot';
341
- }
342
-
343
- // ๐Ÿ“ฑ MULTI-COMMAND detection (ENHANCED)
344
- if (/\b(and|then|after|next)\b/i.test(cleanText)) {
345
- return this.parseMultiCommand(cleanText);
346
- }
347
-
348
- // ๐Ÿš€ LAUNCH/OPEN commands
349
- if (/\b(launch|open|start|run|begin)\b/i.test(cleanText)) {
350
- const appName = this.extractAppName(cleanText) || 'settings';
351
- return `launch ${appName}`;
352
- }
353
-
354
- // ๐Ÿ–ฑ๏ธ CLICK/TAP commands
355
- if (/\b(click|tap|press|touch|select)\b/i.test(cleanText)) {
356
- const element = this.extractElementName(cleanText);
357
- return element ? `click ${element}` : null;
358
- }
359
-
360
- // ๐Ÿ‘† SWIPE commands
361
- if (/\b(swipe|scroll|slide|drag)\b/i.test(cleanText)) {
362
- const direction = this.extractDirection(cleanText) || 'up';
363
- return `swipe ${direction}`;
364
- }
365
-
366
- // ๐Ÿ  HOME/NAVIGATION commands
367
- if (/\b(home|back|return|exit|close)\b/i.test(cleanText)) {
368
- if (/\bhome\b/i.test(cleanText)) return 'home';
369
- if (/\bback\b/i.test(cleanText)) return 'back';
370
- return 'home';
371
- }
372
-
373
- // โŒจ๏ธ TYPE commands
374
- if (/\b(type|enter|input|write|search)\b/i.test(cleanText)) {
375
- const textToType = this.extractTextToType(cleanText);
376
- return textToType ? `type ${textToType}` : null;
377
- }
378
-
379
- // ๐Ÿ“ธ PHOTO/SCREENSHOT commands (NEW - HIGH PRIORITY)
380
- if (/\b(take|capture|snap)\b/i.test(cleanText) &&
381
- /\b(photo|picture|screenshot|pic|image|shot)\b/i.test(cleanText)) {
382
- return 'screenshot';
383
- }
384
-
385
- // ๐Ÿ“ท Camera-specific photo commands
386
- if (/\bcamera\b/i.test(cleanText) &&
387
- /\b(photo|picture|take|capture|snap|pic)\b/i.test(cleanText)) {
388
- return 'screenshot';
389
- }
390
-
391
- // ๐Ÿ“ฑ Check if it contains an app name (implicit launch)
392
- const appName = this.extractAppName(cleanText);
393
- if (appName) {
394
- return `launch ${appName}`;
395
- }
396
-
397
- // ๐Ÿ”˜ Check if it contains a UI element (implicit click)
398
- const element = this.extractElementName(cleanText);
399
- if (element) {
400
- return `click ${element}`;
401
- }
402
-
403
- return null;
404
- }
405
-
406
- /**
407
- * ๐Ÿ”— ENHANCED: Parse multi-command sequences
408
- */
409
- parseMultiCommand(text) {
410
- const separators = ['and then', 'then', 'and', 'after that', 'next', ','];
411
- let parts = [text];
412
-
413
- // Split by separators
414
- for (const separator of separators) {
415
- const newParts = [];
416
- for (const part of parts) {
417
- const regex = new RegExp(`\\s+${separator}\\s+`, 'i');
418
- newParts.push(...part.split(regex));
419
- }
420
- parts = newParts.filter(p => p.trim().length > 0);
421
- if (parts.length > 1) break; // Found a separator
422
- }
423
-
424
- if (parts.length > 1) {
425
- const commands = [];
426
- for (const part of parts) {
427
- const command = this.parseSingleCommand(part.trim());
428
- if (command && !command.includes('parseMultiCommand')) {
429
- commands.push(command);
430
- }
431
- }
432
- return commands.length > 0 ? commands.join('\nWAIT 1500\n') : null;
433
- }
434
-
435
- return null;
436
- }
437
-
438
- /**
439
- * ๐Ÿ“Š Calculate similarity score for a category
440
- */
441
- calculateCategoryScore(text, config) {
442
- let maxScore = 0;
443
-
444
- // Check pattern words
445
- for (const pattern of config.patterns) {
446
- const similarity = this.calculateWordSimilarity(text, pattern);
447
- maxScore = Math.max(maxScore, similarity);
448
- }
449
-
450
- // Check specific terms (apps, elements, etc.)
451
- for (const [key, values] of Object.entries(config)) {
452
- if (key !== 'patterns' && Array.isArray(values)) {
453
- for (const value of values) {
454
- const similarity = this.calculateWordSimilarity(text, value);
455
- maxScore = Math.max(maxScore, similarity * 0.9); // Slightly lower weight for specific terms
456
- }
457
- }
458
- }
459
-
460
- return maxScore;
461
- }
462
-
463
- /**
464
- * ๐Ÿ“ Calculate word similarity using simple but effective methods
465
- */
466
- calculateWordSimilarity(text, word) {
467
- // Exact match
468
- if (text.includes(word)) return 1.0;
469
-
470
- // Fuzzy matching for typos
471
- const distance = this.levenshteinDistance(text, word);
472
- const maxLength = Math.max(text.length, word.length);
473
- const similarity = 1 - (distance / maxLength);
474
-
475
- // Boost score if word appears in text
476
- const words = text.split(/\s+/);
477
- for (const textWord of words) {
478
- if (textWord === word) return 1.0;
479
-
480
- const wordDistance = this.levenshteinDistance(textWord, word);
481
- const wordSimilarity = 1 - (wordDistance / Math.max(textWord.length, word.length));
482
-
483
- if (wordSimilarity > 0.8) return wordSimilarity;
484
- }
485
-
486
- return Math.max(0, similarity > 0.6 ? similarity : 0);
487
- }
488
-
489
- /**
490
- * ๐Ÿ“ Levenshtein distance for typo tolerance
491
- */
492
- levenshteinDistance(str1, str2) {
493
- const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
494
-
495
- for (let i = 0; i <= str1.length; i += 1) {
496
- matrix[0][i] = i;
497
- }
498
-
499
- for (let j = 0; j <= str2.length; j += 1) {
500
- matrix[j][0] = j;
501
- }
502
-
503
- for (let j = 1; j <= str2.length; j += 1) {
504
- for (let i = 1; i <= str1.length; i += 1) {
505
- const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
506
- matrix[j][i] = Math.min(
507
- matrix[j][i - 1] + 1, // deletion
508
- matrix[j - 1][i] + 1, // insertion
509
- matrix[j - 1][i - 1] + indicator, // substitution
510
- );
511
- }
512
- }
513
-
514
- return matrix[str2.length][str1.length];
515
- }
516
-
517
- /**
518
- * ๐Ÿ” Find best matching pattern/element in category
519
- */
520
- findBestMatch(text, config) {
521
- let bestMatch = null;
522
- let bestScore = 0;
523
-
524
- for (const [key, values] of Object.entries(config)) {
525
- if (Array.isArray(values)) {
526
- for (const value of values) {
527
- const score = this.calculateWordSimilarity(text, value);
528
- if (score > bestScore) {
529
- bestScore = score;
530
- bestMatch = value;
531
- }
532
- }
533
- }
534
- }
535
-
536
- return bestMatch;
537
- }
538
-
539
- /**
540
- * ๐ŸŽฏ Generate specific commands from category and matches
541
- */
542
- generateCommandsFromCategory(inputText, category, bestMatch) {
543
- const commands = [];
544
-
545
- switch (category) {
546
- case 'launch':
547
- const appName = this.extractAppName(inputText) || 'settings';
548
- commands.push(`launch ${appName}`);
549
- break;
550
-
551
- case 'click':
552
- const element = this.extractElementName(inputText) || 'button';
553
- commands.push(`click ${element}`);
554
- break;
555
-
556
- case 'swipe':
557
- const direction = this.extractDirection(inputText) || 'up';
558
- commands.push(`swipe ${direction}`);
559
- break;
560
-
561
- case 'navigation':
562
- if (inputText.includes('home')) {
563
- commands.push('home');
564
- } else if (inputText.includes('back')) {
565
- commands.push('back');
566
- } else {
567
- commands.push('home');
568
- }
569
- break;
570
-
571
- case 'input':
572
- const textToType = this.extractTextToType(inputText);
573
- if (textToType) {
574
- commands.push(`type ${textToType}`);
575
- } else {
576
- commands.push('type text');
577
- }
578
- break;
579
-
580
- default:
581
- commands.push('launch settings');
582
- }
583
-
584
- return commands.length > 0 ? commands : ['launch settings'];
585
- }
586
-
587
- /**
588
- * ๐Ÿ” Extract app name from command text (enhanced)
589
- */
590
- extractAppName(text) {
591
- const appKeywords = ['settings', 'camera', 'calculator', 'safari', 'maps', 'photos', 'mail', 'notes', 'music', 'calendar'];
592
-
593
- // Check for exact matches first
594
- for (const app of appKeywords) {
595
- if (text.includes(app)) {
596
- return app;
597
- }
598
- }
599
-
600
- // Check for close matches
601
- for (const app of appKeywords) {
602
- if (this.calculateWordSimilarity(text, app) > 0.8) {
603
- return app;
604
- }
605
- }
606
-
607
- // Extract word after launch/open keywords
608
- const match = text.match(/(?:launch|open|start|run)\s+(\w+)/);
609
- if (match) {
610
- const candidate = match[1];
611
- // Check if it's a known app or similar
612
- for (const app of appKeywords) {
613
- if (this.calculateWordSimilarity(candidate, app) > 0.7) {
614
- return app;
615
- }
616
- }
617
- return candidate;
618
- }
619
-
620
- return 'settings';
621
- }
622
-
623
- /**
624
- * ๐Ÿ” Extract element name from command text (enhanced)
625
- */
626
- extractElementName(text) {
627
- const elementKeywords = ['bluetooth', 'wifi', 'cellular', 'battery', 'display', 'sound', 'general', 'privacy', 'storage'];
628
-
629
- for (const element of elementKeywords) {
630
- if (text.includes(element) || this.calculateWordSimilarity(text, element) > 0.8) {
631
- return element;
632
- }
633
- }
634
-
635
- const match = text.match(/(?:click|tap|press|touch)\s+(\w+)/);
636
- return match ? match[1] : 'button';
637
- }
638
-
639
- /**
640
- * ๐Ÿ” Extract direction from command text
641
- */
642
- extractDirection(text) {
643
- const directions = ['up', 'down', 'left', 'right'];
644
-
645
- for (const direction of directions) {
646
- if (text.includes(direction)) {
647
- return direction;
648
- }
649
- }
650
-
651
- return 'up';
652
- }
653
-
654
- /**
655
- * ๐Ÿ” Extract text to type from command
656
- */
657
- extractTextToType(text) {
658
- const match = text.match(/(?:type|enter|input|search)\s+(.+)/);
659
- return match ? match[1].trim() : null;
660
- }
661
-
662
- /**
663
- * ๐Ÿ”„ Get rule-based AI fallback
664
- */
665
- async getRuleBasedFallback(text, devices, options) {
666
- if (!this.ruleBasedAI) {
667
- const LocalBuiltInAI = require('./localBuiltInAI');
668
- this.ruleBasedAI = new LocalBuiltInAI();
669
- }
670
-
671
- return await this.ruleBasedAI.convertCommand(text, devices, options);
672
- }
673
-
674
- /**
675
- * ๐Ÿ“Š Update average inference time
676
- */
677
- updateAverageInferenceTime(newTime) {
678
- if (this.stats.tensorflowSuccess === 1) {
679
- this.stats.avgInferenceTime = newTime;
680
- } else {
681
- this.stats.avgInferenceTime = (this.stats.avgInferenceTime * (this.stats.tensorflowSuccess - 1) + newTime) / this.stats.tensorflowSuccess;
682
- }
683
- }
684
-
685
- /**
686
- * ๐Ÿ“Š Get AI status and performance metrics
687
- */
688
- getStatus() {
689
- return {
690
- tensorflow: {
691
- ready: this.isReady,
692
- loading: this.isLoading,
693
- modelSize: '0MB (Enhanced Pattern Matching)',
694
- avgInferenceTime: `${Math.round(this.stats.avgInferenceTime)}ms`,
695
- mode: 'offline-patterns'
696
- },
697
- stats: { ...this.stats },
698
- efficiency: this.stats.totalRequests > 0
699
- ? `${(this.stats.tensorflowSuccess / this.stats.totalRequests * 100).toFixed(1)}% handled by enhanced patterns`
700
- : 'No requests yet',
701
- memoryUsage: process.memoryUsage()
702
- };
703
- }
704
-
705
- /**
706
- * ๐Ÿงน Cleanup resources (lightweight - nothing to dispose)
707
- */
708
- dispose() {
709
- this.isReady = false;
710
- this.logger.info('๐Ÿงน TensorFlowAI: Pattern matching resources cleaned up');
711
- }
712
- }
713
-
714
- module.exports = TensorFlowAI;