@aiscene/aiserver 1.9.6 → 1.9.7

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.
@@ -0,0 +1,283 @@
1
+ import axios from 'axios';
2
+ import { getNodeAuthHeaders } from '../auth/node-auth.js';
3
+ import { createLogger } from '../core/logger.js';
4
+ const defaultLogger = createLogger('TestCaseReferenceResolver');
5
+ const TEST_CASE_REFERENCE_MARKER = /\/\/\s*@test-case-reference\s+(\{.*\})\s*$/;
6
+ const PLUGIN_CONFIG_LINE = /\/\/\s*@plugin-config(?:\s+([a-zA-Z0-9_-]+))?\s+(\{.*\})\s*$/;
7
+ const PLUGIN_END_LINE = /\/\/\s*@plugin-end(?:\s+([a-zA-Z0-9_-]+))?\s*$/;
8
+ const LEGACY_REFERENCE_LINE = /\/\/\s*引用用例:\s*(.+)$/;
9
+ const LEGACY_REFERENCE_ID_LINE = /\/\/\s*用例ID:\s*(.+)$/;
10
+ function toRecord(value) {
11
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
12
+ }
13
+ function asString(value) {
14
+ return typeof value === 'string' ? value : '';
15
+ }
16
+ function normalizeApiUrl(apiUrl) {
17
+ return String(apiUrl || '').replace(/\/+$/, '');
18
+ }
19
+ function parseJsonObjectFromLine(line) {
20
+ const start = line.indexOf('{');
21
+ const end = line.lastIndexOf('}');
22
+ if (start < 0 || end <= start)
23
+ return null;
24
+ try {
25
+ const parsed = JSON.parse(line.slice(start, end + 1));
26
+ return toRecord(parsed);
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ function parsePluginConfigLine(line) {
33
+ const match = line.match(PLUGIN_CONFIG_LINE);
34
+ if (!match)
35
+ return null;
36
+ try {
37
+ const parsed = JSON.parse(match[2]);
38
+ const config = toRecord(parsed);
39
+ return config ? { instanceId: match[1] || '', config } : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ function findPluginEndIndex(lines, startIndex, instanceId) {
46
+ for (let i = startIndex + 1; i < lines.length; i++) {
47
+ const match = lines[i].match(PLUGIN_END_LINE);
48
+ if (!match)
49
+ continue;
50
+ const endInstanceId = match[1] || '';
51
+ if (!instanceId || !endInstanceId || endInstanceId === instanceId) {
52
+ return i;
53
+ }
54
+ }
55
+ return startIndex;
56
+ }
57
+ function isPluginConfigRemainderBeforeReference(line, nextLine) {
58
+ return /^\s*}+\s*,?\s*$/.test(line) && !!nextLine && TEST_CASE_REFERENCE_MARKER.test(nextLine);
59
+ }
60
+ function normalizeReferenceConfig(value) {
61
+ const record = toRecord(value);
62
+ if (!record)
63
+ return null;
64
+ const config = toRecord(record.config) || toRecord(record.param) || record;
65
+ const testCaseId = config.testCaseId ??
66
+ config.configId ??
67
+ config.id ??
68
+ record.testCaseId ??
69
+ record.configId ??
70
+ record.id;
71
+ if (testCaseId === undefined || testCaseId === null || String(testCaseId).trim() === '') {
72
+ return null;
73
+ }
74
+ return {
75
+ testCaseId: String(testCaseId),
76
+ configName: asString(config.configName || config.name || record.configName || record.name),
77
+ businessLineId: config.businessLineId ?? record.businessLineId,
78
+ };
79
+ }
80
+ function extractReferenceFromSerializedItem(item) {
81
+ const type = asString(item.type);
82
+ const pluginId = asString(item.pluginId);
83
+ if (type === 'test-case-reference' || pluginId === 'test-case-reference') {
84
+ return normalizeReferenceConfig(item);
85
+ }
86
+ const code = asString(item.code);
87
+ if (code) {
88
+ const markerLine = code.split('\n').find((line) => TEST_CASE_REFERENCE_MARKER.test(line));
89
+ if (markerLine) {
90
+ return normalizeReferenceConfig(parseJsonObjectFromLine(markerLine));
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+ function normalizeConfigPayload(payload) {
96
+ const root = toRecord(payload) || {};
97
+ const data = toRecord(root.data) || root;
98
+ const nestedData = toRecord(data.data);
99
+ const config = toRecord(data.config) || toRecord(nestedData?.config) || data;
100
+ return {
101
+ ...config,
102
+ businessLineId: config.businessLineId ?? data.businessLineId ?? nestedData?.businessLineId,
103
+ };
104
+ }
105
+ function pickScriptContent(config) {
106
+ const candidates = [
107
+ config.naturalLanguage,
108
+ config.natural_language,
109
+ config.script,
110
+ config.scriptContent,
111
+ config.script_content,
112
+ config.content,
113
+ config.code,
114
+ ];
115
+ const script = candidates.find((value) => typeof value === 'string' && value.trim() !== '');
116
+ return typeof script === 'string' ? script : '';
117
+ }
118
+ async function fetchConfigDetail(reference, options) {
119
+ const apiUrl = normalizeApiUrl(options.apiUrl);
120
+ if (!apiUrl) {
121
+ throw new Error('缺少后端 apiUrl,无法拉取引用用例');
122
+ }
123
+ const encodedId = encodeURIComponent(reference.testCaseId);
124
+ const urls = [
125
+ `${apiUrl}/rest/ai-validator/configs/${encodedId}`,
126
+ `${apiUrl}/api/ai-validator/configs/${encodedId}`,
127
+ ];
128
+ let lastError;
129
+ for (const url of urls) {
130
+ try {
131
+ const response = await axios.get(url, {
132
+ timeout: 15000,
133
+ headers: getNodeAuthHeaders(),
134
+ });
135
+ return normalizeConfigPayload(response.data);
136
+ }
137
+ catch (error) {
138
+ lastError = error;
139
+ }
140
+ }
141
+ const message = lastError instanceof Error ? lastError.message : String(lastError || 'unknown error');
142
+ throw new Error(`拉取引用用例失败: ${reference.configName || reference.testCaseId}, ${message}`);
143
+ }
144
+ async function resolveReferencedCase(reference, options, state) {
145
+ const logger = options.logger || defaultLogger;
146
+ const key = reference.testCaseId;
147
+ if (state.cache.has(key)) {
148
+ return state.cache.get(key) || '';
149
+ }
150
+ if (state.resolvingIds.has(key)) {
151
+ logger.warn?.(`[TestCaseReference] 检测到循环引用,已跳过: ${key}`);
152
+ return '';
153
+ }
154
+ state.resolvingIds.add(key);
155
+ try {
156
+ const config = await fetchConfigDetail(reference, options);
157
+ const script = pickScriptContent(config);
158
+ if (!script) {
159
+ logger.warn?.(`[TestCaseReference] 引用用例没有可执行脚本: ${reference.configName || key}`);
160
+ state.cache.set(key, '');
161
+ return '';
162
+ }
163
+ const resolved = await resolveTestCaseReferences(script, options, state);
164
+ const wrapped = [
165
+ `// ===== 引用用例开始: ${reference.configName || asString(config.configName) || key} (${key}) =====`,
166
+ resolved,
167
+ `// ===== 引用用例结束: ${reference.configName || asString(config.configName) || key} (${key}) =====`,
168
+ ].filter(Boolean).join('\n');
169
+ state.cache.set(key, wrapped);
170
+ return wrapped;
171
+ }
172
+ finally {
173
+ state.resolvingIds.delete(key);
174
+ }
175
+ }
176
+ async function resolveSerializedScript(items, options, state) {
177
+ const dependencies = [];
178
+ const mainParts = [];
179
+ for (const item of items) {
180
+ const record = toRecord(item);
181
+ if (!record)
182
+ continue;
183
+ const reference = extractReferenceFromSerializedItem(record);
184
+ if (reference) {
185
+ const resolved = await resolveReferencedCase(reference, options, state);
186
+ if (resolved.trim())
187
+ dependencies.push(resolved);
188
+ continue;
189
+ }
190
+ const code = asString(record.code);
191
+ if (code.trim()) {
192
+ mainParts.push(await resolveRawScript(code, options, state));
193
+ }
194
+ }
195
+ return [...dependencies, ...mainParts].filter((part) => part.trim() !== '').join('\n\n');
196
+ }
197
+ async function resolveRawScript(input, options, state) {
198
+ const lines = input.split('\n');
199
+ const dependencies = [];
200
+ const outputLines = [];
201
+ for (let i = 0; i < lines.length; i++) {
202
+ const line = lines[i];
203
+ if (isPluginConfigRemainderBeforeReference(line, lines[i + 1])) {
204
+ continue;
205
+ }
206
+ if (line.includes('@plugin-config')) {
207
+ const parsedPlugin = parsePluginConfigLine(line);
208
+ const pluginConfig = parsedPlugin?.config || parseJsonObjectFromLine(line);
209
+ const pluginId = asString(pluginConfig?.pluginId);
210
+ if (pluginId === 'test-case-reference') {
211
+ const reference = normalizeReferenceConfig(pluginConfig?.config);
212
+ if (reference) {
213
+ const resolved = await resolveReferencedCase(reference, options, state);
214
+ if (resolved.trim())
215
+ dependencies.push(resolved);
216
+ }
217
+ i = findPluginEndIndex(lines, i, parsedPlugin?.instanceId || '');
218
+ continue;
219
+ }
220
+ }
221
+ const markerMatch = line.match(TEST_CASE_REFERENCE_MARKER);
222
+ if (markerMatch) {
223
+ const reference = normalizeReferenceConfig(parseJsonObjectFromLine(line));
224
+ if (reference) {
225
+ const resolved = await resolveReferencedCase(reference, options, state);
226
+ if (resolved.trim())
227
+ dependencies.push(resolved);
228
+ }
229
+ if (lines[i + 1]?.includes('[TestCaseReference] 引用用例将在执行前展开')) {
230
+ i += 1;
231
+ }
232
+ continue;
233
+ }
234
+ const legacyMatch = line.match(LEGACY_REFERENCE_LINE);
235
+ if (legacyMatch) {
236
+ let referenceId = '';
237
+ let endIndex = i;
238
+ for (let j = i + 1; j < Math.min(i + 20, lines.length); j++) {
239
+ const idMatch = lines[j].match(LEGACY_REFERENCE_ID_LINE);
240
+ if (idMatch)
241
+ referenceId = idMatch[1].trim();
242
+ endIndex = j;
243
+ if (j > i + 1 && lines[j].includes('// ========================================'))
244
+ break;
245
+ }
246
+ if (referenceId) {
247
+ const resolved = await resolveReferencedCase({
248
+ testCaseId: referenceId,
249
+ configName: legacyMatch[1].trim(),
250
+ }, options, state);
251
+ if (resolved.trim())
252
+ dependencies.push(resolved);
253
+ i = endIndex;
254
+ continue;
255
+ }
256
+ }
257
+ outputLines.push(line);
258
+ }
259
+ const mainScript = outputLines.join('\n').trim();
260
+ return [...dependencies, mainScript].filter((part) => part.trim() !== '').join('\n\n');
261
+ }
262
+ export async function resolveTestCaseReferences(input, options, state) {
263
+ if (!input || typeof input !== 'string')
264
+ return input || '';
265
+ const currentState = state || {
266
+ resolvingIds: new Set(),
267
+ cache: new Map(),
268
+ };
269
+ const trimmed = input.trim();
270
+ if (!trimmed)
271
+ return input;
272
+ try {
273
+ const parsed = JSON.parse(trimmed);
274
+ if (Array.isArray(parsed)) {
275
+ return await resolveSerializedScript(parsed, options, currentState);
276
+ }
277
+ }
278
+ catch {
279
+ // Not serialized plugin JSON; fall through to marker parsing.
280
+ }
281
+ return await resolveRawScript(input, options, currentState);
282
+ }
283
+ //# sourceMappingURL=test-case-reference-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-case-reference-resolver.js","sourceRoot":"","sources":["../../src/task/test-case-reference-resolver.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"debug-page.d.ts","sourceRoot":"","sources":["../../src/web/debug-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAstDzC"}
1
+ {"version":3,"file":"debug-page.d.ts","sourceRoot":"","sources":["../../src/web/debug-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CA6sDzC"}
@@ -1638,37 +1638,43 @@ async function handleAiGenerate() {
1638
1638
  const platform = document.getElementById('debug-platform').value;
1639
1639
  const packageName = getPackageName();
1640
1640
  const testUrl = document.getElementById('debug-url').value || '';
1641
- const erp = 'system';
1642
-
1643
- // 构建请求参数
1644
- const body = {
1645
- traceId: Date.now().toString() + Math.random().toString(36).substr(2, 9),
1646
- reqId: Date.now().toString(),
1647
- erp: erp,
1648
- keyword: keyword,
1649
- platform: platform,
1650
- packageName: packageName,
1651
- testUrl: testUrl
1652
- };
1653
1641
 
1654
- const headers = {
1655
- 'Content-Type': 'application/json',
1656
- 'Accept': 'text/event-stream',
1657
- 'autobots-agent-id': '30323',
1658
- 'autobots-token': '60e7b3f68f654e9992ae0d403d2d90e5'
1659
- };
1642
+ const traceId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
1643
+ const reqId = Date.now().toString();
1644
+ const autobotsSearchUrl = window.__AUTOBOTS_SEARCH_AI_SSE_URL__ || 'http://autobots-bk.jd.local/autobots/api/v1/searchAiSse';
1645
+ const autobotsAgentId = window.__AUTOBOTS_AGENT_ID__;
1646
+ const autobotsToken = window.__AUTOBOTS_TOKEN__;
1647
+ if (!autobotsAgentId || !autobotsToken) {
1648
+ throw new Error('缺少 Autobots SSE 配置:__AUTOBOTS_AGENT_ID__ / __AUTOBOTS_TOKEN__');
1649
+ }
1660
1650
 
1661
- // 直接发送fetch请求处理SSE
1662
- const response = await fetch('http://autobots-bk.jd.local/autobots/api/v1/searchAiSse', {
1651
+ // 直接请求公司部署的 Autobots SSE 服务。
1652
+ const response = await fetch(autobotsSearchUrl, {
1663
1653
  method: 'POST',
1664
- headers: headers,
1665
- body: JSON.stringify(body),
1654
+ headers: {
1655
+ 'Content-Type': 'application/json',
1656
+ 'Accept': 'text/event-stream',
1657
+ 'autobots-agent-id': autobotsAgentId,
1658
+ 'autobots-token': autobotsToken
1659
+ },
1660
+ body: JSON.stringify({
1661
+ traceId: traceId,
1662
+ reqId: reqId,
1663
+ erp: 'system',
1664
+ keyword: keyword,
1665
+ platform: platform,
1666
+ testUrl: testUrl,
1667
+ packageName: packageName,
1668
+ }),
1666
1669
  });
1667
1670
 
1668
1671
  if (!response.ok) {
1669
1672
  throw new Error('HTTP ' + response.status);
1670
1673
  }
1671
1674
 
1675
+ // 脚本编辑器 - 记住原有内容
1676
+ const editor = document.getElementById('debug-script');
1677
+ const existingContent = editor.value.trim();
1672
1678
  if (!response.body) {
1673
1679
  throw new Error('No response body');
1674
1680
  }
@@ -1678,54 +1684,39 @@ async function handleAiGenerate() {
1678
1684
  let buffer = '';
1679
1685
  let finalContent = '';
1680
1686
 
1681
- // 脚本编辑器 - 记住原有内容
1682
- const editor = document.getElementById('debug-script');
1683
- const existingContent = editor.value.trim();
1684
-
1685
1687
  while (true) {
1686
1688
  const { done, value } = await reader.read();
1687
- if (done) {
1688
- addDebugLog('脚本生成完成', 'success');
1689
- break;
1690
- }
1689
+ if (done) break;
1691
1690
 
1692
1691
  buffer += decoder.decode(value, { stream: true });
1693
-
1694
- // 按行分割处理
1695
1692
  const lines = buffer.split('\\n');
1696
1693
  buffer = lines.pop() || '';
1697
1694
 
1698
1695
  for (const line of lines) {
1699
- if (line.startsWith('data:')) {
1700
- try {
1701
- const jsonStr = line.slice(5).trim();
1702
- const parsedData = JSON.parse(jsonStr);
1703
- const responseContent = parsedData.data?.response || parsedData.response || '';
1704
- const responseAll = parsedData.data?.responseAll || parsedData.responseAll || '';
1705
-
1706
- if (responseContent) {
1707
- const cleanContent = cleanCodeBlock(responseContent);
1708
- finalContent = cleanContent;
1709
- }
1710
-
1711
- if (parsedData.data?.status === 'finished' || parsedData.status === 'finished') {
1712
- if (responseAll) {
1713
- const cleanContent = cleanCodeBlock(responseAll);
1714
- finalContent = cleanContent;
1715
- }
1716
- }
1717
-
1718
- // 流式过程中实时预览生成内容
1719
- if (finalContent) {
1720
- editor.value = finalContent;
1721
- editor.scrollTop = editor.scrollHeight;
1722
- }
1723
- } catch (error) {
1724
- // 忽略解析错误
1696
+ if (!line.startsWith('data:')) continue;
1697
+ try {
1698
+ const jsonStr = line.slice(5).trim();
1699
+ if (!jsonStr || jsonStr === '[DONE]') continue;
1700
+ const parsedData = JSON.parse(jsonStr);
1701
+ const responseContent = parsedData.data?.response || parsedData.response || '';
1702
+ const responseAll = parsedData.data?.responseAll || parsedData.responseAll || '';
1703
+
1704
+ if (responseAll) {
1705
+ finalContent = cleanCodeBlock(responseAll);
1706
+ } else if (responseContent) {
1707
+ finalContent = cleanCodeBlock(finalContent + responseContent);
1708
+ }
1709
+
1710
+ if (finalContent) {
1711
+ editor.value = finalContent;
1712
+ editor.scrollTop = editor.scrollHeight;
1725
1713
  }
1714
+ } catch (error) {
1715
+ // 忽略单行解析错误,继续读取后续 SSE。
1726
1716
  }
1727
1717
  }
1728
1718
  }
1719
+ addDebugLog('脚本生成完成', 'success');
1729
1720
 
1730
1721
  // 生成完成,将最终内容追加到编辑器原有内容后面
1731
1722
  if (finalContent) {
@@ -1 +1 @@
1
- {"version":3,"file":"debug-page.js","sourceRoot":"","sources":["../../src/web/debug-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAotDR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"debug-page.js","sourceRoot":"","sources":["../../src/web/debug-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2sDR,CAAC;AACF,CAAC"}
@@ -1,10 +1,15 @@
1
1
  import type { ServerConfig } from '../config/schema.js';
2
+ import type { BatchActionRequest } from '../debug/types.js';
2
3
  export declare class WebServer {
3
4
  private app;
4
5
  private config;
5
6
  private server;
7
+ private debugWebSocketServer;
6
8
  private authWaiters;
7
9
  constructor();
10
+ bindDebugWebSocketServer(server: {
11
+ runBatchActionInBackground: (request: BatchActionRequest) => void;
12
+ }): void;
8
13
  private setupMiddleware;
9
14
  private setupApiRoutes;
10
15
  private setupDetailRoutes;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAsnBxD,qBAAa,SAAS;IACpB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAIX;;IAUR,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,cAAc;IAo2BtB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,eAAe;IA0evB,OAAO,CAAC,iBAAiB;IAqFzB,OAAO,CAAC,kBAAkB;IAgF1B,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1C,KAAK,IAAI,IAAI;IAQb,eAAe,CAAC,iBAAiB,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAShF,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,yBAAyB;CAOlC;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAknB5D,qBAAa,SAAS;IACpB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,oBAAoB,CAAsF;IAClH,OAAO,CAAC,WAAW,CAIX;;IAUR,wBAAwB,CAAC,MAAM,EAAE;QAAE,0BAA0B,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAA;KAAE,GAAG,IAAI;IAI7G,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,cAAc;IAs4BtB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,eAAe;IA0evB,OAAO,CAAC,iBAAiB;IAqFzB,OAAO,CAAC,kBAAkB;IAgF1B,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1C,KAAK,IAAI,IAAI;IAQb,eAAe,CAAC,iBAAiB,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAShF,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,yBAAyB;CAOlC;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
@@ -595,6 +595,7 @@ export class WebServer {
595
595
  app;
596
596
  config;
597
597
  server = null;
598
+ debugWebSocketServer = null;
598
599
  authWaiters = [];
599
600
  constructor() {
600
601
  this.app = express();
@@ -603,6 +604,9 @@ export class WebServer {
603
604
  this.setupDetailRoutes();
604
605
  this.setupStaticFiles();
605
606
  }
607
+ bindDebugWebSocketServer(server) {
608
+ this.debugWebSocketServer = server;
609
+ }
606
610
  setupMiddleware() {
607
611
  this.app.use(express.json());
608
612
  this.app.use((_, res, next) => {
@@ -691,6 +695,37 @@ export class WebServer {
691
695
  res.status(400).json({ success: false, message });
692
696
  }
693
697
  });
698
+ api.post('/batch-action', (req, res) => {
699
+ try {
700
+ if (!this.debugWebSocketServer) {
701
+ res.status(503).json({ success: false, message: 'Debug 执行服务尚未启动' });
702
+ return;
703
+ }
704
+ const request = req.body;
705
+ const batchId = request?.batchId;
706
+ const cases = Array.isArray(request?.cases) ? request.cases : [];
707
+ if (!batchId || cases.length === 0) {
708
+ res.status(400).json({ success: false, message: 'batch_action requires batchId and non-empty cases array' });
709
+ return;
710
+ }
711
+ this.debugWebSocketServer.runBatchActionInBackground({
712
+ ...request,
713
+ type: 'batch_action',
714
+ });
715
+ res.json({
716
+ success: true,
717
+ message: '本地批次已接收,AIServer 将在后台执行',
718
+ data: {
719
+ batchId,
720
+ totalCases: cases.length,
721
+ platform: request.platform,
722
+ },
723
+ });
724
+ }
725
+ catch (error) {
726
+ res.status(500).json({ success: false, message: error.message });
727
+ }
728
+ });
694
729
  // ===== Dashboard =====
695
730
  api.get('/dashboard', (_, res) => {
696
731
  const devices = deviceRepo.getAll();