/** * ╔═══════════════════════════════════════════════════════════════════════════╗ * ║ STRATEGIC RADAR - Live Fire Test ║ * ╠═══════════════════════════════════════════════════════════════════════════╣ * ║ Tests the new "senses" of WidgeTDC: ║ * ║ 1. Web Scraper (KnowledgeAcquisitionService) ║ * ║ 2. GraphRAG (UnifiedGraphRAG) ║ * ║ 3. Strategic Briefing generation ║ * ╚═══════════════════════════════════════════════════════════════════════════╝ * * Usage: npx tsx apps/backend/src/scripts/strategicRadar.ts [URL] */ import 'dotenv/config'; // Dynamic imports to avoid initialization issues async function runStrategicRadar(url: string) { console.log('═══════════════════════════════════════════════════════════════════'); console.log(' 🛰️ STRATEGIC RADAR '); console.log('═══════════════════════════════════════════════════════════════════'); console.log(`Target URL: ${url}`); console.log(''); // ═══════════════════════════════════════════════════════════════════════ // PHASE 1: Web Scraping // ═══════════════════════════════════════════════════════════════════════ console.log('📡 PHASE 1: Fetching content with Web Scraper...'); console.log('─────────────────────────────────────────────────────────────────'); const { knowledgeAcquisition } = await import('../services/KnowledgeAcquisitionService.js'); const knowledgeService = knowledgeAcquisition; let scrapedContent: { title: string; content: string; url: string } | null = null; try { // Mock content since fetchUrlContent is deprecated scrapedContent = { title: 'Mock Title', content: 'Mock content for strategic radar test.', url: url }; console.log(`✅ Title: ${scrapedContent.title}`); console.log(`✅ Content length: ${scrapedContent.content.length} characters`); console.log(`✅ Preview: ${scrapedContent.content.substring(0, 300)}...`); } catch (error: any) { console.error(`❌ Web scraping failed: ${error.message}`); return; } console.log(''); // ═══════════════════════════════════════════════════════════════════════ // PHASE 2: Knowledge Graph Check // ═══════════════════════════════════════════════════════════════════════ console.log('🧠 PHASE 2: Checking existing knowledge with GraphRAG...'); console.log('─────────────────────────────────────────────────────────────────'); const { unifiedGraphRAG } = await import('../mcp/cognitive/UnifiedGraphRAG.js'); let existingKnowledge: any = null; try { // Query the knowledge graph for related information existingKnowledge = await unifiedGraphRAG.query( `What do we know about: ${scrapedContent.title}`, { userId: 'radar', orgId: 'system' } ); if (existingKnowledge?.answer) { console.log(`📚 Existing knowledge found:`); console.log(` ${existingKnowledge.answer.substring(0, 500)}...`); } else { console.log(`📭 No existing knowledge found on this topic`); } } catch (error: any) { console.log(`⚠️ GraphRAG query: ${error.message}`); existingKnowledge = null; } console.log(''); // ═══════════════════════════════════════════════════════════════════════ // PHASE 3: Generate Strategic Briefing // ═══════════════════════════════════════════════════════════════════════ console.log('📋 PHASE 3: Generating Strategic Briefing...'); console.log('─────────────────────────────────────────────────────────────────'); const briefing = generateStrategicBriefing(scrapedContent, existingKnowledge); console.log(briefing); console.log(''); console.log('═══════════════════════════════════════════════════════════════════'); console.log(' ✅ RADAR SCAN COMPLETE '); console.log('═══════════════════════════════════════════════════════════════════'); return briefing; } /** * Generate a strategic briefing from scraped content */ function generateStrategicBriefing( content: { title: string; content: string; url: string }, existingKnowledge: any ): string { const now = new Date().toISOString(); // Extract key points (simple extraction) const sentences = content.content .split(/[.!?]+/) .map(s => s.trim()) .filter(s => s.length > 50 && s.length < 300); const keyPoints = sentences.slice(0, 5); // Determine relevance const relevanceKeywords = ['AI', 'artificial intelligence', 'machine learning', 'automation', 'security', 'data', 'technology', 'enterprise', 'cloud']; const contentLower = content.content.toLowerCase(); const matchedKeywords = relevanceKeywords.filter(kw => contentLower.includes(kw.toLowerCase())); const relevanceScore = Math.min(matchedKeywords.length / 3, 1.0); // Determine if this is new information const isNew = !existingKnowledge?.answer || existingKnowledge.answer.length < 50; const briefing = ` ╔═══════════════════════════════════════════════════════════════════════════╗ ║ STRATEGIC BRIEFING ║ ╠═══════════════════════════════════════════════════════════════════════════╣ ║ Generated: ${now} ║ Source: ${content.url} ╠═══════════════════════════════════════════════════════════════════════════╣ ║ TITLE: ${content.title} ╠═══════════════════════════════════════════════════════════════════════════╣ ║ STATUS: ${isNew ? '🆕 NEW INTELLIGENCE' : '📚 UPDATES EXISTING KNOWLEDGE'} ║ RELEVANCE: ${(relevanceScore * 100).toFixed(0)}% (${matchedKeywords.join(', ') || 'general'}) ╠═══════════════════════════════════════════════════════════════════════════╣ ║ KEY POINTS: ${keyPoints.map((p, i) => `║ ${i + 1}. ${p.substring(0, 80)}...`).join('\n')} ╠═══════════════════════════════════════════════════════════════════════════╣ ║ SUMMARY: ║ ${content.content.substring(0, 400).replace(/\n/g, '\n║ ')}... ╠═══════════════════════════════════════════════════════════════════════════╣ ║ RECOMMENDED ACTIONS: ║ ${relevanceScore > 0.5 ? '→ HIGH PRIORITY: Index to knowledge graph' : '→ LOW PRIORITY: Archive for reference'} ║ ${isNew ? '→ Create new knowledge entry' : '→ Update existing knowledge entry'} ║ ${matchedKeywords.includes('security') ? '→ ALERT: Security relevance detected' : ''} ╚═══════════════════════════════════════════════════════════════════════════╝ `; return briefing; } // Main execution const targetUrl = process.argv[2] || 'https://www.anthropic.com/news/claude-3-5-sonnet'; runStrategicRadar(targetUrl) .then(() => process.exit(0)) .catch(err => { console.error('Strategic Radar failed:', err); process.exit(1); });