fix: IoT多设备支持 + Review Pipeline审查消息 + 意图分析快速通道优化
- IoT Provider: 重写Execute()支持多设备命令批量执行,修复persona路径 - Intent Analyzer: 新增isStrongIoTCommand快速通道,跳过LLM分析节省2-3s - Orchestrator: parseReviewMessages()内联审查 + 快速通道扩展(chat/greeting跳过子会话) - Gateway: SSE review_messages解析→WebSocket结构化消息转发(action/chat) - Persona: 对话风格注入action格式指令(括号包裹动作描述) - Frontend: sessionStore历史消息msgType映射 - 新增E2E测试脚本 + 调试标准文档 + 第4轮修复报告 E2E验证: IoT设备操控✅ Review消息拆分✅ 快速通道✅ 响应时间~3.4s Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import { WebSocket } from 'ws';
|
||||
import http from 'http';
|
||||
|
||||
const CDP_HOST = 'localhost';
|
||||
const CDP_PORT = 9222;
|
||||
|
||||
function httpRequest(method, path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = http.request({ hostname: CDP_HOST, port: CDP_PORT, method, path }, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (c) => data += c);
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(data)); } catch(e) { resolve(data); }
|
||||
});
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
function cdpCommand(ws, method, params = {}) {
|
||||
const id = Math.floor(Math.random() * 1000000);
|
||||
return new Promise((resolve) => {
|
||||
const handler = (raw) => {
|
||||
try {
|
||||
const msg = JSON.parse(raw.toString());
|
||||
if (msg.id === id) {
|
||||
ws.off('message', handler);
|
||||
resolve(msg.result || msg);
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
ws.on('message', handler);
|
||||
ws.send(JSON.stringify({ id, method, params }));
|
||||
setTimeout(() => { ws.off('message', handler); resolve({ error: 'timeout' }); }, 8000);
|
||||
});
|
||||
}
|
||||
|
||||
async function testPage(label) {
|
||||
console.log(`\n=== ${label} ===`);
|
||||
const newTab = await httpRequest('PUT', '/json/new?about:blank');
|
||||
const ws = new WebSocket(newTab.webSocketDebuggerUrl);
|
||||
await new Promise((resolve) => ws.on('open', resolve));
|
||||
|
||||
await cdpCommand(ws, 'Runtime.enable');
|
||||
await cdpCommand(ws, 'Page.enable');
|
||||
await cdpCommand(ws, 'Log.enable');
|
||||
|
||||
const errors = [];
|
||||
const logs = [];
|
||||
ws.on('message', (raw) => {
|
||||
try {
|
||||
const msg = JSON.parse(raw.toString());
|
||||
if (msg.method === 'Runtime.exceptionThrown') {
|
||||
errors.push(msg.params.exceptionDetails.text || JSON.stringify(msg.params.exceptionDetails).substring(0, 200));
|
||||
}
|
||||
if (msg.method === 'Log.entryAdded' && msg.params.entry.level === 'error') {
|
||||
errors.push('[LOG] ' + msg.params.entry.text?.substring(0, 200));
|
||||
}
|
||||
if (msg.method === 'Runtime.consoleAPICalled') {
|
||||
logs.push(`[${msg.params.type}] ${msg.params.args?.map(a => a.value || '').join(' ').substring(0, 150)}`);
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
|
||||
await cdpCommand(ws, 'Page.navigate', { url: 'http://localhost:5199/' });
|
||||
await new Promise(r => setTimeout(r, 6000));
|
||||
|
||||
// Check #root
|
||||
const e1 = await cdpCommand(ws, 'Runtime.evaluate', {
|
||||
expression: `(() => { const r = document.getElementById('root'); return r ? (r.innerHTML.trim() ? 'CONTENT(' + r.innerHTML.length + ')' : 'EMPTY') : 'NO_ROOT'; })()`,
|
||||
returnByValue: true,
|
||||
});
|
||||
console.log(' #root:', e1?.result?.value);
|
||||
|
||||
// Check if JS loaded
|
||||
const e2 = await cdpCommand(ws, 'Runtime.evaluate', {
|
||||
expression: `typeof React !== 'undefined' ? 'React OK' : 'React MISSING'`,
|
||||
returnByValue: true,
|
||||
});
|
||||
console.log(' React:', e2?.result?.value);
|
||||
|
||||
// Check SW status
|
||||
const e3 = await cdpCommand(ws, 'Runtime.evaluate', {
|
||||
expression: `(() => { try { return 'serviceWorker' in navigator ? 'SW supported' : 'SW not supported'; } catch(e) { return 'Error: '+e.message; } })()`,
|
||||
returnByValue: true,
|
||||
});
|
||||
console.log(' SW:', e3?.result?.value);
|
||||
|
||||
console.log(' Errors:', errors.length);
|
||||
errors.forEach(e => console.log(' ', e.substring(0, 200)));
|
||||
console.log(' Logs:', logs.length);
|
||||
|
||||
ws.close();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// First visit - install SW
|
||||
await testPage('1st VISIT (SW install)');
|
||||
|
||||
// Wait a bit for SW activation
|
||||
console.log('\nWaiting 3s for SW activation...');
|
||||
await new Promise(r => setTimeout(r, 3000));
|
||||
|
||||
// Second visit - SW should be active
|
||||
await testPage('2nd VISIT (SW active)');
|
||||
|
||||
// Third visit
|
||||
await testPage('3rd VISIT');
|
||||
|
||||
console.log('\n=== DONE ===');
|
||||
}
|
||||
|
||||
main().catch(e => { console.error('Fatal:', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user