File size: 4,117 Bytes
173e9ec
 
3ec7b5a
173e9ec
03c48e8
b4adf10
173e9ec
 
 
 
 
 
 
 
 
 
3ec7b5a
173e9ec
 
 
 
 
 
 
 
 
 
 
 
 
5fedeff
173e9ec
 
5fedeff
173e9ec
5fedeff
173e9ec
3ec7b5a
 
 
 
 
 
173e9ec
 
 
 
5fedeff
173e9ec
 
5fedeff
173e9ec
5fedeff
173e9ec
 
5fedeff
173e9ec
5fedeff
 
173e9ec
1d80394
173e9ec
 
5fedeff
173e9ec
 
 
5fedeff
173e9ec
 
5fedeff
173e9ec
5fedeff
173e9ec
 
 
 
 
 
 
 
 
 
 
 
 
 
3ec7b5a
 
 
 
173e9ec
 
 
 
 
 
 
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
import asyncio
import logging
import random
from datetime import datetime
from typing import Dict, List
from app.core.config import settings
from app.core.scrapers import scraper
from app.core.filters import sieve
from app.core.brain import brain
from app.core.vault import vault

logger = logging.getLogger("hawk.agent")

class HawkAgent:
    def __init__(self):
        self.is_running = False
        self.pulse_interval = settings.PULSE_INTERVAL_MINUTES

    def notify_jewel_discovery(self, jewel: Dict):
        """Notify the user about a high-signal discovery."""
        logger.info(f"!!! JEWEL DISCOVERED: {jewel.get('title')} !!!")
        logger.info(f"Significance: {jewel.get('technical_significance')}")
        # Placeholder for real notifications (Discord, Email, etc.)

    async def run_swoop_cycle(self):
        """The core search-filter-synthesize-vault loop."""
        logger.info(f"Hawk is taking flight at {datetime.now()}")
        
        try:
            # 1. Swoop (Scrape all sources)
            logger.info("PHASE 1: Taking flight for Discovery Swoop...")
            raw_signals = await scraper.swoop()
            if not raw_signals:
                logger.warning("PHASE 1 FAILED: No raw signals captured.")
                return
            logger.info(f"PHASE 1 COMPLETE: Captured {len(raw_signals)} potential signals.")
            
            # Real-time local summarization for the telemetry stream
            logger.info("PHASE 1.5: Generating immediate forensic gists via local Qwen...")
            for s in raw_signals:
                text = f"{s.get('title', '')} {s.get('description', '')}"
                s['local_summary'] = await sieve.summarize_locally(text)
            
            # Save raw signals for the 'All' stream in frontend
            vault.save_raw(raw_signals)

            # 2. Sieve (Filter)
            logger.info("PHASE 2: Sifting signals through local Sieve...")
            high_signal_items = await sieve.filter_noise(raw_signals)
            if not high_signal_items:
                logger.info("PHASE 2 COMPLETE: No signals passed the dense noise filter.")
                return
            logger.info(f"PHASE 2 COMPLETE: {len(high_signal_items)} high-signal candidates identified.")

            # 3. Brain (Synthesize)
            logger.info("PHASE 3: Initiating Groq Synthesis for candidate jewels...")
            jewels = []
            for i, item in enumerate(high_signal_items, 1):
                logger.info(f"Synthesizing candidate {i}/{len(high_signal_items)}: {item.get('title')[:50]}...")
                jewel = await brain.synthesize(item)
                if jewel:
                    jewels.append(jewel)
                    self.notify_jewel_discovery(jewel)
            logger.info(f"PHASE 3 COMPLETE: Synthesized {len(jewels)} technical jewels.")

            # 4. Vault (Store)
            if jewels:
                logger.info("PHASE 4: Locking jewels into the Technical Vault...")
                vault.save_locally(jewels)
                await vault.push_to_hf()
                logger.info(f"PHASE 4 COMPLETE: Project Hawk cycle finalized. {len(jewels)} jewels securely vaulted.")
            else:
                logger.info("PHASE 4 SKIPPED: No new jewels to vault this cycle.")

        except Exception as e:
            logger.error(f"Error in Hawk agent cycle: {e}")

    async def start(self):
        """Start the autonomous loop."""
        if self.is_running:
            return
        
        self.is_running = True
        logger.info("Hawk Agent autonomous loop started.")
        
        while self.is_running:
            await self.run_swoop_cycle()
            # Randomized breather between pulses (jitter)
            breather = self.pulse_interval + random.randint(-2, 5)
            logger.info(f"Hawk is hovering for {breather} minutes before next pulse...")
            await asyncio.sleep(max(1, breather) * 60)

    def stop(self):
        """Stop the autonomous loop."""
        self.is_running = False
        logger.info("Hawk Agent stopping...")

hawk_agent = HawkAgent()