@aiscene/aiserver 1.0.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 (169) hide show
  1. package/dist/api/callback.d.ts +7 -0
  2. package/dist/api/callback.d.ts.map +1 -0
  3. package/dist/api/callback.js +116 -0
  4. package/dist/api/callback.js.map +1 -0
  5. package/dist/api/device-api.d.ts +13 -0
  6. package/dist/api/device-api.d.ts.map +1 -0
  7. package/dist/api/device-api.js +98 -0
  8. package/dist/api/device-api.js.map +1 -0
  9. package/dist/api/task-api.d.ts +9 -0
  10. package/dist/api/task-api.d.ts.map +1 -0
  11. package/dist/api/task-api.js +47 -0
  12. package/dist/api/task-api.js.map +1 -0
  13. package/dist/config/cli.d.ts +30 -0
  14. package/dist/config/cli.d.ts.map +1 -0
  15. package/dist/config/cli.js +129 -0
  16. package/dist/config/cli.js.map +1 -0
  17. package/dist/config/index.d.ts +6 -0
  18. package/dist/config/index.d.ts.map +1 -0
  19. package/dist/config/index.js +142 -0
  20. package/dist/config/index.js.map +1 -0
  21. package/dist/config/schema.d.ts +66 -0
  22. package/dist/config/schema.d.ts.map +1 -0
  23. package/dist/config/schema.js +2 -0
  24. package/dist/config/schema.js.map +1 -0
  25. package/dist/core/event-bus.d.ts +14 -0
  26. package/dist/core/event-bus.d.ts.map +1 -0
  27. package/dist/core/event-bus.js +33 -0
  28. package/dist/core/event-bus.js.map +1 -0
  29. package/dist/core/logger.d.ts +24 -0
  30. package/dist/core/logger.d.ts.map +1 -0
  31. package/dist/core/logger.js +52 -0
  32. package/dist/core/logger.js.map +1 -0
  33. package/dist/core/types.d.ts +134 -0
  34. package/dist/core/types.d.ts.map +1 -0
  35. package/dist/core/types.js +3 -0
  36. package/dist/core/types.js.map +1 -0
  37. package/dist/debug/dump-manager.d.ts +10 -0
  38. package/dist/debug/dump-manager.d.ts.map +1 -0
  39. package/dist/debug/dump-manager.js +52 -0
  40. package/dist/debug/dump-manager.js.map +1 -0
  41. package/dist/debug/screencast.d.ts +11 -0
  42. package/dist/debug/screencast.d.ts.map +1 -0
  43. package/dist/debug/screencast.js +88 -0
  44. package/dist/debug/screencast.js.map +1 -0
  45. package/dist/debug/session-manager.d.ts +14 -0
  46. package/dist/debug/session-manager.d.ts.map +1 -0
  47. package/dist/debug/session-manager.js +76 -0
  48. package/dist/debug/session-manager.js.map +1 -0
  49. package/dist/debug/types.d.ts +76 -0
  50. package/dist/debug/types.d.ts.map +1 -0
  51. package/dist/debug/types.js +2 -0
  52. package/dist/debug/types.js.map +1 -0
  53. package/dist/debug/web-screencast.d.ts +60 -0
  54. package/dist/debug/web-screencast.d.ts.map +1 -0
  55. package/dist/debug/web-screencast.js +146 -0
  56. package/dist/debug/web-screencast.js.map +1 -0
  57. package/dist/debug/websocket-server.d.ts +27 -0
  58. package/dist/debug/websocket-server.d.ts.map +1 -0
  59. package/dist/debug/websocket-server.js +681 -0
  60. package/dist/debug/websocket-server.js.map +1 -0
  61. package/dist/device/detector.d.ts +10 -0
  62. package/dist/device/detector.d.ts.map +1 -0
  63. package/dist/device/detector.js +100 -0
  64. package/dist/device/detector.js.map +1 -0
  65. package/dist/device/heartbeat.d.ts +26 -0
  66. package/dist/device/heartbeat.d.ts.map +1 -0
  67. package/dist/device/heartbeat.js +225 -0
  68. package/dist/device/heartbeat.js.map +1 -0
  69. package/dist/device/status-manager.d.ts +15 -0
  70. package/dist/device/status-manager.d.ts.map +1 -0
  71. package/dist/device/status-manager.js +58 -0
  72. package/dist/device/status-manager.js.map +1 -0
  73. package/dist/device/types.d.ts +30 -0
  74. package/dist/device/types.d.ts.map +1 -0
  75. package/dist/device/types.js +2 -0
  76. package/dist/device/types.js.map +1 -0
  77. package/dist/executor/action-executor.d.ts +25 -0
  78. package/dist/executor/action-executor.d.ts.map +1 -0
  79. package/dist/executor/action-executor.js +261 -0
  80. package/dist/executor/action-executor.js.map +1 -0
  81. package/dist/executor/android-executor.d.ts +12 -0
  82. package/dist/executor/android-executor.d.ts.map +1 -0
  83. package/dist/executor/android-executor.js +127 -0
  84. package/dist/executor/android-executor.js.map +1 -0
  85. package/dist/executor/base.d.ts +20 -0
  86. package/dist/executor/base.d.ts.map +1 -0
  87. package/dist/executor/base.js +91 -0
  88. package/dist/executor/base.js.map +1 -0
  89. package/dist/executor/cli-executor.d.ts +12 -0
  90. package/dist/executor/cli-executor.d.ts.map +1 -0
  91. package/dist/executor/cli-executor.js +94 -0
  92. package/dist/executor/cli-executor.js.map +1 -0
  93. package/dist/executor/code-executor.d.ts +13 -0
  94. package/dist/executor/code-executor.d.ts.map +1 -0
  95. package/dist/executor/code-executor.js +52 -0
  96. package/dist/executor/code-executor.js.map +1 -0
  97. package/dist/executor/code-instrument.d.ts +12 -0
  98. package/dist/executor/code-instrument.d.ts.map +1 -0
  99. package/dist/executor/code-instrument.js +116 -0
  100. package/dist/executor/code-instrument.js.map +1 -0
  101. package/dist/executor/executor-factory.d.ts +7 -0
  102. package/dist/executor/executor-factory.d.ts.map +1 -0
  103. package/dist/executor/executor-factory.js +24 -0
  104. package/dist/executor/executor-factory.js.map +1 -0
  105. package/dist/executor/ios-executor.d.ts +10 -0
  106. package/dist/executor/ios-executor.d.ts.map +1 -0
  107. package/dist/executor/ios-executor.js +91 -0
  108. package/dist/executor/ios-executor.js.map +1 -0
  109. package/dist/executor/types.d.ts +14 -0
  110. package/dist/executor/types.d.ts.map +1 -0
  111. package/dist/executor/types.js +2 -0
  112. package/dist/executor/types.js.map +1 -0
  113. package/dist/executor/worker-entry.d.ts +2 -0
  114. package/dist/executor/worker-entry.d.ts.map +1 -0
  115. package/dist/executor/worker-entry.js +61 -0
  116. package/dist/executor/worker-entry.js.map +1 -0
  117. package/dist/index.d.ts +22 -0
  118. package/dist/index.d.ts.map +1 -0
  119. package/dist/index.js +157 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/node/service.d.ts +21 -0
  122. package/dist/node/service.d.ts.map +1 -0
  123. package/dist/node/service.js +178 -0
  124. package/dist/node/service.js.map +1 -0
  125. package/dist/node/types.d.ts +45 -0
  126. package/dist/node/types.d.ts.map +1 -0
  127. package/dist/node/types.js +3 -0
  128. package/dist/node/types.js.map +1 -0
  129. package/dist/storage/database.d.ts +6 -0
  130. package/dist/storage/database.d.ts.map +1 -0
  131. package/dist/storage/database.js +154 -0
  132. package/dist/storage/database.js.map +1 -0
  133. package/dist/storage/repositories/debug-log-repo.d.ts +29 -0
  134. package/dist/storage/repositories/debug-log-repo.d.ts.map +1 -0
  135. package/dist/storage/repositories/debug-log-repo.js +90 -0
  136. package/dist/storage/repositories/debug-log-repo.js.map +1 -0
  137. package/dist/storage/repositories/device-repo.d.ts +12 -0
  138. package/dist/storage/repositories/device-repo.d.ts.map +1 -0
  139. package/dist/storage/repositories/device-repo.js +87 -0
  140. package/dist/storage/repositories/device-repo.js.map +1 -0
  141. package/dist/storage/repositories/execution-log-repo.d.ts +9 -0
  142. package/dist/storage/repositories/execution-log-repo.d.ts.map +1 -0
  143. package/dist/storage/repositories/execution-log-repo.js +49 -0
  144. package/dist/storage/repositories/execution-log-repo.js.map +1 -0
  145. package/dist/storage/repositories/task-repo.d.ts +13 -0
  146. package/dist/storage/repositories/task-repo.d.ts.map +1 -0
  147. package/dist/storage/repositories/task-repo.js +109 -0
  148. package/dist/storage/repositories/task-repo.js.map +1 -0
  149. package/dist/task/poller.d.ts +25 -0
  150. package/dist/task/poller.d.ts.map +1 -0
  151. package/dist/task/poller.js +153 -0
  152. package/dist/task/poller.js.map +1 -0
  153. package/dist/task/queue.d.ts +13 -0
  154. package/dist/task/queue.d.ts.map +1 -0
  155. package/dist/task/queue.js +38 -0
  156. package/dist/task/queue.js.map +1 -0
  157. package/dist/task/scheduler.d.ts +25 -0
  158. package/dist/task/scheduler.d.ts.map +1 -0
  159. package/dist/task/scheduler.js +274 -0
  160. package/dist/task/scheduler.js.map +1 -0
  161. package/dist/task/types.d.ts +31 -0
  162. package/dist/task/types.d.ts.map +1 -0
  163. package/dist/task/types.js +37 -0
  164. package/dist/task/types.js.map +1 -0
  165. package/dist/web/server.d.ts +14 -0
  166. package/dist/web/server.d.ts.map +1 -0
  167. package/dist/web/server.js +478 -0
  168. package/dist/web/server.js.map +1 -0
  169. package/package.json +49 -0
