Kraft102 commited on
Commit
f1a6f7e
Β·
verified Β·
1 Parent(s): 33f2414

Deploy from GitHub Actions 2025-12-16_04-55-23

Browse files
apps/backend/src/index.ts CHANGED
@@ -171,7 +171,6 @@ async function startServer() {
171
  // Cloud defaults like 7860 break the internal reflex arc.
172
  const PORT = 3001;
173
 
174
- // Start server IMMEDIATELY
175
  server.listen(PORT, '0.0.0.0', () => {
176
  console.log(`πŸš€ Backend server running on http://0.0.0.0:${PORT}`);
177
  console.log(`πŸ“‘ MCP WebSocket available at ws://0.0.0.0:${PORT}/mcp/ws`);
@@ -1227,21 +1226,29 @@ async function startServer() {
1227
  * GET /api/evolution/graph/stats
1228
  * Get Neo4j graph statistics for 3D visualization
1229
  * πŸ”— NEURAL LINK ENDPOINT
 
 
 
1230
  */
1231
  app.get('/api/evolution/graph/stats', async (_req, res) => {
1232
  try {
1233
  const { neo4jService } = await import('./database/Neo4jService.js');
1234
 
1235
- // 1. Fetch Stats
1236
- const statsQuery = `
1237
- MATCH (n)
1238
- OPTIONAL MATCH ()-[r]->()
1239
- RETURN count(DISTINCT n) as nodes, count(DISTINCT r) as relationships
1240
- `;
1241
- const statsResult = await neo4jService.runQuery(statsQuery);
 
 
 
 
 
1242
  const stats = {
1243
- nodes: statsResult[0]?.nodes?.toNumber ? statsResult[0].nodes.toNumber() : (statsResult[0]?.nodes || 0),
1244
- relationships: statsResult[0]?.relationships?.toNumber ? statsResult[0].relationships.toNumber() : (statsResult[0]?.relationships || 0)
1245
  };
1246
 
1247
  // 2. Fetch Sample Nodes for Visualization
 
171
  // Cloud defaults like 7860 break the internal reflex arc.
172
  const PORT = 3001;
173
 
 
174
  server.listen(PORT, '0.0.0.0', () => {
175
  console.log(`πŸš€ Backend server running on http://0.0.0.0:${PORT}`);
176
  console.log(`πŸ“‘ MCP WebSocket available at ws://0.0.0.0:${PORT}/mcp/ws`);
 
1226
  * GET /api/evolution/graph/stats
1227
  * Get Neo4j graph statistics for 3D visualization
1228
  * πŸ”— NEURAL LINK ENDPOINT
1229
+ *
1230
+ * OPTIMIZED: Uses separate lightweight queries to avoid memory overflow
1231
+ * on Neo4j AuraDB free tier (824 MiB limit)
1232
  */
1233
  app.get('/api/evolution/graph/stats', async (_req, res) => {
1234
  try {
1235
  const { neo4jService } = await import('./database/Neo4jService.js');
1236
 
1237
+ // 1. Fetch Stats using memory-efficient separate queries
1238
+ // Note: The original MATCH (n) OPTIONAL MATCH ()-[r]->() creates a cross-product
1239
+ // that exceeds Neo4j AuraDB's memory limits on large graphs (150K+ nodes)
1240
+ const nodeCountQuery = `MATCH (n) RETURN count(n) as nodes`;
1241
+ const relCountQuery = `MATCH ()-[r]->() RETURN count(r) as relationships`;
1242
+
1243
+ // Run queries in parallel for better performance
1244
+ const [nodeResult, relResult] = await Promise.all([
1245
+ neo4jService.runQuery(nodeCountQuery),
1246
+ neo4jService.runQuery(relCountQuery)
1247
+ ]);
1248
+
1249
  const stats = {
1250
+ nodes: nodeResult[0]?.nodes?.toNumber ? nodeResult[0].nodes.toNumber() : (nodeResult[0]?.nodes || 0),
1251
+ relationships: relResult[0]?.relationships?.toNumber ? relResult[0].relationships.toNumber() : (relResult[0]?.relationships || 0)
1252
  };
1253
 
1254
  // 2. Fetch Sample Nodes for Visualization
apps/backend/src/mcp/servers/NeuralBridgeServer.ts CHANGED
@@ -1471,7 +1471,8 @@ class NeuralBridgeServer {
1471
  break;
1472
 
1473
  case 'backend':
1474
- const backendResponse = await fetch('http://localhost:3001/api/health', {
 
1475
  signal: AbortSignal.timeout(5000)
1476
  });
1477
  success = backendResponse.ok;
 
1471
  break;
1472
 
1473
  case 'backend':
1474
+ const backendPort = process.env.PORT || 7860;
1475
+ const backendResponse = await fetch(`http://localhost:${backendPort}/api/health`, {
1476
  signal: AbortSignal.timeout(5000)
1477
  });
1478
  success = backendResponse.ok;
apps/backend/src/services/CognitiveErrorIntelligence.ts CHANGED
@@ -33,6 +33,9 @@ import { logger } from '../utils/logger.js';
33
 
34
  const log = logger.child({ module: 'CognitiveErrorIntelligence' });
35
 
 
 
 
36
  // ═══════════════════════════════════════════════════════════════════════════
37
  // TYPES
38
  // ═══════════════════════════════════════════════════════════════════════════
@@ -558,8 +561,11 @@ export class CognitiveErrorIntelligence extends EventEmitter {
558
  });
559
  });
560
  } else if (action.apiCall) {
561
- // Execute API call
562
- const response = await fetch(action.apiCall.endpoint, {
 
 
 
563
  method: action.apiCall.method,
564
  headers: { 'Content-Type': 'application/json' },
565
  body: action.apiCall.body ? JSON.stringify(action.apiCall.body) : undefined
@@ -709,7 +715,7 @@ export class CognitiveErrorIntelligence extends EventEmitter {
709
  name: 'Restart Redis Connection',
710
  description: 'Reconnect to Redis when connection is lost',
711
  errorPatterns: ['ECONNREFUSED', 'redis', 'connection refused'],
712
- apiCall: { endpoint: 'http://localhost:3001/api/healing/service/redis', method: 'POST' },
713
  requiresApproval: false,
714
  riskLevel: 'low',
715
  successRate: 0.85,
@@ -720,7 +726,7 @@ export class CognitiveErrorIntelligence extends EventEmitter {
720
  name: 'Clear Memory Cache',
721
  description: 'Clear in-memory caches when memory is low',
722
  errorPatterns: ['heap', 'memory', 'OOM'],
723
- apiCall: { endpoint: 'http://localhost:3001/api/system/clear-cache', method: 'POST' },
724
  requiresApproval: false,
725
  riskLevel: 'low',
726
  successRate: 0.9,
@@ -731,7 +737,7 @@ export class CognitiveErrorIntelligence extends EventEmitter {
731
  name: 'Retry Database Connection',
732
  description: 'Attempt to reconnect to database',
733
  errorPatterns: ['database', 'postgres', 'neo4j', 'SQLSTATE'],
734
- apiCall: { endpoint: 'http://localhost:3001/api/healing/service/database', method: 'POST' },
735
  requiresApproval: false,
736
  riskLevel: 'medium',
737
  successRate: 0.75,
 
33
 
34
  const log = logger.child({ module: 'CognitiveErrorIntelligence' });
35
 
36
+ // Dynamic base URL for self-healing API calls
37
+ const getBaseUrl = () => `http://localhost:${process.env.PORT || 7860}`;
38
+
39
  // ═══════════════════════════════════════════════════════════════════════════
40
  // TYPES
41
  // ═══════════════════════════════════════════════════════════════════════════
 
561
  });
562
  });
563
  } else if (action.apiCall) {
564
+ // Execute API call - prepend base URL to relative paths
565
+ const endpoint = action.apiCall.endpoint.startsWith('/')
566
+ ? `${getBaseUrl()}${action.apiCall.endpoint}`
567
+ : action.apiCall.endpoint;
568
+ const response = await fetch(endpoint, {
569
  method: action.apiCall.method,
570
  headers: { 'Content-Type': 'application/json' },
571
  body: action.apiCall.body ? JSON.stringify(action.apiCall.body) : undefined
 
715
  name: 'Restart Redis Connection',
716
  description: 'Reconnect to Redis when connection is lost',
717
  errorPatterns: ['ECONNREFUSED', 'redis', 'connection refused'],
718
+ apiCall: { endpoint: '/api/healing/service/redis', method: 'POST' },
719
  requiresApproval: false,
720
  riskLevel: 'low',
721
  successRate: 0.85,
 
726
  name: 'Clear Memory Cache',
727
  description: 'Clear in-memory caches when memory is low',
728
  errorPatterns: ['heap', 'memory', 'OOM'],
729
+ apiCall: { endpoint: '/api/system/clear-cache', method: 'POST' },
730
  requiresApproval: false,
731
  riskLevel: 'low',
732
  successRate: 0.9,
 
737
  name: 'Retry Database Connection',
738
  description: 'Attempt to reconnect to database',
739
  errorPatterns: ['database', 'postgres', 'neo4j', 'SQLSTATE'],
740
+ apiCall: { endpoint: '/api/healing/service/database', method: 'POST' },
741
  requiresApproval: false,
742
  riskLevel: 'medium',
743
  successRate: 0.75,
apps/backend/src/services/NudgeService.ts CHANGED
@@ -249,17 +249,15 @@ class NudgeService {
249
 
250
  try {
251
  if (this.neo4jAdapter) {
252
- // Get current graph stats
253
- const statsResult = await this.neo4jAdapter.runQuery(`
254
- MATCH (n)
255
- WITH count(n) as nodeCount
256
- MATCH ()-[r]->()
257
- RETURN nodeCount, count(r) as relCount
258
- `);
259
-
260
- const stats = statsResult?.[0];
261
- const nodeCount = stats?.nodeCount || 0;
262
- const relCount = stats?.relCount || 0;
263
 
264
  // Create evolution event node
265
  await this.neo4jAdapter.runQuery(`
@@ -332,7 +330,7 @@ class NudgeService {
332
 
333
  try {
334
  // Trigger compilation via HTTP to self
335
- const port = process.env.PORT || 3001;
336
  const response = await fetch(`http://localhost:${port}/api/knowledge/compile`, {
337
  method: 'POST',
338
  headers: { 'Content-Type': 'application/json' }
 
249
 
250
  try {
251
  if (this.neo4jAdapter) {
252
+ // Get current graph stats - use separate queries to avoid memory overflow
253
+ // on Neo4j AuraDB free tier (824 MiB limit with 150K+ nodes)
254
+ const [nodeResult, relResult] = await Promise.all([
255
+ this.neo4jAdapter.runQuery(`MATCH (n) RETURN count(n) as nodeCount`),
256
+ this.neo4jAdapter.runQuery(`MATCH ()-[r]->() RETURN count(r) as relCount`)
257
+ ]);
258
+
259
+ const nodeCount = nodeResult?.[0]?.nodeCount || 0;
260
+ const relCount = relResult?.[0]?.relCount || 0;
 
 
261
 
262
  // Create evolution event node
263
  await this.neo4jAdapter.runQuery(`
 
330
 
331
  try {
332
  // Trigger compilation via HTTP to self
333
+ const port = process.env.PORT || 7860;
334
  const response = await fetch(`http://localhost:${port}/api/knowledge/compile`, {
335
  method: 'POST',
336
  headers: { 'Content-Type': 'application/json' }
apps/backend/src/services/agent/HansPedderAgentController.ts CHANGED
@@ -99,6 +99,13 @@ export class HansPedderAgentController {
99
 
100
  eventBus.on('threat:detected', () => {
101
  this.healthMetrics.lastIngestion = new Date();
 
 
 
 
 
 
 
102
  });
103
 
104
  eventBus.on('system:heartbeat', (data: any) => {
@@ -240,7 +247,8 @@ export class HansPedderAgentController {
240
 
241
  try {
242
  // Check if MCP tools endpoint responds (indicates server is ready)
243
- const port = process.env.PORT || 3001;
 
244
  const baseUrl = process.env.API_BASE_URL || `http://localhost:${port}`;
245
  const response = await fetch(`${baseUrl}/api/mcp/tools`, {
246
  method: 'GET',
@@ -275,8 +283,8 @@ export class HansPedderAgentController {
275
  const name = 'apiEndpoints';
276
 
277
  try {
278
- // Test key API endpoints (use port 3001 where backend runs)
279
- const port = process.env.PORT || 3001;
280
  const baseUrl = process.env.API_BASE_URL || `http://localhost:${port}`;
281
  const endpoints = [
282
  { url: `${baseUrl}/health`, method: 'GET' },
@@ -405,7 +413,7 @@ export class HansPedderAgentController {
405
  logger.info(' β†’ API endpoints unreachable - checking backend status...');
406
  fixAction = 'Health check on correct backend port';
407
  try {
408
- const backendPort = process.env.PORT || '3001';
409
  const testUrl = `http://localhost:${backendPort}/health`;
410
  const response = await fetch(testUrl, { signal: AbortSignal.timeout(3000) });
411
  if (response.ok) {
 
99
 
100
  eventBus.on('threat:detected', () => {
101
  this.healthMetrics.lastIngestion = new Date();
102
+ this.healthMetrics.dataflowOk = true;
103
+ });
104
+
105
+ // Also track threat feed broadcasts (from OpenPhish etc.)
106
+ eventBus.on('threats:broadcast', () => {
107
+ this.healthMetrics.lastIngestion = new Date();
108
+ this.healthMetrics.dataflowOk = true;
109
  });
110
 
111
  eventBus.on('system:heartbeat', (data: any) => {
 
247
 
248
  try {
249
  // Check if MCP tools endpoint responds (indicates server is ready)
250
+ // Default to 7860 which is the standard port for WidgeTDC backend (both local and HuggingFace)
251
+ const port = process.env.PORT || 7860;
252
  const baseUrl = process.env.API_BASE_URL || `http://localhost:${port}`;
253
  const response = await fetch(`${baseUrl}/api/mcp/tools`, {
254
  method: 'GET',
 
283
  const name = 'apiEndpoints';
284
 
285
  try {
286
+ // Test key API endpoints - default to 7860 which is standard for WidgeTDC
287
+ const port = process.env.PORT || 7860;
288
  const baseUrl = process.env.API_BASE_URL || `http://localhost:${port}`;
289
  const endpoints = [
290
  { url: `${baseUrl}/health`, method: 'GET' },
 
413
  logger.info(' β†’ API endpoints unreachable - checking backend status...');
414
  fixAction = 'Health check on correct backend port';
415
  try {
416
+ const backendPort = process.env.PORT || '7860';
417
  const testUrl = `http://localhost:${backendPort}/health`;
418
  const response = await fetch(testUrl, { signal: AbortSignal.timeout(3000) });
419
  if (response.ok) {