Spaces:
Paused
Paused
File size: 3,739 Bytes
33f2414 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | import fs from 'fs';
import path from 'path';
import { EventEmitter } from 'events';
// DEFINITION: Path to the Single Source of Truth
// Assuming running from apps/backend/src or similar structure in Docker
const HANDOVER_LOG_PATH = path.join(process.cwd(), '..', '..', 'docs', 'HANDOVER_LOG.md');
export class HandoverWatchdog extends EventEmitter {
private static instance: HandoverWatchdog;
private isWatching: boolean = false;
private lastProcessedTime: number = 0;
private constructor() {
super();
}
public static getInstance(): HandoverWatchdog {
if (!HandoverWatchdog.instance) {
HandoverWatchdog.instance = new HandoverWatchdog();
}
return HandoverWatchdog.instance;
}
/**
* Starts the surveillance of the Blackboard Protocol.
*/
public startWatch(): void {
if (this.isWatching) {
console.log('ποΈ [WATCHDOG] Already active.');
return;
}
console.log(`ποΈ [WATCHDOG] Initializing Blackboard Protocol surveillance...`);
console.log(`π [WATCHDOG] Target: ${HANDOVER_LOG_PATH}`);
// Verify existence of the Truth Document
if (!fs.existsSync(HANDOVER_LOG_PATH)) {
console.warn(`β οΈ [WATCHDOG] Critical Failure: Handover log not found at ${HANDOVER_LOG_PATH}`);
// Retry logic could be added here, but for now we warn
return;
}
try {
// We use watchFile for better Docker volume compatibility than fs.watch
fs.watchFile(HANDOVER_LOG_PATH, { interval: 2000 }, (curr, prev) => {
// Only trigger if modified time changed and it's newer than last process
if (curr.mtimeMs !== prev.mtimeMs) {
console.log('β‘ [WATCHDOG] Detect: Blackboard updated. Analyzing...');
this.analyzeBlackboard();
}
});
this.isWatching = true;
console.log('π’ [WATCHDOG] Active and Waiting for Signals.');
} catch (error) {
console.error('β [WATCHDOG] Failed to initialize:', error);
}
}
/**
* Reads the Blackboard and looks for "READY FOR [AGENT]" signals.
*/
private analyzeBlackboard(): void {
try {
const content = fs.readFileSync(HANDOVER_LOG_PATH, 'utf-8');
// REGEX LOGIC:
// We look for: **Status:** [BOLD/EMOJI?] READY FOR [AGENT_NAME]
// Captures the agent name. Case insensitive.
const statusRegex = /\*\*Status:\*\*\s*(?:β
|π΄|π’|\*\*)?\s*READY FOR\s*\[?(.*?)\]?/i;
// We only scan the last 2000 characters to be efficient
const recentContent = content.slice(-2000);
const match = statusRegex.exec(recentContent);
if (match && match[1]) {
const targetAgent = match[1].trim().replace(/\*|\]|\[/g, ''); // Cleanup cleanup
console.log(`π [WATCHDOG] SIGNAL VERIFIED: Handover to Agent [${targetAgent}]`);
// Emit the signal for the Orchestrator to pick up
this.emit('handover_signal', {
target: targetAgent,
timestamp: new Date(),
source: 'Blackboard'
});
} else {
// Debug log to confirm scan happened (can be removed later for silence)
// console.log('π [WATCHDOG] Scanned. No active handover signal found.');
}
} catch (error) {
console.error('β [WATCHDOG] Read error:', error);
}
}
}
export const handoverWatchdog = HandoverWatchdog.getInstance();
|