@@ -0,0 +1,7 @@
1
+ import type { CallbackConfig } from '../config/schema.js';
2
+ export declare function uploadReportFile(filePath: string, taskId: string, testName: string, testUrl: string | undefined, success: boolean, errorMessage: string | undefined, nodeId: string, config: CallbackConfig): Promise<unknown>;
3
+ export declare function updateTaskStatusToServer(taskId: string, success: boolean, nodeId: string, errorMessage: string | null, config: CallbackConfig): Promise<{
4
+ success: boolean;
5
+ message: string;
6
+ }>;
7
+ //# sourceMappingURL=callback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../src/api/callback.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAwB1D,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,OAAO,CAAC,CAwDlB;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyChD"}
@@ -0,0 +1,116 @@
1
+ import axios from 'axios';
2
+ import FormData from 'form-data';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { createLogger } from '../core/logger.js';
6
+ const logger = createLogger('Callback');
7
+ async function axiosWithRetry(requestFn, maxRetries = 1, timeout = 15000) {
8
+ for (let i = 0; i <= maxRetries; i++) {
9
+ try {
10
+ return await requestFn(timeout);
11
+ }
12
+ catch (error) {
13
+ if (i === maxRetries) {
14
+ logger.warn(`Request failed after ${maxRetries + 1} attempts: ${error.message}`);
15
+ return null;
16
+ }
17
+ logger.debug(`Request failed, retry ${i + 1}...`);
18
+ await new Promise(r => setTimeout(r, 1000));
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ export async function uploadReportFile(filePath, taskId, testName, testUrl, success, errorMessage, nodeId, config) {
24
+ if (!taskId || taskId.startsWith('debug-')) {
25
+ logger.info('Debug mode, skipping report upload');
26
+ return;
27
+ }
28
+ try {
29
+ const fileStats = fs.statSync(filePath);
30
+ const fileName = path.basename(filePath);
31
+ logger.info(`Uploading report: ${fileName} (${fileStats.size} bytes)`);
32
+ let fileBuffer;
33
+ if (fileStats.size > 50 * 1024 * 1024) {
34
+ fileBuffer = await new Promise((resolve, reject) => {
35
+ const chunks = [];
36
+ const readStream = fs.createReadStream(filePath);
37
+ readStream.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
38
+ readStream.on('end', () => resolve(Buffer.concat(chunks)));
39
+ readStream.on('error', reject);
40
+ });
41
+ }
42
+ else {
43
+ fileBuffer = fs.readFileSync(filePath);
44
+ }
45
+ const formData = new FormData();
46
+ formData.append('taskId', taskId);
47
+ formData.append('nodeId', nodeId);
48
+ formData.append('testName', testName);
49
+ formData.append('testUrl', testUrl || '');
50
+ formData.append('success', success.toString());
51
+ if (!success && errorMessage) {
52
+ formData.append('errorMessage', errorMessage);
53
+ }
54
+ formData.append('file', fileBuffer, fileName);
55
+ const requestFn = (timeout) => axios.post(config.reportUploadUrl, formData, {
56
+ headers: {
57
+ 'User-Agent': 'aiserver/1.0',
58
+ 'Accept': '*/*',
59
+ 'Connection': 'close',
60
+ 'Expect': '',
61
+ },
62
+ timeout,
63
+ maxRedirects: 0,
64
+ });
65
+ const response = await axiosWithRetry(requestFn, 1, 120000);
66
+ if (response) {
67
+ logger.info('Report upload successful');
68
+ return response.data;
69
+ }
70
+ }
71
+ catch (error) {
72
+ logger.error(`Report upload failed: ${error.message}`);
73
+ throw error;
74
+ }
75
+ }
76
+ export async function updateTaskStatusToServer(taskId, success, nodeId, errorMessage, config) {
77
+ if (!taskId || taskId.startsWith('debug-')) {
78
+ logger.info('Debug mode, skipping status update');
79
+ return { success: true, message: 'Debug mode' };
80
+ }
81
+ try {
82
+ const url = `${config.statusUpdateUrl}/${taskId}/result`;
83
+ logger.info(`Updating task status on server: PUT ${url} (success=${success}, nodeId=${nodeId})`);
84
+ // 与参考项目一致:params 中只传 nodeId, success, result, errorMessage
85
+ // result 为简单字符串,不传 JSON 对象
86
+ const params = {
87
+ nodeId,
88
+ success: success.toString(),
89
+ result: success ? 'success' : 'failed',
90
+ };
91
+ if (errorMessage && !success) {
92
+ params.errorMessage = errorMessage.length > 300 ? errorMessage.substring(0, 300) + '...(truncated)' : errorMessage;
93
+ }
94
+ const response = await axios.put(url, null, {
95
+ params,
96
+ timeout: 10000,
97
+ });
98
+ if (response.status >= 200 && response.status < 300) {
99
+ logger.info(`Task status updated on server: ${taskId} -> ${success ? 'success' : 'failed'}, HTTP ${response.status}`);
100
+ return { success: true, message: 'Status updated' };
101
+ }
102
+ logger.warn(`Task status update unexpected response: HTTP ${response.status}`);
103
+ return { success: false, message: `HTTP ${response.status}` };
104
+ }
105
+ catch (error) {
106
+ const axiosErr = error;
107
+ if (axiosErr.response) {
108
+ logger.error(`Task status update failed: HTTP ${axiosErr.response.status} - ${JSON.stringify(axiosErr.response.data)}`);
109
+ }
110
+ else {
111
+ logger.error(`Task status update failed: ${axiosErr.message || error.message}`);
112
+ }
113
+ return { success: false, message: error.message };
114
+ }
115
+ }
116
+ //# sourceMappingURL=callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../src/api/callback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { CallbackConfig } from '../config/schema.js';
2
+ import type { Device } from '../core/types.js';
3
+ /**
4
+ * Send device heartbeat, consistent with reference project
5
+ * URL: /rest/mobile-devices/heartbeat
6
+ */
7
+ export declare function sendDeviceHeartbeat(device: Device, config: CallbackConfig): Promise<boolean>;
8
+ /**
9
+ * Update device status on backend, consistent with reference project
10
+ * URL: /rest/mobile-devices/{serialNumber}/status
11
+ */
12
+ export declare function updateDeviceStatus(serialNumber: string, status: number, reason: string, config: CallbackConfig): Promise<boolean>;
13
+ //# sourceMappingURL=device-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-api.d.ts","sourceRoot":"","sources":["../../src/api/device-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkB/C;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,OAAO,CAAC,CAuClB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,OAAO,CAAC,CAkClB"}
@@ -0,0 +1,98 @@
1
+ import axios from 'axios';
2
+ import os from 'os';
3
+ import { createLogger } from '../core/logger.js';
4
+ const logger = createLogger('DeviceAPI');
5
+ function getLocalIPAddress() {
6
+ const interfaces = os.networkInterfaces();
7
+ for (const name of Object.keys(interfaces)) {
8
+ const nets = interfaces[name];
9
+ if (!nets)
10
+ continue;
11
+ for (const net of nets) {
12
+ if (net.family === 'IPv4' && !net.internal) {
13
+ return net.address;
14
+ }
15
+ }
16
+ }
17
+ return '127.0.0.1';
18
+ }
19
+ /**
20
+ * Send device heartbeat, consistent with reference project
21
+ * URL: /rest/mobile-devices/heartbeat
22
+ */
23
+ export async function sendDeviceHeartbeat(device, config) {
24
+ try {
25
+ const nodeId = os.hostname();
26
+ const data = {
27
+ nodeId,
28
+ deviceId: device.serialNumber,
29
+ deviceModel: device.model || 'Unknown',
30
+ deviceBrand: device.brand || 'Unknown',
31
+ status: 1, // online
32
+ timestamp: new Date().toISOString(),
33
+ batteryLevel: 100,
34
+ isCharging: false,
35
+ cpuUsage: 0.1,
36
+ memoryUsage: 0.5,
37
+ storageUsage: 0.3,
38
+ networkType: 'WIFI',
39
+ signalStrength: 100,
40
+ ipAddress: getLocalIPAddress(),
41
+ };
42
+ const response = await axios.post(config.deviceHeartbeatUrl, data, {
43
+ timeout: 10000,
44
+ headers: { 'Content-Type': 'application/json' },
45
+ });
46
+ if (response.status === 200 && response.data) {
47
+ const success = response.data.success || response.data.code === 200 || response.data.status === 'success';
48
+ if (success) {
49
+ logger.info(`Device heartbeat sent successfully for ${device.serialNumber}`);
50
+ }
51
+ else {
52
+ logger.warn(`Device heartbeat sent but with warning for ${device.serialNumber}: ${response.data.message}`);
53
+ }
54
+ return success;
55
+ }
56
+ return false;
57
+ }
58
+ catch (error) {
59
+ logger.warn(`Device heartbeat API failed for ${device.serialNumber}: ${error.message}`);
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Update device status on backend, consistent with reference project
65
+ * URL: /rest/mobile-devices/{serialNumber}/status
66
+ */
67
+ export async function updateDeviceStatus(serialNumber, status, reason, config) {
68
+ try {
69
+ const nodeId = os.hostname();
70
+ const updateUrl = `${config.deviceStatusUpdateUrl}/${serialNumber}/status`;
71
+ const params = {
72
+ status: status,
73
+ reason: reason,
74
+ nodeId: nodeId,
75
+ };
76
+ const response = await axios.put(updateUrl, null, {
77
+ params: params,
78
+ timeout: 10000,
79
+ headers: { 'Content-Type': 'application/json' },
80
+ });
81
+ if (response.status === 200 && response.data) {
82
+ const success = response.data.success || response.data.code === 200 || response.data.status === 'success';
83
+ if (success) {
84
+ logger.info(`Device status updated: ${serialNumber} -> status=${status}`);
85
+ }
86
+ else {
87
+ logger.warn(`Device status update warning for ${serialNumber}: ${response.data.message}`);
88
+ }
89
+ return success;
90
+ }
91
+ return false;
92
+ }
93
+ catch (error) {
94
+ logger.error(`Device status update failed for ${serialNumber}: ${error.message}`);
95
+ return false;
96
+ }
97
+ }
98
+ //# sourceMappingURL=device-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-api.js","sourceRoot":"","sources":["../../src/api/device-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKjD,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AAEzC,SAAS,iBAAiB;IACxB,MAAM,UAAU,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAC3C,OAAO,GAAG,CAAC,OAAO,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc,EACd,MAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAwB;YAChC,MAAM;YACN,QAAQ,EAAE,MAAM,CAAC,YAAY;YAC7B,WAAW,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;YACtC,WAAW,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;YACtC,MAAM,EAAE,CAAC,EAAE,SAAS;YACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,YAAY,EAAE,GAAG;YACjB,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,GAAG;YACb,WAAW,EAAE,GAAG;YAChB,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,MAAM;YACnB,cAAc,EAAE,GAAG;YACnB,SAAS,EAAE,iBAAiB,EAAE;SAC/B,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,IAAI,EAAE;YACjE,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;YAC1G,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,0CAA0C,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,8CAA8C,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7G,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,mCAAmC,MAAM,CAAC,YAAY,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACnG,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB,EACpB,MAAc,EACd,MAAc,EACd,MAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,qBAAqB,IAAI,YAAY,SAAS,CAAC;QAC3E,MAAM,MAAM,GAAG;YACb,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,MAAM;SACf,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAC9B,SAAS,EACT,IAAI,EACJ;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CACF,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;YAC1G,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,0BAA0B,YAAY,cAAc,MAAM,EAAE,CAAC,CAAC;YAC5E,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,oCAAoC,YAAY,KAAK,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5F,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,mCAAmC,YAAY,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7F,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { TaskConfig } from '../config/schema.js';
2
+ import type { TaskPollResult } from '../task/types.js';
3
+ /**
4
+ * Fetch next task from server using POST /rest/execution-queue/tasks/next
5
+ * Consistent with reference project (electron-shadcn)
6
+ */
7
+ export declare function fetchNextTask(config: TaskConfig): Promise<TaskPollResult>;
8
+ export declare function acknowledgeTask(executionId: string, nodeId: string, config: TaskConfig): Promise<boolean>;
9
+ //# sourceMappingURL=task-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-api.d.ts","sourceRoot":"","sources":["../../src/api/task-api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKzE;;;GAGG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CA2B/E;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,OAAO,CAAC,CAWlB"}
@@ -0,0 +1,47 @@
1
+ import axios from 'axios';
2
+ import { createLogger } from '../core/logger.js';
3
+ const logger = createLogger('TaskAPI');
4
+ /**
5
+ * Fetch next task from server using POST /rest/execution-queue/tasks/next
6
+ * Consistent with reference project (electron-shadcn)
7
+ */
8
+ export async function fetchNextTask(config) {
9
+ try {
10
+ const response = await axios.post(`${config.apiUrl}/rest/execution-queue/tasks/next`, null, {
11
+ params: {
12
+ nodeId: config.nodeId,
13
+ },
14
+ timeout: 10000,
15
+ });
16
+ if (response.status === 200 && response.data) {
17
+ const d = response.data;
18
+ const data = d.data && typeof d.data === 'object' ? d.data : d;
19
+ const task = (data.task || d.task);
20
+ const device = (data.allocatedDevice ||
21
+ data.availableMobileDevice ||
22
+ data.availableMobileDevices?.[0] ||
23
+ d.allocatedDevice ||
24
+ d.availableMobileDevice);
25
+ return { task, device };
26
+ }
27
+ return { task: null, device: null };
28
+ }
29
+ catch (error) {
30
+ logger.warn(`Failed to fetch next task: ${error.message}`);
31
+ return { task: null, device: null };
32
+ }
33
+ }
34
+ export async function acknowledgeTask(executionId, nodeId, config) {
35
+ try {
36
+ await axios.put(`${config.apiUrl}/rest/execution-queue/tasks/${executionId}/ack`, {
37
+ nodeId,
38
+ status: 1, // Running
39
+ }, { timeout: 10000 });
40
+ return true;
41
+ }
42
+ catch (error) {
43
+ logger.warn(`Failed to acknowledge task ${executionId}: ${error.message}`);
44
+ return false;
45
+ }
46
+ }
47
+ //# sourceMappingURL=task-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-api.js","sourceRoot":"","sources":["../../src/api/task-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKjD,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,kCAAkC,EAAE,IAAI,EAAE;YAC1F,MAAM,EAAE;gBACN,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB;YACD,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;YACxB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAE/D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAA4B,CAAC;YAC9D,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,eAAe;gBACrB,IAAI,CAAC,qBAAqB;gBAC1B,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,eAAe;gBACjB,CAAC,CAAC,qBAAqB,CAA2B,CAAC;YAElE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,8BAA+B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACtE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,MAAc,EACd,MAAkB;IAElB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,+BAA+B,WAAW,MAAM,EAAE;YAChF,MAAM;YACN,MAAM,EAAE,CAAC,EAAE,UAAU;SACtB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACtF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Command-line argument parser for @aiscene/aiserver
3
+ *
4
+ * Supported arguments:
5
+ * --supported-tags <tags> Supported tags (e.g. "task,open,android,ios,web")
6
+ * --max-concurrent <n> Max concurrent tasks
7
+ * --node-name <name> Node name
8
+ * --node-type <type> Node type (e.g. "executor")
9
+ * --node-weight <n> Node weight
10
+ * --environment <env> Environment (e.g. "prod", "test")
11
+ * --region <region> Node region
12
+ * --description <desc> Node description
13
+ * --port <port> Server port
14
+ * --web-port <port> Web dashboard port
15
+ * --help Show help
16
+ */
17
+ export interface CliArgs {
18
+ supportedTags?: string;
19
+ maxConcurrent?: number;
20
+ nodeName?: string;
21
+ nodeType?: string;
22
+ nodeWeight?: number;
23
+ environment?: string;
24
+ region?: string;
25
+ description?: string;
26
+ port?: number;
27
+ webPort?: number;
28
+ }
29
+ export declare function parseCliArgs(): CliArgs;
30
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/config/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,OAAO;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2BD,wBAAgB,YAAY,IAAI,OAAO,CAuFtC"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Command-line argument parser for @aiscene/aiserver
3
+ *
4
+ * Supported arguments:
5
+ * --supported-tags <tags> Supported tags (e.g. "task,open,android,ios,web")
6
+ * --max-concurrent <n> Max concurrent tasks
7
+ * --node-name <name> Node name
8
+ * --node-type <type> Node type (e.g. "executor")
9
+ * --node-weight <n> Node weight
10
+ * --environment <env> Environment (e.g. "prod", "test")
11
+ * --region <region> Node region
12
+ * --description <desc> Node description
13
+ * --port <port> Server port
14
+ * --web-port <port> Web dashboard port
15
+ * --help Show help
16
+ */
17
+ function showHelp() {
18
+ console.log(`
19
+ @aiscene/aiserver - AI Automation Server
20
+
21
+ Usage: aiserver [options]
22
+
23
+ Options:
24
+ --supported-tags <tags> Supported tags for task routing (e.g. "task,open,android,ios,web")
25
+ --max-concurrent <n> Max concurrent tasks (default: 3)
26
+ --node-name <name> Node display name
27
+ --node-type <type> Node type (default: "executor")
28
+ --node-weight <n> Node weight for load balancing (default: 1)
29
+ --environment <env> Deployment environment (default: "prod")
30
+ --region <region> Node region
31
+ --description <desc> Node description
32
+ --port <port> WebSocket server port (default: 8002)
33
+ --web-port <port> Web dashboard port (default: 3000)
34
+ --help Show this help message
35
+
36
+ Examples:
37
+ aiserver --supported-tags task,open --max-concurrent 5
38
+ aiserver --supported-tags task --node-name "my-executor" --region "us-east"
39
+ `);
40
+ }
41
+ export function parseCliArgs() {
42
+ const args = {};
43
+ const argv = process.argv.slice(2);
44
+ if (argv.includes('--help') || argv.includes('-h')) {
45
+ showHelp();
46
+ process.exit(0);
47
+ }
48
+ for (let i = 0; i < argv.length; i++) {
49
+ const arg = argv[i];
50
+ const next = argv[i + 1];
51
+ switch (arg) {
52
+ case '--supported-tags':
53
+ if (next && !next.startsWith('--')) {
54
+ args.supportedTags = next;
55
+ i++;
56
+ }
57
+ break;
58
+ case '--max-concurrent':
59
+ if (next && !next.startsWith('--')) {
60
+ const val = parseInt(next, 10);
61
+ if (!isNaN(val))
62
+ args.maxConcurrent = val;
63
+ i++;
64
+ }
65
+ break;
66
+ case '--node-name':
67
+ if (next && !next.startsWith('--')) {
68
+ args.nodeName = next;
69
+ i++;
70
+ }
71
+ break;
72
+ case '--node-type':
73
+ if (next && !next.startsWith('--')) {
74
+ args.nodeType = next;
75
+ i++;
76
+ }
77
+ break;
78
+ case '--node-weight':
79
+ if (next && !next.startsWith('--')) {
80
+ const val = parseInt(next, 10);
81
+ if (!isNaN(val))
82
+ args.nodeWeight = val;
83
+ i++;
84
+ }
85
+ break;
86
+ case '--environment':
87
+ if (next && !next.startsWith('--')) {
88
+ args.environment = next;
89
+ i++;
90
+ }
91
+ break;
92
+ case '--region':
93
+ if (next && !next.startsWith('--')) {
94
+ args.region = next;
95
+ i++;
96
+ }
97
+ break;
98
+ case '--description':
99
+ if (next && !next.startsWith('--')) {
100
+ args.description = next;
101
+ i++;
102
+ }
103
+ break;
104
+ case '--port':
105
+ if (next && !next.startsWith('--')) {
106
+ const val = parseInt(next, 10);
107
+ if (!isNaN(val))
108
+ args.port = val;
109
+ i++;
110
+ }
111
+ break;
112
+ case '--web-port':
113
+ if (next && !next.startsWith('--')) {
114
+ const val = parseInt(next, 10);
115
+ if (!isNaN(val))
116
+ args.webPort = val;
117
+ i++;
118
+ }
119
+ break;
120
+ default:
121
+ if (arg.startsWith('--')) {
122
+ console.warn(`Unknown argument: ${arg}`);
123
+ }
124
+ break;
125
+ }
126
+ }
127
+ return args;
128
+ }
129
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/config/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAeH,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;CAqBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,IAAI,GAAY,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,QAAQ,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,kBAAkB;gBACrB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;oBAC1B,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,kBAAkB;gBACrB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;wBAAE,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;oBAC1C,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,aAAa;gBAChB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;oBACrB,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,aAAa;gBAChB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;oBACrB,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,eAAe;gBAClB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;wBAAE,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;oBACvC,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,eAAe;gBAClB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;oBACxB,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;oBACnB,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,eAAe;gBAClB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;oBACxB,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;wBAAE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;oBACjC,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR,KAAK,YAAY;gBACf,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;wBAAE,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;oBACpC,CAAC,EAAE,CAAC;gBACN,CAAC;gBACD,MAAM;YACR;gBACE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,OAAO,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;gBAC3C,CAAC;gBACD,MAAM;QACV,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ import 'dotenv/config';
2
+ import type { AIServerConfig } from './schema.js';
3
+ export declare function loadConfig(configPath?: string): AIServerConfig;
4
+ export declare function getConfig(): AIServerConfig;
5
+ export declare function reloadConfig(): AIServerConfig;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAIvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8ClD,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAyF9D;AAID,wBAAgB,SAAS,IAAI,cAAc,CAK1C;AAED,wBAAgB,YAAY,IAAI,cAAc,CAG7C"}
@@ -0,0 +1,142 @@
1
+ import 'dotenv/config';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { createLogger } from '../core/logger.js';
6
+ import { parseCliArgs } from './cli.js';
7
+ const logger = createLogger('Config');
8
+ const defaultNodeId = os.hostname();
9
+ function getEnv(key, defaultValue = '') {
10
+ return process.env[key] || defaultValue;
11
+ }
12
+ function getEnvNumber(key, defaultValue) {
13
+ const val = process.env[key];
14
+ if (val) {
15
+ const num = parseInt(val, 10);
16
+ return isNaN(num) ? defaultValue : num;
17
+ }
18
+ return defaultValue;
19
+ }
20
+ function getEnvBoolean(key, defaultValue) {
21
+ const val = process.env[key];
22
+ if (val === '1' || val === 'true')
23
+ return true;
24
+ if (val === '0' || val === 'false')
25
+ return false;
26
+ return defaultValue;
27
+ }
28
+ function loadEnvFile(envPath) {
29
+ if (fs.existsSync(envPath)) {
30
+ const content = fs.readFileSync(envPath, 'utf-8');
31
+ for (const line of content.split('\n')) {
32
+ const trimmed = line.trim();
33
+ if (!trimmed || trimmed.startsWith('#'))
34
+ continue;
35
+ const eqIndex = trimmed.indexOf('=');
36
+ if (eqIndex === -1)
37
+ continue;
38
+ const key = trimmed.substring(0, eqIndex).trim();
39
+ const value = trimmed.substring(eqIndex + 1).trim();
40
+ if (!process.env[key]) {
41
+ process.env[key] = value;
42
+ }
43
+ }
44
+ logger.info(`Loaded env file: ${envPath}`);
45
+ }
46
+ }
47
+ export function loadConfig(configPath) {
48
+ // Parse CLI arguments (highest priority)
49
+ const cliArgs = parseCliArgs();
50
+ // Load .env file
51
+ const envPaths = [
52
+ path.resolve(process.cwd(), '.env'),
53
+ path.resolve(process.cwd(), '.env.local'),
54
+ ];
55
+ for (const p of envPaths) {
56
+ loadEnvFile(p);
57
+ }
58
+ // Load custom config file if provided
59
+ if (configPath && fs.existsSync(configPath)) {
60
+ loadEnvFile(configPath);
61
+ }
62
+ // CLI args override env vars
63
+ const maxConcurrent = cliArgs.maxConcurrent ?? getEnvNumber('AISERVER_TASK_MAX_CONCURRENT', 3);
64
+ const config = {
65
+ server: {
66
+ port: cliArgs.port ?? getEnvNumber('AISERVER_PORT', 8002),
67
+ webPort: cliArgs.webPort ?? getEnvNumber('AISERVER_WEB_PORT', 3000),
68
+ host: getEnv('AISERVER_HOST', '0.0.0.0'),
69
+ },
70
+ device: {
71
+ heartbeatInterval: getEnvNumber('AISERVER_DEVICE_HEARTBEAT_INTERVAL', 30000),
72
+ offlineRetryCount: getEnvNumber('AISERVER_DEVICE_OFFLINE_RETRY_COUNT', 3),
73
+ offlineCallbackUrl: getEnv('AISERVER_DEVICE_OFFLINE_CALLBACK_URL', ''),
74
+ },
75
+ task: {
76
+ pollInterval: getEnvNumber('AISERVER_TASK_POLL_INTERVAL', 5000),
77
+ apiUrl: getEnv('AISERVER_TASK_API_URL', 'http://nethp-test.jd.com'),
78
+ nodeId: defaultNodeId,
79
+ maxConcurrent: maxConcurrent,
80
+ timeout: getEnvNumber('AISERVER_TASK_TIMEOUT', 1200000),
81
+ },
82
+ ai: {
83
+ baseUrl: getEnv('OPENAI_BASE_URL', ''),
84
+ apiKey: getEnv('OPENAI_API_KEY', ''),
85
+ modelName: getEnv('MIDSCENE_MODEL_NAME', ''),
86
+ useQwen3Vl: getEnvBoolean('MIDSCENE_USE_QWEN3_VL', true),
87
+ insightModelName: getEnv('MIDSCENE_INSIGHT_MODEL_NAME', ''),
88
+ insightModelApiKey: getEnv('MIDSCENE_INSIGHT_MODEL_API_KEY', ''),
89
+ insightModelBaseUrl: getEnv('MIDSCENE_INSIGHT_MODEL_BASE_URL', ''),
90
+ insightModelFamily: getEnv('MIDSCENE_INSIGHT_MODEL_FAMILY', ''),
91
+ insightModelTimeout: getEnvNumber('MIDSCENE_INSIGHT_MODEL_TIMEOUT', 60000),
92
+ insightModelTemperature: getEnvNumber('MIDSCENE_INSIGHT_MODEL_TEMPERATURE', 1),
93
+ },
94
+ storage: {
95
+ dbPath: getEnv('AISERVER_DB_PATH', path.resolve(process.cwd(), 'data', 'aiserver.db')),
96
+ },
97
+ node: {
98
+ nodeId: defaultNodeId,
99
+ nodeName: cliArgs.nodeName ?? getEnv('AISERVER_NODE_NAME', defaultNodeId),
100
+ ipAddress: getEnv('AISERVER_NODE_IP_ADDRESS', ''),
101
+ port: cliArgs.port ?? getEnvNumber('AISERVER_NODE_PORT', 8002),
102
+ nodeType: cliArgs.nodeType ?? getEnv('AISERVER_NODE_TYPE', 'executor'),
103
+ version: getEnv('AISERVER_NODE_VERSION', '1.0.0'),
104
+ environment: cliArgs.environment ?? getEnv('AISERVER_NODE_ENVIRONMENT', 'prod'),
105
+ maxConcurrentTasks: maxConcurrent,
106
+ weight: cliArgs.nodeWeight ?? getEnvNumber('AISERVER_NODE_WEIGHT', 1),
107
+ supportedTags: cliArgs.supportedTags ?? getEnv('AISERVER_NODE_SUPPORTED_TAGS', 'android,ios,web'),
108
+ region: cliArgs.region ?? getEnv('AISERVER_NODE_REGION', ''),
109
+ description: cliArgs.description ?? getEnv('AISERVER_NODE_DESCRIPTION', ''),
110
+ registerUrl: getEnv('AISERVER_NODE_REGISTER_URL', 'http://nethp-test.jd.com/rest/execution-nodes/register'),
111
+ heartbeatUrl: getEnv('AISERVER_NODE_HEARTBEAT_URL', 'http://nethp-test.jd.com/rest/execution-nodes/heartbeat'),
112
+ heartbeatInterval: getEnvNumber('AISERVER_NODE_HEARTBEAT_INTERVAL', 30000),
113
+ configInfo: {
114
+ heartbeatInterval: getEnvNumber('AISERVER_NODE_HEARTBEAT_INTERVAL', 30000),
115
+ },
116
+ },
117
+ callback: {
118
+ statusUpdateUrl: getEnv('AISERVER_STATUS_UPDATE_URL', 'http://nethp-test.jd.com/rest/execution-queue/tasks'),
119
+ reportUploadUrl: getEnv('AISERVER_REPORT_UPLOAD_URL', 'http://nethp-test.jd.com/rest/execution-callback/result-file'),
120
+ deviceHeartbeatUrl: getEnv('AISERVER_DEVICE_HEARTBEAT_URL', 'http://nethp-test.jd.com/rest/mobile-devices/heartbeat'),
121
+ deviceStatusUpdateUrl: getEnv('AISERVER_DEVICE_STATUS_UPDATE_URL', 'http://nethp-test.jd.com/rest/mobile-devices'),
122
+ },
123
+ };
124
+ // Log CLI overrides if any were used
125
+ if (Object.keys(cliArgs).length > 0) {
126
+ logger.info(`CLI arguments applied: ${JSON.stringify(cliArgs)}`);
127
+ }
128
+ logger.info('Configuration loaded successfully');
129
+ return config;
130
+ }
131
+ let _config = null;
132
+ export function getConfig() {
133
+ if (!_config) {
134
+ _config = loadConfig();
135
+ }
136
+ return _config;
137
+ }
138
+ export function reloadConfig() {
139
+ _config = loadConfig();
140
+ return _config;
141
+ }
142
+ //# sourceMappingURL=index.js.map