Kraft102's picture
Update backend source
34367da verified
/**
* ╔═══════════════════════════════════════════════════════════════════════════╗
* β•‘ 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);
});