Feat/gt analytics openclaw (#392)

* 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>
This commit is contained in:
Shadowbroker
2026-06-16 17:05:46 -06:00
committed by GitHub
co-authored by Robert Pickett Cursor
parent 9c5a4054f6
commit cfbeabda1e
69 changed files with 8101 additions and 77 deletions
+15 -14
View File
@@ -97,6 +97,7 @@ _SLOW_KEYS = (
"cyber_threats",
"scm_suppliers",
"telegram_osint",
"gt_risk",
)
@@ -210,6 +211,9 @@ _LAYER_ALIASES = {
"telegram": "telegram_osint",
"telegram_osint": "telegram_osint",
"osint_feed": "telegram_osint",
"gt_risk": "gt_risk",
"strategic_risk": "gt_risk",
"gt_analytics": "gt_risk",
"malware": "malware_threats",
"malware_threats": "malware_threats",
"malware_c2": "malware_threats",
@@ -710,10 +714,10 @@ _UNIVERSAL_SEARCH_SPECS: dict[str, dict[str, Any]] = {
"time_fields": ("updated_at", "timestamp"),
},
"telegram_osint": {
"fields": ("title", "description", "source", "channel", "link"),
"primary_fields": ("title", "description", "channel"),
"label_fields": ("title", "channel"),
"summary_fields": ("description", "source"),
"fields": ("title", "description", "title_translated", "description_translated", "source", "channel", "link"),
"primary_fields": ("title_translated", "title", "description_translated", "description", "channel"),
"label_fields": ("title_translated", "title", "channel"),
"summary_fields": ("description_translated", "description", "source"),
"type_fields": ("channel", "source"),
"id_fields": ("id", "link"),
"time_fields": ("published", "timestamp"),
@@ -2089,30 +2093,27 @@ def search_news(
return {"results": out, "version": get_data_version(), "truncated": True}
if include_telegram:
from services.telegram_osint_text import telegram_post_display_title, telegram_post_search_text
for post in _unwrap_layer_items(snap.get("telegram_osint"), "telegram_osint"):
if not isinstance(post, dict):
continue
text = " ".join(
(
_norm_text(post.get("title")),
_norm_text(post.get("description")),
_norm_text(post.get("source")),
_norm_text(post.get("channel")),
)
)
text = telegram_post_search_text(post)
if not _text_matches_query(query_norm, text):
continue
lat, lng = _extract_coords(post)
out.append(
{
"source_layer": "telegram_osint",
"title": post.get("title") or "",
"summary": post.get("description") or "",
"title": telegram_post_display_title(post),
"summary": post.get("description_translated") or post.get("description") or "",
"source": post.get("source") or post.get("channel") or "Telegram",
"link": post.get("link") or "",
"lat": lat,
"lng": lng,
"risk_score": post.get("risk_score"),
"source_lang": post.get("source_lang"),
"source_lang_label": post.get("source_lang_label"),
}
)
if len(out) >= limit: