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,370 +0,0 @@
1
- /**
2
- * ๐Ÿš€ UNIVERSAL SESSION MANAGER - REVOLUTIONARY APPROACH
3
- * ====================================================
4
- *
5
- * CORE PRINCIPLE: NEVER STORE SESSIONS, ALWAYS GET LIVE SESSIONS FROM WDA
6
- *
7
- * This eliminates ALL session conflicts, file corruption, and timing issues.
8
- * Always returns the ACTUAL active session from the running WDA process.
9
- */
10
-
11
- const axios = require('axios');
12
- const Logger = require('./logger');
13
-
14
- class UniversalSessionManager {
15
- constructor() {
16
- this.logger = new Logger('UniversalSessionManager');
17
-
18
- // Device port mapping (the ONLY thing we store)
19
- this.devicePorts = new Map(); // Map<deviceName, port>
20
-
21
- // Reference to connected devices (for sync with global session manager)
22
- this.connectedDevices = null;
23
-
24
- this.logger.info('๐Ÿš€ Universal Session Manager initialized - LIVE SESSION MODE');
25
- }
26
-
27
- /**
28
- * ๐ŸŽฏ SET CONNECTED DEVICES REFERENCE: For port mapping sync
29
- */
30
- setConnectedDevices(connectedDevices) {
31
- this.connectedDevices = connectedDevices;
32
- this.logger.debug(`๐Ÿ“ Connected devices reference set (${connectedDevices ? connectedDevices.length : 0} devices)`);
33
- }
34
-
35
- /**
36
- * ๐ŸŽฏ CORE METHOD: Get Live Active Session ID
37
- * Always fetches from running WDA/UIAutomator2 process, never from storage
38
- */
39
- async getLiveSessionId(deviceName, port = null) {
40
- try {
41
- // Get port from mapping or parameter
42
- const devicePort = port || this.devicePorts.get(deviceName) || this.guessPortFromName(deviceName);
43
-
44
- if (!devicePort) {
45
- throw new Error(`No port mapping found for device: ${deviceName}`);
46
- }
47
-
48
- this.logger.debug(`๐Ÿ” Getting live session for ${deviceName}:${devicePort}...`);
49
-
50
- // Determine if this is Android UIAutomator2 (port >= 8200) or iOS WDA (port < 8200)
51
- const isUIAutomator2 = devicePort >= 8200;
52
-
53
- if (isUIAutomator2) {
54
- // Method 1A: Try UIAutomator2 /wd/hub/sessions endpoint
55
- try {
56
- const sessionsResponse = await axios.get(`http://localhost:${devicePort}/wd/hub/sessions`, {
57
- timeout: 2000 // Reduced from 3000ms to 2000ms for faster response
58
- });
59
-
60
- if (sessionsResponse.data?.value && Array.isArray(sessionsResponse.data.value)) {
61
- const activeSessions = sessionsResponse.data.value;
62
-
63
- if (activeSessions.length > 0) {
64
- const sessionId = activeSessions[0].id || activeSessions[0].sessionId;
65
- this.logger.debug(`โœ… Live UIAutomator2 session found via /wd/hub/sessions: ${sessionId.substring(0, 8)}... for ${deviceName}:${devicePort}`);
66
- return {
67
- sessionId,
68
- port: devicePort,
69
- platform: 'android'
70
- };
71
- }
72
- }
73
- } catch (sessionsError) {
74
- this.logger.debug(`UIAutomator2 /wd/hub/sessions endpoint failed for ${deviceName}:${devicePort}: ${sessionsError.message}`);
75
- }
76
-
77
- // Method 2A: Try UIAutomator2 status endpoint
78
- try {
79
- const statusResponse = await axios.get(`http://localhost:${devicePort}/wd/hub/status`, {
80
- timeout: 2000 // Reduced timeout
81
- });
82
-
83
- if (statusResponse.status === 200) {
84
- // UIAutomator2 is running, but we need to get session from sessions endpoint
85
- this.logger.debug(`UIAutomator2 server is running on ${devicePort}, but no active sessions found`);
86
- }
87
- } catch (statusError) {
88
- this.logger.debug(`UIAutomator2 /wd/hub/status endpoint failed for ${deviceName}:${devicePort}: ${statusError.message}`);
89
- }
90
- } else {
91
- // Method 1B: Try iOS WDA /sessions endpoint (most reliable)
92
- try {
93
- const sessionsResponse = await axios.get(`http://localhost:${devicePort}/sessions`, {
94
- timeout: 2000 // Reduced from 3000ms to 2000ms
95
- });
96
-
97
- if (sessionsResponse.data?.value && Array.isArray(sessionsResponse.data.value)) {
98
- const activeSessions = sessionsResponse.data.value;
99
-
100
- if (activeSessions.length > 0) {
101
- const sessionId = activeSessions[0].id;
102
- this.logger.debug(`โœ… Live WDA session found via /sessions: ${sessionId.substring(0, 8)}... for ${deviceName}:${devicePort}`);
103
- return sessionId;
104
- }
105
- }
106
- } catch (sessionsError) {
107
- this.logger.debug(`WDA /sessions endpoint failed for ${deviceName}:${devicePort}: ${sessionsError.message}`);
108
- }
109
-
110
- // Method 2B: Try iOS WDA status endpoint (alternative)
111
- try {
112
- const statusResponse = await axios.get(`http://localhost:${devicePort}/status`, {
113
- timeout: 3000
114
- });
115
-
116
- if (statusResponse.data?.sessionId) {
117
- const sessionId = statusResponse.data.sessionId;
118
- this.logger.debug(`โœ… Live WDA session found via /status: ${sessionId.substring(0, 8)}... for ${deviceName}:${devicePort}`);
119
- return sessionId;
120
- }
121
- } catch (statusError) {
122
- this.logger.debug(`WDA /status endpoint failed for ${deviceName}:${devicePort}: ${statusError.message}`);
123
- }
124
- }
125
-
126
- // Method 3: Check if WDA is actually running before attempting to create session
127
- try {
128
- // First, verify WDA is running on this port
129
- const healthCheck = await axios.get(`http://localhost:${devicePort}/health`, {
130
- timeout: 2000,
131
- validateStatus: () => true
132
- });
133
-
134
- if (healthCheck.status !== 200) {
135
- this.logger.debug(`โš ๏ธ WDA health check failed on port ${devicePort} - WDA may not be running`);
136
- throw new Error(`WDA not responding on port ${devicePort}`);
137
- }
138
-
139
- this.logger.info(`๐Ÿ”„ No active session found, creating new session for ${deviceName}:${devicePort}...`);
140
-
141
- const createResponse = await axios.post(`http://localhost:${devicePort}/session`, {
142
- capabilities: {
143
- alwaysMatch: {},
144
- firstMatch: [{}]
145
- }
146
- }, { timeout: 10000 });
147
-
148
- if (createResponse.data?.sessionId) {
149
- const sessionId = createResponse.data.sessionId;
150
- this.logger.info(`โœ… Created new session: ${sessionId.substring(0, 8)}... for ${deviceName}:${devicePort}`);
151
- return sessionId;
152
- }
153
-
154
- // Handle alternative session response format
155
- if (createResponse.data?.value?.sessionId) {
156
- const sessionId = createResponse.data.value.sessionId;
157
- this.logger.info(`โœ… Created new session (alt format): ${sessionId.substring(0, 8)}... for ${deviceName}:${devicePort}`);
158
- return sessionId;
159
- }
160
- } catch (createError) {
161
- this.logger.warn(`Failed to create session for ${deviceName}:${devicePort}: ${createError.message}`);
162
- }
163
-
164
- throw new Error(`No active WDA session available for ${deviceName} on port ${devicePort}`);
165
-
166
- } catch (error) {
167
- this.logger.error(`โŒ Failed to get live session for ${deviceName}: ${error.message}`);
168
- throw error;
169
- }
170
- }
171
-
172
- /**
173
- * ๐ŸŽฏ VALIDATE SESSION: Check if session ID is still valid
174
- */
175
- async validateSession(sessionId, deviceName, port = null) {
176
- try {
177
- const devicePort = port || this.devicePorts.get(deviceName) || this.guessPortFromName(deviceName);
178
-
179
- // Try multiple validation methods - start with lightest
180
-
181
- // Method 1: Try status endpoint first (lighter)
182
- try {
183
- const statusResponse = await axios.get(`http://localhost:${devicePort}/status`, {
184
- timeout: 1500
185
- });
186
-
187
- if (statusResponse.data && statusResponse.status === 200) {
188
- this.logger.debug(`โœ… Session ${sessionId.substring(0, 8)}... validated via status for ${deviceName}`);
189
- return true;
190
- }
191
- } catch (statusError) {
192
- this.logger.debug(`Status validation failed for ${deviceName}: ${statusError.message}`);
193
- }
194
-
195
- // Method 2: If status fails, try sessions endpoint
196
- try {
197
- const sessionsResponse = await axios.get(`http://localhost:${devicePort}/sessions`, {
198
- timeout: 1500
199
- });
200
-
201
- if (sessionsResponse.data?.value && Array.isArray(sessionsResponse.data.value)) {
202
- const activeSessions = sessionsResponse.data.value;
203
- const sessionExists = activeSessions.find(s => s.id === sessionId);
204
-
205
- if (sessionExists) {
206
- this.logger.debug(`โœ… Session ${sessionId.substring(0, 8)}... validated via sessions for ${deviceName}`);
207
- return true;
208
- }
209
- }
210
- } catch (sessionsError) {
211
- this.logger.debug(`Sessions validation failed for ${deviceName}: ${sessionsError.message}`);
212
- }
213
-
214
- // Method 3: Last resort - try source endpoint (heaviest)
215
- try {
216
- await axios.get(`http://localhost:${devicePort}/session/${sessionId}/source`, {
217
- timeout: 2000
218
- });
219
-
220
- this.logger.debug(`โœ… Session ${sessionId.substring(0, 8)}... validated via source for ${deviceName}`);
221
- return true;
222
-
223
- } catch (sourceError) {
224
- this.logger.debug(`Source validation failed for ${deviceName}: ${sourceError.message}`);
225
- }
226
-
227
- return false;
228
-
229
- } catch (error) {
230
- this.logger.debug(`โŒ Session ${sessionId?.substring(0, 8) || 'null'}... validation failed for ${deviceName}: ${error.message}`);
231
- return false;
232
- }
233
- }
234
-
235
- /**
236
- * ๐ŸŽฏ REGISTER DEVICE PORT: Store port mapping and sync with universal manager
237
- */
238
- setDevicePort(deviceName, port) {
239
- this.devicePorts.set(deviceName, port);
240
- this.logger.debug(`๐Ÿ“ Port mapping registered: ${deviceName} โ†’ ${port}`);
241
-
242
- // Also register in global session manager if available
243
- if (global.sessionManager) {
244
- // Find device by name in connected devices to get UDID
245
- let device = null;
246
-
247
- // Try multiple ways to find the device
248
- if (global.connectedDevices) {
249
- device = global.connectedDevices.find(d => d.name === deviceName);
250
- }
251
-
252
- // Fallback: check if we have a connected devices reference in the session manager
253
- if (!device && this.connectedDevices) {
254
- device = this.connectedDevices.find(d => d.name === deviceName);
255
- }
256
-
257
- if (device?.udid) {
258
- try {
259
- global.sessionManager.updateDevicePort(device.udid, port);
260
- this.logger.debug(`๐Ÿ“ Synced port mapping to global session manager: ${deviceName} โ†’ ${port}`);
261
- } catch (error) {
262
- // Non-critical error
263
- this.logger.debug(`โš ๏ธ Could not sync to global session manager: ${error.message}`);
264
- }
265
- } else {
266
- this.logger.debug(`โš ๏ธ Could not find device ${deviceName} to sync port mapping`);
267
- }
268
- }
269
- }
270
-
271
- /**
272
- * ๐ŸŽฏ REMOVE DEVICE: Clean up port mapping
273
- */
274
- removeDevice(deviceName) {
275
- this.devicePorts.delete(deviceName);
276
- this.logger.debug(`๐Ÿงน Port mapping removed for ${deviceName}`);
277
- }
278
-
279
- /**
280
- * ๐ŸŽฏ SMART PORT GUESSING: Guess port based on device name patterns
281
- */
282
- guessPortFromName(deviceName) {
283
- // Common port patterns based on device names
284
- if (deviceName.toLowerCase().includes('ipad') && !deviceName.toLowerCase().includes('pro')) {
285
- return 8101; // Regular iPads typically on 8101
286
- }
287
-
288
- if (deviceName.toLowerCase().includes('iphone')) {
289
- return 8100; // iPhones typically on 8100
290
- }
291
-
292
- // Check if it's likely the second device
293
- if (deviceName.toLowerCase().includes('pro') || deviceName.toLowerCase().includes('suresh')) {
294
- return 8101; // Second devices typically on 8101
295
- }
296
-
297
- // Default to 8100
298
- return 8100;
299
- }
300
-
301
- /**
302
- * ๐ŸŽฏ GET SESSION WITH AUTO-RETRY: Robust session getter with options
303
- */
304
- async getSessionWithRetry(deviceName, port = null, maxRetries = 2, skipValidation = false) {
305
- let lastError;
306
-
307
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
308
- try {
309
- const sessionId = await this.getLiveSessionId(deviceName, port);
310
-
311
- // Skip validation if requested (for more aggressive session usage)
312
- if (skipValidation) {
313
- this.logger.debug(`โœ… Session acquired (validation skipped): ${sessionId.substring(0, 8)}... for ${deviceName}`);
314
- return sessionId;
315
- }
316
-
317
- // Validate the session works
318
- const isValid = await this.validateSession(sessionId, deviceName, port);
319
-
320
- if (isValid) {
321
- return sessionId;
322
- } else {
323
- throw new Error('Session validation failed');
324
- }
325
-
326
- } catch (error) {
327
- lastError = error;
328
-
329
- if (attempt < maxRetries) {
330
- this.logger.warn(`โš ๏ธ Session attempt ${attempt} failed for ${deviceName}, retrying... (${error.message})`);
331
-
332
- // Wait a bit before retry
333
- await new Promise(resolve => setTimeout(resolve, 1000));
334
- }
335
- }
336
- }
337
-
338
- throw new Error(`Failed to get valid session for ${deviceName} after ${maxRetries} attempts: ${lastError.message}`);
339
- }
340
-
341
- /**
342
- * ๐ŸŽฏ GET ALL ACTIVE SESSIONS: For debugging/monitoring
343
- */
344
- async getAllActiveSessions() {
345
- const activeSessions = {};
346
-
347
- for (const [deviceName, port] of this.devicePorts.entries()) {
348
- try {
349
- const sessionId = await this.getLiveSessionId(deviceName, port);
350
- activeSessions[deviceName] = {
351
- port,
352
- sessionId,
353
- status: 'active'
354
- };
355
- } catch (error) {
356
- activeSessions[deviceName] = {
357
- port,
358
- sessionId: null,
359
- status: 'inactive',
360
- error: error.message
361
- };
362
- }
363
- }
364
-
365
- return activeSessions;
366
- }
367
- }
368
-
369
- // Export singleton instance
370
- module.exports = new UniversalSessionManager();