Merge: Network Discovery Agent deployment script - resolved conflicts

This commit is contained in:
Vinnie Esposito 2025-11-23 11:01:58 -06:00
commit 1d75f0c22c
2 changed files with 266 additions and 1 deletions

View file

@ -0,0 +1,263 @@
#!/usr/bin/env bun
/**
* NetworkDiscoveryAgent Deployment Script
* Agent 8 - Geographic Network Discovery and Analysis
*
* This script provides standalone deployment for the NetworkDiscoveryAgent,
* which maps and analyzes the geographic distribution of the plant network.
*
* Responsibilities:
* - Map plant distribution across regions
* - Identify network hotspots and clusters
* - Suggest grower/consumer connections
* - Track network growth patterns
* - Detect coverage gaps
*
* Usage:
* bun run deploy/NetworkDiscoveryAgent.ts
* bun run deploy:network-discovery
*
* Environment Variables:
* AGENT_INTERVAL_MS - Execution interval (default: 600000 = 10 min)
* AGENT_LOG_LEVEL - Log level: debug, info, warn, error (default: info)
* AGENT_AUTO_RESTART - Auto-restart on failure (default: true)
* AGENT_MAX_RETRIES - Max retry attempts (default: 3)
*/
import { getNetworkDiscoveryAgent, NetworkDiscoveryAgent } from '../lib/agents/NetworkDiscoveryAgent';
// Configuration from environment
const config = {
intervalMs: parseInt(process.env.AGENT_INTERVAL_MS || '600000'),
logLevel: process.env.AGENT_LOG_LEVEL || 'info',
autoRestart: process.env.AGENT_AUTO_RESTART !== 'false',
maxRetries: parseInt(process.env.AGENT_MAX_RETRIES || '3'),
};
// Logger utility
const log = {
debug: (...args: any[]) => config.logLevel === 'debug' && console.log('[DEBUG]', ...args),
info: (...args: any[]) => ['debug', 'info'].includes(config.logLevel) && console.log('[INFO]', ...args),
warn: (...args: any[]) => ['debug', 'info', 'warn'].includes(config.logLevel) && console.warn('[WARN]', ...args),
error: (...args: any[]) => console.error('[ERROR]', ...args),
};
/**
* Format uptime as human-readable string
*/
function formatUptime(ms: number): string {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;
if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
return `${seconds}s`;
}
/**
* Display agent status
*/
function displayStatus(agent: NetworkDiscoveryAgent): void {
const metrics = agent.getMetrics();
const analysis = agent.getNetworkAnalysis();
const clusters = agent.getClusters();
const gaps = agent.getCoverageGaps();
const suggestions = agent.getConnectionSuggestions();
const growth = agent.getGrowthHistory();
const regions = agent.getRegionalStats();
console.log('\n' + '='.repeat(60));
console.log(' NETWORK DISCOVERY AGENT - STATUS REPORT');
console.log('='.repeat(60));
// Agent Metrics
console.log('\n AGENT METRICS');
console.log(' ' + '-'.repeat(40));
console.log(` Status: ${agent.status}`);
console.log(` Uptime: ${formatUptime(metrics.uptime)}`);
console.log(` Tasks Completed: ${metrics.tasksCompleted}`);
console.log(` Tasks Failed: ${metrics.tasksFailed}`);
console.log(` Avg Execution: ${Math.round(metrics.averageExecutionMs)}ms`);
console.log(` Last Run: ${metrics.lastRunAt || 'Never'}`);
// Network Analysis
console.log('\n NETWORK ANALYSIS');
console.log(' ' + '-'.repeat(40));
console.log(` Total Nodes: ${analysis.totalNodes}`);
console.log(` Connections: ${analysis.totalConnections}`);
console.log(` Clusters: ${clusters.length}`);
console.log(` Hotspots: ${analysis.hotspots.length}`);
console.log(` Coverage Gaps: ${gaps.length}`);
console.log(` Suggestions: ${suggestions.length}`);
// Cluster Details
if (clusters.length > 0) {
console.log('\n TOP CLUSTERS');
console.log(' ' + '-'.repeat(40));
const topClusters = clusters.slice(0, 5);
for (const cluster of topClusters) {
console.log(` - ${cluster.activityLevel.toUpperCase()} activity cluster`);
console.log(` Nodes: ${cluster.nodes.length}, Radius: ${cluster.radius}km`);
if (cluster.dominantSpecies.length > 0) {
console.log(` Species: ${cluster.dominantSpecies.slice(0, 3).join(', ')}`);
}
}
}
// Coverage Gaps
if (gaps.length > 0) {
console.log('\n COVERAGE GAPS');
console.log(' ' + '-'.repeat(40));
for (const gap of gaps.slice(0, 3)) {
console.log(` - ${gap.populationDensity.toUpperCase()} area`);
console.log(` Distance to nearest: ${gap.distanceToNearest}km`);
console.log(` Potential demand: ${gap.potentialDemand}`);
}
}
// Top Suggestions
if (suggestions.length > 0) {
console.log('\n TOP CONNECTION SUGGESTIONS');
console.log(' ' + '-'.repeat(40));
for (const suggestion of suggestions.slice(0, 3)) {
console.log(` - Strength: ${suggestion.strength}%`);
console.log(` Distance: ${suggestion.distance}km`);
console.log(` Reason: ${suggestion.reason}`);
}
}
// Regional Stats
if (regions.length > 0) {
console.log('\n REGIONAL STATISTICS');
console.log(' ' + '-'.repeat(40));
for (const region of regions) {
if (region.nodeCount > 0) {
console.log(` ${region.region}:`);
console.log(` Nodes: ${region.nodeCount}, Plants: ${region.plantCount}`);
console.log(` Species: ${region.uniqueSpecies}, Activity: ${region.avgActivityScore}`);
}
}
}
// Growth Trend
if (growth.length > 0) {
const latest = growth[growth.length - 1];
console.log('\n NETWORK GROWTH');
console.log(' ' + '-'.repeat(40));
console.log(` Total Nodes: ${latest.totalNodes}`);
console.log(` Total Connections: ${latest.totalConnections}`);
console.log(` New Nodes/Week: ${latest.newNodesWeek}`);
console.log(` Geographic Span: ${latest.geographicExpansion}km`);
}
// Alerts
const alerts = agent.getAlerts();
const unacknowledged = alerts.filter(a => !a.acknowledged);
if (unacknowledged.length > 0) {
console.log('\n ACTIVE ALERTS');
console.log(' ' + '-'.repeat(40));
for (const alert of unacknowledged.slice(0, 5)) {
console.log(` [${alert.severity.toUpperCase()}] ${alert.title}`);
console.log(` ${alert.message}`);
}
}
console.log('\n' + '='.repeat(60));
}
/**
* Main deployment function
*/
async function deploy(): Promise<void> {
console.log('\n' + '='.repeat(60));
console.log(' DEPLOYING NETWORK DISCOVERY AGENT (Agent 8)');
console.log('='.repeat(60));
console.log(`\n Configuration:`);
console.log(` - Interval: ${config.intervalMs}ms (${config.intervalMs / 60000} min)`);
console.log(` - Log Level: ${config.logLevel}`);
console.log(` - Auto Restart: ${config.autoRestart}`);
console.log(` - Max Retries: ${config.maxRetries}`);
console.log('');
// Get agent instance
const agent = getNetworkDiscoveryAgent();
// Register event handlers
agent.on('task_completed', (data) => {
log.info(`Task completed: ${JSON.stringify(data.result)}`);
});
agent.on('task_failed', (data) => {
log.error(`Task failed: ${data.error}`);
});
agent.on('agent_started', () => {
log.info('Network Discovery Agent started');
});
agent.on('agent_stopped', () => {
log.info('Network Discovery Agent stopped');
});
// Start the agent
log.info('Starting Network Discovery Agent...');
try {
await agent.start();
log.info('Agent started successfully');
// Run initial discovery
log.info('Running initial network discovery...');
await agent.runOnce();
log.info('Initial discovery complete');
// Display initial status
displayStatus(agent);
// Set up periodic status display
const statusInterval = setInterval(() => {
displayStatus(agent);
}, config.intervalMs);
// Handle shutdown signals
const shutdown = async (signal: string) => {
log.info(`Received ${signal}, shutting down...`);
clearInterval(statusInterval);
try {
await agent.stop();
log.info('Agent stopped gracefully');
process.exit(0);
} catch (error) {
log.error('Error during shutdown:', error);
process.exit(1);
}
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
// Keep the process running
log.info(`Agent running. Press Ctrl+C to stop.`);
log.info(`Next discovery in ${config.intervalMs / 60000} minutes...`);
} catch (error) {
log.error('Failed to start agent:', error);
if (config.autoRestart) {
log.info('Auto-restart enabled, retrying in 10 seconds...');
setTimeout(() => deploy(), 10000);
} else {
process.exit(1);
}
}
}
// Run deployment
deploy().catch((error) => {
console.error('Deployment failed:', error);
process.exit(1);
});

View file

@ -28,7 +28,9 @@
"db:seed": "bun run prisma/seed.ts", "db:seed": "bun run prisma/seed.ts",
"db:studio": "prisma studio", "db:studio": "prisma studio",
"prepare": "husky install", "prepare": "husky install",
"validate": "bun run type-check && bun run lint && bun run test" "validate": "bun run type-check && bun run lint && bun run test",
"deploy:network-discovery": "bun run deploy/NetworkDiscoveryAgent.ts",
"agent:network-discovery": "bun run deploy/NetworkDiscoveryAgent.ts"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.937.0", "@aws-sdk/client-s3": "^3.937.0",