@xenon-device-management/xenon 1.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 (228) hide show
  1. package/README.md +446 -0
  2. package/lib/package.json +207 -0
  3. package/lib/public/assets/Layouts-7IT8aFLI.js +11 -0
  4. package/lib/public/assets/Layouts-DPMls9vh.css +1 -0
  5. package/lib/public/assets/ai-settings-BbnfgdEx.js +11 -0
  6. package/lib/public/assets/apps-CRMrI4_p.js +16 -0
  7. package/lib/public/assets/apps-CcM77dgg.css +1 -0
  8. package/lib/public/assets/badge-B1nKs8zj.css +1 -0
  9. package/lib/public/assets/badge-CSvl5xIU.js +11 -0
  10. package/lib/public/assets/button-CJlKn4PZ.css +1 -0
  11. package/lib/public/assets/button-CvLaGFYj.js +26 -0
  12. package/lib/public/assets/calendar-6w-D6Oaw.js +6 -0
  13. package/lib/public/assets/clock-DcdeWBPr.js +6 -0
  14. package/lib/public/assets/cpu-DiSoXT9n.js +6 -0
  15. package/lib/public/assets/device-explorer-CajM63OJ.js +193 -0
  16. package/lib/public/assets/device-explorer-CxdUAoTL.css +1 -0
  17. package/lib/public/assets/index-ByQwMN5T.js +174 -0
  18. package/lib/public/assets/index-C1DBaoSh.js +1 -0
  19. package/lib/public/assets/index-qzCez_kk.css +1 -0
  20. package/lib/public/assets/lock-B23ibZmo.js +6 -0
  21. package/lib/public/assets/maintenance-settings-CirzA6yG.js +6 -0
  22. package/lib/public/assets/mouse-pointer-2-Cz76SHFb.js +6 -0
  23. package/lib/public/assets/plus-BBwlIevt.js +6 -0
  24. package/lib/public/assets/session-dashboard-C2k7FFv_.css +1 -0
  25. package/lib/public/assets/session-dashboard-HPDtwPOZ.js +62 -0
  26. package/lib/public/assets/settings-DrZsZwdc.js +1 -0
  27. package/lib/public/assets/trash-2-DQpvzJec.js +6 -0
  28. package/lib/public/assets/useSocket-Dxsqae2a.js +16 -0
  29. package/lib/public/assets/webhook-settings-CDPgsgkb.css +1 -0
  30. package/lib/public/assets/webhook-settings-Cp-B4Nrw.js +1 -0
  31. package/lib/public/assets/zap-DovP6iow.js +6 -0
  32. package/lib/public/favicon.ico +0 -0
  33. package/lib/public/favicon.png +0 -0
  34. package/lib/public/favicon.svg +9 -0
  35. package/lib/public/index.html +46 -0
  36. package/lib/public/logo.svg +17 -0
  37. package/lib/public/logo192.png +0 -0
  38. package/lib/public/logo512.png +0 -0
  39. package/lib/public/manifest.json +25 -0
  40. package/lib/public/robots.txt +3 -0
  41. package/lib/schema.json +348 -0
  42. package/lib/src/InternalHttpClient.js +212 -0
  43. package/lib/src/PluginContext.js +29 -0
  44. package/lib/src/XenonCapabilityManager.js +199 -0
  45. package/lib/src/app/index.js +167 -0
  46. package/lib/src/app/routers/apps.js +79 -0
  47. package/lib/src/app/routers/config.js +131 -0
  48. package/lib/src/app/routers/control.js +835 -0
  49. package/lib/src/app/routers/dashboard.js +301 -0
  50. package/lib/src/app/routers/grid.js +352 -0
  51. package/lib/src/app/routers/reservation.js +190 -0
  52. package/lib/src/app/routers/webhook.js +83 -0
  53. package/lib/src/app/swagger-docs.js +203 -0
  54. package/lib/src/app/swagger.js +366 -0
  55. package/lib/src/chromeUtils.js +148 -0
  56. package/lib/src/commands/handle.js +19 -0
  57. package/lib/src/commands/index.js +8 -0
  58. package/lib/src/config.js +73 -0
  59. package/lib/src/dashboard/asset-manager.js +84 -0
  60. package/lib/src/dashboard/commands.js +284 -0
  61. package/lib/src/dashboard/event-manager.js +699 -0
  62. package/lib/src/dashboard/services/app-service.js +134 -0
  63. package/lib/src/dashboard/services/failure-analysis-service.js +173 -0
  64. package/lib/src/dashboard/services/session-service.js +113 -0
  65. package/lib/src/data-service/CircuitBreaker.js +83 -0
  66. package/lib/src/data-service/config-service.js +155 -0
  67. package/lib/src/data-service/db.js +122 -0
  68. package/lib/src/data-service/device-service.js +320 -0
  69. package/lib/src/data-service/device-store.interface.js +2 -0
  70. package/lib/src/data-service/device-store.js +345 -0
  71. package/lib/src/data-service/pending-sessions-service.js +25 -0
  72. package/lib/src/data-service/pluginArgs.js +25 -0
  73. package/lib/src/data-service/prisma-service.js +31 -0
  74. package/lib/src/data-service/prisma-store.js +385 -0
  75. package/lib/src/data-service/queue-service.js +150 -0
  76. package/lib/src/data-service/web-config-service.js +130 -0
  77. package/lib/src/device-managers/AndroidDeviceManager.js +1155 -0
  78. package/lib/src/device-managers/ChromeDriverManager.js +68 -0
  79. package/lib/src/device-managers/HealthMonitorService.js +325 -0
  80. package/lib/src/device-managers/IOSDeviceManager.js +351 -0
  81. package/lib/src/device-managers/NodeDevices.js +82 -0
  82. package/lib/src/device-managers/android/AndroidStreamService.js +370 -0
  83. package/lib/src/device-managers/android/DeviceLockManager.js +45 -0
  84. package/lib/src/device-managers/cloud/CapabilityManager.js +26 -0
  85. package/lib/src/device-managers/cloud/Devices.js +86 -0
  86. package/lib/src/device-managers/iOSTracker.js +44 -0
  87. package/lib/src/device-managers/index.js +89 -0
  88. package/lib/src/device-managers/ios/IOSDiscoveryService.js +268 -0
  89. package/lib/src/device-managers/ios/IOSStreamService.js +893 -0
  90. package/lib/src/device-managers/ios/WDAClient.js +866 -0
  91. package/lib/src/device-utils.js +663 -0
  92. package/lib/src/enums/Capabilities.js +8 -0
  93. package/lib/src/enums/Cloud.js +11 -0
  94. package/lib/src/enums/Platform.js +9 -0
  95. package/lib/src/enums/SessionType.js +9 -0
  96. package/lib/src/enums/SocketEvents.js +15 -0
  97. package/lib/src/helpers/UniversalMjpegProxy.js +273 -0
  98. package/lib/src/helpers/index.js +229 -0
  99. package/lib/src/index.js +95 -0
  100. package/lib/src/interceptors/CommandInterceptor.js +524 -0
  101. package/lib/src/interfaces/ICloudManager.js +2 -0
  102. package/lib/src/interfaces/IDevice.js +2 -0
  103. package/lib/src/interfaces/IDeviceFilterOptions.js +2 -0
  104. package/lib/src/interfaces/IDeviceManager.js +2 -0
  105. package/lib/src/interfaces/IOptions.js +2 -0
  106. package/lib/src/interfaces/IPluginArgs.js +55 -0
  107. package/lib/src/interfaces/ISessionCapability.js +2 -0
  108. package/lib/src/logger.js +225 -0
  109. package/lib/src/plugin.js +244 -0
  110. package/lib/src/prisma.js +12 -0
  111. package/lib/src/profiling/AndroidAppProfiler.js +213 -0
  112. package/lib/src/proxy/wd-command-proxy.js +221 -0
  113. package/lib/src/scripts/generate-database-migration.js +59 -0
  114. package/lib/src/scripts/initialize-database.js +55 -0
  115. package/lib/src/scripts/install-go-ios.js +66 -0
  116. package/lib/src/scripts/prepare-prisma.js +89 -0
  117. package/lib/src/services/AICommandService.js +143 -0
  118. package/lib/src/services/AIService.js +466 -0
  119. package/lib/src/services/CleanupService.js +141 -0
  120. package/lib/src/services/EventBus.js +74 -0
  121. package/lib/src/services/InspectorService.js +395 -0
  122. package/lib/src/services/MetricsService.js +134 -0
  123. package/lib/src/services/NetworkConditioningService.js +173 -0
  124. package/lib/src/services/NotificationService.js +163 -0
  125. package/lib/src/services/RequestLogService.js +252 -0
  126. package/lib/src/services/ResourceIsolationService.js +122 -0
  127. package/lib/src/services/SecurityService.js +120 -0
  128. package/lib/src/services/ServerManager.js +284 -0
  129. package/lib/src/services/SessionHeartbeatService.js +158 -0
  130. package/lib/src/services/SessionLifecycleService.js +572 -0
  131. package/lib/src/services/SocketClient.js +71 -0
  132. package/lib/src/services/SocketServer.js +87 -0
  133. package/lib/src/services/TracingService.js +132 -0
  134. package/lib/src/services/VideoPipelineService.js +220 -0
  135. package/lib/src/services/healing/FuzzyXmlHealingProvider.js +333 -0
  136. package/lib/src/services/healing/HealEtalonService.js +98 -0
  137. package/lib/src/services/healing/HealedLocatorGenerator.js +132 -0
  138. package/lib/src/services/healing/HealingOrchestrator.js +165 -0
  139. package/lib/src/services/healing/LlmHealingProvider.js +77 -0
  140. package/lib/src/services/healing/OcrHealingProvider.js +119 -0
  141. package/lib/src/services/healing/ResilioTreeHealingProvider.js +100 -0
  142. package/lib/src/services/healing/VisualAiHealingProvider.js +90 -0
  143. package/lib/src/services/healing/types.js +12 -0
  144. package/lib/src/services/omni-vision/OmniVisionService.js +718 -0
  145. package/lib/src/services/omni-vision/VisionAssertionService.js +68 -0
  146. package/lib/src/sessions/CloudSession.js +42 -0
  147. package/lib/src/sessions/LocalSession.js +313 -0
  148. package/lib/src/sessions/RemoteSession.js +287 -0
  149. package/lib/src/sessions/SessionManager.js +238 -0
  150. package/lib/src/sessions/XenonSession.js +44 -0
  151. package/lib/src/types/CLIArgs.js +2 -0
  152. package/lib/src/types/CloudArgs.js +2 -0
  153. package/lib/src/types/CloudSchema.js +131 -0
  154. package/lib/src/types/DeviceType.js +2 -0
  155. package/lib/src/types/DeviceUpdate.js +2 -0
  156. package/lib/src/types/IOSDevice.js +2 -0
  157. package/lib/src/types/Platform.js +2 -0
  158. package/lib/src/types/SessionStatus.js +11 -0
  159. package/lib/src/validators/CapabilityValidator.js +93 -0
  160. package/lib/test/e2e/android/conf.spec.js +43 -0
  161. package/lib/test/e2e/android/conf2.spec.js +44 -0
  162. package/lib/test/e2e/android/conf3.spec.js +44 -0
  163. package/lib/test/e2e/e2ehelper.js +113 -0
  164. package/lib/test/e2e/hubnode/forward-request.spec.js +224 -0
  165. package/lib/test/e2e/hubnode/hubnode.spec.js +214 -0
  166. package/lib/test/e2e/ios/conf1.spec.js +39 -0
  167. package/lib/test/e2e/ios/conf2.spec.js +39 -0
  168. package/lib/test/e2e/plugin-harness.js +236 -0
  169. package/lib/test/e2e/plugin.spec.js +97 -0
  170. package/lib/test/e2e/telemetry_verification.spec.js +83 -0
  171. package/lib/test/e2e/video-recording-test.spec.js +63 -0
  172. package/lib/test/helpers/test-container.js +112 -0
  173. package/lib/test/integration/androidDevices.spec.js +137 -0
  174. package/lib/test/integration/cliArgs.js +73 -0
  175. package/lib/test/integration/ios/01iOSSimulator.spec.js +291 -0
  176. package/lib/test/integration/ios/02iOSDevices.spec.js +75 -0
  177. package/lib/test/integration/testHelpers.js +74 -0
  178. package/lib/test/unit/AndroidDeviceManager.spec.js +178 -0
  179. package/lib/test/unit/ChromeDriverManager.spec.js +26 -0
  180. package/lib/test/unit/CleanupService.spec.js +21 -0
  181. package/lib/test/unit/DeviceModel.spec.js +157 -0
  182. package/lib/test/unit/FuzzyXmlHealingProvider.test.js +294 -0
  183. package/lib/test/unit/GetAdbOriginal.js +42 -0
  184. package/lib/test/unit/HealingCascade.test.js +128 -0
  185. package/lib/test/unit/IOSDeviceManager.spec.js +261 -0
  186. package/lib/test/unit/RemoteIOs.spec.js +78 -0
  187. package/lib/test/unit/ResilioTreeHealingProvider.test.js +96 -0
  188. package/lib/test/unit/commands.spec.js +27 -0
  189. package/lib/test/unit/config.spec.js +27 -0
  190. package/lib/test/unit/device-service.spec.js +307 -0
  191. package/lib/test/unit/device-utils.spec.js +313 -0
  192. package/lib/test/unit/fixtures/device.config.js +4 -0
  193. package/lib/test/unit/fixtures/devices.js +89 -0
  194. package/lib/test/unit/helpers.spec.js +62 -0
  195. package/lib/test/unit/omni-vision.spec.js +100 -0
  196. package/lib/test/unit/plugin.spec.js +133 -0
  197. package/lib/tsconfig.tsbuildinfo +1 -0
  198. package/package.json +207 -0
  199. package/prisma/data.db +0 -0
  200. package/prisma/dev.db +0 -0
  201. package/prisma/dev.db-journal +0 -0
  202. package/prisma/migrations/20231011074725_initial_tables/migration.sql +47 -0
  203. package/prisma/migrations/20231226115334_update_session_log/migration.sql +2 -0
  204. package/prisma/migrations/20251204113710_add_video_recording_enabled/migration.sql +29 -0
  205. package/prisma/migrations/20251204132449_add_log_table/migration.sql +11 -0
  206. package/prisma/migrations/20251205050111_add_profiling_support/migration.sql +47 -0
  207. package/prisma/migrations/20251205050947_add_is_error_field/migration.sql +24 -0
  208. package/prisma/migrations/20260126201337_add_app_model/migration.sql +18 -0
  209. package/prisma/migrations/20260130115722_add_performance_trace_and_xenon_sync/migration.sql +2 -0
  210. package/prisma/migrations/20260130135114_add_device_models/migration.sql +57 -0
  211. package/prisma/migrations/20260130140655_make_systemport_optional/migration.sql +45 -0
  212. package/prisma/migrations/20260130140932_make_device_fields_optional/migration.sql +45 -0
  213. package/prisma/migrations/20260130141040_final_schema_fix/migration.sql +45 -0
  214. package/prisma/migrations/20260130143234_add_device_health_fields/migration.sql +4 -0
  215. package/prisma/migrations/20260130144921_add_failure_category/migration.sql +2 -0
  216. package/prisma/migrations/20260131151456_add_webhook_config/migration.sql +10 -0
  217. package/prisma/migrations/20260201094507_add_device_tags/migration.sql +11 -0
  218. package/prisma/migrations/20260201103410_add_managed_process/migration.sql +15 -0
  219. package/prisma/migrations/20260201140637_add_web_config/migration.sql +22 -0
  220. package/prisma/migrations/20260201162232_add_session_progress/migration.sql +2 -0
  221. package/prisma/migrations/20260201174231_add_total_healed_count/migration.sql +2 -0
  222. package/prisma/migrations/migration_lock.toml +3 -0
  223. package/prisma/schema.prisma +210 -0
  224. package/schema.json +348 -0
  225. package/scripts/build-xenon.sh +32 -0
  226. package/scripts/dev/debug-gemini.ts +44 -0
  227. package/scripts/generate-types-from-schema.js +86 -0
  228. package/scripts/install-compatible-driver.js +39 -0
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.prepareDirectory = prepareDirectory;
40
+ exports.saveScreenShot = saveScreenShot;
41
+ exports.saveVideoRecording = saveVideoRecording;
42
+ exports.savePerformanceTrace = savePerformanceTrace;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const config_1 = require("../config");
46
+ const uuid_1 = require("uuid");
47
+ const logger_1 = __importDefault(require("../logger"));
48
+ const SCREENSHOT_DIRECTORY = 'screenshots';
49
+ const VIDEO_DIRECTORY = 'video';
50
+ const PERFORMANCE_DIRECTORY = 'performance';
51
+ function prepareDirectory(sessionId) {
52
+ [SCREENSHOT_DIRECTORY, VIDEO_DIRECTORY, PERFORMANCE_DIRECTORY].forEach((folder) => {
53
+ fs.mkdirSync(path.join(config_1.config.sessionAssetsPath, sessionId, folder), { recursive: true });
54
+ });
55
+ }
56
+ function saveScreenShot(sessionId, screenshotBase64String) {
57
+ const directory = path.join(config_1.config.sessionAssetsPath, sessionId, SCREENSHOT_DIRECTORY);
58
+ if (!fs.existsSync(directory)) {
59
+ fs.mkdirSync(directory, { recursive: true });
60
+ }
61
+ const assetPath = path.join(sessionId, SCREENSHOT_DIRECTORY, `${(0, uuid_1.v4)()}.png`);
62
+ const fullPath = path.join(config_1.config.sessionAssetsPath, assetPath);
63
+ fs.writeFileSync(fullPath, screenshotBase64String, 'base64');
64
+ logger_1.default.info(`[AssetManager] Saved screenshot for session ${sessionId} at ${fullPath}`);
65
+ return assetPath;
66
+ }
67
+ function saveVideoRecording(sessionId, videoBase64String) {
68
+ const directory = path.join(config_1.config.sessionAssetsPath, sessionId, VIDEO_DIRECTORY);
69
+ if (!fs.existsSync(directory)) {
70
+ fs.mkdirSync(directory, { recursive: true });
71
+ }
72
+ const assetPath = path.join(sessionId, VIDEO_DIRECTORY, `${sessionId}.mp4`);
73
+ fs.writeFileSync(path.join(config_1.config.sessionAssetsPath, assetPath), videoBase64String, 'base64');
74
+ return assetPath;
75
+ }
76
+ function savePerformanceTrace(sessionId, traceBase64String) {
77
+ const directory = path.join(config_1.config.sessionAssetsPath, sessionId, PERFORMANCE_DIRECTORY);
78
+ if (!fs.existsSync(directory)) {
79
+ fs.mkdirSync(directory, { recursive: true });
80
+ }
81
+ const assetPath = path.join(sessionId, PERFORMANCE_DIRECTORY, `${sessionId}.zip`);
82
+ fs.writeFileSync(path.join(config_1.config.sessionAssetsPath, assetPath), traceBase64String, 'base64');
83
+ return assetPath;
84
+ }
@@ -0,0 +1,284 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.dashboardCommands = exports.DashboardCommands = void 0;
49
+ const session_service_1 = require("./services/session-service");
50
+ const prisma_1 = require("../prisma");
51
+ const logger_1 = __importDefault(require("../logger"));
52
+ const lodash_1 = __importDefault(require("lodash"));
53
+ const SessionManager_1 = require("../sessions/SessionManager");
54
+ const asset_manager_1 = require("./asset-manager");
55
+ class DashboardCommands {
56
+ isDashboardCommand(commandName) {
57
+ return commandName.startsWith('xenon') || commandName.startsWith('xe');
58
+ }
59
+ process(sessionId, request, response) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ const { script } = request.body;
62
+ logger_1.default.info(`[DashboardCommands] Processing command: ${script}`);
63
+ if (!script) {
64
+ return this.sendSuccessResponse(response);
65
+ }
66
+ const commandName = script.split(':')[1];
67
+ logger_1.default.info(`[DashboardCommands] Parsed command name: ${commandName}`);
68
+ if (commandName && commandName.trim()) {
69
+ const trimmedCommand = commandName.trim();
70
+ logger_1.default.info(`[DashboardCommands] Trimmed command: ${trimmedCommand}`);
71
+ switch (trimmedCommand) {
72
+ case 'setSessionName':
73
+ logger_1.default.info('[DashboardCommands] Executing setSessionName');
74
+ return yield this.setSessionName(sessionId, request, response);
75
+ case 'setSessionStatus':
76
+ logger_1.default.info('[DashboardCommands] Executing setSessionStatus');
77
+ return yield this.setSessionStatus(sessionId, request, response);
78
+ case 'debug':
79
+ logger_1.default.info('[DashboardCommands] Executing debug command');
80
+ return yield this.debug(sessionId, request, response);
81
+ case 'captureEvidence':
82
+ logger_1.default.info('[DashboardCommands] Executing captureEvidence');
83
+ return yield this.captureEvidence(sessionId, request, response);
84
+ case 'addTag':
85
+ logger_1.default.info('[DashboardCommands] Executing addTag');
86
+ return yield this.addTag(sessionId, request, response);
87
+ default:
88
+ logger_1.default.warn(`[DashboardCommands] Unknown command: ${trimmedCommand}`);
89
+ return this.sendSuccessResponse(response);
90
+ }
91
+ }
92
+ return this.sendSuccessResponse(response);
93
+ });
94
+ }
95
+ sendSuccessResponse(response) {
96
+ return response.status(200).json({ value: null });
97
+ }
98
+ /* Commands */
99
+ /**
100
+ * Set the name of current test(session)
101
+ *
102
+ * driver.executeScript("xenon: setSessionName", "MyTestName")
103
+ * or
104
+ * driver.executeScript("xenon: setSessionName", {"name": "MyTestName"})
105
+ */
106
+ setSessionName(sessionId, request, response) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ const { args } = request.body;
109
+ yield (0, session_service_1.updateSessionDetails)(sessionId, {
110
+ name: typeof args[0] === 'object' && args[0].name ? args[0].name : args[0],
111
+ });
112
+ return this.sendSuccessResponse(response);
113
+ });
114
+ }
115
+ /**
116
+ * Update the status of the session
117
+ *
118
+ * driver.executeScript("xenon: setSessionStatus", {"status": "passed/failed", "reason": "optional reason"})
119
+ */
120
+ setSessionStatus(sessionId, request, response) {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ const { args } = request.body;
123
+ let statusArg = {};
124
+ if (lodash_1.default.isArray(args)) {
125
+ if (typeof args[0] === 'object') {
126
+ statusArg = args[0];
127
+ }
128
+ else {
129
+ // Handle positional: executeScript("xe:setSessionStatus", "failed", "reason")
130
+ statusArg = {
131
+ status: args[0],
132
+ reason: args[1],
133
+ };
134
+ }
135
+ }
136
+ else if (typeof args === 'object') {
137
+ statusArg = args;
138
+ }
139
+ // Normalize input
140
+ const inputStatus = (statusArg.status || '').toLowerCase();
141
+ const validStatuses = ['success', 'failed', 'passed'];
142
+ if (!validStatuses.includes(inputStatus)) {
143
+ logger_1.default.warn(`[DashboardCommands] Invalid status: ${statusArg.status}. Valid: ${validStatuses.join(', ')}`);
144
+ return this.sendSuccessResponse(response);
145
+ }
146
+ // Normalize 'passed' to 'success' for consistency with SessionStatus enum
147
+ const normalizedStatus = inputStatus === 'passed' ? 'success' : inputStatus;
148
+ yield (0, session_service_1.updateSessionDetails)(sessionId, {
149
+ status: normalizedStatus,
150
+ failure_reason: statusArg.reason || undefined,
151
+ });
152
+ // --- REAL-TIME UI UPDATE ---
153
+ // Principal Speed: Emit a socket event so the dashboard row updates immediately.
154
+ const { SocketServer } = yield Promise.resolve().then(() => __importStar(require('../services/SocketServer')));
155
+ const { Container } = yield Promise.resolve().then(() => __importStar(require('typedi')));
156
+ const { SocketEvents } = yield Promise.resolve().then(() => __importStar(require('../enums/SocketEvents')));
157
+ Container.get(SocketServer).emitToDashboard(SocketEvents.SESSION_STOPPED, {
158
+ id: sessionId,
159
+ status: normalizedStatus,
160
+ failure_reason: args.reason || undefined,
161
+ });
162
+ return this.sendSuccessResponse(response);
163
+ });
164
+ }
165
+ /**
166
+ * Add debug logs to the session
167
+ *
168
+ * driver.executeScript("xenon: debug", {"message": "Debug message"})
169
+ * or
170
+ * driver.executeScript("xenon: debug", "Debug message")
171
+ */
172
+ debug(sessionId, request, response) {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ const { args } = request.body;
175
+ const logData = lodash_1.default.isArray(args) ? args[0] : args;
176
+ // Support both string and object format
177
+ const message = typeof logData === 'string' ? logData : logData.message || JSON.stringify(logData);
178
+ yield prisma_1.prisma.log.create({
179
+ data: {
180
+ session_id: sessionId,
181
+ log_type: 'DEBUG',
182
+ message: message,
183
+ },
184
+ });
185
+ return this.sendSuccessResponse(response);
186
+ });
187
+ }
188
+ /**
189
+ * Capture evidence (screenshot) with optional reason/label
190
+ *
191
+ * driver.executeScript("xenon: captureEvidence", {"reason": "Login failed", "label": "error_state"})
192
+ * or
193
+ * driver.executeScript("xenon: captureEvidence", "Checkpoint reached")
194
+ */
195
+ captureEvidence(sessionId, request, response) {
196
+ return __awaiter(this, void 0, void 0, function* () {
197
+ const { args } = request.body;
198
+ const evidenceData = lodash_1.default.isArray(args) ? args[0] : args;
199
+ const reason = typeof evidenceData === 'string' ? evidenceData : evidenceData.reason || 'Manual capture';
200
+ const label = typeof evidenceData === 'object' ? evidenceData.label : undefined;
201
+ try {
202
+ const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
203
+ if (!session) {
204
+ logger_1.default.warn(`[DashboardCommands] captureEvidence: Session ${sessionId} not found`);
205
+ return this.sendSuccessResponse(response);
206
+ }
207
+ const screenshotBase64 = yield session.getScreenShot();
208
+ if (screenshotBase64) {
209
+ const screenshotPath = (0, asset_manager_1.saveScreenShot)(sessionId, screenshotBase64);
210
+ // Log the evidence capture
211
+ yield prisma_1.prisma.sessionLog.create({
212
+ data: {
213
+ session_id: sessionId,
214
+ command_name: 'captureEvidence',
215
+ body: JSON.stringify({ reason, label }),
216
+ response: JSON.stringify({ captured: true }),
217
+ is_success: true,
218
+ is_error: false,
219
+ method: 'POST',
220
+ title: 'Evidence Captured',
221
+ subtitle: reason,
222
+ screenshot: screenshotPath,
223
+ url: '/execute/sync',
224
+ },
225
+ });
226
+ logger_1.default.info(`[DashboardCommands] Evidence captured for ${sessionId}: ${reason}`);
227
+ }
228
+ }
229
+ catch (err) {
230
+ logger_1.default.error(`[DashboardCommands] captureEvidence failed: ${err.message}`);
231
+ }
232
+ return this.sendSuccessResponse(response);
233
+ });
234
+ }
235
+ /**
236
+ * Add searchable tags to the session
237
+ *
238
+ * driver.executeScript("xenon: addTag", {"tag": "regression"})
239
+ * or
240
+ * driver.executeScript("xenon: addTag", "smoke-test")
241
+ */
242
+ addTag(sessionId, request, response) {
243
+ return __awaiter(this, void 0, void 0, function* () {
244
+ const { args } = request.body;
245
+ const tagData = lodash_1.default.isArray(args) ? args[0] : args;
246
+ const newTag = typeof tagData === 'string' ? tagData : tagData.tag;
247
+ if (!newTag) {
248
+ logger_1.default.warn('[DashboardCommands] addTag: No tag provided');
249
+ return this.sendSuccessResponse(response);
250
+ }
251
+ try {
252
+ // Get current session to append tag
253
+ const session = yield prisma_1.prisma.session.findUnique({
254
+ where: { id: sessionId },
255
+ select: { tags: true },
256
+ });
257
+ // Parse existing tags or initialize empty array
258
+ let existingTags = [];
259
+ if (session === null || session === void 0 ? void 0 : session.tags) {
260
+ try {
261
+ existingTags = JSON.parse(session.tags);
262
+ }
263
+ catch (_a) {
264
+ existingTags = [];
265
+ }
266
+ }
267
+ // Add new tag if not already present
268
+ if (!existingTags.includes(newTag)) {
269
+ existingTags.push(newTag);
270
+ yield (0, session_service_1.updateSessionDetails)(sessionId, {
271
+ tags: JSON.stringify(existingTags),
272
+ });
273
+ logger_1.default.info(`[DashboardCommands] Tag added to ${sessionId}: ${newTag}`);
274
+ }
275
+ }
276
+ catch (err) {
277
+ logger_1.default.error(`[DashboardCommands] addTag failed: ${err.message}`);
278
+ }
279
+ return this.sendSuccessResponse(response);
280
+ });
281
+ }
282
+ }
283
+ exports.DashboardCommands = DashboardCommands;
284
+ exports.dashboardCommands = new DashboardCommands();