mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-06-18 12:00:20 +02:00
cfbeabda1e
* feat(telegram): auto-translate OSINT channel posts to English Cherry-picked from @Bobpick PR #391 (telegram-only slice): server-side translation during fetch, SHOW ORIGINAL toggle in TelegramOsintPopup, and on-demand /api/telegram-feed?lang=. Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com> Co-authored-by: Cursor <cursoragent@cursor.com> * feat(gt): experimental Derived OSINT analytics with lean-node safeguards Cherry-picked from @Bobpick PR #391 (GT + OpenClaw slice): Bayesian strategic-risk engine, map overlay, OpenClaw commands, and telegram_rhetoric watchdog. Off by default (GT_ANALYTICS_ENABLED=false, gt_risk layer false). 1 vCPU nodes get cgroup detection, UI warning on layer toggle, and lean profile that skips scheduled ingest/Louvain unless GT_ANALYTICS_ACK_LOW_CPU=true. Backtest HUD removed from dashboard (OpenClaw/API regression only). Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com> Co-authored-by: Cursor <cursoragent@cursor.com>
158 lines
4.8 KiB
Python
158 lines
4.8 KiB
Python
"""Configuration for Strategic Risk Analytics (feature-flagged)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
from dataclasses import dataclass, field
|
|
from functools import lru_cache
|
|
from typing import Any
|
|
|
|
|
|
def _env_bool(name: str, default: bool = False) -> bool:
|
|
raw = str(os.environ.get(name, "")).strip().lower()
|
|
if not raw:
|
|
return default
|
|
return raw not in {"0", "false", "no", "off"}
|
|
|
|
|
|
def _env_float(name: str, default: float) -> float:
|
|
raw = str(os.environ.get(name, "")).strip()
|
|
if not raw:
|
|
return default
|
|
try:
|
|
return float(raw)
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def _env_int(name: str, default: int) -> int:
|
|
raw = str(os.environ.get(name, "")).strip()
|
|
if not raw:
|
|
return default
|
|
try:
|
|
return int(raw)
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def _parse_signal_weights(raw: str) -> dict[str, float]:
|
|
if not raw.strip():
|
|
return {}
|
|
try:
|
|
parsed = json.loads(raw)
|
|
if isinstance(parsed, dict):
|
|
return {str(k): float(v) for k, v in parsed.items()}
|
|
except (json.JSONDecodeError, TypeError, ValueError):
|
|
pass
|
|
weights: dict[str, float] = {}
|
|
for part in raw.split(","):
|
|
piece = part.strip()
|
|
if not piece or "=" not in piece:
|
|
continue
|
|
key, value = piece.split("=", 1)
|
|
try:
|
|
weights[key.strip()] = float(value.strip())
|
|
except ValueError:
|
|
continue
|
|
return weights
|
|
|
|
|
|
def resolve_gt_profile() -> str:
|
|
from services.runtime_profile import resolve_profile_name
|
|
|
|
return resolve_profile_name()
|
|
|
|
|
|
def gt_analytics_ack_low_cpu() -> bool:
|
|
return _env_bool("GT_ANALYTICS_ACK_LOW_CPU", default=False)
|
|
|
|
|
|
def gt_engine_operational() -> bool:
|
|
"""Full GT engine (scheduled ingest, heatmap, Louvain) — not watchdog-only."""
|
|
if not get_gt_settings().enabled:
|
|
return False
|
|
if resolve_gt_profile() == "lean" and not gt_analytics_ack_low_cpu():
|
|
return False
|
|
return True
|
|
|
|
|
|
def gt_scheduled_ingest_enabled() -> bool:
|
|
return gt_engine_operational()
|
|
|
|
|
|
def gt_louvain_enabled() -> bool:
|
|
return gt_engine_operational()
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GTAnalyticsSettings:
|
|
enabled: bool = False
|
|
profile: str = "standard"
|
|
base_prior: float = 0.15
|
|
evidence_cap: float = 3.0
|
|
evidence_scale: float = 5.0
|
|
min_prob: float = 0.01
|
|
max_prob: float = 0.99
|
|
high_risk_threshold: float = 0.6
|
|
max_history_per_region: int = 200
|
|
max_heatmap_features: int = 500
|
|
louvain_min_weight: float = 0.5
|
|
louvain_interval_minutes: int = 30
|
|
signal_weight_overrides: dict[str, float] = field(default_factory=dict)
|
|
watched_channels: tuple[str, ...] = ()
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_gt_settings() -> GTAnalyticsSettings:
|
|
channels_raw = str(os.environ.get("GT_ANALYTICS_WATCHED_CHANNELS", "")).strip()
|
|
channels = tuple(
|
|
part.strip().lstrip("@")
|
|
for part in channels_raw.split(",")
|
|
if part.strip()
|
|
)
|
|
profile = resolve_gt_profile()
|
|
lean = profile == "lean"
|
|
return GTAnalyticsSettings(
|
|
enabled=_env_bool("GT_ANALYTICS_ENABLED", default=False),
|
|
profile=profile,
|
|
base_prior=_env_float("GT_ANALYTICS_BASE_PRIOR", 0.15),
|
|
evidence_cap=_env_float("GT_ANALYTICS_EVIDENCE_CAP", 3.0),
|
|
evidence_scale=_env_float("GT_ANALYTICS_EVIDENCE_SCALE", 5.0),
|
|
min_prob=_env_float("GT_ANALYTICS_MIN_PROB", 0.01),
|
|
max_prob=_env_float("GT_ANALYTICS_MAX_PROB", 0.99),
|
|
high_risk_threshold=_env_float("GT_ANALYTICS_HIGH_RISK_THRESHOLD", 0.6),
|
|
max_history_per_region=_env_int("GT_ANALYTICS_MAX_HISTORY", 200),
|
|
max_heatmap_features=_env_int(
|
|
"GT_ANALYTICS_MAX_HEATMAP_FEATURES",
|
|
50 if lean else 500,
|
|
),
|
|
louvain_min_weight=_env_float("GT_ANALYTICS_LOUVAIN_MIN_WEIGHT", 0.5),
|
|
louvain_interval_minutes=max(5, _env_int("GT_ANALYTICS_LOUVAIN_INTERVAL_MINUTES", 30)),
|
|
signal_weight_overrides=_parse_signal_weights(
|
|
str(os.environ.get("GT_ANALYTICS_SIGNAL_WEIGHTS", ""))
|
|
),
|
|
watched_channels=channels,
|
|
)
|
|
|
|
|
|
def gt_analytics_enabled() -> bool:
|
|
return get_gt_settings().enabled
|
|
|
|
|
|
def gt_analytics_status() -> dict[str, Any]:
|
|
settings = get_gt_settings()
|
|
from services.runtime_profile import get_runtime_profile
|
|
|
|
runtime = get_runtime_profile()
|
|
operational = gt_engine_operational()
|
|
return {
|
|
"enabled": settings.enabled,
|
|
"operational": operational,
|
|
"profile": settings.profile,
|
|
"ack_low_cpu": gt_analytics_ack_low_cpu(),
|
|
"recommended": bool(runtime.get("gt_analytics", {}).get("recommended")),
|
|
"lean_node": bool(runtime.get("gt_analytics", {}).get("lean_node")),
|
|
"warning": runtime.get("gt_analytics", {}).get("warning"),
|
|
"experimental": True,
|
|
} |