@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,548 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
export class AIEnvironmentAnalyzer {
|
|
3
|
+
llm;
|
|
4
|
+
constructor(llm) {
|
|
5
|
+
this.llm = llm;
|
|
6
|
+
}
|
|
7
|
+
async analyze(code, detected, missing, browserType = 'chrome') {
|
|
8
|
+
if (!this.llm) {
|
|
9
|
+
logger.warn('LLM服务未配置,跳过AI分析');
|
|
10
|
+
return this.getEmptyResult();
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
logger.info('🤖 开始AI环境分析...');
|
|
14
|
+
const prompt = this.buildAnalysisPrompt(code, detected, missing, browserType);
|
|
15
|
+
const response = await this.llm.chat([{ role: 'user', content: prompt }]);
|
|
16
|
+
const result = this.parseAIResponse(response.content);
|
|
17
|
+
logger.info(`✅ AI分析完成,置信度: ${(result.confidence * 100).toFixed(1)}%`);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
logger.error('AI分析失败', error);
|
|
22
|
+
return this.getEmptyResult();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
buildAnalysisPrompt(code, detected, missing, browserType) {
|
|
26
|
+
const codeSnippet = code.length > 5000 ? code.substring(0, 5000) + '\n\n// ... (code truncated for analysis)' : code;
|
|
27
|
+
const systemPrompt = `# Role
|
|
28
|
+
You are an expert JavaScript reverse engineer and anti-detection specialist with 10+ years of experience in:
|
|
29
|
+
- Browser environment emulation and fingerprinting
|
|
30
|
+
- Anti-bot and anti-scraping technique analysis
|
|
31
|
+
- JavaScript obfuscation and deobfuscation
|
|
32
|
+
- Browser API implementation and polyfills
|
|
33
|
+
- Web security and privacy technologies
|
|
34
|
+
|
|
35
|
+
# Expertise Areas
|
|
36
|
+
- **Browser Fingerprinting**: Canvas, WebGL, Audio, Font, CSS fingerprinting
|
|
37
|
+
- **Environment Detection**: WebDriver, Headless Chrome, Puppeteer detection
|
|
38
|
+
- **API Emulation**: DOM, BOM, Web APIs (Crypto, Storage, Performance, etc.)
|
|
39
|
+
- **Anti-Detection**: Stealth techniques, environment consistency checks
|
|
40
|
+
- **Browser Internals**: Chrome, Firefox, Safari implementation differences
|
|
41
|
+
|
|
42
|
+
# Task
|
|
43
|
+
Analyze the provided JavaScript code to:
|
|
44
|
+
1. Identify ALL browser environment variables and APIs being accessed
|
|
45
|
+
2. Detect anti-bot and fingerprinting techniques
|
|
46
|
+
3. Recommend realistic values for missing environment variables
|
|
47
|
+
4. Provide working JavaScript implementations for missing APIs
|
|
48
|
+
5. Assess detection risks and provide mitigation strategies
|
|
49
|
+
|
|
50
|
+
# Analysis Standards
|
|
51
|
+
- Follow W3C Web API specifications
|
|
52
|
+
- Use real browser behavior patterns (not placeholder values)
|
|
53
|
+
- Ensure environment consistency (e.g., userAgent matches platform)
|
|
54
|
+
- Detect common anti-bot libraries (Cloudflare, PerimeterX, DataDome, etc.)
|
|
55
|
+
- Identify fingerprinting scripts (FingerprintJS, CreepJS, etc.)`;
|
|
56
|
+
const userPrompt = `# Target Browser
|
|
57
|
+
${browserType.toUpperCase()} (Latest stable version, 2024-2025)
|
|
58
|
+
|
|
59
|
+
# Detected Environment Variable Access
|
|
60
|
+
\`\`\`json
|
|
61
|
+
${JSON.stringify(detected, null, 2)}
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
# Missing APIs (Need Implementation)
|
|
65
|
+
\`\`\`json
|
|
66
|
+
${JSON.stringify(missing.map(m => ({ path: m.path, type: m.type })), null, 2)}
|
|
67
|
+
\`\`\`
|
|
68
|
+
|
|
69
|
+
# Code to Analyze
|
|
70
|
+
\`\`\`javascript
|
|
71
|
+
${codeSnippet}
|
|
72
|
+
\`\`\`
|
|
73
|
+
|
|
74
|
+
# Required Output Schema
|
|
75
|
+
Return ONLY valid JSON with this EXACT structure (all fields required):
|
|
76
|
+
|
|
77
|
+
\`\`\`json
|
|
78
|
+
{
|
|
79
|
+
"recommendedVariables": {
|
|
80
|
+
"navigator.userAgent": "string - realistic UA matching target browser",
|
|
81
|
+
"navigator.platform": "string - must match UA (Win32, MacIntel, Linux x86_64)",
|
|
82
|
+
"navigator.vendor": "string - Google Inc. for Chrome, empty for Firefox",
|
|
83
|
+
"window.chrome": "object | undefined - Chrome-specific object",
|
|
84
|
+
"navigator.webdriver": "boolean - MUST be false or undefined for stealth",
|
|
85
|
+
"navigator.plugins": "PluginArray - realistic plugin list, not empty array",
|
|
86
|
+
"...": "other detected variables with realistic values"
|
|
87
|
+
},
|
|
88
|
+
"recommendedAPIs": [
|
|
89
|
+
{
|
|
90
|
+
"path": "string - full API path (e.g., 'window.requestAnimationFrame')",
|
|
91
|
+
"implementation": "string - complete working JavaScript code",
|
|
92
|
+
"reason": "string - why this API is needed and how it's used in the code",
|
|
93
|
+
"priority": "critical | high | medium | low",
|
|
94
|
+
"complexity": "simple | moderate | complex"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"antiCrawlFeatures": [
|
|
98
|
+
{
|
|
99
|
+
"feature": "string - specific technique name",
|
|
100
|
+
"type": "fingerprinting | detection | obfuscation | challenge",
|
|
101
|
+
"severity": "critical | high | medium | low",
|
|
102
|
+
"description": "string - detailed technical description",
|
|
103
|
+
"location": "string - line number or function name if identifiable",
|
|
104
|
+
"mitigation": "string - specific bypass technique with code example",
|
|
105
|
+
"confidence": 0.95
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"environmentConsistency": {
|
|
109
|
+
"issues": [
|
|
110
|
+
{
|
|
111
|
+
"variable1": "navigator.userAgent",
|
|
112
|
+
"variable2": "navigator.platform",
|
|
113
|
+
"issue": "UA indicates Windows but platform is MacIntel",
|
|
114
|
+
"fix": "Ensure platform matches UA OS"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"score": 85
|
|
118
|
+
},
|
|
119
|
+
"suggestions": [
|
|
120
|
+
"string - actionable recommendation 1",
|
|
121
|
+
"string - actionable recommendation 2",
|
|
122
|
+
"string - actionable recommendation 3"
|
|
123
|
+
],
|
|
124
|
+
"confidence": 0.85,
|
|
125
|
+
"summary": "2-3 sentence summary of findings and main risks"
|
|
126
|
+
}
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
# Example Output (for reference)
|
|
130
|
+
\`\`\`json
|
|
131
|
+
{
|
|
132
|
+
"recommendedVariables": {
|
|
133
|
+
"navigator.userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
134
|
+
"navigator.platform": "Win32",
|
|
135
|
+
"navigator.vendor": "Google Inc.",
|
|
136
|
+
"navigator.webdriver": false,
|
|
137
|
+
"navigator.plugins": "[{name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', length: 1}]",
|
|
138
|
+
"window.chrome": "{runtime: {}, loadTimes: function(){}, csi: function(){}}",
|
|
139
|
+
"navigator.hardwareConcurrency": 8,
|
|
140
|
+
"navigator.deviceMemory": 8
|
|
141
|
+
},
|
|
142
|
+
"recommendedAPIs": [
|
|
143
|
+
{
|
|
144
|
+
"path": "window.requestAnimationFrame",
|
|
145
|
+
"implementation": "window.requestAnimationFrame = function(callback) { return setTimeout(callback, 16); };",
|
|
146
|
+
"reason": "Code uses rAF for animation timing, detected at line 45",
|
|
147
|
+
"priority": "high",
|
|
148
|
+
"complexity": "simple"
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
"antiCrawlFeatures": [
|
|
152
|
+
{
|
|
153
|
+
"feature": "Canvas Fingerprinting",
|
|
154
|
+
"type": "fingerprinting",
|
|
155
|
+
"severity": "high",
|
|
156
|
+
"description": "Code draws text on canvas and extracts toDataURL() for fingerprinting",
|
|
157
|
+
"location": "line 123, function generateFingerprint()",
|
|
158
|
+
"mitigation": "Inject consistent canvas noise or override toDataURL() to return fixed hash",
|
|
159
|
+
"confidence": 0.98
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"feature": "WebDriver Detection",
|
|
163
|
+
"type": "detection",
|
|
164
|
+
"severity": "critical",
|
|
165
|
+
"description": "Checks navigator.webdriver property",
|
|
166
|
+
"location": "line 67",
|
|
167
|
+
"mitigation": "Object.defineProperty(navigator, 'webdriver', {get: () => false})",
|
|
168
|
+
"confidence": 1.0
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"environmentConsistency": {
|
|
172
|
+
"issues": [],
|
|
173
|
+
"score": 95
|
|
174
|
+
},
|
|
175
|
+
"suggestions": [
|
|
176
|
+
"Use Puppeteer Stealth plugin to automatically handle common detections",
|
|
177
|
+
"Implement consistent navigator.plugins array with at least 3 realistic plugins",
|
|
178
|
+
"Override canvas toDataURL() to return consistent fingerprint across sessions"
|
|
179
|
+
],
|
|
180
|
+
"confidence": 0.92,
|
|
181
|
+
"summary": "Code implements Canvas and WebDriver detection. High risk of bot detection. Requires comprehensive environment emulation with stealth techniques."
|
|
182
|
+
}
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
# Analysis Methodology
|
|
186
|
+
1. **First Pass**: Scan for known anti-bot library signatures (Cloudflare Turnstile, reCAPTCHA, etc.)
|
|
187
|
+
2. **Second Pass**: Identify fingerprinting techniques (Canvas, WebGL, Audio, Font)
|
|
188
|
+
3. **Third Pass**: Map all environment variable accesses and their usage context
|
|
189
|
+
4. **Fourth Pass**: Generate realistic values ensuring cross-variable consistency
|
|
190
|
+
5. **Fifth Pass**: Provide working API implementations based on W3C specs
|
|
191
|
+
6. **Final Pass**: Assess overall detection risk and prioritize mitigations
|
|
192
|
+
|
|
193
|
+
# Important Notes
|
|
194
|
+
- DO NOT use placeholder values like "example.com" or "test123"
|
|
195
|
+
- DO ensure navigator.userAgent matches navigator.platform and navigator.vendor
|
|
196
|
+
- DO provide complete, working JavaScript code for API implementations
|
|
197
|
+
- DO identify specific anti-bot products if detected (Cloudflare, PerimeterX, etc.)
|
|
198
|
+
- DO NOT hallucinate - only report features you actually detect in the code
|
|
199
|
+
|
|
200
|
+
Now analyze the code and return ONLY the JSON output (no markdown, no explanations).`;
|
|
201
|
+
return systemPrompt + '\n\n' + userPrompt;
|
|
202
|
+
}
|
|
203
|
+
parseAIResponse(response) {
|
|
204
|
+
try {
|
|
205
|
+
const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) ||
|
|
206
|
+
response.match(/\{[\s\S]*\}/);
|
|
207
|
+
if (!jsonMatch) {
|
|
208
|
+
logger.warn('AI响应中未找到JSON');
|
|
209
|
+
return this.getEmptyResult();
|
|
210
|
+
}
|
|
211
|
+
const jsonStr = jsonMatch[1] || jsonMatch[0];
|
|
212
|
+
const parsed = JSON.parse(jsonStr);
|
|
213
|
+
return {
|
|
214
|
+
recommendedVariables: parsed.recommendedVariables || {},
|
|
215
|
+
recommendedAPIs: parsed.recommendedAPIs || [],
|
|
216
|
+
antiCrawlFeatures: parsed.antiCrawlFeatures || [],
|
|
217
|
+
suggestions: parsed.suggestions || [],
|
|
218
|
+
confidence: parsed.confidence || 0.5,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
logger.error('解析AI响应失败', error);
|
|
223
|
+
return this.getEmptyResult();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
getEmptyResult() {
|
|
227
|
+
return {
|
|
228
|
+
recommendedVariables: {},
|
|
229
|
+
recommendedAPIs: [],
|
|
230
|
+
antiCrawlFeatures: [],
|
|
231
|
+
suggestions: [],
|
|
232
|
+
confidence: 0,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
async analyzeAntiCrawl(code) {
|
|
236
|
+
if (!this.llm) {
|
|
237
|
+
return [];
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const systemPrompt = `# Role
|
|
241
|
+
You are an expert in web anti-bot and anti-scraping technologies with deep knowledge of:
|
|
242
|
+
- Commercial anti-bot solutions (Cloudflare, PerimeterX, DataDome, Akamai, etc.)
|
|
243
|
+
- Browser fingerprinting techniques (Canvas, WebGL, Audio, Font, CSS, etc.)
|
|
244
|
+
- Bot detection methods (behavioral analysis, TLS fingerprinting, etc.)
|
|
245
|
+
- Stealth and evasion techniques
|
|
246
|
+
|
|
247
|
+
# Known Anti-Bot Techniques (2024-2025)
|
|
248
|
+
1. **Browser Fingerprinting**
|
|
249
|
+
- Canvas fingerprinting (toDataURL, getImageData)
|
|
250
|
+
- WebGL fingerprinting (renderer, vendor, extensions)
|
|
251
|
+
- Audio fingerprinting (AudioContext, OscillatorNode)
|
|
252
|
+
- Font fingerprinting (measureText, font enumeration)
|
|
253
|
+
- CSS fingerprinting (getComputedStyle)
|
|
254
|
+
|
|
255
|
+
2. **Environment Detection**
|
|
256
|
+
- WebDriver detection (navigator.webdriver)
|
|
257
|
+
- Headless detection (chrome.runtime, permissions)
|
|
258
|
+
- Automation tool detection (window.cdc_, $cdc_, __webdriver_)
|
|
259
|
+
- Plugin detection (navigator.plugins length check)
|
|
260
|
+
|
|
261
|
+
3. **Behavioral Analysis**
|
|
262
|
+
- Mouse movement patterns (entropy, velocity, acceleration)
|
|
263
|
+
- Keyboard timing analysis
|
|
264
|
+
- Scroll behavior patterns
|
|
265
|
+
- Touch event simulation detection
|
|
266
|
+
|
|
267
|
+
4. **Advanced Techniques**
|
|
268
|
+
- TLS/SSL fingerprinting (JA3, JA3S)
|
|
269
|
+
- HTTP/2 fingerprinting
|
|
270
|
+
- Timing attacks (performance.now() precision)
|
|
271
|
+
- Memory/CPU profiling
|
|
272
|
+
- Stack trace analysis
|
|
273
|
+
|
|
274
|
+
# Task
|
|
275
|
+
Analyze the code and identify ALL anti-bot and fingerprinting techniques with high precision.`;
|
|
276
|
+
const userPrompt = `# Code to Analyze
|
|
277
|
+
\`\`\`javascript
|
|
278
|
+
${code.substring(0, 3000)}${code.length > 3000 ? '\n\n// ... (truncated)' : ''}
|
|
279
|
+
\`\`\`
|
|
280
|
+
|
|
281
|
+
# Required Output Schema
|
|
282
|
+
Return ONLY valid JSON array with this structure:
|
|
283
|
+
|
|
284
|
+
\`\`\`json
|
|
285
|
+
[
|
|
286
|
+
{
|
|
287
|
+
"feature": "string - specific technique name (e.g., 'Canvas Fingerprinting via toDataURL')",
|
|
288
|
+
"type": "fingerprinting | detection | behavioral | challenge | obfuscation",
|
|
289
|
+
"severity": "critical | high | medium | low",
|
|
290
|
+
"description": "string - detailed technical description of what the code does",
|
|
291
|
+
"location": "string - line number, function name, or code pattern",
|
|
292
|
+
"mitigation": "string - specific bypass code or technique",
|
|
293
|
+
"confidence": 0.95,
|
|
294
|
+
"vendor": "string | null - if identifiable (Cloudflare, PerimeterX, etc.)"
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
# Example Output
|
|
300
|
+
\`\`\`json
|
|
301
|
+
[
|
|
302
|
+
{
|
|
303
|
+
"feature": "Canvas Fingerprinting",
|
|
304
|
+
"type": "fingerprinting",
|
|
305
|
+
"severity": "high",
|
|
306
|
+
"description": "Creates canvas element, draws text with specific font, extracts pixel data via toDataURL() and hashes it for unique browser identification",
|
|
307
|
+
"location": "function getCanvasFingerprint(), lines 45-67",
|
|
308
|
+
"mitigation": "Override HTMLCanvasElement.prototype.toDataURL to return consistent hash: const originalToDataURL = HTMLCanvasElement.prototype.toDataURL; HTMLCanvasElement.prototype.toDataURL = function() { return 'data:image/png;base64,iVBORw0KGgoAAAANS...' };",
|
|
309
|
+
"confidence": 0.98,
|
|
310
|
+
"vendor": null
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"feature": "WebDriver Detection",
|
|
314
|
+
"type": "detection",
|
|
315
|
+
"severity": "critical",
|
|
316
|
+
"description": "Checks navigator.webdriver property which is true in Selenium/Puppeteer",
|
|
317
|
+
"location": "if(navigator.webdriver) at line 23",
|
|
318
|
+
"mitigation": "Delete property before page load: Object.defineProperty(navigator, 'webdriver', {get: () => undefined});",
|
|
319
|
+
"confidence": 1.0,
|
|
320
|
+
"vendor": null
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"feature": "Cloudflare Turnstile Challenge",
|
|
324
|
+
"type": "challenge",
|
|
325
|
+
"severity": "critical",
|
|
326
|
+
"description": "Cloudflare's CAPTCHA alternative that validates browser environment",
|
|
327
|
+
"location": "cf-turnstile widget initialization",
|
|
328
|
+
"mitigation": "Requires solving Turnstile challenge via 2captcha or manual intervention",
|
|
329
|
+
"confidence": 0.92,
|
|
330
|
+
"vendor": "Cloudflare"
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
\`\`\`
|
|
334
|
+
|
|
335
|
+
# Analysis Guidelines
|
|
336
|
+
- Be specific: "Canvas toDataURL fingerprinting" not just "Canvas detection"
|
|
337
|
+
- Provide working mitigation code when possible
|
|
338
|
+
- Identify vendor if signature matches known products
|
|
339
|
+
- Only report techniques you actually see in the code
|
|
340
|
+
- Use confidence scores honestly (0.7-0.8 for uncertain, 0.9+ for definite)
|
|
341
|
+
|
|
342
|
+
Now analyze and return ONLY the JSON array.`;
|
|
343
|
+
const response = await this.llm.chat([
|
|
344
|
+
{ role: 'system', content: systemPrompt },
|
|
345
|
+
{ role: 'user', content: userPrompt }
|
|
346
|
+
]);
|
|
347
|
+
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)\s*```/) ||
|
|
348
|
+
response.content.match(/\[[\s\S]*\]/);
|
|
349
|
+
if (jsonMatch) {
|
|
350
|
+
const jsonStr = jsonMatch[1] || jsonMatch[0];
|
|
351
|
+
return JSON.parse(jsonStr);
|
|
352
|
+
}
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
logger.error('反爬虫特征分析失败', error);
|
|
357
|
+
return [];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async inferAPIImplementation(apiPath, context) {
|
|
361
|
+
if (!this.llm) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
const systemPrompt = `# Role
|
|
366
|
+
You are a browser API implementation expert with deep knowledge of:
|
|
367
|
+
- W3C Web API specifications
|
|
368
|
+
- Browser internals (V8, SpiderMonkey, JavaScriptCore)
|
|
369
|
+
- DOM, BOM, and Web APIs implementation details
|
|
370
|
+
- Cross-browser compatibility
|
|
371
|
+
- Anti-detection and stealth techniques
|
|
372
|
+
|
|
373
|
+
# Task
|
|
374
|
+
Provide a realistic, working JavaScript implementation for the requested browser API that:
|
|
375
|
+
1. Follows W3C specifications
|
|
376
|
+
2. Matches real browser behavior
|
|
377
|
+
3. Passes anti-detection checks
|
|
378
|
+
4. Is production-ready (handles edge cases)
|
|
379
|
+
5. Is concise but complete
|
|
380
|
+
|
|
381
|
+
# Implementation Standards
|
|
382
|
+
- Return realistic values (not null/undefined unless spec requires)
|
|
383
|
+
- Handle all parameter variations
|
|
384
|
+
- Include proper error handling
|
|
385
|
+
- Match browser-specific behavior when needed
|
|
386
|
+
- Consider performance implications`;
|
|
387
|
+
const userPrompt = `# API to Implement
|
|
388
|
+
\`${apiPath}\`
|
|
389
|
+
|
|
390
|
+
# Usage Context
|
|
391
|
+
\`\`\`javascript
|
|
392
|
+
${context.substring(0, 1000)}${context.length > 1000 ? '\n// ... (truncated)' : ''}
|
|
393
|
+
\`\`\`
|
|
394
|
+
|
|
395
|
+
# Requirements
|
|
396
|
+
1. Provide ONLY the JavaScript implementation code
|
|
397
|
+
2. Code must be production-ready and handle edge cases
|
|
398
|
+
3. Match real browser behavior (not a mock/stub)
|
|
399
|
+
4. Include JSDoc comment explaining the implementation
|
|
400
|
+
5. Consider anti-detection (e.g., function.toString() should look native)
|
|
401
|
+
|
|
402
|
+
# Output Format
|
|
403
|
+
Return ONLY JavaScript code in a code block, no explanations outside the code.
|
|
404
|
+
|
|
405
|
+
# Example Output
|
|
406
|
+
\`\`\`javascript
|
|
407
|
+
/**
|
|
408
|
+
* Implementation of window.requestAnimationFrame
|
|
409
|
+
* Polyfill that mimics browser behavior using setTimeout
|
|
410
|
+
* @param {FrameRequestCallback} callback - Function to call before next repaint
|
|
411
|
+
* @returns {number} Request ID for cancellation
|
|
412
|
+
*/
|
|
413
|
+
window.requestAnimationFrame = window.requestAnimationFrame || function(callback) {
|
|
414
|
+
const start = Date.now();
|
|
415
|
+
return setTimeout(function() {
|
|
416
|
+
callback(Date.now() - start);
|
|
417
|
+
}, 16); // ~60fps
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// Make it look native
|
|
421
|
+
Object.defineProperty(window.requestAnimationFrame, 'toString', {
|
|
422
|
+
value: function() { return 'function requestAnimationFrame() { [native code] }'; }
|
|
423
|
+
});
|
|
424
|
+
\`\`\`
|
|
425
|
+
|
|
426
|
+
Now provide the implementation for \`${apiPath}\`:`;
|
|
427
|
+
const response = await this.llm.chat([
|
|
428
|
+
{ role: 'system', content: systemPrompt },
|
|
429
|
+
{ role: 'user', content: userPrompt }
|
|
430
|
+
]);
|
|
431
|
+
const codeMatch = response.content.match(/```(?:javascript|js)?\s*([\s\S]*?)\s*```/);
|
|
432
|
+
if (codeMatch && codeMatch[1]) {
|
|
433
|
+
return codeMatch[1].trim();
|
|
434
|
+
}
|
|
435
|
+
const trimmed = response.content.trim();
|
|
436
|
+
if (trimmed.includes('function') || trimmed.includes('const') || trimmed.includes('var')) {
|
|
437
|
+
return trimmed;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
logger.error('API实现推断失败', error);
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
async generateSuggestions(detected, missing, browserType) {
|
|
447
|
+
if (!this.llm) {
|
|
448
|
+
return this.getDefaultSuggestions(detected, missing);
|
|
449
|
+
}
|
|
450
|
+
try {
|
|
451
|
+
const systemPrompt = `# Role
|
|
452
|
+
You are a browser automation and anti-detection expert providing actionable recommendations.
|
|
453
|
+
|
|
454
|
+
# Task
|
|
455
|
+
Generate 3-5 specific, prioritized recommendations for browser environment emulation.
|
|
456
|
+
|
|
457
|
+
# Recommendation Criteria
|
|
458
|
+
1. **Actionable**: Provide specific steps or code snippets
|
|
459
|
+
2. **Prioritized**: Most critical issues first
|
|
460
|
+
3. **Realistic**: Based on real-world anti-bot scenarios
|
|
461
|
+
4. **Concise**: One clear sentence per recommendation
|
|
462
|
+
5. **Technical**: Include specific API names or techniques`;
|
|
463
|
+
const userPrompt = `# Environment Analysis
|
|
464
|
+
- **Target Browser**: ${browserType.toUpperCase()}
|
|
465
|
+
- **Detected Variables**: ${Object.values(detected).flat().length} environment variables accessed
|
|
466
|
+
- **Missing APIs**: ${missing.length} APIs need implementation
|
|
467
|
+
|
|
468
|
+
# Missing API Details
|
|
469
|
+
${missing.slice(0, 20).map(m => `- \`${m.path}\` (${m.type})`).join('\n')}
|
|
470
|
+
${missing.length > 20 ? `\n... and ${missing.length - 20} more` : ''}
|
|
471
|
+
|
|
472
|
+
# Key Patterns Detected
|
|
473
|
+
- Navigator access: ${detected.navigator.length} properties
|
|
474
|
+
- Window access: ${detected.window.length} properties
|
|
475
|
+
- Document access: ${detected.document.length} properties
|
|
476
|
+
- Screen access: ${detected.screen.length} properties
|
|
477
|
+
|
|
478
|
+
# Required Output
|
|
479
|
+
Return ONLY a JSON array of 3-5 actionable recommendations:
|
|
480
|
+
|
|
481
|
+
\`\`\`json
|
|
482
|
+
[
|
|
483
|
+
"Recommendation 1 with specific action",
|
|
484
|
+
"Recommendation 2 with specific action",
|
|
485
|
+
"Recommendation 3 with specific action"
|
|
486
|
+
]
|
|
487
|
+
\`\`\`
|
|
488
|
+
|
|
489
|
+
# Example Output
|
|
490
|
+
\`\`\`json
|
|
491
|
+
[
|
|
492
|
+
"Set navigator.webdriver to false using Object.defineProperty() before page load to avoid Selenium detection",
|
|
493
|
+
"Implement navigator.plugins with at least 3 realistic plugins (PDF, Chrome PDF Viewer, Native Client) to pass plugin enumeration checks",
|
|
494
|
+
"Override canvas toDataURL() to return consistent fingerprint hash across sessions to avoid canvas fingerprinting",
|
|
495
|
+
"Use Puppeteer Stealth plugin or manually patch window.chrome object to include runtime, loadTimes, and csi properties",
|
|
496
|
+
"Ensure navigator.userAgent, navigator.platform, and navigator.vendor are consistent (e.g., Windows UA must have Win32 platform)"
|
|
497
|
+
]
|
|
498
|
+
\`\`\`
|
|
499
|
+
|
|
500
|
+
# Guidelines
|
|
501
|
+
- Focus on high-impact, easy-to-implement fixes first
|
|
502
|
+
- Mention specific tools (Puppeteer Stealth, undetected-chromedriver) when relevant
|
|
503
|
+
- Include code snippets in recommendations when helpful
|
|
504
|
+
- Prioritize anti-detection over completeness
|
|
505
|
+
|
|
506
|
+
Now generate recommendations:`;
|
|
507
|
+
const response = await this.llm.chat([
|
|
508
|
+
{ role: 'system', content: systemPrompt },
|
|
509
|
+
{ role: 'user', content: userPrompt }
|
|
510
|
+
]);
|
|
511
|
+
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)\s*```/) ||
|
|
512
|
+
response.content.match(/\[[\s\S]*\]/);
|
|
513
|
+
if (jsonMatch) {
|
|
514
|
+
const jsonStr = jsonMatch[1] || jsonMatch[0];
|
|
515
|
+
const suggestions = JSON.parse(jsonStr);
|
|
516
|
+
if (Array.isArray(suggestions) && suggestions.every(s => typeof s === 'string')) {
|
|
517
|
+
return suggestions;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return this.getDefaultSuggestions(detected, missing);
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
logger.error('生成建议失败', error);
|
|
524
|
+
return this.getDefaultSuggestions(detected, missing);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
getDefaultSuggestions(detected, missing) {
|
|
528
|
+
const suggestions = [];
|
|
529
|
+
const totalVars = Object.values(detected).flat().length;
|
|
530
|
+
if (totalVars > 50) {
|
|
531
|
+
suggestions.push('检测到大量环境变量访问,建议使用真实浏览器环境提取功能');
|
|
532
|
+
}
|
|
533
|
+
if (missing.length > 10) {
|
|
534
|
+
suggestions.push(`有${missing.length}个API需要补充,建议优先补充高重要性的API`);
|
|
535
|
+
}
|
|
536
|
+
if (detected.navigator.some(v => v.includes('webdriver'))) {
|
|
537
|
+
suggestions.push('检测到webdriver检测,建议设置navigator.webdriver = false');
|
|
538
|
+
}
|
|
539
|
+
if (detected.navigator.some(v => v.includes('plugins'))) {
|
|
540
|
+
suggestions.push('检测到plugins访问,建议补充真实的插件列表');
|
|
541
|
+
}
|
|
542
|
+
if (detected.window.some(v => v.includes('chrome'))) {
|
|
543
|
+
suggestions.push('检测到chrome对象访问,建议补充window.chrome对象');
|
|
544
|
+
}
|
|
545
|
+
return suggestions;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
//# sourceMappingURL=AIEnvironmentAnalyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AIEnvironmentAnalyzer.js","sourceRoot":"","sources":["../../../src/modules/emulator/AIEnvironmentAnalyzer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAkC/C,MAAM,OAAO,qBAAqB;IACZ;IAApB,YAAoB,GAAgB;QAAhB,QAAG,GAAH,GAAG,CAAa;IAAG,CAAC;IAKxC,KAAK,CAAC,OAAO,CACX,IAAY,EACZ,QAAsC,EACtC,OAAqB,EACrB,cAA2B,QAAQ;QAEnC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;YAC9E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAE1E,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAEtE,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC9B,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAYO,mBAAmB,CACzB,IAAY,EACZ,QAAsC,EACtC,OAAqB,EACrB,WAAwB;QAExB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,0CAA0C,CAAC,CAAC,CAAC,IAAI,CAAC;QAErH,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEA4BwC,CAAC;QAE9D,MAAM,UAAU,GAAG;EACrB,WAAW,CAAC,WAAW,EAAE;;;;EAIzB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;EAKjC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;EAK3E,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qFAiIwE,CAAC;QAElF,OAAO,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC;IAC5C,CAAC;IAKO,eAAe,CAAC,QAAgB;QACtC,IAAI,CAAC;YAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,4BAA4B,CAAC;gBAC7C,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAE/C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC5B,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;YAC/B,CAAC;YAED,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAEnC,OAAO;gBACL,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,IAAI,EAAE;gBACvD,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,EAAE;gBAC7C,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,EAAE;gBACjD,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;gBACrC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,GAAG;aACrC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAChC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAKO,cAAc;QACpB,OAAO;YACL,oBAAoB,EAAE,EAAE;YACxB,eAAe,EAAE,EAAE;YACnB,iBAAiB,EAAE,EAAE;YACrB,WAAW,EAAE,EAAE;YACf,UAAU,EAAE,CAAC;SACd,CAAC;IACJ,CAAC;IAQD,KAAK,CAAC,gBAAgB,CAAC,IAAY;QACjC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8FAmCmE,CAAC;YAEzF,MAAM,UAAU,GAAG;;EAEvB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CAgElC,CAAC;YAEvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBACnC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;gBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC;gBACrD,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAEvD,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YAED,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACjC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAOD,KAAK,CAAC,sBAAsB,CAC1B,OAAe,EACf,OAAe;QAEf,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;oCAqBS,CAAC;YAE/B,MAAM,UAAU,GAAG;IACrB,OAAO;;;;EAIT,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAkC3C,OAAO,KAAK,CAAC;YAE9C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBACnC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;gBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC,CAAC,CAAC;YAGH,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;YACrF,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9B,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7B,CAAC;YAGD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAExC,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzF,OAAO,OAAO,CAAC;YACjB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAOD,KAAK,CAAC,mBAAmB,CACvB,QAAsC,EACtC,OAAqB,EACrB,WAAwB;QAExB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,YAAY,GAAG;;;;;;;;;;;2DAWgC,CAAC;YAEtD,MAAM,UAAU,GAAG;wBACD,WAAW,CAAC,WAAW,EAAE;4BACrB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM;sBAC3C,OAAO,CAAC,MAAM;;;EAGlC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;EACvE,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,OAAO,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;;;sBAG9C,QAAQ,CAAC,SAAS,CAAC,MAAM;mBAC5B,QAAQ,CAAC,MAAM,CAAC,MAAM;qBACpB,QAAQ,CAAC,QAAQ,CAAC,MAAM;mBAC1B,QAAQ,CAAC,MAAM,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BA8BX,CAAC;YAEzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBACnC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;gBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC;gBACrD,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAEvD,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAExC,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;oBAChF,OAAO,WAAW,CAAC;gBACrB,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC9B,OAAO,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAKO,qBAAqB,CAC3B,QAAsC,EACtC,OAAqB;QAErB,MAAM,WAAW,GAAa,EAAE,CAAC;QAEjC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;QACxD,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;YACnB,WAAW,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACxB,WAAW,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,yBAAyB,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;YAC1D,WAAW,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACxD,WAAW,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACpD,WAAW,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { BrowserType } from './BrowserEnvironmentRules.js';
|
|
2
|
+
export type APIType = 'property' | 'method' | 'constructor' | 'event';
|
|
3
|
+
export interface APIDefinition {
|
|
4
|
+
name: string;
|
|
5
|
+
path: string;
|
|
6
|
+
type: APIType;
|
|
7
|
+
returnType?: string;
|
|
8
|
+
parameters?: Array<{
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
optional?: boolean;
|
|
12
|
+
defaultValue?: any;
|
|
13
|
+
}>;
|
|
14
|
+
implementation?: string | Function;
|
|
15
|
+
description?: string;
|
|
16
|
+
browsers?: BrowserType[];
|
|
17
|
+
minVersion?: Record<BrowserType, string>;
|
|
18
|
+
deprecated?: boolean;
|
|
19
|
+
replacement?: string;
|
|
20
|
+
antiCrawlImportance?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class BrowserAPIDatabase {
|
|
23
|
+
private apis;
|
|
24
|
+
constructor();
|
|
25
|
+
private initializeAPIs;
|
|
26
|
+
addAPI(api: APIDefinition): void;
|
|
27
|
+
getAPI(path: string): APIDefinition | undefined;
|
|
28
|
+
getAllAPIs(): APIDefinition[];
|
|
29
|
+
getAPIsByType(type: APIType): APIDefinition[];
|
|
30
|
+
searchAPIs(query: string): APIDefinition[];
|
|
31
|
+
exportToJSON(): string;
|
|
32
|
+
loadFromJSON(json: string): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=BrowserAPIDatabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserAPIDatabase.d.ts","sourceRoot":"","sources":["../../../src/modules/emulator/BrowserAPIDatabase.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAKhE,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,OAAO,CAAC;AAKtE,MAAM,WAAW,aAAa;IAE5B,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,OAAO,CAAC;IAGd,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,CAAC,EAAE,GAAG,CAAC;KACpB,CAAC,CAAC;IAGH,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAGnC,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAGzC,UAAU,CAAC,EAAE,OAAO,CAAC;IAGrB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAKD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAyC;;IASrD,OAAO,CAAC,cAAc;IAwVtB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAOhC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAO/C,UAAU,IAAI,aAAa,EAAE;IAO7B,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,EAAE;IAO7C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IAY1C,YAAY,IAAI,MAAM;IAOtB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAIjC"}
|