@aiscene/aiserver 1.2.6 → 1.2.8
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.
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/debug/types.d.ts +1 -0
- package/dist/debug/types.d.ts.map +1 -1
- package/dist/debug/websocket-server.d.ts +5 -0
- package/dist/debug/websocket-server.d.ts.map +1 -1
- package/dist/debug/websocket-server.js +243 -16
- package/dist/debug/websocket-server.js.map +1 -1
- package/dist/executor/action-executor.d.ts +5 -0
- package/dist/executor/action-executor.d.ts.map +1 -1
- package/dist/executor/action-executor.js +134 -59
- package/dist/executor/action-executor.js.map +1 -1
- package/dist/executor/code-executor.d.ts.map +1 -1
- package/dist/executor/code-executor.js +8 -1
- package/dist/executor/code-executor.js.map +1 -1
- package/dist/executor/code-instrument.d.ts.map +1 -1
- package/dist/executor/code-instrument.js +3 -10
- package/dist/executor/code-instrument.js.map +1 -1
- package/dist/executor/worker-entry.js +73 -0
- package/dist/executor/worker-entry.js.map +1 -1
- package/dist/web/debug-page.d.ts.map +1 -1
- package/dist/web/debug-page.js +40 -19
- package/dist/web/debug-page.js.map +1 -1
- package/package.json +2 -2
package/dist/core/types.d.ts
CHANGED
|
@@ -95,6 +95,7 @@ export interface ExecuteResult {
|
|
|
95
95
|
errorMessage?: string;
|
|
96
96
|
result?: unknown;
|
|
97
97
|
dump?: string;
|
|
98
|
+
executionDump?: unknown;
|
|
98
99
|
reportHTML?: string;
|
|
99
100
|
}
|
|
100
101
|
export type DebugSessionStatus = 'idle' | 'running' | 'completed' | 'failed' | 'stopped';
|
|
@@ -115,6 +116,8 @@ export interface DebugSession {
|
|
|
115
116
|
screencastEnabled?: boolean;
|
|
116
117
|
dumpIntervalId?: NodeJS.Timeout;
|
|
117
118
|
process?: unknown;
|
|
119
|
+
executor?: unknown;
|
|
120
|
+
abortController?: AbortController;
|
|
118
121
|
}
|
|
119
122
|
export type EventType = 'task:started' | 'task:completed' | 'task:failed' | 'task:log' | 'device:online' | 'device:offline' | 'device:heartbeat' | 'node:registered' | 'node:command' | 'debug:session_created' | 'debug:log_output' | 'debug:action_dump' | 'debug:execution_line' | 'debug:action_result' | 'debug:completed' | 'debug:error' | 'executor:dump';
|
|
120
123
|
export interface EventPayload {
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,MAAM;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,GAAG,KAAK,CAAC;IAC5B,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAGD,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AACrE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAGpF,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzF,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAEhB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
package/dist/debug/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/debug/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,aAAa,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/debug/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,11 @@ export declare class DebugWebSocketServer {
|
|
|
48
48
|
private handleCloseWebSession;
|
|
49
49
|
private handleStopDebug;
|
|
50
50
|
private handleGetLogs;
|
|
51
|
+
/**
|
|
52
|
+
* 将前端传来的 modelConfig 应用到环境变量
|
|
53
|
+
* ActionExecutor 通过环境变量读取模型配置,所以需要同步更新
|
|
54
|
+
*/
|
|
55
|
+
private applyModelConfig;
|
|
51
56
|
private sendMessage;
|
|
52
57
|
private sendError;
|
|
53
58
|
private cleanupSession;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../../src/debug/websocket-server.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmB1D,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAkB;IAGnC,OAAO,CAAC,kBAAkB,CAA0C;IAEpE,OAAO,CAAC,uBAAuB,CAA0C;gBAE7D,IAAI,GAAE,MAAa;IAIzB,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../../src/debug/websocket-server.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmB1D,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAkB;IAGnC,OAAO,CAAC,kBAAkB,CAA0C;IAEpE,OAAO,CAAC,uBAAuB,CAA0C;gBAE7D,IAAI,GAAE,MAAa;IAIzB,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqElD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,uBAAuB;YAiCjB,aAAa;IAyC3B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,yBAAyB;IAWjC,4CAA4C;IAC5C,OAAO,CAAC,YAAY;YAMN,gBAAgB;IA2B9B,6CAA6C;YAC/B,uBAAuB;IA6ErC,uCAAuC;YACzB,wBAAwB;YAkFxB,mBAAmB;YAgGnB,kBAAkB;YAgGlB,sBAAsB;YA+RtB,qBAAqB;YA4BrB,oBAAoB;YAuBpB,qBAAqB;YAoCrB,eAAe;YA8Ff,aAAa;IAU3B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,WAAW;IAmCnB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAMtB,WAAW,IAAI,YAAY,EAAE;IAIvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAW7B"}
|
|
@@ -47,6 +47,21 @@ export class DebugWebSocketServer {
|
|
|
47
47
|
host: config.server.host,
|
|
48
48
|
port: this.port,
|
|
49
49
|
perMessageDeflate: false,
|
|
50
|
+
maxPayload: 10 * 1024 * 1024, // 10MB max message size
|
|
51
|
+
});
|
|
52
|
+
// 定期 ping 所有客户端,防止反向代理/负载均衡器因空闲超时断开 WebSocket
|
|
53
|
+
const heartbeatInterval = setInterval(() => {
|
|
54
|
+
this.wss?.clients.forEach((ws) => {
|
|
55
|
+
if (ws.isAlive === false) {
|
|
56
|
+
logger.warn('[WS] Client missed heartbeat, terminating connection');
|
|
57
|
+
return ws.terminate();
|
|
58
|
+
}
|
|
59
|
+
ws.isAlive = false;
|
|
60
|
+
ws.ping();
|
|
61
|
+
});
|
|
62
|
+
}, 30000);
|
|
63
|
+
this.wss.on('close', () => {
|
|
64
|
+
clearInterval(heartbeatInterval);
|
|
50
65
|
});
|
|
51
66
|
this.wss.on('connection', (ws, req) => {
|
|
52
67
|
let parsedUrl;
|
|
@@ -164,13 +179,19 @@ export class DebugWebSocketServer {
|
|
|
164
179
|
}
|
|
165
180
|
handleControlConnection(ws) {
|
|
166
181
|
logger.info('[Control] New connection');
|
|
182
|
+
// 心跳:收到 pong 标记为存活
|
|
183
|
+
ws.isAlive = true;
|
|
184
|
+
ws.on('pong', () => {
|
|
185
|
+
ws.isAlive = true;
|
|
186
|
+
});
|
|
167
187
|
ws.on('message', async (data) => {
|
|
168
188
|
try {
|
|
169
189
|
const message = JSON.parse(data.toString());
|
|
170
190
|
await this.handleMessage(ws, message);
|
|
171
191
|
}
|
|
172
192
|
catch (error) {
|
|
173
|
-
|
|
193
|
+
logger.error(`[Control] Message handling error: ${error.message}`);
|
|
194
|
+
this.sendError(ws, `Message handling error: ${error.message}`);
|
|
174
195
|
}
|
|
175
196
|
});
|
|
176
197
|
ws.on('close', () => {
|
|
@@ -275,6 +296,12 @@ export class DebugWebSocketServer {
|
|
|
275
296
|
}
|
|
276
297
|
/** 代码模式:在主进程内使用 ActionExecutor 执行 runCode */
|
|
277
298
|
async executeRunCodeInProcess(ws, sessionId, request) {
|
|
299
|
+
const session = sessionManager.get(sessionId);
|
|
300
|
+
const abortController = new AbortController();
|
|
301
|
+
if (session)
|
|
302
|
+
session.abortController = abortController;
|
|
303
|
+
// 将前端传来的 modelConfig 应用到环境变量
|
|
304
|
+
this.applyModelConfig(request.modelConfig);
|
|
278
305
|
const executor = ExecutorFactory.create('action', {
|
|
279
306
|
sessionId,
|
|
280
307
|
onLog: (msg) => {
|
|
@@ -288,6 +315,9 @@ export class DebugWebSocketServer {
|
|
|
288
315
|
this.sendMessage(ws, { type: 'execution_line', sessionId, line }, request.deviceId);
|
|
289
316
|
},
|
|
290
317
|
});
|
|
318
|
+
// 保存 executor 引用到 session,以便 stop_debug 时可以中断
|
|
319
|
+
if (session)
|
|
320
|
+
session.executor = executor;
|
|
291
321
|
const config = {
|
|
292
322
|
type: request.platform || 'android',
|
|
293
323
|
testName: 'debug-runCode',
|
|
@@ -300,7 +330,23 @@ export class DebugWebSocketServer {
|
|
|
300
330
|
modelConfig: undefined,
|
|
301
331
|
executionId: sessionId,
|
|
302
332
|
};
|
|
303
|
-
|
|
333
|
+
// 使用 AbortSignal 监听停止请求
|
|
334
|
+
const executePromise = executor.execute(config);
|
|
335
|
+
const abortPromise = new Promise((resolve) => {
|
|
336
|
+
abortController.signal.addEventListener('abort', () => {
|
|
337
|
+
resolve({ success: false, errorMessage: 'Action stopped by user' });
|
|
338
|
+
}, { once: true });
|
|
339
|
+
});
|
|
340
|
+
let result;
|
|
341
|
+
try {
|
|
342
|
+
result = await Promise.race([executePromise, abortPromise]);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
result = { success: false, errorMessage: error.message };
|
|
346
|
+
}
|
|
347
|
+
// 清理 executor 引用
|
|
348
|
+
if (session)
|
|
349
|
+
session.executor = undefined;
|
|
304
350
|
sessionManager.updateStatus(sessionId, result.success ? 'completed' : 'failed');
|
|
305
351
|
this.sendMessage(ws, {
|
|
306
352
|
type: 'action_result',
|
|
@@ -308,7 +354,7 @@ export class DebugWebSocketServer {
|
|
|
308
354
|
actionType: 'runCode',
|
|
309
355
|
success: result.success,
|
|
310
356
|
result: result.result,
|
|
311
|
-
dump: result.dump || '',
|
|
357
|
+
dump: result.executionDump || result.dump || '',
|
|
312
358
|
reportHTML: result.reportHTML || '',
|
|
313
359
|
error: result.errorMessage,
|
|
314
360
|
platform: request.platform || 'android',
|
|
@@ -322,6 +368,8 @@ export class DebugWebSocketServer {
|
|
|
322
368
|
}
|
|
323
369
|
/** 自然语言模式:Fork worker 进程执行 aiAction */
|
|
324
370
|
async executeWithWorkerProcess(ws, sessionId, request) {
|
|
371
|
+
// 将前端传来的 modelConfig 应用到环境变量(fork 前应用,子进程继承)
|
|
372
|
+
this.applyModelConfig(request.modelConfig);
|
|
325
373
|
const execConfig = {
|
|
326
374
|
type: request.platform || 'android',
|
|
327
375
|
testName: 'debugtest',
|
|
@@ -362,12 +410,27 @@ export class DebugWebSocketServer {
|
|
|
362
410
|
sessionManager.addLog(sessionId, `ERROR: ${errorOutput}`);
|
|
363
411
|
this.sendMessage(ws, { type: 'log_output', sessionId, content: `ERROR: ${errorOutput}`, level: 'error' }, request.deviceId);
|
|
364
412
|
});
|
|
413
|
+
// 缓存 worker 返回的结果(包括 dump 数据)
|
|
414
|
+
let workerResult = {};
|
|
365
415
|
childProcess.on('exit', (code) => {
|
|
366
416
|
const success = code === 0;
|
|
367
417
|
sessionManager.updateStatus(sessionId, success ? 'completed' : 'failed');
|
|
368
|
-
|
|
418
|
+
// 发送 debug_completed 消息时包含 dump 数据
|
|
419
|
+
this.sendMessage(ws, {
|
|
420
|
+
type: 'debug_completed',
|
|
421
|
+
sessionId,
|
|
422
|
+
success,
|
|
423
|
+
exitCode: code,
|
|
424
|
+
dump: workerResult.dump || '',
|
|
425
|
+
reportFile: workerResult.reportFile,
|
|
426
|
+
errorMessage: workerResult.errorMessage,
|
|
427
|
+
}, request.deviceId);
|
|
369
428
|
});
|
|
370
429
|
childProcess.on('message', (message) => {
|
|
430
|
+
// 缓存 worker 返回的结果,用于在 exit 时发送
|
|
431
|
+
if (typeof message === 'object' && message) {
|
|
432
|
+
workerResult = { ...workerResult, ...message };
|
|
433
|
+
}
|
|
371
434
|
this.sendMessage(ws, { type: 'execution_result', sessionId, ...(typeof message === 'object' && message ? message : {}) }, request.deviceId);
|
|
372
435
|
});
|
|
373
436
|
childProcess.on('error', (error) => {
|
|
@@ -379,7 +442,12 @@ export class DebugWebSocketServer {
|
|
|
379
442
|
async handleExecuteAction(ws, request) {
|
|
380
443
|
const sessionId = `action-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
381
444
|
const session = sessionManager.create(sessionId, ws, request.deviceId);
|
|
445
|
+
const abortController = new AbortController();
|
|
446
|
+
session.abortController = abortController;
|
|
447
|
+
// 将前端传来的 modelConfig 应用到环境变量
|
|
448
|
+
this.applyModelConfig(request.modelConfig);
|
|
382
449
|
try {
|
|
450
|
+
sessionManager.updateStatus(sessionId, 'running');
|
|
383
451
|
this.sendMessage(ws, { type: 'action_started', sessionId, actionType: request.actionType }, request.deviceId);
|
|
384
452
|
const executor = ExecutorFactory.create('action', {
|
|
385
453
|
sessionId,
|
|
@@ -394,6 +462,8 @@ export class DebugWebSocketServer {
|
|
|
394
462
|
this.sendMessage(ws, { type: 'execution_line', sessionId, line }, request.deviceId);
|
|
395
463
|
},
|
|
396
464
|
});
|
|
465
|
+
// 保存 executor 引用到 session,以便 stop_debug 时可以中断
|
|
466
|
+
session.executor = executor;
|
|
397
467
|
const config = {
|
|
398
468
|
type: request.platform || 'android',
|
|
399
469
|
testName: `action-${request.actionType}`,
|
|
@@ -406,33 +476,63 @@ export class DebugWebSocketServer {
|
|
|
406
476
|
modelConfig: undefined,
|
|
407
477
|
executionId: sessionId,
|
|
408
478
|
};
|
|
409
|
-
|
|
410
|
-
|
|
479
|
+
// 使用 AbortSignal 监听停止请求
|
|
480
|
+
const executePromise = executor.execute(config);
|
|
481
|
+
const abortPromise = new Promise((resolve) => {
|
|
482
|
+
abortController.signal.addEventListener('abort', () => {
|
|
483
|
+
resolve({ success: false, errorMessage: 'Action stopped by user' });
|
|
484
|
+
}, { once: true });
|
|
485
|
+
});
|
|
486
|
+
const result = await Promise.race([executePromise, abortPromise]);
|
|
487
|
+
// 清理 executor 引用
|
|
488
|
+
session.executor = undefined;
|
|
489
|
+
const status = result.success ? 'completed' : 'failed';
|
|
490
|
+
sessionManager.updateStatus(sessionId, status);
|
|
491
|
+
logger.info(`[Action] Execution finished: sessionId=${sessionId}, status=${status}, ws.readyState=${ws.readyState}`);
|
|
411
492
|
this.sendMessage(ws, {
|
|
412
493
|
type: 'action_result',
|
|
413
494
|
sessionId,
|
|
414
495
|
success: result.success,
|
|
415
496
|
result: result.result,
|
|
416
|
-
dump: result.dump || '',
|
|
497
|
+
dump: result.executionDump || result.dump || '',
|
|
417
498
|
reportHTML: result.reportHTML || '',
|
|
418
499
|
error: result.errorMessage,
|
|
419
500
|
}, request.deviceId);
|
|
501
|
+
this.sendMessage(ws, {
|
|
502
|
+
type: 'debug_completed',
|
|
503
|
+
sessionId,
|
|
504
|
+
success: result.success,
|
|
505
|
+
}, request.deviceId);
|
|
506
|
+
logger.info(`[Action] Sent action_result + debug_completed for sessionId=${sessionId}`);
|
|
420
507
|
}
|
|
421
508
|
catch (error) {
|
|
509
|
+
session.executor = undefined;
|
|
422
510
|
sessionManager.updateStatus(sessionId, 'failed');
|
|
511
|
+
logger.error(`[Action] Execution error: sessionId=${sessionId}, error=${error.message}, ws.readyState=${ws.readyState}`);
|
|
423
512
|
this.sendMessage(ws, {
|
|
424
513
|
type: 'action_result',
|
|
425
514
|
sessionId,
|
|
426
515
|
success: false,
|
|
427
516
|
error: error.message,
|
|
428
517
|
}, request.deviceId);
|
|
518
|
+
// 异常时也发送 debug_completed,确保前端能退出执行中状态
|
|
519
|
+
this.sendMessage(ws, {
|
|
520
|
+
type: 'debug_completed',
|
|
521
|
+
sessionId,
|
|
522
|
+
success: false,
|
|
523
|
+
}, request.deviceId);
|
|
429
524
|
}
|
|
430
525
|
}
|
|
431
526
|
// ==================== Execute AI Act ====================
|
|
432
527
|
async handleExecuteAiAct(ws, request) {
|
|
433
528
|
const sessionId = `aiact-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
434
529
|
const session = sessionManager.create(sessionId, ws, request.deviceId);
|
|
530
|
+
const abortController = new AbortController();
|
|
531
|
+
session.abortController = abortController;
|
|
532
|
+
// 将前端传来的 modelConfig 应用到环境变量
|
|
533
|
+
this.applyModelConfig(request.modelConfig);
|
|
435
534
|
try {
|
|
535
|
+
sessionManager.updateStatus(sessionId, 'running');
|
|
436
536
|
this.sendMessage(ws, { type: 'ai_act_started', sessionId }, request.deviceId);
|
|
437
537
|
const executor = ExecutorFactory.create('action', {
|
|
438
538
|
sessionId,
|
|
@@ -444,6 +544,8 @@ export class DebugWebSocketServer {
|
|
|
444
544
|
this.sendMessage(ws, { type: 'action_dump', sessionId, dump }, request.deviceId);
|
|
445
545
|
},
|
|
446
546
|
});
|
|
547
|
+
// 保存 executor 引用到 session,以便 stop_debug 时可以中断
|
|
548
|
+
session.executor = executor;
|
|
447
549
|
const config = {
|
|
448
550
|
type: request.platform || 'android',
|
|
449
551
|
testName: 'ai-act',
|
|
@@ -457,26 +559,52 @@ export class DebugWebSocketServer {
|
|
|
457
559
|
deepThink: request.deepThink,
|
|
458
560
|
},
|
|
459
561
|
};
|
|
460
|
-
|
|
461
|
-
|
|
562
|
+
// 使用 AbortSignal 监听停止请求
|
|
563
|
+
const executePromise = executor.execute(config);
|
|
564
|
+
const abortPromise = new Promise((resolve) => {
|
|
565
|
+
abortController.signal.addEventListener('abort', () => {
|
|
566
|
+
resolve({ success: false, errorMessage: 'Action stopped by user' });
|
|
567
|
+
}, { once: true });
|
|
568
|
+
});
|
|
569
|
+
const result = await Promise.race([executePromise, abortPromise]);
|
|
570
|
+
// 清理 executor 引用
|
|
571
|
+
session.executor = undefined;
|
|
572
|
+
const status = result.success ? 'completed' : 'failed';
|
|
573
|
+
sessionManager.updateStatus(sessionId, status);
|
|
574
|
+
logger.info(`[AiAct] Execution finished: sessionId=${sessionId}, status=${status}, ws.readyState=${ws.readyState}`);
|
|
462
575
|
this.sendMessage(ws, {
|
|
463
576
|
type: 'ai_act_result',
|
|
464
577
|
sessionId,
|
|
465
578
|
success: result.success,
|
|
466
579
|
result: result.result,
|
|
467
|
-
dump: result.dump || '',
|
|
580
|
+
dump: result.executionDump || result.dump || '',
|
|
468
581
|
reportHTML: result.reportHTML || '',
|
|
469
582
|
error: result.errorMessage,
|
|
470
583
|
}, request.deviceId);
|
|
584
|
+
// 发送 debug_completed,让前端能正确识别执行完成状态
|
|
585
|
+
this.sendMessage(ws, {
|
|
586
|
+
type: 'debug_completed',
|
|
587
|
+
sessionId,
|
|
588
|
+
success: result.success,
|
|
589
|
+
}, request.deviceId);
|
|
590
|
+
logger.info(`[AiAct] Sent ai_act_result + debug_completed for sessionId=${sessionId}`);
|
|
471
591
|
}
|
|
472
592
|
catch (error) {
|
|
593
|
+
session.executor = undefined;
|
|
473
594
|
sessionManager.updateStatus(sessionId, 'failed');
|
|
595
|
+
logger.error(`[AiAct] Execution error: sessionId=${sessionId}, error=${error.message}, ws.readyState=${ws.readyState}`);
|
|
474
596
|
this.sendMessage(ws, {
|
|
475
597
|
type: 'ai_act_result',
|
|
476
598
|
sessionId,
|
|
477
599
|
success: false,
|
|
478
600
|
error: error.message,
|
|
479
601
|
}, request.deviceId);
|
|
602
|
+
// 异常时也发送 debug_completed,确保前端能退出执行中状态
|
|
603
|
+
this.sendMessage(ws, {
|
|
604
|
+
type: 'debug_completed',
|
|
605
|
+
sessionId,
|
|
606
|
+
success: false,
|
|
607
|
+
}, request.deviceId);
|
|
480
608
|
}
|
|
481
609
|
}
|
|
482
610
|
// ==================== Execute Web Action (Playwright + Midscene, with screencast) ====================
|
|
@@ -821,11 +949,49 @@ export class DebugWebSocketServer {
|
|
|
821
949
|
// ==================== Stop Debug ====================
|
|
822
950
|
async handleStopDebug(ws, request) {
|
|
823
951
|
const session = sessionManager.get(request.sessionId);
|
|
824
|
-
|
|
825
|
-
|
|
952
|
+
// Session 不存在或已结束,直接返回 debug_stopped(而非报错)
|
|
953
|
+
// 前端可能在执行完成后才发 stop 请求,此时 session 已被清理或状态已变更
|
|
954
|
+
if (!session || (session.status !== 'running' && session.status !== 'idle')) {
|
|
955
|
+
this.sendMessage(ws, { type: 'debug_stopped', sessionId: request.sessionId });
|
|
826
956
|
return;
|
|
827
957
|
}
|
|
828
|
-
//
|
|
958
|
+
// 仿照 playground cancelTask:先获取当前执行数据,再 destroy agent
|
|
959
|
+
let dump = '';
|
|
960
|
+
let reportHTML = '';
|
|
961
|
+
const agent = session.executor?.getAgent?.() || session.agent;
|
|
962
|
+
// 获取 dump 数据(必须在 destroy 之前,因为 dump 存储在 agent 内存中)
|
|
963
|
+
try {
|
|
964
|
+
if (agent && typeof agent.dumpDataString === 'function') {
|
|
965
|
+
dump = agent.dumpDataString({ inlineScreenshots: true }) || '';
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
catch (error) {
|
|
969
|
+
logger.warn(`Failed to get dump before cancel: ${error.message}`);
|
|
970
|
+
}
|
|
971
|
+
// 获取 reportHTML
|
|
972
|
+
try {
|
|
973
|
+
if (agent && typeof agent.reportHTMLString === 'function') {
|
|
974
|
+
reportHTML = agent.reportHTMLString({ inlineScreenshots: true }) || '';
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
logger.warn(`Failed to get reportHTML before cancel: ${error.message}`);
|
|
979
|
+
}
|
|
980
|
+
// 中断主进程内的执行(execute_action / execute_ai_act)
|
|
981
|
+
if (session.abortController && !session.abortController.signal.aborted) {
|
|
982
|
+
session.abortController.abort();
|
|
983
|
+
}
|
|
984
|
+
// 销毁 executor(释放 device/agent 资源)—— 仿照 playground 的 recreateAgent
|
|
985
|
+
if (session.executor && typeof session.executor.destroy === 'function') {
|
|
986
|
+
try {
|
|
987
|
+
await session.executor.destroy();
|
|
988
|
+
}
|
|
989
|
+
catch (error) {
|
|
990
|
+
logger.warn(`Executor destroy error: ${error.message}`);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
session.executor = undefined;
|
|
994
|
+
// Stop child process (for start_debug with worker process)
|
|
829
995
|
if (session.process) {
|
|
830
996
|
session.process.kill('SIGTERM');
|
|
831
997
|
}
|
|
@@ -841,7 +1007,28 @@ export class DebugWebSocketServer {
|
|
|
841
1007
|
}
|
|
842
1008
|
}
|
|
843
1009
|
sessionManager.updateStatus(request.sessionId, 'stopped');
|
|
844
|
-
|
|
1010
|
+
// 发送带执行数据的停止消息(仿照 playground cancel 返回 dump + reportHTML)
|
|
1011
|
+
this.sendMessage(ws, {
|
|
1012
|
+
type: 'debug_stopped',
|
|
1013
|
+
sessionId: request.sessionId,
|
|
1014
|
+
dump,
|
|
1015
|
+
reportHTML,
|
|
1016
|
+
});
|
|
1017
|
+
// 同时发送 action_result,让前端能获取到停止时的执行数据
|
|
1018
|
+
this.sendMessage(ws, {
|
|
1019
|
+
type: 'action_result',
|
|
1020
|
+
sessionId: request.sessionId,
|
|
1021
|
+
success: false,
|
|
1022
|
+
error: 'Action stopped by user',
|
|
1023
|
+
dump,
|
|
1024
|
+
reportHTML,
|
|
1025
|
+
});
|
|
1026
|
+
// 发送 debug_completed
|
|
1027
|
+
this.sendMessage(ws, {
|
|
1028
|
+
type: 'debug_completed',
|
|
1029
|
+
sessionId: request.sessionId,
|
|
1030
|
+
success: false,
|
|
1031
|
+
});
|
|
845
1032
|
}
|
|
846
1033
|
// ==================== Get Logs ====================
|
|
847
1034
|
async handleGetLogs(ws, request) {
|
|
@@ -853,6 +1040,26 @@ export class DebugWebSocketServer {
|
|
|
853
1040
|
this.sendMessage(ws, { type: 'all_logs', sessionId: request.sessionId, logs: session.logs });
|
|
854
1041
|
}
|
|
855
1042
|
// ==================== Utilities ====================
|
|
1043
|
+
/**
|
|
1044
|
+
* 将前端传来的 modelConfig 应用到环境变量
|
|
1045
|
+
* ActionExecutor 通过环境变量读取模型配置,所以需要同步更新
|
|
1046
|
+
*/
|
|
1047
|
+
applyModelConfig(modelConfig) {
|
|
1048
|
+
if (!modelConfig || typeof modelConfig !== 'object')
|
|
1049
|
+
return;
|
|
1050
|
+
const envMapping = {
|
|
1051
|
+
MIDSCENE_MODEL_BASE_URL: 'MIDSCENE_MODEL_BASE_URL',
|
|
1052
|
+
MIDSCENE_MODEL_API_KEY: 'MIDSCENE_MODEL_API_KEY',
|
|
1053
|
+
MIDSCENE_MODEL_NAME: 'MIDSCENE_MODEL_NAME',
|
|
1054
|
+
MIDSCENE_MODEL_FAMILY: 'MIDSCENE_MODEL_FAMILY',
|
|
1055
|
+
};
|
|
1056
|
+
for (const [configKey, envKey] of Object.entries(envMapping)) {
|
|
1057
|
+
if (modelConfig[configKey] && typeof modelConfig[configKey] === 'string') {
|
|
1058
|
+
process.env[envKey] = modelConfig[configKey];
|
|
1059
|
+
logger.info(`[ModelConfig] Applied ${envKey} from request`);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
856
1063
|
sendMessage(ws, message, deviceId) {
|
|
857
1064
|
try {
|
|
858
1065
|
const msg = {
|
|
@@ -861,11 +1068,31 @@ export class DebugWebSocketServer {
|
|
|
861
1068
|
timestamp: new Date().toISOString(),
|
|
862
1069
|
};
|
|
863
1070
|
if (ws.readyState === ws.OPEN) {
|
|
864
|
-
|
|
1071
|
+
const payload = JSON.stringify(msg);
|
|
1072
|
+
// 大数据消息(如 reportHTML)截断,避免超出 WebSocket 帧大小限制
|
|
1073
|
+
const MAX_PAYLOAD_SIZE = 2 * 1024 * 1024; // 2MB
|
|
1074
|
+
if (payload.length > MAX_PAYLOAD_SIZE) {
|
|
1075
|
+
logger.warn(`[WS] Message too large (${(payload.length / 1024 / 1024).toFixed(2)}MB), type=${message.type}, truncating reportHTML/dump`);
|
|
1076
|
+
// 截断 reportHTML 和 dump 字段
|
|
1077
|
+
if (msg.reportHTML && typeof msg.reportHTML === 'string' && msg.reportHTML.length > 512 * 1024) {
|
|
1078
|
+
msg.reportHTML = msg.reportHTML.substring(0, 512 * 1024) + '\n...[truncated]';
|
|
1079
|
+
}
|
|
1080
|
+
if (msg.dump && typeof msg.dump === 'string' && msg.dump.length > 512 * 1024) {
|
|
1081
|
+
msg.dump = msg.dump.substring(0, 512 * 1024) + '\n...[truncated]';
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
ws.send(payload, (err) => {
|
|
1085
|
+
if (err) {
|
|
1086
|
+
logger.error(`[WS] Send failed: type=${message.type}, error=${err.message}`);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
logger.warn(`[WS] Cannot send message: ws not open (readyState=${ws.readyState}), type=${message.type}, sessionId=${message.sessionId}`);
|
|
865
1092
|
}
|
|
866
1093
|
}
|
|
867
1094
|
catch (error) {
|
|
868
|
-
logger.error(`Send message error: ${error.message}`);
|
|
1095
|
+
logger.error(`Send message error: ${error.message}, type=${message.type}`);
|
|
869
1096
|
}
|
|
870
1097
|
}
|
|
871
1098
|
sendError(ws, error) {
|