Spaces:
Paused
Paused
| import { Request, Response, Router } from 'express'; | |
| import { OmniHarvester } from './OmniHarvester.js'; | |
| import { knowledgeAcquisition } from '../KnowledgeAcquisitionService.js'; | |
| import path from 'path'; | |
| const router = Router(); | |
| const harvester = new OmniHarvester(path.resolve(process.cwd(), '../../')); // Scan project root | |
| // --- HARVEST CONTROL STATE --- | |
| let isHarvesting = false; | |
| let currentHarvestId: string | null = null; | |
| let harvestStats = { | |
| projectFiles: 0, | |
| intelFiles: 0, | |
| startTime: 0 | |
| }; | |
| // 1. Harvest Status | |
| router.get('/harvest/status', (req, res) => { | |
| res.json({ | |
| isRunning: isHarvesting, | |
| harvestId: currentHarvestId, | |
| canAbort: isHarvesting, | |
| duration: isHarvesting ? Date.now() - harvestStats.startTime : 0 | |
| }); | |
| }); | |
| // 2. Harvest Summary | |
| router.get('/harvest/summary', async (req, res) => { | |
| // In a real scenario, query Neo4j for accurate counts. | |
| // For now, return tracking stats. | |
| try { | |
| const vectorStats = await knowledgeAcquisition.getVectorStats(); | |
| res.json({ | |
| project: { | |
| totalFiles: harvestStats.projectFiles, | |
| byStrategy: { 'code': harvestStats.projectFiles } | |
| }, | |
| intel: { | |
| totalFiles: vectorStats.totalRecords || harvestStats.intelFiles, | |
| byStrategy: { 'web': vectorStats.totalRecords || 0 } | |
| }, | |
| totalFiles: harvestStats.projectFiles + (vectorStats.totalRecords || 0) | |
| }); | |
| } catch (err) { | |
| res.json({ | |
| project: { totalFiles: 0, byStrategy: {} }, | |
| intel: { totalFiles: 0, byStrategy: {} }, | |
| totalFiles: 0 | |
| }); | |
| } | |
| }); | |
| // 3. Start Harvest (Project) | |
| router.post('/harvest', async (req, res) => { | |
| if (isHarvesting) return res.status(409).json({ error: 'Harvest already in progress' }); | |
| isHarvesting = true; | |
| currentHarvestId = `h-${Date.now()}`; | |
| harvestStats.startTime = Date.now(); | |
| // Start async process | |
| (async () => { | |
| try { | |
| // Use OmniHarvester to scan file system | |
| const nodes = await harvester.scan(); | |
| // TODO: Actually ingest these nodes into KnowledgeAcquisition | |
| harvestStats.projectFiles = nodes.length; // Simplified count | |
| } catch (e) { | |
| console.error("Harvest failed:", e); | |
| } finally { | |
| isHarvesting = false; | |
| currentHarvestId = null; | |
| } | |
| })(); | |
| res.json({ message: 'Project harvest started', harvestId: currentHarvestId }); | |
| }); | |
| // 4. Start Harvest (Intel / Targets) | |
| router.post('/harvest/intel', async (req, res) => { | |
| if (isHarvesting) return res.status(409).json({ error: 'Harvest already in progress' }); | |
| isHarvesting = true; | |
| currentHarvestId = `i-${Date.now()}`; | |
| harvestStats.startTime = Date.now(); | |
| (async () => { | |
| try { | |
| const results = await knowledgeAcquisition.acquireFromTargets(); | |
| harvestStats.intelFiles += results.filter(r => r.success).length; | |
| } catch (e) { | |
| console.error("Intel harvest failed:", e); | |
| } finally { | |
| isHarvesting = false; | |
| currentHarvestId = null; | |
| } | |
| })(); | |
| res.json({ message: 'Intel harvest started', harvestId: currentHarvestId }); | |
| }); | |
| // 5. Full Sweep | |
| router.post('/harvest/all', async (req, res) => { | |
| if (isHarvesting) return res.status(409).json({ error: 'Harvest already in progress' }); | |
| isHarvesting = true; | |
| currentHarvestId = `f-${Date.now()}`; | |
| (async () => { | |
| try { | |
| // 1. Project | |
| const nodes = await harvester.scan(); | |
| harvestStats.projectFiles = nodes.length; | |
| // 2. Intel | |
| const results = await knowledgeAcquisition.acquireFromTargets(); | |
| harvestStats.intelFiles += results.filter(r => r.success).length; | |
| } finally { | |
| isHarvesting = false; | |
| currentHarvestId = null; | |
| } | |
| })(); | |
| res.json({ message: 'Full sweep started', harvestId: currentHarvestId }); | |
| }); | |
| // 6. Abort / Nødstop | |
| router.post('/harvest/abort', (req, res) => { | |
| if (!isHarvesting) return res.status(400).json({ message: 'No active harvest to abort' }); | |
| // Logic to kill the async process would go here (requires AbortController implementation in services) | |
| isHarvesting = false; | |
| currentHarvestId = null; | |
| res.json({ success: true, message: 'Harvest aborted immediately' }); | |
| }); | |
| router.get('/graph', async (req: Request, res: Response) => { | |
| try { | |
| // In a real implementation, this would query Neo4j. | |
| // For the prototype, we scan the file system live and return a tree structure | |
| // which the frontend can visualize as a graph. | |
| const nodes = await harvester.scan(); | |
| // Flatten the tree for the 3D graph (simplified) | |
| // This maps the recursive structure to a flat node/link list | |
| const graphData = { | |
| nodes: [] as any[], | |
| links: [] as any[] | |
| }; | |
| let idCounter = 0; | |
| function processNode(node: any, parentId: number | null = null) { | |
| const currentId = idCounter++; | |
| const isDir = node.type === 'directory'; | |
| graphData.nodes.push({ | |
| id: currentId, | |
| name: node.name, | |
| type: node.type, | |
| val: isDir ? 5 : 1, // Size for visualizer | |
| color: isDir ? '#ff00ff' : '#00B5CB' | |
| }); | |
| if (parentId !== null) { | |
| graphData.links.push({ | |
| source: parentId, | |
| target: currentId | |
| }); | |
| } | |
| if (node.children) { | |
| node.children.forEach((child: any) => processNode(child, currentId)); | |
| } | |
| } | |
| // Only process first level depth for performance in this mocked version if it's huge | |
| nodes.forEach(node => processNode(node, null)); | |
| res.json(graphData); | |
| } catch (error: any) { | |
| console.error("Evolution Graph Error:", error); | |
| res.status(500).json({ error: error.message }); | |
| } | |
| }); | |
| router.post('/evolve', async (req: Request, res: Response) => { | |
| // Placeholder for self-modification endpoint | |
| res.json({ message: "Evolution request received. Analysis started." }); | |
| }); | |
| export const evolutionRouter = router; |