Paritosh Upadhyay commited on
Commit
fa0757c
·
1 Parent(s): a4277f4

Aggressive Tactical Upgrade: Parallel Foraging & Search Identity Juggling

Browse files
backend/app/services/holocron.py CHANGED
@@ -11,6 +11,7 @@ import threading
11
  import time
12
  from app.services.tools import search
13
  from app.services import state_sync, watchdog, state
 
14
 
15
  logger = logging.getLogger("friday.holocron")
16
 
@@ -217,20 +218,28 @@ def batch_mine_priorities():
217
  ]
218
  random.shuffle(domains) # Jitter topic order to avoid pattern matching
219
 
 
 
 
 
 
 
 
 
 
220
  def _run_batch():
221
- logger.info("Holocron: Initiating Sovereign Priority Ingestion Cycle...")
222
- for d in domains:
223
- if _check_halt():
224
- logger.warning("Holocron: Sovereign Termination signal received. Aborting batch cycle.")
225
- break
226
- _active_foraging_threads.add(d)
227
- try:
228
- _mine_sync(d, depth=1)
229
- finally:
230
- _active_foraging_threads.remove(d)
231
-
232
- time.sleep(random.randint(15, 30))
233
  logger.info("Holocron: Sovereign Priority Ingestion Cycle Complete.")
 
234
 
235
  threading.Thread(target=_run_batch, daemon=True).start()
236
 
 
11
  import time
12
  from app.services.tools import search
13
  from app.services import state_sync, watchdog, state
14
+ import concurrent.futures
15
 
16
  logger = logging.getLogger("friday.holocron")
17
 
 
218
  ]
219
  random.shuffle(domains) # Jitter topic order to avoid pattern matching
220
 
221
+ def _threaded_mine(d: str):
222
+ """Thread wrapper for mining a specific topic."""
223
+ if _check_halt(): return
224
+ _active_foraging_threads.add(d)
225
+ try:
226
+ _mine_sync(d, depth=1)
227
+ finally:
228
+ _active_foraging_threads.remove(d)
229
+
230
  def _run_batch():
231
+ logger.info("Holocron: Initiating Sovereign Parallel Ingestion (Workers: 3)...")
232
+ with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
233
+ futures = [executor.submit(_threaded_mine, d) for d in domains if not _check_halt()]
234
+ for future in concurrent.futures.as_completed(futures):
235
+ if _check_halt(): break
236
+ try:
237
+ future.result()
238
+ except Exception as e:
239
+ logger.error(f"Parallel Worker Error: {e}")
240
+
 
 
241
  logger.info("Holocron: Sovereign Priority Ingestion Cycle Complete.")
242
+ time.sleep(random.randint(45, 90)) # Increased sleep after a parallel burst to cool down IP
243
 
244
  threading.Thread(target=_run_batch, daemon=True).start()
245
 
backend/app/services/tools/search.py CHANGED
@@ -37,6 +37,7 @@ def search_web(query: str, max_results: int = 5, bypass_cache: bool = False) ->
37
  logger.info(f"Memory hit for: {query}. Using local cache.")
38
  return [{"title": "Cached Local Memory", "href": "local://memory", "body": cached_result}]
39
 
 
40
  for attempt in range(max_retries):
41
  # INSTANT KILL-SWITCH CHECK
42
  if state.is_sovereign_locked() or state.is_learning_locked():
@@ -44,17 +45,16 @@ def search_web(query: str, max_results: int = 5, bypass_cache: bool = False) ->
44
  return []
45
 
46
  try:
47
- # [STEALH] Adaptive Jitter: 5-12 seconds to mimic human reading/thinking
48
- jitter = random.uniform(5, 12)
49
- time.sleep(jitter)
50
 
51
- logger.info(f"Searching web for: {query} (Attempt {attempt+1}/{max_retries})")
52
-
53
- # [STEALTH] User-Agent Rotation
54
  ua = random.choice(user_agents)
55
- with DDGS(headers={"User-Agent": ua}, timeout=45) as ddgs:
56
- # [SOVEREIGN HARDENING]: Lite backend is more robust against automation detection
57
- backend = "lite"
 
 
58
  results = [r for r in ddgs.text(query, max_results=max_results, backend=backend)]
59
 
60
  # Consolidate into memory if useful
@@ -64,16 +64,18 @@ def search_web(query: str, max_results: int = 5, bypass_cache: bool = False) ->
64
  memory.embed_conversation("knowledge_cache", summary, entities=query)
65
 
66
  return results
67
- except (RatelimitException, TimeoutException, Exception) as e:
68
  err_str = str(e).lower()
69
  is_transient = any(k in err_str for k in ["ratelimit", "timeout", "202", "connection"])
70
 
71
  if is_transient and attempt < max_retries - 1:
72
- wait_time = retry_delay * (2 ** attempt)
73
- logger.warning(f"Search Transient Error: {e}. Retrying in {wait_time}s...")
 
74
  time.sleep(wait_time)
75
  else:
76
- raise e
 
77
 
78
  except Exception as e:
79
  logger.error(f"Web search failed after critical retries: {e}")
 
37
  logger.info(f"Memory hit for: {query}. Using local cache.")
38
  return [{"title": "Cached Local Memory", "href": "local://memory", "body": cached_result}]
39
 
40
+ backends = ["lite", "html", "auto"]
41
  for attempt in range(max_retries):
42
  # INSTANT KILL-SWITCH CHECK
43
  if state.is_sovereign_locked() or state.is_learning_locked():
 
45
  return []
46
 
47
  try:
48
+ # [STEALH] Smaller Jitter for speed (3-6s)
49
+ time.sleep(random.uniform(3, 6))
 
50
 
51
+ # [STEALTH] Identity Juggling: UA + Backend Rotation
 
 
52
  ua = random.choice(user_agents)
53
+ backend = backends[attempt % len(backends)]
54
+
55
+ logger.info(f"Searching [{backend}] for: {query} (Attempt {attempt+1}/{max_retries})")
56
+
57
+ with DDGS(headers={"User-Agent": ua}, timeout=40) as ddgs:
58
  results = [r for r in ddgs.text(query, max_results=max_results, backend=backend)]
59
 
60
  # Consolidate into memory if useful
 
64
  memory.embed_conversation("knowledge_cache", summary, entities=query)
65
 
66
  return results
67
+ except Exception as e:
68
  err_str = str(e).lower()
69
  is_transient = any(k in err_str for k in ["ratelimit", "timeout", "202", "connection"])
70
 
71
  if is_transient and attempt < max_retries - 1:
72
+ # [TACTICAL] 2-5s burst retry with NEW identity
73
+ wait_time = random.uniform(2, 5)
74
+ logger.warning(f"Search Tactical Maneuver: {e}. Swapping Identity & Retrying in {wait_time:.1f}s...")
75
  time.sleep(wait_time)
76
  else:
77
+ logger.error(f"Search Exhausted: {e}")
78
+ return []
79
 
80
  except Exception as e:
81
  logger.error(f"Web search failed after critical retries: {e}")