@ai-jshook/mcp 0.1.1
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/.env.example +38 -0
- package/CLAUDE.md +170 -0
- package/README.md +564 -0
- package/bun.lock +1484 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/analyzer/AISummarizer.d.ts +41 -0
- package/dist/modules/analyzer/AISummarizer.d.ts.map +1 -0
- package/dist/modules/analyzer/AISummarizer.js +186 -0
- package/dist/modules/analyzer/AISummarizer.js.map +1 -0
- package/dist/modules/analyzer/CodeAnalyzer.d.ts +28 -0
- package/dist/modules/analyzer/CodeAnalyzer.d.ts.map +1 -0
- package/dist/modules/analyzer/CodeAnalyzer.js +1287 -0
- package/dist/modules/analyzer/CodeAnalyzer.js.map +1 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.d.ts +114 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.d.ts.map +1 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.js +1176 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.js.map +1 -0
- package/dist/modules/browser/BrowserModeManager.d.ts +31 -0
- package/dist/modules/browser/BrowserModeManager.d.ts.map +1 -0
- package/dist/modules/browser/BrowserModeManager.js +241 -0
- package/dist/modules/browser/BrowserModeManager.js.map +1 -0
- package/dist/modules/captcha/AICaptchaDetector.d.ts +32 -0
- package/dist/modules/captcha/AICaptchaDetector.d.ts.map +1 -0
- package/dist/modules/captcha/AICaptchaDetector.js +387 -0
- package/dist/modules/captcha/AICaptchaDetector.js.map +1 -0
- package/dist/modules/captcha/CaptchaDetector.d.ts +28 -0
- package/dist/modules/captcha/CaptchaDetector.d.ts.map +1 -0
- package/dist/modules/captcha/CaptchaDetector.js +513 -0
- package/dist/modules/captcha/CaptchaDetector.js.map +1 -0
- package/dist/modules/collector/CodeCache.d.ts +37 -0
- package/dist/modules/collector/CodeCache.d.ts.map +1 -0
- package/dist/modules/collector/CodeCache.js +188 -0
- package/dist/modules/collector/CodeCache.js.map +1 -0
- package/dist/modules/collector/CodeCollector.d.ts +107 -0
- package/dist/modules/collector/CodeCollector.d.ts.map +1 -0
- package/dist/modules/collector/CodeCollector.js +796 -0
- package/dist/modules/collector/CodeCollector.js.map +1 -0
- package/dist/modules/collector/CodeCompressor.d.ts +65 -0
- package/dist/modules/collector/CodeCompressor.d.ts.map +1 -0
- package/dist/modules/collector/CodeCompressor.js +245 -0
- package/dist/modules/collector/CodeCompressor.js.map +1 -0
- package/dist/modules/collector/DOMInspector.d.ts +51 -0
- package/dist/modules/collector/DOMInspector.d.ts.map +1 -0
- package/dist/modules/collector/DOMInspector.js +437 -0
- package/dist/modules/collector/DOMInspector.js.map +1 -0
- package/dist/modules/collector/PageController.d.ts +79 -0
- package/dist/modules/collector/PageController.d.ts.map +1 -0
- package/dist/modules/collector/PageController.js +287 -0
- package/dist/modules/collector/PageController.js.map +1 -0
- package/dist/modules/collector/SmartCodeCollector.d.ts +38 -0
- package/dist/modules/collector/SmartCodeCollector.d.ts.map +1 -0
- package/dist/modules/collector/SmartCodeCollector.js +208 -0
- package/dist/modules/collector/SmartCodeCollector.js.map +1 -0
- package/dist/modules/collector/StreamingCollector.d.ts +46 -0
- package/dist/modules/collector/StreamingCollector.d.ts.map +1 -0
- package/dist/modules/collector/StreamingCollector.js +127 -0
- package/dist/modules/collector/StreamingCollector.js.map +1 -0
- package/dist/modules/crypto/CryptoDetector.d.ts +22 -0
- package/dist/modules/crypto/CryptoDetector.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoDetector.js +168 -0
- package/dist/modules/crypto/CryptoDetector.js.map +1 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts +31 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.js +269 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.js.map +1 -0
- package/dist/modules/crypto/CryptoRules.d.ts +59 -0
- package/dist/modules/crypto/CryptoRules.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoRules.js +234 -0
- package/dist/modules/crypto/CryptoRules.js.map +1 -0
- package/dist/modules/debugger/BlackboxManager.d.ts +14 -0
- package/dist/modules/debugger/BlackboxManager.d.ts.map +1 -0
- package/dist/modules/debugger/BlackboxManager.js +98 -0
- package/dist/modules/debugger/BlackboxManager.js.map +1 -0
- package/dist/modules/debugger/DebuggerManager.d.ts +138 -0
- package/dist/modules/debugger/DebuggerManager.d.ts.map +1 -0
- package/dist/modules/debugger/DebuggerManager.js +777 -0
- package/dist/modules/debugger/DebuggerManager.js.map +1 -0
- package/dist/modules/debugger/EventBreakpointManager.d.ts +30 -0
- package/dist/modules/debugger/EventBreakpointManager.d.ts.map +1 -0
- package/dist/modules/debugger/EventBreakpointManager.js +125 -0
- package/dist/modules/debugger/EventBreakpointManager.js.map +1 -0
- package/dist/modules/debugger/RuntimeInspector.d.ts +54 -0
- package/dist/modules/debugger/RuntimeInspector.d.ts.map +1 -0
- package/dist/modules/debugger/RuntimeInspector.js +277 -0
- package/dist/modules/debugger/RuntimeInspector.js.map +1 -0
- package/dist/modules/debugger/ScriptManager.d.ts +94 -0
- package/dist/modules/debugger/ScriptManager.d.ts.map +1 -0
- package/dist/modules/debugger/ScriptManager.js +433 -0
- package/dist/modules/debugger/ScriptManager.js.map +1 -0
- package/dist/modules/debugger/WatchExpressionManager.d.ts +52 -0
- package/dist/modules/debugger/WatchExpressionManager.d.ts.map +1 -0
- package/dist/modules/debugger/WatchExpressionManager.js +136 -0
- package/dist/modules/debugger/WatchExpressionManager.js.map +1 -0
- package/dist/modules/debugger/XHRBreakpointManager.d.ts +21 -0
- package/dist/modules/debugger/XHRBreakpointManager.d.ts.map +1 -0
- package/dist/modules/debugger/XHRBreakpointManager.js +81 -0
- package/dist/modules/debugger/XHRBreakpointManager.js.map +1 -0
- package/dist/modules/deobfuscator/ASTOptimizer.d.ts +12 -0
- package/dist/modules/deobfuscator/ASTOptimizer.d.ts.map +1 -0
- package/dist/modules/deobfuscator/ASTOptimizer.js +234 -0
- package/dist/modules/deobfuscator/ASTOptimizer.js.map +1 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts +52 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.js +985 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/Deobfuscator.d.ts +23 -0
- package/dist/modules/deobfuscator/Deobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/Deobfuscator.js +487 -0
- package/dist/modules/deobfuscator/Deobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts +19 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.js +594 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts +28 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.js +239 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts +38 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.js +191 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.js.map +1 -0
- package/dist/modules/detector/ObfuscationDetector.d.ts +35 -0
- package/dist/modules/detector/ObfuscationDetector.d.ts.map +1 -0
- package/dist/modules/detector/ObfuscationDetector.js +278 -0
- package/dist/modules/detector/ObfuscationDetector.js.map +1 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts +32 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts.map +1 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.js +548 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.js.map +1 -0
- package/dist/modules/emulator/BrowserAPIDatabase.d.ts +34 -0
- package/dist/modules/emulator/BrowserAPIDatabase.d.ts.map +1 -0
- package/dist/modules/emulator/BrowserAPIDatabase.js +326 -0
- package/dist/modules/emulator/BrowserAPIDatabase.js.map +1 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.d.ts +47 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.d.ts.map +1 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.js +493 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.js.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulator.d.ts +27 -0
- package/dist/modules/emulator/EnvironmentEmulator.d.ts.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulator.js +1113 -0
- package/dist/modules/emulator/EnvironmentEmulator.js.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts +26 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js +493 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js.map +1 -0
- package/dist/modules/emulator/templates/chrome-env.d.ts +260 -0
- package/dist/modules/emulator/templates/chrome-env.d.ts.map +1 -0
- package/dist/modules/emulator/templates/chrome-env.js +253 -0
- package/dist/modules/emulator/templates/chrome-env.js.map +1 -0
- package/dist/modules/hook/AIHookGenerator.d.ts +53 -0
- package/dist/modules/hook/AIHookGenerator.d.ts.map +1 -0
- package/dist/modules/hook/AIHookGenerator.js +353 -0
- package/dist/modules/hook/AIHookGenerator.js.map +1 -0
- package/dist/modules/hook/HookManager.d.ts +67 -0
- package/dist/modules/hook/HookManager.d.ts.map +1 -0
- package/dist/modules/hook/HookManager.js +1225 -0
- package/dist/modules/hook/HookManager.js.map +1 -0
- package/dist/modules/monitor/ConsoleMonitor.d.ts +140 -0
- package/dist/modules/monitor/ConsoleMonitor.d.ts.map +1 -0
- package/dist/modules/monitor/ConsoleMonitor.js +834 -0
- package/dist/modules/monitor/ConsoleMonitor.js.map +1 -0
- package/dist/modules/monitor/PerformanceMonitor.d.ts +65 -0
- package/dist/modules/monitor/PerformanceMonitor.d.ts.map +1 -0
- package/dist/modules/monitor/PerformanceMonitor.js +175 -0
- package/dist/modules/monitor/PerformanceMonitor.js.map +1 -0
- package/dist/modules/stealth/StealthScripts2025.d.ts +17 -0
- package/dist/modules/stealth/StealthScripts2025.d.ts.map +1 -0
- package/dist/modules/stealth/StealthScripts2025.js +274 -0
- package/dist/modules/stealth/StealthScripts2025.js.map +1 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts +69 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts.map +1 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.js +232 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.js.map +1 -0
- package/dist/modules/symbolic/SymbolicExecutor.d.ts +69 -0
- package/dist/modules/symbolic/SymbolicExecutor.d.ts.map +1 -0
- package/dist/modules/symbolic/SymbolicExecutor.js +346 -0
- package/dist/modules/symbolic/SymbolicExecutor.js.map +1 -0
- package/dist/server/AIHookToolDefinitions.d.ts +3 -0
- package/dist/server/AIHookToolDefinitions.d.ts.map +1 -0
- package/dist/server/AIHookToolDefinitions.js +284 -0
- package/dist/server/AIHookToolDefinitions.js.map +1 -0
- package/dist/server/AIHookToolHandlers.d.ts +50 -0
- package/dist/server/AIHookToolHandlers.d.ts.map +1 -0
- package/dist/server/AIHookToolHandlers.js +311 -0
- package/dist/server/AIHookToolHandlers.js.map +1 -0
- package/dist/server/AdvancedToolDefinitions.d.ts +3 -0
- package/dist/server/AdvancedToolDefinitions.d.ts.map +1 -0
- package/dist/server/AdvancedToolDefinitions.js +218 -0
- package/dist/server/AdvancedToolDefinitions.js.map +1 -0
- package/dist/server/AdvancedToolHandlers.d.ts +85 -0
- package/dist/server/AdvancedToolHandlers.d.ts.map +1 -0
- package/dist/server/AdvancedToolHandlers.js +431 -0
- package/dist/server/AdvancedToolHandlers.js.map +1 -0
- package/dist/server/BrowserToolDefinitions.d.ts +3 -0
- package/dist/server/BrowserToolDefinitions.d.ts.map +1 -0
- package/dist/server/BrowserToolDefinitions.js +841 -0
- package/dist/server/BrowserToolDefinitions.js.map +1 -0
- package/dist/server/BrowserToolHandlers.d.ts +290 -0
- package/dist/server/BrowserToolHandlers.d.ts.map +1 -0
- package/dist/server/BrowserToolHandlers.js +784 -0
- package/dist/server/BrowserToolHandlers.js.map +1 -0
- package/dist/server/CacheToolDefinitions.d.ts +3 -0
- package/dist/server/CacheToolDefinitions.d.ts.map +1 -0
- package/dist/server/CacheToolDefinitions.js +166 -0
- package/dist/server/CacheToolDefinitions.js.map +1 -0
- package/dist/server/DebuggerToolDefinitions.d.ts +3 -0
- package/dist/server/DebuggerToolDefinitions.d.ts.map +1 -0
- package/dist/server/DebuggerToolDefinitions.js +600 -0
- package/dist/server/DebuggerToolDefinitions.js.map +1 -0
- package/dist/server/DebuggerToolHandlers.d.ts +230 -0
- package/dist/server/DebuggerToolHandlers.d.ts.map +1 -0
- package/dist/server/DebuggerToolHandlers.js +935 -0
- package/dist/server/DebuggerToolHandlers.js.map +1 -0
- package/dist/server/MCPServer.d.ts +55 -0
- package/dist/server/MCPServer.d.ts.map +1 -0
- package/dist/server/MCPServer.js +1344 -0
- package/dist/server/MCPServer.js.map +1 -0
- package/dist/server/TokenBudgetToolDefinitions.d.ts +3 -0
- package/dist/server/TokenBudgetToolDefinitions.d.ts.map +1 -0
- package/dist/server/TokenBudgetToolDefinitions.js +114 -0
- package/dist/server/TokenBudgetToolDefinitions.js.map +1 -0
- package/dist/services/LLMService.d.ts +41 -0
- package/dist/services/LLMService.d.ts.map +1 -0
- package/dist/services/LLMService.js +792 -0
- package/dist/services/LLMService.js.map +1 -0
- package/dist/types/index.d.ts +527 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/AdaptiveDataSerializer.d.ts +27 -0
- package/dist/utils/AdaptiveDataSerializer.d.ts.map +1 -0
- package/dist/utils/AdaptiveDataSerializer.js +215 -0
- package/dist/utils/AdaptiveDataSerializer.js.map +1 -0
- package/dist/utils/CacheAdapters.d.ts +30 -0
- package/dist/utils/CacheAdapters.d.ts.map +1 -0
- package/dist/utils/CacheAdapters.js +83 -0
- package/dist/utils/CacheAdapters.js.map +1 -0
- package/dist/utils/TokenBudgetManager.d.ts +52 -0
- package/dist/utils/TokenBudgetManager.d.ts.map +1 -0
- package/dist/utils/TokenBudgetManager.js +190 -0
- package/dist/utils/TokenBudgetManager.js.map +1 -0
- package/dist/utils/UnifiedCacheManager.d.ts +55 -0
- package/dist/utils/UnifiedCacheManager.d.ts.map +1 -0
- package/dist/utils/UnifiedCacheManager.js +207 -0
- package/dist/utils/UnifiedCacheManager.js.map +1 -0
- package/dist/utils/cache.d.ts +13 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +92 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/config.d.ts +7 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +93 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/detailedDataManager.d.ts +60 -0
- package/dist/utils/detailedDataManager.d.ts.map +1 -0
- package/dist/utils/detailedDataManager.js +204 -0
- package/dist/utils/detailedDataManager.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/parallel.d.ts +40 -0
- package/dist/utils/parallel.d.ts.map +1 -0
- package/dist/utils/parallel.js +148 -0
- package/dist/utils/parallel.js.map +1 -0
- package/package.json +94 -0
- package/server.json +39 -0
- package/tsconfig.dev.json +14 -0
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
export class ConsoleMonitor {
|
|
3
|
+
collector;
|
|
4
|
+
cdpSession = null;
|
|
5
|
+
messages = [];
|
|
6
|
+
MAX_MESSAGES = 1000;
|
|
7
|
+
exceptions = [];
|
|
8
|
+
MAX_EXCEPTIONS = 500;
|
|
9
|
+
networkEnabled = false;
|
|
10
|
+
requests = new Map();
|
|
11
|
+
responses = new Map();
|
|
12
|
+
MAX_NETWORK_RECORDS = 500;
|
|
13
|
+
networkListeners = {};
|
|
14
|
+
objectCache = new Map();
|
|
15
|
+
constructor(collector) {
|
|
16
|
+
this.collector = collector;
|
|
17
|
+
}
|
|
18
|
+
async enable(options) {
|
|
19
|
+
if (this.cdpSession) {
|
|
20
|
+
logger.warn('ConsoleMonitor already enabled');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const page = await this.collector.getActivePage();
|
|
24
|
+
this.cdpSession = await page.createCDPSession();
|
|
25
|
+
await this.cdpSession.send('Runtime.enable');
|
|
26
|
+
await this.cdpSession.send('Console.enable');
|
|
27
|
+
this.cdpSession.on('Runtime.consoleAPICalled', (params) => {
|
|
28
|
+
const stackTrace = params.stackTrace?.callFrames?.map((frame) => ({
|
|
29
|
+
functionName: frame.functionName || '(anonymous)',
|
|
30
|
+
url: frame.url,
|
|
31
|
+
lineNumber: frame.lineNumber,
|
|
32
|
+
columnNumber: frame.columnNumber,
|
|
33
|
+
})) || [];
|
|
34
|
+
const message = {
|
|
35
|
+
type: params.type,
|
|
36
|
+
text: params.args.map((arg) => this.formatRemoteObject(arg)).join(' '),
|
|
37
|
+
args: params.args.map((arg) => this.extractValue(arg)),
|
|
38
|
+
timestamp: params.timestamp,
|
|
39
|
+
stackTrace,
|
|
40
|
+
url: stackTrace[0]?.url,
|
|
41
|
+
lineNumber: stackTrace[0]?.lineNumber,
|
|
42
|
+
columnNumber: stackTrace[0]?.columnNumber,
|
|
43
|
+
};
|
|
44
|
+
this.messages.push(message);
|
|
45
|
+
if (this.messages.length > this.MAX_MESSAGES) {
|
|
46
|
+
this.messages = this.messages.slice(-Math.floor(this.MAX_MESSAGES / 2));
|
|
47
|
+
}
|
|
48
|
+
logger.debug(`Console ${params.type}: ${message.text}`);
|
|
49
|
+
});
|
|
50
|
+
this.cdpSession.on('Console.messageAdded', (params) => {
|
|
51
|
+
const msg = params.message;
|
|
52
|
+
const message = {
|
|
53
|
+
type: msg.level,
|
|
54
|
+
text: msg.text,
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
url: msg.url,
|
|
57
|
+
lineNumber: msg.line,
|
|
58
|
+
columnNumber: msg.column,
|
|
59
|
+
};
|
|
60
|
+
this.messages.push(message);
|
|
61
|
+
if (this.messages.length > this.MAX_MESSAGES) {
|
|
62
|
+
this.messages = this.messages.slice(-Math.floor(this.MAX_MESSAGES / 2));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
if (options?.enableExceptions !== false) {
|
|
66
|
+
this.cdpSession.on('Runtime.exceptionThrown', (params) => {
|
|
67
|
+
const exception = params.exceptionDetails;
|
|
68
|
+
const stackTrace = exception.stackTrace?.callFrames?.map((frame) => ({
|
|
69
|
+
functionName: frame.functionName || '(anonymous)',
|
|
70
|
+
url: frame.url,
|
|
71
|
+
lineNumber: frame.lineNumber,
|
|
72
|
+
columnNumber: frame.columnNumber,
|
|
73
|
+
})) || [];
|
|
74
|
+
const exceptionInfo = {
|
|
75
|
+
text: exception.exception?.description || exception.text,
|
|
76
|
+
exceptionId: exception.exceptionId,
|
|
77
|
+
timestamp: Date.now(),
|
|
78
|
+
stackTrace,
|
|
79
|
+
url: exception.url,
|
|
80
|
+
lineNumber: exception.lineNumber,
|
|
81
|
+
columnNumber: exception.columnNumber,
|
|
82
|
+
scriptId: exception.scriptId,
|
|
83
|
+
};
|
|
84
|
+
this.exceptions.push(exceptionInfo);
|
|
85
|
+
if (this.exceptions.length > this.MAX_EXCEPTIONS) {
|
|
86
|
+
this.exceptions = this.exceptions.slice(-Math.floor(this.MAX_EXCEPTIONS / 2));
|
|
87
|
+
}
|
|
88
|
+
logger.error(`Exception thrown: ${exceptionInfo.text}`, {
|
|
89
|
+
url: exceptionInfo.url,
|
|
90
|
+
line: exceptionInfo.lineNumber,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (options?.enableNetwork) {
|
|
95
|
+
await this.enableNetworkMonitoring();
|
|
96
|
+
}
|
|
97
|
+
logger.info('ConsoleMonitor enabled', {
|
|
98
|
+
network: options?.enableNetwork || false,
|
|
99
|
+
exceptions: options?.enableExceptions !== false,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async disable() {
|
|
103
|
+
if (this.cdpSession) {
|
|
104
|
+
if (this.networkEnabled) {
|
|
105
|
+
if (this.networkListeners.requestWillBeSent) {
|
|
106
|
+
this.cdpSession.off('Network.requestWillBeSent', this.networkListeners.requestWillBeSent);
|
|
107
|
+
}
|
|
108
|
+
if (this.networkListeners.responseReceived) {
|
|
109
|
+
this.cdpSession.off('Network.responseReceived', this.networkListeners.responseReceived);
|
|
110
|
+
}
|
|
111
|
+
if (this.networkListeners.loadingFinished) {
|
|
112
|
+
this.cdpSession.off('Network.loadingFinished', this.networkListeners.loadingFinished);
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
await this.cdpSession.send('Network.disable');
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
logger.warn('Failed to disable Network domain:', error);
|
|
119
|
+
}
|
|
120
|
+
this.networkListeners = {};
|
|
121
|
+
this.networkEnabled = false;
|
|
122
|
+
logger.info('Network monitoring disabled');
|
|
123
|
+
}
|
|
124
|
+
await this.cdpSession.send('Console.disable');
|
|
125
|
+
await this.cdpSession.send('Runtime.disable');
|
|
126
|
+
await this.cdpSession.detach();
|
|
127
|
+
this.cdpSession = null;
|
|
128
|
+
logger.info('ConsoleMonitor disabled');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
getLogs(filter) {
|
|
132
|
+
let logs = this.messages;
|
|
133
|
+
if (filter?.type) {
|
|
134
|
+
logs = logs.filter(msg => msg.type === filter.type);
|
|
135
|
+
}
|
|
136
|
+
if (filter?.since !== undefined) {
|
|
137
|
+
logs = logs.filter(msg => msg.timestamp >= filter.since);
|
|
138
|
+
}
|
|
139
|
+
if (filter?.limit) {
|
|
140
|
+
logs = logs.slice(-filter.limit);
|
|
141
|
+
}
|
|
142
|
+
logger.info(`getLogs: ${logs.length} messages`);
|
|
143
|
+
return logs;
|
|
144
|
+
}
|
|
145
|
+
async execute(expression) {
|
|
146
|
+
if (!this.cdpSession) {
|
|
147
|
+
await this.enable();
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
const result = await this.cdpSession.send('Runtime.evaluate', {
|
|
151
|
+
expression,
|
|
152
|
+
returnByValue: true,
|
|
153
|
+
});
|
|
154
|
+
if (result.exceptionDetails) {
|
|
155
|
+
logger.error('Console execute error:', result.exceptionDetails);
|
|
156
|
+
throw new Error(result.exceptionDetails.text);
|
|
157
|
+
}
|
|
158
|
+
logger.info(`Console executed: ${expression.substring(0, 50)}...`);
|
|
159
|
+
return result.result.value;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
logger.error('Console execute failed:', error);
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
clearLogs() {
|
|
167
|
+
this.messages = [];
|
|
168
|
+
logger.info('Console logs cleared');
|
|
169
|
+
}
|
|
170
|
+
getStats() {
|
|
171
|
+
const byType = {};
|
|
172
|
+
for (const msg of this.messages) {
|
|
173
|
+
byType[msg.type] = (byType[msg.type] || 0) + 1;
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
totalMessages: this.messages.length,
|
|
177
|
+
byType,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async close() {
|
|
181
|
+
await this.disable();
|
|
182
|
+
}
|
|
183
|
+
async enableNetworkMonitoring() {
|
|
184
|
+
if (!this.cdpSession) {
|
|
185
|
+
throw new Error('CDP session not initialized');
|
|
186
|
+
}
|
|
187
|
+
if (this.networkEnabled) {
|
|
188
|
+
logger.warn('Network monitoring already enabled');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
await this.cdpSession.send('Network.enable', {
|
|
193
|
+
maxTotalBufferSize: 10000000,
|
|
194
|
+
maxResourceBufferSize: 5000000,
|
|
195
|
+
maxPostDataSize: 65536,
|
|
196
|
+
});
|
|
197
|
+
logger.info('Network domain enabled');
|
|
198
|
+
this.networkListeners.requestWillBeSent = (params) => {
|
|
199
|
+
const request = {
|
|
200
|
+
requestId: params.requestId,
|
|
201
|
+
url: params.request.url,
|
|
202
|
+
method: params.request.method,
|
|
203
|
+
headers: params.request.headers,
|
|
204
|
+
postData: params.request.postData,
|
|
205
|
+
timestamp: params.timestamp,
|
|
206
|
+
type: params.type,
|
|
207
|
+
initiator: params.initiator,
|
|
208
|
+
};
|
|
209
|
+
this.requests.set(params.requestId, request);
|
|
210
|
+
if (this.requests.size > this.MAX_NETWORK_RECORDS) {
|
|
211
|
+
const firstKey = this.requests.keys().next().value;
|
|
212
|
+
if (firstKey) {
|
|
213
|
+
this.requests.delete(firstKey);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
logger.debug(`Network request captured: ${params.request.method} ${params.request.url}`);
|
|
217
|
+
};
|
|
218
|
+
this.networkListeners.responseReceived = (params) => {
|
|
219
|
+
const response = {
|
|
220
|
+
requestId: params.requestId,
|
|
221
|
+
url: params.response.url,
|
|
222
|
+
status: params.response.status,
|
|
223
|
+
statusText: params.response.statusText,
|
|
224
|
+
headers: params.response.headers,
|
|
225
|
+
mimeType: params.response.mimeType,
|
|
226
|
+
timestamp: params.timestamp,
|
|
227
|
+
fromCache: params.response.fromDiskCache || params.response.fromServiceWorker,
|
|
228
|
+
timing: params.response.timing,
|
|
229
|
+
};
|
|
230
|
+
this.responses.set(params.requestId, response);
|
|
231
|
+
if (this.responses.size > this.MAX_NETWORK_RECORDS) {
|
|
232
|
+
const firstKey = this.responses.keys().next().value;
|
|
233
|
+
if (firstKey) {
|
|
234
|
+
this.responses.delete(firstKey);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
logger.debug(`Network response captured: ${params.response.status} ${params.response.url}`);
|
|
238
|
+
};
|
|
239
|
+
this.networkListeners.loadingFinished = (params) => {
|
|
240
|
+
logger.debug(`Network loading finished: ${params.requestId}`);
|
|
241
|
+
};
|
|
242
|
+
this.cdpSession.on('Network.requestWillBeSent', this.networkListeners.requestWillBeSent);
|
|
243
|
+
this.cdpSession.on('Network.responseReceived', this.networkListeners.responseReceived);
|
|
244
|
+
this.cdpSession.on('Network.loadingFinished', this.networkListeners.loadingFinished);
|
|
245
|
+
this.networkEnabled = true;
|
|
246
|
+
logger.info('✅ Network monitoring enabled successfully', {
|
|
247
|
+
requestListeners: !!this.networkListeners.requestWillBeSent,
|
|
248
|
+
responseListeners: !!this.networkListeners.responseReceived,
|
|
249
|
+
loadingListeners: !!this.networkListeners.loadingFinished,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
logger.error('❌ Failed to enable network monitoring:', error);
|
|
254
|
+
this.networkEnabled = false;
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
isNetworkEnabled() {
|
|
259
|
+
return this.networkEnabled;
|
|
260
|
+
}
|
|
261
|
+
getNetworkStatus() {
|
|
262
|
+
return {
|
|
263
|
+
enabled: this.networkEnabled,
|
|
264
|
+
requestCount: this.requests.size,
|
|
265
|
+
responseCount: this.responses.size,
|
|
266
|
+
listenerCount: Object.keys(this.networkListeners).filter(key => this.networkListeners[key] !== undefined).length,
|
|
267
|
+
cdpSessionActive: this.cdpSession !== null,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
getNetworkRequests(filter) {
|
|
271
|
+
let requests = Array.from(this.requests.values());
|
|
272
|
+
if (filter?.url) {
|
|
273
|
+
requests = requests.filter(req => req.url.includes(filter.url));
|
|
274
|
+
}
|
|
275
|
+
if (filter?.method) {
|
|
276
|
+
requests = requests.filter(req => req.method === filter.method);
|
|
277
|
+
}
|
|
278
|
+
if (filter?.limit) {
|
|
279
|
+
requests = requests.slice(-filter.limit);
|
|
280
|
+
}
|
|
281
|
+
return requests;
|
|
282
|
+
}
|
|
283
|
+
getNetworkResponses(filter) {
|
|
284
|
+
let responses = Array.from(this.responses.values());
|
|
285
|
+
if (filter?.url) {
|
|
286
|
+
responses = responses.filter(res => res.url.includes(filter.url));
|
|
287
|
+
}
|
|
288
|
+
if (filter?.status) {
|
|
289
|
+
responses = responses.filter(res => res.status === filter.status);
|
|
290
|
+
}
|
|
291
|
+
if (filter?.limit) {
|
|
292
|
+
responses = responses.slice(-filter.limit);
|
|
293
|
+
}
|
|
294
|
+
return responses;
|
|
295
|
+
}
|
|
296
|
+
getNetworkActivity(requestId) {
|
|
297
|
+
return {
|
|
298
|
+
request: this.requests.get(requestId),
|
|
299
|
+
response: this.responses.get(requestId),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
async getResponseBody(requestId) {
|
|
303
|
+
if (!this.cdpSession) {
|
|
304
|
+
throw new Error('CDP session not initialized');
|
|
305
|
+
}
|
|
306
|
+
if (!this.networkEnabled) {
|
|
307
|
+
logger.error('Network monitoring is not enabled. Call enable() with enableNetwork: true first.');
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const request = this.requests.get(requestId);
|
|
311
|
+
const response = this.responses.get(requestId);
|
|
312
|
+
if (!request) {
|
|
313
|
+
logger.error(`Request not found: ${requestId}. Make sure network monitoring was enabled before the request.`);
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
if (!response) {
|
|
317
|
+
logger.warn(`Response not yet received for request: ${requestId}. The request may still be pending.`);
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
const result = await this.cdpSession.send('Network.getResponseBody', {
|
|
322
|
+
requestId,
|
|
323
|
+
});
|
|
324
|
+
logger.info(`Response body retrieved for request: ${requestId}`, {
|
|
325
|
+
url: response.url,
|
|
326
|
+
status: response.status,
|
|
327
|
+
size: result.body.length,
|
|
328
|
+
base64: result.base64Encoded,
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
body: result.body,
|
|
332
|
+
base64Encoded: result.base64Encoded,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
logger.error(`Failed to get response body for ${requestId}:`, {
|
|
337
|
+
url: response.url,
|
|
338
|
+
status: response.status,
|
|
339
|
+
error: error.message,
|
|
340
|
+
hint: 'The response body may not be available for this request type (e.g., cached, redirected, or failed requests)',
|
|
341
|
+
});
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async getAllJavaScriptResponses() {
|
|
346
|
+
const jsResponses = [];
|
|
347
|
+
for (const [requestId, response] of this.responses.entries()) {
|
|
348
|
+
if (response.mimeType.includes('javascript') ||
|
|
349
|
+
response.url.endsWith('.js') ||
|
|
350
|
+
response.url.includes('.js?')) {
|
|
351
|
+
const bodyResult = await this.getResponseBody(requestId);
|
|
352
|
+
if (bodyResult) {
|
|
353
|
+
const content = bodyResult.base64Encoded
|
|
354
|
+
? Buffer.from(bodyResult.body, 'base64').toString('utf-8')
|
|
355
|
+
: bodyResult.body;
|
|
356
|
+
jsResponses.push({
|
|
357
|
+
url: response.url,
|
|
358
|
+
content,
|
|
359
|
+
size: content.length,
|
|
360
|
+
requestId,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
logger.info(`Collected ${jsResponses.length} JavaScript responses`);
|
|
366
|
+
return jsResponses;
|
|
367
|
+
}
|
|
368
|
+
clearNetworkRecords() {
|
|
369
|
+
this.requests.clear();
|
|
370
|
+
this.responses.clear();
|
|
371
|
+
logger.info('Network records cleared');
|
|
372
|
+
}
|
|
373
|
+
getNetworkStats() {
|
|
374
|
+
const byMethod = {};
|
|
375
|
+
const byStatus = {};
|
|
376
|
+
const byType = {};
|
|
377
|
+
for (const request of this.requests.values()) {
|
|
378
|
+
byMethod[request.method] = (byMethod[request.method] || 0) + 1;
|
|
379
|
+
if (request.type) {
|
|
380
|
+
byType[request.type] = (byType[request.type] || 0) + 1;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
for (const response of this.responses.values()) {
|
|
384
|
+
byStatus[response.status] = (byStatus[response.status] || 0) + 1;
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
totalRequests: this.requests.size,
|
|
388
|
+
totalResponses: this.responses.size,
|
|
389
|
+
byMethod,
|
|
390
|
+
byStatus,
|
|
391
|
+
byType,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
getExceptions(filter) {
|
|
395
|
+
let exceptions = this.exceptions;
|
|
396
|
+
if (filter?.url) {
|
|
397
|
+
exceptions = exceptions.filter(ex => ex.url?.includes(filter.url));
|
|
398
|
+
}
|
|
399
|
+
if (filter?.since !== undefined) {
|
|
400
|
+
exceptions = exceptions.filter(ex => ex.timestamp >= filter.since);
|
|
401
|
+
}
|
|
402
|
+
if (filter?.limit) {
|
|
403
|
+
exceptions = exceptions.slice(-filter.limit);
|
|
404
|
+
}
|
|
405
|
+
return exceptions;
|
|
406
|
+
}
|
|
407
|
+
clearExceptions() {
|
|
408
|
+
this.exceptions = [];
|
|
409
|
+
logger.info('Exceptions cleared');
|
|
410
|
+
}
|
|
411
|
+
async inspectObject(objectId) {
|
|
412
|
+
if (!this.cdpSession) {
|
|
413
|
+
throw new Error('CDP session not initialized');
|
|
414
|
+
}
|
|
415
|
+
if (this.objectCache.has(objectId)) {
|
|
416
|
+
return this.objectCache.get(objectId);
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
const result = await this.cdpSession.send('Runtime.getProperties', {
|
|
420
|
+
objectId,
|
|
421
|
+
ownProperties: true,
|
|
422
|
+
accessorPropertiesOnly: false,
|
|
423
|
+
generatePreview: true,
|
|
424
|
+
});
|
|
425
|
+
const properties = {};
|
|
426
|
+
for (const prop of result.result) {
|
|
427
|
+
if (!prop.value)
|
|
428
|
+
continue;
|
|
429
|
+
properties[prop.name] = {
|
|
430
|
+
value: this.extractValue(prop.value),
|
|
431
|
+
type: prop.value.type,
|
|
432
|
+
objectId: prop.value.objectId,
|
|
433
|
+
description: prop.value.description,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
this.objectCache.set(objectId, properties);
|
|
437
|
+
logger.info(`Object inspected: ${objectId}`, {
|
|
438
|
+
propertyCount: Object.keys(properties).length,
|
|
439
|
+
});
|
|
440
|
+
return properties;
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
logger.error('Failed to inspect object:', error);
|
|
444
|
+
throw error;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
clearObjectCache() {
|
|
448
|
+
this.objectCache.clear();
|
|
449
|
+
logger.info('Object cache cleared');
|
|
450
|
+
}
|
|
451
|
+
async enableDynamicScriptMonitoring() {
|
|
452
|
+
if (!this.cdpSession) {
|
|
453
|
+
throw new Error('CDP session not initialized');
|
|
454
|
+
}
|
|
455
|
+
const monitorCode = `
|
|
456
|
+
(function() {
|
|
457
|
+
// 防止重复注入
|
|
458
|
+
if (window.__dynamicScriptMonitorInstalled) {
|
|
459
|
+
console.log('[ScriptMonitor] Already installed');
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
window.__dynamicScriptMonitorInstalled = true;
|
|
463
|
+
|
|
464
|
+
// 记录所有动态添加的脚本
|
|
465
|
+
const dynamicScripts = [];
|
|
466
|
+
|
|
467
|
+
// 1. 监听DOM变化(MutationObserver)
|
|
468
|
+
const observer = new MutationObserver((mutations) => {
|
|
469
|
+
mutations.forEach((mutation) => {
|
|
470
|
+
mutation.addedNodes.forEach((node) => {
|
|
471
|
+
if (node.nodeName === 'SCRIPT') {
|
|
472
|
+
const script = node;
|
|
473
|
+
const info = {
|
|
474
|
+
type: 'dynamic',
|
|
475
|
+
src: script.src || '(inline)',
|
|
476
|
+
content: script.src ? null : script.textContent,
|
|
477
|
+
timestamp: Date.now(),
|
|
478
|
+
async: script.async,
|
|
479
|
+
defer: script.defer,
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
dynamicScripts.push(info);
|
|
483
|
+
console.log('[ScriptMonitor] Dynamic script added:', info);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
observer.observe(document.documentElement, {
|
|
490
|
+
childList: true,
|
|
491
|
+
subtree: true,
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// 2. Hook document.createElement('script')
|
|
495
|
+
const originalCreateElement = document.createElement;
|
|
496
|
+
document.createElement = function(tagName) {
|
|
497
|
+
const element = originalCreateElement.call(document, tagName);
|
|
498
|
+
|
|
499
|
+
if (tagName.toLowerCase() === 'script') {
|
|
500
|
+
console.log('[ScriptMonitor] Script element created via createElement');
|
|
501
|
+
|
|
502
|
+
// 监听src属性变化
|
|
503
|
+
const originalSetAttribute = element.setAttribute;
|
|
504
|
+
element.setAttribute = function(name, value) {
|
|
505
|
+
if (name === 'src') {
|
|
506
|
+
console.log('[ScriptMonitor] Script src set to:', value);
|
|
507
|
+
}
|
|
508
|
+
return originalSetAttribute.call(element, name, value);
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
return element;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
// 3. Hook eval (危险但有用)
|
|
516
|
+
const originalEval = window.eval;
|
|
517
|
+
window.eval = function(code) {
|
|
518
|
+
console.log('[ScriptMonitor] eval() called with code:',
|
|
519
|
+
typeof code === 'string' ? code.substring(0, 100) + '...' : code);
|
|
520
|
+
return originalEval.call(window, code);
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// 4. Hook Function constructor
|
|
524
|
+
const originalFunction = window.Function;
|
|
525
|
+
window.Function = function(...args) {
|
|
526
|
+
console.log('[ScriptMonitor] Function() constructor called with args:', args);
|
|
527
|
+
return originalFunction.apply(this, args);
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// 5. 暴露API供外部查询
|
|
531
|
+
window.__getDynamicScripts = function() {
|
|
532
|
+
return dynamicScripts;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
console.log('[ScriptMonitor] Dynamic script monitoring enabled');
|
|
536
|
+
})();
|
|
537
|
+
`;
|
|
538
|
+
await this.cdpSession.send('Runtime.evaluate', {
|
|
539
|
+
expression: monitorCode,
|
|
540
|
+
});
|
|
541
|
+
logger.info('Dynamic script monitoring enabled');
|
|
542
|
+
}
|
|
543
|
+
async getDynamicScripts() {
|
|
544
|
+
if (!this.cdpSession) {
|
|
545
|
+
throw new Error('CDP session not initialized');
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
const result = await this.cdpSession.send('Runtime.evaluate', {
|
|
549
|
+
expression: 'window.__getDynamicScripts ? window.__getDynamicScripts() : []',
|
|
550
|
+
returnByValue: true,
|
|
551
|
+
});
|
|
552
|
+
return result.result.value || [];
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
logger.error('Failed to get dynamic scripts:', error);
|
|
556
|
+
return [];
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async injectFunctionTracer(functionName) {
|
|
560
|
+
if (!this.cdpSession) {
|
|
561
|
+
throw new Error('CDP session not initialized');
|
|
562
|
+
}
|
|
563
|
+
const tracerCode = `
|
|
564
|
+
(function() {
|
|
565
|
+
const originalFunc = window.${functionName};
|
|
566
|
+
if (typeof originalFunc !== 'function') {
|
|
567
|
+
console.error('[Tracer] ${functionName} is not a function');
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
window.${functionName} = new Proxy(originalFunc, {
|
|
572
|
+
apply: function(target, thisArg, args) {
|
|
573
|
+
console.log('[Tracer] ${functionName} called with args:', args);
|
|
574
|
+
const startTime = performance.now();
|
|
575
|
+
|
|
576
|
+
try {
|
|
577
|
+
const result = target.apply(thisArg, args);
|
|
578
|
+
const endTime = performance.now();
|
|
579
|
+
console.log('[Tracer] ${functionName} returned:', result, 'Time:', (endTime - startTime).toFixed(2), 'ms');
|
|
580
|
+
return result;
|
|
581
|
+
} catch (error) {
|
|
582
|
+
console.error('[Tracer] ${functionName} threw error:', error);
|
|
583
|
+
throw error;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
console.log('[Tracer] ${functionName} is now being traced');
|
|
589
|
+
})();
|
|
590
|
+
`;
|
|
591
|
+
await this.cdpSession.send('Runtime.evaluate', {
|
|
592
|
+
expression: tracerCode,
|
|
593
|
+
});
|
|
594
|
+
logger.info(`Function tracer injected for: ${functionName}`);
|
|
595
|
+
}
|
|
596
|
+
async injectXHRInterceptor() {
|
|
597
|
+
if (!this.cdpSession) {
|
|
598
|
+
throw new Error('CDP session not initialized');
|
|
599
|
+
}
|
|
600
|
+
const interceptorCode = `
|
|
601
|
+
(function() {
|
|
602
|
+
if (window.__xhrInterceptorInstalled) {
|
|
603
|
+
console.log('[XHRInterceptor] Already installed');
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
window.__xhrInterceptorInstalled = true;
|
|
607
|
+
|
|
608
|
+
const xhrRequests = [];
|
|
609
|
+
const originalXHR = window.XMLHttpRequest;
|
|
610
|
+
|
|
611
|
+
window.XMLHttpRequest = function() {
|
|
612
|
+
const xhr = new originalXHR();
|
|
613
|
+
const requestInfo = {
|
|
614
|
+
method: '',
|
|
615
|
+
url: '',
|
|
616
|
+
requestHeaders: {},
|
|
617
|
+
responseHeaders: {},
|
|
618
|
+
status: 0,
|
|
619
|
+
response: null,
|
|
620
|
+
timestamp: Date.now(),
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
// Hook open
|
|
624
|
+
const originalOpen = xhr.open;
|
|
625
|
+
xhr.open = function(method, url, ...args) {
|
|
626
|
+
requestInfo.method = method;
|
|
627
|
+
requestInfo.url = url;
|
|
628
|
+
console.log('[XHRInterceptor] XHR opened:', method, url);
|
|
629
|
+
return originalOpen.call(xhr, method, url, ...args);
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// Hook setRequestHeader
|
|
633
|
+
const originalSetRequestHeader = xhr.setRequestHeader;
|
|
634
|
+
xhr.setRequestHeader = function(header, value) {
|
|
635
|
+
requestInfo.requestHeaders[header] = value;
|
|
636
|
+
return originalSetRequestHeader.call(xhr, header, value);
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// Hook send
|
|
640
|
+
const originalSend = xhr.send;
|
|
641
|
+
xhr.send = function(body) {
|
|
642
|
+
console.log('[XHRInterceptor] XHR sent:', requestInfo.url, 'Body:', body);
|
|
643
|
+
|
|
644
|
+
xhr.addEventListener('load', function() {
|
|
645
|
+
requestInfo.status = xhr.status;
|
|
646
|
+
requestInfo.response = xhr.response;
|
|
647
|
+
requestInfo.responseHeaders = xhr.getAllResponseHeaders();
|
|
648
|
+
|
|
649
|
+
xhrRequests.push(requestInfo);
|
|
650
|
+
console.log('[XHRInterceptor] XHR completed:', requestInfo.url, 'Status:', xhr.status);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
return originalSend.call(xhr, body);
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
return xhr;
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
window.__getXHRRequests = function() {
|
|
660
|
+
return xhrRequests;
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
console.log('[XHRInterceptor] XHR interceptor installed');
|
|
664
|
+
})();
|
|
665
|
+
`;
|
|
666
|
+
await this.cdpSession.send('Runtime.evaluate', {
|
|
667
|
+
expression: interceptorCode,
|
|
668
|
+
});
|
|
669
|
+
logger.info('XHR interceptor injected');
|
|
670
|
+
}
|
|
671
|
+
async injectFetchInterceptor() {
|
|
672
|
+
if (!this.cdpSession) {
|
|
673
|
+
throw new Error('CDP session not initialized');
|
|
674
|
+
}
|
|
675
|
+
const interceptorCode = `
|
|
676
|
+
(function() {
|
|
677
|
+
if (window.__fetchInterceptorInstalled) {
|
|
678
|
+
console.log('[FetchInterceptor] Already installed');
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
window.__fetchInterceptorInstalled = true;
|
|
682
|
+
|
|
683
|
+
const fetchRequests = [];
|
|
684
|
+
const originalFetch = window.fetch;
|
|
685
|
+
|
|
686
|
+
window.fetch = function(url, options = {}) {
|
|
687
|
+
const requestInfo = {
|
|
688
|
+
url: typeof url === 'string' ? url : url.url,
|
|
689
|
+
method: options.method || 'GET',
|
|
690
|
+
headers: options.headers || {},
|
|
691
|
+
body: options.body,
|
|
692
|
+
timestamp: Date.now(),
|
|
693
|
+
response: null,
|
|
694
|
+
status: 0,
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
console.log('[FetchInterceptor] Fetch called:', requestInfo.method, requestInfo.url);
|
|
698
|
+
|
|
699
|
+
return originalFetch.call(window, url, options).then(async (response) => {
|
|
700
|
+
requestInfo.status = response.status;
|
|
701
|
+
|
|
702
|
+
// Clone response to read body
|
|
703
|
+
const clonedResponse = response.clone();
|
|
704
|
+
try {
|
|
705
|
+
requestInfo.response = await clonedResponse.text();
|
|
706
|
+
} catch (e) {
|
|
707
|
+
requestInfo.response = '[Unable to read response]';
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
fetchRequests.push(requestInfo);
|
|
711
|
+
console.log('[FetchInterceptor] Fetch completed:', requestInfo.url, 'Status:', response.status);
|
|
712
|
+
|
|
713
|
+
return response;
|
|
714
|
+
}).catch((error) => {
|
|
715
|
+
console.error('[FetchInterceptor] Fetch failed:', requestInfo.url, error);
|
|
716
|
+
throw error;
|
|
717
|
+
});
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
window.__getFetchRequests = function() {
|
|
721
|
+
return fetchRequests;
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
console.log('[FetchInterceptor] Fetch interceptor installed');
|
|
725
|
+
})();
|
|
726
|
+
`;
|
|
727
|
+
await this.cdpSession.send('Runtime.evaluate', {
|
|
728
|
+
expression: interceptorCode,
|
|
729
|
+
});
|
|
730
|
+
logger.info('Fetch interceptor injected');
|
|
731
|
+
}
|
|
732
|
+
async getXHRRequests() {
|
|
733
|
+
if (!this.cdpSession) {
|
|
734
|
+
throw new Error('CDP session not initialized');
|
|
735
|
+
}
|
|
736
|
+
try {
|
|
737
|
+
const result = await this.cdpSession.send('Runtime.evaluate', {
|
|
738
|
+
expression: 'window.__getXHRRequests ? window.__getXHRRequests() : []',
|
|
739
|
+
returnByValue: true,
|
|
740
|
+
});
|
|
741
|
+
return result.result.value || [];
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
logger.error('Failed to get XHR requests:', error);
|
|
745
|
+
return [];
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
async getFetchRequests() {
|
|
749
|
+
if (!this.cdpSession) {
|
|
750
|
+
throw new Error('CDP session not initialized');
|
|
751
|
+
}
|
|
752
|
+
try {
|
|
753
|
+
const result = await this.cdpSession.send('Runtime.evaluate', {
|
|
754
|
+
expression: 'window.__getFetchRequests ? window.__getFetchRequests() : []',
|
|
755
|
+
returnByValue: true,
|
|
756
|
+
});
|
|
757
|
+
return result.result.value || [];
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
logger.error('Failed to get Fetch requests:', error);
|
|
761
|
+
return [];
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
async injectPropertyWatcher(objectPath, propertyName) {
|
|
765
|
+
if (!this.cdpSession) {
|
|
766
|
+
throw new Error('CDP session not initialized');
|
|
767
|
+
}
|
|
768
|
+
const watcherCode = `
|
|
769
|
+
(function() {
|
|
770
|
+
const obj = ${objectPath};
|
|
771
|
+
if (!obj) {
|
|
772
|
+
console.error('[Watcher] Object not found: ${objectPath}');
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
let value = obj.${propertyName};
|
|
777
|
+
|
|
778
|
+
Object.defineProperty(obj, '${propertyName}', {
|
|
779
|
+
get: function() {
|
|
780
|
+
console.log('[Watcher] ${objectPath}.${propertyName} accessed, value:', value);
|
|
781
|
+
return value;
|
|
782
|
+
},
|
|
783
|
+
set: function(newValue) {
|
|
784
|
+
console.log('[Watcher] ${objectPath}.${propertyName} changed from', value, 'to', newValue);
|
|
785
|
+
value = newValue;
|
|
786
|
+
},
|
|
787
|
+
enumerable: true,
|
|
788
|
+
configurable: true
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
console.log('[Watcher] Property watcher installed for ${objectPath}.${propertyName}');
|
|
792
|
+
})();
|
|
793
|
+
`;
|
|
794
|
+
await this.cdpSession.send('Runtime.evaluate', {
|
|
795
|
+
expression: watcherCode,
|
|
796
|
+
});
|
|
797
|
+
logger.info(`Property watcher injected for: ${objectPath}.${propertyName}`);
|
|
798
|
+
}
|
|
799
|
+
formatRemoteObject(obj) {
|
|
800
|
+
if (obj.value !== undefined) {
|
|
801
|
+
return String(obj.value);
|
|
802
|
+
}
|
|
803
|
+
if (obj.description) {
|
|
804
|
+
return obj.description;
|
|
805
|
+
}
|
|
806
|
+
if (obj.type === 'undefined') {
|
|
807
|
+
return 'undefined';
|
|
808
|
+
}
|
|
809
|
+
if (obj.type === 'object' && obj.subtype === 'null') {
|
|
810
|
+
return 'null';
|
|
811
|
+
}
|
|
812
|
+
return `[${obj.type}]`;
|
|
813
|
+
}
|
|
814
|
+
extractValue(obj) {
|
|
815
|
+
if (obj.value !== undefined) {
|
|
816
|
+
return obj.value;
|
|
817
|
+
}
|
|
818
|
+
if (obj.type === 'undefined') {
|
|
819
|
+
return undefined;
|
|
820
|
+
}
|
|
821
|
+
if (obj.type === 'object' && obj.subtype === 'null') {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
if (obj.objectId) {
|
|
825
|
+
return {
|
|
826
|
+
__objectId: obj.objectId,
|
|
827
|
+
__type: obj.type,
|
|
828
|
+
__description: obj.description,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
return obj.description || `[${obj.type}]`;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
//# sourceMappingURL=ConsoleMonitor.js.map
|